Make drag-and-drop on workboards interact with priority column headers

Summary:
Ref T10333. Ref T8135. Depends on D20247. Allow users to drag-and-drop cards on a priority-sorted workboard under headers, even if the header has no other cards.

As of D20247, headers show up but they aren't really interactive. Now, you can drag cards directly underneath a header (instead of only between other cards). For example, if a column has only one "Wishlist" task, you may drag it under the "High", "Normal", or "Low" priority headers to select a specific priority.

(Some of this code still feels a little rough, but I think it will generalize once other types of sorting are available.)

Test Plan: Dragged cards within and between priority groups, saw appropriate priority edits applied in every case I could come up with.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T10333, T8135

Differential Revision: https://secure.phabricator.com/D20248
This commit is contained in:
epriestley
2019-03-05 07:38:35 -08:00
parent 14a433c773
commit 40af472ff5
11 changed files with 208 additions and 79 deletions

View File

@@ -651,11 +651,15 @@ final class PhabricatorProjectBoardViewController
));
$headers[] = array(
'order' => 'priority',
'order' => PhabricatorProjectColumn::ORDER_PRIORITY,
'key' => $header_key,
'template' => hsprintf('%s', $template),
'vector' => array(
(int)-$priority,
PhabricatorProjectColumn::NODETYPE_HEADER,
),
'editProperties' => array(
PhabricatorProjectColumn::ORDER_PRIORITY => (int)$priority,
),
);
}

View File

@@ -15,6 +15,14 @@ final class PhabricatorProjectMoveController
$before_phid = $request->getStr('beforePHID');
$order = $request->getStr('order', PhabricatorProjectColumn::DEFAULT_ORDER);
$edit_header = null;
$raw_header = $request->getStr('header');
if (strlen($raw_header)) {
$edit_header = phutil_json_decode($raw_header);
} else {
$edit_header = array();
}
$project = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->requireCapabilities(
@@ -87,10 +95,14 @@ final class PhabricatorProjectMoveController
));
if ($order == PhabricatorProjectColumn::ORDER_PRIORITY) {
$header_priority = idx(
$edit_header,
PhabricatorProjectColumn::ORDER_PRIORITY);
$priority_xactions = $this->getPriorityTransactions(
$object,
$after_phid,
$before_phid);
$before_phid,
$header_priority);
foreach ($priority_xactions as $xaction) {
$xactions[] = $xaction;
}
@@ -110,13 +122,33 @@ final class PhabricatorProjectMoveController
private function getPriorityTransactions(
ManiphestTask $task,
$after_phid,
$before_phid) {
$before_phid,
$header_priority) {
$xactions = array();
$must_move = false;
if ($header_priority !== null) {
if ($task->getPriority() !== $header_priority) {
$task = id(clone $task)
->setPriority($header_priority);
$keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
$keyword = head(idx($keyword_map, $header_priority));
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(
ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
->setNewValue($keyword);
$must_move = true;
}
}
list($after_task, $before_task) = $this->loadPriorityTasks(
$after_phid,
$before_phid);
$must_move = false;
if ($after_task && !$task->isLowerPriorityThan($after_task)) {
$must_move = true;
}
@@ -125,10 +157,10 @@ final class PhabricatorProjectMoveController
$must_move = true;
}
// The move doesn't require a priority change to be valid, so don't
// change the priority since we are not being forced to.
// The move doesn't require a subpriority change to be valid, so don't
// change the subpriority since we are not being forced to.
if (!$must_move) {
return array();
return $xactions;
}
$try = array(
@@ -139,28 +171,41 @@ final class PhabricatorProjectMoveController
$pri = null;
$sub = null;
foreach ($try as $spec) {
list($task, $is_after) = $spec;
list($nearby_task, $is_after) = $spec;
if (!$task) {
if (!$nearby_task) {
continue;
}
list($pri, $sub) = ManiphestTransactionEditor::getAdjacentSubpriority(
$task,
$nearby_task,
$is_after);
// If we drag under a "Low" header between a "Normal" task and a "Low"
// task, we don't want to accept a subpriority assignment which changes
// our priority to "Normal". Only accept a subpriority that keeps us in
// the right primary priority.
if ($header_priority !== null) {
if ($pri !== $header_priority) {
continue;
}
}
// If we find a priority on the first try, don't keep going.
break;
}
$keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
$keyword = head(idx($keyword_map, $pri));
$xactions = array();
if ($pri !== null) {
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
->setNewValue($keyword);
if ($header_priority === null) {
$keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
$keyword = head(idx($keyword_map, $pri));
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(
ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
->setNewValue($keyword);
}
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(
ManiphestTaskSubpriorityTransaction::TRANSACTIONTYPE)