From de4519fa2c45ca96d4bf0b9ce288cad600d09854 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Fri, 19 Feb 2016 22:59:47 -0500 Subject: [PATCH] Add subtasks drag and drop --- ChangeLog | 1 + app/Controller/Subtask.php | 15 ++- app/Model/Subtask.php | 70 ++++-------- app/Template/subtask/menu.php | 10 -- app/Template/subtask/show.php | 2 +- app/Template/subtask/table.php | 13 ++- app/Template/task/show.php | 1 - assets/css/app.css | 2 +- assets/css/print.css | 2 +- assets/css/src/table.css | 38 ++++++- assets/js/app.js | 2 +- assets/js/src/App.js | 2 +- assets/js/src/Subtask.js | 62 ++++++++++- composer.json | 2 +- composer.lock | 24 ++-- tests/units/Model/SubtaskTest.php | 176 +++++++++++------------------- 16 files changed, 217 insertions(+), 205 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5a1d3331b..fa2c25977 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ Version 1.0.26 (unreleased) New features: +* Add subtasks drag and drop * Add file drag and drop and asynchronous upload * Enable/Disable users * Add setting option to disable private projects diff --git a/app/Controller/Subtask.php b/app/Controller/Subtask.php index f87989063..a0a3eb669 100644 --- a/app/Controller/Subtask.php +++ b/app/Controller/Subtask.php @@ -23,7 +23,6 @@ class Subtask extends Base 'project' => $this->getProject(), 'subtasks' => $this->subtask->getAll($task['id']), 'editable' => true, - 'redirect' => 'subtask', ))); } @@ -169,15 +168,15 @@ class Subtask extends Base */ public function movePosition() { - $this->checkCSRFParam(); $project_id = $this->request->getIntegerParam('project_id'); $task_id = $this->request->getIntegerParam('task_id'); - $subtask_id = $this->request->getIntegerParam('subtask_id'); - $direction = $this->request->getStringParam('direction'); - $method = $direction === 'up' ? 'moveUp' : 'moveDown'; - $redirect = $this->request->getStringParam('redirect', 'task'); + $values = $this->request->getJson(); - $this->subtask->$method($task_id, $subtask_id); - $this->response->redirect($this->helper->url->to($redirect, 'show', array('project_id' => $project_id, 'task_id' => $task_id), 'subtasks')); + if (! empty($values) && $this->helper->user->hasProjectAccess('Subtask', 'movePosition', $project_id)) { + $result = $this->subtask->changePosition($task_id, $values['subtask_id'], $values['position']); + $this->response->json(array('result' => $result)); + } + + $this->forbidden(); } } diff --git a/app/Model/Subtask.php b/app/Model/Subtask.php index 14853941f..3707af138 100644 --- a/app/Model/Subtask.php +++ b/app/Model/Subtask.php @@ -284,68 +284,36 @@ class Subtask extends Base } /** - * Save the new positions for a set of subtasks + * Save subtask position * * @access public - * @param array $subtasks Hashmap of column_id/column_position + * @param integer $task_id + * @param integer $subtask_id + * @param integer $position * @return boolean */ - public function savePositions(array $subtasks) + public function changePosition($task_id, $subtask_id, $position) { - return $this->db->transaction(function (Database $db) use ($subtasks) { + if ($position < 1 || $position > $this->db->table(self::TABLE)->eq('task_id', $task_id)->count()) { + return false; + } - foreach ($subtasks as $subtask_id => $position) { - if (! $db->table(Subtask::TABLE)->eq('id', $subtask_id)->update(array('position' => $position))) { - return false; - } + $subtask_ids = $this->db->table(self::TABLE)->eq('task_id', $task_id)->neq('id', $subtask_id)->asc('position')->findAllByColumn('id'); + $offset = 1; + $results = array(); + + foreach ($subtask_ids as $current_subtask_id) { + if ($offset == $position) { + $offset++; } - }); - } - /** - * Move a subtask down, increment the position value - * - * @access public - * @param integer $task_id - * @param integer $subtask_id - * @return boolean - */ - public function moveDown($task_id, $subtask_id) - { - $subtasks = $this->getNormalizedPositions($task_id); - $positions = array_flip($subtasks); - - if (isset($subtasks[$subtask_id]) && $subtasks[$subtask_id] < count($subtasks)) { - $position = ++$subtasks[$subtask_id]; - $subtasks[$positions[$position]]--; - - return $this->savePositions($subtasks); + $results[] = $this->db->table(self::TABLE)->eq('id', $current_subtask_id)->update(array('position' => $offset)); + $offset++; } - return false; - } + $results[] = $this->db->table(self::TABLE)->eq('id', $subtask_id)->update(array('position' => $position)); - /** - * Move a subtask up, decrement the position value - * - * @access public - * @param integer $task_id - * @param integer $subtask_id - * @return boolean - */ - public function moveUp($task_id, $subtask_id) - { - $subtasks = $this->getNormalizedPositions($task_id); - $positions = array_flip($subtasks); - - if (isset($subtasks[$subtask_id]) && $subtasks[$subtask_id] > 1) { - $position = --$subtasks[$subtask_id]; - $subtasks[$positions[$position]]++; - - return $this->savePositions($subtasks); - } - - return false; + return !in_array(false, $results, true); } /** diff --git a/app/Template/subtask/menu.php b/app/Template/subtask/menu.php index 16174bcf7..6c98b951a 100644 --- a/app/Template/subtask/menu.php +++ b/app/Template/subtask/menu.php @@ -1,16 +1,6 @@