* merge current 18.x into ai.

This commit is contained in:
liwenrui
2023-08-16 10:28:06 +08:00
1522 changed files with 26414 additions and 902918 deletions
+2
View File
@@ -144,6 +144,7 @@ $config->project->checkList->waterfall = array('execution', 'design', 'doc',
$config->project->checkList->kanban = array('execution', 'build');
$config->project->checkList->agileplus = $config->project->checkList->scrum;
$config->project->checkList->waterfallplus = $config->project->checkList->waterfall;
$config->project->checkList->ipd = $config->project->checkList->waterfall;
$config->project->maxCheckList = new stdclass();
$config->project->maxCheckList->scrum = array('bug', 'execution', 'build', 'doc', 'release', 'testtask', 'case', 'issue', 'risk', 'meeting');
@@ -151,6 +152,7 @@ $config->project->maxCheckList->waterfall = array('execution', 'design', 'do
$config->project->maxCheckList->kanban = array('execution', 'build');
$config->project->maxCheckList->agileplus = $config->project->maxCheckList->scrum;
$config->project->maxCheckList->waterfallplus = $config->project->maxCheckList->waterfall;
$config->project->maxCheckList->ipd = $config->project->maxCheckList->waterfall;
$config->project->search['module'] = 'project';
$config->project->search['fields']['name'] = $lang->project->name;
+37 -38
View File
@@ -137,11 +137,14 @@ class project extends control
->orderBy('order_asc,id_desc')
->fetchAll('id');
$parents = array_column($projects, 'parent');
$parents = $this->dao->select('id,path')->from(TABLE_PROJECT)->where('id')->in($parents)->fetchAll('id');
$programs = $this->program->getPairs(true);
foreach($projects as $project)
{
$project->parent = $this->program->getTopByID($project->parent);
$project->parent = isset($parents[$project->id]) ? $this->program->getTopByPath($parents[$project->id]) : 0;
$project->parent = isset($programs[$project->parent]) ? $project->parent : $project->id;
$orderedProjects[$project->parent][] = $project;
unset($projects[$project->id]);
@@ -405,11 +408,12 @@ class project extends control
$actionURL = $this->createLink('project', 'browse', "&programID=$programID&browseType=bySearch&queryID=myQueryID");
$this->project->buildSearchForm($queryID, $actionURL);
$this->loadModel('program')->refreshStats(); // Refresh stats fields of projects.
$programTitle = $this->loadModel('setting')->getItem('owner=' . $this->app->user->account . '&module=project&key=programTitle');
$projectStats = $this->loadModel('program')->getProjectStats($programID, $browseType, $queryID, $orderBy, $pager, $programTitle);
$this->view->title = $this->lang->project->browse;
$this->view->projectStats = $projectStats;
$this->view->projectStats = $this->program->getProjectStats($programID, $browseType, $queryID, $orderBy, $pager, $programTitle);
$this->view->pager = $pager;
$this->view->programID = $programID;
$this->view->program = $this->program->getByID($programID);
@@ -426,7 +430,6 @@ class project extends control
$this->view->recPerPage = $recPerPage;
$this->view->pageID = $pageID;
$this->view->showBatchEdit = $this->cookie->showProjectBatchEdit;
$this->view->allProjectsNum = $this->loadModel('program')->getProjectStats($programID, 'all');
$this->display();
}
@@ -515,7 +518,7 @@ class project extends control
{
foreach($planStory as $id => $story)
{
if($story->status == 'draft' or $story->status == 'reviewing')
if($story->status != 'active')
{
unset($planStory[$id]);
continue;
@@ -875,14 +878,14 @@ class project extends control
$projectID = $this->project->setMenu($projectID);
$project = $this->project->getById($projectID);
if($this->config->systemMode == 'ALM')
if(in_array($this->config->systemMode, array('ALM', 'PLM')))
{
$programList = array_filter(explode(',', $project->path));
array_pop($programList);
$this->view->programList = $this->loadModel('program')->getPairsByList($programList);
}
if(empty($project) || strpos('scrum,waterfall,kanban,agileplus,waterfallplus', $project->model) === false)
if(empty($project) || strpos('scrum,waterfall,kanban,agileplus,waterfallplus,ipd', $project->model) === false)
{
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'code' => 404, 'message' => '404 Not found'));
return print(js::error($this->lang->notFound) . js::locate($this->createLink('project', 'browse')));
@@ -898,10 +901,6 @@ class project extends control
}
}
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager(0, 30, 1);
/* Check exist extend fields. */
$isExtended = false;
if($this->config->edition != 'open')
@@ -924,7 +923,7 @@ class project extends control
$this->view->workhour = $this->project->getWorkhour($projectID);
$this->view->planGroup = $this->loadModel('execution')->getPlans($products);
$this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), '', $linkedBranches);
$this->view->dynamics = $this->loadModel('action')->getDynamic('all', 'all', 'date_desc', $pager, 'all', $projectID);
$this->view->dynamics = $this->loadModel('action')->getDynamic('all', 'all', 'date_desc', 30, 'all', $projectID);
$this->view->isExtended = $isExtended;
$this->display();
@@ -1017,7 +1016,7 @@ class project extends control
$this->session->set('testtaskList', $uri, 'qa');
$this->session->set('reportList', $uri, 'qa');
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
$this->session->set('riskList', $uri, 'project');
$this->session->set('issueList', $uri, 'project');
@@ -1026,10 +1025,6 @@ class project extends control
/* Append id for secend sort. */
$orderBy = $direction == 'next' ? 'date_desc' : 'date_asc';
/* Set the pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage = 50, $pageID = 1);
/* Set the user and type. */
$account = 'all';
if($type == 'account')
@@ -1037,30 +1032,27 @@ class project extends control
$user = $this->loadModel('user')->getById($param, 'account');
if($user) $account = $user->account;
}
$period = $type == 'account' ? 'all' : $type;
$date = empty($date) ? '' : date('Y-m-d', $date);
$actions = $this->loadModel('action')->getDynamic($account, $period, $orderBy, $pager, 'all', $projectID, 'all', $date, $direction);
if(empty($recTotal)) $recTotal = count($actions);
$period = $type == 'account' ? 'all' : $type;
$date = empty($date) ? '' : date('Y-m-d', $date);
$actions = $this->loadModel('action')->getDynamic($account, $period, $orderBy, 50, 'all', $projectID, 'all', $date, $direction);
$dateGroups = $this->action->buildDateGroup($actions, $direction, $type);
if(empty($recTotal)) $recTotal = count($dateGroups) < 2 ? count($actions) : $this->action->getDynamicCount();
/* The header and position. */
$project = $this->project->getByID($projectID);
$this->view->title = $project->name . $this->lang->colon . $this->lang->project->dynamic;
$this->view->position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name);
$this->view->position[] = $this->lang->project->dynamic;
$this->view->userIdPairs = $this->loadModel('user')->getTeamMemberPairs($projectID, 'project');
$this->view->accountPairs = $this->user->getPairs('noletter|nodeleted');
/* Assign. */
$this->view->projectID = $projectID;
$this->view->type = $type;
$this->view->orderBy = $orderBy;
$this->view->pager = $pager;
$this->view->account = $account;
$this->view->param = $param;
$this->view->dateGroups = $this->action->buildDateGroup($actions, $direction, $type);
$this->view->direction = $direction;
$this->view->recTotal = $recTotal;
$this->view->title = $project->name . $this->lang->colon . $this->lang->project->dynamic;
$this->view->userIdPairs = $this->loadModel('user')->getTeamMemberPairs($projectID, 'project');
$this->view->accountPairs = $this->user->getPairs('noletter|nodeleted');
$this->view->projectID = $projectID;
$this->view->type = $type;
$this->view->orderBy = $orderBy;
$this->view->account = $account;
$this->view->param = $param;
$this->view->dateGroups = $dateGroups;
$this->view->direction = $direction;
$this->view->recTotal = $recTotal;
$this->display();
}
@@ -1098,6 +1090,8 @@ class project extends control
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$this->loadModel('program')->refreshStats(); // Refresh stats fields of projects.
$allExecution = $this->execution->getStatData($projectID, 'all');
$this->view->allExecutionNum = empty($allExecution);
@@ -1122,6 +1116,11 @@ class project extends control
}
$changeStatusHtml .= "</div></div></div>";
if($project->model == 'ipd' and $this->config->edition == 'ipd')
{
$this->view->reviewPoints = $this->loadModel('review')->getReviewPointByProject($projectID);
}
$this->view->executionStats = $executionStats;
$this->view->showToggleIcon = $showToggleIcon;
$this->view->productList = $this->loadModel('product')->getProductPairsByProject($projectID, 'all', '', false);
@@ -1134,7 +1133,7 @@ class project extends control
$this->view->orderBy = $orderBy;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->status = $status;
$this->view->isStage = (isset($project->model) and ($project->model == 'waterfall' or $project->model == 'waterfallplus')) ? true : false;
$this->view->isStage = (isset($project->model) and in_array($project->model, array('waterfall', 'waterfallplus', 'ipd'))) ? true : false;
$this->view->changeStatusHtml = common::hasPriv('execution', 'batchChangeStatus') ? $changeStatusHtml : '';
$this->display();
+3 -1
View File
@@ -139,7 +139,7 @@ function computeEndDate(delta)
}
/**
* Initialization operation.
* Initialization.
*
* @access public
* @return void
@@ -160,6 +160,8 @@ $(function()
$(this).parents('tr').find('input[type=checkbox]').prop('checked', checked);
}
});
$('#subNavbar').find('li[data-id=module] a').attr('data-app', 'project');
})
/**
+2 -2
View File
@@ -1,6 +1,6 @@
$(function()
{
$('[name=hasProduct]').change(function()
$(document).on('change', '[name=hasProduct]', function()
{
const hasProduct = $('[name=hasProduct]:checked').val();
@@ -17,7 +17,7 @@ $(function()
});
if(chosenProducts > 1) $('.division').removeClass('hide');
}
});
})
$('[name=hasProduct]').change();
+6
View File
@@ -9,6 +9,12 @@ $(function()
$('input#editExecution1').prop('disabled', show).attr('title', show == 1 ? disabledExecutionTip : defaultExecutionTip);
window.location.reload();
});
$('input[name^="showStage"]').click(function()
{
var show = $(this).is(':checked') ? 1 : 0;
$.cookie('showStage', show, {expires:config.cookieLife, path:config.webRoot});
window.location.reload();
});
if($.cookie('showTask') == 1) $('input#editExecution1').prop('disabled', true).attr('title', disabledExecutionTip);
$('input#editExecution1').click(function()
+5 -1
View File
@@ -1,4 +1,6 @@
<?php
global $config;
/* Actions. */
$lang->project->createGuide = 'Select Template';
$lang->project->index = 'Dashboard';
@@ -267,6 +269,7 @@ $lang->project->currencySymbol['THB'] = '฿';
$lang->project->currencySymbol['SGD'] = 'S$';
$lang->project->modelList[''] = '';
$lang->project->modelList['ipd'] = "IPD";
$lang->project->modelList['scrum'] = "Scrum";
if(helper::hasFeature('waterfall')) $lang->project->modelList['waterfall'] = "CMMI";
$lang->project->modelList['kanban'] = "Kanban";
@@ -327,7 +330,6 @@ $lang->project->kanbanSubAclList['private'] = "Private (Only the {$lang->project
$lang->project->kanbanSubAclList['open'] = "Open (accessible with {$lang->projectCommon} view permissions)";
$lang->project->kanbanSubAclList['program'] = "Open in the program (all upper-level program team leaders and stakeholders, the {$lang->projectCommon} leader, team members can access)";
global $config;
if($config->systemMode == 'light')
{
unset($lang->project->subAclList['program']);
@@ -350,6 +352,7 @@ $lang->project->endList[186] = 'Half year';
$lang->project->endList[365] = 'One year';
$lang->project->endList[999] = 'Longtime';
$lang->project->ipdTitle = "Integrated Product Development";
$lang->project->scrumTitle = 'Agile Development Management';
$lang->project->waterfallTitle = "Waterfall {$lang->projectCommon} Management";
$lang->project->kanbanTitle = "Kanban {$lang->projectCommon} Management";
@@ -364,6 +367,7 @@ $lang->project->membersUnit = '%s men';
$lang->project->lastIteration = "Recent {$lang->executionCommon}";
$lang->project->lastKanban = 'Recent Kanban';
$lang->project->ongoingStage = 'Ongoing stage';
$lang->project->ipd = 'IPD';
$lang->project->scrum = 'Scrum';
$lang->project->waterfall = 'Waterfall';
$lang->project->agileplus = 'Agile +';
+5 -1
View File
@@ -1,4 +1,6 @@
<?php
global $config;
/* Actions. */
$lang->project->createGuide = 'Select Template';
$lang->project->index = 'Dashboard';
@@ -267,6 +269,7 @@ $lang->project->currencySymbol['THB'] = '฿';
$lang->project->currencySymbol['SGD'] = 'S$';
$lang->project->modelList[''] = '';
$lang->project->modelList['ipd'] = "IPD";
$lang->project->modelList['scrum'] = "Scrum";
if(helper::hasFeature('waterfall')) $lang->project->modelList['waterfall'] = "CMMI";
$lang->project->modelList['kanban'] = "Kanban";
@@ -327,7 +330,6 @@ $lang->project->kanbanSubAclList['private'] = "Private (Only the {$lang->project
$lang->project->kanbanSubAclList['open'] = "Open (accessible with {$lang->projectCommon} view permissions)";
$lang->project->kanbanSubAclList['program'] = "Open in the program (all upper-level program team leaders and stakeholders, the {$lang->projectCommon} leader, team members can access)";
global $config;
if($config->systemMode == 'light')
{
unset($lang->project->subAclList['program']);
@@ -350,6 +352,7 @@ $lang->project->endList[186] = 'Half year';
$lang->project->endList[365] = 'One year';
$lang->project->endList[999] = 'Longtime';
$lang->project->ipdTitle = "Integrated Product Development";
$lang->project->scrumTitle = 'Agile Development Management';
$lang->project->waterfallTitle = "Waterfall {$lang->projectCommon} Management";
$lang->project->kanbanTitle = "Kanban {$lang->projectCommon} Management";
@@ -364,6 +367,7 @@ $lang->project->membersUnit = '%s men';
$lang->project->lastIteration = "Recent {$lang->executionCommon}";
$lang->project->lastKanban = 'Recent Kanban';
$lang->project->ongoingStage = 'Ongoing stage';
$lang->project->ipd = 'IPD';
$lang->project->scrum = 'Scrum';
$lang->project->waterfall = 'Waterfall';
$lang->project->agileplus = 'Agile +';
+5 -1
View File
@@ -1,4 +1,6 @@
<?php
global $config;
/* Actions. */
$lang->project->createGuide = 'Select Template';
$lang->project->index = 'Dashboard';
@@ -267,6 +269,7 @@ $lang->project->currencySymbol['THB'] = '฿';
$lang->project->currencySymbol['SGD'] = 'S$';
$lang->project->modelList[''] = '';
$lang->project->modelList['ipd'] = "IPD";
$lang->project->modelList['scrum'] = "Scrum";
if(helper::hasFeature('waterfall')) $lang->project->modelList['waterfall'] = "CMMI";
$lang->project->modelList['kanban'] = "Kanban";
@@ -327,7 +330,6 @@ $lang->project->kanbanSubAclList['private'] = "Private (Only the {$lang->project
$lang->project->kanbanSubAclList['open'] = "Open (accessible with {$lang->projectCommon} view permissions)";
$lang->project->kanbanSubAclList['program'] = "Open in the program (all upper-level program team leaders and stakeholders, the {$lang->projectCommon} leader, team members can access)";
global $config;
if($config->systemMode == 'light')
{
unset($lang->project->subAclList['program']);
@@ -350,6 +352,7 @@ $lang->project->endList[186] = 'Half year';
$lang->project->endList[365] = 'One year';
$lang->project->endList[999] = 'Longtime';
$lang->project->ipdTitle = "Integrated Product Development";
$lang->project->scrumTitle = 'Agile Development Management';
$lang->project->waterfallTitle = "Waterfall {$lang->projectCommon} Management";
$lang->project->kanbanTitle = "Kanban {$lang->projectCommon} Management";
@@ -364,6 +367,7 @@ $lang->project->membersUnit = '%s men';
$lang->project->lastIteration = "Recent {$lang->executionCommon}";
$lang->project->lastKanban = 'Recent Kanban';
$lang->project->ongoingStage = 'Ongoing stage';
$lang->project->ipd = 'IPD';
$lang->project->scrum = 'Scrum';
$lang->project->waterfall = 'Waterfall';
$lang->project->agileplus = 'Agile +';
+5 -1
View File
@@ -1,4 +1,6 @@
<?php
global $config;
/* Actions. */
$lang->project->createGuide = "选择{$lang->projectCommon}模板";
$lang->project->index = "{$lang->projectCommon}仪表盘";
@@ -267,6 +269,7 @@ $lang->project->currencySymbol['THB'] = '฿';
$lang->project->currencySymbol['SGD'] = 'S$';
$lang->project->modelList[''] = "";
$lang->project->modelList['ipd'] = "IPD";
$lang->project->modelList['scrum'] = "Scrum";
if(helper::hasFeature('waterfall')) $lang->project->modelList['waterfall'] = "瀑布";
$lang->project->modelList['kanban'] = "看板";
@@ -327,7 +330,6 @@ $lang->project->kanbanSubAclList['private'] = "私有 (只有{$lang->projectComm
$lang->project->kanbanSubAclList['open'] = "公开 (有{$lang->projectCommon}视图权限即可访问)";
$lang->project->kanbanSubAclList['program'] = "项目集内公开(所有上级项目集负责人和干系人、{$lang->projectCommon}负责人、团队成员可访问)";
global $config;
if($config->systemMode == 'light')
{
unset($lang->project->subAclList['program']);
@@ -350,6 +352,7 @@ $lang->project->endList[186] = '半年';
$lang->project->endList[365] = '一年';
$lang->project->endList[999] = '长期';
$lang->project->ipdTitle = "集成产品开发";
$lang->project->scrumTitle = "敏捷开发全流程{$lang->projectCommon}管理";
$lang->project->waterfallTitle = "瀑布式{$lang->projectCommon}管理";
$lang->project->kanbanTitle = "专业研发看板{$lang->projectCommon}管理";
@@ -364,6 +367,7 @@ $lang->project->membersUnit = '%s人';
$lang->project->lastIteration = "近期{$lang->executionCommon}";
$lang->project->lastKanban = '近期看板';
$lang->project->ongoingStage = '进行中的阶段';
$lang->project->ipd = 'IPD';
$lang->project->scrum = 'Scrum';
$lang->project->waterfall = '瀑布';
$lang->project->agileplus = '融合敏捷';
+67 -51
View File
@@ -10,11 +10,7 @@ class projectModel extends model
*/
public function checkPriv($projectID)
{
if(empty($projectID)) return false;
/* If is admin, return true. */
if($this->app->user->admin) return true;
return (strpos(",{$this->app->user->view->projects},", ",{$projectID},") !== false);
return !empty($projectID) && ($this->app->user->admin || (strpos(",{$this->app->user->view->projects},", ",{$projectID},") !== false));
}
/**
@@ -236,32 +232,22 @@ class projectModel extends model
$projects = $this->loadModel('program')->getProjectList(0, $status, 0, $orderBy, $pager, 0, $involved);
if(empty($projects)) return array();
$projectIdList = array_keys($projects);
$teams = $this->dao->select('t1.root, count(t1.id) as count')->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account=t2.account')
->where('t1.root')->in($projectIdList)
->andWhere('t2.deleted')->eq(0)
->groupBy('t1.root')
->fetchAll('root');
$projectParentNames = $this->getParentProgram($projects);
$estimates = $this->dao->select("t2.project as project, sum(t1.estimate) as estimate")->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution = t2.id')
->where('t1.parent')->lt(1)
->andWhere('t2.project')->in($projectIdList)
->andWhere('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->groupBy('t2.project')
->fetchAll('project');
$executions = $this->dao->select('*')->from(TABLE_EXECUTION)
->where('project')->in(array_keys($projects))
->andWhere('status')->notin('done,closed')
->andWhere('deleted')->eq(0)
->orderBy($orderBy)
->fetchGroup('project');
$this->app->loadClass('pager', $static = true);
foreach($projects as $projectID => $project)
{
$orderBy = $project->model == 'waterfall' ? 'id_asc' : 'id_desc';
$pager = $project->model == 'waterfall' ? null : new pager(0, 1, 1);
$project->executions = $this->loadModel('execution')->getStatData($projectID, 'undone', 0, 0, false, '', $orderBy, $pager);
$project->teamCount = isset($teams[$projectID]) ? $teams[$projectID]->count : 0;
$project->estimate = isset($estimates[$projectID]) ? round($estimates[$projectID]->estimate, 2) : 0;
$project->parentName = $this->getParentProgram($project);
$project->executions = isset($executions[$projectID]) ? $executions[$projectID] : array();
$project->parentName = $projectParentNames[$project->id];
}
return $projects;
}
@@ -269,21 +255,45 @@ class projectModel extends model
/**
* Get all parent program of a program.
*
* @param int $parentID
* @param array $projects
* @access public
* @return string
* @return array
*/
public function getParentProgram($project)
public function getParentProgram($projects)
{
if($project->parent == 0) return '';
if(empty($projects)) return array();
$parentName = $this->dao->select('id,name')->from(TABLE_PROGRAM)->where('id')->in(trim($project->path, ','))->andWhere('grade')->lt($project->grade)->orderBy('grade asc')->fetchPairs();
$parents = array();
$projectParents = array();
foreach($projects as $project)
{
$projectParents[$project->id] = array();
$parentProgram = '';
foreach($parentName as $name) $parentProgram .= $name . '/';
$parentProgram = rtrim($parentProgram, '/');
if(!$project->parent) continue;
return $parentProgram;
foreach(explode(',', trim($project->path, ',')) as $parent)
{
if($parent == $project->id) continue;
$parents[$parent] = $parent;
$projectParents[$project->id][] = $parent;
}
}
$parentNames = $this->dao->select('id,name')->from(TABLE_PROGRAM)->where('id')->in($parents)->fetchPairs();
foreach($projectParents as $projectID => $parents)
{
$programNames = array();
foreach($parents as $parent)
{
$programNames[] = $parentNames[$parent];
}
$projectParents[$projectID] = implode('/', $programNames);
}
return $projectParents;
}
/**
@@ -385,12 +395,11 @@ class projectModel extends model
*/
public function getTotalTaskByProject($projectIdList)
{
return $this->dao->select("t1.project, count(t1.id) as allTasks, count(if(t1.status = 'wait', 1, null)) as waitTasks, count(if(t1.status = 'doing', 1, null)) as doingTasks, count(if(t1.status = 'done', 1, null)) as doneTasks, count(if(t1.status = 'wait' or t1.status = 'pause' or t1.status = 'cancel', 1, null)) as leftTasks, count(if(t1.status = 'done' or t1.status = 'closed', 1, null)) as litedoneTasks")->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution=t2.id')
->where('t1.project')->in($projectIdList)
->andWhere('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->groupBy('t1.project')
$executionIdList = $this->dao->select('id')->from(TABLE_EXECUTION)->where('project')->in($projectIdList)->andWhere('deleted')->eq(0)->fetchPairs();
return $this->dao->select("project, count(id) as allTasks, count(if(status = 'wait', 1, null)) as waitTasks, count(if(status = 'doing', 1, null)) as doingTasks, count(if(status = 'done', 1, null)) as doneTasks, count(if(status = 'wait' or status = 'pause' or status = 'cancel', 1, null)) as leftTasks, count(if(status = 'done' or status = 'closed', 1, null)) as litedoneTasks")->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->andWhere('deleted')->eq(0)
->groupBy('project')
->fetchAll('project');
}
@@ -523,9 +532,11 @@ class projectModel extends model
$workhour = new stdclass();
$workhour->totalHours = $this->dao->select('sum(t1.days * t1.hours) AS totalHours')->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.root=t2.id')
->leftJoin(TABLE_USER)->alias('t3')->on('t1.account=t3.account')
->where('t2.id')->in($projectID)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.type')->eq('project')
->andWhere('t3.deleted')->eq(0)
->fetch('totalHours');
$workhour->totalEstimate = $total->totalEstimate;
$workhour->totalConsumed = $totalConsumed;
@@ -1233,6 +1244,7 @@ class projectModel extends model
->setIF($this->post->acl == 'open', 'whitelist', '')
->setIF(!isset($_POST['whitelist']), 'whitelist', '')
->setIF(!isset($_POST['multiple']), 'multiple', '1')
->setIF($this->post->model == 'ipd', 'division', '0')
->setDefault('openedBy', $this->app->user->account)
->setDefault('openedDate', helper::now())
->setDefault('team', $this->post->name)
@@ -1258,7 +1270,7 @@ class projectModel extends model
}
}
if($_POST['products'])
if($_POST['products'] and $this->post->model != 'ipd')
{
$topProgramID = $this->loadModel('program')->getTopByID($project->parent);
$multipleProducts = $this->loadModel('product')->getMultiBranchPairs($topProgramID);
@@ -1546,7 +1558,7 @@ class projectModel extends model
if(dao::isError()) return false;
}
if($_POST['products'])
if($_POST['products'] and $oldProject->model != 'ipd')
{
$topProgramID = $this->loadModel('program')->getTopByID($project->parent);
$multipleProducts = $this->loadModel('product')->getMultiBranchPairs($topProgramID);
@@ -2401,7 +2413,9 @@ class projectModel extends model
{
$this->loadModel('user');
$members = array_keys($this->getTeamMembers($projectID));
$teams = array_keys($this->getTeamMembers($projectID));
$stakeholders = array_keys($this->loadModel('stakeholder')->getStakeHolderPairs($projectID));
$members = array_merge($teams, $stakeholders);
/* Link products of other programs. */
if(!empty($_POST['otherProducts']))
@@ -2796,8 +2810,11 @@ class projectModel extends model
}
}
if($project and $project->model == 'waterfall') $model = $project->model;
if($project and $project->model == 'waterfallplus') $model = 'waterfall';
if($project)
{
if(in_array($project->model, array('waterfall', 'waterfallplus'))) $model = 'waterfall';
if($project->model == 'ipd') $model = 'ipd';
}
if($project and $project->model == 'kanban')
{
$model = $project->model . 'Project';
@@ -2812,9 +2829,8 @@ class projectModel extends model
$lang->project->dividerMenu = $lang->{$model}->dividerMenu;
}
if(empty($project->hasProduct))
if(empty($project->hasProduct) or $model == 'ipd')
{
unset($lang->project->menu->settings['subMenu']->products);
$projectProduct = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($objectID)->fetch('product');
$lang->project->menu->settings['subMenu']->module['link'] = sprintf($lang->project->menu->settings['subMenu']->module['link'], $projectProduct);
@@ -2838,8 +2854,6 @@ class projectModel extends model
$lang->project->menu->story['dropMenu']->story['link'] = sprintf($lang->project->menu->storyGroup['dropMenu']->story['link'], '%s', $projectProduct);
$lang->project->menu->story['dropMenu']->requirement['link'] = sprintf($lang->project->menu->storyGroup['dropMenu']->requirement['link'], '%s', $projectProduct);
}
unset($lang->project->menu->settings['subMenu']->products);
}
}
else
@@ -2848,7 +2862,9 @@ class projectModel extends model
unset($lang->project->menu->projectplan);
}
if(isset($lang->project->menu->storyGroup)) unset($lang->project->menu->storyGroup);
if(isset($lang->project->menu->storyGroup)) unset($lang->project->menu->storyGroup);
if($model != 'ipd' and $project->hasProduct) unset($lang->project->menu->settings['subMenu']->module);
if(empty($project->hasProduct)) unset($lang->project->menu->settings['subMenu']->products);
/* Reset project priv. */
$moduleName = $this->app->rawModule;
@@ -2856,7 +2872,7 @@ class projectModel extends model
$this->loadModel('common')->resetProjectPriv($objectID);
if(!$this->common->isOpenMethod($moduleName, $methodName) and !commonModel::hasPriv($moduleName, $methodName)) $this->common->deny($moduleName, $methodName, false);
if(isset($project->model) and ($project->model == 'waterfall' or $project->model == 'waterfallplus'))
if(isset($project->model) and (in_array($project->model, array('waterfall', 'waterfallplus', 'ipd'))))
{
$lang->project->createExecution = str_replace($lang->executionCommon, $lang->project->stage, $lang->project->createExecution);
$lang->project->lastIteration = str_replace($lang->executionCommon, $lang->project->stage, $lang->project->lastIteration);
@@ -2998,7 +3014,7 @@ class projectModel extends model
public function checkCanChangeModel($projectID, $model)
{
$checkList = $this->config->project->checkList->$model;
if($this->config->edition == 'max') $checkList = $this->config->project->maxCheckList->$model;
if($this->config->edition == 'max' or $this->config->edition == 'ipd') $checkList = $this->config->project->maxCheckList->$model;
foreach($checkList as $module)
{
if($module == '') continue;
+5 -5
View File
@@ -54,15 +54,15 @@ foreach($projects as $programID => $programProjects)
}
$projectsPinYin = common::convert2Pinyin($projectNames);
$myProjectsHtml = $config->systemMode == 'ALM' ? '<ul class="tree tree-angles" data-ride="tree">' : '<ul class="tree noProgram">';
$normalProjectsHtml = $config->systemMode == 'ALM' ? '<ul class="tree tree-angles" data-ride="tree">' : '<ul class="tree noProgram">';
$closedProjectsHtml = $config->systemMode == 'ALM' ? '<ul class="tree tree-angles" data-ride="tree">' : '<ul class="tree noProgram">';
$myProjectsHtml = in_array($config->systemMode, array('ALM', 'PLM')) ? '<ul class="tree tree-angles" data-ride="tree">' : '<ul class="tree noProgram">';
$normalProjectsHtml = in_array($config->systemMode, array('ALM', 'PLM')) ? '<ul class="tree tree-angles" data-ride="tree">' : '<ul class="tree noProgram">';
$closedProjectsHtml = in_array($config->systemMode, array('ALM', 'PLM')) ? '<ul class="tree tree-angles" data-ride="tree">' : '<ul class="tree noProgram">';
$indexLink = helper::createLink('project', 'index', "projectID=%s");
foreach($projects as $programID => $programProjects)
{
/* Add the program name before project. */
if(isset($programs[$programID]) and $config->systemMode == 'ALM')
if(isset($programs[$programID]) and in_array($config->systemMode, array('ALM', 'PLM')))
{
$programName = zget($programs, $programID);
@@ -145,7 +145,7 @@ foreach($projects as $programID => $programProjects)
}
/* If the project is the last one in the program, print the closed label. */
if($config->systemMode == 'ALM' and isset($programs[$programID]) and !isset($programProjects[$index + 1]))
if(in_array($config->systemMode, array('ALM', 'PLM')) and isset($programs[$programID]) and !isset($programProjects[$index + 1]))
{
if($projectCounts[$programID]['myProject']) $myProjectsHtml .= '</ul></li>';
if($projectCounts[$programID]['others']) $normalProjectsHtml .= '</ul></li>';
@@ -80,13 +80,11 @@ $closedCount = 0;
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->project->empty;?></span>
<?php if(empty($allProjectsNum)):?>
<?php if(!defined('TUTORIAL')):?>
<?php if(common::hasPriv('project', 'create') and $browseType != 'bysearch') common::printLink('project', 'createGuide', "programID=$programID", '<i class="icon icon-plus"></i> ' . $lang->project->create, '', 'class="btn btn-info" data-toggle="modal"');?>
<?php else:?>
<?php common::printLink('execution', 'create', '', '<i class="icon icon-plus"></i> ' . $lang->execution->create, '', 'class="btn btn-info"');?>
<?php endif;?>
<?php endif;?>
</p>
</div>
<?php else:?>
+1 -1
View File
@@ -148,7 +148,7 @@
<?php $i = 0;?>
<?php foreach($products as $product):?>
<tr>
<th><?php if($i == 0) echo $lang->project->manageProductPlan;?></th>
<th id='productTitle'><?php if($i == 0) echo $lang->project->manageProductPlan;?></th>
<td class='text-left productsBox' colspan="3">
<div class='row'>
<div class="col-sm-6">
+16 -12
View File
@@ -27,14 +27,23 @@
<button class="close" data-dismiss="modal">x</button>
<h2 class='text-center'><?php echo $lang->project->chooseProgramType; ?></h2>
<div class='row'>
<div class='col col-xs-4'>
<?php
$tab = $from == 'global' ? 'project' : $app->tab;
if($tab == 'product') $tab = 'project';
<?php
$tab = $from == 'global' ? 'project' : $app->tab;
if($tab == 'product') $tab = 'project';
$hasWaterfall = helper::hasFeature('waterfall');
$hasWaterfallPlus = helper::hasFeature('waterfallplus');
?>
$hasWaterfall = helper::hasFeature('waterfall');
$hasWaterfallPlus = helper::hasFeature('waterfallplus');
?>
<?php if($config->systemMode == 'PLM'):?>
<div class='col col-xs-4'>
<div class='project-type text-center'>
<?php echo html::a($this->createLink("project", "create", "model=ipd&programID=$programID&copyProjectID=0&extra=productID=$productID,branchID=$branchID"), "<img class='project-type-img' data-type='ipd' src='{$config->webRoot}theme/default/images/main/ipd.png'>", '', "data-app='{$tab}' class='createButton'")?>
<h3><?php echo $lang->project->ipd; ?></h3>
<p><?php echo $lang->project->ipdTitle; ?></p>
</div>
</div>
<?php endif;?>
<div class='col col-xs-4'>
<div class='project-type text-center'>
<?php echo html::a($this->createLink("project", "create", "model=scrum&programID=$programID&copyProjectID=0&extra=productID=$productID,branchID=$branchID"), "<img class='project-type-img' data-type='scrum' src='{$config->webRoot}theme/default/images/main/scrum.png'>", '', "data-app='{$tab}' class='createButton'")?>
<h3><?php echo $lang->project->scrum; ?></h3>
@@ -72,11 +81,6 @@
<p><?php echo $lang->project->waterfallplusTitle;?></p>
</div>
</div>
<div class='col col-xs-4'>
<div class='project-type text-center'>
<div class='project-type-img more-type'><span class='text-muted'><?php echo $lang->project->moreModelTitle;?></span></div>
</div>
</div>
<?php endif;?>
</div>
</div>
+5 -5
View File
@@ -1,12 +1,12 @@
<?php
/**
* The action->dynamic view file of dashboard module of ZenTaoPMS.
* The dynamic view file of project module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package dashboard
* @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $
* @package project
* @version $Id: dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $
* @link http://www.zentao.net
*/
?>
@@ -106,8 +106,8 @@ $firstDate = date('Y-m-d', strtotime($firstAction->originalDate) + 24 * 3600);
$lastDate = substr($action->originalDate, 0, 10);
$hasPre = $this->action->hasPreOrNext($firstDate, 'pre');
$hasNext = $this->action->hasPreOrNext($lastDate, 'next');
$preLink = $hasPre ? inlink('dynamic', "projectID=$projectID&type=$type&param=$param&recTotal={$pager->recTotal}&date=" . strtotime($firstDate) . '&direction=pre') : 'javascript:;';
$nextLink = $hasNext ? inlink('dynamic', "projectID=$projectID&type=$type&param=$param&recTotal={$pager->recTotal}&date=" . strtotime($lastDate) . '&direction=next') : 'javascript:;';
$preLink = $hasPre ? inlink('dynamic', "projectID=$projectID&type=$type&param=$param&recTotal={$recTotal}&date=" . strtotime($firstDate) . '&direction=pre') : 'javascript:;';
$nextLink = $hasNext ? inlink('dynamic', "projectID=$projectID&type=$type&param=$param&recTotal={$recTotal}&date=" . strtotime($lastDate) . '&direction=next') : 'javascript:;';
?>
<?php if($hasPre or $hasNext):?>
<div id="mainActions" class='main-actions'>
+5 -4
View File
@@ -12,8 +12,8 @@
<?php js::set('checkedSummary', $lang->execution->checkedExecSummary);?>
<?php js::set('pageSummary', $lang->execution->pageExecSummary);?>
<?php js::set('executionSummary', $lang->execution->executionSummary);?>
<?php js::set('checkedExecutions', $lang->execution->checkedExecutions);?>
<?php js::set('changeStatusHtml', $changeStatusHtml);?>
<?php if($project->model == 'ipd') js::set('reviewPoints', json_encode($reviewPoints));?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<?php if($project->division and $project->hasProduct):?>
@@ -42,9 +42,10 @@
<?php endforeach;?>
<?php if(common::hasPriv('execution', 'batchEdit') and !empty($executionStats)) echo html::checkbox('editExecution', array('1' => $lang->edit . $lang->executionCommon), '', $this->cookie->editExecution ? 'checked=checked' : '');?>
<?php if(common::hasPriv('execution', 'task')) echo html::checkbox('showTask', array('1' => $lang->programplan->stageCustom->task), '', $this->cookie->showTask ? 'checked=checked' : '');?>
<?php if($project->model == 'ipd') echo html::checkbox('showStage', array('1' => $lang->programplan->stageCustom->point), '', $this->cookie->showStage ? 'checked=checked' : '');?>
</div>
<div class='btn-toolbar pull-right'>
<?php if(($project->model == 'waterfall' or $project->model == 'waterfallplus') and $this->config->edition == 'max'):?>
<?php if(in_array($project->model, array('waterfall', 'waterfallplus', 'ipd')) and ($this->config->edition == 'max' or $this->config->edition == 'ipd')):?>
<div class="btn-group">
<?php echo html::a($this->createLink('programplan', 'browse', "projectID=$projectID&productID=$productID&type=gantt"), "<i class='icon-gantt-alt'></i> &nbsp;", '', "class='btn btn-icon switchBtn' title='{$lang->programplan->gantt}'");?>
<?php echo html::a('', "<i class='icon-list'></i> &nbsp;", '', "class='btn btn-icon text-primary switchBtn' title='{$lang->project->bylist}'");?>
@@ -102,7 +103,7 @@
<th class='c-status text-center'><?php echo $lang->project->status;?></th>
<th class='w-50px'><?php echo $lang->execution->owner;?></th>
<th class='c-date'><?php echo $lang->programplan->begin;?></th>
<th class='c-date'><?php echo $lang->programplan->end;?></th>
<th class='c-enddate'><?php echo $lang->programplan->end;?></th>
<th class='w-50px text-right'><?php echo $lang->task->estimateAB;?></th>
<th class='w-50px text-right'><?php echo $lang->task->consumedAB;?></th>
<th class='w-50px text-right'><?php echo $lang->task->leftAB;?> </th>
@@ -115,7 +116,7 @@
<?php foreach($executionStats as $execution):?>
<?php $execution->division = $project->division;?>
<?php $executionProductID = (empty($productID) and !empty($execution->product)) ? $execution->product : $productID;?>
<?php $this->execution->printNestedList($execution, false, $users, $executionProductID);?>
<?php $this->execution->printNestedList($execution, false, $users, $executionProductID, $project);?>
<?php endforeach;?>
</tbody>
</table>
+1 -1
View File
@@ -140,7 +140,7 @@
</div>
</div>
<?php $noticeSwitch = (!$project->division and count($linkedProducts) == 1 and empty($executions));?>
<?php $noticeSwitch = (!$project->division and count($linkedProducts) == 1 and empty($executions) and in_array($project->model, array('waterfall', 'waterfallplus')));?>
<?php js::set('linkedProducts', array_keys($linkedProducts));?>
<?php js::set('noticeSwitch', $noticeSwitch);?>
<?php js::set('noticeDivsion', $lang->project->noticeDivsion);?>