From 1bf5b045f41aca4cf7b5ada297d9dd518f6cabe4 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Fri, 10 Nov 2023 15:39:36 +0800 Subject: [PATCH] * Adjust execution-taskkanban style. --- module/bug/zen.php | 2 +- module/execution/control.php | 2 - module/execution/css/taskkanban.ui.css | 4 + module/execution/js/taskkanban.ui.js | 90 +++++++++++++++++---- module/execution/ui/taskkanban.html.php | 100 ++++++++++++------------ module/kanban/lang/de.php | 6 +- module/kanban/lang/en.php | 6 +- module/kanban/lang/fr.php | 6 +- module/kanban/lang/zh-cn.php | 6 +- module/kanban/model.php | 4 +- 10 files changed, 147 insertions(+), 79 deletions(-) create mode 100644 module/execution/css/taskkanban.ui.css diff --git a/module/bug/zen.php b/module/bug/zen.php index 68b1e7c1d7..14f6927d22 100644 --- a/module/bug/zen.php +++ b/module/bug/zen.php @@ -1371,7 +1371,7 @@ class bugZen extends bug $this->view->builds = $builds; $this->view->branch = $branch; $this->view->branches = $branches; - $this->view->moduleOptionMenu = $this->tree->getOptionMenu($product->id, 'bug', 0, $branch === 'all' ? 0 : $branch); + $this->view->moduleOptionMenu = $this->tree->getOptionMenu($product->id, 'bug', 0, $branch === 'all' ? 0 : (int)$branch); } /** diff --git a/module/execution/control.php b/module/execution/control.php index 40b907ce8e..efaeec33a1 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -2872,8 +2872,6 @@ class execution extends control */ public function importPlanStories(int $executionID, int $planID, int $productID = 0, string $extra = '') { - if($_SERVER['REQUEST_METHOD'] !== 'POST') return $this->sendError($this->lang->error->unsupportedReq); - $execution = $this->dao->findById($executionID)->from(TABLE_EXECUTION)->fetch(); $planStories = array(); $planStory = $this->loadModel('story')->getPlanStories($planID); diff --git a/module/execution/css/taskkanban.ui.css b/module/execution/css/taskkanban.ui.css new file mode 100644 index 0000000000..62869cf8a9 --- /dev/null +++ b/module/execution/css/taskkanban.ui.css @@ -0,0 +1,4 @@ +.toolbar .btn-link{color: unset; text-decoration-line: unset;} +.toolbar .kanbanSetting.btn-link .caret{display: none;} +.dropdown-menu .menu-divider a{display:none;} +.dropdown-menu .menu-divider {border-top:1px solid #dedede;} diff --git a/module/execution/js/taskkanban.ui.js b/module/execution/js/taskkanban.ui.js index bb285b3d78..149a0c1b13 100644 --- a/module/execution/js/taskkanban.ui.js +++ b/module/execution/js/taskkanban.ui.js @@ -1,4 +1,4 @@ -window.kanbanDropRules = +const kanbanDropRules = { story: { @@ -28,7 +28,52 @@ window.kanbanDropRules = 'canceled': ['developing', 'closed'], 'closed': ['developing'], } -} +}; + +window.changeBrowseType = function() +{ + const type = $('.c-type [name=type]').val(); + loadPage($.createLink('execution', 'taskKanban', "executionID=" + executionID + '&type=' + type)); +}; + +window.changeGroupBy = function() +{ + const troup = $('.c-group [name=group]').val(); + const type = $('.c-type [name=type]').val(); + loadPage($.createLink('execution', 'taskKanban', 'executionID=' + executionID + '&type=' + type + '&orderBy=order_asc' + '&groupBy=' + group)); +}; + +window.changeBugProduct = function() +{ + const productID = $('[name=productName]').val(); + if(productID) $('#batchCreateBugButton').attr('href', $.createLink('bug', 'batchCreate', 'productID=' + productID + '&branch=&executionID=' + executionID)); +}; + +window.linkPlanStory = function() +{ + const planID = $('[name=plan]').val(); + if(planID) + { + var param = "¶m=executionID=" + executionID + ",browseType=" + browseType + ",orderBy=id_asc,groupBy=" + groupBy; + $.ajaxSubmit({url: $.createLink('execution', 'importPlanStories', 'executionID=' + executionID + '&planID=' + planID + '&productID=0&fromMethod=taskKanban&extra=' + param)}); + } +}; + +window.toggleSearchBox = function() +{ + $('#taskKanbanSearch').toggle(); + + if($('#taskKanbanSearch').css('display') == 'block') + { + $(".querybox-toggle").css("color", "#0c64eb"); + } + else + { + $(".querybox-toggle").css("color", "#3c495c"); + $('#taskKanbanSearchInput').attr('value', ''); + searchCards(''); + } +}; window.getLane = function(lane) { @@ -226,9 +271,6 @@ window.buildCardActions = function(item) window.canDrop = function(dragInfo, dropInfo) { - console.log(dragInfo); - console.log(dropInfo); - return true; if(!dragInfo) return false; const column = this.getCol(dropInfo.col); @@ -239,11 +281,6 @@ window.canDrop = function(dragInfo, dropInfo) /* 卡片可在同组内拖动。 */ if(dragInfo.item.group != column.group) return false; - - let kanbanRules = window.kanbanDropRules[lane.type]; - let colRules = typeof kanbanRules[colPairs[dragInfo.col]] == 'undefined' ? null : kanbanRules[colPairs[dragInfo.col]]; - if(!colRules) return false; - return true; } window.onDrop = function(changes, dropInfo) @@ -259,6 +296,11 @@ window.onDrop = function(changes, dropInfo) const toColType = colPairs[toColID]; const objectID = dropInfo.drag.item.id; + let kanbanRules = kanbanDropRules[laneType]; + let colRules = typeof kanbanRules[fromColType] == 'undefined' ? null : kanbanRules[fromColType]; + if(!colRules) return false; + if(!colRules.includes(toColType)) return false; + let link = ''; let moveCard = false; @@ -308,18 +350,25 @@ window.onDrop = function(changes, dropInfo) if(data) { data = $.parseJSON(data); - if(data.status == 'draft' || data.status == 'changing' || data.status == 'reviewing') return zui.Modal.alert(executionLang.storyDragError); - return ajaxMoveCard(objectID, fromColID, toColID, fromLaneID, toLaneID); + if(data.status == 'draft' || data.status == 'changing' || data.status == 'reviewing') + { + zui.Modal.alert(executionLang.storyDragError); + return false; + } + ajaxMoveCard(objectID, fromColID, toColID, fromLaneID, toLaneID); + return false; } }); } else if(!link) { - return ajaxMoveCard(objectID, fromColID, toColID, fromLaneID, toLaneID); + ajaxMoveCard(objectID, fromColID, toColID, fromLaneID, toLaneID); + return false; } } if(link) zui.Modal.open({url: link}); + return false; } function formatDate(inputDate) @@ -416,8 +465,21 @@ window.hideAllAction = function() * @access public * @return void */ -function ajaxMoveCard(objectID, fromColID, toColID, fromLaneID, toLaneID) +window.ajaxMoveCard = function(objectID, fromColID, toColID, fromLaneID, toLaneID) { var link = $.createLink('kanban', 'ajaxMoveCard', 'cardID=' + objectID + '&fromColID=' + fromColID + '&toColID=' + toColID + '&fromLaneID=' + fromLaneID + '&toLaneID=' + toLaneID + '&execitionID=' + executionID + '&browseType=' + browseType + '&groupBy=' + groupBy); $.get(link, function(data){ loadCurrentPage() }); } + +window.searchCards = function(value, order) +{ + const $kanbanList = $('[data-zui-kanbanlist]').zui('kanbanList'); + const options = $kanbanList.options; + const searchValue = value; + if(typeof order == 'undefined') order = orderBy; + $.get($.createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=0&browseType=" + browseType + "&groupBy=" + groupBy + '&from=execution&searchValue=' + value + '&orderBy=' + order), function(data) + { + options.items = $.parseJSON(data); + $kanbanList.render(options); + }); +} diff --git a/module/execution/ui/taskkanban.html.php b/module/execution/ui/taskkanban.html.php index 06149170aa..6fcb3072a1 100644 --- a/module/execution/ui/taskkanban.html.php +++ b/module/execution/ui/taskkanban.html.php @@ -68,7 +68,6 @@ jsVar('kanbanList', array_keys($kanbanGroup)); jsVar('browseType', $browseType); jsVar('groupBy', $groupBy); jsVar('productNum', $productNum); -jsVar('searchValue', ''); jsVar('priv', array( 'canEditName' => common::hasPriv('kanban', 'setColumn'), 'canSetWIP' => common::hasPriv('kanban', 'setWIP'), @@ -128,14 +127,18 @@ row setClass('items-center justify-between mb-3'), cell ( + setClass('flex'), $features['qa'] ? inputControl ( setClass('c-type'), picker ( + set::width('200'), set::name('type'), set::items($lang->kanban->type), set::value($browseType), + set::require(true), + set::onchange('changeBrowseType()'), ) ) : null, $browseType != 'all' ? inputControl @@ -143,17 +146,21 @@ row setClass('c-group'), picker ( + set::width('200'), set::name('group'), set::items($lang->kanban->group->$browseType), set::value($groupBy), + set::require(true), + set::onchange('changeGroupBy()'), ) ) : null, ), cell ( - setClass('flex'), + setClass('flex toolbar'), inputGroup ( + set::style(array('display' => 'none')), setID('taskKanbanSearch'), inputControl ( @@ -168,13 +175,13 @@ row ) ) ), - btn(setClass('querybox-toggle'), set::onclick('toggleSearchBox()'), set::icon('search'), $lang->searchAB), - common::hasPriv('task', 'export') ? btn(set::url(createLink('task', 'export', "execution=$executionID&orderBy=$orderBy&type=unclosed")), set::icon('export'), set('data-toggle', 'modal'), $lang->export) : null, + btn(setClass('querybox-toggle'), set::type('link'), set::onclick('toggleSearchBox()'), set::icon('search'), $lang->searchAB), + common::hasPriv('task', 'export') ? btn(set::type('link'), set::url(createLink('task', 'export', "execution=$executionID&orderBy=$orderBy&type=unclosed")), set::icon('export'), set('data-toggle', 'modal'), $lang->export) : null, $canBeChanged ? dropdown ( setID('importAction'), set::arrow(true), - btn(set::icon('import'), $lang->import), + btn(set::type('link'), set::icon('import'), $lang->import), set::items(array ( common::hasPriv('execution', 'importTask') ? array('text' => $lang->execution->importTask, 'url' => createLink('execution', 'importTask', "execution=$execution->id")) : null, @@ -183,28 +190,28 @@ row ) : null, dropdown ( - btn(icon('ellipsis-v')), + setClass('kanbanSetting mr-2'), + btn(set::type('link'), icon('ellipsis-v')), set::items(array ( common::hasPriv('execution', 'setKanban') ? array('text' => $lang->execution->setKanban, 'url' => createLink('execution', 'setKanban', "executionID=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'sm') : null, common::hasPriv('execution', 'printKanban') ? array('text' => $lang->execution->printKanban, 'url' => createLink('execution', 'printKanban', "executionID=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'sm', 'id' => 'printKanban') : null, - array('text' => $lang->execution->fullScreen, 'url' => 'javascript:fullScreen()', 'data-toggle' => 'modal', 'data-size' => 'sm'), + array('text' => $lang->execution->fullScreen, 'url' => 'javascript:fullScreen()'), )), - set::arrow(false), ), $canCreateObject ? dropdown ( setID('createDropdown'), - btn(set::icon('plus'), $lang->create), + btn(setClass('primary'),set::icon('plus'), $lang->create), set::items(array ( ($features['story'] and $hasStoryButton and $canCreateStory) ? array('text' => $lang->execution->createStory, 'url' => createLink('story', 'create', "productID=$productID&branch=0&moduleID=0&story=0&execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null, ($features['story'] and $hasStoryButton and $canBatchCreateStory) ? array('text' => $lang->execution->batchCreateStory, 'url' => createLink('story', 'batchCreate', "productID=$productID&branch=0&moduleID=0&story=0&execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null, ($features['story'] and $hasStoryButton and $canLinkStory) ? array('text' => $lang->execution->linkStory, 'url' => createLink('story', 'linkStory', "execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null, ($features['story'] and $hasStoryButton and $canLinkStoryByPlan) ? array('text' => $lang->execution->linkStoryByPlan, 'url' => '#linkStoryByPlan', 'data-toggle' => 'modal') : null, - ($features['story'] and $hasStoryButton and $features['qa']) ? array('text' => '', 'class' => 'menu-divider') : null, + ($features['story'] and $hasStoryButton and $features['qa']) ? array('class' => 'menu-divider') : null, ($features['qa'] && $canCreateBug) ? array('text' => $lang->bug->create, 'url' => createLink('bug', 'create', "productID=$productID&branch=0&extra=executionID=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null, - ($features['qa'] && $canBatchCreateBug) ? array('text' => $lang->bug->create, 'url' => ($productNum > 1 ? '#batchCreateBug' : createLink('bug', 'create', "productID=$productID&branch=0&extra=executionID=$execution->id")), 'data-toggle' => 'modal', $productNum > 1 ? null : 'data-size' => 'lg') : null, + ($features['qa'] && $canBatchCreateBug) ? array('text' => $lang->bug->batchCreate, 'url' => ($productNum >= 1 ? '#batchCreateBug' : createLink('bug', 'batchCreate', "productID=$productID&branch=0&executionID=$execution->id")), 'data-toggle' => 'modal', $productNum > 1 ? null : 'data-size' => 'lg') : null, ($features['qa'] && $canImportBug) ? array('text' => $lang->execution->importBug, 'url' => createLink('execution', 'importBug', "execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null, ($features['story'] and $hasStoryButton and $features['qa']) ? array('text' => '', 'class' => 'menu-divider') : null, ($canCreateTask) ? array('text' => $lang->task->create, 'url' => createLink('task', 'create', "execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null, @@ -216,6 +223,7 @@ row div ( + set::id('kanbanList'), setClass('bg-white'), zui::kanbanList ( @@ -233,21 +241,20 @@ modal h4($lang->execution->linkStoryByPlan), "({$lang->execution->linkStoryByPlanTips})", ), - div + inputGroup ( - inputGroup + setClass('mt-1'), + picker ( - picker - ( - setID('plan'), - set::name('plan'), - set::items($allPlans), - ), - span - ( - setClass('input-group-btn'), - btn(setClass('primary'), setID('toStoryButton'), $lang->execution->linkStory) - ) + set::width(200), + setID('plan'), + set::name('plan'), + set::items($allPlans), + ), + span + ( + setClass('input-group-btn'), + btn(setClass('primary'), setID('toStoryButton'), set::onclick('linkPlanStory()'), $lang->execution->linkStory) ) ) ); @@ -255,36 +262,33 @@ modal modal ( setID('batchCreateBug'), - set::header($lang->bug->product), - div + set::title($lang->bug->product), + inputGroup ( - inputGroup + setClass('mt-3'), + picker ( - picker + set::width(200), + setID('product'), + set::name('productName'), + set::items($productNames), + set::onchange('changeBugProduct()'), + ), + span + ( + setClass('input-group-btn'), + btn ( - setID('product'), - set::name('productName'), - set::items($productNames), - ), - span - ( - setClass('input-group-btn'), - btn - ( - setClass('primary'), - setID('batchCreateBugButton'), - set::url(createLink('bug', 'batchCreate', 'productID=' . key($productNames) . '&branch=&executionID=' . $executionID)), - set('data-toggle', 'modal'), - set('data-dismiss', 'modal'), - set('data-size', 'lg'), - $lang->bug->batchCreate - ) + setClass('primary'), + setID('batchCreateBugButton'), + set::url(createLink('bug', 'batchCreate', 'productID=' . key($productNames) . '&branch=&executionID=' . $executionID)), + set('data-toggle', 'modal'), + set('data-dismiss', 'modal'), + set('data-size', 'lg'), + $lang->bug->batchCreate ) ) ) ); -modal(setID('actionModal')); - render(); - diff --git a/module/kanban/lang/de.php b/module/kanban/lang/de.php index bf0bd44c39..203bbe1bec 100644 --- a/module/kanban/lang/de.php +++ b/module/kanban/lang/de.php @@ -156,7 +156,7 @@ $lang->kanban->group = new stdclass(); $lang->kanban->group->all = array(); $lang->kanban->group->story = array(); -$lang->kanban->group->story['default'] = "Default"; +$lang->kanban->group->story['default'] = "Default Group"; $lang->kanban->group->story['pri'] = "Story Priority"; $lang->kanban->group->story['category'] = "Story Category"; $lang->kanban->group->story['module'] = "Story Module"; @@ -164,7 +164,7 @@ $lang->kanban->group->story['source'] = "Story Source"; $lang->kanban->group->story['assignedTo'] = "Assigned To"; $lang->kanban->group->task = array(); -$lang->kanban->group->task['default'] = "Default"; +$lang->kanban->group->task['default'] = "Default Group"; $lang->kanban->group->task['pri'] = "Task Priority"; $lang->kanban->group->task['type'] = "Task Type"; $lang->kanban->group->task['module'] = "Task Module"; @@ -172,7 +172,7 @@ $lang->kanban->group->task['assignedTo'] = "Assigned To"; $lang->kanban->group->task['story'] = "Story"; $lang->kanban->group->bug = array(); -$lang->kanban->group->bug['default'] = "Default"; +$lang->kanban->group->bug['default'] = "Default Group"; $lang->kanban->group->bug['pri'] = "Bug Priority"; $lang->kanban->group->bug['severity'] = "Bug Severity"; $lang->kanban->group->bug['module'] = "Bug Module"; diff --git a/module/kanban/lang/en.php b/module/kanban/lang/en.php index 7320164820..49f30cbb04 100644 --- a/module/kanban/lang/en.php +++ b/module/kanban/lang/en.php @@ -156,7 +156,7 @@ $lang->kanban->group = new stdclass(); $lang->kanban->group->all = array(); $lang->kanban->group->story = array(); -$lang->kanban->group->story['default'] = "Default"; +$lang->kanban->group->story['default'] = "Default Group"; $lang->kanban->group->story['pri'] = "Story Priority"; $lang->kanban->group->story['category'] = "Story Category"; $lang->kanban->group->story['module'] = "Story Module"; @@ -164,7 +164,7 @@ $lang->kanban->group->story['source'] = "Story Source"; $lang->kanban->group->story['assignedTo'] = "Assigned To"; $lang->kanban->group->task = array(); -$lang->kanban->group->task['default'] = "Default"; +$lang->kanban->group->task['default'] = "Default Group"; $lang->kanban->group->task['pri'] = "Task Priority"; $lang->kanban->group->task['type'] = "Task Type"; $lang->kanban->group->task['module'] = "Task Module"; @@ -172,7 +172,7 @@ $lang->kanban->group->task['assignedTo'] = "Assigned To"; $lang->kanban->group->task['story'] = "Story"; $lang->kanban->group->bug = array(); -$lang->kanban->group->bug['default'] = "Default"; +$lang->kanban->group->bug['default'] = "Default Group"; $lang->kanban->group->bug['pri'] = "Bug Priority"; $lang->kanban->group->bug['severity'] = "Bug Severity"; $lang->kanban->group->bug['module'] = "Bug Module"; diff --git a/module/kanban/lang/fr.php b/module/kanban/lang/fr.php index 9d32bb5f79..cf206af624 100644 --- a/module/kanban/lang/fr.php +++ b/module/kanban/lang/fr.php @@ -156,7 +156,7 @@ $lang->kanban->group = new stdclass(); $lang->kanban->group->all = array(); $lang->kanban->group->story = array(); -$lang->kanban->group->story['default'] = "Default"; +$lang->kanban->group->story['default'] = "Default Group"; $lang->kanban->group->story['pri'] = "Story Priority"; $lang->kanban->group->story['category'] = "Story Category"; $lang->kanban->group->story['module'] = "Story Module"; @@ -164,7 +164,7 @@ $lang->kanban->group->story['source'] = "Story Source"; $lang->kanban->group->story['assignedTo'] = "Assigned To"; $lang->kanban->group->task = array(); -$lang->kanban->group->task['default'] = "Default"; +$lang->kanban->group->task['default'] = "Default Group"; $lang->kanban->group->task['pri'] = "Task Priority"; $lang->kanban->group->task['type'] = "Task Type"; $lang->kanban->group->task['module'] = "Task Module"; @@ -172,7 +172,7 @@ $lang->kanban->group->task['assignedTo'] = "Assigned To"; $lang->kanban->group->task['story'] = "Story"; $lang->kanban->group->bug = array(); -$lang->kanban->group->bug['default'] = "Default"; +$lang->kanban->group->bug['default'] = "Default Group"; $lang->kanban->group->bug['pri'] = "Bug Priority"; $lang->kanban->group->bug['severity'] = "Bug Severity"; $lang->kanban->group->bug['module'] = "Bug Module"; diff --git a/module/kanban/lang/zh-cn.php b/module/kanban/lang/zh-cn.php index bfa9b192f0..f5d0dd7796 100644 --- a/module/kanban/lang/zh-cn.php +++ b/module/kanban/lang/zh-cn.php @@ -156,7 +156,7 @@ $lang->kanban->group = new stdclass(); $lang->kanban->group->all = array(); $lang->kanban->group->story = array(); -$lang->kanban->group->story['default'] = "默认方式"; +$lang->kanban->group->story['default'] = "默认分组"; $lang->kanban->group->story['pri'] = "需求优先级"; $lang->kanban->group->story['category'] = "需求类别"; $lang->kanban->group->story['module'] = "需求模块"; @@ -164,7 +164,7 @@ $lang->kanban->group->story['source'] = "需求来源"; $lang->kanban->group->story['assignedTo'] = "指派人员"; $lang->kanban->group->task = array(); -$lang->kanban->group->task['default'] = "默认方式"; +$lang->kanban->group->task['default'] = "默认分组"; $lang->kanban->group->task['pri'] = "任务优先级"; $lang->kanban->group->task['type'] = "任务类型"; $lang->kanban->group->task['module'] = "任务所属模块"; @@ -172,7 +172,7 @@ $lang->kanban->group->task['assignedTo'] = "指派人员"; $lang->kanban->group->task['story'] = "{$lang->SRCommon}"; $lang->kanban->group->bug = array(); -$lang->kanban->group->bug['default'] = "默认方式"; +$lang->kanban->group->bug['default'] = "默认分组"; $lang->kanban->group->bug['pri'] = "Bug优先级"; $lang->kanban->group->bug['severity'] = "Bug严重程度"; $lang->kanban->group->bug['module'] = "Bug模块"; diff --git a/module/kanban/model.php b/module/kanban/model.php index a6f58fb6b4..fb1757d873 100755 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1579,7 +1579,7 @@ class kanbanModel extends model if(empty($lanes)) return array(); - foreach($lanes as $lane) $this->refreshCards($lane); + foreach($lanes as $lane) $this->refreshCards((array)$lane); $columns = $this->dao->select('t1.cards, t1.lane, t2.id, t2.type, t2.name, t2.color, t2.limit, t2.parent')->from(TABLE_KANBANCELL)->alias('t1') ->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.column = t2.id') @@ -2985,7 +2985,7 @@ class kanbanModel extends model ->fetchAll('id'); } - foreach($lanes as $lane) $this->refreshCards($lane); + foreach($lanes as $lane) $this->refreshCards((array)$lane); } /**