Merge branch '15.4'

This commit is contained in:
王怡栋
2021-09-02 19:21:30 +08:00
35 changed files with 228 additions and 146 deletions
-1
View File
@@ -11,7 +11,6 @@ clean:
rm -fr zentaotest
rm -fr *.tar.gz
rm -fr *.zip
rm -fr api*
rm -fr build/linux/lampp
rm -fr lampp
common:
+1 -1
View File
@@ -1345,7 +1345,7 @@ INSERT INTO `zt_group` (`id`, `name`, `role`, `desc`) VALUES
(10, 'OTHERS', 'others', 'for others.'),
(11, 'guest', 'guest', 'For guest'),
(12, 'LIMITED', 'limited', 'For limited user'),
(13, 'Project Admin', 'projectAdmin', 'Project Admins manage project privileges');
(13, 'PROJECTADMIN', 'projectAdmin', 'Project Admins manage project privileges');
INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(1,'action','comment'),
+1
View File
@@ -388,6 +388,7 @@ class buildModel extends model
$oldBuild = $this->dao->select('*')->from(TABLE_BUILD)->where('id')->eq($buildID)->fetch();
$build = fixer::input('post')->stripTags($this->config->build->editor->edit['id'], $this->config->allowedTags)
->setDefault('product', $oldBuild->product)
->setDefault('branch', $oldBuild->branch)
->cleanInt('product,branch,execution')
->remove('allchecker,resolvedBy,files,labels,uid')
->get();
+1 -1
View File
@@ -322,8 +322,8 @@ class doc extends control
$this->app->rawMethod = $objectType;
unset($this->lang->doc->menu->product['subMenu']);
unset($this->lang->doc->menu->custom['subMenu']);
unset($this->lang->doc->menu->execution['subMenu']);
if($this->config->systemMode == 'new') unset($this->lang->doc->menu->project['subMenu']);
if($this->config->systemMode == 'classic') unset($this->lang->doc->menu->execution['subMenu']);
}
/* Get libs and the default lib id. */
+2 -2
View File
@@ -1271,7 +1271,7 @@ class docModel extends model
$orderedExecutions = array();
foreach($executions as $id => $execution)
{
$execution->name = zget($projectPairs, $execution->project) . ' / ' . $execution->name;
$execution->name = $this->config->systemMode == 'new' ? zget($projectPairs, $execution->project) . ' / ' . $execution->name : $execution->name;
if($execution->status != 'done' and $execution->status != 'closed' and $execution->PM == $this->app->user->account)
{
@@ -2004,7 +2004,7 @@ class docModel extends model
if($this->app->tab == 'doc' and $type != 'custom' and $type != 'book')
{
$objectTitle = $type == 'execution' ? substr($objects[$objectID], strpos($objects[$objectID], '/') + 1) : $objects[$objectID];
$objectTitle = ($this->config->systemMode == 'new' and $type == 'execution') ? substr($objects[$objectID], strpos($objects[$objectID], '/') + 1) : $objects[$objectID];
$output = <<<EOT
<div class='btn-group angle-btn'>
+4 -1
View File
@@ -3122,9 +3122,12 @@ class execution extends control
}
$planProducts[$story->id] = $story->product;
}
$projectID = $this->dao->findByID($executionID)->from(TABLE_EXECUTION)->fetch('project');
$planStories = array_keys($planStory);
$this->execution->linkStory($executionID, $planStories, $planProducts);
if($executionID != $this->session->project) $this->execution->linkStory($this->session->project, $planStories, $planProducts);
if($this->config->systemMode == 'new' and $executionID != $projectID) $this->execution->linkStory($projectID, $planStories, $planProducts);
}
$moduleName = 'execution';
+7 -6
View File
@@ -295,12 +295,11 @@ $lang->execution->doneExecutions = 'Finished';
$lang->execution->selectDept = 'Select Department';
$lang->execution->selectDeptTitle = 'Select User';
$lang->execution->copyTeam = 'Copy Team';
$lang->execution->copyFromTeam = "Copy from {$lang->executionCommon} Team: <strong>%s</strong>";
$lang->execution->noMatched = "No $lang->executionCommon including '%s'can be found.";
$lang->execution->copyTitle = "Choose a {$lang->executionCommon} to copy.";
$lang->execution->copyTeamTitle = "Choose a {$lang->projectCommon} or {$lang->executionCommon} Team to copy.";
$lang->execution->copyNoExecution = "No {$lang->executionCommon} can be copied.";
$lang->execution->copyFromExecution = "Copy from {$lang->executionCommon} <strong>%s</strong>";
$lang->execution->copyFromTeam = "Copy from {$lang->execution->common} Team: <strong>%s</strong>";
$lang->execution->noMatched = "No {$lang->execution->common} including '%s'can be found.";
$lang->execution->copyTitle = "Choose a {$lang->execution->common} to copy.";
$lang->execution->copyNoExecution = "No {$lang->execution->common} can be copied.";
$lang->execution->copyFromExecution = "Copy from {$lang->execution->common} <strong>%s</strong>";
$lang->execution->cancelCopy = 'Cancel Copy';
$lang->execution->byPeriod = 'By Time';
$lang->execution->byUser = 'By User';
@@ -310,6 +309,8 @@ $lang->execution->noMembers = 'No team members yet. ';
$lang->execution->workloadTotal = "The cumulative workload ratio should not exceed 100, and the total workload under the current product is: %s";
// $lang->execution->linkProjectStoryTip = "(Link {$lang->SRCommon} comes from {$lang->SRCommon} linked under the execution)";
$lang->execution->linkAllStoryTip = "({$lang->SRCommon} has never been linked under the execution, and can be directly linked with {$lang->SRCommon} of the product linked with the sprint/stage)";
if($config->systemMode == 'classic') $lang->execution->copyTeamTitle = "Choose a {$lang->execution->common} Team to copy.";
if($config->systemMode == 'new') $lang->execution->copyTeamTitle = "Choose a {$lang->projectCommon} or {$lang->execution->common} Team to copy.";
/* Interactive prompts. */
$lang->execution->confirmDelete = "Do you want to delete the {$lang->executionCommon}[%s]?";
+7 -6
View File
@@ -295,12 +295,11 @@ $lang->execution->doneExecutions = '已结束';
$lang->execution->selectDept = '选择部门';
$lang->execution->selectDeptTitle = '选择一个部门的成员';
$lang->execution->copyTeam = '复制团队';
$lang->execution->copyFromTeam = "复制自{$lang->executionCommon}团队: <strong>%s</strong>";
$lang->execution->noMatched = "找不到包含'%s'的$lang->executionCommon";
$lang->execution->copyTitle = "请选择一个{$lang->executionCommon}来复制";
$lang->execution->copyTeamTitle = "选择一个{$lang->projectCommon}或{$lang->executionCommon}团队来复制";
$lang->execution->copyNoExecution = "没有可用的{$lang->executionCommon}来复制";
$lang->execution->copyFromExecution = "复制自{$lang->executionCommon} <strong>%s</strong>";
$lang->execution->copyFromTeam = "复制自{$lang->execution->common}团队: <strong>%s</strong>";
$lang->execution->noMatched = "找不到包含'%s'的{$lang->execution->common}";
$lang->execution->copyTitle = "请选择一个{$lang->execution->common}来复制";
$lang->execution->copyNoExecution = "没有可用的{$lang->execution->common}来复制";
$lang->execution->copyFromExecution = "复制自{$lang->execution->common} <strong>%s</strong>";
$lang->execution->cancelCopy = '取消复制';
$lang->execution->byPeriod = '按时间段';
$lang->execution->byUser = '按用户';
@@ -310,6 +309,8 @@ $lang->execution->noMembers = '暂时没有团队成员。';
$lang->execution->workloadTotal = "工作量占比累计不应当超过100, 当前产品下的工作量之和为%s";
// $lang->execution->linkProjectStoryTip = "(关联{$lang->SRCommon}来源于项目下所关联的{$lang->SRCommon})";
$lang->execution->linkAllStoryTip = "(项目下还未关联{$lang->SRCommon},可直接关联该{$lang->execution->common}所关联产品的{$lang->SRCommon})";
if($config->systemMode == 'classic') $lang->execution->copyTeamTitle = "选择一个{$lang->execution->common}团队来复制";
if($config->systemMode == 'new') $lang->execution->copyTeamTitle = "选择一个{$lang->projectCommon}或{$lang->execution->common}团队来复制";
/* 交互提示。*/
$lang->execution->confirmDelete = "您确定删除{$lang->executionCommon}[%s]吗?";
+7 -6
View File
@@ -295,12 +295,11 @@ $lang->execution->doneExecutions = '已結束';
$lang->execution->selectDept = '選擇部門';
$lang->execution->selectDeptTitle = '選擇一個部門的成員';
$lang->execution->copyTeam = '複製團隊';
$lang->execution->copyFromTeam = "複製自{$lang->executionCommon}團隊: <strong>%s</strong>";
$lang->execution->noMatched = "找不到包含'%s'的$lang->executionCommon";
$lang->execution->copyTitle = "請選擇一個{$lang->executionCommon}來複制";
$lang->execution->copyTeamTitle = "選擇一個{$lang->projectCommon}或{$lang->executionCommon}團隊來複制";
$lang->execution->copyNoExecution = "沒有可用的{$lang->executionCommon}來複制";
$lang->execution->copyFromExecution = "複製自{$lang->executionCommon} <strong>%s</strong>";
$lang->execution->copyFromTeam = "複製自{$lang->execution->common}團隊: <strong>%s</strong>";
$lang->execution->noMatched = "找不到包含'%s'的{$lang->execution->common}";
$lang->execution->copyTitle = "請選擇一個{$lang->execution->common}來複制";
$lang->execution->copyNoExecution = "沒有可用的{$lang->execution->common}來複制";
$lang->execution->copyFromExecution = "複製自{$lang->execution->common} <strong>%s</strong>";
$lang->execution->cancelCopy = '取消複製';
$lang->execution->byPeriod = '按時間段';
$lang->execution->byUser = '按用戶';
@@ -310,6 +309,8 @@ $lang->execution->noMembers = '暫時沒有團隊成員。';
$lang->execution->workloadTotal = "工作量占比累計不應當超過100, 當前產品下的工作量之和為%s";
// $lang->execution->linkProjectStoryTip = "(關聯{$lang->SRCommon}來源於項目下所關聯的{$lang->SRCommon})";
$lang->execution->linkAllStoryTip = "(項目下還未關聯{$lang->SRCommon},可直接關聯該{$lang->execution->common}所關聯產品的{$lang->SRCommon})";
if($config->systemMode == 'classic') $lang->execution->copyTeamTitle = "選擇一個{$lang->execution->common}團隊來複制";
if($config->systemMode == 'new') $lang->execution->copyTeamTitle = "選擇一個{$lang->projectCommon}或{$lang->execution->common}團隊來複制";
/* 交互提示。*/
$lang->execution->confirmDelete = "您確定刪除{$lang->executionCommon}[%s]嗎?";
+1 -1
View File
@@ -386,7 +386,7 @@ class executionModel extends model
/* Set team of execution. */
$members = isset($_POST['teamMembers']) ? $_POST['teamMembers'] : array();
$roles = $this->loadModel('user')->getUserRoles(array_keys($members));
$roles = $this->loadModel('user')->getUserRoles(array_values($members));
foreach($members as $account)
{
if(empty($account)) continue;
+1 -1
View File
@@ -16,7 +16,7 @@
<?php foreach($lang->execution->featureBar['all'] as $key => $label):?>
<?php echo html::a($this->createLink($this->app->rawModule, $this->app->rawMethod, "status=$key&projectID=$projectID&orderBy=$orderBy&productID=$productID"), "<span class='text'>{$label}</span>", '', "class='btn btn-link' id='{$key}Tab' data-app='$from'");?>
<?php endforeach;?>
<?php if($from == 'execution'):?>
<?php if($from == 'execution' and $this->config->systemMode == 'new'):?>
<div class='input-control w-150px'>
<?php echo html::select('project', $projects, $projectID, "class='form-control chosen' data-placeholder='{$lang->execution->selectProject}'");?>
</div>
+3 -1
View File
@@ -413,8 +413,10 @@ class gitlabModel extends model
$allResults = array();
for($page = 1; true; $page ++)
{
$results = json_decode(commonModel::http($host . "?private_token={$gitlab->token}&simple=true&page={$page}&per_page=100"));
$results = json_decode(commonModel::http($host . "?private_token={$gitlab->token}&simple=true&membership=true&page={$page}&per_page=100"));
if(isset($results->error)) break;
if(empty($results) or $page > 10) break;
$allResults = array_merge($allResults, $results);
}
+1 -1
View File
@@ -46,7 +46,7 @@
<td class='text' title='<?php echo $gitlab->url;?>'><?php echo $gitlab->url;?></td>
<td class='c-actions text-left'>
<?php
$disabled = !$gitlab->isAdminToken ? 'disabled' : '';
$disabled = !empty($gitlab->isAdminToken) ? '' : 'disabled';
common::printLink('gitlab', 'edit', "gitlabID=$id", "<i class='icon icon-edit'></i> ", '',"title={$lang->gitlab->edit} class='btn btn-primary'");
common::printLink('gitlab', 'bindUser', "id=$id", "<i class='icon icon-group'></i> ", '', "title={$lang->gitlab->bindUser} class='btn btn-primary {$disabled}' ,'disabled'");
if(common::hasPriv('gitlab', 'delete')) echo html::a($this->createLink('gitlab', 'delete', "gitlabID=$id"), '<i class="icon-trash"></i>', 'hiddenwin', "title='{$lang->gitlab->delete}' class='btn'");
+24 -22
View File
@@ -162,28 +162,30 @@ $lang->install->errorEmptyPassword = 'Password should not be blank.';
$lang->install->selectedMode = 'Selection mode';
$lang->install->selectedModeTips = 'You can go to the Admin - Custom - Mode to set it later.';
$lang->install->groupList['ADMIN']['name'] = 'Admin';
$lang->install->groupList['ADMIN']['desc'] = 'System Admin';
$lang->install->groupList['DEV']['name'] = 'Dev';
$lang->install->groupList['DEV']['desc'] = 'Developer';
$lang->install->groupList['QA']['name'] = 'Test';
$lang->install->groupList['QA']['desc'] = 'Tester';
$lang->install->groupList['PM']['name'] = 'PM';
$lang->install->groupList['PM']['desc'] = 'Project Manager';
$lang->install->groupList['PO']['name'] = 'PO';
$lang->install->groupList['PO']['desc'] = 'Product Owner';
$lang->install->groupList['TD']['name'] = 'Dev Manager';
$lang->install->groupList['TD']['desc'] = 'Development Manager';
$lang->install->groupList['PD']['name'] = 'PD';
$lang->install->groupList['PD']['desc'] = 'Product Director';
$lang->install->groupList['QD']['name'] = 'QD';
$lang->install->groupList['QD']['desc'] = 'Test Director';
$lang->install->groupList['TOP']['name'] = 'Senior';
$lang->install->groupList['TOP']['desc'] = 'Senior Manager';
$lang->install->groupList['OTHERS']['name'] = 'Others';
$lang->install->groupList['OTHERS']['desc'] = 'other users';
$lang->install->groupList['LIMITED']['name'] = 'Limited User';
$lang->install->groupList['LIMITED']['desc'] = 'Users can only edit contents related to themselves.';
$lang->install->groupList['ADMIN']['name'] = 'Admin';
$lang->install->groupList['ADMIN']['desc'] = 'System Admin';
$lang->install->groupList['DEV']['name'] = 'Dev';
$lang->install->groupList['DEV']['desc'] = 'Developer';
$lang->install->groupList['QA']['name'] = 'Test';
$lang->install->groupList['QA']['desc'] = 'Tester';
$lang->install->groupList['PM']['name'] = 'PM';
$lang->install->groupList['PM']['desc'] = 'Project Manager';
$lang->install->groupList['PO']['name'] = 'PO';
$lang->install->groupList['PO']['desc'] = 'Product Owner';
$lang->install->groupList['TD']['name'] = 'Dev Manager';
$lang->install->groupList['TD']['desc'] = 'Development Manager';
$lang->install->groupList['PD']['name'] = 'PD';
$lang->install->groupList['PD']['desc'] = 'Product Director';
$lang->install->groupList['QD']['name'] = 'QD';
$lang->install->groupList['QD']['desc'] = 'Test Director';
$lang->install->groupList['TOP']['name'] = 'Senior';
$lang->install->groupList['TOP']['desc'] = 'Senior Manager';
$lang->install->groupList['OTHERS']['name'] = 'Others';
$lang->install->groupList['OTHERS']['desc'] = 'other users';
$lang->install->groupList['LIMITED']['name'] = 'Limited User';
$lang->install->groupList['LIMITED']['desc'] = 'Users can only edit contents related to themselves.';
$lang->install->groupList['PROJECTADMIN']['name'] = 'Project Admin';
$lang->install->groupList['PROJECTADMIN']['desc'] = 'Project Admins manage project privileges';
$lang->install->cronList[''] = 'Monitor Cron';
$lang->install->cronList['moduleName=execution&methodName=computeBurn'] = 'Update Burndown Chart';
+24 -22
View File
@@ -162,28 +162,30 @@ $lang->install->errorEmptyPassword = '密码不能为空';
$lang->install->selectedMode = '选择模式';
$lang->install->selectedModeTips = '后续您还可以去后台-自定义-模式中进行调整';
$lang->install->groupList['ADMIN']['name'] = '管理员';
$lang->install->groupList['ADMIN']['desc'] = '系统管理员';
$lang->install->groupList['DEV']['name'] = '研发';
$lang->install->groupList['DEV']['desc'] = '研发人员';
$lang->install->groupList['QA']['name'] = '测试';
$lang->install->groupList['QA']['desc'] = '测试人员';
$lang->install->groupList['PM']['name'] = '项目经理';
$lang->install->groupList['PM']['desc'] = '项目经理';
$lang->install->groupList['PO']['name'] = '产品经理';
$lang->install->groupList['PO']['desc'] = '产品经理';
$lang->install->groupList['TD']['name'] = '研发主管';
$lang->install->groupList['TD']['desc'] = '研发主管';
$lang->install->groupList['PD']['name'] = '产品主管';
$lang->install->groupList['PD']['desc'] = '产品主管';
$lang->install->groupList['QD']['name'] = '测试主管';
$lang->install->groupList['QD']['desc'] = '测试主管';
$lang->install->groupList['TOP']['name'] = '高层管理';
$lang->install->groupList['TOP']['desc'] = '高层管理';
$lang->install->groupList['OTHERS']['name'] = '其他';
$lang->install->groupList['OTHERS']['desc'] = '其他';
$lang->install->groupList['LIMITED']['name'] = '受限用户';
$lang->install->groupList['LIMITED']['desc'] = '受限用户分组(只能编辑与自己相关的内容)';
$lang->install->groupList['ADMIN']['name'] = '管理员';
$lang->install->groupList['ADMIN']['desc'] = '系统管理员';
$lang->install->groupList['DEV']['name'] = '研发';
$lang->install->groupList['DEV']['desc'] = '研发人员';
$lang->install->groupList['QA']['name'] = '测试';
$lang->install->groupList['QA']['desc'] = '测试人员';
$lang->install->groupList['PM']['name'] = '项目经理';
$lang->install->groupList['PM']['desc'] = '项目经理';
$lang->install->groupList['PO']['name'] = '产品经理';
$lang->install->groupList['PO']['desc'] = '产品经理';
$lang->install->groupList['TD']['name'] = '研发主管';
$lang->install->groupList['TD']['desc'] = '研发主管';
$lang->install->groupList['PD']['name'] = '产品主管';
$lang->install->groupList['PD']['desc'] = '产品主管';
$lang->install->groupList['QD']['name'] = '测试主管';
$lang->install->groupList['QD']['desc'] = '测试主管';
$lang->install->groupList['TOP']['name'] = '高层管理';
$lang->install->groupList['TOP']['desc'] = '高层管理';
$lang->install->groupList['OTHERS']['name'] = '其他';
$lang->install->groupList['OTHERS']['desc'] = '其他';
$lang->install->groupList['LIMITED']['name'] = '受限用户';
$lang->install->groupList['LIMITED']['desc'] = '受限用户分组(只能编辑与自己相关的内容)';
$lang->install->groupList['PROJECTADMIN']['name'] = '项目管理员';
$lang->install->groupList['PROJECTADMIN']['desc'] = '项目管理员可以维护项目的权限';
$lang->install->cronList[''] = '监控定时任务';
$lang->install->cronList['moduleName=execution&methodName=computeBurn'] = '更新燃尽图';
+27 -25
View File
@@ -46,7 +46,7 @@ $lang->install->howToUse = "請問您計劃如何使用禪道的新
$lang->install->introductionContent = <<<EOT
<div>
<h4>尊敬的用戶您好,歡迎您使用禪道%s。</h4>
<p>禪道%s提供了兩種使用模式, 一種是精典管理模式,功能較為精簡,提供了產品和項目兩個核心功能;另一種是全新項目集管理模式,具備所有核心功能。如下是相關功能介紹,您可以根據需要選擇使用的模式。</p>
<p>禪道%s提供了兩種使用模式, 一種是經典管理模式,功能較為精簡,提供了產品和項目兩個核心功能;另一種是全新項目集管理模式,具備所有核心功能。如下是相關功能介紹,您可以根據需要選擇使用的模式。</p>
<div class='block-content'>
<div class='block-details'><p class='block-title'><i class='icon icon-program'></i><strong>項目集</strong></p><p>項目集是一組相互關聯,且被協調管理的項目集合,可以進行多層級管理,屬於戰略層面的管理。</p></div>
<div class='block-details block-right'>
@@ -63,8 +63,8 @@ $lang->install->introductionContent = <<<EOT
</div>
</div>
<div class='text-center introduction-link'>
<a href='https://dl.cnezsoft.com/zentao/zentaoconcept.pdf' target='_blank' class='btn btn-wide btn-info'>文檔介紹</a>
<a href='https://dl.cnezsoft.com/vedio/program0716.mp4' target='_blank' class='btn btn-wide btn-info'>視頻介紹</a>
<a href='https://dl.cnezsoft.com/zentao/zentaoconcept.pdf' target='_blank' class='btn btn-wide btn-info'><i class='icon icon-p-square'></i> 文檔介紹</a>
<a href='https://dl.cnezsoft.com/vedio/program0716.mp4' target='_blank' class='btn btn-wide btn-info'><i class='icon icon-video-play'></i> 視頻介紹</a>
</div>
</div>
EOT;
@@ -162,28 +162,30 @@ $lang->install->errorEmptyPassword = '密碼不能為空';
$lang->install->selectedMode = '選擇模式';
$lang->install->selectedModeTips = '後續您還可以去後台-自定義-模式中進行調整';
$lang->install->groupList['ADMIN']['name'] = '管理員';
$lang->install->groupList['ADMIN']['desc'] = '系統管理員';
$lang->install->groupList['DEV']['name'] = '研發';
$lang->install->groupList['DEV']['desc'] = '研發人員';
$lang->install->groupList['QA']['name'] = '測試';
$lang->install->groupList['QA']['desc'] = '測試人員';
$lang->install->groupList['PM']['name'] = '項目經理';
$lang->install->groupList['PM']['desc'] = '項目經理';
$lang->install->groupList['PO']['name'] = '產品經理';
$lang->install->groupList['PO']['desc'] = '產品經理';
$lang->install->groupList['TD']['name'] = '研發主管';
$lang->install->groupList['TD']['desc'] = '研發主管';
$lang->install->groupList['PD']['name'] = '產品主管';
$lang->install->groupList['PD']['desc'] = '產品主管';
$lang->install->groupList['QD']['name'] = '測試主管';
$lang->install->groupList['QD']['desc'] = '測試主管';
$lang->install->groupList['TOP']['name'] = '高層管理';
$lang->install->groupList['TOP']['desc'] = '高層管理';
$lang->install->groupList['OTHERS']['name'] = '其他';
$lang->install->groupList['OTHERS']['desc'] = '其他';
$lang->install->groupList['LIMITED']['name'] = '受限用戶';
$lang->install->groupList['LIMITED']['desc'] = '受限用戶分組(只能編輯與自己相關的內容)';
$lang->install->groupList['ADMIN']['name'] = '管理員';
$lang->install->groupList['ADMIN']['desc'] = '系統管理員';
$lang->install->groupList['DEV']['name'] = '研發';
$lang->install->groupList['DEV']['desc'] = '研發人員';
$lang->install->groupList['QA']['name'] = '測試';
$lang->install->groupList['QA']['desc'] = '測試人員';
$lang->install->groupList['PM']['name'] = '項目經理';
$lang->install->groupList['PM']['desc'] = '項目經理';
$lang->install->groupList['PO']['name'] = '產品經理';
$lang->install->groupList['PO']['desc'] = '產品經理';
$lang->install->groupList['TD']['name'] = '研發主管';
$lang->install->groupList['TD']['desc'] = '研發主管';
$lang->install->groupList['PD']['name'] = '產品主管';
$lang->install->groupList['PD']['desc'] = '產品主管';
$lang->install->groupList['QD']['name'] = '測試主管';
$lang->install->groupList['QD']['desc'] = '測試主管';
$lang->install->groupList['TOP']['name'] = '高層管理';
$lang->install->groupList['TOP']['desc'] = '高層管理';
$lang->install->groupList['OTHERS']['name'] = '其他';
$lang->install->groupList['OTHERS']['desc'] = '其他';
$lang->install->groupList['LIMITED']['name'] = '受限用戶';
$lang->install->groupList['LIMITED']['desc'] = '受限用戶分組(只能編輯與自己相關的內容)';
$lang->install->groupList['PROJECTADMIN']['name'] = '項目管理員';
$lang->install->groupList['PROJECTADMIN']['desc'] = '項目管理員可以維護項目的權限';
$lang->install->cronList[''] = '監控定時任務';
$lang->install->cronList['moduleName=execution&methodName=computeBurn'] = '更新燃盡圖';
+3 -2
View File
@@ -315,8 +315,9 @@ class job extends control
if($_POST)
{
$reference = new stdclass;
$reference->ref = explode("::", $refList[$this->post->ref])[1];
$reference = new stdclass;
$explodedRefs = explode("::", $refList[$this->post->ref]);
$reference->ref = $explodedRefs[1];
$variables = array();
foreach($this->post->keys as $key => $field)
+7 -1
View File
@@ -107,7 +107,13 @@
</td>
<td><span class='label-pri <?php echo 'label-pri-' . $bug->pri?>' title='<?php echo zget($lang->bug->priList, $bug->pri);?>'><?php echo zget($lang->bug->priList, $bug->pri)?></span></td>
<td class='text-left nobr'><?php echo html::a($this->createLink('bug', 'view', "bugID=$bug->id"), $bug->title, null, "style='color: $bug->color' title={$bug->title}");?></td>
<td class='text-left nobr'><?php echo html::a($this->createLink('product', 'index', "productID=$bug->product"), $bug->productName, null, "title={$bug->productName}");?></td>
<?php $param = $config->productLink == 'product-all' ? '' : "productID=$bug->product";?>
<td class='text-left nobr'>
<?php
$productLink = explode('-', $config->productLink);
echo html::a($this->createLink('product', $productLink[1], $param), $bug->productName, null, "title={$bug->productName}");
?>
</td>
<td title="<?php echo zget($lang->bug->typeList, $bug->type, '');?>"><?php echo zget($lang->bug->typeList, $bug->type, '');?></td>
<?php if($type != 'openedBy'): ?>
<td><?php echo zget($users, $bug->openedBy);?></td>
+5 -4
View File
@@ -190,10 +190,11 @@ class personnel extends control
$copyUsers = empty($copyID) ? array() : $this->personnel->getWhitelistAccount($copyID, $copyObjectType);
$appendUsers = array_unique($deptUsers + $copyUsers);
$objectName = $this->lang->projectCommon . $this->lang->execution->or . $this->lang->execution->common;
if($objectType == 'program') $objectName = $this->lang->program->common;
if($objectType == 'product') $objectName = $this->lang->productCommon;
if($objectType == 'project') $objectName = $this->lang->projectCommon;
$objectName = $this->lang->execution->common;
if($this->config->systemMode == 'new') $objectName = $this->lang->projectCommon . $this->lang->execution->or . $objectName;
if($objectType == 'program') $objectName = $this->lang->program->common;
if($objectType == 'product') $objectName = $this->lang->productCommon;
if($objectType == 'project') $objectName = $this->lang->projectCommon;
$this->lang->personnel->selectObjectTips = sprintf($this->lang->personnel->selectObjectTips, $objectName);
$this->view->title = $this->lang->personnel->addWhitelist;
+7 -4
View File
@@ -134,14 +134,17 @@ class personnelModel extends model
$issueInvest = $this->getIssueInvest($accountPairs, $projects);
$riskInvest = $this->getRiskInvest($accountPairs, $projects);
}
$userPairs = $this->loadModel('user')->getListByAccounts(array_keys($accountPairs), 'account');
foreach($userPairs as $user) $user->role = zget($this->lang->user->roleList, $user->role, $user->role);
$users = $this->loadModel('user')->getListByAccounts(array_keys($accountPairs), 'account');
foreach($users as $user) $user->role = zget($this->lang->user->roleList, $user->role, $user->role);
foreach($accountPairs as $account => $projects)
{
$personnelList[$account]['realname'] = $userPairs[$account]->realname;
$user = zget($users, $account, '');
$personnelList[$account]['realname'] = $user ? $user->realname : $account;
$personnelList[$account]['account'] = $account;
$personnelList[$account]['role'] = $userPairs[$account]->role;
$personnelList[$account]['role'] = $user ? $user->role : '';
$personnelList[$account]['projects'] = $projects;
$personnelList[$account]['executions'] = zget($executionPairs, $account, 0);
+9 -8
View File
@@ -80,22 +80,22 @@ class productplanModel extends model
public function getList($product = 0, $branch = 0, $browseType = 'all', $pager = null, $orderBy = 'begin_desc')
{
$date = date('Y-m-d');
$plans = $this->dao->select('t1.*,t2.project')->from(TABLE_PRODUCTPLAN)->alias('t1')
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on("t2.plan = t1.id and t2.product = '$product'")
->where('t1.product')->eq($product)
->andWhere('t1.deleted')->eq(0)
->beginIF(!empty($branch))->andWhere('t1.branch')->eq($branch)->fi()
->beginIF($browseType == 'unexpired')->andWhere('t1.end')->ge($date)->fi()
->beginIF($browseType == 'overdue')->andWhere('t1.end')->lt($date)->fi()
$plans = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('product')->eq($product)
->andWhere('deleted')->eq(0)
->beginIF(!empty($branch))->andWhere('branch')->eq($branch)->fi()
->beginIF($browseType == 'unexpired')->andWhere('end')->ge($date)->fi()
->beginIF($browseType == 'overdue')->andWhere('end')->lt($date)->fi()
->orderBy($orderBy)
->page($pager, 't1.id')
->page($pager)
->fetchAll('id');
if(!empty($plans))
{
$plans = $this->reorder4Children($plans);
$planIdList = array_keys($plans);
$planProjects = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('product')->eq($product)->andWhere('plan')->in(array_keys($plans))->fetchPairs('plan', 'project');
$storyCountInTable = $this->dao->select('plan,count(story) as count')->from(TABLE_PLANSTORY)->where('plan')->in($planIdList)->groupBy('plan')->fetchPairs('plan', 'count');
$product = $this->loadModel('product')->getById($product);
if($product->type == 'normal')
@@ -126,6 +126,7 @@ class productplanModel extends model
$plan->stories = count($storyPairs);
$plan->bugs = isset($bugs[$plan->id]) ? count($bugs[$plan->id]) : 0;
$plan->hour = array_sum($storyPairs);
$plan->project = zget($planProjects, $plan->id, '');
$plan->projectID = $plan->project;
/* Sync linked stories. */
+4 -1
View File
@@ -182,7 +182,10 @@ class program extends control
$program = $this->program->getByID($programID);
$parentProgram = $program->parent ? $this->program->getByID($program->parent) : '';
$parents = $this->program->getParentPairs();
unset($parents[$programID]);
/* Remove children program from parents. */
$children = $this->dao->select('*')->from(TABLE_PROGRAM)->where('path')->like("%,$programID,%")->fetchPairs('id', 'id');
foreach($children as $childID) unset($parents[$childID]);
$this->view->title = $this->lang->program->edit;
$this->view->position[] = $this->lang->program->edit;
+56 -13
View File
@@ -738,7 +738,15 @@ class programModel extends model
$this->loadModel('personnel')->updateWhitelist($whitelist, 'program', $programID);
if($program->acl != 'open') $this->loadModel('user')->updateUserView($programID, 'program');
if($oldProgram->parent != $program->parent) $this->processNode($programID, $program->parent, $oldProgram->path, $oldProgram->grade);
if($oldProgram->parent != $program->parent)
{
$this->processNode($programID, $program->parent, $oldProgram->path, $oldProgram->grade);
/* Move product to new top program. */
$oldTopProgram = $this->getTopByPath($oldProgram->path);
$newTopProgram = $this->getTopByID($programID);
if($oldTopProgram != $newTopProgram) $this->dao->update(TABLE_PRODUCT)->set('program')->eq($newTopProgram)->where('program')->eq($oldTopProgram)->exec();
}
return common::createChanges($oldProgram, $program);
}
@@ -813,25 +821,19 @@ class programModel extends model
while($program = $stmt->fetch())
{
$link = $from == 'program' ? helper::createLink($moduleName, $methodName, "programID=$program->id") : helper::createLink('product', 'all', "programID=$program->id" . $vars);
$link = $this->getLink($moduleName, $methodName, $program->id, $vars, $from);
$linkHtml = html::a($link, $program->name, '', "id='program$program->id' class='text-ellipsis' title=$program->name");
if(isset($programMenu[$program->id]) and !empty($programMenu[$program->id]))
{
if(!isset($programMenu[$program->parent])) $programMenu[$program->parent] = '';
$programMenu[$program->parent] .= "<li>$linkHtml";
$programMenu[$program->parent] .= "<ul>".$programMenu[$program->id]."</ul>\n";
$programMenu[$program->parent] .= "<ul>" . $programMenu[$program->id] . "</ul>\n";
}
else
{
if(isset($programMenu[$program->parent]) and !empty($programMenu[$program->parent]))
{
$programMenu[$program->parent] .= "<li>$linkHtml\n";
}
else
{
$programMenu[$program->parent] = "<li>$linkHtml\n";
}
if(empty($programMenu[$program->parent])) $programMenu[$program->parent] = '';
$programMenu[$program->parent] .= "<li>$linkHtml\n";
}
$programMenu[$program->parent] .= "</li>\n";
}
@@ -843,6 +845,35 @@ class programModel extends model
return $lastMenu;
}
/**
* Get link for drop tree menu.
*
* @param string $moduleName
* @param string $methodName
* @param int $programID
* @param string $vars
* @param string $from
* @access public
* @return string
*/
public function getLink($moduleName, $methodName, $programID, $vars = '', $from = 'program')
{
if($from != 'program') return helper::createLink('product', 'all', "programID=$programID" . $vars);
if($moduleName == 'project')
{
$moduleName = 'program';
$methodName = 'project';
}
if($moduleName == 'product')
{
$moduleName = 'program';
$methodName = 'product';
}
return helper::createLink($moduleName, $methodName, "programID=$programID");
}
/**
* Get top program pairs.
*
@@ -879,8 +910,20 @@ class programModel extends model
$program = $this->getByID($programID);
if(empty($program)) return 0;
$path = explode(',', trim($program->path, ','));
return $path[0];
return $this->getTopByPath($program->path);
}
/**
* get top program by path.
*
* @param string $path
* @access public
* @return string
*/
public function getTopByPath($path)
{
$paths = explode(',', trim($path, ','));
return $paths[0];
}
/**
+1
View File
@@ -400,6 +400,7 @@ class project extends control
}
if($this->app->tab == 'program') $this->loadModel('program')->setMenu($programID);
$this->session->set('projectModel', $model);
$name = '';
$code = '';
+1 -1
View File
@@ -113,7 +113,7 @@
<div class='panel-body'>
<div class='project-infos'>
<?php
$projectBudget = in_array($app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$project->budget / 10000, 2) . $lang->project->tenThousand : round((float)$project->budget, 2);
$projectBudget = in_array($app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$project->budget / 10000, 2) . $lang->project->tenThousand : round((float)$project->budget, 2);
$budgetTitle = $project->budget != 0 ? zget($lang->project->currencySymbol, $project->budgetUnit) . ' ' . $projectBudget : $lang->project->budget . $lang->project->future;
$project->end = $project->end == LONG_TIME ? $this->lang->project->longTime : $project->end;
$project->date = str_replace('-', '.', $project->begin) . ' - ' . str_replace('-', '.', $project->end);
+1 -1
View File
@@ -13,7 +13,7 @@
<div class='input-group space w-200px'>
<span class='input-group-addon'><?php echo $lang->execution->selectDept?></span>
<?php echo html::select('dept', $depts, $dept, "class='form-control chosen' onchange='setDeptUsers(this)' data-placeholder='{$lang->execution->selectDeptTitle}'");?>
<?php if(!empty(array_filter($teams2Import))):?>
<?php if(count($teams2Import) > 1):?>
<span class='input-group-addon'><?php echo $lang->execution->copyTeam;?></span>
<?php echo html::select('project', $teams2Import, $copyProjectID, "class='form-control chosen' onchange='choseTeam2Copy(this)' data-placeholder='{$lang->project->copyTeamTitle}'");?>
<?php endif;?>
+1 -1
View File
@@ -137,7 +137,7 @@ class story extends control
if($objectID != 0)
{
if($objectID != $this->session->project) $this->loadModel('action')->create('story', $storyID, 'linked2execution', '', $objectID);
$this->loadModel('action')->create('story', $storyID, 'linked2project', '', $this->session->project);
if($this->config->systemMode == 'new') $this->loadModel('action')->create('story', $storyID, 'linked2project', '', $this->session->project);
}
if($todoID > 0)
+1 -1
View File
@@ -273,7 +273,7 @@ class storyModel extends model
if($executionID != 0)
{
$this->linkStory($executionID, $this->post->product, $storyID);
if($executionID != $this->session->project) $this->linkStory($this->session->project, $this->post->product, $storyID);
if($this->config->systemMode == 'new' and $executionID != $this->session->project) $this->linkStory($this->session->project, $this->post->product, $storyID);
}
if(is_array($this->post->URS))
+2 -1
View File
@@ -465,12 +465,13 @@ class taskModel extends model
{
$task->version = 1;
$task->openedBy = $this->app->user->account;
$task->lastEditedBy = $this->app->user->account;
$task->assignedDate = isset($task->assignedTo) ? helper::now() : 0;
$task->story = 0;
$task->module = 0;
$task->estimate = 0;
$task->estStarted = '0000-00-00';
$task->left = 1;
$task->left = 0;
$task->pri = 3;
$task->type = 'devel';
+1 -1
View File
@@ -90,7 +90,7 @@ $lang->upgrade->mergeProgramDesc = <<<EOD
<p>可以选择这些{$lang->projectCommon}归属于某个新项目下。</p>
EOD;
$lang->upgrade->to15Mode['classic'] = '保持老版本的习惯';
$lang->upgrade->to15Mode['classic'] = '经典管理模式';
$lang->upgrade->to15Mode['new'] = '全新项目集管理模式';
$lang->upgrade->selectedModeTips['classic'] = '后续您还可以在后台-自定义里面切换为全新项目集管理的模式。';
+1 -1
View File
@@ -90,7 +90,7 @@ $lang->upgrade->mergeProgramDesc = <<<EOD
<p>可以選擇這些{$lang->projectCommon}歸屬於某個新項目下。</p>
EOD;
$lang->upgrade->to15Mode['classic'] = '保持老版本的習慣';
$lang->upgrade->to15Mode['classic'] = '經典管理模式';
$lang->upgrade->to15Mode['new'] = '全新項目集管理模式';
$lang->upgrade->selectedModeTips['classic'] = '後續您還可以在後台-自定義裡面切換為全新項目集管理的模式。';
+2 -1
View File
@@ -4679,6 +4679,7 @@ class upgradeModel extends model
*/
public function computeObjectMembers()
{
$this->app->loadLang('user');
$projects = $this->dao->select('id,days')->from(TABLE_PROJECT)->where('type')->eq('project')->fetchAll('id');
$projectIdList = array_keys($projects);
@@ -4747,7 +4748,7 @@ class upgradeModel extends model
$team->root = $projectID;
$team->type = 'project';
$team->account = $account;
$team->role = $user->role;
$team->role = zget($this->lang->user->roleList, $user->role, $user->role);
$team->join = $today;
$team->days = $project->days;
$team->hours = '7.0';
+7 -3
View File
@@ -1588,13 +1588,15 @@ class userModel extends model
/* Get teams. */
if($teams === null)
{
$stmt = $this->dao->select('root,account')->from(TABLE_TEAM)->where('type')->in('project,execution')->query();
$teams = array();
$stmt = $this->dao->select('root,account')->from(TABLE_TEAM)->where('type')->in('project,execution')->query();
while($team = $stmt->fetch()) $teams[$team->root][$team->account] = $team->account;
}
/* Get product white list. */
if($productWhiteList === null)
{
$productWhiteList = array();
$stmt = $this->dao->select('objectID,account')->from(TABLE_ACL)->where('objectType')->eq('product')->query();
while($acl = $stmt->fetch()) $productWhiteList[$acl->objectID][$acl->account] = $acl->account;
}
@@ -1602,14 +1604,16 @@ class userModel extends model
/* Get white list. */
if($whiteList === null)
{
$stmt = $this->dao->select('objectID,account')->from(TABLE_ACL)->where('objectType')->in('program,project,sprint')->query();
$whiteList = array();
$stmt = $this->dao->select('objectID,account')->from(TABLE_ACL)->where('objectType')->in('program,project,sprint')->query();
while($acl = $stmt->fetch()) $whiteList[$acl->objectID][$acl->account] = $acl->account;
}
/* Get stakeholders. */
if($stakeholders === null)
{
$stmt = $this->dao->select('objectID,user')->from(TABLE_STAKEHOLDER)->query();
$stakeholders = array();
$stmt = $this->dao->select('objectID,user')->from(TABLE_STAKEHOLDER)->query();
while($stakeholder = $stmt->fetch()) $stakeholders[$stakeholder->objectID][$stakeholder->user] = $stakeholder->user;
}
+6 -3
View File
@@ -12,11 +12,11 @@ $jsRoot = $baseDir . '/www/js/';
$jqueryRoot = $jsRoot . 'jquery/';
/* Set js files to combined. */
$jsFiles[] = $jqueryRoot . 'lib.js';
$jsFiles[] = $jqueryRoot . 'lib.js';
$jsFiles[] = $jqueryRoot . 'tablesorter/min.js';
$jsFiles[] = $jqueryRoot . 'tablesorter/metadata.js';
$jsFiles[] = $jsRoot . 'zui/min.js';
$jsFiles[] = $jsRoot . 'zui/picker/zui.picker.min.js';
$jsFiles[] = $jsRoot . 'zui/min.js';
$jsFiles[] = $jsRoot . 'zui/picker/zui.picker.min.js';
$jsFiles[] = $jsRoot . 'my.full.js';
/* Combine these js files. */
@@ -39,6 +39,9 @@ $config->programLink = '-';
$config->productLink = '-';
$config->projectLink = '-';
$config->executionLink = '-';
$config->systemMode = '';
$config->URAndSR = '';
$config->systemScore = '';
include $baseDir . '/config/config.php';
$lang = new stdclass();
+2 -2
View File
File diff suppressed because one or more lines are too long