diff --git a/module/task/config/form.php b/module/task/config/form.php index 41986e20f5..c1c28e16a7 100644 --- a/module/task/config/form.php +++ b/module/task/config/form.php @@ -93,3 +93,8 @@ $config->task->form->batchCreate['estStarted'] = array('type' => 'array', 're $config->task->form->batchCreate['deadline'] = array('type' => 'array', 'required' => false, 'default' => array()); $config->task->form->batchCreate['desc'] = array('type' => 'array', 'required' => false, 'default' => array()); $config->task->form->batchCreate['pri'] = array('type' => 'array', 'required' => false, 'default' => array()); + +$config->task->form->pause = array(); +$config->task->form->pause['lastEditedBy'] = array('type' => 'string', 'required' => false, 'default' => $app->user->account); +$config->task->form->pause['lastEditedDate'] = array('type' => 'string', 'required' => false, 'default' => helper::now()); +$config->task->form->pause['status'] = array('type' => 'string', 'required' => false, 'default' => 'pause'); diff --git a/module/task/control.php b/module/task/control.php index 113d54dcf7..846531c2b6 100755 --- a/module/task/control.php +++ b/module/task/control.php @@ -802,6 +802,7 @@ class task extends control } /** + * 暂停任务。 * Pause task. * * @param int $taskID @@ -809,7 +810,7 @@ class task extends control * @access public * @return void */ - public function pause($taskID, $extra = '') + public function pause(int $taskID, string $extra = '') { $this->taskZen->commonAction($taskID); @@ -818,52 +819,33 @@ class task extends control if(!empty($_POST)) { - $this->loadModel('action'); - $changes = $this->task->pause($taskID, $extra); - if(dao::isError()) return print(js::error(dao::getError())); + /* Init task data. */ + $postData = form::data($this->config->task->form->pause); + $task = $postData->data; + $task->id = $taskID; + /* Pause task. */ + $changes = $this->task->pause($task, $output); + if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError()); + + /* Record log. */ if($this->post->comment != '' or !empty($changes)) { - $actionID = $this->action->create('task', $taskID, 'Paused', $this->post->comment); + $actionID = $this->loadModel('action')->create('task', $taskID, 'Paused', $this->post->comment); $this->action->logHistory($actionID, $changes); } $this->executeHooks($taskID); - if(isonlybody()) - { - $task = $this->task->getById($taskID); - $execution = $this->execution->getByID($task->execution); - $executionLaneType = $this->session->executionLaneType ? $this->session->executionLaneType : 'all'; - $executionGroupBy = $this->session->executionGroupBy ? $this->session->executionGroupBy : 'default'; - if(($this->app->tab == 'execution' or ($this->config->vision == 'lite' and $this->app->tab == 'project')) and $execution->type == 'kanban') - { - $rdSearchValue = $this->session->rdSearchValue ? $this->session->rdSearchValue : ''; - $regionID = !empty($output['regionID']) ? $output['regionID'] : 0; - $kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $executionLaneType, 'id_desc', $regionID, $executionGroupBy, $rdSearchValue); - $kanbanData = json_encode($kanbanData); - - return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)")); - } - if($output['from'] == 'taskkanban') - { - $taskSearchValue = $this->session->taskSearchValue ? $this->session->taskSearchValue : ''; - $kanbanData = $this->loadModel('kanban')->getExecutionKanban($task->execution, $executionLaneType, $executionGroupBy, $taskSearchValue); - $kanbanType = $executionLaneType == 'all' ? 'task' : key($kanbanData); - $kanbanData = $kanbanData[$kanbanType]; - $kanbanData = json_encode($kanbanData); - - return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban(\"task\", $kanbanData)")); - } - return print(js::closeModal('parent.parent', 'this')); - } - - return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); + /* Get response after the suspended task. */ + $from = zget($output, 'from'); + $task = $this->task->getById($taskID); + $response = $this->taskZen->responseAfterChangeStatus($task, $from); + return $this->send($response); } - $this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->task->pause; - $this->view->position[] = $this->lang->task->pause; - + /* Show the variables associated. */ + $this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->task->pause; $this->view->users = $this->loadModel('user')->getPairs('noletter'); $this->display(); } diff --git a/module/task/model.php b/module/task/model.php index 55304e2a25..575b24a4c2 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -1514,36 +1514,27 @@ class taskModel extends model /** * Pause task * - * @param int $taskID - * @param string $extra + * @param object $task + * @param array $output * @access public - * @return array + * @return array|bool */ - public function pause($taskID, $extra = '') + public function pause(object $task, array $output = array()): bool|array { - $extra = str_replace(array(',', ' '), array('&', ''), $extra); - parse_str($extra, $output); + /* Get old task. */ + $oldTask = $this->getById($task->id); - $oldTask = $this->getById($taskID); + /* Update kanban status. */ + $this->dao->update(TABLE_TASK)->data($task)->autoCheck()->checkFlow()->where('id')->eq($task->id)->exec(); - $task = fixer::input('post') - ->add('id', $taskID) - ->setDefault('status', 'pause') - ->setDefault('lastEditedBy', $this->app->user->account) - ->setDefault('lastEditedDate', helper::now()) - ->stripTags($this->config->task->editor->pause['id'], $this->config->allowedTags) - ->remove('comment') - ->get(); + /* If task has parent task, update status of the parent task. */ + if($oldTask->parent > 0) $this->updateParentStatus($task->id); - $task = $this->loadModel('file')->processImgURL($task, $this->config->task->editor->pause['id'], $this->post->uid); - $this->dao->update(TABLE_TASK)->data($task)->autoCheck()->checkFlow()->where('id')->eq((int)$taskID)->exec(); + /* If output is not empty, update kanban cell. */ + $this->updateKanbanCell($task->id, $output, $oldTask->execution); - if($oldTask->parent > 0) $this->updateParentStatus($taskID); - - $this->loadModel('kanban'); - if(!isset($output['toColID'])) $this->kanban->updateLane($oldTask->execution, 'task', $taskID); - if(isset($output['toColID'])) $this->kanban->moveCard($taskID, $output['fromColID'], $output['toColID'], $output['fromLaneID'], $output['toLaneID']); - if(!dao::isError()) return common::createChanges($oldTask, $task); + if(dao::isError()) return false; + return common::createChanges($oldTask, $task); } /** @@ -3455,7 +3446,7 @@ class taskModel extends model $menu .= $this->buildMenu('task', 'finish', $params, $task, 'browse', '', '', 'iframe', true); $menu .= $this->buildMenu('task', 'close', $params, $task, 'browse', '', '', 'iframe', true); - if(in_array(true, array($canStart, $canRestart, $canFinish, $canClose)) and in_array(true, array($canRecordEstimate, $canEdit, $canBatchCreate))) + if(in_array(true, array($canStart, $canRestart, $canFinish, $canClose)) and in_array(true, $canRecordEstimate, $canEdit, $canBatchCreate)) { $menu .= "
"; } @@ -3922,4 +3913,20 @@ class taskModel extends model $this->action->create('task', $childTaskID, 'Opened'); } } + + /** + * 更新看板单元格。 + * Update kanban cell. + * + * @param int $taskID + * @param array $output + * @param int $executionID + * @access public + * @return void + */ + public function updateKanbanCell(int $taskID, array $output, int $executionID): void + { + if(!isset($output['toColID'])) $this->loadModel('kanban')->updateLane($executionID, 'task', $taskID); + if(isset($output['toColID'])) $this->loadModel('kanban')->moveCard($taskID, $output['fromColID'], $output['toColID'], $output['fromLaneID'], $output['toLaneID']); + } } diff --git a/module/task/test/model/pause.php b/module/task/test/model/pause.php index dd38c1440e..396e48c647 100755 --- a/module/task/test/model/pause.php +++ b/module/task/test/model/pause.php @@ -2,27 +2,24 @@ config('task_pause')->gen(7); +zdTable('project')->config('project_pause')->gen(1); /** title=taskModel->pause(); +timeout=0 cid=1 -pid=1 - -wait状态任务暂停 >> status,wait,pause -doing状态任务暂停 >> status,doing,pause -done状态任务暂停 >> status,done,pause -cancel状态任务暂停 >> status,cancel,pause -closed状态任务暂停 >> status,closed,pause */ -$taskIDList = array('19','20','21','23','24'); +$taskIDList = array('1', '2', '3', '4', '5', '7'); $task = new taskTest(); -r($task->pauseTest($taskIDList[0])) && p('0:field,old,new') && e('status,wait,pause'); //wait状态任务暂停 -r($task->pauseTest($taskIDList[1])) && p('0:field,old,new') && e('status,doing,pause'); //doing状态任务暂停 -r($task->pauseTest($taskIDList[2])) && p('0:field,old,new') && e('status,done,pause'); //done状态任务暂停 -r($task->pauseTest($taskIDList[3])) && p('0:field,old,new') && e('status,cancel,pause'); //cancel状态任务暂停 -r($task->pauseTest($taskIDList[4])) && p('0:field,old,new') && e('status,closed,pause'); //closed状态任务暂停 +r($task->pauseTest($taskIDList[0])) && p('0:field,old,new') && e('status,wait,pause'); // wait状态任务暂停 +r($task->pauseTest($taskIDList[1])) && p('0:field,old,new') && e('status,doing,pause'); // doing状态任务暂停 +r($task->pauseTest($taskIDList[2])) && p('0:field,old,new') && e('status,done,pause'); // done状态任务暂停 +r($task->pauseTest($taskIDList[3])) && p('0:field,old,new') && e('status,cancel,pause'); // cancel状态任务暂停 +r($task->pauseTest($taskIDList[4])) && p('0:field,old,new') && e('status,closed,pause'); // closed状态任务暂停 +r($task->pauseTest($taskIDList[5])) && p('0:field,old,new') && e('status,doing,pause'); // doing状态子任务暂停 diff --git a/module/task/test/model/updatekanbancell.php b/module/task/test/model/updatekanbancell.php new file mode 100644 index 0000000000..a3b8a425ed --- /dev/null +++ b/module/task/test/model/updatekanbancell.php @@ -0,0 +1,37 @@ +#!/usr/bin/env php +config('task_updatekanbancell')->gen(7); +zdTable('project')->config('project_updatekanbancell')->gen(1); + +zdTable('kanbanregion')->config('kanbanregion_updatekanbancell')->gen(1); +zdTable('kanbanlane')->config('kanbanlane_updatekanbancell')->gen(1); +zdTable('kanbancolumn')->config('kanbancolumn_updatekanbancell')->gen(7); +zdTable('kanbancell')->config('kanbancell_updatekanbancell')->gen(7); + +/** + +title=taskModel->updateKanbanCell(); +timeout=0 +cid=1 + +*/ + +$taskIDList = array(1, 2, 3, 4, 5, 7); +$executionID = 11; + +$output = array(); +$output[] = array('fromColID' => 1, 'toColID' => 2, 'fromLaneID' => 1, 'toLaneID' => 1); +$output[] = array('fromColID' => 2, 'toColID' => 6, 'fromLaneID' => 1, 'toLaneID' => 1); + + +$task = new taskTest(); +r($task->updateKanbanCellTest($taskIDList[0], $executionID, array())) && p() && e('1:,1,|2:|3:,2,7,|4:,3,|5:|6:,4,|7:,5,'); // 测试获取wait状态任务更新看板单元格不传output后的看板单元格数据 +r($task->updateKanbanCellTest($taskIDList[1], $executionID, array())) && p() && e('1:,1,|2:|3:,2,7,|4:,3,|5:|6:,4,|7:,5,'); // 测试获取doing状态任务更新看板单元格不传output后的看板单元格数据 +r($task->updateKanbanCellTest($taskIDList[2], $executionID, array())) && p() && e('1:,1,|2:|3:,2,7,|4:,3,|5:|6:,4,|7:,5,'); // 测试获取done状态任务更新看板单元格不传output后的看板单元格数据 +r($task->updateKanbanCellTest($taskIDList[3], $executionID, array())) && p() && e('1:,1,|2:|3:,2,7,|4:,3,|5:|6:,4,|7:,5,'); // 测试获取cancel状态任务更新看板单元格不传output后的看板单元格数据 +r($task->updateKanbanCellTest($taskIDList[4], $executionID, array())) && p() && e('1:,1,|2:|3:,2,7,|4:,3,|5:|6:,4,|7:,5,'); // 测试获取closed状态任务更新看板单元格不传output后的看板单元格数据 +r($task->updateKanbanCellTest($taskIDList[0], $executionID, $output[0])) && p() && e('1:|2:,1,|3:,2,7,|4:,3,|5:|6:,4,|7:,5,'); // 测试获取wait状态从第一列挪到第二列后的看板单元格数据 +r($task->updateKanbanCellTest($taskIDList[0], $executionID, $output[1])) && p() && e('1:|2:|3:,2,7,|4:,3,|5:|6:,4,1,|7:,5,'); // 测试获取wait状态从第二列挪到第六列后的看板单元格数据 diff --git a/module/task/test/model/yaml/pause/project_pause.yaml b/module/task/test/model/yaml/pause/project_pause.yaml new file mode 100755 index 0000000000..e9d090d55a --- /dev/null +++ b/module/task/test/model/yaml/pause/project_pause.yaml @@ -0,0 +1,9 @@ +--- +title: zt_project +author: Mengyi Liu +version: "1.0" +fields: +- field: type + range: scrum +... + diff --git a/module/task/test/model/yaml/pause/task_pause.yaml b/module/task/test/model/yaml/pause/task_pause.yaml new file mode 100755 index 0000000000..3945c873f9 --- /dev/null +++ b/module/task/test/model/yaml/pause/task_pause.yaml @@ -0,0 +1,15 @@ +--- +title: zt_task +author: Mengyi Liu +version: "1.0" +fields: +- field: execution + range: 11 +- field: story + range: 0 +- field: parent + range: "0{5},`-1`,6" +- field: status + range: "wait,doing,done,cancel,closed,doing{2}" +... + diff --git a/module/task/test/model/yaml/updatekanbancell/kanbancell_updatekanbancell.yaml b/module/task/test/model/yaml/updatekanbancell/kanbancell_updatekanbancell.yaml new file mode 100644 index 0000000000..d08a208f3a --- /dev/null +++ b/module/task/test/model/yaml/updatekanbancell/kanbancell_updatekanbancell.yaml @@ -0,0 +1,19 @@ +--- +title: zt_kanbancell +author: Mengyi Liu +version: "1.0" +fields: +- field: id + range: 1-100 +- field: kanban + range: 11 +- field: lane + range: 1 +- field: column + range: 1-7 +- field: type + range: "task" +- field: cards + range: "[]" +... + diff --git a/module/task/test/model/yaml/updatekanbancell/kanbancolumn_updatekanbancell.yaml b/module/task/test/model/yaml/updatekanbancell/kanbancolumn_updatekanbancell.yaml new file mode 100644 index 0000000000..30d9d8d7f3 --- /dev/null +++ b/module/task/test/model/yaml/updatekanbancell/kanbancolumn_updatekanbancell.yaml @@ -0,0 +1,19 @@ +--- +title: zt_kanbancolumn +author: Mengyi Liu +version: "1.0" +fields: +- field: id + range: 1-7 +- field: region + range: 1 +- field: type + range: wait,develop,developing,developed,pause,canceled,closed, +- field: parent + range: "0,`-1`,2{2},0{3}" +- field: name + range: 未开始,开发,研发中,研发完毕,已暂停,已取消,已关闭 +- field: limit + range: "`-1`" +... + diff --git a/module/task/test/model/yaml/updatekanbancell/kanbanlane_updatekanbancell.yaml b/module/task/test/model/yaml/updatekanbancell/kanbanlane_updatekanbancell.yaml new file mode 100644 index 0000000000..e9fbd9a9db --- /dev/null +++ b/module/task/test/model/yaml/updatekanbancell/kanbanlane_updatekanbancell.yaml @@ -0,0 +1,19 @@ +--- +title: zt_kanbanlane +author: Mengyi Liu +version: "1.0" +fields: +- field: id + range: 1-10 +- field: execution + range: 11 +- field: type + range: "task" +- field: region + range: 1 +- field: lastEditedTime + range: "20220101 000000" + type: timestamp + format: "YY/MM/DD hh:mm:ss" +... + diff --git a/module/task/test/model/yaml/updatekanbancell/kanbanregion_updatekanbancell.yaml b/module/task/test/model/yaml/updatekanbancell/kanbanregion_updatekanbancell.yaml new file mode 100644 index 0000000000..300db12fd6 --- /dev/null +++ b/module/task/test/model/yaml/updatekanbancell/kanbanregion_updatekanbancell.yaml @@ -0,0 +1,17 @@ +--- +title: zt_kanbanregion +author: Mengyi Liu +version: "1.0" +fields: +- field: id + range: 1-10 +- field: space + range: 0 +- field: kanban + range: 11 +- field: lastEditedDate + range: "20220101 000000" + type: timestamp + format: "YY/MM/DD hh:mm:ss" +... + diff --git a/module/task/test/model/yaml/updatekanbancell/project_updatekanbancell.yaml b/module/task/test/model/yaml/updatekanbancell/project_updatekanbancell.yaml new file mode 100755 index 0000000000..e9d090d55a --- /dev/null +++ b/module/task/test/model/yaml/updatekanbancell/project_updatekanbancell.yaml @@ -0,0 +1,9 @@ +--- +title: zt_project +author: Mengyi Liu +version: "1.0" +fields: +- field: type + range: scrum +... + diff --git a/module/task/test/model/yaml/updatekanbancell/task_updatekanbancell.yaml b/module/task/test/model/yaml/updatekanbancell/task_updatekanbancell.yaml new file mode 100755 index 0000000000..3945c873f9 --- /dev/null +++ b/module/task/test/model/yaml/updatekanbancell/task_updatekanbancell.yaml @@ -0,0 +1,15 @@ +--- +title: zt_task +author: Mengyi Liu +version: "1.0" +fields: +- field: execution + range: 11 +- field: story + range: 0 +- field: parent + range: "0{5},`-1`,6" +- field: status + range: "wait,doing,done,cancel,closed,doing{2}" +... + diff --git a/module/task/test/task.class.php b/module/task/test/task.class.php index d1460af5af..542932d73d 100644 --- a/module/task/test/task.class.php +++ b/module/task/test/task.class.php @@ -584,29 +584,28 @@ class taskTest } /** + * 测试暂停任务。 * Test pause a task. * * @param int $taskID - * @param array $param * @access public * @return array */ - public function pauseTest($taskID, $param = array()) + public function pauseTest(int $taskID): array { - $createFields = array('status' => 'pause', 'comment' => '单元测试'); - foreach($createFields as $field => $defaultValue) $_POST[$field] = $defaultValue; - foreach($param as $key => $value) $_POST[$key] = $value; - $object = $this->objectModel->pause($taskID); - unset($_POST); - if(dao::isError()) - { - $error = dao::getError(); - return $error[0]; - } - else - { - return $object; - } + $task = new stdclass(); + $task->id = $taskID; + $task->status = 'pause'; + $task->lastEditedBy = 'admin'; + $task->lastEditedDate = helper::now(); + + $_SERVER['HTTP_HOST'] = ''; + + $changes = $this->objectModel->pause($task, array()); + + if(dao::isError()) return dao::getError(); + + return $changes; } /** @@ -2052,4 +2051,28 @@ class taskTest return $result; } + + /** + * 测试更新看板单元格。 + * Test update kanban cell. + * + * @param int $taskID + * @param array $output + * @param int $executionID + * @access public + * @return array|string + */ + public function updateKanbanCellTest(int $taskID, int $executionID, array $output): array|string + { + $_SERVER['HTTP_HOST'] = ''; + + $this->objectModel->updateKanbanCell($taskID, $output, $executionID); + + global $tester; + $cells = $tester->dao->select("CONCAT(id, ':', cards) as cards")->from(TABLE_KANBANCELL)->where('kanban')->eq($executionID)->fetchPairs(); + + if(dao::isError()) return dao::getError(); + + return implode('|', $cells); + } } diff --git a/module/task/ui/pause.html.php b/module/task/ui/pause.html.php new file mode 100644 index 0000000000..9d0815f744 --- /dev/null +++ b/module/task/ui/pause.html.php @@ -0,0 +1,32 @@ + + * @package task + * @link https://www.zentao.net + */ + +namespace zin; + +/* ====== Define the page structure with zin widgets ====== */ + +formPanel +( + set::id('taskPauseForm'), + set::title($lang->task->pause), + formGroup + ( + set::label($lang->comment), + set::name('comment'), + set::control('editor'), + ), +); + + +/* ====== Render page ====== */ + +render(); diff --git a/module/task/zen.php b/module/task/zen.php index d0bd768831..b8bdeb923f 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -1331,4 +1331,20 @@ class taskZen extends task $kanbanType = $executionLaneType == 'all' ? 'task' : key($kanbanData); return json_encode($kanbanData[$kanbanType]); } + + /** + * 处理开始任务后的返回信息。 + * The information return after process the start task. + * + * @param object $task + * @param string $from ''|taskkanban + * @access protected + * @return array + */ + protected function responseAfterChangeStatus(object $task, string $from): array + { + if($this->viewType == 'json' || (defined('RUN_MODE') && RUN_MODE == 'api')) return array('result' => 'success'); + if(isonlybody()) return $this->taskZen->responseKanban($task, $from); + return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('task', 'view', "taskID={$task->id}")); + } }