diff --git a/.gitignore b/.gitignore index 5529453cfe..1a682f8be0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,7 @@ tmp/cache/* tmp/extension/* .gitkeep .bak +.idea +.gitignore +_log +framework/ \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/framework/helper.class.php b/framework/helper.class.php index 165ba1bab1..dc33d2ffa0 100644 --- a/framework/helper.class.php +++ b/framework/helper.class.php @@ -141,3 +141,11 @@ function formatTime($time, $format = '') if($format) return date($format, strtotime($time)); return trim($time); } + +function b($val) +{ + echo '
';
+    print_r($val);
+    echo '
'; + exit; +} \ No newline at end of file diff --git a/module/project/css/task.css b/module/project/css/task.css index 12b48fcf8a..050b253d51 100644 --- a/module/project/css/task.css +++ b/module/project/css/task.css @@ -24,3 +24,4 @@ .pl-5px{padding-left:5px;} tbody > tr > td > .btn-icon {margin-right: 2px} +.table-children td{background-color:#fff0f5!important;} \ No newline at end of file diff --git a/module/project/view/datatabledata.html.php b/module/project/view/datatabledata.html.php index ad92507c5d..31ac138adf 100644 --- a/module/project/view/datatabledata.html.php +++ b/module/project/view/datatabledata.html.php @@ -35,5 +35,10 @@ extract($widths); $value) $this->task->printCell($value, $task, $users, $browseType, $branchGroups, $modulePairs);?> + children) foreach($task->children as $child):?> + + $value) $this->task->printCell($value, $child, $users, $browseType, $branchGroups, $modulePairs);?> + + diff --git a/module/project/view/taskdata.html.php b/module/project/view/taskdata.html.php index 152b51c3b2..1401800464 100644 --- a/module/project/view/taskdata.html.php +++ b/module/project/view/taskdata.html.php @@ -44,7 +44,7 @@ - actions;?> + actions;?> @@ -122,9 +122,90 @@ common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list', '', '', 'iframe', true); common::printIcon('task', 'close', "taskID=$task->id", $task, 'list', '', '', 'iframe', true); common::printIcon('task', 'edit', "taskID=$task->id", $task, 'list'); + common::printIcon('task', 'batchCreate', "project=$projectID&storyID=&moduleID=$moduleID&taskID=$task->id", $task, 'list','plus','','','','',$lang->task->children); ?> + children):?> + children as $child):?> + assignedTo == $app->user->account ? 'style=color:red' : ''; ?> + + + + id", sprintf('%03d', $child->id))) printf('%03d', $child->id);?> + + task->priList, $child->pri, $child->pri)?>'>pri == '0' ? '' : zget($lang->task->priList, $child->pri, $child->pri);?> + + product][$child->branch])) echo "" . $branchGroups[$child->product][$child->branch] . '';?> + module) echo "" . $modulePairs[$child->module] . '';?> + id", $child->name, null, "style='color: $child->color'")) echo $child->name; + if($child->fromBug) echo html::a($this->createLink('bug', 'view', "id=$child->fromBug"), "[BUG#$child->fromBug]", '_blank', "class='bug'"); + ?> + + + storyStatus == 'active' and $child->latestStoryVersion > $child->storyVersion); + if($storyChanged) + { + echo "({$lang->story->changed} "; + echo html::a($this->createLink('task', 'confirmStoryChange', "taskID=$child->id"), $lang->confirm, 'hiddenwin'); + echo ")"; + } + else + { + echo $lang->task->statusList[$child->status]; + } + ?> + + deadline, 0, 4) > 0) echo substr($child->deadline, 5, 6);?> + + cookie->windowWidth > $this->config->wideSize):?> + openedDate, 5, 6);?> + + + >assignedTo == 'closed' ? 'Closed' : zget($users, $child->assignedTo, $child->assignedTo);?> + finishedBy, $child->finishedBy);?> + + cookie->windowWidth > $this->config->wideSize):?> + finishedDate, 5, 6);?> + + + estimate;?> + consumed;?> + left;?> + progess?>% + type == 'sprint') + { + echo ''; + if($child->storyID) + { + if(!common::printLink('story', 'view', "storyid=$child->storyID", $child->storyTitle)) print $child->storyTitle; + } + echo ''; + } + ?> + + project&taskID=$child->id", $child, 'list', '', '', 'iframe', true); + common::printIcon('task', 'start', "taskID=$child->id", $child, 'list', '', '', 'iframe', true); + + common::printIcon('task', 'recordEstimate', "taskID=$child->id", $child, 'list', 'time', '', 'iframe', true); + if($browseType == 'needconfirm') + { + $lang->task->confirmStoryChange = $lang->confirm; + common::printIcon('task', 'confirmStoryChange', "taskid=$child->id", '', 'list', '', 'hiddenwin'); + } + common::printIcon('task', 'finish', "taskID=$child->id", $child, 'list', '', '', 'iframe', true); + common::printIcon('task', 'close', "taskID=$child->id", $child, 'list', '', '', 'iframe', true); + common::printIcon('task', 'edit', "taskID=$child->id", $child, 'list'); + common::printIcon('task', 'batchCreate', "", $child, 'list','plus','','','','',$lang->task->children); + ?> + + + + diff --git a/module/task/config.php b/module/task/config.php index b5bbbc3481..ca4fc78573 100644 --- a/module/task/config.php +++ b/module/task/config.php @@ -183,5 +183,5 @@ $config->task->datatable->fieldList['story']['required'] = 'no'; $config->task->datatable->fieldList['actions']['title'] = 'actions'; $config->task->datatable->fieldList['actions']['fixed'] = 'right'; -$config->task->datatable->fieldList['actions']['width'] = '140'; +$config->task->datatable->fieldList['actions']['width'] = '180'; $config->task->datatable->fieldList['actions']['required'] = 'yes'; diff --git a/module/task/control.php b/module/task/control.php index 4beb48389d..002e5c1db6 100644 --- a/module/task/control.php +++ b/module/task/control.php @@ -169,12 +169,15 @@ class task extends control /** * Batch create task. * - * @param int $projectID - * @param int $storyID + * @param int $projectID + * @param int $storyID + * @param int $iframe + * @param int $taskID + * * @access public - * @return void + * @return mixed */ - public function batchCreate($projectID = 0, $storyID = 0, $iframe = 0) + public function batchCreate($projectID = 0, $storyID = 0, $iframe = 0, $taskID = 0) { $project = $this->project->getById($projectID); $taskLink = $this->createLink('project', 'browse', "projectID=$projectID&tab=task"); @@ -213,6 +216,7 @@ class task extends control $this->view->project = $project; $this->view->stories = $stories; $this->view->modules = $modules; + $this->view->parent = $taskID; $this->view->storyID = $storyID; $this->view->story = $this->story->getByID($storyID); $this->view->storyTasks = $this->task->getStoryTaskCounts(array_keys($stories), $projectID); @@ -426,10 +430,20 @@ class task extends control die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); } + $task = $this->task->getByID($taskID); + + $members = $this->project->getTeamMemberPairs($projectID, 'nodeleted'); + /* Compute next assignedTo. */ + if(!empty($task->team)) + { + $task->assignedTo = $this->task->getNextUser(array_keys($task->team), $task->assignedTo); + $members = $this->task->getMemberPairs($task); + } + $this->view->title = $this->view->project->name . $this->lang->colon . $this->lang->task->assign; $this->view->position[] = $this->lang->task->assign; - - $this->view->users = $this->project->getTeamMemberPairs($projectID, 'nodeleted'); + $this->view->task = $task; + $this->view->users = $members; $this->display(); } @@ -518,6 +532,8 @@ class task extends control $task->storyFiles = $this->loadModel('file')->getByObject('story', $task->story); } + if($task->team) $this->lang->task->assign = $this->lang->task->transmit; + /* Update action. */ if($task->assignedTo == $this->app->user->account) $this->loadModel('action')->read('task', $taskID); diff --git a/module/task/js/common.js b/module/task/js/common.js index f6b1f07a1c..140db4051e 100644 --- a/module/task/js/common.js +++ b/module/task/js/common.js @@ -14,3 +14,46 @@ function checkLeft() } } } + +$('.btn-move-up, .btn-move-down').click(function() +{ + var $this = $(this); + if($this.hasClass('btn-move-up')) + { + $(this).parents('tr').prev().before($(this).parents('tr')); + } + else + { + $this.parents('tr').next().after($(this).parents('tr')); + } + $('.btn-move-up, .btn-move-down').removeClass('disabled').removeAttr('disabled'); + + adjustSortBtn(); +}); +function adjustSortBtn() +{ + $('.btn-move-up:first').addClass('disabled').attr('disabled', 'disabled'); + $('.btn-move-down:last').addClass('disabled').attr('disabled', 'disabled'); +} + +$('#modalTeam .btn').click(function() +{ + var team = ''; + var time = 0; + $('[name*=team]').each(function() + { + if($(this).find('option:selected').text() != '') + { + team += ' ' + $(this).find('option:selected').text(); + } + + estimate = parseFloat($(this).parents('td').next('td').find('[name*=teamEstimate]').val()); + if(!isNaN(estimate)) + { + time += estimate; + } + + $('#teamMember').val(team); + $('#estimate').val(time); + }) +}) diff --git a/module/task/js/create.js b/module/task/js/create.js index e50bb46e83..bdb27f8b2f 100644 --- a/module/task/js/create.js +++ b/module/task/js/create.js @@ -202,3 +202,26 @@ $(document).ready(function() return false; }); }); + +/* show team menu. */ +$('[name^=multiple]').change(function() +{ + if($(this).prop('checked')) + { + $('#assignedTo, #assignedTo_chosen').addClass('hidden'); + $('.team-group').removeClass('hidden'); + $('#estimate').attr('readonly', true); + } + else + { + $('#assignedTo, #assignedTo_chosen').removeClass('hidden'); + $('.team-group').addClass('hidden'); + $('#estimate').attr('readonly', false); + } +}); + +$(".btn[data-toggle='modalTeam']").click(function() +{ + $('#modalTeam').modal('show'); + adjustSortBtn(); +}); \ No newline at end of file diff --git a/module/task/js/edit.js b/module/task/js/edit.js index 6ed08f4209..401c03d80e 100644 --- a/module/task/js/edit.js +++ b/module/task/js/edit.js @@ -67,3 +67,25 @@ function loadProjectMembers(projectID) /* empty function. */ function setPreview(){} +$(".btn[data-toggle='modalTeam']").click(function() +{ + $('#modalTeam').modal('show') + adjustSortBtn(); +}); + +$(document).ready(function() +{ + /* show team menu. */ + $('[name=multiple]').change(function() + { + var checked = $(this).prop('checked'); + if(checked) + { + $('#teamTr').removeClass('hidden'); + } + else + { + $('#teamTr').addClass('hidden'); + } + }); +}); \ No newline at end of file diff --git a/module/task/lang/en.php b/module/task/lang/en.php index 94cbe81964..c863c97ed8 100644 --- a/module/task/lang/en.php +++ b/module/task/lang/en.php @@ -95,6 +95,15 @@ $lang->task->deleteEstimate = 'Delete Man-Hour'; $lang->task->colorTag = 'Color Tag'; $lang->task->files = 'Files'; $lang->task->hasConsumed = 'Consumed'; +$lang->task->multiple = 'Multiple Tasks'; +$lang->task->multipleAB = 'Multiple'; +$lang->task->team = 'Team'; +$lang->task->transmit = 'Transfer'; +$lang->task->transmitTo = 'Transfer To'; +$lang->task->children = 'Child'; +$lang->task->childrenAB = 'Child'; +$lang->task->parent = 'Parent Task'; +$lang->task->unfinished = 'Unfinished'; $lang->task->ditto = 'Ditto'; $lang->task->dittoNotice = "This Task does not belong to the Project as the previous one does!"; diff --git a/module/task/lang/zh-cn.php b/module/task/lang/zh-cn.php index 60e5fd64a1..54e7d352d0 100644 --- a/module/task/lang/zh-cn.php +++ b/module/task/lang/zh-cn.php @@ -39,62 +39,71 @@ $lang->task->progess = '进度'; $lang->task->progessTips = '已消耗/(已消耗+剩余)'; $lang->task->copy = '复制任务'; -$lang->task->common = '任务'; -$lang->task->id = '编号'; -$lang->task->project = '所属' . $lang->projectCommon; -$lang->task->module = '所属模块'; -$lang->task->moduleAB = '模块'; -$lang->task->story = '相关需求'; -$lang->task->storySpec = '需求描述'; -$lang->task->storyVerify = '验收标准'; -$lang->task->name = '任务名称'; -$lang->task->type = '任务类型'; -$lang->task->pri = '优先级'; -$lang->task->mailto = '抄送给'; -$lang->task->estimate = '最初预计'; -$lang->task->estimateAB = '预'; -$lang->task->left = '预计剩余'; -$lang->task->leftAB = '剩'; -$lang->task->consumed = '总消耗'; -$lang->task->consumedAB = '消耗'; -$lang->task->hour = '小时'; -$lang->task->consumedThisTime = '工时'; -$lang->task->leftThisTime = '剩余'; -$lang->task->datePlan = '日程规划'; -$lang->task->estStarted = '预计开始'; -$lang->task->realStarted = '实际开始'; -$lang->task->date = '日期'; -$lang->task->deadline = '截止日期'; -$lang->task->deadlineAB = '截止'; -$lang->task->status = '任务状态'; -$lang->task->desc = '任务描述'; -$lang->task->assign = '指派'; -$lang->task->assignTo = $lang->task->assign; -$lang->task->batchAssignTo = '批量指派'; -$lang->task->assignedTo = '指派给'; -$lang->task->assignedToAB = '指派给'; -$lang->task->assignedDate = '指派日期'; -$lang->task->openedBy = '由谁创建'; -$lang->task->openedDate = '创建日期'; -$lang->task->openedDateAB = '创建'; -$lang->task->finishedBy = '由谁完成'; -$lang->task->finishedByAB = '完成者'; -$lang->task->finishedDate = '完成时间'; -$lang->task->finishedDateAB = '完成'; -$lang->task->canceledBy = '由谁取消'; -$lang->task->canceledDate = '取消时间'; -$lang->task->closedBy = '由谁关闭'; -$lang->task->closedDate = '关闭时间'; -$lang->task->closedReason = '关闭原因'; -$lang->task->lastEditedBy = '最后修改'; -$lang->task->lastEditedDate = '最后修改日期'; -$lang->task->lastEdited = '最后编辑'; -$lang->task->recordEstimate = '工时'; -$lang->task->editEstimate = '编辑工时'; -$lang->task->deleteEstimate = '删除工时'; -$lang->task->colorTag = '颜色标签'; -$lang->task->files = '附件'; -$lang->task->hasConsumed = '已消耗'; +$lang->task->common = '任务'; +$lang->task->id = '编号'; +$lang->task->project = '所属' . $lang->projectCommon; +$lang->task->module = '所属模块'; +$lang->task->moduleAB = '模块'; +$lang->task->story = '相关需求'; +$lang->task->storySpec = '需求描述'; +$lang->task->storyVerify = '验收标准'; +$lang->task->name = '任务名称'; +$lang->task->type = '任务类型'; +$lang->task->pri = '优先级'; +$lang->task->mailto = '抄送给'; +$lang->task->estimate = '最初预计'; +$lang->task->estimateAB = '预'; +$lang->task->left = '预计剩余'; +$lang->task->leftAB = '剩'; +$lang->task->consumed = '总消耗'; +$lang->task->consumedAB = '消耗'; +$lang->task->hour = '小时'; +$lang->task->consumedThisTime = '工时'; +$lang->task->leftThisTime = '剩余'; +$lang->task->datePlan = '日程规划'; +$lang->task->estStarted = '预计开始'; +$lang->task->realStarted = '实际开始'; +$lang->task->date = '日期'; +$lang->task->deadline = '截止日期'; +$lang->task->deadlineAB = '截止'; +$lang->task->status = '任务状态'; +$lang->task->desc = '任务描述'; +$lang->task->assign = '指派'; +$lang->task->assignTo = $lang->task->assign; +$lang->task->batchAssignTo = '批量指派'; +$lang->task->assignedTo = '指派给'; +$lang->task->assignedToAB = '指派给'; +$lang->task->assignedDate = '指派日期'; +$lang->task->openedBy = '由谁创建'; +$lang->task->openedDate = '创建日期'; +$lang->task->openedDateAB = '创建'; +$lang->task->finishedBy = '由谁完成'; +$lang->task->finishedByAB = '完成者'; +$lang->task->finishedDate = '完成时间'; +$lang->task->finishedDateAB = '完成'; +$lang->task->canceledBy = '由谁取消'; +$lang->task->canceledDate = '取消时间'; +$lang->task->closedBy = '由谁关闭'; +$lang->task->closedDate = '关闭时间'; +$lang->task->closedReason = '关闭原因'; +$lang->task->lastEditedBy = '最后修改'; +$lang->task->lastEditedDate = '最后修改日期'; +$lang->task->lastEdited = '最后编辑'; +$lang->task->recordEstimate = '工时'; +$lang->task->editEstimate = '编辑工时'; +$lang->task->deleteEstimate = '删除工时'; +$lang->task->colorTag = '颜色标签'; +$lang->task->files = '附件'; +$lang->task->hasConsumed = '已消耗'; +$lang->task->multiple = '多人任务'; +$lang->task->multipleAB = '多人'; +$lang->task->team = '团队'; +$lang->task->transmit = '转交'; +$lang->task->transmitTo = '转交给'; +$lang->task->children = '子任务'; +$lang->task->childrenAB = '子'; +$lang->task->parent = '父任务'; +$lang->task->unfinished = '未完成'; $lang->task->ditto = '同上'; $lang->task->dittoNotice = "该任务与上一任务不属于同一项目!"; @@ -104,13 +113,13 @@ $lang->task->noAssigned = '未指派'; $lang->task->noFinished = '未完成'; $lang->task->noClosed = '未关闭'; -$lang->task->statusList[''] = ''; -$lang->task->statusList['wait'] = '未开始'; -$lang->task->statusList['doing'] = '进行中'; -$lang->task->statusList['done'] = '已完成'; -$lang->task->statusList['pause'] = '已暂停'; -$lang->task->statusList['cancel'] = '已取消'; -$lang->task->statusList['closed'] = '已关闭'; +$lang->task->statusList[''] = ''; +$lang->task->statusList['wait'] = '未开始'; +$lang->task->statusList['doing'] = '进行中'; +$lang->task->statusList['done'] = '已完成'; +$lang->task->statusList['pause'] = '已暂停'; +$lang->task->statusList['cancel'] = '已取消'; +$lang->task->statusList['closed'] = '已关闭'; $lang->task->typeList[''] = ''; $lang->task->typeList['design'] = '设计'; @@ -122,11 +131,11 @@ $lang->task->typeList['ui'] = '界面'; $lang->task->typeList['affair'] = '事务'; $lang->task->typeList['misc'] = '其他'; -$lang->task->priList[0] = ''; -$lang->task->priList[3] = '3'; -$lang->task->priList[1] = '1'; -$lang->task->priList[2] = '2'; -$lang->task->priList[4] = '4'; +$lang->task->priList[0] = ''; +$lang->task->priList[3] = '3'; +$lang->task->priList[1] = '1'; +$lang->task->priList[2] = '2'; +$lang->task->priList[4] = '4'; $lang->task->reasonList[''] = ''; $lang->task->reasonList['done'] = '已完成'; @@ -155,7 +164,7 @@ $lang->task->noticeLinkStory = "没有可关联的相关需求,您可以 $lang->task->noticeSaveRecord = '您有尚未保存的工时记录,请先将其保存。'; $lang->task->commentActions = '%s. %s, 由 %s 添加备注。'; -$lang->task->error = new stdclass(); +$lang->task->error = new stdclass(); $lang->task->error->consumedNumber = '"已经消耗"必须为数字'; $lang->task->error->estimateNumber = '"预计剩余"必须为数字'; $lang->task->error->consumedSmall = '"已经消耗"必须大于之前消耗'; @@ -166,7 +175,7 @@ $lang->task->error->skipClose = '任务:%s 不是“已完成”或“ $lang->task->error->consumed = '任务:%s工时不能小于0,忽略该任务工时的改动'; /* 统计报表。*/ -$lang->task->report = new stdclass(); +$lang->task->report = new stdclass(); $lang->task->report->common = '报表'; $lang->task->report->select = '请选择报表类型'; $lang->task->report->create = '生成报表'; @@ -186,8 +195,8 @@ $lang->task->report->charts['tasksPerFinishedBy'] = '由谁完成统计'; $lang->task->report->charts['tasksPerClosedReason'] = '关闭原因统计'; $lang->task->report->charts['finishedTasksPerDay'] = '每天完成统计'; -$lang->task->report->options = new stdclass(); -$lang->task->report->options->graph = new stdclass(); +$lang->task->report->options = new stdclass(); +$lang->task->report->options->graph = new stdclass(); $lang->task->report->options->type = 'pie'; $lang->task->report->options->width = 500; $lang->task->report->options->height = 140; @@ -247,5 +256,5 @@ $lang->task->report->tasksPerConsumed->graph->xAxisName = '时间'; $lang->task->report->tasksPerFinishedBy->graph->xAxisName = '用户'; $lang->task->report->tasksPerClosedReason->graph->xAxisName = '关闭原因'; -$lang->task->report->finishedTasksPerDay->type = 'bar'; -$lang->task->report->finishedTasksPerDay->graph->xAxisName = '日期'; +$lang->task->report->finishedTasksPerDay->type = 'bar'; +$lang->task->report->finishedTasksPerDay->graph->xAxisName = '日期'; diff --git a/module/task/lang/zh-tw.php b/module/task/lang/zh-tw.php index 3533c2bc56..d75d0e2d61 100644 --- a/module/task/lang/zh-tw.php +++ b/module/task/lang/zh-tw.php @@ -95,6 +95,15 @@ $lang->task->deleteEstimate = '刪除工時'; $lang->task->colorTag = '顏色標籤'; $lang->task->files = '附件'; $lang->task->hasConsumed = '已消耗'; +$lang->task->multiple = '多人任務'; +$lang->task->multipleAB = '多人'; +$lang->task->team = '團隊'; +$lang->task->transmit = '轉交'; +$lang->task->transmitTo = '轉交給'; +$lang->task->children = '子任務'; +$lang->task->childrenAB = '子'; +$lang->task->parent = '父任務'; +$lang->task->unfinished = '未完成'; $lang->task->ditto = '同上'; $lang->task->dittoNotice = "該任務與上一任務不屬於同一項目!"; diff --git a/module/task/model.php b/module/task/model.php index b74b5e646c..fc0599a781 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -15,8 +15,8 @@ class taskModel extends model { /** * Create a task. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -37,9 +37,11 @@ class taskModel extends model ->setDefault('openedDate', helper::now()) ->stripTags($this->config->task->editor->create['id'], $this->config->allowedTags) ->join('mailto', ',') - ->remove('after,files,labels,assignedTo,uid,storyEstimate,storyDesc,storyPri') + ->remove('after,files,labels,assignedTo,uid,storyEstimate,storyDesc,storyPri,team,teamEstimate,teamMember,multiple,teams') ->get(); + + foreach($this->post->assignedTo as $assignedTo) { /* When type is affair and has assigned then ignore none. */ @@ -48,6 +50,37 @@ class taskModel extends model $task->assignedTo = $assignedTo; if($assignedTo) $task->assignedDate = helper::now(); + $teams = array(); + if($this->post->multiple) + { + $estimate = 0; + $left = 0; + foreach($this->post->team as $row => $account) + { + if(empty($account) or isset($team[$account])) continue; + $member = new stdClass(); + $member->project = 0; + $member->account = $account; + $member->role = $assignedTo; + $member->join = helper::today(); + $member->estimate = $this->post->teamEstimate[$row] ? $this->post->teamEstimate[$row] : 0; + $member->left = $member->estimate; + $member->order = $row; + + $teams[$account] = $member; + $estimate += (float)$member->eatimate; + $left += (float)$member->left; + } + + if(!empty($teams)) + { + $firstMember = reset($teams); + $task->assignedTo = $firstMember->account; + $task->estimate = $estimate; + $task->left = $left; + } + } + /* Check duplicate task. */ if($task->type != 'affair') { @@ -67,31 +100,33 @@ class taskModel extends model ->checkIF($task->deadline != '0000-00-00', 'deadline', 'ge', $task->estStarted) ->exec(); - if(!dao::isError()) + if(dao::isError()) return false; + + $taskID = $this->dao->lastInsertID(); + if($this->post->story) $this->loadModel('story')->setStage($this->post->story); + $this->file->updateObjectID($this->post->uid, $taskID, 'task'); + if(!empty($taskFiles)) { - $taskID = $this->dao->lastInsertID(); - if($this->post->story) $this->loadModel('story')->setStage($this->post->story); - $this->file->updateObjectID($this->post->uid, $taskID, 'task'); - if(!empty($taskFiles)) + foreach($taskFiles as $taskFile) { - foreach($taskFiles as $taskFile) - { - $taskFile->objectID = $taskID; - $this->dao->insert(TABLE_FILE)->data($taskFile)->exec(); - } + $taskFile->objectID = $taskID; + $this->dao->insert(TABLE_FILE)->data($taskFile)->exec(); } - else - { - $taskFileTitle = $this->file->saveUpload('task', $taskID); - $taskFiles = $this->dao->select('*')->from(TABLE_FILE)->where('id')->in(array_keys($taskFileTitle))->fetchAll('id'); - foreach($taskFiles as $fileID => $taskFile) unset($taskFiles[$fileID]->id); - } - $tasksID[$assignedTo] = array('status' => 'created', 'id' => $taskID); } else { - return false; + $taskFileTitle = $this->file->saveUpload('task', $taskID); + $taskFiles = $this->dao->select('*')->from(TABLE_FILE)->where('id')->in(array_keys($taskFileTitle))->fetchAll('id'); + foreach($taskFiles as $fileID => $taskFile) unset($taskFiles[$fileID]->id); } + + if(!empty($teams)) foreach($teams as $team) + { + $team->task = $taskID; + $this->dao->insert(TABLE_TEAM)->data($team)->autoCheck()->exec(); + } + + $tasksID[$assignedTo] = array('status' => 'created', 'id' => $taskID); } return $tasksID; } @@ -111,7 +146,7 @@ class taskModel extends model $tasks = fixer::input('post')->get(); $batchNum = count(reset($tasks)); - $storyIDs = array(); + $storyIDs = array(); $taskNames = array(); foreach($tasks->story as $key => $storyID) { @@ -120,7 +155,7 @@ class taskModel extends model $inNames = in_array($tasks->name[$key], $taskNames); if(!$inNames || $inNames && !in_array($storyID, $storyIDs)) { - $storyIDs[] = $storyID; + $storyIDs[] = $storyID; $taskNames[] = $tasks->name[$key]; } else @@ -141,7 +176,7 @@ class taskModel extends model { die(js::alert($this->lang->task->error->estimateNumber)); } - if(!empty($tasks->name[$i]) and empty($tasks->type[$i]))die(js::alert(sprintf($this->lang->error->notempty, $this->lang->task->type))); + if(!empty($tasks->name[$i]) and empty($tasks->type[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->task->type))); } $story = 0; @@ -165,23 +200,24 @@ class taskModel extends model { if(empty($tasks->name[$i])) continue; - $data[$i] = new stdclass(); - $data[$i]->story = $tasks->story[$i]; - $data[$i]->type = $tasks->type[$i]; - $data[$i]->module = $tasks->module[$i]; - $data[$i]->assignedTo = $tasks->assignedTo[$i]; - $data[$i]->color = $tasks->color[$i]; - $data[$i]->name = $tasks->name[$i]; - $data[$i]->desc = nl2br($tasks->desc[$i]); - $data[$i]->pri = $tasks->pri[$i]; - $data[$i]->estimate = $tasks->estimate[$i]; - $data[$i]->left = $tasks->estimate[$i]; - $data[$i]->project = $projectID; - $data[$i]->estStarted = empty($tasks->estStarted[$i]) ? '0000-00-00' : $tasks->estStarted[$i]; - $data[$i]->deadline = empty($tasks->deadline[$i]) ? '0000-00-00' : $tasks->deadline[$i]; - $data[$i]->status = 'wait'; - $data[$i]->openedBy = $this->app->user->account; - $data[$i]->openedDate = $now; + $data[$i] = new stdclass(); + $data[$i]->story = $tasks->story[$i]; + $data[$i]->type = $tasks->type[$i]; + $data[$i]->module = $tasks->module[$i]; + $data[$i]->assignedTo = $tasks->assignedTo[$i]; + $data[$i]->color = $tasks->color[$i]; + $data[$i]->name = $tasks->name[$i]; + $data[$i]->desc = nl2br($tasks->desc[$i]); + $data[$i]->pri = $tasks->pri[$i]; + $data[$i]->estimate = $tasks->estimate[$i]; + $data[$i]->left = $tasks->estimate[$i]; + $data[$i]->project = $projectID; + $data[$i]->estStarted = empty($tasks->estStarted[$i]) ? '0000-00-00' : $tasks->estStarted[$i]; + $data[$i]->deadline = empty($tasks->deadline[$i]) ? '0000-00-00' : $tasks->deadline[$i]; + $data[$i]->status = 'wait'; + $data[$i]->openedBy = $this->app->user->account; + $data[$i]->openedDate = $now; + $data[$i]->parent = $tasks->parent[$i]; if($tasks->story[$i] != '') $data[$i]->storyVersion = $this->loadModel('story')->getVersion($data[$i]->story); if($tasks->assignedTo[$i] != '') $data[$i]->assignedDate = $now; @@ -202,13 +238,49 @@ class taskModel extends model $mails[$i]->actionID = $actionID; } + $this->countTime($tasks->parent[0]); + return $mails; } + /** + * count parent task estimate and left value + * + * @param $taskID + * + * @access public + * @return void + */ + public function countTime($taskID) + { + if(!$taskID) return true; + + $tasks = $this->dao->select('`id`,`estimate`,`consumed`,`left`')->from(TABLE_TASK)->where('parent')->eq($taskID)->fetchAll('id'); + + if(empty($tasks)) return true; + + $estimate = 0; + $consumed = 0; + $left = 0; + foreach($tasks as $task) + { + $estimate += $task->estimate; + $consumed += $task->consumed; + $left += $task->left; + } + + $newTask = new stdClass(); + $newTask->estimate = $estimate; + $newTask->consumed = $consumed; + $newTask->left = $left; + + $this->dao->update(TABLE_TASK)->data($newTask)->autoCheck()->where('id')->eq($taskID)->exec(); + } + /** * Update a task. - * - * @param int $taskID + * + * @param int $taskID * @access public * @return void */ @@ -248,10 +320,46 @@ class taskModel extends model ->add('lastEditedDate', $now) ->stripTags($this->config->task->editor->edit['id'], $this->config->allowedTags) ->join('mailto', ',') - ->remove('comment,files,labels,uid') + ->remove('comment,files,labels,uid,multiple,team,teamEstimate,teamConsumed,teamLeft') ->get(); - if($task->consumed < $oldTask->consumed) + $teams = array(); + if($this->post->multiple) + { + $estimate = 0; + $left = 0; + foreach($this->post->team as $row => $account) + { + if(empty($account) or isset($team[$account])) continue; + $member = new stdClass(); + $member->project = 0; + $member->account = $account; + $member->role = $task->assignedTo; + $member->join = helper::today(); + $member->task = $taskID; + $member->estimate = $this->post->teamEstimate[$row] ? $this->post->teamEstimate[$row] : 0; + $member->consumed = $this->post->teamConsumed[$row] ? $this->post->teamConsumed[$row] : 0; + $member->left = $member->estimate - $member->consumed; + $member->order = $row; + + $teams[$account] = $member; + $estimate += (float)$member->eatimate; + $left += (float)$member->left; + } + + if(!empty($teams)) + { + $task->estimate = $estimate; + $task->left = $left; + if(!isset($task->assignedTo)) + { + $firstMember = reset($teams); + $task->assignedTo = $firstMember->account; + } + } + } + + if($task->consumed < $oldTask->consumed) { die(js::error($this->lang->task->error->consumedSmall)); } @@ -287,6 +395,12 @@ class taskModel extends model ->batchCheckIF($task->closedReason == 'cancel', 'finishedBy, finishedDate', 'empty') ->where('id')->eq((int)$taskID)->exec(); + $this->countTime($oldTask->parent); + + /* Save team. */ + $this->dao->delete()->from(TABLE_TEAM)->where('task')->eq($taskID)->exec(); + if(!empty($teams)) foreach($teams as $member) $this->dao->insert(TABLE_TEAM)->data($member)->autoCheck()->exec(); + if($this->post->story != false) $this->loadModel('story')->setStage($this->post->story); if(!dao::isError()) { @@ -297,7 +411,7 @@ class taskModel extends model /** * Batch update task. - * + * * @access public * @return void */ @@ -432,7 +546,7 @@ class taskModel extends model break; case 'pause': { - $task->finishedDate = ''; + $task->finishedDate = ''; } default:break; @@ -462,7 +576,7 @@ class taskModel extends model if($task->status == 'done' and $task->closedReason) $this->dao->update(TABLE_TASK)->set('status')->eq('closed')->where('id')->eq($taskID)->exec(); if($oldTask->story != false) $this->loadModel('story')->setStage($oldTask->story); - if(!dao::isError()) + if(!dao::isError()) { $allChanges[$taskID] = common::createChanges($oldTask, $task); } @@ -506,8 +620,8 @@ class taskModel extends model /** * Assign a task to a user again. - * - * @param int $taskID + * + * @param int $taskID * @access public * @return void */ @@ -527,15 +641,15 @@ class taskModel extends model ->data($task) ->autoCheck() ->check('left', 'float') - ->where('id')->eq($taskID)->exec(); + ->where('id')->eq($taskID)->exec(); if(!dao::isError()) return common::createChanges($oldTask, $task); } /** * Start a task. - * - * @param int $taskID + * + * @param int $taskID * @access public * @return void */ @@ -547,12 +661,12 @@ class taskModel extends model $task = fixer::input('post') ->setDefault('assignedTo', $this->app->user->account) ->setDefault('lastEditedBy', $this->app->user->account) - ->setDefault('lastEditedDate', $now) + ->setDefault('lastEditedDate', $now) ->setIF($oldTask->assignedTo != $this->app->user->account, 'assignedDate', $now) ->remove('comment')->get(); if($this->post->left == 0) { - $task->status = 'done'; + $task->status = 'done'; $task->finishedBy = $this->app->user->account; $task->finishedDate = helper::now(); } @@ -563,11 +677,11 @@ class taskModel extends model /* Record consumed and left. */ $estimate = fixer::input('post') - ->setDefault('account', $this->app->user->account) - ->setDefault('task', $taskID) - ->setDefault('date', $task->realStarted) + ->setDefault('account', $this->app->user->account) + ->setDefault('task', $taskID) + ->setDefault('date', $task->realStarted) ->remove('realStarted,comment')->get(); - $estimate->consumed = $estimate->consumed - $oldTask->consumed; + $estimate->consumed = $estimate->consumed - $oldTask->consumed; $this->addTaskEstimate($estimate); $this->dao->update(TABLE_TASK)->data($task) @@ -580,9 +694,9 @@ class taskModel extends model } /** - * Record estimate and left of task. - * - * @param int $taskID + * Record estimate and left of task. + * + * @param int $taskID * @access public * @return void */ @@ -649,7 +763,7 @@ class taskModel extends model $data->lastEditedDate = $now; if($left == 0) { - $task->status = 'done'; + $task->status = 'done'; $data->status = $task->status; $data->assignedTo = $task->openedBy; $data->assignedDate = $now; @@ -658,7 +772,7 @@ class taskModel extends model } else if($task->status == 'wait') { - $task->status = 'doing'; + $task->status = 'doing'; $data->status = $task->status; $data->assignedTo = $this->app->user->account; $data->assignedDate = $now; @@ -666,7 +780,7 @@ class taskModel extends model } else if($task->status == 'pause') { - $task->status = 'doing'; + $task->status = 'doing'; $data->status = $task->status; $data->assignedTo = $this->app->user->account; $data->assignedDate = $now; @@ -687,13 +801,15 @@ class taskModel extends model if(!empty($actionID)) $this->action->logHistory($actionID, $changes); if($task->story) $this->loadModel('story')->setStage($task->story); + $this->countTime($task->parent); + return $changes; } /** * Finish a task. - * - * @param int $taskID + * + * @param int $taskID * @access public * @return void */ @@ -707,7 +823,7 @@ class taskModel extends model ->setDefault('assignedDate', $now) ->setDefault('status', 'done') ->setDefault('finishedBy, lastEditedBy', $this->app->user->account) - ->setDefault('finishedDate, lastEditedDate', $now) + ->setDefault('finishedDate, lastEditedDate', $now) ->remove('comment,files,labels') ->get(); if($task->finishedDate == substr($now, 0, 10)) $task->finishedDate = $now; @@ -718,13 +834,13 @@ class taskModel extends model $consumed = $task->consumed - $oldTask->consumed; if($consumed < 0) die(js::error($this->lang->task->error->consumedSmall)); $estimate = fixer::input('post') - ->setDefault('account', $this->app->user->account) - ->setDefault('task', $taskID) - ->setDefault('date', date(DT_DATE1)) + ->setDefault('account', $this->app->user->account) + ->setDefault('task', $taskID) + ->setDefault('date', date(DT_DATE1)) ->setDefault('left', 0) ->remove('finishedDate,comment,assignedTo,files,labels,consumed') ->get(); - $estimate->consumed = $consumed; + $estimate->consumed = $consumed; if($estimate->consumed) $this->addTaskEstimate($estimate); $this->dao->update(TABLE_TASK)->data($task) @@ -737,9 +853,9 @@ class taskModel extends model } /** - * Pause task - * - * @param int $taskID + * Pause task + * + * @param int $taskID * @access public * @return array */ @@ -750,18 +866,18 @@ class taskModel extends model $task = fixer::input('post') ->setDefault('status', 'pause') ->setDefault('lastEditedBy', $this->app->user->account) - ->setDefault('lastEditedDate', $now) + ->setDefault('lastEditedDate', $now) ->remove('comment')->get(); $this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('id')->eq((int)$taskID)->exec(); if(!dao::isError()) return common::createChanges($oldTask, $task); } - + /** * Close a task. - * - * @param int $taskID + * + * @param int $taskID * @access public * @return void */ @@ -774,9 +890,9 @@ class taskModel extends model ->setDefault('assignedTo', 'closed') ->setDefault('assignedDate', $now) ->setDefault('closedBy, lastEditedBy', $this->app->user->account) - ->setDefault('closedDate, lastEditedDate', $now) - ->setIF($oldTask->status == 'done', 'closedReason', 'done') - ->setIF($oldTask->status == 'cancel', 'closedReason', 'cancel') + ->setDefault('closedDate, lastEditedDate', $now) + ->setIF($oldTask->status == 'done', 'closedReason', 'done') + ->setIF($oldTask->status == 'cancel', 'closedReason', 'cancel') ->remove('_recPerPage') ->remove('comment')->get(); @@ -788,8 +904,8 @@ class taskModel extends model /** * Cancel a task. - * - * @param int $taskID + * + * @param int $taskID * @access public * @return void */ @@ -804,7 +920,7 @@ class taskModel extends model ->setDefault('finishedBy', '') ->setDefault('finishedDate', '0000-00-00') ->setDefault('canceledBy, lastEditedBy', $this->app->user->account) - ->setDefault('canceledDate, lastEditedDate', $now) + ->setDefault('canceledDate, lastEditedDate', $now) ->remove('comment')->get(); $this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('id')->eq((int)$taskID)->exec(); @@ -815,8 +931,8 @@ class taskModel extends model /** * Activate a task. - * - * @param int $taskID + * + * @param int $taskID * @access public * @return void */ @@ -844,8 +960,8 @@ class taskModel extends model /** * Get task info by Id. - * - * @param int $taskID + * + * @param int $taskID * @param bool $setImgSize * @access public * @return object|bool @@ -862,6 +978,14 @@ class taskModel extends model ->fetch(); if(!$task) return false; + $children = $this->dao->select('*')->from(TABLE_TASK)->where('parent')->eq($taskID)->andWhere('deleted')->eq(0)->fetchAll('id'); + $task->children = $children; + + $teams = $this->dao->select('*')->from(TABLE_TEAM)->where('task')->eq($taskID)->orderBy('order_desc')->fetchGroup('task', 'account'); + foreach($teams as $key => $team) $teams[$key] = array_reverse($team); + $task->team = isset($teams[$taskID]) ? $teams[$taskID] : array(); + foreach($children as $child) $child->team = isset($teams[$child->id]) ? $teams[$child->id] : array(); + $task = $this->loadModel('file')->replaceImgURL($task, 'desc'); if($setImgSize) $task->desc = $this->file->setImgSize($task->desc); if($task->assignedTo == 'closed') $task->assignedToRealName = 'Closed'; @@ -876,8 +1000,8 @@ class taskModel extends model /** * Get task list. - * - * @param int|array|string $taskIDList + * + * @param int|array|string $taskIDList * @access public * @return array */ @@ -922,13 +1046,15 @@ class taskModel extends model /** * Get tasks of a project. * - * @param int $projectID - * @param string $status all|needConfirm|wait|doing|done|cancel - * @param string $type - * @param array|string $modules - * @param object $pager + * @param $projectID + * @param int $productID + * @param string $type + * @param int $modules + * @param string $orderBy + * @param null $pager + * * @access public - * @return array + * @return array|void */ public function getProjectTasks($projectID, $productID = 0, $type = 'all', $modules = 0, $orderBy = 'status_asc, id_desc', $pager = null) { @@ -939,6 +1065,7 @@ class taskModel extends model ->leftJoin(TABLE_USER)->alias('t3')->on('t1.assignedTo = t3.account') ->where('t1.project')->eq((int)$projectID) ->andWhere('t1.deleted')->eq(0) + ->andWhere('t1.parent')->eq(0) ->beginIF($productID)->andWhere('t2.product')->eq((int)$productID)->fi() ->beginIF($type == 'undone')->andWhere("(t1.status = 'wait' or t1.status ='doing')")->fi() ->beginIF($type == 'needconfirm')->andWhere('t2.version > t1.storyVersion')->andWhere("t2.status = 'active'")->fi() @@ -949,10 +1076,16 @@ class taskModel extends model ->beginIF($modules)->andWhere('t1.module')->in($modules)->fi() ->orderBy($orderBy) ->page($pager) - ->fetchAll(); + ->fetchAll('id'); $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'task', ($productID or $type == 'needconfirm') ? false : true); + $taskList = array_keys($tasks); + $children = $this->dao->select('*')->from(TABLE_TASK)->where('parent')->in($taskList)->orderBy('id_desc')->fetchGroup('parent'); + if($children) foreach($children as $key => $child) $tasks[$key]->children = $child; + $teams = $this->dao->select('*')->from(TABLE_TEAM)->where('task')->in($taskList)->fetchGroup('task'); + if($teams) foreach($teams as $key => $team) if(!empty($team)) $tasks[$key]->team = $team; + if($tasks) return $this->processTasks($tasks); return array(); } @@ -960,9 +1093,9 @@ class taskModel extends model /** * Get project tasks pairs. * - * @param int $projectID + * @param int $projectID * @param string $status - * @param string $orderBy + * @param string $orderBy * @access public * @return array */ @@ -983,11 +1116,11 @@ class taskModel extends model /** * Get tasks of a user. - * - * @param string $account - * @param string $type the query type - * @param int $limit - * @param object $pager + * + * @param string $account + * @param string $type the query type + * @param int $limit + * @param object $pager * @access public * @return array */ @@ -1013,9 +1146,9 @@ class taskModel extends model /** * Get tasks pairs of a user. - * - * @param string $account - * @param string $status + * + * @param string $account + * @param string $status * @access public * @return array */ @@ -1038,9 +1171,9 @@ class taskModel extends model /** * Get task pairs of a story. - * - * @param int $storyID - * @param int $projectID + * + * @param int $storyID + * @param int $projectID * @access public * @return array */ @@ -1075,9 +1208,9 @@ class taskModel extends model /** * Get counts of some stories' tasks. - * - * @param array $stories - * @param int $projectID + * + * @param array $stories + * @param int $projectID * @access public * @return int */ @@ -1095,30 +1228,30 @@ class taskModel extends model } /** - * Get task estimate. - * - * @param int $taskID + * Get task estimate. + * + * @param int $taskID * @access public - * @return object + * @return object */ public function getTaskEstimate($taskID) { - return $this->dao->select('*')->from(TABLE_TASKESTIMATE) + return $this->dao->select('*')->from(TABLE_TASKESTIMATE) ->where('task')->eq($taskID) ->orderBy('date,id') ->fetchAll(); } /** - * Get estimate by id. - * - * @param int $estimateID + * Get estimate by id. + * + * @param int $estimateID * @access public - * @return object. + * @return object. */ public function getEstimateById($estimateID) { - $estimate = $this->dao->select('*')->from(TABLE_TASKESTIMATE) + $estimate = $this->dao->select('*')->from(TABLE_TASKESTIMATE) ->where('id')->eq($estimateID) ->fetch(); @@ -1127,14 +1260,14 @@ class taskModel extends model ->where('task')->eq($estimate->task) ->andWhere('id')->gt($estimate->id) ->fetch('id'); - $estimate->isLast = $lastID ? false :true; + $estimate->isLast = $lastID ? false :true; return $estimate; } /** - * Update estimate. - * - * @param int $estimateID + * Update estimate. + * + * @param int $estimateID * @access public * @return void */ @@ -1152,7 +1285,7 @@ class taskModel extends model $consumed = $task->consumed + $estimate->consumed - $oldEstimate->consumed; $lastEstimate = $this->dao->select('*')->from(TABLE_TASKESTIMATE)->where('task')->eq($task->id)->orderBy('id desc')->fetch(); - $left = ($lastEstimate and $estimateID == $lastEstimate->id) ? $estimate->left : $task->left; + $left = ($lastEstimate and $estimateID == $lastEstimate->id) ? $estimate->left : $task->left; if($left == 0) $task->status = 'done'; $now = helper::now(); @@ -1162,7 +1295,7 @@ class taskModel extends model $data->status = $task->status; $data->lastEditedBy = $this->app->user->account; $data->lastEditedDate = $now; - if(!$left) + if(!$left) { $data->finishedBy = $this->app->user->account; $data->finishedDate = $now; @@ -1183,9 +1316,9 @@ class taskModel extends model } /** - * Delete estimate. - * - * @param int $estimateID + * Delete estimate. + * + * @param int $estimateID * @access public * @return void */ @@ -1198,7 +1331,7 @@ class taskModel extends model $consumed = $task->consumed - $estimate->consumed; $left = $lastEstimate->left ? $lastEstimate->left : $estimate->left; $oldStatus = $task->status; - if($left == 0 and $consumed != 0) $task->status = 'done'; + if($left == 0 and $consumed != 0) $task->status = 'done'; $this->dao->update(TABLE_TASK) ->set("consumed")->eq($consumed) ->set('`left`')->eq($left) @@ -1219,8 +1352,8 @@ class taskModel extends model /** * Batch process tasks. - * - * @param int $tasks + * + * @param int $tasks * @access private * @return void */ @@ -1229,6 +1362,10 @@ class taskModel extends model foreach($tasks as $task) { $task = $this->processTask($task); + if($task->children) foreach($task->children as $child) + { + $task = $this->processTask($child); + } } return $tasks; } @@ -1303,7 +1440,7 @@ class taskModel extends model return true; } - + /** * Get story comments. * @@ -1322,8 +1459,8 @@ class taskModel extends model /** * Merge the default chart settings and the settings of current chart. - * - * @param string $chartType + * + * @param string $chartType * @access public * @return void */ @@ -1340,10 +1477,10 @@ class taskModel extends model /* merge configuration */ foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value; } - + /** - * Get report data of tasks per project - * + * Get report data of tasks per project + * * @access public * @return array */ @@ -1362,8 +1499,8 @@ class taskModel extends model } /** - * Get report data of tasks per module - * + * Get report data of tasks per module + * * @access public * @return array */ @@ -1383,8 +1520,8 @@ class taskModel extends model } /** - * Get report data of tasks per assignedTo - * + * Get report data of tasks per assignedTo + * * @access public * @return array */ @@ -1403,8 +1540,8 @@ class taskModel extends model } /** - * Get report data of tasks per type - * + * Get report data of tasks per type + * * @access public * @return array */ @@ -1423,7 +1560,7 @@ class taskModel extends model /** * Get report data of tasks per priority - * + * * @access public * @return array */ @@ -1445,8 +1582,8 @@ class taskModel extends model } /** - * Get report data of tasks per deadline - * + * Get report data of tasks per deadline + * * @access public * @return array */ @@ -1461,8 +1598,8 @@ class taskModel extends model } /** - * Get report data of tasks per estimate - * + * Get report data of tasks per estimate + * * @access public * @return array */ @@ -1478,7 +1615,7 @@ class taskModel extends model /** * Get report data of tasks per left - * + * * @access public * @return array */ @@ -1494,7 +1631,7 @@ class taskModel extends model /** * Get report data of tasks per consumed - * + * * @access public * @return array */ @@ -1509,8 +1646,8 @@ class taskModel extends model } /** - * Get report data of tasks per finishedBy - * + * Get report data of tasks per finishedBy + * * @access public * @return array */ @@ -1530,8 +1667,8 @@ class taskModel extends model } /** - * Get report data of tasks per closed reason - * + * Get report data of tasks per closed reason + * * @access public * @return array */ @@ -1556,7 +1693,7 @@ class taskModel extends model /** * Get report data of finished tasks per day - * + * * @access public * @return array */ @@ -1581,7 +1718,7 @@ class taskModel extends model /** * Get report data of status - * + * * @access public * @return array */ @@ -1613,6 +1750,11 @@ class taskModel extends model { $action = strtolower($action); + if($action == 'start' and !empty($task->children)) return false; + if($action == 'recordestimate' and !empty($task->children)) return false; + if($action == 'batchcreate' and !empty($task->team)) return false; + if($action == 'batchcreate' and $task->parent) return false; + if($action == 'assignto') return $task->status != 'closed' and $task->status != 'cancel'; if($action == 'start') return $task->status == 'wait'; if($action == 'restart') return $task->status == 'pause'; @@ -1622,12 +1764,14 @@ class taskModel extends model if($action == 'cancel') return $task->status != 'done' and $task->status != 'closed' and $task->status != 'cancel'; if($action == 'pause') return $task->status == 'doing'; + + return true; } /** * Get report condition from session. - * + * * @access public * @return void */ @@ -1643,8 +1787,8 @@ class taskModel extends model /** * Add task estimate. - * - * @param object $data + * + * @param object $data * @access public * @return void */ @@ -1655,11 +1799,11 @@ class taskModel extends model /** * Print cell data. - * - * @param object $col - * @param object $task - * @param array $users - * @param string $browseType + * + * @param object $col + * @param object $task + * @param array $users + * @param string $browseType * @access public * @return void */ @@ -1773,6 +1917,7 @@ class taskModel extends model common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list', '', '', 'iframe', true); common::printIcon('task', 'close', "taskID=$task->id", $task, 'list', '', '', 'iframe', true); common::printIcon('task', 'edit',"taskID=$task->id", $task, 'list'); + if(!$task->team or !$task->children) common::printIcon('task', 'batchCreate', "project=$task->project&storyID=$task->story&moduleID=$task->module&taskID=$task->id", $task, 'list','plus','','','','',$this->lang->task->children); break; } echo ''; @@ -1781,9 +1926,9 @@ class taskModel extends model /** * Send mail. - * - * @param int $taskID - * @param int $actionID + * + * @param int $taskID + * @param int $actionID * @access public * @return void */ @@ -1844,4 +1989,51 @@ class taskModel extends model $this->mail->send($toList, 'TASK#' . $task->id . ' ' . $task->name . ' - ' . $projectName, $mailContent, $ccList); if($this->mail->isError()) trigger_error(join("\n", $this->mail->getError())); } + + /** + * Get next user. + * + * @param string $users + * @param string $current + * @access public + * @return void + */ + public function getNextUser($users, $current) + { + /* Process user */ + if(!is_array($users)) $users = explode(',', trim($users, ',')); + if(!$current) return reset($users); + $hit = false; + $next = ''; + foreach($users as $key => $account) + { + if($hit) + { + $next = $account; + break; + } + + if($account == $current) $hit = true; + } + if($next == '') return reset($users); + return $next; + } + + /** + * Get task's team member pairs. + * + * @param object $task + * @access public + * @return array + */ + public function getMemberPairs($task) + { + $users = $this->loadModel('user')->getPairs('noletter'); + $members = array(); + foreach($task->team as $member) + { + $members[$member->account] = $users[$member->account]; + } + return array('' => '') + $members; + } } diff --git a/module/task/view/assignto.html.php b/module/task/view/assignto.html.php index 166f610599..2b80014f08 100644 --- a/module/task/view/assignto.html.php +++ b/module/task/view/assignto.html.php @@ -16,14 +16,14 @@
icons['task']);?> id;?> createLink('task', 'view', 'task=' . $task->id), $task->name, '_blank');?> - task->assign;?> + team) ? $lang->task->assign : $lang->task->transmit;?>
- - + + diff --git a/module/task/view/batchcreate.html.php b/module/task/view/batchcreate.html.php index f58f2670f5..af9b4e682c 100644 --- a/module/task/view/batchcreate.html.php +++ b/module/task/view/batchcreate.html.php @@ -73,7 +73,7 @@ if($hiddenStory and isset($visibleFields['story'])) $colspan -= 1; ?> - + - + config->global->flow != 'onlyTask'):?> @@ -175,6 +192,37 @@
task->assignedTo;?>team) ? $lang->task->assign : $lang->task->transmitTo;?>assignedTo, "class='form-control chosen'");?>
task->left;?>
style='overflow:visible'>id, $i)'")?> style='overflow: visible'>
diff --git a/module/task/view/create.html.php b/module/task/view/create.html.php index b36c445810..d88374d6e0 100644 --- a/module/task/view/create.html.php +++ b/module/task/view/create.html.php @@ -38,9 +38,26 @@
task->assignedTo;?>assignedTo, "class='form-control chosen'");?> - +
+
+ assignedTo, "class='form-control chosen'");?> +
+ type == 'ops') :?> +
+ +
+ +
+ +
+ +
+
+ type != 'ops') :?> + +
+
createLink('custom', 'ajaxSaveCustomFields', 'module=task§ion=custom&key=createFields')?> diff --git a/module/task/view/edit.html.php b/module/task/view/edit.html.php index 04e7086b73..bf6af02834 100644 --- a/module/task/view/edit.html.php +++ b/module/task/view/edit.html.php @@ -35,6 +35,14 @@
name, 'class="form-control" autocomplete="off" placeholder="' . $lang->task->name . '"');?> + children) and empty($task->parent)):?> + + + +
@@ -81,6 +89,10 @@ task->assignedTo;?> assignedTo, "class='form-control chosen'");?> + ' id='teamTr'> + task->team;?> + task->team,'', "class='form-control btn' data-toggle='modalTeam'");?> + task->type;?> task->typeList, $task->type, 'class=form-control');?> @@ -168,5 +180,56 @@ + diff --git a/module/task/view/view.html.php b/module/task/view/view.html.php index e7cec9645a..3decac4ae3 100644 --- a/module/task/view/view.html.php +++ b/module/task/view/view.html.php @@ -31,7 +31,7 @@ { ob_start(); echo "
"; - common::printIcon('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $task, 'button', '', '', 'iframe', true); + common::printIcon('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $task, 'button', '', '', 'iframe', true); common::printIcon('task', 'start', "taskID=$task->id", $task, 'button', '', '', 'iframe', true); common::printIcon('task', 'restart', "taskID=$task->id", $task, 'button', '', '', 'iframe', true); common::printIcon('task', 'recordEstimate', "taskID=$task->id", $task, 'button', '', '', 'iframe', true); @@ -175,7 +175,7 @@ task->assignedTo;?> - assignedTo ? $task->assignedToRealName . $lang->at . $task->assignedDate : '';?> + assignedTo ? $task->assignedToRealName . $lang->at . $task->assignedDate : '';?> task->type;?> @@ -195,6 +195,29 @@
+ team)) :?> +
+ task->team;?> + + + + + + + + + + team as $member):?> + + + + + + + +
task->team?>task->estimate?>task->consumed?>task->left?>
account)?>estimate?>consumed?>left?>
+
+
task->legendEffort;?>