diff --git a/module/task/ui/view.html.php b/module/task/ui/view.html.php index 729cb0f687..842ce19c5f 100644 --- a/module/task/ui/view.html.php +++ b/module/task/ui/view.html.php @@ -12,540 +12,163 @@ namespace zin; include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php'); -global $lang; +$isInModal = isInModal(); -/* Join mailto. */ -$mailtoList = array(); -if(!empty($task->mailto)) +/* 初始化头部右上方工具栏。Init detail toolbar. */ +$toolbar = array(); +if(!$isInModal && hasPriv('task', 'create', $task)) { - foreach(explode(',', $task->mailto) as $account) - { - if(empty($account)) continue; - $mailtoList[] = zget($users, trim($account)); - } -} -$mailtoList = implode($lang->comma, $mailtoList); - -detailHeader -( - to::title + $toolbar[] = array ( - $task->team ? span - ( - setClass('label primary-pale'), - $lang->task->modeList[$task->mode] - ) : null, - entityLabel - ( - set - ( - array - ( - 'entityID' => $task->id, - 'level' => 1 - ) - ), - $task->parent > 0 ? - span - ( - setClass('text'), - set::title($task->name), - span(setClass('label gray-pale rounded-xl'), $lang->task->childrenAB), - a(set::href(createLink('task', 'view', "taskID={$task->parent}")), $task->parentName), - span('/'), - span(setStyle(array('color' => $task->color)), $task->name) - ) : span(setStyle(array('color' => $task->color)), $task->name) - ), - $task->deleted ? span(setClass('label danger'), $lang->task->deleted) : null - ), - !isAjaxRequest('modal') && common::hasPriv('task', 'create', $task) ? to::suffix(btn(set::icon('plus'), set::url(createLink('task', 'create', "executionID={$task->execution}")), set::type('primary'), set('data-app', $app->tab), $lang->task->create)) : null -); - -/* Construct suitable actions for the current task. */ -if(common::hasPriv('repo', 'createBranch') && empty($task->linkedBranch)) $hasRepo = $this->loadModel('repo')->getRepoPairs('execution', $task->execution, false); - -$operateMenus = array(); -foreach($config->task->view->operateList['main'] as $operate) -{ - if($operate == 'createBranch') - { - if(empty($hasRepo) || !common::hasPriv('repo', $operate) || !empty($task->linkedBranch) || !common::canModify('execution', $execution)) continue; - } - else - { - if(!common::hasPriv('task', $operate, $task)) continue; - if(!$this->task->isClickable($task, $operate)) continue; - - if($operate == 'batchCreate') $config->task->actionList['batchCreate']['text'] = $lang->task->children; - } - - $operateMenus[] = $config->task->actionList[$operate]; -} - -/* Construct common actions for task. */ -$commonActions = array(); -foreach($config->task->view->operateList['common'] as $operate) -{ - if(!common::hasPriv('task', $operate, $task)) continue; - if($operate == 'view' && $task->parent <= 0) continue; - - $settings = $config->task->actionList[$operate]; - if($operate != 'view') $settings['text'] = ''; - - $commonActions[] = $settings; -} - -if($task->children) $children = initTableData($task->children, $config->task->dtable->children->fieldList, $this->task); -if($task->team) -{ - $teams = array(); - foreach($task->team as $team) - { - $teams[] = h::tr - ( - h::td - ( - zget($users, $team->account) - ), - h::td - ( - (float)$team->estimate - ), - h::td - ( - (float)$team->consumed - ), - h::td - ( - (float)$team->left - ), - h::td - ( - setClass("status-{$team->status}"), - zget($lang->task->statusList, $team->status) - ) - ); - } -} - -/* Set the module name of the task. */ -$moduleTitle = ''; -$moduleItems = array(); -if(empty($modulePath)) -{ - $moduleTitle .= '/'; - $moduleItems[] = span('/'); -} -else -{ - if($product) - { - $moduleTitle .= $product->name . '/'; - $moduleItems[] = span(a(set::href(createLink('product', 'browse', "productID=$product->id")), $product->name)); - $moduleItems[] = icon('angle-right'); - } - foreach($modulePath as $key => $module) - { - $moduleTitle .= $module->name; - $moduleItems[] = a(set::href(createLink('execution', 'task', "executionID=$task->execution&browseType=byModule¶m=$module->id")), $module->name) ?? span($module->name); - if(isset($modulePath[$key + 1])) - { - $moduleTitle .= '/'; - $moduleItems[] = icon('angle-right'); - } - } -} - -$canViewMR = common::hasPriv('mr', 'view'); -$linkedMR = array(); -foreach($linkMRTitles as $MRID => $linkMRTitle) -{ - $linkedMR[] = $canViewMR ? a - ( - set::href(createLink('mr', 'view', "MRID=$MRID")), - "#$MRID $linkMRTitle", - setData('app', 'devops') - ) : div("#$MRID $linkMRTitle"); -} - -$canViewRevision = common::hasPriv('repo', 'revision'); -$linkedCommits = array(); -foreach($linkCommits as $commit) -{ - if(empty($commit->revision)) continue; - - $revision = substr($commit->revision, 0, 10); - $linkedCommits[] = $canViewRevision ? a - ( - set::href(createLink('repo', 'revision', "repoID={$commit->repo}&objectID={$task->execution}&revision={$commit->revision}")), - "#$revision", - setData('app', 'devops') - ) : div($revision . ' ' . $commit->comment); -} - -$linkedCases = array(); -$canViewCase = common::hasPriv('testcase', 'view'); -if(!empty($task->cases)) -{ - foreach($task->cases as $caseID => $case) - { - $linkedCases[] = $canViewCase ? a - ( - setClass('flex clip'), - set::href(createLink('testcase', 'view', "caseID={$caseID}")), - setData('toggle', 'modal'), - setData('size', 'lg'), - set::title($case), - "#{$caseID} " . $case - ) : div( - setClass('flex clip'), - set::title($case), - "#{$caseID} " . $case - ); - } -} - -detailBody -( - sectionList - ( - section - ( - set::title($lang->task->legendDesc), - set::content(empty($task->desc) ? $lang->noData : $task->desc), - set::useHtml(true) - ), - $task->fromBug ? - section - ( - set::title($lang->task->fromBug), - sectionCard - ( - entityLabel - ( - set::entityID($task->fromBug), - set::text($fromBug->title) - ), - item - ( - set::title($lang->bug->steps), - empty($fromBug->steps) ? $lang->noData : html($fromBug->steps) - ) - ) - ) : null, - !$task->fromBug && $task->story ? - section - ( - set::title($lang->task->story), - sectionCard - ( - entityLabel - ( - set::entityID($task->storyID), - set::text($task->storyTitle), - set::href(createLink('story', 'view', "storyID=$task->storyID")), - set::textClass('clip'), - $task->needConfirm ? to::suffix - ( - div - ( - setClass('flex-1 text-right nowrap'), - span($lang->task->storyChange), - a - ( - setClass('mx-2 btn primary size-sm'), - set::href(createLink('task', 'confirmStoryChange', "taskID={$task->id}")), - $lang->confirm - ) - ) - ) : null - ), - div - ( - setClass('p-4'), - span("[{$lang->story->legendSpec}]", setClass('text-gray')), - empty($task->storySpec) && empty($task->storyFiles) ? $lang->noData : html($task->storySpec) - ), - div - ( - setClass('p-4'), - span("[{$lang->task->storyVerify}]", setClass('text-gray')), - empty($task->storyVerify) ? $lang->noData : html($task->storyVerify) - ) - ) - ) : null, - !empty($task->cases) ? section - ( - set::title($lang->task->case), - div($linkedCases) - ) : null, - $task->children ? - section - ( - set::title($lang->task->children), - dtable - ( - set::cols(array_values($config->task->dtable->children->fieldList)), - set::userMap($users), - set::data($children), - set::checkable(false) - ) - ) : null - ), - $task->files ? fileList - ( - set::files($task->files) - ) : null, - history(), - floatToolbar - ( - isAjaxRequest('modal') ? null : to::prefix(backBtn(set::icon('back'), $lang->goback)), - $task->deleted == '0' ? set::main($operateMenus) : null, - $task->deleted == '0' ? set::suffix($commonActions) : null, - set::object($task) - ), - detailSide - ( - tabs - ( - set::collapse(true), - tabPane - ( - set::key('legend-basic'), - set::title($lang->task->legendBasic), - set::active(true), - tableData - ( - $execution->multiple ? item - ( - set::name($lang->task->execution), - a - ( - set::href(createLink('execution', 'view', "executionID=$execution->id")), - $execution->name - ) - ) : null, - item - ( - set::name($lang->task->module), - set::title($moduleTitle), - $moduleItems - ), - item - ( - set::name($lang->task->fromBug), - !empty($fromBug) ? a - ( - setData - ( - array - ( - 'toggle' => 'modal', - 'size' => 'lg' - ) - ), - set::href(createLink('bug', 'view', "id={$task->fromBug}")), - set::title($fromBug->title), - $fromBug->title - ) : null - ), - item - ( - set::name($lang->task->assignedTo), - zget($users, $task->assignedTo, '') - ), - item - ( - set::name($lang->task->type), - zget($this->lang->task->typeList, $task->type, $task->type) - ), - item - ( - set::name($lang->task->status), - $this->processStatus('task', $task) - ), - item - ( - set::name($lang->task->progress), - $task->progress . ' %' - ), - item - ( - set::name($lang->task->pri), - priLabel - ( - setClass('align-sub'), - $task->pri, - set::text($lang->task->priList) - ) - ), - item - ( - set::name($lang->task->keywords), - $task->keywords - ), - item - ( - set::name($lang->task->mailto), - $mailtoList - ) - ) - ), - tabPane - ( - set::key('legend-life'), - set::title($lang->task->legendLife), - tableData - ( - item - ( - set::name($lang->task->openedBy), - $task->openedBy ? zget($users, $task->openedBy, $task->openedBy) . $lang->at . $task->openedDate : '' - ), - item - ( - set::name($lang->task->finishedBy), - $task->finishedBy ? zget($users, $task->finishedBy, $task->finishedBy) . $lang->at . $task->finishedDate : '' - ), - item - ( - set::name($lang->task->canceledBy), - $task->canceledBy ? zget($users, $task->canceledBy, $task->canceledBy) . $lang->at . $task->canceledDate : '' - ), - item - ( - set::name($lang->task->closedBy), - $task->closedBy ? zget($users, $task->closedBy, $task->closedBy) . $lang->at . $task->closedDate : '' - ), - item - ( - set::name($lang->task->closedReason), - $task->closedReason ? $lang->task->reasonList[$task->closedReason] : '' - ), - item - ( - set::name($lang->task->lastEdited), - $task->lastEditedBy ? zget($users, $task->lastEditedBy, $task->lastEditedBy) . $lang->at . $task->lastEditedDate : '' - ) - ) - ), - $task->team ? tabPane - ( - set::key('legend-team'), - set::title($lang->task->team), - h::table - ( - setClass('table condensed bordered'), - setID('team'), - h::thead - ( - h::tr - ( - h::th - ( - $lang->task->team, - set::width('80px') - ), - h::th - ( - $lang->task->estimateAB, - set::width('60px') - ), - h::th - ( - $lang->task->consumedAB, - set::width('60px') - ), - h::th - ( - $lang->task->leftAB, - set::width('60px') - ), - h::th - ( - $lang->task->statusAB, - set::width('80px') - ) - ) - ), - h::tbody($teams) - ) - ) : null - ), - tabs - ( - set::collapse(true), - tabPane - ( - set::key('legend-effort'), - set::title($lang->task->legendEffort), - set::active(true), - tableData - ( - item - ( - set::name($lang->task->estimate), - $task->estimate . ' ' . $lang->task->suffixHour - ), - item - ( - set::name($lang->task->consumed), - round($task->consumed, 2) . ' ' . $lang->task->suffixHour - ), - item - ( - set::name($lang->task->left), - $task->left . ' ' . $lang->task->suffixHour - ), - item - ( - set::name($lang->task->estStarted), - helper::isZeroDate($task->estStarted) ? '' : $task->estStarted - ), - item - ( - set::name($lang->task->realStarted), - helper::isZeroDate($task->realStarted) ? '' : substr($task->realStarted, 0, 19) - ), - item - ( - set::name($lang->task->deadline), - helper::isZeroDate($task->deadline) ? '' : $task->deadline - ) - ) - ), - tabPane - ( - set::key('legend-misc'), - set::title($lang->task->legendMisc), - tableData - ( - empty($task->linkedBranch) ? null : item - ( - set::name($lang->task->relatedBranch), - current($task->linkedBranch) - ), - item - ( - set::name($lang->task->linkMR), - div($linkedMR) - ), - item - ( - set::name($lang->task->linkCommit), - div($linkedCommits) - ) - ) - ) - ) - ) -); - -if(!isInModal()) -{ - floatPreNextBtn - ( - !empty($preAndNext->pre) ? set::preLink(createLink('task', 'view', "taskID={$preAndNext->pre->id}")) : null, - !empty($preAndNext->next) ? set::nextLink(createLink('task', 'view', "taskID={$preAndNext->next->id}")) : null + 'icon' => 'plus', + 'type' => 'primary', + 'text' => $lang->task->create, + 'url' => createLink('task', 'create', "executionID={$task->execution}") ); } + +/* 初始化底部操作栏。Init bottom actions. */ +$actions = array(); +if(!$task->deleted) +{ + $hasRepo = common::hasPriv('repo', 'createBranch') && empty($task->linkedBranch) && $this->loadModel('repo')->getRepoPairs('execution', $task->execution, false); + /* Construct suitable actions for the current task. */ + foreach($config->task->view->operateList['main'] as $operate) + { + if($operate == 'createBranch') + { + if(empty($hasRepo) || !common::hasPriv('repo', $operate) || !empty($task->linkedBranch) || !common::canModify('execution', $execution)) continue; + } + else + { + if(!common::hasPriv('task', $operate, $task)) continue; + if(!$this->task->isClickable($task, $operate)) continue; + + if($operate == 'batchCreate') $config->task->actionList['batchCreate']['text'] = $lang->task->children; + } + + $actions[] = $config->task->actionList[$operate]; + } + /* Construct common actions for task. */ + $commonActions = array(); + foreach($config->task->view->operateList['common'] as $operate) + { + if(!common::hasPriv('task', $operate, $task)) continue; + if($operate == 'view' && $task->parent <= 0) continue; + + $settings = $config->task->actionList[$operate]; + if($operate != 'view') $settings['text'] = ''; + + $commonActions[] = $settings; + } + if($commonActions) $actions = array_merge($actions, array(array('type' => 'divider')), $commonActions); +} + +/* 初始化主栏内容。Init sections in main column. */ +$sections = array(); +$sections[] = setting() + ->title($lang->task->legendDesc) + ->control('html') + ->content(empty($task->desc) ? $lang->noDesc : $task->desc); +if($task->fromBug) +{ + $sections[] = setting() + ->title($lang->task->fromBug) + ->control('detailCard') + ->object($fromBug) + ->content(setting()->title($lang->bug->steps)->control('html')->content(empty($fromBug->steps) ? $lang->noData : $fromBug->steps)); +} +if(!$task->fromBug && $task->story) +{ + $storyDetailProps = array + ( + 'control' => 'detailCard', + 'title' => $task->storyTitle, + 'url' => createLink('story', 'view', "storyID=$task->storyID"), + 'objectID' => $task->storyID, + 'toolbar' => !$task->needConfirm ? array + ( + array('text' => $lang->task->storyChange, 'class' => 'ghost pointer-events-none'), + array('text' => $lang->confirm, 'type' => 'primary', 'url' => createLink('task', 'confirmStoryChange', "taskID={$task->id}")) + ) : null, + 'sections' => array + ( + setting()->title("[{$lang->story->legendSpec}]")->control('html')->content(empty($task->storySpec) && empty($task->storyFiles) ? $lang->noData : $task->storySpec), + setting()->title("[{$lang->task->storyVerify}]")->control('html')->content(empty($task->storyVerify) ? $lang->noData : $task->storyVerify) + ) + ); + $sections[] = setting() + ->title($lang->task->story) + ->control($storyDetailProps); +} +if(!empty($task->cases)) +{ + $sections[] = setting() + ->title($lang->task->case) + ->control('entityList') + ->type('testcase') + ->items($task->cases); +} +if($task->children) +{ + $children = initTableData($task->children, $config->task->dtable->children->fieldList, $this->task); + $sections[] = setting() + ->title($lang->task->children) + ->control('dtable') + ->className('ring') + ->cols(array_values($config->task->dtable->children->fieldList)) + ->userMap($users) + ->data($children) + ->checkable(false); +} +if($task->files) +{ + $sections[] = array + ( + 'title' => $lang->files, + 'control' => 'fileList', + 'files' => $task->files, + 'object' => $task + ); +} + +/* 初始化侧边栏标签页。Init sidebar tabs. */ +$tabs = array(); + +/* 基本信息。Legend basic items. */ +$tabs[] = setting() + ->group('basic') + ->title($lang->task->legendBasic) + ->control('taskBasicInfo') + ->statusText($this->processStatus('task', $task)); + +/* 一生信息。Legend life items. */ +$tabs[] = setting() + ->group('basic') + ->title($lang->task->legendLife) + ->control('taskLifeInfo'); + +if($task->team) +{ + $tabs[] = setting() + ->group('basic') + ->title($lang->task->team) + ->control('taskTeam'); +} + +$tabs[] = setting() + ->group('related') + ->title($lang->task->legendEffort) + ->control('taskEffortInfo'); +$tabs[] = setting() + ->group('related') + ->title($lang->task->legendMisc) + ->control('taskMiscInfo'); + +detail +( + set::toolbar($toolbar), + set::sections($sections), + set::tabs($tabs), + set::actions($actions) +);