diff --git a/db/update18.1.sql b/db/update18.1.sql index feba83e887..ef6ffc263f 100644 --- a/db/update18.1.sql +++ b/db/update18.1.sql @@ -25,3 +25,6 @@ ALTER table `zt_reviewcl` ADD `type` varchar(255) NOT NULL DEFAULT '' AFTER `cat UPDATE `zt_reviewcl` SET `type` = 'waterfall' WHERE `type` = ''; UPDATE `zt_activity` SET `order` = `id` * 5 WHERE `order` = '0'; + +ALTER table `zt_cmcl` ADD `projectType` varchar(255) NOT NULL DEFAULT '' AFTER `type`; +UPDATE `zt_cmcl` SET `projectType` = 'waterfall' WHERE `projectType` = ''; diff --git a/db/zentao.sql b/db/zentao.sql index cad8faf602..9abe206715 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -9780,6 +9780,7 @@ CREATE TABLE IF NOT EXISTS `zt_reviewlist` ( CREATE TABLE IF NOT EXISTS `zt_cmcl` ( `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, `type` char(30) NOT NULL, + `projectType` varchar(255) NOT NULL, `title` int(11) NOT NULL, `contents` text NOT NULL, `assignedTo` varchar(30) NOT NULL, diff --git a/framework/helper.class.php b/framework/helper.class.php index 6435c7b69e..cb474da2c8 100644 --- a/framework/helper.class.php +++ b/framework/helper.class.php @@ -339,12 +339,12 @@ class helper extends baseHelper $dateInterval->hour = $interval->format('%H'); $dateInterval->minute = $interval->format('%i'); $dateInterval->secound = $interval->format('%s'); - $dateInterval->year = ltrim($dateInterval->year, '0'); - $dateInterval->month = ltrim($dateInterval->month, '0'); - $dateInterval->day = ltrim($dateInterval->day, '0'); - $dateInterval->hour = ltrim($dateInterval->hour, '0'); - $dateInterval->minute = ltrim($dateInterval->minute, '0'); - $dateInterval->secound = ltrim($dateInterval->secound, '0'); + $dateInterval->year = $dateInterval->year == '00' ? 0 : ltrim($dateInterval->year, '0'); + $dateInterval->month = $dateInterval->month == '00' ? 0 : ltrim($dateInterval->month, '0'); + $dateInterval->day = $dateInterval->day == '00' ? 0 : ltrim($dateInterval->day, '0'); + $dateInterval->hour = $dateInterval->hour == '00' ? 0 : ltrim($dateInterval->hour, '0'); + $dateInterval->minute = $dateInterval->minute == '00' ? 0 : ltrim($dateInterval->minute, '0'); + $dateInterval->secound = $dateInterval->secound == '00' ? 0 : ltrim($dateInterval->secound, '0'); } return $dateInterval; } diff --git a/module/compile/view/browse.html.php b/module/compile/view/browse.html.php index 28af0b3337..e04439c77f 100644 --- a/module/compile/view/browse.html.php +++ b/module/compile/view/browse.html.php @@ -14,8 +14,12 @@ diff --git a/module/custom/model.php b/module/custom/model.php index 7778cb03f3..112ced5617 100644 --- a/module/custom/model.php +++ b/module/custom/model.php @@ -1146,13 +1146,15 @@ class customModel extends model $disabledFeatures = $this->setting->getItem('owner=system&module=common§ion=&key=disabledFeatures'); $disabledFeatures = $disabledFeatures . ',' . $closedFeatures; - $hasWaterfall = strpos(",{$disabledFeatures},", ',waterfall,') === false; - $hasWaterfallPlus = strpos(",{$disabledFeatures},", ',waterfallplus,') === false; - $hasScrumMeasrecord = strpos(",{$disabledFeatures},", ',scrumMeasrecord,') === false; - $hasWaterfallMeasrecord = (strpos(",{$disabledFeatures},", ',waterfallMeasrecord,') === false and ($hasWaterfall or $hasWaterfallPlus)); + $hasWaterfall = strpos(",{$disabledFeatures},", ',waterfall,') === false; + $hasWaterfallPlus = strpos(",{$disabledFeatures},", ',waterfallplus,') === false; + $hasScrumMeasrecord = strpos(",{$disabledFeatures},", ',scrumMeasrecord,') === false; + $hasAgilePlusMeasrecord = strpos(",{$disabledFeatures},", ',agileMeasrecord,') === false; + $hasWaterfallMeasrecord = (strpos(",{$disabledFeatures},", ',waterfallMeasrecord,') === false and $hasWaterfall); + $hasWaterfallPlusMeasrecord = (strpos(",{$disabledFeatures},", ',waterfallplusMeasrecord,') === false and $hasWaterfallPlus); $cronStatus = 'normal'; - if(!$hasScrumMeasrecord and !$hasWaterfallMeasrecord) $cronStatus = 'stop'; + if(!$hasScrumMeasrecord and !$hasAgilePlusMeasrecord and !$hasWaterfallMeasrecord and $hasWaterfallPlusMeasrecord) $cronStatus = 'stop'; $this->loadModel('cron'); $cron = $this->dao->select('id,status')->from(TABLE_CRON)->where('command')->like('%methodName=initCrontabQueue')->fetch(); diff --git a/module/dev/js/langitem.js b/module/dev/js/langitem.js index 8a237c5262..878d67287c 100644 --- a/module/dev/js/langitem.js +++ b/module/dev/js/langitem.js @@ -1,51 +1,54 @@ $(function() { - $(".input-list").on("click", 'input', function(e) - { - handleClickItem(e.target.id); - }); - $(".input-list").on("blur", 'input', function(e) - { - removeActive(e.target.id); - }); - - $('.label-list > .input-label').on('click', function(e) - { - handleClickItem($(this).attr('labelid')); - }); - - initMenu(); - - $('li.has-list > ul').addClass("menu-active-primary menu-hover-primary") - - handleInputSearch(); - + /** + * Add class active while click item in form. + * + * @param string $id + * @access public + * @return void + */ function addActive(id) { $('[labelid=' + id + ']').addClass('text-primary'); $('[iconid=' + id + ']').removeClass('hidden'); } + /** + * Remove class active while blur or click item in form. + * + * @param string $id + * @access public + * @return void + */ function removeActive(id) { $('[labelid=' + id + ']').removeClass('text-primary'); $('[iconid=' + id + ']').addClass('hidden'); } + /** + * Handle function click in label. + * + * @param string $id + * @access public + * @return void + */ function handleClickItem(clickId) { - var clearId = $('.label-list > .text-primary').attr('labelid'); - if(clearId && clearId !== clickId) - { - removeActive(clearId); - }; - - if(clickId && clickId != clearId) + var clearId = $('.label-list > .text-primary').attr('labelid'); + if(clearId !== clickId) { - addActive(clickId); + if(clearId) removeActive(clearId); + if(clickId) addActive(clickId); }; } + /** + * Handle function input on search comp and update menu tree. + * + * @access public + * @return void + */ function handleInputSearch() { $('.menu-tree .search-input').on('input', function() @@ -61,20 +64,9 @@ $(function() for (var i = 0; i < menuTree.length; i++) { var item = {}; - $.extend(true, item, menuTree[i]) - if (item.children) - { - var children = []; - for (var j = 0; j < item.children.length; j++) - { - if (item.children[j].title.includes(val) || (item.children[j].key && item.children[j].key.includes(val))) - { - children.push(item.children[j]); - } - } - item.children = children; - } - if (item.children.length || item.title.includes(val) ||(item.key && item.key.includes(val))) + $.extend(true, item, menuTree[i]); + item.children = filterChildren(item, val); + if ((item.children && item.children.length) || item.title.indexOf(val) != -1 || (item.key && item.key.indexOf(val) != -1)) { updateData.push(item); } @@ -84,9 +76,40 @@ $(function() }) } + /** + * Handle function filter in array children in every item in menu tree. + * + * @access public + * @return array + */ + function filterChildren(item, val) + { + var childern = null; + if (item && item.children) + { + children = []; + for (var i = 0; i < item.children.length; i++) + { + item.children[i].children = filterChildren(item.children[i], val); + if (item.children[i].title.indexOf(val) != -1 || (item.children[i].key && item.children[i].key.indexOf(val) != -1) || item.children[i].children) + { + children.push(item.children[i]); + } + } + } + + return children; + } + + /** + * Init menu tree by zui. + * + * @access public + * @return void + */ function initMenu() { - if (navTypes.includes(type)) + if (navTypes.indexOf(type) != -1) { $('#menuTree').tree( { @@ -103,9 +126,27 @@ $(function() $('#menuTree').on('click', 'a', function(e) { var target = $(e.target); - if (target.attr('data-has-children') === 'true') return + if (target.attr('data-has-children') === 'true') return; self.location.href = createLink('dev', 'langItem', 'type=' + type + '&module=' + target.attr('data-module') + '&method=' + target.attr('data-method')); }) } + + $(".input-list").on("click", 'input', function(e) + { + handleClickItem(e.target.id); + }).on("blur", 'input', function(e) + { + removeActive(e.target.id); + }); + + $('.label-list > .input-label').on('click', function() + { + handleClickItem($(this).attr('labelid')); + }); + + initMenu(); + handleInputSearch(); + + $('li.has-list > ul').addClass("menu-active-primary menu-hover-primary") }) diff --git a/module/dev/model.php b/module/dev/model.php index 5db2d1a3ea..a9505f1e9a 100644 --- a/module/dev/model.php +++ b/module/dev/model.php @@ -582,16 +582,24 @@ class devModel extends model * @access public * @return array */ - public function getFeatureMenus($menu, $module = '', $method = '') + public function getFeatureMenus($menu, $module = '', $method = '', $loadModules = array()) { - $this->app->loadLang($menu); $menus = array(); + $this->app->loadLang($menu); + if(!in_array($menu, $loadModules) and isset($this->lang->$menu->menu)) + { + $loadModules[] = $menu; + $menuLang = $this->getLinkTitle($this->lang->$menu->menu); + foreach($menuLang as $menuKey => $menuName) $menus += $this->getFeatureMenus($menuKey, $module, $method, $loadModules); + } + if(isset($this->lang->$menu->featureBar)) { - $featureBar = $this->lang->$menu->featureBar; + $featureBar = $this->lang->$menu->featureBar; foreach($featureBar as $methodName => $feature) { if($methodName == 'caselib') $methodName = 'caseLib'; + if($methodName == 'all') $methodName = 'browse'; $subMenu = new stdClass(); $subMenu->title = zget($this->lang->$menu, $methodName); @@ -637,8 +645,6 @@ class devModel extends model $mainNav = $this->getLinkTitle($mainNav); $maimNavPinYin = common::convert2Pinyin($mainNav); - - if(empty($module)) $module = 'my'; foreach($mainNav as $menuKey => $menu) { $menuItem = new stdclass(); diff --git a/module/execution/css/batchedit.css b/module/execution/css/batchedit.css index 6051595822..5fb6ae17e4 100644 --- a/module/execution/css/batchedit.css +++ b/module/execution/css/batchedit.css @@ -2,3 +2,5 @@ .c-team-name {width: 120px;} .c-project, .c-user, .c-code, .c-desc, .c-days {width: 150px;} .c-method {width: 45px;} +.c-type > .icon-help {vertical-align: text-top;} +.c-type > .popover .popover-content {font-weight: 400;} diff --git a/module/execution/css/batchedit.en.css b/module/execution/css/batchedit.en.css index 1bc7227968..d4858d89b7 100644 --- a/module/execution/css/batchedit.en.css +++ b/module/execution/css/batchedit.en.css @@ -1,3 +1,4 @@ .c-user {width: 150px !important;} .c-date {width: 125px;} .c-method {width: 60px;} +.c-type {width: 130px;} diff --git a/module/execution/css/create.css b/module/execution/css/create.css index 8a387053df..8ba2c65184 100644 --- a/module/execution/css/create.css +++ b/module/execution/css/create.css @@ -39,3 +39,4 @@ .productsBox .required + .text-danger.help-text {position: relative; left: 10px;} .productsBox > #productNameLabel {padding-top: 8px;} .productsBox div[id^='branch'].chosen-disabled {pointer-events: none;} +.methodTip icon:before {margin-bottom: 5px;} diff --git a/module/execution/js/batchedit.js b/module/execution/js/batchedit.js index db84c6b085..603122e2bd 100644 --- a/module/execution/js/batchedit.js +++ b/module/execution/js/batchedit.js @@ -27,3 +27,8 @@ $('#executionForm').on('change input mousedown', '.has-error', function() $(this).parent().find('.text-danger').remove(); $(this).removeClass('has-error'); }) + +$(function() +{ + $('[data-toggle="popover"]').popover(); +}) diff --git a/module/execution/js/create.js b/module/execution/js/create.js index 750bdae6b0..56ac637410 100644 --- a/module/execution/js/create.js +++ b/module/execution/js/create.js @@ -153,6 +153,8 @@ $(function() { $('.disabledBranch div[id^="branch"]').addClass('chosen-disabled'); } + + $('[data-toggle="popover"]').popover(); }); function showLifeTimeTips() diff --git a/module/execution/js/edit.js b/module/execution/js/edit.js index 5527fd5b0b..58f5d31712 100644 --- a/module/execution/js/edit.js +++ b/module/execution/js/edit.js @@ -112,6 +112,8 @@ $(function() { $('.disabledBranch div[id^="branch"]').addClass('chosen-disabled'); } + + $('[data-toggle="popover"]').popover(); }) var lastProjectID = $("#project").val(); diff --git a/module/execution/lang/de.php b/module/execution/lang/de.php index d6c506033d..aacc1a5dba 100644 --- a/module/execution/lang/de.php +++ b/module/execution/lang/de.php @@ -151,6 +151,8 @@ $lang->execution->left = 'Left'; $lang->execution->copyTeamTip = "copy Project/project team members"; $lang->execution->daysGreaterProject = 'Days cannot be greater than days of execution 『%s』'; $lang->execution->errorHours = 'Hours/Day cannot be greater than『24』'; +$lang->execution->agileplusMethodTip = 'When creating executions in an Agile Plus project, both Iteration and Kanban management methods are supported.'; +$lang->execution->typeTip = "The sub-stages of other types can be created under the parent stage of the 'mix' type, while the type of other parent-child levels is consistent."; $lang->execution->start = 'Start'; $lang->execution->activate = 'Aktivieren'; diff --git a/module/execution/lang/en.php b/module/execution/lang/en.php index 995e4f9d53..d8f522124d 100644 --- a/module/execution/lang/en.php +++ b/module/execution/lang/en.php @@ -151,6 +151,8 @@ $lang->execution->left = 'Left'; $lang->execution->copyTeamTip = "copy Project/project team members"; $lang->execution->daysGreaterProject = 'Days cannot be greater than days of execution 『%s』'; $lang->execution->errorHours = 'Hours/Day cannot be greater than『24』'; +$lang->execution->agileplusMethodTip = 'When creating executions in an Agile Plus project, both Iteration and Kanban management methods are supported.'; +$lang->execution->typeTip = "The sub-stages of other types can be created under the parent stage of the 'mix' type, while the type of other parent-child levels is consistent."; $lang->execution->start = 'Start'; $lang->execution->activate = 'Activate'; diff --git a/module/execution/lang/fr.php b/module/execution/lang/fr.php index ac5351d360..46f9661aa7 100644 --- a/module/execution/lang/fr.php +++ b/module/execution/lang/fr.php @@ -151,6 +151,8 @@ $lang->execution->left = 'Left'; $lang->execution->copyTeamTip = "copy Project/project team members"; $lang->execution->daysGreaterProject = 'Days cannot be greater than days of execution 『%s』'; $lang->execution->errorHours = 'Hours/Day cannot be greater than『24』'; +$lang->execution->agileplusMethodTip = 'When creating executions in an Agile Plus project, both Iteration and Kanban management methods are supported.'; +$lang->execution->typeTip = "The sub-stages of other types can be created under the parent stage of the 'mix' type, while the type of other parent-child levels is consistent."; $lang->execution->start = 'Démarrer'; $lang->execution->activate = 'Activer'; diff --git a/module/execution/lang/zh-cn.php b/module/execution/lang/zh-cn.php index a83b65dc25..211e47444a 100644 --- a/module/execution/lang/zh-cn.php +++ b/module/execution/lang/zh-cn.php @@ -151,6 +151,8 @@ $lang->execution->left = '剩余'; $lang->execution->copyTeamTip = "可以选择复制项目或{$lang->execution->common}团队的成员"; $lang->execution->daysGreaterProject = '可用工日不能大于执行的可用工日『%s』'; $lang->execution->errorHours = '可用工时/天不能大于『24』'; +$lang->execution->agileplusMethodTip = '融合敏捷项目创建执行时,支持迭代和看板两种管理方法。'; +$lang->execution->typeTip = '“综合”类型的父阶段可以创建其它类型的子级,其它父子层级的类型均一致。'; $lang->execution->start = "开始"; $lang->execution->activate = "激活"; diff --git a/module/execution/view/batchedit.html.php b/module/execution/view/batchedit.html.php index 5b95828e0f..d78ab1d11f 100755 --- a/module/execution/view/batchedit.html.php +++ b/module/execution/view/batchedit.html.php @@ -62,7 +62,10 @@ '>execution->PO;?> '>execution->QD;?> '>execution->RD;?> - '>execution->$type;?> + '> + execution->$type;?> + + execution->begin;?> execution->end;?> '>execution->$desc;?> diff --git a/module/execution/view/create.html.php b/module/execution/view/create.html.php index cb134dfd7e..f8e6f80772 100644 --- a/module/execution/view/create.html.php +++ b/module/execution/view/create.html.php @@ -66,7 +66,10 @@ execution->method;?> execution->typeList, $type, "class='form-control chosen' required onchange='setType(this.value)'");?> - + + + + diff --git a/module/execution/view/edit.html.php b/module/execution/view/edit.html.php index 6ade126e6e..d5d43fe019 100644 --- a/module/execution/view/edit.html.php +++ b/module/execution/view/edit.html.php @@ -98,6 +98,9 @@ } ?> + + + diff --git a/module/group/control.php b/module/group/control.php index 525866f45c..eab5efd9b1 100644 --- a/module/group/control.php +++ b/module/group/control.php @@ -254,9 +254,9 @@ class group extends control foreach($this->lang->resource as $module => $moduleActions) { $modules[$module] = $this->lang->$module->common; - foreach($moduleActions as $action) + foreach($moduleActions as $key => $action) { - $actions[$module][$action] = $this->lang->$module->$action; + $actions[$module][$key] = $this->lang->$module->$action; } } $this->view->groups = $this->group->getPairs(); diff --git a/module/job/lang/de.php b/module/job/lang/de.php index 78072999ed..5fd9c49559 100644 --- a/module/job/lang/de.php +++ b/module/job/lang/de.php @@ -100,3 +100,6 @@ $lang->job->pipelineVariables = "Variables"; $lang->job->pipelineVariablesKeyPlaceHolder = "Input variable key"; $lang->job->pipelineVariablesValuePlaceHolder = "Input variable value"; $lang->job->pipelineVariablesTips = "Specify variable values to be used in this run. The values specified in CI/CD settings will be used by default."; + +$lang->job->featureBar['browse']['job'] = 'List'; +$lang->job->featureBar['browse']['compile'] = 'History'; diff --git a/module/job/lang/en.php b/module/job/lang/en.php index bec5a4a940..0356380338 100644 --- a/module/job/lang/en.php +++ b/module/job/lang/en.php @@ -100,3 +100,6 @@ $lang->job->pipelineVariables = "Variables"; $lang->job->pipelineVariablesKeyPlaceHolder = "Input variable key"; $lang->job->pipelineVariablesValuePlaceHolder = "Input variable value"; $lang->job->pipelineVariablesTips = "Specify variable values to be used in this run. The values specified in CI/CD settings will be used by default."; + +$lang->job->featureBar['browse']['job'] = 'List'; +$lang->job->featureBar['browse']['compile'] = 'History'; diff --git a/module/job/lang/fr.php b/module/job/lang/fr.php index 5bc3abe9b0..09f6f216bf 100644 --- a/module/job/lang/fr.php +++ b/module/job/lang/fr.php @@ -100,3 +100,6 @@ $lang->job->pipelineVariables = "Variables"; $lang->job->pipelineVariablesKeyPlaceHolder = "Input variable key"; $lang->job->pipelineVariablesValuePlaceHolder = "Input variable value"; $lang->job->pipelineVariablesTips = "Specify variable values to be used in this run. The values specified in CI/CD settings will be used by default."; + +$lang->job->featureBar['browse']['job'] = 'List'; +$lang->job->featureBar['browse']['compile'] = 'History'; diff --git a/module/job/lang/zh-cn.php b/module/job/lang/zh-cn.php index 7c53b987e8..f10093ea5b 100644 --- a/module/job/lang/zh-cn.php +++ b/module/job/lang/zh-cn.php @@ -101,3 +101,6 @@ $lang->job->pipelineVariablesKeyPlaceHolder = "输入变量的名称"; $lang->job->pipelineVariablesValuePlaceHolder = "输入变量的值"; $lang->job->pipelineVariablesTips = "指定要在此次运行中使用的变量值。CI/CD设置中指定的值将用作默认值。"; $lang->job->setReferenceTips = "在执行构建前,请先设置代码库的分支信息。"; + +$lang->job->featureBar['browse']['job'] = '列表'; +$lang->job->featureBar['browse']['compile'] = '构建历史'; diff --git a/module/job/view/browse.html.php b/module/job/view/browse.html.php index 6d7c8d4c2d..f430b00f49 100644 --- a/module/job/view/browse.html.php +++ b/module/job/view/browse.html.php @@ -13,8 +13,14 @@