diff --git a/module/task/config/form.php b/module/task/config/form.php new file mode 100644 index 0000000000..1338a5fa42 --- /dev/null +++ b/module/task/config/form.php @@ -0,0 +1,11 @@ +task->form = new stdclass(); + +global $app; +$config->task->form->assign = array(); +$config->task->form->assign['assignedTo'] = array('type' => 'string', 'required' => false, 'default' => ''); +$config->task->form->assign['left'] = array('type' => 'float', 'required' => true); +$config->task->form->assign['lastEditedBy'] = array('type' => 'string', 'required' => false, 'default' => $app->user->account); +$config->task->form->assign['lastEditedDate'] = array('type' => 'date', 'required' => false, 'default' => helper::now()); +$config->task->form->assign['assignedDate'] = array('type' => 'date', 'required' => false, 'default' => helper::now()); +$config->task->form->assign['comment'] = array('type' => 'text', 'required' => false, 'default' => ''); diff --git a/module/task/control.php b/module/task/control.php index e53bf8d65e..14bef201c0 100755 --- a/module/task/control.php +++ b/module/task/control.php @@ -808,68 +808,22 @@ class task extends control if(!empty($_POST)) { - $this->loadModel('action'); - $changes = $this->task->assign($taskID); + $data = form::data($this->config->task->form->assign)->get(); + $postComment = $data->comment; + unset($data->comment); - if(dao::isError()) - { - if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - return print(js::error(dao::getError())); - } + $changes = $this->task->assign($data, $taskID); + if(dao::isError()) return $this->taskZen->errorAfterAssignTo(); - $actionID = $this->action->create('task', $taskID, 'Assigned', $this->post->comment, $this->post->assignedTo); + $actionID = $this->loadModel('action')->create('task', $taskID, 'Assigned', $postComment, $this->post->assignedTo); $this->action->logHistory($actionID, $changes); $this->executeHooks($taskID); - if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success')); - if(isonlybody()) - { - $task = $this->task->getById($taskID); - $execution = $this->execution->getByID($task->execution); - $execLaneType = $this->session->execLaneType ? $this->session->execLaneType : 'all'; - $execGroupBy = $this->session->execGroupBy ? $this->session->execGroupBy : 'default'; - if(($this->app->tab == 'execution' or ($this->config->vision == 'lite' and $this->app->tab == 'project' and $this->session->kanbanview == 'kanban')) and $execution->type == 'kanban') - { - $rdSearchValue = $this->session->rdSearchValue ? $this->session->rdSearchValue : ''; - $kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $execLaneType, 'id_desc', 0, $execGroupBy, $rdSearchValue); - $kanbanData = json_encode($kanbanData); - - return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)")); - } - if($from == 'taskkanban') - { - $taskSearchValue = $this->session->taskSearchValue ? $this->session->taskSearchValue : ''; - $kanbanData = $this->loadModel('kanban')->getExecutionKanban($task->execution, $execLaneType, $execGroupBy, $taskSearchValue); - $kanbanType = $execLaneType == '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')); + return $this->taskZen->reponseAfterAssignTo($changes); } - $members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted'); - - /* Compute next assignedTo. */ - if(!empty($task->team) and strpos('done,cencel,closed', $task->status) === false) - { - $task->nextUser = $this->task->getAssignedTo4Multi($task->team, $task, 'next'); - $members = $this->task->getMemberPairs($task); - } - - if(!isset($members[$task->assignedTo])) $members[$task->assignedTo] = $task->assignedTo; - if(isset($members['closed']) or $task->status == 'closed') $members['closed'] = 'Closed'; - - $this->view->title = $this->view->execution->name . $this->lang->colon . $this->lang->task->assign; - $this->view->position[] = $this->lang->task->assign; - $this->view->task = $task; - $this->view->members = $members; - $this->view->users = $this->loadModel('user')->getPairs(); - $this->display(); + $this->taskZen->buildAssignToForm($executionID, $task); } /** diff --git a/module/task/model.php b/module/task/model.php index f76324a189..e80f3800d8 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -1595,24 +1595,16 @@ class taskModel extends model /** * Assign a task to a user again. * + * @param object $task * @param int $taskID * @access public - * @return void + * @return array */ - public function assign($taskID) + public function assign($task, $taskID): array|false { + $task->id = $taskID; $oldTask = $this->getById($taskID); - $now = helper::now(); - $task = fixer::input('post') - ->add('id', $taskID) - ->cleanFloat('left') - ->setDefault('lastEditedBy', $this->app->user->account) - ->setDefault('lastEditedDate', $now) - ->setDefault('assignedDate', $now) - ->stripTags($this->config->task->editor->assignto['id'], $this->config->allowedTags) - ->remove('comment,showModule') - ->get(); if($oldTask->status != 'done' and $oldTask->status != 'closed' and isset($task->left) and $task->left == 0) { dao::$errors[] = sprintf($this->lang->error->notempty, $this->lang->task->left); diff --git a/module/task/test/model/assign.php b/module/task/test/model/assign.php index 1baa2507eb..0881dd1338 100755 --- a/module/task/test/model/assign.php +++ b/module/task/test/model/assign.php @@ -7,31 +7,84 @@ su('admin'); /** title=taskModel->assign(); +timeout=0 cid=1 -pid=1 -wait状态任务指派 >> assignedTo,po82,user92 -doing状态任务指派 >> assignedTo,,user93 -done状态任务指派 >> assignedTo,,user94 -pause状态任务指派 >> assignedTo,,user95 -cancel状态任务指派 >> assignedTo,,user96 -closed状态任务指派 >> assignedTo,,user97 +- 执行task模块的assign方法,参数是$taskIDlist[0],$waitTask + - 第0条的field属性 @assignedTo + - 第0条的old属性 @old1 + - 第0条的new属性 @user92 + +- 执行task模块的assign方法,参数是$taskIDlist[0],$waitTaskLeft + - 第1条的field属性 @left + - 第1条的old属性 @0 + - 第1条的new属性 @1 + +- 执行task模块的assign方法,参数是$taskIDlist[1],$doingTask + - 第0条的field属性 @assignedTo + - 第0条的old属性 @old2 + - 第0条的new属性 @user93 + +- 执行task模块的assign方法,参数是$taskIDlist[2],$doneTask + - 第0条的field属性 @assignedTo + - 第0条的old属性 @old3 + - 第0条的new属性 @user94 + +- 执行task模块的assign方法,参数是$taskIDlist[3],$pauseTask + - 第0条的field属性 @assignedTo + - 第0条的old属性 @old4 + - 第0条的new属性 @user95 + +- 执行task模块的assign方法,参数是$taskIDlist[4],$cancelTask + - 第0条的field属性 @assignedTo + - 第0条的old属性 @old5 + - 第0条的new属性 @user96 + +- 执行task模块的assign方法,参数是$taskIDlist[5],$closedTask + - 第0条的field属性 @assignedTo + - 第0条的old属性 @old6 + - 第0条的new属性 @user97 + + */ +function initData() +{ + $task = zdTable('task'); + $task->id->range('1-6'); + $task->execution->range('2,3,3,4'); + $task->name->prefix("任务")->range('1-6'); + $task->left->range('0'); + $task->assignedTo->prefix("old")->range('1-6'); + $task->status->range("wait,doing,done,pause,cancel,closed"); + + $task->gen(6); + + $user = zdTable('user'); + $user->id->range('1-100'); + $user->account->range('1-100')->prefix('user'); + $user->password->range('f8e41d6c31824c01e5d67c61a8ae49e9,e10adc3949ba59abbe56e057f20f883e'); + $user->realname->range('1-100')->prefix("开发"); + $user->gen(50); +} + +initData(); $taskIDlist = array('1','2','3','4','5','6'); -$waitTask = array('assignedTo' => 'user92','status' => 'wait', 'left' => '1'); -$doingTask = array('assignedTo' => 'user93','status' => 'doing'); -$doneTask = array('assignedTo' => 'user94','status' => 'done'); -$pauseTask = array('assignedTo' => 'user95','status' => 'pause'); -$cancelTask = array('assignedTo' => 'user96','status' => 'cancel'); -$closedTask = array('assignedTo' => 'user97','status' => 'closed'); +$waitTask = array('assignedTo' => 'user92','status' => 'wait'); +$waitTaskLeft = array('assignedTo' => 'user91','status' => 'wait', 'left' => '1'); +$doingTask = array('assignedTo' => 'user93','status' => 'doing'); +$doneTask = array('assignedTo' => 'user94','status' => 'done'); +$pauseTask = array('assignedTo' => 'user95','status' => 'pause'); +$cancelTask = array('assignedTo' => 'user96','status' => 'cancel'); +$closedTask = array('assignedTo' => 'user97','status' => 'closed'); $task = new taskTest(); -r($task->assignTest($taskIDlist[0],$waitTask)) && p('0:field,old,new') && e('assignedTo,po82,user92'); // wait状态任务指派 -r($task->assignTest($taskIDlist[1],$doingTask)) && p('0:field,old,new') && e('assignedTo,,user93'); // doing状态任务指派 -r($task->assignTest($taskIDlist[2],$doneTask)) && p('0:field,old,new') && e('assignedTo,,user94'); // done状态任务指派 -r($task->assignTest($taskIDlist[3],$pauseTask)) && p('0:field,old,new') && e('assignedTo,,user95'); // pause状态任务指派 -r($task->assignTest($taskIDlist[4],$cancelTask)) && p('0:field,old,new') && e('assignedTo,,user96'); // cancel状态任务指派 -r($task->assignTest($taskIDlist[5],$closedTask)) && p('0:field,old,new') && e('assignedTo,,user97'); // closed状态任务指派 +r($task->assignTest($taskIDlist[0],$waitTask)) && p('0:field,old,new') && e('assignedTo,old1,user92'); // wait状态任务指派 +r($task->assignTest($taskIDlist[0],$waitTaskLeft)) && p('1:field,old,new') && e('left,0,1'); // wait状态任务指派修改预计剩余 +r($task->assignTest($taskIDlist[1],$doingTask)) && p('0:field,old,new') && e('assignedTo,old2,user93'); // doing状态任务指派 +r($task->assignTest($taskIDlist[2],$doneTask)) && p('0:field,old,new') && e('assignedTo,old3,user94'); // done状态任务指派 +r($task->assignTest($taskIDlist[3],$pauseTask)) && p('0:field,old,new') && e('assignedTo,old4,user95'); // pause状态任务指派 +r($task->assignTest($taskIDlist[4],$cancelTask)) && p('0:field,old,new') && e('assignedTo,old5,user96'); // cancel状态任务指派 +r($task->assignTest($taskIDlist[5],$closedTask)) && p('0:field,old,new') && e('assignedTo,old6,user97'); // closed状态任务指派 \ No newline at end of file diff --git a/module/task/test/task.class.php b/module/task/test/task.class.php index d9b4d9f86d..3c8311cf5e 100644 --- a/module/task/test/task.class.php +++ b/module/task/test/task.class.php @@ -290,7 +290,10 @@ class taskTest $createFields = array('assignedTo' => '', 'status' => '', 'comment' => ''); foreach($createFields as $field => $defaultValue) $_POST[$field] = $defaultValue; foreach($param as $key => $value) $_POST[$key] = $value; - $object = $this->objectModel->assign($taskID); + + $task = $_POST; + unset($task['comment']); + $object = $this->objectModel->assign((object)$task, $taskID); unset($_POST); if(dao::isError()) { diff --git a/module/task/ui/assignto.html.php b/module/task/ui/assignto.html.php index f5f2b71cf7..51b1e7d8da 100644 --- a/module/task/ui/assignto.html.php +++ b/module/task/ui/assignto.html.php @@ -1,52 +1,73 @@ $value) -{ - $items[] = ['text' => $value, 'value' => $key]; -} +/* zin: Set variables to define picker options for form */ +$formTitle = $task->name; +$assignedToOptions = $members; -set::itemID($task->id); -set::title($task->name); -form +/* ====== Define the page structure with zin widgets ====== */ + +/* zin: Define the form in main content */ +formPanel ( + set::title($formTitle), // The form title is diffrent from the page title, formGroup ( - set::label($lang->assignedToAB), - set::name('assignedTo'), - set::control(['type' => 'select', 'items' => $items]), + set::width("1/3"), + set::name("assignedTo"), + set::label("指派"), + set::value((empty($task->team) or strpos('done,cencel,closed', $task->status) !== false) ? $task->assignedTo : $task->nextUser), + set::control("picker"), + set::items($assignedToOptions) ), formGroup ( - set::label($lang->task->left), - div + set::width("1/3"), + set::label("预计剩余"), + inputGroup ( - setClass('input-control has-suffix'), - input + control(set(array ( - set::type('number'), - set::min(0), - set::name('left'), - set::id('left'), - ), - h::label - ( - setClass('input-control-suffix'), - $lang->workingHour - ) + 'name' => "left", + 'id' => "left", + 'value' => $task->left, + 'disabled' => false, + 'type' => "text" + ))), + "小时" ) ), formGroup ( - set::label($lang->comment), - set::name('comment'), - set::control(['type' => 'textarea']), - ), - set::actions(['save']) + set::width("2/3"), + set::name("comment"), + set::label("备注"), + set::control("editor") + ) ); -render('modalDialog'); + +/* ====== Render page ====== */ + +render(); diff --git a/module/task/zen.php b/module/task/zen.php new file mode 100644 index 0000000000..e0f5ad84c5 --- /dev/null +++ b/module/task/zen.php @@ -0,0 +1,95 @@ + + * @package task + * @link https://www.zentao.net + */ +class taskZen extends task +{ + /** + * Reponse after assignto. + * + * @param int $taskID + * @access protected + * @return void + */ + protected function reponseAfterAssignTo(int $taskID): int + { + if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success')); + if(isonlybody()) + { + $task = $this->task->getById($taskID); + $execution = $this->execution->getByID($task->execution); + $execLaneType = $this->session->execLaneType ? $this->session->execLaneType : 'all'; + $execGroupBy = $this->session->execGroupBy ? $this->session->execGroupBy : 'default'; + if(($this->app->tab == 'execution' or ($this->config->vision == 'lite' and $this->app->tab == 'project' and $this->session->kanbanview == 'kanban')) and $execution->type == 'kanban') + { + $rdSearchValue = $this->session->rdSearchValue ? $this->session->rdSearchValue : ''; + $kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $execLaneType, 'id_desc', 0, $execGroupBy, $rdSearchValue); + $kanbanData = json_encode($kanbanData); + + return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)")); + } + if($from == 'taskkanban') + { + $taskSearchValue = $this->session->taskSearchValue ? $this->session->taskSearchValue : ''; + $kanbanData = $this->loadModel('kanban')->getExecutionKanban($task->execution, $execLaneType, $execGroupBy, $taskSearchValue); + $kanbanType = $execLaneType == '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')); + } + + /** + * Return the error after assignto. + * + * @access protected + * @return void + */ + protected function errorAfterAssignTo(): int + { + if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + return print(js::error(dao::getError())); + } + + /** + * Build AssignTo Form. + * + * @param int $executionID + * @param object $task + * @access protected + * @return void + */ + protected function buildAssignToForm(int $executionID, object $task): void + { + $this->loadModel('action'); + $members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted'); + + /* Compute next assignedTo. */ + if(!empty($task->team) and strpos('done,cencel,closed', $task->status) === false) + { + $task->nextUser = $this->task->getAssignedTo4Multi($task->team, $task, 'next'); + $members = $this->task->getMemberPairs($task); + } + + if(!isset($members[$task->assignedTo])) $members[$task->assignedTo] = $task->assignedTo; + if(isset($members['closed']) or $task->status == 'closed') $members['closed'] = 'Closed'; + + $this->view->title = $this->view->execution->name . $this->lang->colon . $this->lang->task->assign; + $this->view->position[] = $this->lang->task->assign; + $this->view->task = $task; + $this->view->members = $members; + $this->view->users = $this->loadModel('user')->getPairs(); + $this->display(); + } +}