Skip to content
Snippets Groups Projects
Commit a0dc664b authored by Christopher Johnson's avatar Christopher Johnson
Browse files

updates to c01f23adfb82295588e3a9536f5281f32eef2b6e 04.02.2016

Bug: T125775

Change-Id: Ic632cad2b631fdc6b1b586a21f60698bcab7dbb3
parent 062482bf
No related branches found
No related tags found
No related merge requests found
......@@ -210,7 +210,7 @@ JX.behavior('sprint-boards', function(config, statics) {
JX.DOM.setContent(column, items);
onupdate(column);
}
};
function update_statics(update_config) {
statics.boardID = update_config.boardID;
......@@ -276,13 +276,16 @@ JX.behavior('sprint-boards', function(config, statics) {
// close the dropdown, but don't want to follow the link.
e.prevent();
var column_phid = e.getNodeData('column-add-task').columnPHID;
var column_data = e.getNodeData('column-add-task');
var column_phid = column_data.columnPHID;
var request_data = {
responseType: 'card',
columnPHID: column_phid,
projects: statics.projectPHID,
projects: column_data.projectPHID,
order: statics.order
};
var cols = getcolumns();
var ii;
var column;
......@@ -349,7 +352,8 @@ JX.behavior('sprint-boards', function(config, statics) {
var current_page_id = JX.Quicksand.getCurrentPageID();
statics.boardConfigCache = {};
statics.boardConfigCache[current_page_id] = config;
statics.setup = init_board();
init_board();
statics.setup = setup();
}
});
......@@ -23,6 +23,8 @@ final class SprintBoardColumnDetailController
}
$this->setProject($project);
$project_id = $project->getID();
$column = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withIDs(array($id))
......@@ -46,6 +48,10 @@ final class SprintBoardColumnDetailController
$actions = $this->buildActionView($column);
$properties = $this->buildPropertyView($column, $actions);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Workboard'), "/project/board/{$project_id}/");
$crumbs->addTextCrumb(pht('Column: %s', $title));
$box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
......@@ -55,6 +61,7 @@ final class SprintBoardColumnDetailController
return $this->newPage()
->setTitle($title)
->setNavigation($nav)
->setCrumbs($crumbs)
->appendChild(
array(
$box,
......
......@@ -81,10 +81,12 @@ final class SprintBoardColumnEditController
$xactions = array();
if (!$column->getProxy()) {
$type_name = PhabricatorProjectColumnTransaction::TYPE_NAME;
$xactions[] = id(new PhabricatorProjectColumnTransaction())
->setTransactionType($type_name)
->setNewValue($v_name);
}
$type_limit = PhabricatorProjectColumnTransaction::TYPE_LIMIT;
$xactions[] = id(new PhabricatorProjectColumnTransaction())
......@@ -105,18 +107,19 @@ final class SprintBoardColumnEditController
}
}
$form = new AphrontFormView();
$form
->setUser($request->getUser())
->appendChild(
$form = id(new AphrontFormView())
->setUser($request->getUser());
if (!$column->getProxy()) {
$form->appendChild(
id(new AphrontFormTextControl())
->setValue($v_name)
->setLabel(pht('Name'))
->setName('name')
->setError($e_name)
->setCaption(
pht('This will be displayed as the header of the column.')))
->appendChild(
->setError($e_name));
}
$form->appendChild(
id(new AphrontFormTextControl())
->setValue($v_limit)
->setLabel(pht('Point Limit'))
......
......@@ -26,6 +26,7 @@ final class SprintBoardMoveController
return new Aphront404Response();
}
$is_sprint = $this->isSprint($project);
$board_phid = $project->getPHID();
$object = id(new ManiphestTaskQuery())
->setViewer($viewer)
......@@ -55,11 +56,14 @@ final class SprintBoardMoveController
return new Aphront404Response();
}
$positions = id(new PhabricatorProjectColumnPositionQuery())
$engine = id(new PhabricatorBoardLayoutEngine())
->setViewer($viewer)
->withColumns($columns)
->withObjectPHIDs(array($object_phid))
->execute();
->setBoardPHIDs(array($board_phid))
->setObjectPHIDs(array($object_phid))
->executeLayout();
$columns = $engine->getObjectColumns($board_phid, $object_phid);
$old_column_phids = mpull($columns, 'getPHID');
$xactions = array();
......@@ -81,7 +85,7 @@ final class SprintBoardMoveController
) + $order_params)
->setOldValue(
array(
'columnPHIDs' => mpull($positions, 'getColumnPHID'),
'columnPHIDs' => $old_column_phids,
'projectPHID' => $column->getProjectPHID(),
));
......@@ -137,6 +141,32 @@ final class SprintBoardMoveController
}
}
$proxy = $column->getProxy();
if ($proxy) {
// We're moving the task into a subproject or milestone column, so add
// the subproject or milestone.
$add_projects = array($proxy->getPHID());
} else if ($project->getHasSubprojects() || $project->getHasMilestones()) {
// We're moving the task into the "Backlog" column on the parent project,
// so add the parent explicitly. This gets rid of any subproject or
// milestone tags.
$add_projects = array($project->getPHID());
} else {
$add_projects = array();
}
if ($add_projects) {
$project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $project_type)
->setNewValue(
array(
'+' => array_fuse($add_projects),
));
}
$editor = id(new ManiphestTransactionEditor())
->setActor($viewer)
->setContinueOnMissingFields(true)
......@@ -152,9 +182,41 @@ final class SprintBoardMoveController
->withPHIDs(array($object->getOwnerPHID()))
->executeOne();
}
// Reload the object so it reflects edits which have been applied.
$object = id(new ManiphestTaskQuery())
->setViewer($viewer)
->withPHIDs(array($object_phid))
->needProjectPHIDs(true)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
$except_phids = array($board_phid);
if ($project->getHasSubprojects() || $project->getHasMilestones()) {
$descendants = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withAncestorProjectPHIDs($except_phids)
->execute();
foreach ($descendants as $descendant) {
$except_phids[] = $descendant->getPHID();
}
}
$except_phids = array_fuse($except_phids);
$handle_phids = array_fuse($object->getProjectPHIDs());
$handle_phids = array_diff_key($handle_phids, $except_phids);
$project_handles = $viewer->loadHandles($handle_phids);
$project_handles = iterator_to_array($project_handles);
if ($is_sprint == true) {
$card = id(new SprintBoardTaskCard())
->setProject($project)
->setProjectHandles($project_handles)
->setViewer($viewer)
->setTask($object)
->setOwner($owner)
......@@ -164,6 +226,7 @@ final class SprintBoardMoveController
$card = id(new ProjectBoardTaskCard())
->setViewer($viewer)
->setTask($object)
->setProjectHandles($project_handles)
->setOwner($owner)
->setCanEdit(true)
->setProject($project)
......
......@@ -28,68 +28,34 @@ final class SprintBoardViewController
$project = $this->getProject();
$this->readRequestState();
$columns = $this->loadColumns($project);
// TODO: Expand the checks here if we add the ability
// to hide the Backlog column
if (!$columns) {
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$project,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$can_edit) {
$content = $this->buildNoAccessContent($project);
} else {
$content = $this->buildInitializeContent($project);
}
if ($content instanceof AphrontResponse) {
return $content;
}
$nav = $this->getProfileMenu();
$nav->selectFilter(PhabricatorProject::PANEL_WORKBOARD);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Workboard'));
return $this->newPage()
->setTitle(
array(
pht('Workboard'),
$project->getName(),
))
->setNavigation($nav)
->setCrumbs($crumbs)
->appendChild($content);
}
$is_sprint = $this->isSprint($project);
$board_uri = $this->getApplicationURI('board/'.$project->getID().'/');
$engine = id(new ManiphestTaskSearchEngine())
$search_engine = id(new ManiphestTaskSearchEngine())
->setViewer($viewer)
->setBaseURI($board_uri)
->setIsBoardView(true);
if ($request->isFormPost()) {
$saved = $engine->buildSavedQueryFromRequest($request);
$engine->saveQuery($saved);
if ($request->isFormPost() && !$request->getBool('initialize')) {
$saved = $search_engine->buildSavedQueryFromRequest($request);
$search_engine->saveQuery($saved);
$filter_form = id(new AphrontFormView())
->setUser($viewer);
$engine->buildSearchForm($filter_form, $saved);
if ($engine->getErrors()) {
$search_engine->buildSearchForm($filter_form, $saved);
if ($search_engine->getErrors()) {
return $this->newDialog()
->setWidth(AphrontDialogView::WIDTH_FULL)
->setTitle(pht('Advanced Filter'))
->appendChild($filter_form->buildLayoutView())
->setErrors($engine->getErrors())
->setErrors($search_engine->getErrors())
->setSubmitURI($board_uri)
->addSubmitButton(pht('Apply Filter'))
->addCancelButton($board_uri);
}
return id(new AphrontRedirectResponse())->setURI(
$this->getURIWithState(
$engine->getQueryResultsPageURI($saved->getQueryKey())));
$search_engine->getQueryResultsPageURI($saved->getQueryKey())));
}
$query_key = $request->getURIData('queryKey');
......@@ -103,8 +69,8 @@ final class SprintBoardViewController
$this->queryKey = $query_key;
$custom_query = null;
if ($engine->isBuiltinQuery($query_key)) {
$saved = $engine->buildSavedQueryFromBuiltin($query_key);
if ($search_engine->isBuiltinQuery($query_key)) {
$saved = $search_engine->buildSavedQueryFromBuiltin($query_key);
} else {
$saved = id(new PhabricatorSavedQueryQuery())
->setViewer($viewer)
......@@ -121,7 +87,7 @@ final class SprintBoardViewController
if ($request->getURIData('filter')) {
$filter_form = id(new AphrontFormView())
->setUser($viewer);
$engine->buildSearchForm($filter_form, $saved);
$search_engine->buildSearchForm($filter_form, $saved);
return $this->newDialog()
->setWidth(AphrontDialogView::WIDTH_FULL)
......@@ -132,58 +98,68 @@ final class SprintBoardViewController
->addCancelButton($board_uri);
}
$task_query = $engine->buildQueryFromSavedQuery($saved);
$task_query = $search_engine->buildQueryFromSavedQuery($saved);
$select_phids = array($project->getPHID());
if ($project->getHasSubprojects() || $project->getHasMilestones()) {
$descendants = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withAncestorProjectPHIDs($select_phids)
->execute();
foreach ($descendants as $descendant) {
$select_phids[] = $descendant->getPHID();
}
}
$tasks = $task_query
->withEdgeLogicPHIDs(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
PhabricatorQueryConstraint::OPERATOR_AND,
array($project->getPHID()))
PhabricatorQueryConstraint::OPERATOR_ANCESTOR,
array($select_phids))
->setOrder(ManiphestTaskQuery::ORDER_PRIORITY)
->setViewer($viewer)
->execute();
$tasks = mpull($tasks, null, 'getPHID');
if ($tasks) {
$positions = id(new PhabricatorProjectColumnPositionQuery())
$board_phid = $project->getPHID();
$layout_engine = id(new PhabricatorBoardLayoutEngine())
->setViewer($viewer)
->withObjectPHIDs(mpull($tasks, 'getPHID'))
->withColumns($columns)
->execute();
$positions = mpull($positions, null, 'getObjectPHID');
->setBoardPHIDs(array($board_phid))
->setObjectPHIDs(array_keys($tasks))
->executeLayout();
$columns = $layout_engine->getColumns($board_phid);
if (!$columns) {
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$project,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$can_edit) {
$content = $this->buildNoAccessContent($project);
} else {
$positions = array();
$content = $this->buildInitializeContent($project);
}
$task_map = array();
foreach ($tasks as $task) {
$task_phid = $task->getPHID();
if (empty($positions[$task_phid])) {
// This shouldn't normally be possible because we create positions on
// demand, but we might have raced as an object was removed from the
// board. Just drop the task if we don't have a position for it.
continue;
if ($content instanceof AphrontResponse) {
return $content;
}
$position = $positions[$task_phid];
$task_map[$position->getColumnPHID()][] = $task_phid;
}
$nav = $this->getProfileMenu();
$nav->selectFilter(PhabricatorProject::PANEL_WORKBOARD);
// If we're showing the board in "natural" order, sort columns by their
// column positions.
if ($this->sortKey == PhabricatorProjectColumn::ORDER_NATURAL) {
foreach ($task_map as $column_phid => $task_phids) {
$order = array();
foreach ($task_phids as $task_phid) {
if (isset($positions[$task_phid])) {
$order[$task_phid] = $positions[$task_phid]->getOrderingKey();
} else {
$order[$task_phid] = 0;
}
}
asort($order);
$task_map[$column_phid] = array_keys($order);
}
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Workboard'));
return $this->newPage()
->setTitle(
array(
pht('Workboard'),
$project->getName(),
))
->setNavigation($nav)
->setCrumbs($crumbs)
->appendChild($content);
}
$task_can_edit_map = id(new PhabricatorPolicyFilter())
......@@ -202,7 +178,10 @@ final class SprintBoardViewController
return new Aphront404Response();
}
$batch_task_phids = idx($task_map, $batch_column->getPHID(), array());
$batch_task_phids = $layout_engine->getColumnObjectPHIDs(
$board_phid,
$batch_column->getPHID());
foreach ($batch_task_phids as $key => $batch_task_phid) {
if (empty($task_can_edit_map[$batch_task_phid])) {
unset($batch_task_phids[$key]);
......@@ -270,10 +249,46 @@ final class SprintBoardViewController
$this->handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks);
$all_project_phids = array();
foreach ($tasks as $task) {
foreach ($task->getProjectPHIDs() as $project_phid) {
$all_project_phids[$project_phid] = $project_phid;
}
}
foreach ($select_phids as $phid) {
unset($all_project_phids[$phid]);
}
$all_handles = $viewer->loadHandles($all_project_phids);
$all_handles = iterator_to_array($all_handles);
foreach ($columns as $column) {
$task_phids = idx($task_map, $column->getPHID(), array());
if (!$this->showHidden) {
if ($column->isHidden()) {
continue;
}
}
$proxy = $column->getProxy();
if ($proxy && !$proxy->isMilestone()) {
// TODO: For now, don't show subproject columns because we can't
// handle tasks with multiple positions yet.
continue;
}
$task_phids = $layout_engine->getColumnObjectPHIDs(
$board_phid,
$column->getPHID());
$column_tasks = array_select_keys($tasks, $task_phids);
// If we aren't using "natural" order, reorder the column by the original
// query order.
if ($this->sortKey != PhabricatorProjectColumn::ORDER_NATURAL) {
$column_tasks = array_select_keys($column_tasks, array_keys($tasks));
}
$panel = id(new PHUIWorkpanelView())
->setHeader($column->getDisplayName())
->setSubHeader($column->getDisplayType())
......@@ -284,6 +299,11 @@ final class SprintBoardViewController
$panel->setHeaderIcon($header_icon);
}
$display_class = $column->getDisplayClass();
if ($display_class) {
$panel->addClass($display_class);
}
if ($column->isHidden()) {
$panel->addClass('project-panel-hidden');
}
......@@ -323,9 +343,11 @@ final class SprintBoardViewController
$owner = $this->handles[$task->getOwnerPHID()];
}
$can_edit = idx($task_can_edit_map, $task->getPHID(), false);
$handles = array_select_keys($all_handles, $task->getProjectPHIDs());
if ($is_sprint == true) {
$cards->addItem(id(new SprintBoardTaskCard())
->setProject($project)
->setProjectHandles($handles)
->setViewer($viewer)
->setTask($task)
->setOwner($owner)
......@@ -335,6 +357,7 @@ final class SprintBoardViewController
$cards->addItem(id(new ProjectBoardTaskCard())
->setViewer($viewer)
->setProject($project)
->setProjectHandles($handles)
->setTask($task)
->setOwner($owner)
->setCanEdit($can_edit)
......@@ -352,7 +375,7 @@ final class SprintBoardViewController
$filter_menu = $this->buildFilterMenu(
$viewer,
$custom_query,
$engine,
$search_engine,
$query_key);
$manage_menu = $this->buildManageMenu($project, $this->showHidden);
......@@ -413,25 +436,6 @@ final class SprintBoardViewController
$this->sortKey = $sort_key;
}
private function loadColumns(PhabricatorProject $project) {
$viewer = $this->getViewer();
$column_query = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withProjectPHIDs(array($project->getPHID()));
if (!$this->showHidden) {
$column_query->withStatuses(
array(PhabricatorProjectColumn::STATUS_ACTIVE));
}
$columns = $column_query->execute();
$columns = mpull($columns, null, 'getSequence');
ksort($columns);
return $columns;
}
private function buildSortMenu(
PhabricatorUser $viewer,
$sort_key) {
......@@ -562,7 +566,7 @@ final class SprintBoardViewController
$show_hidden) {
$request = $this->getRequest();
$viewer = $request->getViewer();
$viewer = $request->getUser();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
......@@ -648,6 +652,12 @@ final class SprintBoardViewController
$column_items = array();
if ($column->getProxyPHID()) {
$default_phid = $column->getProxyPHID();
} else {
$default_phid = $column->getProjectPHID();
}
$column_items[] = id(new PhabricatorActionView())
->setIcon('fa-plus')
->setName(pht('Create Task...'))
......@@ -656,6 +666,7 @@ final class SprintBoardViewController
->setMetadata(
array(
'columnPHID' => $column->getPHID(),
'projectPHID' => $default_phid,
));
$batch_edit_uri = $request->getRequestURI();
......@@ -718,6 +729,7 @@ final class SprintBoardViewController
return $column_button;
}
/**
* Add current state parameters (like order and the visibility of hidden
* columns) to a URI.
......@@ -833,6 +845,7 @@ final class SprintBoardViewController
$form = id(new AphrontFormView())
->setUser($viewer)
->addHiddenInput('initialize', 1)
->appendRemarkupInstructions(
pht('The workboard for this project has not been created yet.'))
->appendControl($new_selector)
......
......@@ -280,20 +280,35 @@ final class SprintManiphestEditEngine
return new Aphront404Response();
}
// If the workboard's project has been removed from the card's project
// list, we are going to remove it from the board completely.
// If the workboard's project and all descendant projects have been removed
// from the card's project list, we are going to remove it from the board
// completely.
// TODO: If the user did something sneaky and changed a subproject, we'll
// currently leave the card where it was but should really move it to the
// proper new column.
$descendant_projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withAncestorProjectPHIDs(array($column->getProjectPHID()))
->execute();
$board_phids = mpull($descendant_projects, 'getPHID', 'getPHID');
$board_phids[$column->getProjectPHID()] = $column->getProjectPHID();
$project_map = array_fuse($task->getProjectPHIDs());
$remove_card = empty($project_map[$column->getProjectPHID()]);
$remove_card = !array_intersect_key($board_phids, $project_map);
$positions = id(new PhabricatorProjectColumnPositionQuery())
->setViewer($viewer)
->withColumns(array($column))
->withBoardPHIDs(array($column->getProjectPHID()))
->withColumnPHIDs(array($column->getPHID()))
->execute();
$task_phids = mpull($positions, 'getObjectPHID');
$column_tasks = id(new ManiphestTaskQuery())
->setViewer($viewer)
->withPHIDs($task_phids)
->needProjectPHIDs(true)
->execute();
if ($order == PhabricatorProjectColumn::ORDER_NATURAL) {
......@@ -329,17 +344,27 @@ final class SprintManiphestEditEngine
->executeOne();
}
$handle_phids = $task->getProjectPHIDs();
$handle_phids = array_fuse($handle_phids);
$handle_phids = array_diff_key($handle_phids, $board_phids);
$project_handles = $viewer->loadHandles($handle_phids);
$project_handles = iterator_to_array($project_handles);
$projects = $request->getArr('projectPHIDs');
$project = $this->getSprintProjectforTask($viewer, $projects);
$tasks = id(new SprintBoardTaskCard())
->setViewer($viewer)
->setProject($project)
->setProjectHandles($project_handles)
->setTask($task)
->setOwner($owner)
->setCanEdit(true)
->getItem();
$tasks->addClass('phui-workcard');
$payload = array(
'tasks' => $tasks,
'data' => $data,
......
......@@ -304,8 +304,7 @@ final class SprintQuery extends SprintDAO {
->setViewer($this->viewer)
->withBoardPHIDs(array($this->projectPHID))
->withObjectPHIDs(mpull($tasks, 'getPHID'))
->withColumns($columns)
->needColumns(true)
->withColumnPHIDs(mpull($columns, 'getPHID'))
->execute();
$positions = mpull($positions, null, 'getObjectPHID');
} else {
......
......@@ -4,6 +4,7 @@ final class SprintBoardTaskCard extends Phobject {
private $project;
private $viewer;
private $projectHandles;
private $task;
private $owner;
private $canEdit;
......@@ -28,6 +29,15 @@ final class SprintBoardTaskCard extends Phobject {
return $this->viewer;
}
public function setProjectHandles(array $handles) {
$this->projectHandles = $handles;
return $this;
}
public function getProjectHandles() {
return $this->projectHandles;
}
public function setTask(ManiphestTask $task) {
$this->task = $task;
return $this;
......@@ -128,14 +138,12 @@ final class SprintBoardTaskCard extends Phobject {
$card->addHandleIcon($owner, $owner->getName());
}
$card->addAttribute($this->getCardAttributes());
$project_phids = array_fuse($task->getProjectPHIDs());
unset($project_phids[$this->project->getPHID()]);
if ($project_phids) {
$handle_list = $viewer->loadHandles($project_phids);
$project_handles = $this->getProjectHandles();
if ($project_handles) {
$tag_list = id(new PHUIHandleTagListView())
->setSlim(true)
->setHandles($handle_list);
->setHandles($project_handles);
$card->addAttribute($tag_list);
}
return $card;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment