diff --git a/db/update15.7.sql b/db/update15.7.sql index 6f0f50c608..a45191525f 100644 --- a/db/update15.7.sql +++ b/db/update15.7.sql @@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS `zt_kanbanlane` ( `id` int(8) NOT NULL AUTO_INCREMENT, `execution` mediumint(8) NOT NULL DEFAULT '0', `type` char(30) NOT NULL, + `groupby` char(30) NOT NULL, `extra` char(30) NOT NULL, `name` varchar(255) NOT NULL DEFAULT '', `color` char(30) NOT NULL, diff --git a/db/zentao.sql b/db/zentao.sql index 91efb3fcce..60f013c5d7 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -600,6 +600,7 @@ CREATE TABLE IF NOT EXISTS `zt_kanbanlane` ( `id` int(8) NOT NULL AUTO_INCREMENT, `execution` mediumint(8) NOT NULL DEFAULT '0', `type` char(30) NOT NULL, + `groupby` char(30) NOT NULL, `extra` char(30) NOT NULL, `name` varchar(255) NOT NULL DEFAULT '', `color` char(30) NOT NULL, diff --git a/module/bug/control.php b/module/bug/control.php index 9a34399db4..e53565f090 100644 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -649,6 +649,9 @@ class bug extends control } setcookie('bugModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false); + + /* If link from no head then reload. */ + if(isonlybody()) die(js::reload('parent.parent')); die(js::locate($this->createLink('bug', 'browse', "productID={$productID}&branch=$branch&browseType=unclosed¶m=0&orderBy=id_desc"), 'parent')); } diff --git a/module/common/lang/en.php b/module/common/lang/en.php index 99a8a185da..84156def3d 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -136,6 +136,7 @@ $lang->program->common = 'Program'; $lang->product->common = 'Product'; $lang->project->common = 'Project'; $lang->execution->common = $config->systemMode == 'new' ? 'Execution' : $lang->executionCommon; +$lang->kanban->common = 'Kanban'; $lang->qa->common = 'QA'; $lang->devops->common = 'DevOps'; $lang->doc->common = 'Doc'; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 077ff2857b..97ba7d7763 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -136,6 +136,7 @@ $lang->program->common = '项目集'; $lang->product->common = '产品'; $lang->project->common = '项目'; $lang->execution->common = $config->systemMode == 'new' ? '执行' : $lang->executionCommon; +$lang->kanban->common = '看板'; $lang->qa->common = '测试'; $lang->devops->common = 'DevOps'; $lang->doc->common = '文档'; diff --git a/module/execution/control.php b/module/execution/control.php index 054bb6656f..afe476ae0f 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1838,14 +1838,19 @@ class execution extends control $this->app->session->set('taskList', $uri, 'execution'); $this->app->session->set('bugList', $uri, 'qa'); + /* Load language. */ + $this->app->loadLang('story'); + $this->app->loadLang('task'); + $this->app->loadLang('bug'); + /* Compatibility IE8. */ if(strpos($this->server->http_user_agent, 'MSIE 8.0') !== false) header("X-UA-Compatible: IE=EmulateIE7"); - $kanbanGroup = $this->loadModel('kanban')->getExecutionKanban($executionID, $browseType); + $kanbanGroup = $this->loadModel('kanban')->getExecutionKanban($executionID, $browseType, $groupBy); if(empty($kanbanGroup)) { $this->kanban->createLanes($executionID, $browseType, $groupBy); - $kanbanGroup = $this->kanban->getExecutionKanban($executionID, $browseType); + $kanbanGroup = $this->kanban->getExecutionKanban($executionID, $browseType, $groupBy); } $this->execution->setMenu($executionID); @@ -2404,6 +2409,8 @@ class execution extends control { $this->execution->linkStory($objectID); if($object->type != 'project' and $object->project != 0) $this->execution->linkStory($object->project); + + if(isonlybody()) die(js::reload('parent')); die(js::locate($browseLink)); } @@ -3120,13 +3127,14 @@ class execution extends control /** * Import stories by plan. * - * @param int $executionID - * @param int $planID - * @param int $productID + * @param int $executionID + * @param int $planID + * @param int $productID + * @param string $fromMethod * @access public * @return void */ - public function importPlanStories($executionID, $planID, $productID = 0) + public function importPlanStories($executionID, $planID, $productID = 0, $fromMethod = 'story') { $planStories = $planProducts = array(); $planStory = $this->loadModel('story')->getPlanStories($planID); @@ -3161,7 +3169,7 @@ class execution extends control $param = "projectID=$executionID"; } if($count != 0) echo js::alert(sprintf($this->lang->execution->haveDraft, $count)) . js::locate($this->createLink($moduleName, 'story', $param)); - die(js::locate(helper::createLink($moduleName, 'story', $param), 'parent')); + die(js::locate(helper::createLink($moduleName, $fromMethod, $param))); } /** diff --git a/module/execution/css/kanban.css b/module/execution/css/kanban.css index a04ce818c5..cef2290d04 100644 --- a/module/execution/css/kanban.css +++ b/module/execution/css/kanban.css @@ -31,4 +31,5 @@ .dropdown-menu a {text-align: left;} .scrollbar-hover {max-height: 2000px; overflow: scroll !important;} -.c-type, .c-group {width: 150px !important; overflow: unset; display: "";} +.c-type, .c-group {width: 150px !important; overflow: unset;} +.c-type {margin-left: 0px !important;} diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js index a1d92554ae..1ef11785f7 100644 --- a/module/execution/js/kanban.js +++ b/module/execution/js/kanban.js @@ -219,7 +219,12 @@ function renderHeaderCol($col, col, $header, kanban) if(!$col.children('.actions').length) { var $actions = $('
'); - if(col.type === 'backlog' || col.type === 'wait' || col.type == 'unconfirmed') + var printStoryButton = printTaskButton = printBugButton = false; + if(priv.canCreateStory || priv.canBatchCreateStory || priv.canLinkStory || priv.canLinkStoryByPlane) printStoryButton = true; + if(priv.canCreateTask || priv.canBatchCreateTask) printTaskButton = true; + if(priv.canCreateBug || priv.canBatchCreateBug) printBugButton = true; + + if((col.type === 'backlog' && printStoryButton) || (col.type === 'wait' && printTaskButton) || (col.type == 'unconfirmed' && printBugButton)) { $actions.append([ '', @@ -227,11 +232,12 @@ function renderHeaderCol($col, col, $header, kanban) '' ].join('')); } + $actions.append([ - '', - '', - '' - ].join('')); + '', + '', + '' + ].join('')); $actions.appendTo($col); } } @@ -491,8 +497,8 @@ function createColumnMenu(options) var kanbanID = options.kanban; var items = []; - if(priv.hasEditName) items.push({label: executionLang.editName, url: $.createLink('kanban', 'setColumn', 'col=' + col.columnID + '&executionID=' + executionID), className: 'iframe'}) - if(priv.hasSetWIP) items.push({label: executionLang.setWIP, url: $.createLink('kanban', 'setWIP', 'col=' + col.columnID + '&executionID=' + executionID), className: 'iframe'}) + if(priv.hasEditName) items.push({label: executionLang.editName, url: $.createLink('kanban', 'setColumn', 'col=' + col.columnID + '&executionID=' + executionID), className: 'iframe', attrs: {'data-width': '500px'}}) + if(priv.hasSetWIP) items.push({label: executionLang.setWIP, url: $.createLink('kanban', 'setWIP', 'col=' + col.columnID + '&executionID=' + executionID), className: 'iframe', attrs: {'data-width': '500px'}}) items.push({label: executionLang.sortColumn, items: ['按ID倒序', '按ID顺序'], className: 'iframe', onClick: handleSortColCards}) return items; } @@ -509,20 +515,20 @@ function createColumnCreateMenu(options) if(col.laneType == 'story') { - if(priv.canCreateStory) items.push({label: storyLang.create, url: $.createLink('story', 'create', 'productID=' + productID)}); - if(priv.canBatchCreateStory) items.push({label: storyLang.batchCreate, url: $.createLink('story', 'batchcreate', 'productID=' + productID)}); - if(priv.canLinkStory) items.push({label: executionLang.linkStory, url: $.createLink('execution', 'linkStory', 'executionID=' + executionID)}); + if(priv.canCreateStory) items.push({label: storyLang.create, url: $.createLink('story', 'create', 'productID=' + productID, '', true), className: 'iframe'}); + if(priv.canBatchCreateStory) items.push({label: storyLang.batchCreate, url: $.createLink('story', 'batchcreate', 'productID=' + productID + '&branch=0&moduleID=0&storyID=0&executionID=' + executionID, '', true), className: 'iframe'}); + if(priv.canLinkStory) items.push({label: executionLang.linkStory, url: $.createLink('execution', 'linkStory', 'executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-width': '85%'}}); if(priv.canLinkStoryByPlane) items.push({label: executionLang.linkStoryByPlan, url: '#linkStoryByPlan', 'attrs' : {'data-toggle': 'modal'}}); } else if(col.laneType == 'bug') { - if(priv.canCreateBug) items.push({label: bugLang.create, url: $.createLink('bug', 'create', 'productID=0&moduleID=0&extra=executionID=' + executionID)}); - if(priv.canBatchCreateBug) items.push({label: bugLang.batchCreate, url: $.createLink('bug', 'batchcreate', 'productID=' + productID + '&moduleID=0&executionID=' + executionID)}); + if(priv.canCreateBug) items.push({label: bugLang.create, url: $.createLink('bug', 'create', 'productID=0&moduleID=0&extra=executionID=' + executionID, '', true), className: 'iframe'}); + if(priv.canBatchCreateBug) items.push({label: bugLang.batchCreate, url: $.createLink('bug', 'batchcreate', 'productID=' + productID + '&moduleID=0&executionID=' + executionID, '', true), className: 'iframe'}); } else { - if(priv.canCreateTask) items.push({label: taskLang.create, url: $.createLink('task', 'create', 'executionID=' + executionID)}); - if(priv.canBatchCreateTask) items.push({label: taskLang.batchCreate, url: $.createLink('task', 'batchcreate', 'executionID=' + executionID)}); + if(priv.canCreateTask) items.push({label: taskLang.create, url: $.createLink('task', 'create', 'executionID=' + executionID, '', true), className: 'iframe'}); + if(priv.canBatchCreateTask) items.push({label: taskLang.batchCreate, url: $.createLink('task', 'batchcreate', 'executionID=' + executionID, '', true), className: 'iframe'}); } return items; } @@ -687,9 +693,9 @@ $(function() } /* Init iframe modals */ - $(document).on('click', '.iframe', function(event) + $(document).on('click', '#kanbans .iframe,.contextmenu-menu .iframe', function(event) { - $(this).modalTrigger({show: true, width: '500px'}); + $(this).modalTrigger({show: true}); event.preventDefault(); }); @@ -720,31 +726,15 @@ $(function() var planID = $('#plan').val(); if(planID) { - parent.location.href = createLink('execution', 'importPlanStories', 'executionID=' + executionID + '&planID=' + planID); + location.href = createLink('execution', 'importPlanStories', 'executionID=' + executionID + '&planID=' + planID + '&productID=0&fromMethod=kanban'); } }) }); -/** - * Hide group menu. - * - * @access public - * @return void - */ -function hideGroupMenu() -{ - var type = $('#type').val(); - if(type == 'all') $('.c-group').hide(); -} - $('#type').change(function() { var type = $('#type').val(); - if(type == 'all') - { - $('.c-group').hide(); - } - else + if(type != 'all') { $('.c-group').show(); $.get(createLink('execution', 'ajaxGetGroup', 'type=' + type), function(data) diff --git a/module/execution/view/kanban.html.php b/module/execution/view/kanban.html.php index 8090074870..0070919378 100644 --- a/module/execution/view/kanban.html.php +++ b/module/execution/view/kanban.html.php @@ -13,12 +13,13 @@