Skip to content

Commit 21dca29

Browse files
committed
Workboards - add new "initialization" flow
Summary: Currently, we just create a default "backlog" column if / when you visit a workboard for the first time. Post this patch, instead you see a blocking dialog that lets you either create the default backlog column or import columns from another project. In the case of the latter, the user gets another dialog which lets them select any project of which they are a member that also has columns in it. Note that only not hidden columns get imported. Fixes T4431. Test Plan: - made a new workboard and got my new dialog. made a default backlog and it worked! - made a new workboard again and tried the import flow - it also worked. - verified projects with no columns do not show up in import dialog - verified project with / without columns still all show up in maniphest project typeahead Reviewers: epriestley Reviewed By: epriestley Subscribers: epriestley, Korvin Maniphest Tasks: T4431 Differential Revision: https://secure.phabricator.com/D10153
1 parent e68b6de commit 21dca29

5 files changed

+152
-9
lines changed

src/__phutil_library_map__.php

+4
Original file line numberDiff line numberDiff line change
@@ -1926,6 +1926,7 @@
19261926
'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php',
19271927
'PhabricatorProjectBoardDeleteController' => 'applications/project/controller/PhabricatorProjectBoardDeleteController.php',
19281928
'PhabricatorProjectBoardEditController' => 'applications/project/controller/PhabricatorProjectBoardEditController.php',
1929+
'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php',
19291930
'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php',
19301931
'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php',
19311932
'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
@@ -2620,6 +2621,7 @@
26202621
'PonderVoteSaveController' => 'applications/ponder/controller/PonderVoteSaveController.php',
26212622
'ProjectBoardTaskCard' => 'applications/project/view/ProjectBoardTaskCard.php',
26222623
'ProjectConduitAPIMethod' => 'applications/project/conduit/ProjectConduitAPIMethod.php',
2624+
'ProjectCreateConduitAPIMethod' => 'applications/project/conduit/ProjectCreateConduitAPIMethod.php',
26232625
'ProjectCreateProjectsCapability' => 'applications/project/capability/ProjectCreateProjectsCapability.php',
26242626
'ProjectQueryConduitAPIMethod' => 'applications/project/conduit/ProjectQueryConduitAPIMethod.php',
26252627
'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php',
@@ -4752,6 +4754,7 @@
47524754
'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
47534755
'PhabricatorProjectBoardDeleteController' => 'PhabricatorProjectBoardController',
47544756
'PhabricatorProjectBoardEditController' => 'PhabricatorProjectBoardController',
4757+
'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController',
47554758
'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController',
47564759
'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController',
47574760
'PhabricatorProjectColumn' => array(
@@ -5561,6 +5564,7 @@
55615564
'PonderVoteEditor' => 'PhabricatorEditor',
55625565
'PonderVoteSaveController' => 'PonderController',
55635566
'ProjectConduitAPIMethod' => 'ConduitAPIMethod',
5567+
'ProjectCreateConduitAPIMethod' => 'ProjectConduitAPIMethod',
55645568
'ProjectCreateProjectsCapability' => 'PhabricatorPolicyCapability',
55655569
'ProjectQueryConduitAPIMethod' => 'ProjectConduitAPIMethod',
55665570
'ProjectRemarkupRule' => 'PhabricatorObjectRemarkupRule',

src/applications/project/application/PhabricatorProjectApplication.php

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public function getRoutes() {
7171
=> 'PhabricatorProjectBoardDeleteController',
7272
'column/(?:(?P<id>\d+)/)?'
7373
=> 'PhabricatorProjectColumnDetailController',
74+
'import/'
75+
=> 'PhabricatorProjectBoardImportController',
7476
'reorder/'
7577
=> 'PhabricatorProjectBoardReorderController',
7678
),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
final class PhabricatorProjectBoardImportController
4+
extends PhabricatorProjectBoardController {
5+
6+
private $projectID;
7+
8+
public function willProcessRequest(array $data) {
9+
$this->projectID = $data['projectID'];
10+
}
11+
12+
public function processRequest() {
13+
$request = $this->getRequest();
14+
$viewer = $request->getUser();
15+
16+
$project = id(new PhabricatorProjectQuery())
17+
->setViewer($viewer)
18+
->requireCapabilities(
19+
array(
20+
PhabricatorPolicyCapability::CAN_VIEW,
21+
PhabricatorPolicyCapability::CAN_EDIT,
22+
))
23+
->withIDs(array($this->projectID))
24+
->executeOne();
25+
if (!$project) {
26+
return new Aphront404Response();
27+
}
28+
$this->setProject($project);
29+
30+
$columns = id(new PhabricatorProjectColumnQuery())
31+
->setViewer($viewer)
32+
->withProjectPHIDs(array($project->getPHID()))
33+
->execute();
34+
if ($columns) {
35+
return new Aphront400Response();
36+
}
37+
38+
$project_id = $project->getID();
39+
$board_uri = $this->getApplicationURI("board/{$project_id}/");
40+
41+
if ($request->isFormPost()) {
42+
$import_phid = $request->getArr('importProjectPHID');
43+
$import_phid = reset($import_phid);
44+
45+
$import_columns = id(new PhabricatorProjectColumnQuery())
46+
->setViewer($viewer)
47+
->withProjectPHIDs(array($import_phid))
48+
->execute();
49+
if (!$import_columns) {
50+
return new Aphront400Response();
51+
}
52+
53+
$table = id(new PhabricatorProjectColumn())
54+
->openTransaction();
55+
foreach ($import_columns as $import_column) {
56+
if ($import_column->isHidden()) {
57+
continue;
58+
}
59+
$new_column = PhabricatorProjectColumn::initializeNewColumn($viewer)
60+
->setSequence($import_column->getSequence())
61+
->setProjectPHID($project->getPHID())
62+
->setName($import_column->getName())
63+
->save();
64+
}
65+
$table->saveTransaction();
66+
67+
return id(new AphrontRedirectResponse())->setURI($board_uri);
68+
}
69+
70+
$proj_selector = id(new AphrontFormTokenizerControl())
71+
->setName('importProjectPHID')
72+
->setUser($viewer)
73+
->setDatasource(id(new PhabricatorProjectDatasource())
74+
->setParameters(array('mustHaveColumns' => true))
75+
->setLimit(1));
76+
return $this->newDialog()
77+
->setTitle(pht('Import Columns'))
78+
->setWidth(AphrontDialogView::WIDTH_FORM)
79+
->appendParagraph(pht('Choose a project to import columns from:'))
80+
->appendChild($proj_selector)
81+
->addCancelButton($board_uri)
82+
->addSubmitButton(pht('Import'));
83+
}
84+
85+
}

src/applications/project/controller/PhabricatorProjectBoardViewController.php

+46-9
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,27 @@ public function processRequest() {
5454
$columns = $column_query->execute();
5555
$columns = mpull($columns, null, 'getSequence');
5656

57-
// If there's no default column, create one now.
5857
if (empty($columns[0])) {
59-
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
60-
$column = PhabricatorProjectColumn::initializeNewColumn($viewer)
61-
->setSequence(0)
62-
->setProjectPHID($project->getPHID())
63-
->save();
64-
$column->attachProject($project);
65-
$columns[0] = $column;
66-
unset($unguarded);
58+
switch ($request->getStr('initialize-type')) {
59+
case 'backlog-only':
60+
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
61+
$column = PhabricatorProjectColumn::initializeNewColumn($viewer)
62+
->setSequence(0)
63+
->setProjectPHID($project->getPHID())
64+
->save();
65+
$column->attachProject($project);
66+
$columns[0] = $column;
67+
unset($unguarded);
68+
break;
69+
case 'import':
70+
return id(new AphrontRedirectResponse())
71+
->setURI(
72+
$this->getApplicationURI('board/'.$project->getID().'/import/'));
73+
break;
74+
default:
75+
return $this->initializeWorkboardDialog($project);
76+
break;
77+
}
6778
}
6879

6980
ksort($columns);
@@ -406,5 +417,31 @@ private function buildManageMenu(
406417
return $manage_button;
407418
}
408419

420+
private function initializeWorkboardDialog(PhabricatorProject $project) {
421+
422+
$instructions = pht('This workboard has not been setup yet.');
423+
$new_selector = id(new AphrontFormRadioButtonControl())
424+
->setName('initialize-type')
425+
->setValue('backlog-only')
426+
->addButton(
427+
'backlog-only',
428+
pht('New Empty Board'),
429+
pht('Create a new board with just a backlog column.'))
430+
->addButton(
431+
'import',
432+
pht('Import Columns'),
433+
pht('Import board columns from another project.'));
434+
435+
$dialog = id(new AphrontDialogView())
436+
->setUser($this->getRequest()->getUser())
437+
->setTitle(pht('New Workboard'))
438+
->addSubmitButton('Continue')
439+
->addCancelButton($this->getApplicationURI('view/'.$project->getID().'/'))
440+
->appendParagraph($instructions)
441+
->appendChild($new_selector);
442+
443+
return id(new AphrontDialogResponse())
444+
->setDialog($dialog);
445+
}
409446

410447
}

src/applications/project/typeahead/PhabricatorProjectDatasource.php

+15
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,24 @@ public function loadResults() {
2929
->needSlugs(true)
3030
->withDatasourceQuery($raw_query)
3131
->execute();
32+
$projs = mpull($projs, null, 'getPHID');
33+
34+
$must_have_cols = $this->getParameter('mustHaveColumns', false);
35+
if ($must_have_cols) {
36+
$columns = id(new PhabricatorProjectColumnQuery())
37+
->setViewer($viewer)
38+
->withProjectPHIDs(array_keys($projs))
39+
->execute();
40+
$has_cols = mgroup($columns, 'getProjectPHID');
41+
} else {
42+
$has_cols = array_fill_keys(array_keys($projs), true);
43+
}
3244

3345
$results = array();
3446
foreach ($projs as $proj) {
47+
if (!isset($has_cols[$proj->getPHID()])) {
48+
continue;
49+
}
3550
$closed = null;
3651
if ($proj->isArchived()) {
3752
$closed = pht('Archived');

0 commit comments

Comments
 (0)