From 285807f780114879511d6644adb2e164b788979a Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 25 Oct 2023 09:51:18 +0800 Subject: [PATCH] * Refactor testtask list of under the project app. --- module/build/zen.php | 2 +- module/project/config/dtable.php | 60 ++++++++++++++++ module/project/control.php | 3 +- module/project/css/testtask.ui.css | 2 + module/project/js/testtask.ui.js | 106 ++++++++++++++++++++++++++++ module/project/lang/de.php | 2 - module/project/lang/en.php | 2 - module/project/lang/fr.php | 2 - module/project/lang/zh-cn.php | 2 - module/project/ui/testtask.html.php | 44 ++++++------ module/project/zen.php | 44 ++++++++++++ 11 files changed, 235 insertions(+), 34 deletions(-) create mode 100644 module/project/css/testtask.ui.css create mode 100644 module/project/js/testtask.ui.js diff --git a/module/build/zen.php b/module/build/zen.php index 079a1e7974..23156531f3 100644 --- a/module/build/zen.php +++ b/module/build/zen.php @@ -26,7 +26,7 @@ class buildZen extends build { $productGroups = $branchGroups = array(); $executions = $this->loadModel('execution')->getPairs($projectID, 'all', 'stagefilter|leaf|order_asc'); - $executionID = empty($executionID) ? key($executions) : $executionID; + $executionID = empty($executionID) ? (int)key($executions) : $executionID; if($executionID) { $productGroups = $this->loadModel('product')->getProducts($executionID, $status); diff --git a/module/project/config/dtable.php b/module/project/config/dtable.php index d0dc5ef088..4000c1bc15 100644 --- a/module/project/config/dtable.php +++ b/module/project/config/dtable.php @@ -2,6 +2,7 @@ global $lang,$app; $config->project->dtable = new stdclass(); $config->project->dtable->team = new stdclass(); +$config->project->dtable->testtask = new stdclass(); $config->project->dtable->defaultField = array('id', 'name', 'status', 'PM', 'budget', 'begin', 'end', 'progress', 'actions'); $config->project->dtable->fieldList['id']['title'] = $lang->idAB; @@ -371,3 +372,62 @@ $config->project->dtable->team->fieldList['limited']['sortType'] = false; $config->project->dtable->team->fieldList['actions']['type'] = 'actions'; $config->project->dtable->team->fieldList['actions']['minWidth'] = 60; $config->project->dtable->team->fieldList['actions']['actionsMap'] = $config->project->team->actionList; + +$app->loadLang('testcase'); +$app->loadLang('testtask'); +$app->loadModuleConfig('testtask'); + +$config->project->dtable->testtask->fieldList['product']['name'] = 'productName'; +$config->project->dtable->testtask->fieldList['product']['title'] = $lang->testtask->product; +$config->project->dtable->testtask->fieldList['product']['type'] = 'text'; +$config->project->dtable->testtask->fieldList['product']['group'] = '1'; + +$config->project->dtable->testtask->fieldList['id']['name'] = 'id'; +$config->project->dtable->testtask->fieldList['id']['title'] = $lang->idAB; +$config->project->dtable->testtask->fieldList['id']['type'] = 'id'; +$config->project->dtable->testtask->fieldList['id']['group'] = '2'; +$config->project->dtable->testtask->fieldList['id']['fixed'] = false; + +$config->project->dtable->testtask->fieldList['title']['name'] = 'name'; +$config->project->dtable->testtask->fieldList['title']['title'] = $lang->testtask->name; +$config->project->dtable->testtask->fieldList['title']['type'] = 'title'; +$config->project->dtable->testtask->fieldList['title']['link'] = array('module' => 'testtask', 'method' => 'cases', 'params' => 'taskID={id}'); +$config->project->dtable->testtask->fieldList['title']['group'] = '2'; +$config->project->dtable->testtask->fieldList['title']['fixed'] = false; +$config->project->dtable->testtask->fieldList['title']['width'] = '356'; + +$config->project->dtable->testtask->fieldList['build']['name'] = 'buildName'; +$config->project->dtable->testtask->fieldList['build']['title'] = $lang->testtask->build; +$config->project->dtable->testtask->fieldList['build']['type'] = 'text'; +$config->project->dtable->testtask->fieldList['build']['link'] = array('module' => 'build', 'method' => 'view', 'params' => 'buildID={build}'); +$config->project->dtable->testtask->fieldList['build']['group'] = 'text'; +$config->project->dtable->testtask->fieldList['build']['group'] = '3'; + +$config->project->dtable->testtask->fieldList['owner']['name'] = 'owner'; +$config->project->dtable->testtask->fieldList['owner']['title'] = $lang->testtask->owner; +$config->project->dtable->testtask->fieldList['owner']['type'] = 'user'; +$config->project->dtable->testtask->fieldList['owner']['group'] = '4'; + +$config->project->dtable->testtask->fieldList['begin']['name'] = 'begin'; +$config->project->dtable->testtask->fieldList['begin']['title'] = $lang->testtask->begin; +$config->project->dtable->testtask->fieldList['begin']['type'] = 'date'; +$config->project->dtable->testtask->fieldList['begin']['group'] = '4'; + +$config->project->dtable->testtask->fieldList['end']['name'] = 'end'; +$config->project->dtable->testtask->fieldList['end']['title'] = $lang->testtask->end; +$config->project->dtable->testtask->fieldList['end']['type'] = 'date'; +$config->project->dtable->testtask->fieldList['end']['group'] = '4'; + +$config->project->dtable->testtask->fieldList['status']['name'] = 'status'; +$config->project->dtable->testtask->fieldList['status']['title'] = $lang->testtask->status; +$config->project->dtable->testtask->fieldList['status']['type'] = 'status'; +$config->project->dtable->testtask->fieldList['status']['statusMap'] = $lang->testtask->statusList; +$config->project->dtable->testtask->fieldList['status']['group'] = '4'; + +$config->project->dtable->testtask->fieldList['actions']['name'] = 'actions'; +$config->project->dtable->testtask->fieldList['actions']['title'] = $lang->actions; +$config->project->dtable->testtask->fieldList['actions']['type'] = 'actions'; +$config->project->dtable->testtask->fieldList['actions']['sortType'] = false; +$config->project->dtable->testtask->fieldList['actions']['fixed'] = false; +$config->project->dtable->testtask->fieldList['actions']['list'] = $config->testtask->actionList; +$config->project->dtable->testtask->fieldList['actions']['menu'] = array('cases', 'linkCase', 'report', 'view', 'edit', 'delete'); diff --git a/module/project/control.php b/module/project/control.php index b746af56a0..fbe44decf5 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -885,11 +885,12 @@ class project extends control $project = $this->project->getByID($projectID); $tasks = $this->loadModel('testtask')->getProjectTasks($projectID, $orderBy, $pager); + $this->projectZen->assignTesttaskVars($tasks); + $this->view->title = $project->name . $this->lang->colon . $this->lang->project->common; $this->view->project = $project; $this->view->pager = $pager; $this->view->orderBy = $orderBy; - $this->view->tasks = $tasks; $this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter'); $this->view->products = $this->loadModel('product')->getPairs('', 0); $this->view->actions = $this->loadModel('action')->getList('testtask', $projectID); diff --git a/module/project/css/testtask.ui.css b/module/project/css/testtask.ui.css new file mode 100644 index 0000000000..992f34327c --- /dev/null +++ b/module/project/css/testtask.ui.css @@ -0,0 +1,2 @@ +#taskTable .toggle-icon.is-collapsed:before,.toggle-icon.is-expanded:before,.toggle-icon.is-collapsed:after {background-color: var(--color-current); content: " "; display: block; height: 1px; left: 2px; position: absolute; right: 2px; top: calc((var(--toggle-icon-size) - 3px)/2);} +#taskTable .toggle-icon.is-collapsed:after {--tw-rotate: 90deg; transform: translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));} diff --git a/module/project/js/testtask.ui.js b/module/project/js/testtask.ui.js new file mode 100644 index 0000000000..82a43e07fa --- /dev/null +++ b/module/project/js/testtask.ui.js @@ -0,0 +1,106 @@ +$(function() +{ + const options = zui.DTable.query().options; + initialOptions = $.extend(true, {}, options); +}); + +/** + * 产品列合并单元格。 + * Merge cell in the product column. + * + * @param object cell + * @access public + * @return object + */ +window.getCellSpan = function(cell) +{ + if(cell.col.name == 'productName' && cell.row.data.rowspan) + { + return {rowSpan: cell.row.data.rowspan}; + } + if(cell.col.name == 'id' && cell.row.data.colspan) + { + return {colSpan: cell.row.data.colspan}; + } +} + +/** + * 产品列显示展开收起的图标。 + * Display show icon in the product column. + * + * @param object result + * @param object info + * @access public + * @return object + */ +window.onRenderCell = function(result, {row, col}) +{ + if(result && col.name == 'productName') + { + if(row.data.hidden) + { + result.unshift({html: ''}); + } + else + { + result.unshift({html: ''}); + result.push({outer: false, style: {alignItems: 'start', 'padding-top': '8px'}}) + } + } + if(result && col.name == 'id' && row.data.hidden) + { + result.push({outer: false, style: {alignItems: 'center', justifyContent: 'start'}}) + } + + return result; +} + +window.deformation = function(event) +{ + let newData = []; + const options = zui.DTable.query().options; + const product = $(event.target).closest('a').data('product'); + const oldOptions = $.extend(true, {}, initialOptions); + + if($(event.target).closest('a').find('span').hasClass('is-collapsed')) + { + $.each(options.data, function(index) + { + if(!options.data[index]) return; + if(options.data[index].product == product) + { + $.each(oldOptions.data, function(key) + { + if(!oldOptions.data[key]) return; + if(oldOptions.data[key].product == product) newData.push(oldOptions.data[key]); + }); + } + else + { + newData.push(options.data[index]); + } + }); + options.data = newData; + $(event.target).closest('a').find('span').removeClass('is-collapsed').addClass('is-expanded'); + $('#taskTable').zui('dtable').render(options); + } + else + { + options.data = options.data.filter(function(option) + { + return option.product != product || option.rowspan != 0; + }); + $.each(options.data, function(index) + { + if(options.data[index] && options.data[index].product == product) + { + options.data[index].id = {html: '' + allTasks + ' ' + '' + options.data[index].rowspan + ''}; + options.data[index].rowspan = 1; + options.data[index].colspan = 10; + options.data[index].hidden = 1; + } + }); + $(event.target).closest('a').find('span').removeClass('is-expanded').addClass('is-collapsed'); + $('#taskTable').zui('dtable').render(); + } +} diff --git a/module/project/lang/de.php b/module/project/lang/de.php index 606e3e7707..632deb956d 100644 --- a/module/project/lang/de.php +++ b/module/project/lang/de.php @@ -326,8 +326,6 @@ $lang->project->featureBar['bug']['unresolved'] = 'Unresolved'; $app->loadLang('testcase'); $lang->project->featureBar['testcase'] = $lang->testcase->featureBar['browse']; -$lang->project->featureBar['testtask']['all'] = 'All'; - $lang->project->featureBar['build']['all'] = 'Build List'; $lang->project->featureBar['group']['all'] = 'All Groups'; diff --git a/module/project/lang/en.php b/module/project/lang/en.php index 30c97f3c8c..82e550ca85 100644 --- a/module/project/lang/en.php +++ b/module/project/lang/en.php @@ -326,8 +326,6 @@ $lang->project->featureBar['bug']['unresolved'] = 'Unresolved'; $app->loadLang('testcase'); $lang->project->featureBar['testcase'] = $lang->testcase->featureBar['browse']; -$lang->project->featureBar['testtask']['all'] = 'All'; - $lang->project->featureBar['build']['all'] = 'Build List'; $lang->project->featureBar['group']['all'] = 'All Groups'; diff --git a/module/project/lang/fr.php b/module/project/lang/fr.php index 606e3e7707..632deb956d 100644 --- a/module/project/lang/fr.php +++ b/module/project/lang/fr.php @@ -326,8 +326,6 @@ $lang->project->featureBar['bug']['unresolved'] = 'Unresolved'; $app->loadLang('testcase'); $lang->project->featureBar['testcase'] = $lang->testcase->featureBar['browse']; -$lang->project->featureBar['testtask']['all'] = 'All'; - $lang->project->featureBar['build']['all'] = 'Build List'; $lang->project->featureBar['group']['all'] = 'All Groups'; diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index 6eda2a1167..b3cdade820 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -326,8 +326,6 @@ $lang->project->featureBar['bug']['unresolved'] = '未解决'; $app->loadLang('testcase'); $lang->project->featureBar['testcase'] = $lang->testcase->featureBar['browse']; -$lang->project->featureBar['testtask']['all'] = '全部'; - $lang->project->featureBar['build']['all'] = '全部版本'; $lang->project->featureBar['group']['all'] = '浏览分组'; diff --git a/module/project/ui/testtask.html.php b/module/project/ui/testtask.html.php index 9fac1f9a3e..8274b3c809 100644 --- a/module/project/ui/testtask.html.php +++ b/module/project/ui/testtask.html.php @@ -10,24 +10,18 @@ declare(strict_types=1); */ namespace zin; -/* Compute summary. */ -$waitCount = 0; -$testingCount = 0; -$blockedCount = 0; -$doneCount = 0; -foreach($tasks as $task) -{ - if($task->status == 'wait') $waitCount ++; - if($task->status == 'doing') $testingCount ++; - if($task->status == 'blocked') $blockedCount ++; - if($task->status == 'done') $doneCount ++; - if($task->build == 'trunk' || empty($task->buildName)) $task->buildName = $this->lang->trunk; -} - +jsVar('allTasks', $lang->testtask->allTasks); featureBar ( - set::current('all'), - set::linkParams("projectID={$project->id}") + li + ( + setClass('nav-item'), + a + ( + set('class', 'active'), + $lang->testtask->browse + ) + ) ); toolbar @@ -45,19 +39,21 @@ toolbar unset($config->testtask->dtable->fieldList['product']); unset($config->testtask->dtable->fieldList['execution']); -$tasks = initTableData($tasks, $config->testtask->dtable->fieldList, $this->testtask); -$cols = array_values($config->testtask->dtable->fieldList); -$data = array_values($tasks); -$footerHTML = sprintf($lang->testtask->allSummary, count($tasks), $waitCount, $testingCount, $blockedCount, $doneCount); +$tasks = initTableData($tasks, $config->project->dtable->testtask->fieldList); +$summary = sprintf($lang->testtask->allSummary, count($tasks), $waitCount, $testingCount, $blockedCount, $doneCount); dtable ( - set::cols($cols), - set::data($data), + set::id('taskTable'), + set::cols($config->project->dtable->testtask->fieldList), + set::data($tasks), + set::onRenderCell(jsRaw('window.onRenderCell')), set::userMap($users), - set::fixedLeftWidth('20%'), set::orderBy($orderBy), set::sortLink(createLink('project', 'testtask', "projectID={$project->id}&orderBy={name}_{sortType}&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}")), - set::footer(array(array('html' => $footerHTML), 'flex', 'pager')), + set::plugins(array('cellspan')), + set::getCellSpan(jsRaw('window.getCellSpan')), + set::fixedLeftWidth('20%'), + set::footer(array(array('html' => $summary), 'flex', 'pager')), set::footPager(usePager()), ); diff --git a/module/project/zen.php b/module/project/zen.php index 96daf61661..83b2e07a38 100644 --- a/module/project/zen.php +++ b/module/project/zen.php @@ -1519,4 +1519,48 @@ class projectZen extends project return $executionIdList; } + + /** + * 展示测试单的相关变量。 + * Show the testtask related variables. + * + * @param array $tasks + * @access protected + * @return void + */ + protected function assignTesttaskVars(array $tasks): void + { + /* Compute rowspan. */ + $productGroup = array(); + $waitCount = 0; + $testingCount = 0; + $blockedCount = 0; + $doneCount = 0; + foreach($tasks as $task) + { + $productGroup[$task->product][] = $task; + if($task->status == 'wait') $waitCount ++; + if($task->status == 'doing') $testingCount ++; + if($task->status == 'blocked') $blockedCount ++; + if($task->status == 'done') $doneCount ++; + if($task->build == 'trunk' || empty($task->buildName)) $task->buildName = $this->lang->trunk; + } + + $lastProduct = ''; + foreach($tasks as $taskID => $task) + { + $task->rowspan = 0; + if($lastProduct !== $task->product) + { + $lastProduct = $task->product; + if(!empty($productGroup[$task->product])) $task->rowspan = count($productGroup[$task->product]); + } + } + + $this->view->waitCount = $waitCount; + $this->view->testingCount = $testingCount; + $this->view->blockedCount = $blockedCount; + $this->view->doneCount = $doneCount; + $this->view->tasks = $tasks; + } }