mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 14:30:56 +01:00
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
This commit is contained in:
parent
e68b6deccb
commit
21dca29c5f
5 changed files with 152 additions and 9 deletions
|
@ -1926,6 +1926,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php',
|
'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php',
|
||||||
'PhabricatorProjectBoardDeleteController' => 'applications/project/controller/PhabricatorProjectBoardDeleteController.php',
|
'PhabricatorProjectBoardDeleteController' => 'applications/project/controller/PhabricatorProjectBoardDeleteController.php',
|
||||||
'PhabricatorProjectBoardEditController' => 'applications/project/controller/PhabricatorProjectBoardEditController.php',
|
'PhabricatorProjectBoardEditController' => 'applications/project/controller/PhabricatorProjectBoardEditController.php',
|
||||||
|
'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php',
|
||||||
'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php',
|
'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php',
|
||||||
'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php',
|
'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php',
|
||||||
'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
|
'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
|
||||||
|
@ -2620,6 +2621,7 @@ phutil_register_library_map(array(
|
||||||
'PonderVoteSaveController' => 'applications/ponder/controller/PonderVoteSaveController.php',
|
'PonderVoteSaveController' => 'applications/ponder/controller/PonderVoteSaveController.php',
|
||||||
'ProjectBoardTaskCard' => 'applications/project/view/ProjectBoardTaskCard.php',
|
'ProjectBoardTaskCard' => 'applications/project/view/ProjectBoardTaskCard.php',
|
||||||
'ProjectConduitAPIMethod' => 'applications/project/conduit/ProjectConduitAPIMethod.php',
|
'ProjectConduitAPIMethod' => 'applications/project/conduit/ProjectConduitAPIMethod.php',
|
||||||
|
'ProjectCreateConduitAPIMethod' => 'applications/project/conduit/ProjectCreateConduitAPIMethod.php',
|
||||||
'ProjectCreateProjectsCapability' => 'applications/project/capability/ProjectCreateProjectsCapability.php',
|
'ProjectCreateProjectsCapability' => 'applications/project/capability/ProjectCreateProjectsCapability.php',
|
||||||
'ProjectQueryConduitAPIMethod' => 'applications/project/conduit/ProjectQueryConduitAPIMethod.php',
|
'ProjectQueryConduitAPIMethod' => 'applications/project/conduit/ProjectQueryConduitAPIMethod.php',
|
||||||
'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php',
|
'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php',
|
||||||
|
@ -4752,6 +4754,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
|
'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
|
||||||
'PhabricatorProjectBoardDeleteController' => 'PhabricatorProjectBoardController',
|
'PhabricatorProjectBoardDeleteController' => 'PhabricatorProjectBoardController',
|
||||||
'PhabricatorProjectBoardEditController' => 'PhabricatorProjectBoardController',
|
'PhabricatorProjectBoardEditController' => 'PhabricatorProjectBoardController',
|
||||||
|
'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController',
|
||||||
'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController',
|
'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController',
|
||||||
'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController',
|
'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController',
|
||||||
'PhabricatorProjectColumn' => array(
|
'PhabricatorProjectColumn' => array(
|
||||||
|
@ -5561,6 +5564,7 @@ phutil_register_library_map(array(
|
||||||
'PonderVoteEditor' => 'PhabricatorEditor',
|
'PonderVoteEditor' => 'PhabricatorEditor',
|
||||||
'PonderVoteSaveController' => 'PonderController',
|
'PonderVoteSaveController' => 'PonderController',
|
||||||
'ProjectConduitAPIMethod' => 'ConduitAPIMethod',
|
'ProjectConduitAPIMethod' => 'ConduitAPIMethod',
|
||||||
|
'ProjectCreateConduitAPIMethod' => 'ProjectConduitAPIMethod',
|
||||||
'ProjectCreateProjectsCapability' => 'PhabricatorPolicyCapability',
|
'ProjectCreateProjectsCapability' => 'PhabricatorPolicyCapability',
|
||||||
'ProjectQueryConduitAPIMethod' => 'ProjectConduitAPIMethod',
|
'ProjectQueryConduitAPIMethod' => 'ProjectConduitAPIMethod',
|
||||||
'ProjectRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
'ProjectRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
||||||
|
|
|
@ -71,6 +71,8 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
|
||||||
=> 'PhabricatorProjectBoardDeleteController',
|
=> 'PhabricatorProjectBoardDeleteController',
|
||||||
'column/(?:(?P<id>\d+)/)?'
|
'column/(?:(?P<id>\d+)/)?'
|
||||||
=> 'PhabricatorProjectColumnDetailController',
|
=> 'PhabricatorProjectColumnDetailController',
|
||||||
|
'import/'
|
||||||
|
=> 'PhabricatorProjectBoardImportController',
|
||||||
'reorder/'
|
'reorder/'
|
||||||
=> 'PhabricatorProjectBoardReorderController',
|
=> 'PhabricatorProjectBoardReorderController',
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorProjectBoardImportController
|
||||||
|
extends PhabricatorProjectBoardController {
|
||||||
|
|
||||||
|
private $projectID;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->projectID = $data['projectID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$viewer = $request->getUser();
|
||||||
|
|
||||||
|
$project = id(new PhabricatorProjectQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->requireCapabilities(
|
||||||
|
array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
|
))
|
||||||
|
->withIDs(array($this->projectID))
|
||||||
|
->executeOne();
|
||||||
|
if (!$project) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
$this->setProject($project);
|
||||||
|
|
||||||
|
$columns = id(new PhabricatorProjectColumnQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withProjectPHIDs(array($project->getPHID()))
|
||||||
|
->execute();
|
||||||
|
if ($columns) {
|
||||||
|
return new Aphront400Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$project_id = $project->getID();
|
||||||
|
$board_uri = $this->getApplicationURI("board/{$project_id}/");
|
||||||
|
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
$import_phid = $request->getArr('importProjectPHID');
|
||||||
|
$import_phid = reset($import_phid);
|
||||||
|
|
||||||
|
$import_columns = id(new PhabricatorProjectColumnQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withProjectPHIDs(array($import_phid))
|
||||||
|
->execute();
|
||||||
|
if (!$import_columns) {
|
||||||
|
return new Aphront400Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = id(new PhabricatorProjectColumn())
|
||||||
|
->openTransaction();
|
||||||
|
foreach ($import_columns as $import_column) {
|
||||||
|
if ($import_column->isHidden()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$new_column = PhabricatorProjectColumn::initializeNewColumn($viewer)
|
||||||
|
->setSequence($import_column->getSequence())
|
||||||
|
->setProjectPHID($project->getPHID())
|
||||||
|
->setName($import_column->getName())
|
||||||
|
->save();
|
||||||
|
}
|
||||||
|
$table->saveTransaction();
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())->setURI($board_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
$proj_selector = id(new AphrontFormTokenizerControl())
|
||||||
|
->setName('importProjectPHID')
|
||||||
|
->setUser($viewer)
|
||||||
|
->setDatasource(id(new PhabricatorProjectDatasource())
|
||||||
|
->setParameters(array('mustHaveColumns' => true))
|
||||||
|
->setLimit(1));
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('Import Columns'))
|
||||||
|
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||||
|
->appendParagraph(pht('Choose a project to import columns from:'))
|
||||||
|
->appendChild($proj_selector)
|
||||||
|
->addCancelButton($board_uri)
|
||||||
|
->addSubmitButton(pht('Import'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -54,8 +54,9 @@ final class PhabricatorProjectBoardViewController
|
||||||
$columns = $column_query->execute();
|
$columns = $column_query->execute();
|
||||||
$columns = mpull($columns, null, 'getSequence');
|
$columns = mpull($columns, null, 'getSequence');
|
||||||
|
|
||||||
// If there's no default column, create one now.
|
|
||||||
if (empty($columns[0])) {
|
if (empty($columns[0])) {
|
||||||
|
switch ($request->getStr('initialize-type')) {
|
||||||
|
case 'backlog-only':
|
||||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||||
$column = PhabricatorProjectColumn::initializeNewColumn($viewer)
|
$column = PhabricatorProjectColumn::initializeNewColumn($viewer)
|
||||||
->setSequence(0)
|
->setSequence(0)
|
||||||
|
@ -64,6 +65,16 @@ final class PhabricatorProjectBoardViewController
|
||||||
$column->attachProject($project);
|
$column->attachProject($project);
|
||||||
$columns[0] = $column;
|
$columns[0] = $column;
|
||||||
unset($unguarded);
|
unset($unguarded);
|
||||||
|
break;
|
||||||
|
case 'import':
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI(
|
||||||
|
$this->getApplicationURI('board/'.$project->getID().'/import/'));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return $this->initializeWorkboardDialog($project);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ksort($columns);
|
ksort($columns);
|
||||||
|
@ -406,5 +417,31 @@ final class PhabricatorProjectBoardViewController
|
||||||
return $manage_button;
|
return $manage_button;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function initializeWorkboardDialog(PhabricatorProject $project) {
|
||||||
|
|
||||||
|
$instructions = pht('This workboard has not been setup yet.');
|
||||||
|
$new_selector = id(new AphrontFormRadioButtonControl())
|
||||||
|
->setName('initialize-type')
|
||||||
|
->setValue('backlog-only')
|
||||||
|
->addButton(
|
||||||
|
'backlog-only',
|
||||||
|
pht('New Empty Board'),
|
||||||
|
pht('Create a new board with just a backlog column.'))
|
||||||
|
->addButton(
|
||||||
|
'import',
|
||||||
|
pht('Import Columns'),
|
||||||
|
pht('Import board columns from another project.'));
|
||||||
|
|
||||||
|
$dialog = id(new AphrontDialogView())
|
||||||
|
->setUser($this->getRequest()->getUser())
|
||||||
|
->setTitle(pht('New Workboard'))
|
||||||
|
->addSubmitButton('Continue')
|
||||||
|
->addCancelButton($this->getApplicationURI('view/'.$project->getID().'/'))
|
||||||
|
->appendParagraph($instructions)
|
||||||
|
->appendChild($new_selector);
|
||||||
|
|
||||||
|
return id(new AphrontDialogResponse())
|
||||||
|
->setDialog($dialog);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,24 @@ final class PhabricatorProjectDatasource
|
||||||
->needSlugs(true)
|
->needSlugs(true)
|
||||||
->withDatasourceQuery($raw_query)
|
->withDatasourceQuery($raw_query)
|
||||||
->execute();
|
->execute();
|
||||||
|
$projs = mpull($projs, null, 'getPHID');
|
||||||
|
|
||||||
|
$must_have_cols = $this->getParameter('mustHaveColumns', false);
|
||||||
|
if ($must_have_cols) {
|
||||||
|
$columns = id(new PhabricatorProjectColumnQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withProjectPHIDs(array_keys($projs))
|
||||||
|
->execute();
|
||||||
|
$has_cols = mgroup($columns, 'getProjectPHID');
|
||||||
|
} else {
|
||||||
|
$has_cols = array_fill_keys(array_keys($projs), true);
|
||||||
|
}
|
||||||
|
|
||||||
$results = array();
|
$results = array();
|
||||||
foreach ($projs as $proj) {
|
foreach ($projs as $proj) {
|
||||||
|
if (!isset($has_cols[$proj->getPHID()])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$closed = null;
|
$closed = null;
|
||||||
if ($proj->isArchived()) {
|
if ($proj->isArchived()) {
|
||||||
$closed = pht('Archived');
|
$closed = pht('Archived');
|
||||||
|
|
Loading…
Reference in a new issue