diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index 61ba0959fd..5d9fedcf32 100644
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -924,7 +924,7 @@ $lang->menu->scrum->ci = '代码|repo|browse';
$lang->menu->scrum->projectbuild = array('link' => '版本|projectbuild|browse|project={PROJECT}');
$lang->menu->scrum->projectrelease = array('link' => '发布|projectrelease|browse');
$lang->menu->scrum->other = array('link' => '其他|project|other', 'class' => 'dropdown dropdown-hover waterfall-list', 'subModule' => 'issue,risk,stakeholder');
-$lang->menu->scrum->projectsetting = array('link' => '设置|project|setting', 'class' => 'dropdown dropdown-hover waterfall-list');
+$lang->menu->scrum->projectsetting = array('link' => '设置|program|prjview|project={PROJECT}');
$lang->scrum = new stdclass();
$lang->scrum->subMenu = new stdclass();
@@ -933,8 +933,8 @@ $lang->scrum->subMenu->other->issue = array('link' => '问题|issue|browse
$lang->scrum->subMenu->other->risk = array('link' => '风险|risk|browse|', 'subModule' => 'risk');
$lang->scrum->subMenu->other->stakeholder = array('link' => '干系人|stakeholder|browse|', 'subModule' => 'stakeholder');
-$lang->scrum->subMenu->projectsetting = new stdclass();
-$lang->scrum->subMenu->projectsetting->program = '项目|program|PRJEdit|';
+$lang->scrum->setMenu = new stdclass();
+$lang->scrum->setMenu->view = array('link' => '概况|program|prjview|project={PROJECT}');
/* Waterfall menu. */
$lang->menu->waterfall = new stdclass();
@@ -950,7 +950,7 @@ $lang->menu->waterfall->qa = '测试|qa|index';
$lang->menu->waterfall->projectrelease = array('link' => '发布|projectrelease|browse');
$lang->menu->waterfall->projectbuild = array('link' => '版本|projectbuild|browse|project={PROJECT}');
$lang->menu->waterfall->other = array('link' => '其他|project|other', 'class' => 'dropdown dropdown-hover waterfall-list', 'subModule' => 'issue,risk,stakeholder,nc');
-$lang->menu->waterfall->projectsetting = array('link' => '设置|project|setting', 'class' => 'dropdown dropdown-hover waterfall-list', 'subModule' => 'workestimation,durationestimation,budget,pssp');
+$lang->menu->waterfall->projectsetting = array('link' => '设置|program|prjview|project={PROJECT}', 'subModule' => 'workestimation,durationestimation,budget,pssp');
$lang->waterfall = new stdclass();
$lang->waterfall->subMenu = new stdclass();
@@ -959,9 +959,11 @@ $lang->waterfall->subMenu->other->issue = array('link' => '问题|issue|browse|'
$lang->waterfall->subMenu->other->risk = array('link' => '风险|risk|browse|', 'subModule' => 'risk');
$lang->waterfall->subMenu->other->stakeholder = array('link' => '干系人|stakeholder|browse|', 'subModule' => 'stakeholder');
-$lang->waterfall->subMenu->projectsetting = new stdclass();
-$lang->waterfall->subMenu->projectsetting->workestimation = array('link' => '估算|workestimation|index|program=%s', 'subModule' => 'durationestimation,budget');
-$lang->waterfall->subMenu->projectsetting->program = '项目|program|PRJEdit|';
+$lang->waterfall->setMenu = new stdclass();
+$lang->waterfall->setMenu->view = array('link' => '概况|program|prjview|project={PROJECT}');
+$lang->waterfall->setMenu->workestimation = '工作量估算|workestimation|index|project={PROJECT}';
+$lang->waterfall->setMenu->duration = array('link' => '工期估算|durationestimation|index|project={PROJECT}', 'subModule' => 'durationestimation');
+$lang->waterfall->setMenu->budget = array('link' => '费用估算|budget|summary|', 'subModule' => 'budget');
$lang->waterfallproduct = new stdclass();
$lang->workestimation = new stdclass();
@@ -998,16 +1000,13 @@ $lang->waterfallproduct->menu = new stdclass();
$lang->durationestimation->menu = new stdclass();
$lang->projectstory->menu = new stdclass();
+$lang->workestimation->menu = $lang->waterfall->setMenu;
+$lang->durationestimation->menu = $lang->waterfall->setMenu;
+$lang->budget->menu = $lang->waterfall->setMenu;
+
$lang->stakeholder->menu->list = array('link' => '干系人列表|stakeholder|browse|', 'alias' => 'create,edit,view,batchcreate');
$lang->stakeholder->menu->issue = array('link' => '问题管理|stakeholder|issue|');
-$lang->workestimation->menu->index = '工作量估算|workestimation|index|project={PROJECT}';
-$lang->workestimation->menu->duration = array('link' => '工期估算|durationestimation|index|project={PROJECT}', 'subModule' => 'durationestimation');
-$lang->workestimation->menu->budget = array('link' => '费用估算|budget|summary|', 'subModule' => 'budget');
-
-$lang->durationestimation->menu = $lang->workestimation->menu;
-$lang->budget->menu = $lang->workestimation->menu;
-
$lang->programplan->menu->gantt = array('link' => '甘特图|programplan|browse|programID={PROJECT}&productID={PRODUCT}&type=gantt');
$lang->programplan->menu->lists = array('link' => '阶段列表|programplan|browse|programID={PROJECT}&productID={PRODUCT}&type=lists', 'alias' => 'create');
diff --git a/module/common/model.php b/module/common/model.php
index bf672888f3..2cdcbc65b5 100644
--- a/module/common/model.php
+++ b/module/common/model.php
@@ -631,6 +631,12 @@ class commonModel extends model
/* If program, return.*/
if($moduleName == 'program' and strpos($methodName, 'prj') !== false) $lang->program->menu = $lang->PRJ->menu;
+ if($moduleName == 'program' and $methodName == 'prjview')
+ {
+ $moduleIndex = array_search('program', $lang->noMenuModule);
+ if($moduleIndex !== false) unset($lang->noMenuModule[$moduleIndex]);
+ $lang->navGroup->program = 'project';
+ }
if($moduleName == 'product' and $methodName == 'create') return;
/* Set the main main menu. */
@@ -696,25 +702,7 @@ class commonModel extends model
if(isset($subMenuItem->link['vars'])) $subParams = $subMenuItem->link['vars'];
$subLink = helper::createLink($subModule, $subMethod, $subParams);
- if($subMenuItem->name == 'program')
- {
- /* Print program sub menu.*/
- global $dbh;
- $program = $dbh->query("SELECT * FROM " . TABLE_PROJECT . " WHERE `id` = '{$app->session->PRJ}'")->fetch();
- $subActive .= 'dropdown-submenu';
- $subLink = 'javascript:;';
- $subProgram .= "
";
- }
-
if($currentModule == strtolower($subModule) && $currentMethod == strtolower($subMethod)) $subActive = 'active';
-
$subMenu .= "" . html::a($subLink, $subLabel) . $subProgram . '';
}
@@ -725,7 +713,7 @@ class commonModel extends model
}
/* Disable links to more buttons. */
- if($menuItem->name == 'projectsetting' || $menuItem->name == 'other') $link='javascript:void(0);';
+ if($menuItem->name == 'other') $link='javascript:void(0);';
$menuItemHtml = "" . html::a($link, $label, $target) . $subMenu . "\n";
@@ -779,7 +767,7 @@ class commonModel extends model
$moduleName = $app->rawModule;
$methodName = $app->rawMethod;
$mainMenu = $moduleName;
- if($moduleName == 'program') return;
+ if($moduleName == 'program' and $methodName != 'prjview') return;
if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName;
/* Set main menu by group. */
@@ -787,7 +775,7 @@ class commonModel extends model
if($moduleName == 'admin') return;
if($group == 'repo' || $group == 'ops' || $group == 'feedback') return;
if($group == 'my') self::getMyModuleMenu($moduleName, $methodName);
- if($group == 'project') self::getProgramModuleMenu($moduleName);
+ if($group == 'project') self::getProgramModuleMenu($moduleName, $methodName);
if($group == 'product')
{
$lang->product->menu = $lang->product->setMenu;
@@ -1744,7 +1732,7 @@ EOD;
$method = strtolower($method);
/* More menus do not require permission control. */
- if($module == 'project' && ($method == 'other' || $method == 'setting')) return true;
+ if($module == 'project' && $method == 'other') return true;
/* Check the parent object is closed. */
if(!empty($method) and strpos('close|batchclose', $method) === false and !commonModel::canBeChanged($module, $object)) return false;
@@ -2418,21 +2406,24 @@ EOD;
* Get program module menu by model.
*
* @param varchar $moduleName
+ * @param varchar $methodName
* @static
* @access public
* @return string
*/
- public static function getProgramModuleMenu($moduleName)
+ public static function getProgramModuleMenu($moduleName, $methodName)
{
global $app, $lang, $dbh;
$program = $dbh->query("SELECT * FROM " . TABLE_PROJECT . " WHERE `id` = '{$app->session->PRJ}'")->fetch();
if(empty($program)) return;
if($program->model == 'waterfall')
{
+ if($moduleName == 'program' and $methodName == 'prjview') $lang->program->menu = $lang->waterfall->setMenu;
$lang->$moduleName->menu = self::processMenuVars($lang->$moduleName->menu);
}
if($program->model == 'scrum')
{
+ if($moduleName == 'program' and $methodName == 'prjview') $lang->program->menu = $lang->scrum->setMenu;
unset($lang->stakeholder->menu->issue);
unset($lang->stakeholder->menu->plan);
unset($lang->stakeholder->menu->expectation);
diff --git a/module/product/model.php b/module/product/model.php
index 2420ee0daa..13bffd140b 100644
--- a/module/product/model.php
+++ b/module/product/model.php
@@ -323,7 +323,7 @@ class productModel extends model
*/
public function getProductsByProject($projectID, $status = 'all')
{
- return $this->dao->select('t2.*')
+ return $this->dao->select('t1.branch, t1.plan, t2.*')
->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')
->on('t1.product = t2.id')
diff --git a/module/program/config.php b/module/program/config.php
index d19cbe3621..13fefe21ce 100644
--- a/module/program/config.php
+++ b/module/program/config.php
@@ -16,6 +16,7 @@ $config->program->editor->prjclose = array('id' => 'comment', 'tools' => 'sim
$config->program->editor->prjsuspend = array('id' => 'comment', 'tools' => 'simpleTools');
$config->program->editor->prjstart = array('id' => 'comment', 'tools' => 'simpleTools');
$config->program->editor->prjactivate = array('id' => 'comment', 'tools' => 'simpleTools');
+$config->program->editor->prjview = array('id' => 'comment', 'tools' => 'simpleTools');
$config->program->list = new stdclass();
$config->program->list->exportFields = 'id,name,code,template,product,status,begin,end,budget,PM,end,desc';
diff --git a/module/program/control.php b/module/program/control.php
index 26964cf0eb..bb93d9c6b0 100644
--- a/module/program/control.php
+++ b/module/program/control.php
@@ -1023,6 +1023,40 @@ class program extends control
$this->display();
}
+ /**
+ * View a project.
+ *
+ * @param int $projectID
+ * @access public
+ * @return void
+ */
+ public function PRJView($projectID = 0)
+ {
+ $this->lang->navGroup->program = 'project';
+ $this->app->loadLang('bug');
+
+ $products = $this->loadModel('product')->getProductsByProject($projectID);;
+ $linkedBranches = array();
+ foreach($products as $product)
+ {
+ if($product->branch) $linkedBranches[$product->branch] = $product->branch;
+ }
+
+ $this->view->title = $this->lang->program->PRJView;
+ $this->view->position = $this->lang->program->PRJView;
+ $this->view->projectID = $projectID;
+ $this->view->project = $this->program->getPRJByID($projectID);
+ $this->view->products = $products;
+ $this->view->actions = $this->loadModel('action')->getList('project', $projectID);
+ $this->view->users = $this->loadModel('user')->getPairs('noletter');
+ $this->view->statData = $this->program->getPRJStatData($projectID);
+ $this->view->workhour = $this->program->getPRJWorkhour($projectID);
+ $this->view->planGroup = $this->loadModel('project')->getPlans($products);;
+ $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), '', $linkedBranches);
+
+ $this->display();
+ }
+
/**
* Project browse groups.
*
diff --git a/module/program/css/prjview.css b/module/program/css/prjview.css
new file mode 100644
index 0000000000..7f83fa80fa
--- /dev/null
+++ b/module/program/css/prjview.css
@@ -0,0 +1 @@
+.row > .col-sm-12:first-child {padding-bottom: 20px;}
diff --git a/module/program/lang/zh-cn.php b/module/program/lang/zh-cn.php
index a004d49276..8f2e4a9990 100644
--- a/module/program/lang/zh-cn.php
+++ b/module/program/lang/zh-cn.php
@@ -5,6 +5,7 @@ $lang->program->PRJIndex = '项目仪表盘';
$lang->program->PRJHome = '项目主页';
$lang->program->PRJCreate = '创建项目';
$lang->program->PRJEdit = '编辑项目';
+$lang->program->PRJView = '项目概况';
$lang->program->PRJBatchEdit = '批量编辑';
$lang->program->PRJBrowse = '项目列表';
$lang->program->PRJAll = '所有项目';
diff --git a/module/program/model.php b/module/program/model.php
index 09091cc9dc..7d3354779a 100644
--- a/module/program/model.php
+++ b/module/program/model.php
@@ -810,7 +810,7 @@ class programModel extends model
*/
public function getPRJSwitcher($projectID, $currentModule, $currentMethod)
{
- if($currentModule == 'program' && $currentMethod != 'index') return;
+ if($currentModule == 'program' && ($currentMethod != 'index' && $currentMethod != 'prjview')) return;
$this->loadModel('project');
$currentProjectName = $this->lang->program->common;
@@ -838,7 +838,7 @@ class programModel extends model
*/
public function getPRJMainAction($module, $method)
{
- if($module == 'program' and $method != 'index') return '';
+ if($module == 'program' and ($method != 'index' and $method != 'prjview')) return '';
return common::hasPriv('program', 'prjbrowse') ? html::a(helper::createLink('program', 'prjbrowse'), $this->lang->moreLink, '', "class='btn btn-link'") : '';
}
@@ -1136,6 +1136,69 @@ class programModel extends model
return $stats;
}
+ /**
+ * Get project workhour info.
+ *
+ * @param int $projectID
+ * @access public
+ * @return void
+ */
+ public function getPRJWorkhour($projectID)
+ {
+ $executions = $this->loadModel('project')->getExecutionPairs($projectID);
+
+ $total = $this->dao->select('
+ ROUND(SUM(estimate), 2) AS totalEstimate,
+ ROUND(SUM(consumed), 2) AS totalConsumed,
+ ROUND(SUM(`left`), 2) AS totalLeft')
+ ->from(TABLE_TASK)
+ ->where('project')->in(array_keys($executions))
+ ->andWhere('deleted')->eq(0)
+ ->andWhere('parent')->lt(1)
+ ->fetch();
+ $closedTotalLeft = $this->dao->select('ROUND(SUM(`left`), 2) AS totalLeft')->from(TABLE_TASK)
+ ->where('project')->in(array_keys($executions))
+ ->andWhere('deleted')->eq(0)
+ ->andWhere('parent')->lt(1)
+ ->andWhere('status')->in('closed,cancel')
+ ->fetch('totalLeft');
+
+ $workhour = new stdclass();
+ $workhour->totalHours = $this->dao->select('sum(days * hours) AS totalHours')->from(TABLE_TEAM)->where('root')->in(array_keys($executions))->andWhere('type')->eq('project')->fetch('totalHours');
+ $workhour->totalEstimate = round($total->totalEstimate, 1);
+ $workhour->totalConsumed = round($total->totalConsumed, 1);
+ $workhour->totalLeft = round($total->totalLeft - $closedTotalLeft, 1);
+
+ return $workhour;
+ }
+
+ /**
+ * Get project stat data .
+ *
+ * @param int $projectID
+ * @access public
+ * @return void
+ */
+ public function getPRJStatData($projectID)
+ {
+ $executions = $this->loadModel('project')->getExecutionPairs($projectID);
+ $storyCount = $this->dao->select('count(t2.story) as storyCount')->from(TABLE_STORY)->alias('t1')
+ ->leftJoin(TABLE_PROJECTSTORY)->alias('t2')->on('t1.id = t2.story')
+ ->where('t2.project')->eq($projectID)
+ ->andWhere('t1.deleted')->eq(0)
+ ->fetch('storyCount');
+
+ $taskCount = $this->dao->select('count(id) as taskCount')->from(TABLE_TASK)->where('project')->in(array_keys($executions))->andWhere('deleted')->eq(0)->fetch('taskCount');
+ $bugCount = $this->dao->select('count(id) as bugCount')->from(TABLE_BUG)->where('project')->in(array_keys($executions))->andWhere('deleted')->eq(0)->fetch('bugCount');
+
+ $statData = new stdclass();
+ $statData->storyCount = $storyCount;
+ $statData->taskCount = $taskCount;
+ $statData->bugCount = $bugCount;
+
+ return $statData;
+ }
+
/**
* Get project pairs.
*
diff --git a/module/program/view/prjview.html.php b/module/program/view/prjview.html.php
new file mode 100644
index 0000000000..063d79b8bb
--- /dev/null
+++ b/module/program/view/prjview.html.php
@@ -0,0 +1,166 @@
+
+ * @package project
+ * @version $Id: view.html.php 4594 2013-03-13 06:16:02Z wyd621@gmail.com $
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+
+
+
+
+
id;?> code;?> name;?>
+
+
desc;?>
+
+ deleted):?>
+ project->deleted;?>
+
+ program->PRJLifeTimeList, $project->lifetime);?>
+ delay)):?>
+ project->delayed;?>
+
+ processStatus('project', $project);?>
+
+
+
+
+
+
+ project->manageProducts;?>
+ id", '', '', "class='btn btn-link pull-right muted'");?>
+
+
+
+ $product):?>
+ branch]) ? '/' . $branchGroups[$productID][$product->branch] : '';?>
+
+ createLink('product', 'browse', "productID=$productID&branch=$product->branch"), " " . $product->name . $branchName);?>
+
+
+
+
+
+
+
project->linkPlan;?>
+
+
+ $product):?>
+ plan])):?>
+
createLink('productplan', 'view', "planID={$product->plan}"), $product->name . '/' . $planGroups[$productID][$product->plan]);?>
+
+
+
+
+
+
+
project->lblStats;?>
+
+
+
+ | | | |
+
+ |
+ totalConsumed + $workhour->totalLeft) ? floor($workhour->totalConsumed / ($workhour->totalConsumed + $workhour->totalLeft) * 1000) / 1000 * 100 : 0;?>
+ project->progress;?> percent;?>
+
+ |
+
+
+ | project->begin;?> |
+ begin;?> |
+ project->totalEstimate;?> |
+ totalEstimate . $lang->hourCommon;?> |
+
+
+ | project->end;?> |
+ end;?> |
+ project->totalConsumed;?> |
+ totalConsumed . $lang->hourCommon;?> |
+
+
+ | project->totalDays;?> |
+ days;?> |
+ project->totalLeft;?> |
+ totalLeft . $lang->hourCommon;?> |
+
+
+ | project->totalHours;?> |
+ totalHours . $lang->hourCommon;?> |
+
+
+
+
+
+
+
project->basicInfo;?>
+
+
+
+
+ | story->common;?> |
+ storyCount;?> |
+ task->common;?> |
+ taskCount;?> |
+ bug->common;?> |
+ bugCount;?> |
+
+
+
+
+
+
+
project->acl;?>
+
+
project->aclList[$project->acl];?>
+
+
+ printExtendFields($project, 'div', "position=right&inForm=0&inCell=1");?>
+
+
+
+
+ createLink('action', 'comment', "objectType=project&objectID=$project->id");?>
+
+
+
+
+
+ id";
+ common::printBack(inlink('prjbrowse'));
+ if(!$project->deleted)
+ {
+ echo "
";
+ common::printIcon('project', 'start', "projectID=$project->id", $project, 'button', '', '', 'iframe', true);
+ common::printIcon('project', 'activate', "projectID=$project->id", $project, 'button', '', '', 'iframe', true);
+ common::printIcon('project', 'putoff', "projectID=$project->id", $project, 'button', '', '', 'iframe', true);
+ common::printIcon('project', 'suspend', "projectID=$project->id", $project, 'button', '', '', 'iframe', true);
+ common::printIcon('project', 'close', "projectID=$project->id", $project, 'button', '', '', 'iframe', true);
+
+ echo $this->buildOperateMenu($project, 'view');
+
+ echo "
";
+ common::printIcon('project', 'edit', $params, $project);
+ common::printIcon('project', 'delete', $params, $project, 'button', 'trash', 'hiddenwin');
+ }
+ ?>
+
+
+
+
+
+
+
+