diff --git a/api/v1/entries/builds.php b/api/v1/entries/builds.php index 3709a0463c..e303c9a4e1 100644 --- a/api/v1/entries/builds.php +++ b/api/v1/entries/builds.php @@ -21,6 +21,7 @@ class buildsEntry extends entry public function get($projectID = 0) { if(empty($projectID)) $projectID = $this->param('project', 0); + if(empty($projectID)) return $this->sendError(400, "Need project id."); $control = $this->loadController('project', 'build'); $control->build($projectID, $this->param('type', 'all'), $this->param('param', 0), $this->param('order', 't1.date_desc,t1.id_desc')); diff --git a/api/v1/entries/execution.php b/api/v1/entries/execution.php index 306d6f374b..c5cffb4fc0 100644 --- a/api/v1/entries/execution.php +++ b/api/v1/entries/execution.php @@ -64,6 +64,14 @@ class executionEntry extends Entry { switch($field) { + case 'modules': + $control = $this->loadController('tree', 'browsetask'); + $control->browsetask($executionID); + $data = $this->getData(); + if(isset($data->status) and $data->status == 'success') + { + $execution->modules = $data->data->tree; + } case 'builds': $execution->builds = $this->loadModel('build')->getBuildPairs($productID, 'all', 'noempty,noterminate,nodone', $executionID, 'execution'); break; diff --git a/api/v1/entries/executionmembers.php b/api/v1/entries/executionmembers.php deleted file mode 100644 index 6b7a680b93..0000000000 --- a/api/v1/entries/executionmembers.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @package entries - * @version 1 - * @link http://www.zentao.net - */ -class executionMembersEntry extends entry -{ - public function get($executionID = 0) - { - if(!$executionID) $executionID = $this->param('execution', 0); - if(empty($executionID)) return $this->sendError(400, 'Need execution id.'); - $members = $this->loadModel('execution')->getTeamMembers($executionID); - if(isset($members)) - { - foreach($members as $member) $result[] = $this->format($member, 'join:date'); - } - return $this->send(200, array('members' => $result)); - } -} diff --git a/api/v1/entries/executionstories.php b/api/v1/entries/executionstories.php index d2f74e1126..4f32cb527c 100644 --- a/api/v1/entries/executionstories.php +++ b/api/v1/entries/executionstories.php @@ -34,7 +34,6 @@ class executionStoriesEntry extends entry $result = array(); foreach($stories as $story) { - $story->name =$story->title; $result[] = $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList'); } return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'stories' => $result)); diff --git a/api/v1/entries/modulestories.php b/api/v1/entries/modulestories.php index 03a29b2f2f..16ac618148 100644 --- a/api/v1/entries/modulestories.php +++ b/api/v1/entries/modulestories.php @@ -15,16 +15,15 @@ class moduleStoriesEntry extends Entry { $executionID = $this->param('executionID', 0); if(empty($executionID)) return $this->sendError(400, 'Need execution id.'); - $control = $this->loadController('story', 'ajaxGetExecutionStories'); - $control->ajaxGetExecutionStories($executionID, $this->param('productID', 0), $this->param('branchID', 0), $moduleID); + + $control = $this->loadController('execution', 'story'); + $control->story($executionID, 'order_desc', 'byModule', $moduleID); $data = $this->getData(); - $this->loadModel('story'); + $result = []; - foreach($data as $storyID => $storyName) + foreach($data->data->stories as $story) { - if(empty($storyID)) continue; - $story = $this->story->getById($storyID); $result[] = $this->filterFields($story, 'id,title,module,pri,status,stage,estimate'); } return $this->send(200, array('stories' => $result)); diff --git a/api/v1/entries/productplans.php b/api/v1/entries/productplans.php index e903903f4c..f56cf3ae96 100644 --- a/api/v1/entries/productplans.php +++ b/api/v1/entries/productplans.php @@ -36,7 +36,6 @@ class productplansEntry extends entry foreach($plans as $plan) { - $plan->name = $plan->title; if($plan->parent > 0 and isset($result[$plan->parent])) { $parentPlan = $result[$plan->parent]; diff --git a/api/v1/entries/stories.php b/api/v1/entries/stories.php index d92f3ddd6e..90223294ed 100644 --- a/api/v1/entries/stories.php +++ b/api/v1/entries/stories.php @@ -35,7 +35,6 @@ class storiesEntry extends entry $result = array(); foreach($stories as $story) { - $story->name =$story->title; if(isset($story->children)) $story->children = array_values((array)$story->children); $result[] = $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList'); } @@ -55,7 +54,7 @@ class storiesEntry extends entry if(!$productID and isset($this->requestBody->product)) $productID = $this->requestBody->product; if(!$productID) return $this->sendError(400, 'Need product id.'); - $fields = 'title,spec,verify,reviewer,type,plan,module,moduleOptionMenu,source,sourceNote,category,pri,estimate,mailto,keywords'; + $fields = 'title,spec,verify,reviewer,type,plan,module,moduleOptionMenu,source,sourceNote,category,pri,estimate,mailto,keywords,notifyemail,uid'; $this->batchSetPost($fields); /* If reviewer is not post, set needNotReview. */ diff --git a/api/v1/entries/story.php b/api/v1/entries/story.php index 77889a3dbc..10580c0f8a 100644 --- a/api/v1/entries/story.php +++ b/api/v1/entries/story.php @@ -95,7 +95,7 @@ class storyEntry extends Entry $oldStory = $this->loadModel('story')->getByID($storyID); /* Set $_POST variables. */ - $fields = 'title,product,reviewer,type,plan,module,source,sourceNote,category,pri,estimate,mailto,keywords'; + $fields = 'title,product,reviewer,type,plan,module,source,sourceNote,category,pri,estimate,mailto,keywords,uid'; $this->batchSetPost($fields, $oldStory); $this->setPost('parent', 0); diff --git a/api/v1/entries/storyrecall.php b/api/v1/entries/storyrecall.php new file mode 100644 index 0000000000..99e06cc210 --- /dev/null +++ b/api/v1/entries/storyrecall.php @@ -0,0 +1,30 @@ + + * @package entries + * @version 1 + * @link http://www.zentao.net + */ +class storyRecallEntry extends Entry +{ + /** + * Delete method. + * + * @param int $storyID + * @access public + * @return void + */ + public function delete($storyID) + { + $control = $this->loadController('story', 'recall'); + $control->recall($storyID); + + $this->getData(); + $this->sendSuccess(200, 'success'); + } +} + diff --git a/api/v1/entries/storyreview.php b/api/v1/entries/storyreview.php new file mode 100644 index 0000000000..0148229dc4 --- /dev/null +++ b/api/v1/entries/storyreview.php @@ -0,0 +1,42 @@ + + * @package entries + * @version 1 + * @link http://www.zentao.net + **/ + +class storyReviewEntry extends Entry +{ + /** + * POST method. + * + * @param int $storyID + * @access public + * @return void + */ + public function post($storyID) + { + $oldStory = $this->loadModel('story')->getByID($storyID); + + $fields = 'reviewedDate,result,closedReason,pri,estimate,'; + $this->batchSetPost($fields); + + $control = $this->loadController('story', 'review'); + + $control->review($storyID); + + $data = $this->getData(); + if(!$data or !isset($data->status)) return $this->send400('error'); + if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message); + + $story = $this->loadModel('story')->getByID($storyID); + + $this->send(200, $story); + } +} + diff --git a/api/v1/entries/tabs.php b/api/v1/entries/tabs.php index 71c245e10a..162293dcb3 100644 --- a/api/v1/entries/tabs.php +++ b/api/v1/entries/tabs.php @@ -50,7 +50,10 @@ class tabsEntry extends baseEntry if($menuKey == 'requirement' and empty($this->config->URAndSR)) continue; if(isset($this->lang->product->menu->$menuKey)) { - list($label, $module, $method) = explode('|', $this->lang->product->menu->$menuKey['link']); + $menuName = $this->lang->product->menu->$menuKey; + if(!isset($menuName['link'])) continue; + + list($label, $module, $method) = explode('|', $menuName['link']); if(!common::hasPriv($module, $method)) continue; } else diff --git a/api/v1/entries/task.php b/api/v1/entries/task.php index b06bd8f677..15cd194d6e 100644 --- a/api/v1/entries/task.php +++ b/api/v1/entries/task.php @@ -102,7 +102,7 @@ class taskEntry extends Entry $oldTask = $this->loadModel('task')->getByID($taskID); /* Set $_POST variables. */ - $fields = 'name,type,desc,assignedTo,pri,estimate,left,consumed,story,parent,execution,module,closedReason,status,estStarted,deadline,team,teamEstimate,multiple,mailto'; + $fields = 'name,type,desc,assignedTo,pri,estimate,left,consumed,story,parent,execution,module,closedReason,status,estStarted,deadline,team,teamEstimate,multiple,mailto,uid'; $this->batchSetPost($fields, $oldTask); $control = $this->loadController('task', 'edit'); diff --git a/api/v1/entries/taskbatchcreate.php b/api/v1/entries/taskbatchcreate.php index deda4e24ef..22731a0cc1 100644 --- a/api/v1/entries/taskbatchcreate.php +++ b/api/v1/entries/taskbatchcreate.php @@ -56,7 +56,7 @@ class taskBatchCreateEntry extends Entry $estStarted[] = isset($task->estStarted) ? $task->estStarted : 0; $deadlines[] = isset($task->deadline) ? $task->deadline : null; $desc[] = isset($task->desc) ? $task->desc : ''; - $pri[] = isset($task->pri) ? $task->pri : ''; + $pri[] = isset($task->pri) ? $task->pri : 0; $stories[] = isset($task->story) ? $task->story : $storyID; } $this->setPost('module', $modules); @@ -78,11 +78,9 @@ class taskBatchCreateEntry extends Entry if(!$data) return $this->send400('error'); if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message); - $this->send(200, array()); + if(!$taskID) return $this->send(200, array()); + $task = $this->loadModel('task')->getById($taskID); + return $this->send(200, array('task' => $task)); } - public function setArrayPost($field) - { - $_POST[$field] = array('0' => $_POST[$field]); - } } diff --git a/api/v1/entries/taskcomponent.php b/api/v1/entries/taskcomponent.php new file mode 100644 index 0000000000..50b83afef8 --- /dev/null +++ b/api/v1/entries/taskcomponent.php @@ -0,0 +1,45 @@ + + * @package entries + * @version 1 + * @link http://www.zentao.net + */ +class taskComponentEntry extends Entry +{ + /** + * POST method. + * + * @param int $taskID + * @access public + * @return void + */ + public function post($taskID) + { + $fields = 'name,color,type,assignedTo,parent,estimate,story,module,pri,desc,estStarted,deadline'; + $this->batchSetPost($fields); + + $fields = explode(',', $fields); + foreach($fields as $field) $this->setArrayPost($field); + $task = $this->loadModel('task')->getById($taskID); + + $control = $this->loadController('task', 'batchCreate'); + $control->batchCreate($task->execution, 0, 0, $taskID); + + $data = $this->getData(); + if(!$data) return $this->send400('error'); + if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message); + + $task = $this->task->getById($data->idList[0]); + $this->send(200, $this->format($task, 'deadline:date,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,realStarted:time,finishedBy:user,finishedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,lastEditedBy:user,lastEditedDate:time,deleted:bool,mailto:userList')); + } + + public function setArrayPost($field) + { + $_POST[$field] = array('0' => $_POST[$field]); + } +} diff --git a/api/v1/entries/taskrecordestimate.php b/api/v1/entries/taskrecordestimate.php index 178452030c..f3e1f9c518 100644 --- a/api/v1/entries/taskrecordestimate.php +++ b/api/v1/entries/taskrecordestimate.php @@ -11,6 +11,37 @@ */ class taskRecordEstimateEntry extends Entry { + /** + * GET method. + * + * @param int $taskID + * @access public + * @return void + */ + public function get($taskID) + { + if($this->config->edition != 'open') + { + $control = $this->loadController('effort', 'createForObject'); + $control->createForObject('task', $taskID); + } + else + { + $control = $this->loadController('task', 'recordEstimate'); + $control->recordEstimate($taskID); + } + + $data = $this->getData(); + if(!$data) return $this->error('error'); + if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message); + + $effort = array(); + if($this->config->edition != 'open' and $data->data->efforts) $effort = $data->data->efforts; + if($this->config->edition == 'open' and $data->data->esitimates) $effort = $data->data->esitimates; + $this->send(200, array('effort' => $effort)); + + } + /** * POST method. * diff --git a/api/v1/entries/testcases.php b/api/v1/entries/testcases.php index fef888623b..7b680a8a8d 100644 --- a/api/v1/entries/testcases.php +++ b/api/v1/entries/testcases.php @@ -80,9 +80,11 @@ class testcasesEntry extends entry $stepType = array(); foreach($this->requestBody->steps as $step) { + $type = isset($step->type) ? $step->type : 'step'; + $steps[] = $step->desc; - $expects[] = $step->expect; - $stepType[] = 'item'; + $expects[] = $type == 'group' ? '' : $step->expect; + $stepType[] = $type; } $this->setPost('steps', $steps); $this->setPost('expects', $expects); diff --git a/config/routes.php b/config/routes.php index a484abdcda..fcfe3dd41e 100644 --- a/config/routes.php +++ b/config/routes.php @@ -50,6 +50,8 @@ $routes['/stories/:id/active'] = 'storyActive'; $routes['/stories/:id/assign'] = 'storyAssignto'; $routes['/stories/:id/recordEstimate'] = 'storyRecordEstimate'; $routes['/stories/:id/child'] = 'storyChild'; +$routes['/stories/:id/recall'] = 'storyRecall'; +$routes['/stories/:id/review'] = 'storyReview'; $routes['/module/:id/stories'] = 'moduleStories'; @@ -80,6 +82,7 @@ $routes['/tasks/:id/pause'] = 'taskPause'; $routes['/tasks/:id/finish'] = 'taskFinish'; $routes['/tasks/:id/close'] = 'taskClose'; $routes['/tasks/:id/recordEstimate'] = 'taskRecordEstimate'; +$routes['/tasks/:id/getEstimate'] = 'taskRecordEstimate'; $routes['/users'] = 'users'; $routes['/users/:id'] = 'user'; diff --git a/db/update16.4.sql b/db/update16.4.sql index 82969492c5..32f3287cb8 100644 --- a/db/update16.4.sql +++ b/db/update16.4.sql @@ -23,6 +23,7 @@ ALTER TABLE `zt_story` ADD `activatedDate` datetime NOT NULL AFTER `closedReason ALTER TABLE `zt_task` MODIFY `activatedDate` datetime NOT NULL AFTER `lastEditedDate`; ALTER TABLE `zt_kanbancard` ADD `progress` float unsigned NOT NULL DEFAULT '0' AFTER `estimate`; +UPDATE `zt_kanbancard` SET `progress`='100' WHERE `status` = 'done' and `fromtype` = ''; ALTER TABLE `zt_user` ADD `visions` varchar(20) NOT NULL DEFAULT 'rnd,lite' AFTER `visits`; UPDATE `zt_user` SET `visions`='rnd,lite'; diff --git a/extension/lite/execution/ext/view/kanban.lite.html.hook.php b/extension/lite/execution/ext/view/kanban.lite.html.hook.php index 8d5ff1682c..0f3b49248b 100644 --- a/extension/lite/execution/ext/view/kanban.lite.html.hook.php +++ b/extension/lite/execution/ext/view/kanban.lite.html.hook.php @@ -7,4 +7,8 @@ diff --git a/extension/lite/project/ext/config/lite.php b/extension/lite/project/ext/config/lite.php index c2c824cc1b..f68ccc4780 100644 --- a/extension/lite/project/ext/config/lite.php +++ b/extension/lite/project/ext/config/lite.php @@ -1,2 +1,4 @@ project->datatable->fieldList['actions']['width'] = '120'; + +$config->project->list->exportFields = 'id,code,name,status,budget,PM,desc'; diff --git a/extension/lite/task/ext/view/create.html.php b/extension/lite/task/ext/view/create.html.php index 57fc60a6f7..11d1d0dcfc 100644 --- a/extension/lite/task/ext/view/create.html.php +++ b/extension/lite/task/ext/view/create.html.php @@ -337,8 +337,8 @@ id);?> ';?>