diff --git a/VERSION b/VERSION index adbc6d2b1b..2bbd2b4b42 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -15.1 +15.0.1 diff --git a/config/config.php b/config/config.php index 186ed887a2..fad76cba64 100644 --- a/config/config.php +++ b/config/config.php @@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}} if(!function_exists('getWebRoot')){function getWebRoot(){}} /* 基本设置。Basic settings. */ -$config->version = '15.1'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. +$config->version = '15.0.1'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. $config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP. $config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time. $config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php. diff --git a/db/update15.0.sql b/db/update15.0.sql index 4a1c55ec3c..193e250ca4 100644 --- a/db/update15.0.sql +++ b/db/update15.0.sql @@ -26,3 +26,5 @@ ALTER TABLE `zt_testtask` ADD `testreport` mediumint(8) unsigned NOT NULL AFTER ALTER TABLE `zt_story` MODIFY COLUMN `reviewedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'; REPLACE INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'story', '', 'reviewRules', 'allpass'); + +UPDATE zt_project SET lifetime = '' WHERE lifetime = 'sprint'; diff --git a/module/action/config.php b/module/action/config.php index 460ad0a6f3..03d04cece9 100755 --- a/module/action/config.php +++ b/module/action/config.php @@ -30,9 +30,6 @@ $config->action->objectNameFields['stakeholder'] = 'user'; $config->action->objectNameFields['budget'] = 'name'; $config->action->objectNameFields['job'] = 'name'; $config->action->objectNameFields['team'] = 'name'; -$config->action->objectNameFields['opportunity'] = 'name'; -$config->action->objectNameFields['trainplan'] = 'name'; -$config->action->objectNameFields['gapanalysis'] = 'account'; $config->action->commonImgSize = 870; @@ -47,3 +44,4 @@ $config->action->majorList['project'] = array('opened', 'edited'); $config->action->majorList['execution'] = array('opened', 'edited'); $config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis'; +$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,'; diff --git a/module/action/lang/de.php b/module/action/lang/de.php index b4e41f8e8f..b61f9c8c03 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -99,9 +99,6 @@ $lang->action->objectTypes['webhook'] = 'Webhook'; $lang->action->objectTypes['job'] = 'Job'; $lang->action->objectTypes['team'] = 'Team'; $lang->action->objectTypes['whitelist'] = 'Whitelist'; -$lang->action->objectTypes['opportunity'] = 'Opportunity'; -$lang->action->objectTypes['trainplan'] = 'Trainplan'; -$lang->action->objectTypes['gapanalysis'] = 'Gap Analysis'; /* 用来描述操作历史记录。*/ $lang->action->desc = new stdclass(); @@ -487,9 +484,6 @@ $lang->action->label->risk = 'Risk|risk|view|riskID=%s'; $lang->action->label->issue = 'Issue|issue|view|issueID=%s'; $lang->action->label->design = 'Design|design|view|designID=%s'; $lang->action->label->stakeholder = 'Stakeholder|stakeholder|view|userID=%s'; -$lang->action->label->opportunity = 'Opportunity|opportunity|view|opportunityID=%s'; -$lang->action->label->trainplan = 'Trainplan|trainplan|view|trainplanID=%s'; -$lang->action->label->gapanalysis = 'Gap Analysis|gapanalysis|view|gapanalysisID=%s'; /* Object type. */ $lang->action->search = new stdclass(); diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 740ac31413..2cee6ad09d 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -103,9 +103,6 @@ $lang->action->objectTypes['entry'] = 'Entry'; $lang->action->objectTypes['webhook'] = 'Webhook'; $lang->action->objectTypes['team'] = 'Team'; $lang->action->objectTypes['whitelist'] = 'Whitelist'; -$lang->action->objectTypes['opportunity'] = 'Opportunity'; -$lang->action->objectTypes['trainplan'] = 'Trainplan'; -$lang->action->objectTypes['gapanalysis'] = 'Gap Analysis'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); @@ -490,9 +487,6 @@ $lang->action->label->risk = 'Risk|risk|view|riskID=%s'; $lang->action->label->issue = 'Issue|issue|view|issueID=%s'; $lang->action->label->design = 'Design|design|view|designID=%s'; $lang->action->label->stakeholder = 'Stakeholder|stakeholder|view|userID=%s'; -$lang->action->label->opportunity = 'Opportunity|opportunity|view|opportunityID=%s'; -$lang->action->label->trainplan = 'Trainplan|trainplan|view|trainplanID=%s'; -$lang->action->label->gapanalysis = 'Gap Analysis|gapanalysis|view|gapanalysisID=%s'; /* Object type. */ $lang->action->search = new stdclass(); diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index e39d196bf5..7b4195db98 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -99,9 +99,6 @@ $lang->action->objectTypes['webhook'] = 'Webhook'; $lang->action->objectTypes['job'] = 'Job'; $lang->action->objectTypes['team'] = 'Team'; $lang->action->objectTypes['whitelist'] = 'Whitelist'; -$lang->action->objectTypes['opportunity'] = 'Opportunity'; -$lang->action->objectTypes['trainplan'] = 'Trainplan'; -$lang->action->objectTypes['gapanalysis'] = 'Gap Analysis'; /* 用来描述操作历史记录。*/ $lang->action->desc = new stdclass(); @@ -499,9 +496,6 @@ $lang->action->label->risk = 'Risk|risk|view|riskID=%s'; $lang->action->label->issue = 'Issue|issue|view|issueID=%s'; $lang->action->label->design = 'Design|design|view|designID=%s'; $lang->action->label->stakeholder = 'Stakeholder|stakeholder|view|userID=%s'; -$lang->action->label->opportunity = 'Opportunity|opportunity|view|opportunityID=%s'; -$lang->action->label->trainplan = 'Trainplan|trainplan|view|trainplanID=%s'; -$lang->action->label->gapanalysis = 'Gap Analysis|gapanalysis|view|gapanalysisID=%s'; /* Object type. */ $lang->action->search = new stdclass(); diff --git a/module/action/lang/vi.php b/module/action/lang/vi.php index ff9145b833..2abefe6569 100644 --- a/module/action/lang/vi.php +++ b/module/action/lang/vi.php @@ -99,9 +99,6 @@ $lang->action->objectTypes['webhook'] = 'Webhook'; $lang->action->objectTypes['job'] = 'Job'; $lang->action->objectTypes['team'] = 'Team'; $lang->action->objectTypes['whitelist'] = 'Whitelist'; -$lang->action->objectTypes['opportunity'] = 'Opportunity'; -$lang->action->objectTypes['trainplan'] = 'Trainplan'; -$lang->action->objectTypes['gapanalysis'] = 'Gap Analysis'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); @@ -487,9 +484,6 @@ $lang->action->label->risk = 'Risk|risk|view|riskID%s'; $lang->action->label->issue = 'Issue|issue|view|issueID=%s'; $lang->action->label->design = 'Design|design|view|designID=%s'; $lang->action->label->stakeholder = 'Stakeholder|stakeholder|view|userID=%s'; -$lang->action->label->opportunity = 'Opportunity|opportunity|view|opportunityID=%s'; -$lang->action->label->trainplan = 'Trainplan|trainplan|view|trainplanID=%s'; -$lang->action->label->gapanalysis = 'Gap Analysis|gapanalysis|view|gapanalysisID=%s'; /* Object type. */ $lang->action->search = new stdclass(); diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index 9662bf4504..d94e60c869 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -103,9 +103,6 @@ $lang->action->objectTypes['entry'] = '应用'; $lang->action->objectTypes['webhook'] = 'Webhook'; $lang->action->objectTypes['team'] = '团队'; $lang->action->objectTypes['whitelist'] = '白名单'; -$lang->action->objectTypes['opportunity'] = '机会'; -$lang->action->objectTypes['trainplan'] = '培训计划'; -$lang->action->objectTypes['gapanalysis'] = '能力差距分析'; /* 用来描述操作历史记录。*/ $lang->action->desc = new stdclass(); @@ -490,9 +487,6 @@ $lang->action->label->risk = '风险|risk|view|riskID=%s'; $lang->action->label->issue = '问题|issue|view|issueID=%s'; $lang->action->label->design = '设计|design|view|designID=%s'; $lang->action->label->stakeholder = '干系人|stakeholder|view|userID=%s'; -$lang->action->label->opportunity = '机会|opportunity|view|opportunityID=%s'; -$lang->action->label->trainplan = '培训计划|trainplan|view|trainplanID=%s'; -$lang->action->label->gapanalysis = '能力差距分析|gapanalysis|view|gapanalysisID=%s'; /* Object type. */ $lang->action->search = new stdclass(); diff --git a/module/action/model.php b/module/action/model.php index a91e7052cd..09eb78dbf3 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -49,6 +49,9 @@ class actionModel extends model $action->date = helper::now(); $action->extra = $extra; + if($objectType == 'story' and $actionType !== 'reviewed' and strpos('reviewclosed,passreviewed,clarifyreviewed', $actionType) !== false) $action->actor = 'System'; + + /* Use purifier to process comment. Fix bug #2683. */ $action->comment = fixer::stripDataTags($comment); @@ -60,36 +63,11 @@ class actionModel extends model } /* Get product project and execution for this object. */ - $relation = $this->getRelatedFields($action->objectType, $objectID); - $action->product = $relation['product']; - $action->project = ($actionType == 'unlinkedfromproject' or $actionType == 'linked2project') ? (int)$extra : (int)$relation['project']; - $action->execution = ($actionType == 'unlinkedfromexecution' or $actionType == 'linked2execution') ? (int)$extra : (int)$relation['execution']; + $relation = $this->getRelatedFields($action->objectType, $objectID, $actionType, $extra); + $action->product = (int)$relation['product']; + $action->project = (int)$relation['project']; + $action->execution = (int)$relation['execution']; - if($objectType == 'story' and ($actionType == 'linked2build' or $actionType == 'unlinkedfrombuild')) - { - $build = $this->dao->select('project,execution')->from(TABLE_BUILD)->where('id')->eq((int)$extra)->fetch(); - $action->project = $build->project; - $action->execution = $build->execution; - } - - if($objectType == 'story' and $actionType == 'estimated') - { - $action->project = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq((int)$extra)->fetch('project'); - $action->execution = (int)$extra; - } - - if($objectType == 'story' and $actionType !== 'reviewed' and strpos('reviewclosed,passreviewed,clarifyreviewed', $actionType) !== false) $action->actor = 'System'; - - if($objectType == 'case' and (strpos(',linked2testtask,unlinkedfromtesttask,assigned,run,', ',' . $actionType . ',') !== false) and (int)$extra) - { - $testtask = $this->dao->select('project,execution')->from(TABLE_TESTTASK)->where('id')->eq((int)$extra)->fetch(); - $action->project = $testtask->project; - $action->execution = $testtask->execution; - } - - if($objectType == 'whitelist' and $extra == 'product') $action->product = $objectID; - if($objectType == 'whitelist' and $extra == 'project') $action->project = $objectID; - if($objectType == 'whitelist' and ($extra == 'sprint' or $extra == 'stage')) $action->execution = $objectID; $this->dao->insert(TABLE_ACTION)->data($action)->autoCheck()->exec(); $actionID = $this->dbh->lastInsertID(); @@ -168,10 +146,12 @@ class actionModel extends model * * @param string $objectType * @param int $objectID + * @param string $actionType + * @param string $extra * @access public * @return array */ - public function getRelatedFields($objectType, $objectID) + public function getRelatedFields($objectType, $objectID, $actionType = '', $extra = '') { $emptyRecord = array('product' => ',0,', 'project' => 0, 'execution' => 0); @@ -203,7 +183,7 @@ class actionModel extends model } /* Only process these object types. */ - if(strpos(',story,productplan,release,task,build,bug,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,', ",{$objectType},") !== false) + if(strpos($this->config->action->needGetRelateField, ",{$objectType},") !== false) { if(!isset($this->config->objectTables[$objectType])) return $emptyRecord; @@ -241,6 +221,32 @@ class actionModel extends model } } + if($objectType == 'story' and ($actionType == 'linked2build' or $actionType == 'unlinkedfrombuild')) + { + $build = $this->dao->select('project,execution')->from(TABLE_BUILD)->where('id')->eq((int)$extra)->fetch(); + $record->project = $build->project; + $record->execution = $build->execution; + } + + if($objectType == 'story' and $actionType == 'estimated') + { + $record->project = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq((int)$extra)->fetch('project'); + $record->execution = (int)$extra; + } + + if($objectType == 'case' and (strpos(',linked2testtask,unlinkedfromtesttask,assigned,run,', ',' . $actionType . ',') !== false) and (int)$extra) + { + $testtask = $this->dao->select('project,execution')->from(TABLE_TESTTASK)->where('id')->eq((int)$extra)->fetch(); + $record->project = $testtask->project; + $record->execution = $testtask->execution; + } + + if($objectType == 'whitelist' and $extra == 'product') $record->product = $objectID; + if($objectType == 'whitelist' and $extra == 'project') $record->project = $objectID; + if($objectType == 'whitelist' and ($extra == 'sprint' or $extra == 'stage')) $record->execution = $objectID; + if($actionType == 'unlinkedfromproject' or $actionType == 'linked2project') $record->project = (int)$extra ; + if($actionType == 'unlinkedfromexecution' or $actionType == 'linked2execution') $record->execution = (int)$extra; + if($record) { $record = (array)$record; diff --git a/module/bug/js/edit.js b/module/bug/js/edit.js index b5895c0e65..2669cde048 100644 --- a/module/bug/js/edit.js +++ b/module/bug/js/edit.js @@ -1,6 +1,24 @@ $(function() { loadModuleRelated(); + + resolution = $('#resolution').val(); + if(resolution == 'fixed') + { + $('#resolvedBuildBox').change(function() + { + if($('#resolvedBuild').val() != oldResolvedBuild) + { + confirmResult = confirm(confirmUnlinkBuild); + if(!confirmResult) + { + $('#resolvedBuild').val(oldResolvedBuild); + $('#resolvedBuild').trigger("chosen:updated"); + $('#resolvedBuild').chosen(); + } + } + }); + } }); /** diff --git a/module/bug/lang/de.php b/module/bug/lang/de.php index 87ad7cf382..117da8e767 100644 --- a/module/bug/lang/de.php +++ b/module/bug/lang/de.php @@ -181,6 +181,7 @@ $lang->bug->remindTask = 'This Bug has been converted to Task. Do you $lang->bug->skipClose = 'Bug %s is not resolved. You cannot close it.'; $lang->bug->executionAccessDenied = "You access to the {$lang->executionCommon} to which this bug belongs is denied!"; $lang->bug->stepsNotEmpty = "The reproduction step cannot be empty."; +$lang->bug->confirmUnlinkBuild = "Replacing the solution version will disassociate the bug from the old version. Are you sure you want to disassociate the bug from %s?"; /* 模板。*/ $lang->bug->tplStep = "

[Steps]


"; diff --git a/module/bug/lang/en.php b/module/bug/lang/en.php index 032b0d03dc..584b1c7d59 100644 --- a/module/bug/lang/en.php +++ b/module/bug/lang/en.php @@ -181,6 +181,7 @@ $lang->bug->remindTask = 'This bug has been converted to a task. Do y $lang->bug->skipClose = 'Bug %s is active. You cannot close it.'; $lang->bug->executionAccessDenied = "You access to the {$lang->executionCommon} to which this bug belongs is denied!"; $lang->bug->stepsNotEmpty = "The reproduction step cannot be empty."; +$lang->bug->confirmUnlinkBuild = "Replacing the solution version will disassociate the bug from the old version. Are you sure you want to disassociate the bug from %s?"; /* Template. */ $lang->bug->tplStep = "

[Steps]


"; diff --git a/module/bug/lang/fr.php b/module/bug/lang/fr.php index e2c9e65dc2..569a6f9480 100644 --- a/module/bug/lang/fr.php +++ b/module/bug/lang/fr.php @@ -181,6 +181,7 @@ $lang->bug->remindTask = 'Ce bug a été converti en tâche. Voulez-v $lang->bug->skipClose = 'Bug %s est actif. Vous ne pouvez pas le fermer.'; $lang->bug->executionAccessDenied = "Votre accès à {$lang->executionCommon} auquel ce bug appartient est refusé !"; $lang->bug->stepsNotEmpty = "The reproduction step cannot be empty."; +$lang->bug->confirmUnlinkBuild = "Replacing the solution version will disassociate the bug from the old version. Are you sure you want to disassociate the bug from %s?"; /* 模板。*/ $lang->bug->tplStep = "

[Etape]


"; diff --git a/module/bug/lang/vi.php b/module/bug/lang/vi.php index 8d7e8e026c..d2eeefbe24 100644 --- a/module/bug/lang/vi.php +++ b/module/bug/lang/vi.php @@ -181,6 +181,7 @@ $lang->bug->remindTask = 'Bug này đã chuyển thành một nhiệm $lang->bug->skipClose = 'Bug %s được kích hoạt. Bạn không thể đóng nó.'; $lang->bug->executionAccessDenied = "Truy cập của bạn tới {$lang->executionCommon} mà Bug này sở hữu bị từ chối!"; $lang->bug->stepsNotEmpty = "The reproduction step cannot be empty."; +$lang->bug->confirmUnlinkBuild = "Replacing the solution version will disassociate the bug from the old version. Are you sure you want to disassociate the bug from %s?"; /* Template. */ $lang->bug->tplStep = "

[Các bước]


"; diff --git a/module/bug/lang/zh-cn.php b/module/bug/lang/zh-cn.php index 7dfd1e848b..65fc2086d9 100644 --- a/module/bug/lang/zh-cn.php +++ b/module/bug/lang/zh-cn.php @@ -181,6 +181,7 @@ $lang->bug->remindTask = '该Bug已经转化为任务,是否更新 $lang->bug->skipClose = 'Bug %s 不是已解决状态,不能关闭。'; $lang->bug->executionAccessDenied = "您无权访问该Bug所属的{$lang->executionCommon}!"; $lang->bug->stepsNotEmpty = "重现步骤不能为空。"; +$lang->bug->confirmUnlinkBuild = "更换解决版本将取消与旧版本的关联,您确定取消该bug与%s的关联吗?"; /* 模板。*/ $lang->bug->tplStep = "

[步骤]


"; diff --git a/module/bug/lang/zh-tw.php b/module/bug/lang/zh-tw.php index 1d4da479e7..e84542e49d 100644 --- a/module/bug/lang/zh-tw.php +++ b/module/bug/lang/zh-tw.php @@ -181,6 +181,7 @@ $lang->bug->remindTask = '該Bug已經轉化為任務,是否更新 $lang->bug->skipClose = 'Bug %s 不是已解決狀態,不能關閉。'; $lang->bug->executionAccessDenied = "您無權訪問該Bug所屬的{$lang->executionCommon}!"; $lang->bug->stepsNotEmpty = "重現步驟不能為空。"; +$lang->bug->confirmUnlinkBuild = "更換解决版本將取消與舊版本的關聯,您確定取消該bug與%s的關聯嗎?"; /* 模板。*/ $lang->bug->tplStep = "

[步驟]


"; diff --git a/module/bug/view/edit.html.php b/module/bug/view/edit.html.php index e589cbc8b8..d32e64309d 100644 --- a/module/bug/view/edit.html.php +++ b/module/bug/view/edit.html.php @@ -25,6 +25,7 @@ js::set('oldTaskID' , $bug->task); js::set('oldOpenedBuild' , $bug->openedBuild); js::set('oldResolvedBuild' , $bug->resolvedBuild); js::set('systemMode' , $config->systemMode); +js::set('confirmUnlinkBuild' , sprintf($lang->bug->confirmUnlinkBuild, zget($resolvedBuilds, $bug->resolvedBuild))); ?>
@@ -172,7 +173,7 @@ js::set('systemMode' , $config->systemMode);
-
bug->legendExecStoryTask;?>
+
systemMode == 'class' ? $lang->bug->legendExecStoryTask : $lang->bug->legendPRJExecStoryTask;?>
systemMode == 'new'):?> diff --git a/module/custom/control.php b/module/custom/control.php index 485c0b7b36..f0b13b6818 100644 --- a/module/custom/control.php +++ b/module/custom/control.php @@ -420,6 +420,19 @@ class custom extends control $this->display(); } + /** + * Set story concept. + * + * @param int $key + * @access public + * @return void + */ + public function setDefaultConcept($key = 0) + { + $this->loadModel('setting')->setItem('system.custom.URSR', $key); + die(js::reload('parent')); + } + /** * Delete story concept. * diff --git a/module/custom/lang/de.php b/module/custom/lang/de.php index 6107d9937b..0066022c91 100644 --- a/module/custom/lang/de.php +++ b/module/custom/lang/de.php @@ -38,6 +38,7 @@ $lang->custom->waterfallCommon = "Waterfall"; $lang->custom->buildin = "Buildin"; $lang->custom->editStoryConcept = "Edit Story Concept"; $lang->custom->setStoryConcept = "Set Story Concept"; +$lang->custom->setDefaultConcept = "Set Default Concept"; $lang->custom->browseStoryConcept = "List of story concepts"; $lang->custom->deleteStoryConcept = "Delete story Concept"; $lang->custom->URConcept = "UR Concept"; diff --git a/module/custom/lang/en.php b/module/custom/lang/en.php index 00235b1846..6473f51d14 100644 --- a/module/custom/lang/en.php +++ b/module/custom/lang/en.php @@ -38,6 +38,7 @@ $lang->custom->waterfallCommon = "Waterfall"; $lang->custom->buildin = "Buildin"; $lang->custom->editStoryConcept = "Edit Story Concept"; $lang->custom->setStoryConcept = "Set Story Concept"; +$lang->custom->setDefaultConcept = "Set Default Concept"; $lang->custom->browseStoryConcept = "List of story concepts"; $lang->custom->deleteStoryConcept = "Delete story Concept"; $lang->custom->URConcept = "UR Concept"; diff --git a/module/custom/lang/fr.php b/module/custom/lang/fr.php index 77a1a51ad0..dc63dcbc5b 100644 --- a/module/custom/lang/fr.php +++ b/module/custom/lang/fr.php @@ -38,6 +38,7 @@ $lang->custom->waterfallCommon = "Waterfall"; $lang->custom->buildin = "Buildin"; $lang->custom->editStoryConcept = "Edit Story Concept"; $lang->custom->setStoryConcept = "Set Story Concept"; +$lang->custom->setDefaultConcept = "Set Default Concept"; $lang->custom->browseStoryConcept = "List of story concepts"; $lang->custom->deleteStoryConcept = "Delete story Concept"; $lang->custom->URConcept = "UR Concept"; diff --git a/module/custom/lang/vi.php b/module/custom/lang/vi.php index ddffc57c45..f4a8b48a17 100644 --- a/module/custom/lang/vi.php +++ b/module/custom/lang/vi.php @@ -38,6 +38,7 @@ $lang->custom->waterfallCommon = "Waterfall"; $lang->custom->buildin = "Buildin"; $lang->custom->editStoryConcept = "Edit Story Concept"; $lang->custom->setStoryConcept = "Set Story Concept"; +$lang->custom->setDefaultConcept = "Set Default Concept"; $lang->custom->browseStoryConcept = "List of story concepts"; $lang->custom->deleteStoryConcept = "Delete story Concept"; $lang->custom->URConcept = "UR Concept"; diff --git a/module/custom/lang/zh-cn.php b/module/custom/lang/zh-cn.php index 23a648b109..60b1e10b0b 100644 --- a/module/custom/lang/zh-cn.php +++ b/module/custom/lang/zh-cn.php @@ -38,6 +38,7 @@ $lang->custom->waterfallCommon = "瀑布"; $lang->custom->buildin = "系统内置"; $lang->custom->editStoryConcept = "编辑需求概念"; $lang->custom->setStoryConcept = "设置需求概念"; +$lang->custom->setDefaultConcept = "设置默认概念"; $lang->custom->browseStoryConcept = "需求概念列表"; $lang->custom->deleteStoryConcept = "删除需求概念"; $lang->custom->URConcept = "用需概念"; diff --git a/module/custom/lang/zh-tw.php b/module/custom/lang/zh-tw.php index 2e63c697f2..5dff2482e1 100644 --- a/module/custom/lang/zh-tw.php +++ b/module/custom/lang/zh-tw.php @@ -38,6 +38,7 @@ $lang->custom->waterfallCommon = "瀑布"; $lang->custom->buildin = "系統內置"; $lang->custom->editStoryConcept = "編輯需求概念"; $lang->custom->setStoryConcept = "設置需求概念"; +$lang->custom->setDefaultConcept = "設置預設概念"; $lang->custom->browseStoryConcept = "需求概念列表"; $lang->custom->deleteStoryConcept = "刪除需求概念"; $lang->custom->URConcept = "用需概念"; diff --git a/module/custom/view/browsestoryconcept.html.php b/module/custom/view/browsestoryconcept.html.php index a369471976..bd4627b047 100644 --- a/module/custom/view/browsestoryconcept.html.php +++ b/module/custom/view/browsestoryconcept.html.php @@ -23,6 +23,9 @@
+ + + config->URAndSR):?> @@ -33,6 +36,9 @@ $URSR):?> + + + config->URAndSR):?> @@ -48,4 +54,11 @@
custom->default;?> custom->URConcept;?>
custom->URSR) echo 'checked';?>>
+ diff --git a/module/execution/control.php b/module/execution/control.php index f3c3daa5ff..410a91ba47 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -2759,7 +2759,7 @@ class execution extends control if($this->app->viewType == 'mhtml') { $executionID = $this->execution->saveState(0, $this->executions); - $this->execution->setMenu($productID); + $this->execution->setMenu($executionID); } /* Load pager and get tasks. */ diff --git a/module/execution/model.php b/module/execution/model.php index 5480cce204..dada45e9aa 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -293,31 +293,23 @@ class executionModel extends model return false; } + if($this->config->systemMode == 'new') $this->checkBeginAndEndDate($_POST['project'], $_POST['begin'], $_POST['end']); + if(dao::isError()) return false; + /* Determine whether to add a sprint or a stage according to the model of the execution. */ $project = $this->loadModel('project')->getByID($_POST['project']); - if($_POST['begin'] < $project->begin and $this->config->systemMode == 'new') - { - dao::$errors['begin'] = sprintf($this->lang->execution->errorBegin, $project->begin); - return false; - } + $type = zget($this->config->execution->modelList, $project->model, 'sprint'); - if($_POST['end'] > $project->end and $this->config->systemMode == 'new') + /* If the execution model is a stage, determine whether the product is linked. */ + if($type == 'stage' and empty($this->post->products[0])) { - dao::$errors['end'] = sprintf($this->lang->execution->errorEnd, $project->end); + dao::$errors['message'][] = $this->lang->execution->noLinkProduct; return false; } - $type = zget($this->config->execution->modelList, $project->model, 'sprint'); $this->config->execution->create->requiredFields .= ',project'; } - /* If the execution model is a stage, determine whether the product is linked. */ - if($type == 'stage' and empty($this->post->products[0])) - { - dao::$errors['message'][] = $this->lang->execution->noLinkProduct; - return false; - } - /* Get the data from the post. */ $sprint = fixer::input('post') ->setDefault('status', 'wait') @@ -472,18 +464,9 @@ class executionModel extends model ->remove('products, branch, uid, plans') ->get(); - $project = $this->dao->select('begin, end')->from(TABLE_PROJECT)->where('id')->eq($oldExecution->project)->fetch(); - if($execution->begin < $project->begin and $this->config->systemMode == 'new') - { - dao::$errors['begin'] = sprintf($this->lang->execution->errorBegin, $project->begin); - return false; - } + if($this->config->systemMode == 'new') $this->checkBeginAndEndDate($oldExecution->project, $execution->begin, $execution->end); + if(dao::isError()) return false; - if($execution->end > $project->end and $this->config->systemMode == 'new') - { - dao::$errors['end'] = sprintf($this->lang->execution->errorEnd, $project->end); - return false; - } /* Child stage inherits parent stage permissions. */ if(!isset($execution->acl)) $execution->acl = $oldExecution->acl; if($execution->acl == 'open') $execution->whitelist = ''; @@ -500,10 +483,6 @@ class executionModel extends model if(!empty($execution->realBegan) and !empty($execution->realEnd)) $execution->realDuration = $this->loadModel('programplan')->getDuration($execution->realBegan, $execution->realEnd); } - /* Replace required language. */ - $this->lang->project->name = $this->lang->execution->name; - $this->lang->project->code = $this->lang->execution->code; - /* Update data. */ $this->dao->update(TABLE_EXECUTION)->data($execution) ->autoCheck($skipFields = 'begin,end') @@ -706,18 +685,8 @@ class executionModel extends model ->remove('comment') ->get(); - $project = $this->dao->select('begin, end')->from(TABLE_PROJECT)->where('id')->eq($oldExecution->project)->fetch(); - if($execution->begin < $project->begin and $this->config->systemMode == 'new') - { - dao::$errors['begin'] = sprintf($this->lang->execution->errorBegin, $project->begin); - return false; - } - - if($execution->end > $project->end and $this->config->systemMode == 'new') - { - dao::$errors['end'] = sprintf($this->lang->execution->errorEnd, $project->end); - return false; - } + if($this->config->systemMode == 'new') $this->checkBeginAndEndDate($oldExecution->project, $execution->begin, $execution->end); + if(dao::isError()) return false; $this->dao->update(TABLE_EXECUTION)->data($execution) ->autoCheck() @@ -902,6 +871,22 @@ class executionModel extends model } } + /** + * Check begin and end date. + * + * @param string $begin + * @param string $end + * @access public + * @return void + */ + public function checkBeginAndEndDate($projectID, $begin, $end) + { + $project = $this->loadModel('project')->getByID($projectID); + if($begin < $project->begin) dao::$errors['begin'] = sprintf($this->lang->execution->errorBegin, $project->begin); + + if($end > $project->end) dao::$errors['end'] = sprintf($this->lang->execution->errorEnd, $project->end); + } + /* * Get execution switcher. * diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index cbca515e89..1259b6bf83 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -1081,6 +1081,7 @@ $lang->resource->custom->timezone = 'timezone'; $lang->resource->custom->setStoryConcept = 'setStoryConcept'; $lang->resource->custom->editStoryConcept = 'editStoryConcept'; $lang->resource->custom->browseStoryConcept = 'browseStoryConcept'; +$lang->resource->custom->setDefaultConcept = 'setDefaultConcept'; $lang->resource->custom->deleteStoryConcept = 'deleteStoryConcept'; $lang->custom->methodOrder[5] = 'index'; @@ -1095,7 +1096,8 @@ $lang->custom->methodOrder[45] = 'timezone'; $lang->custom->methodOrder[50] = 'setStoryConcept'; $lang->custom->methodOrder[55] = 'editStoryConcept'; $lang->custom->methodOrder[60] = 'browseStoryConcept'; -$lang->custom->methodOrder[65] = 'deleteStoryConcept'; +$lang->custom->methodOrder[65] = 'setDefaultConcept'; +$lang->custom->methodOrder[70] = 'deleteStoryConcept'; $lang->resource->datatable = new stdclass(); $lang->resource->datatable->setGlobal = 'setGlobal'; @@ -1806,6 +1808,7 @@ $lang->changelog['15.0.rc1'][] = 'user-execution'; $lang->changelog['15.0.rc1'][] = 'custom-setStoryConcept'; $lang->changelog['15.0.rc1'][] = 'custom-editStoryConcept'; $lang->changelog['15.0.rc1'][] = 'custom-browseStoryConcept'; +$lang->changelog['15.0.rc1'][] = 'custom-setDefaultConcept'; $lang->changelog['15.0.rc1'][] = 'custom-deleteStoryConcept'; $lang->changelog['15.0.rc1'][] = 'search-index'; $lang->changelog['15.0.rc1'][] = 'search-buildIndex'; diff --git a/module/my/view/requirement.html.php b/module/my/view/requirement.html.php index c2957dd598..f4031f5183 100644 --- a/module/my/view/requirement.html.php +++ b/module/my/view/requirement.html.php @@ -26,8 +26,8 @@ } else { - echo html::a(inlink($app->rawMethod, "mode=requirement&type=assignedTo&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "{$lang->my->storyMenu->assignedToMe}" . ($type == 'assignedTo' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedTo' ? ' btn-active-text' : '') . "'"); - echo html::a(inlink($app->rawMethod, "mode=requirement&type=reviewBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "{$lang->my->storyMenu->reviewByMe}" . ($type == 'reviewBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'reviewBy' ? ' btn-active-text' : '') . "'"); + echo html::a(inlink($app->rawMethod, "mode=requirement&type=assignedTo&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "{$lang->my->storyMenu->assignedToMe}" . ($type == 'assignedTo' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedTo' ? ' btn-active-text' : '') . "'"); + echo html::a(inlink($app->rawMethod, "mode=requirement&type=reviewBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "{$lang->my->storyMenu->reviewByMe}" . ($type == 'reviewBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'reviewBy' ? ' btn-active-text' : '') . "'"); } ?> diff --git a/module/my/view/story.html.php b/module/my/view/story.html.php index 6c52841a82..e48763c06e 100644 --- a/module/my/view/story.html.php +++ b/module/my/view/story.html.php @@ -26,8 +26,8 @@ } else { - echo html::a(inlink($app->rawMethod, "mode=story&type=assignedTo&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "{$lang->my->storyMenu->assignedToMe}" . ($type == 'assignedTo' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedTo' ? ' btn-active-text' : '') . "'"); - echo html::a(inlink($app->rawMethod, "mode=story&type=reviewBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "{$lang->my->storyMenu->reviewByMe}" . ($type == 'reviewBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'reviewBy' ? ' btn-active-text' : '') . "'"); + echo html::a(inlink($app->rawMethod, "mode=story&type=assignedTo&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "{$lang->my->storyMenu->assignedToMe}" . ($type == 'assignedTo' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedTo' ? ' btn-active-text' : '') . "'"); + echo html::a(inlink($app->rawMethod, "mode=story&type=reviewBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "{$lang->my->storyMenu->reviewByMe}" . ($type == 'reviewBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'reviewBy' ? ' btn-active-text' : '') . "'"); } ?> diff --git a/module/personnel/model.php b/module/personnel/model.php index 899273e09d..74233e628d 100644 --- a/module/personnel/model.php +++ b/module/personnel/model.php @@ -69,9 +69,15 @@ class personnelModel extends model */ public function canViewProgram($programID, $account) { - if(strpos($this->app->company->admins, ",{$account},") !== false) return true; - static $groupAcl = array(); - if(empty($groupAcl)) $groupAcl = $this->dao->select('id,acl')->from(TABLE_GROUP)->fetchPairs(); + if($this->app->user->admin) return true; + + static $groupAcl = array(); + static $groupInfo = array(); + if(empty($groupAcl)) + { + $groupAcl = $this->dao->select('id,acl')->from(TABLE_GROUP)->fetchPairs(); + foreach($groupAcl as $groupID => $group) $groupInfo[$groupID] = json_decode($groupAcl[$groupID]); + } static $userGroups = array(); if(empty($userGroups)) $userGroups = $this->dao->select('*')->from(TABLE_USERGROUP)->fetchGroup('account', 'group'); @@ -81,7 +87,7 @@ class personnelModel extends model { foreach($userGroups[$account] as $groupID => $userGroup) { - $group = json_decode($groupAcl[$groupID]); + $group = $groupInfo[$groupID]; if(!isset($group->programs)) { $programRight = true; diff --git a/module/product/control.php b/module/product/control.php index 0068fa4dec..39d8d7eaab 100644 --- a/module/product/control.php +++ b/module/product/control.php @@ -230,6 +230,8 @@ class product extends control /* Process the sql, get the conditon partion, save it to session. */ $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story', $browseType != 'bysearch' && $this->app->rawModule != 'projectstory'); + if(!empty($stories)) $stories = $this->story->mergeReviewer($stories); + /* Get related tasks, bugs, cases count of each story. */ $storyIdList = array(); foreach($stories as $story) diff --git a/module/product/model.php b/module/product/model.php index 1ec57d6c09..97d3534ca5 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -18,9 +18,10 @@ class productModel extends model * * @param array $products * @param int $productID - * @param string $currentModule - * @param string $currentMethod * @param string $extra + * @param string $branch + * @param string $module + * @param string $moduleType * * @access public * @return string @@ -314,6 +315,24 @@ class productModel extends model return $pairs; } + /** + * Get product pairs by project model. + * + * @param string $model all|scrum|waterfall + * @access public + * @return array + */ + public function getPairsByProjectModel($model) + { + return $this->dao->select('t3.id as id, t3.name as name')->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id') + ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product=t3.id') + ->where('t3.deleted')->eq(0) + ->beginIF(!$this->app->user->admin)->andWhere('t3.id')->in($this->app->user->view->products)->fi() + ->beginIF($model != 'all')->andWhere('t2.model')->eq($model) + ->fetchPairs('id', 'name'); + } + /** * Get products by project. * diff --git a/module/project/lang/de.php b/module/project/lang/de.php index d8f24063c1..e41a23d520 100644 --- a/module/project/lang/de.php +++ b/module/project/lang/de.php @@ -165,6 +165,10 @@ $lang->project->aclList['open'] = "Open (accessible with project view permiss $lang->project->acls['private'] = 'Private'; $lang->project->acls['open'] = "Open"; +$lang->project->subAclList['private'] = "Private (Only the project leader, team members and stakeholders can access)"; +$lang->project->subAclList['open'] = "Open (accessible with project view permissions)"; +$lang->project->subAclList['program'] = 'Open in the program (all upper-level program team leaders and stakeholders, the project leader, team members and stakeholders can access)'; + $lang->project->authList['extend'] = 'Inherit (system privilege and project privilege)'; $lang->project->authList['reset'] = 'Reset (project privilege only)'; diff --git a/module/project/lang/en.php b/module/project/lang/en.php index 6e40215350..0cc3c43396 100644 --- a/module/project/lang/en.php +++ b/module/project/lang/en.php @@ -170,6 +170,10 @@ $lang->project->aclList['open'] = "Open (accessible with project view permiss $lang->project->acls['private'] = 'Private'; $lang->project->acls['open'] = 'Open'; +$lang->project->subAclList['private'] = "Private (Only the project leader, team members and stakeholders can access)"; +$lang->project->subAclList['open'] = "Open (accessible with project view permissions)"; +$lang->project->subAclList['program'] = 'Open in the program (all upper-level program team leaders and stakeholders, the project leader, team members and stakeholders can access)'; + $lang->project->authList['extend'] = 'Inherit (system privilege and project privilege)'; $lang->project->authList['reset'] = 'Reset (project privilege only)'; diff --git a/module/project/lang/fr.php b/module/project/lang/fr.php index c6a2b5cda9..b3c42a7497 100644 --- a/module/project/lang/fr.php +++ b/module/project/lang/fr.php @@ -165,6 +165,10 @@ $lang->project->aclList['open'] = "Open (accessible with project view permiss $lang->project->acls['private'] = 'Private'; $lang->project->acls['open'] = "Open"; +$lang->project->subAclList['private'] = "Private (Only the project leader, team members and stakeholders can access)"; +$lang->project->subAclList['open'] = "Open (accessible with project view permissions)"; +$lang->project->subAclList['program'] = 'Open in the program (all upper-level program team leaders and stakeholders, the project leader, team members and stakeholders can access)'; + $lang->project->authList['extend'] = 'Inherit (system privilege and project privilege)'; $lang->project->authList['reset'] = 'Reset (project privilege only)'; diff --git a/module/project/lang/vi.php b/module/project/lang/vi.php index 40489cff36..f2b435f3aa 100644 --- a/module/project/lang/vi.php +++ b/module/project/lang/vi.php @@ -165,6 +165,10 @@ $lang->project->aclList['open'] = "Open (accessible with project view permiss $lang->project->acls['private'] = 'Private'; $lang->project->acls['open'] = "Open"; +$lang->project->subAclList['private'] = "Private (Only the project leader, team members and stakeholders can access)"; +$lang->project->subAclList['open'] = "Open (accessible with project view permissions)"; +$lang->project->subAclList['program'] = 'Open in the program (all upper-level program team leaders and stakeholders, the project leader, team members and stakeholders can access)'; + $lang->project->authList['extend'] = 'Inherit (system privilege and project privilege)'; $lang->project->authList['reset'] = 'Reset (project privilege only)'; diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index 42758438b6..15222d4003 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -170,6 +170,10 @@ $lang->project->aclList['open'] = "公开 (有项目视图权限即可访问) $lang->project->acls['private'] = '私有'; $lang->project->acls['open'] = '公开'; +$lang->project->subAclList['private'] = "私有 (只有本项目负责人、团队成员和干系人可访问)"; +$lang->project->subAclList['open'] = "公开 (有项目视图权限即可访问)"; +$lang->project->subAclList['program'] = '项目集内公开(所有上级项目集负责人和干系人、本项目负责人、团队成员和干系人可访问)'; + $lang->project->authList['extend'] = '继承 (取系统权限与项目权限的合集)'; $lang->project->authList['reset'] = '重新定义 (只取项目权限)'; diff --git a/module/project/view/create.html.php b/module/project/view/create.html.php index eeb6828a7a..5116b031bd 100644 --- a/module/project/view/create.html.php +++ b/module/project/view/create.html.php @@ -200,6 +200,6 @@ project->aclList, $acl, "onclick='setWhite(this.value);'", 'block'));?> diff --git a/module/project/view/edit.html.php b/module/project/view/edit.html.php index 1293fecea0..8c52ae4ae2 100644 --- a/module/project/view/edit.html.php +++ b/module/project/view/edit.html.php @@ -21,7 +21,7 @@ project->notAllowRemoveProducts);?> project->linkedProjectsTip);?> -parent ? $lang->program->subAclList : $lang->project->aclList;?> +parent ? $lang->project->subAclList : $lang->project->aclList;?> project->edit->requiredFields;?>
@@ -160,7 +160,7 @@ echo html::hidden('model', $project->model); echo html::submitButton(); $browseLink = $this->session->projectList ? $this->session->projectList : $this->createLink('project', 'browse'); - echo isonlybody() ? html::backButton() : html::a($browseLink, $lang->goback, '', 'class="btn btn-back btn-wide"'); + if(!isonlybody()) echo html::a($browseLink, $lang->goback, '', 'class="btn btn-back btn-wide"'); ?> @@ -172,7 +172,7 @@ project->aclList, $project->acl == 'project' ? 'private' : 'open', "onclick='setWhite(this.value);'", 'block'));?>