Merge branch '20.x' of github.com:easysoft/zentaopms into 20.x

This commit is contained in:
tianshujie98
2020-08-25 08:58:20 +08:00
54 changed files with 1224 additions and 329 deletions
+3
View File
@@ -290,3 +290,6 @@ ALTER TABLE `zt_project` ADD `path` varchar(255) NOT NULL AFTER `parent`;
ALTER TABLE `zt_project` ADD `grade` tinyint unsigned NOT NULL AFTER `path`;
INSERT INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system','custom','','URAndSR','1'),('system','custom','','URSRName','{\"urCommon\":{\"zh-cn\":\"\\u7528\\u6237\\u9700\\u6c42\"},\"srCommon\":{\"zh-cn\":\"\\u8f6f\\u4ef6\\u9700\\u6c42\"}}'),('system','custom','','storyPoint','1');
ALTER TABLE `zt_block` ADD `type` char(30) NOT NULL AFTER `module`;
ALTER TABLE `zt_block` ADD UNIQUE `account_module_type_order` (`account`, `module`, `type`, `order`), DROP INDEX `account_module_order_type`;
+2
View File
@@ -30,3 +30,5 @@ $config->action->majorList['task'] = array('assigned', 'finished', 'activated
$config->action->majorList['bug'] = array('assigned', 'resolved');
$config->action->majorList['release'] = array('opened');
$config->action->majorList['build'] = array('opened');
$config->action->majorList['product'] = array('opened', 'edited');
$config->action->majorList['project'] = array('opened', 'edited');
+17 -7
View File
@@ -15,15 +15,25 @@ $config->block->editor = new stdclass();
$config->block->editor->set = array('id' => 'html', 'tools' => 'simple');
$config->block->longBlock = array();
$config->block->longBlock['']['flowchart'] = 'flowchart';
$config->block->longBlock['']['welcome'] = 'welcome';
$config->block->longBlock['product']['statistic'] = 'statistic';
$config->block->longBlock['project']['statistic'] = 'statistic';
$config->block->longBlock['qa']['statistic'] = 'statistic';
$config->block->longBlock['']['flowchart'] = 'flowchart';
$config->block->longBlock['']['welcome'] = 'welcome';
$config->block->longBlock['product']['statistic'] = 'statistic';
$config->block->longBlock['project']['statistic'] = 'statistic';
$config->block->longBlock['qa']['statistic'] = 'statistic';
$config->block->longBlock['program']['cmmireport'] = 'cmmireport';
$config->block->longBlock['program']['cmmiissue'] = 'cmmiissue';
$config->block->longBlock['program']['cmmirisk'] = 'cmmirisk';
$config->block->shortBlock = array();
$config->block->shortBlock['product']['overview'] = 'overview';
$config->block->shortBlock['project']['overview'] = 'overview';
$config->block->shortBlock['product']['overview'] = 'overview';
$config->block->shortBlock['project']['overview'] = 'overview';
$config->block->shortBlock['program']['cmmiestimate'] = 'cmmiestimate';
$config->block->shortBlock['program']['cmmiprogress'] = 'cmmiprogress';
$config->block->shortBlock['']['contribute'] = 'contribute';
$config->block->showAction['overview'] = array('block' => 'qa', 'module' => 'testcase', 'method' => 'create', 'vars' => '');
$config->block->showAction['scrumlist'] = array('block' => 'program', 'module' => 'project', 'method' => 'create', 'vars' => '');
$config->block->showAction['scrumproduct'] = array('block' => 'program', 'module' => 'product', 'method' => 'create', 'vars' => '');
$config->statistic = new stdclass();
$config->statistic->storyStages = array('wait', 'planned', 'developing', 'testing', 'released');
+122 -50
View File
@@ -1,5 +1,5 @@
<?php
/**
/**
* The control file of block of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
@@ -59,6 +59,7 @@ class block extends control
if(strpos(",$closedBlock,", ",|flowchart,") === false and $this->config->global->flow == 'full') $modules['flowchart'] = $this->lang->block->lblFlowchart;
if(strpos(",$closedBlock,", ",|welcome,") === false and $this->config->global->flow == 'full') $modules['welcome'] = $this->lang->block->welcome;
if(strpos(",$closedBlock,", ",|html,") === false) $modules['html'] = 'HTML';
if(strpos(",$closedBlock,", ",|contribute,") === false) $modules['contribute'] = $this->lang->block->contribute;
$modules = array('' => '') + $modules;
$hiddenBlocks = $this->block->getHiddenBlocks();
@@ -207,11 +208,11 @@ class block extends control
public function dashboard($module, $type = '')
{
if($this->loadModel('user')->isLogon()) $this->session->set('blockModule', $module);
$blocks = $this->block->getBlockList($module);
$blocks = $this->block->getBlockList($module, $type);
$inited = empty($this->config->$module->common->blockInited) ? '' : $this->config->$module->common->blockInited;
/* Init block when vist index first. */
if(empty($blocks) and !$inited and !defined('TUTORIAL'))
if((empty($blocks) and !$inited and !defined('TUTORIAL')) || (empty($blocks) and $module == 'program'))
{
if($this->block->initBlock($module, $type)) die(js::reload());
}
@@ -246,13 +247,15 @@ class block extends control
$block->moreLink = $this->createLink('company', 'dynamic');
}
$block->actionLink = '';
if($block->block == 'overview')
if(isset($this->config->block->showAction[$block->block]))
{
if($module == 'qa' && common::hasPriv('testcase', 'create'))
$action = $this->config->block->showAction[$block->block];
if(common::hasPriv($action['module'], $action['method']))
{
$this->app->loadLang('testcase');
$block->actionLink = html::a($this->createLink('testcase', 'create', 'productID='), "<i class='icon icon-sm icon-plus'></i> " . $this->lang->testcase->create, '', "class='btn btn-primary'");
$this->app->loadLang($action['module']);
$block->actionLink = html::a($this->createLink($action['module'], $action['method'], $action['vars']), "<i class='icon icon-sm icon-plus'></i> " . $this->lang->$action['module']->create, '', "class='btn btn-mini'");
}
}
@@ -322,6 +325,19 @@ class block extends control
$this->display();
}
/**
* Print contribute block.
*
* @access public
* @return void
*/
public function contribute()
{
$this->view->data = $this->block->getContributeBlockData();
$this->display();
}
/**
* Print block.
*
@@ -374,6 +390,10 @@ class block extends control
{
$html = $this->fetch('block', 'welcome');
}
elseif($block->block == 'contribute')
{
$html = $this->fetch('block', 'contribute');
}
echo $html;
}
@@ -758,6 +778,7 @@ class block extends control
if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
$this->loadModel('project');
$this->loadModel('weekly');
$this->app->loadLang('task');
$this->app->loadLang('story');
@@ -772,29 +793,43 @@ class block extends control
return false;
}
$today = date('Y-m-d', strtotime(helper::today()));
$date = date('Ymd', strtotime($this->loadModel('weekly')->getThisMonday($today)));
$tasks = $this->dao->select("program, sum(consumed) as totalConsumed, sum(if(status != 'cancel' and status != 'closed', `left`, 0)) as totalLeft")->from(TABLE_TASK)
->where('program')->in(array_keys($programs))
->andWhere('deleted')->eq(0)
->andWhere('parent')->lt(1)
->groupBy('program')
->fetchAll('program');
foreach($programs as $programID => $program)
{
$program->allStories = $program->doneStories = $program->leftStories = 0;
$stories = $this->dao->select('id, status')->from(TABLE_STORY)
->where('deleted')->eq(0)
->andWhere('type')->eq('story')
->andWhere('status')->ne('draft')
->andWhere('program')->eq($programID)
->fetchPairs();
foreach($stories as $id => $status)
if($program->template == 'scrum')
{
$program->allStories ++;
if($status == 'closed') $program->doneStories ++;
if($status != 'closed') $program->leftStories ++;
$program->progress = $program->allStories == 0 ? 0 : round($program->doneStories / $program->allStories, 3) * 100;
$program->projects = $this->project->getProjectStats('all', 0, 0, 1, 'id_desc', null, $programID);
}
else
{
$begin = $program->begin;
$weeks = $this->weekly->getWeekPairs($begin);
$current = zget($weeks, $date, '');
$program->progress = $program->allStories == 0 ? 0 : ceil($program->doneStories / $program->allStories) * 100;
$program->pv = $this->weekly->getPV($programID, $today);
$program->ev = $this->weekly->getEV($programID, $today);
$program->ac = $this->weekly->getAC($programID, $today);
$program->sv = $this->weekly->getSV($program->ev, $program->pv);
$program->cv = $this->weekly->getCV($program->ev, $program->ac);
//$program->projects = $this->dao->select('*')
$progress = isset($tasks[$programID]) ? (($tasks[$programID]->totalConsumed + $tasks[$programID]->totalLeft)) ? round($tasks[$programID]->totalConsumed / ($tasks[$programID]->totalConsumed + $tasks[$programID]->totalLeft), 3) * 100 : 0 : 0;
$program->current = $current;
$program->progress = $progress;
}
}
$this->view->programs = $programs;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
}
/**
@@ -1030,7 +1065,7 @@ class block extends control
$projects[$project->id]->releasedStories = 0;
}
$projects[$project->id]->progress = ($project->totalConsumed || $project->totalLeft) ? round($project->totalConsumed / ($project->totalConsumed + $project->totalLeft), 2) * 100 : 0;
$projects[$project->id]->progress = ($project->totalConsumed || $project->totalLeft) ? round($project->totalConsumed / ($project->totalConsumed + $project->totalLeft), 3) * 100 : 0;
$projects[$project->id]->taskProgress = $project->totalTasks ? round(($project->totalTasks - $project->undoneTasks) / $project->totalTasks, 2) * 100 : 0;
$projects[$project->id]->storyProgress = $project->totalStories ? round(($project->totalStories - $project->unclosedStories) / $project->totalStories, 2) * 100 : 0;
$projects[$project->id]->bugProgress = $project->totalBugs ? round(($project->totalBugs - $project->activeBugs) / $project->totalBugs, 2) * 100 : 0;
@@ -1047,6 +1082,7 @@ class block extends control
*/
public function printCmmiReportBlock()
{
$this->loadModel('program');
$program = $this->loadModel('project')->getByID($this->session->program);
$today = date('Y-m-d', strtotime(helper::today()));
$date = date('Ymd', strtotime($this->loadModel('weekly')->getThisMonday($today)));
@@ -1065,7 +1101,7 @@ class block extends control
$this->view->cv = $this->weekly->getCV($this->view->ev, $this->view->ac);
$this->view->current = $current;
$this->view->progress = ($task->totalConsumed + $task->totalLeft) ? round($task->totalConsumed / ($task->totalConsumed + $task->totalLeft), 2) * 100 : 0;
$this->view->progress = ($task->totalConsumed + $task->totalLeft) ? round($task->totalConsumed / ($task->totalConsumed + $task->totalLeft), 3) * 100 : 0;
}
/**
@@ -1365,6 +1401,7 @@ class block extends control
if(common::hasPriv('todo', 'view')) $hasViewPriv['todo'] = true;
if(common::hasPriv('task', 'view')) $hasViewPriv['task'] = true;
if(common::hasPriv('bug', 'view')) $hasViewPriv['bug'] = true;
if(common::hasPriv('risk', 'view')) $hasViewPriv['risk'] = true;
$params = $this->get->param;
$params = json_decode(base64_decode($params));
@@ -1419,6 +1456,19 @@ class block extends control
$this->view->bugs = $bugs;
}
if(isset($hasViewPriv['risk']))
{
$this->app->loadLang('risk');
$stmt = $this->dao->select('*')->from(TABLE_RISK)
->where('assignedTo')->eq($this->app->user->account)
->andWhere('deleted')->eq('0')
->andWhere('status')->ne('closed')
->orderBy('id_desc');
if(isset($params->riskNum)) $stmt->limit($params->riskNum);
$risks = $stmt->fetchAll();
$this->view->risks = $risks;
}
$this->view->selfCall = $this->selfCall;
$this->view->hasViewPriv = $hasViewPriv;
@@ -1426,17 +1476,6 @@ class block extends control
$this->display();
}
/**
* Print contribute block.
*
* @access public
* @return void
*/
public function printContributeBlock()
{
$this->view->data = $this->block->getContributeBlockData();
}
/**
* Print recent program block.
*
@@ -1535,15 +1574,20 @@ class block extends control
}
/**
* Print srcum progress block.
* Print srcum project list block.
*
* @access public
* @return void
*/
public function printScrumprogressBlock()
public function printScrumlistBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
}
$this->app->loadClass('pager', $static = true);
if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
$num = isset($this->params->num) ? (int)$this->params->num : 0;
$type = isset($this->params->type) ? $this->params->type : 'all';
$pager = pager::init(0, $num, 1);
$this->view->projectStats = $this->loadModel('project')->getProjectStats($type, $productID = 0, $branch = 0, $itemCounts = 30, $orderBy = 'order_desc', $this->viewType != 'json' ? $pager : '', $this->session->program);
}
/**
* Print srcum road map block.
@@ -1553,11 +1597,15 @@ class block extends control
*/
public function printScrumroadmapBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
$this->session->set('releaseList', $this->app->getURI(true));
$this->session->set('productPlanList', $this->app->getURI(true));
$products = $this->loadModel('product')->getPairs();
}
/**
* Print srcum road map block.
* Print srcum test block.
*
* @access public
* @return void
@@ -1574,7 +1622,7 @@ class block extends control
->leftJoin(TABLE_PROJECT)->alias('t4')->on('t1.project=t4.id')
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t5')->on('t1.project=t5.project')
->where('t1.deleted')->eq('0')
->andWhere('t1.product')->eq($this->session->program)->fi()
->andWhere('t1.program')->eq($this->session->program)->fi()
->andWhere('t1.product = t5.product')
->beginIF($this->params->type != 'all')->andWhere('t1.status')->eq($this->params->type)->fi()
->orderBy('t1.id desc')
@@ -1590,7 +1638,17 @@ class block extends control
*/
public function printScrumproductBlock()
{
$this->view->program = $this->loadModel('project')->getByID($this->session->program);
$products = $this->dao->select('id,name')->from(TABLE_PRODUCT)->where('program')->eq($this->session->program)->limit(15)->fetchPairs();
$productID = array_keys($products);
$stories = empty($productID) ? array() : $this->dao->select('count(*) as total, product')->from(TABLE_STORY)->where('product')->in($productID)->andWhere('deleted')->eq('0')->groupBy('product')->fetchPairs('product', 'total');
$bugs = empty($productID) ? array() : $this->dao->select('count(*) as total, product')->from(TABLE_BUG)->where('product')->in($productID)->andWhere('deleted')->eq('0')->groupBy('product')->fetchPairs('product', 'total');
$releases = empty($productID) ? array() : $this->dao->select('count(*) as total, product')->from(TABLE_RELEASE)->where('product')->in($productID)->andWhere('deleted')->eq('0')->groupBy('product')->fetchPairs('product', 'total');
$this->view->products = $products;
$this->view->stories = $stories;
$this->view->bugs = $bugs;
$this->view->releases = $releases;
}
/**
@@ -1601,7 +1659,7 @@ class block extends control
*/
public function printScrumprojectBlock()
{
$this->view->projectOverview = $this->dao->select('count(*) total, count(if(status="doing", id, null)) as doing, count(if(status="closed", id, null)) as finish')->from(TABLE_PROJECT)
$this->view->summary = $this->dao->select('count(*) as total, count(if(status="doing", id, null)) as doing, count(if(status="closed", id, null)) as finish')->from(TABLE_PROJECT)
->where('program')->eq($this->session->program)
->fetch();
}
@@ -1614,13 +1672,27 @@ class block extends control
*/
public function printScrumdynamicBlock()
{
$projects = $this->loadModel('project')->getPairs();
$actions = $this->dao->select('*')->from(TABLE_ACTION)
->where('project')->in(array_keys($projects))
->orderBy('id_desc')
->fetchAll();
$projects = $this->loadModel('project')->getPairs();
$products = $this->loadModel('product')->getPairs();
$productID = array();
foreach($products as $id => $name) $productID[] = ',' . $id . ',';
$this->view->actions = $this->loadModel('action')->transformActions($actions);
if(empty($projects) && empty($products))
{
$actions = array();
}
else
{
$actions = $this->dao->select('*')->from(TABLE_ACTION)
->beginIF($projects && $products)->where('project')->in(array_keys($projects))->orWhere('product')->in($productID)->fi()
->beginIF($projects && empty($products))->where('project')->in(array_keys($projects))->fi()
->beginIF(empty($projects) && $products)->where('product')->in($productID)->fi()
->orderBy('id_desc')
->limit(30)
->fetchAll();
}
$this->view->actions = empty($actions) ? array() : $this->loadModel('action')->transformActions($actions);
$this->view->users = $this->loadModel('user')->getPairs('noletter');
}
}
}
+1 -1
View File
@@ -92,7 +92,7 @@ $(function()
return true;
}
if(moduleID == 'html' || moduleID == 'dynamic' || moduleID == 'flowchart' || moduleID == 'assigntome' || moduleID == 'welcome')
if(moduleID == 'html' || moduleID == 'dynamic' || moduleID == 'flowchart' || moduleID == 'assigntome' || moduleID == 'welcome' || moduleID == 'contribute')
{
getNotSourceParams(moduleID, blockID, onFinish);
return true;
+1
View File
@@ -79,6 +79,7 @@ function refreshBlock($panel, afterRefresh)
}
$panel.find('.tablesorter').sortTable();
initTableHeader($panel);
$(".sparkline").sparkline();
}).fail(function()
{
$panel.addClass('panel-error');
+1
View File
@@ -252,6 +252,7 @@ $lang->block->availableBlocks->plan = 'Plan';
$lang->block->availableBlocks->release = 'Release';
$lang->block->availableBlocks->build = 'Build';
$lang->block->availableBlocks->testtask = 'Testaufgaben';
$lang->block->availableBlocks->risk = 'My Risks';
$lang->block->moduleList['product'] = $lang->productCommon;
$lang->block->moduleList['project'] = $lang->projectCommon;
+1
View File
@@ -252,6 +252,7 @@ $lang->block->availableBlocks->plan = 'Plans';
$lang->block->availableBlocks->release = 'Releases';
$lang->block->availableBlocks->build = 'Builds';
$lang->block->availableBlocks->testtask = 'Requests';
$lang->block->availableBlocks->risk = 'My Risks';
$lang->block->moduleList['product'] = $lang->productCommon;
$lang->block->moduleList['project'] = $lang->projectCommon;
+1
View File
@@ -252,6 +252,7 @@ $lang->block->availableBlocks->plan = 'Plans';
$lang->block->availableBlocks->release = 'Releases';
$lang->block->availableBlocks->build = 'Builds';
$lang->block->availableBlocks->testtask = 'Recettes';
$lang->block->availableBlocks->risk = 'My Risks';
$lang->block->moduleList['product'] = $lang->productCommon;
$lang->block->moduleList['project'] = $lang->projectCommon;
+1
View File
@@ -252,6 +252,7 @@ $lang->block->availableBlocks->plan = 'Kế hoạch';
$lang->block->availableBlocks->release = 'Phát hành';
$lang->block->availableBlocks->build = 'Bản dựng';
$lang->block->availableBlocks->testtask = 'Yêu cầu';
$lang->block->availableBlocks->risk = 'My Risks';
$lang->block->moduleList['product'] = $lang->productCommon;
$lang->block->moduleList['project'] = $lang->projectCommon;
+73 -32
View File
@@ -36,6 +36,7 @@ $lang->block->done = '已完成';
$lang->block->lblFlowchart = '流程图';
$lang->block->welcome = '欢迎总览';
$lang->block->lblTesttask = '查看测试详情';
$lang->block->contribute = '个人贡献';
$lang->block->leftToday = '今天剩余工作总计';
$lang->block->myTask = '我的任务';
@@ -53,6 +54,9 @@ $lang->block->resolvedBugs = '解决Bug数';
$lang->block->openedTestcases = '创建用例数';
$lang->block->cmmi = 'CMMI 3';
$lang->block->scrum = 'Scrum+';
$lang->block->allProject = '所有' . $lang->projectCommon;
$lang->block->doingProject = '进行中的' . $lang->projectCommon;
$lang->block->finishProject = '累积' . $lang->projectCommon;
$lang->block->params = new stdclass();
$lang->block->params->name = '参数名称';
@@ -72,25 +76,34 @@ $lang->block->nbsp = '';
$lang->block->hidden = '隐藏';
$lang->block->dynamicInfo = "<span class='timeline-tag'>%s</span> <span class='timeline-text'>%s <em>%s</em> %s <a href='%s' title='%s'>%s</a></span>";
$lang->block->default['cmmi']['program']['1']['title'] = '项目周报';
$lang->block->default['cmmi']['program']['1']['block'] = 'cmmireport';
$lang->block->default['cmmi']['program']['1']['grid'] = 8;
$lang->block->productName = $lang->productCommon . '名称';
$lang->block->totalStory = '总' . $lang->storyCommon;
$lang->block->totalBug = '总Bug';
$lang->block->totalRelease = '发布次数';
$lang->block->default['cmmi']['program']['2']['title'] = '估算';
$lang->block->default['cmmi']['program']['2']['block'] = 'cmmiestimate';
$lang->block->default['cmmi']['program']['2']['grid'] = 4;
$lang->block->default['cmmi']['program']['1']['title'] = '项目周报';
$lang->block->default['cmmi']['program']['1']['block'] = 'cmmireport';
$lang->block->default['cmmi']['program']['1']['source'] = 'program';
$lang->block->default['cmmi']['program']['1']['grid'] = 8;
$lang->block->default['cmmi']['program']['3']['title'] = '计划甘特图';
$lang->block->default['cmmi']['program']['3']['block'] = 'cmmigantt';
$lang->block->default['cmmi']['program']['3']['grid'] = 8;
$lang->block->default['cmmi']['program']['2']['title'] = '估算';
$lang->block->default['cmmi']['program']['2']['block'] = 'cmmiestimate';
$lang->block->default['cmmi']['program']['2']['source'] = 'program';
$lang->block->default['cmmi']['program']['2']['grid'] = 4;
$lang->block->default['cmmi']['program']['4']['title'] = '到目前为止项目进展趋势图';
$lang->block->default['cmmi']['program']['4']['block'] = 'cmmiprogress';
$lang->block->default['cmmi']['program']['4']['grid'] = 4;
$lang->block->default['cmmi']['program']['3']['title'] = '计划甘特图';
$lang->block->default['cmmi']['program']['3']['block'] = 'cmmigantt';
$lang->block->default['cmmi']['program']['3']['source'] = 'program';
$lang->block->default['cmmi']['program']['3']['grid'] = 8;
$lang->block->default['cmmi']['program']['5']['title'] = '项目问题';
$lang->block->default['cmmi']['program']['5']['block'] = 'cmmiissue';
$lang->block->default['cmmi']['program']['5']['grid'] = 8;
$lang->block->default['cmmi']['program']['4']['title'] = '到目前为止项目进展趋势图';
$lang->block->default['cmmi']['program']['4']['block'] = 'cmmiprogress';
$lang->block->default['cmmi']['program']['4']['grid'] = 4;
$lang->block->default['cmmi']['program']['5']['title'] = '项目问题';
$lang->block->default['cmmi']['program']['5']['block'] = 'cmmiissue';
$lang->block->default['cmmi']['program']['5']['source'] = 'program';
$lang->block->default['cmmi']['program']['5']['grid'] = 8;
$lang->block->default['cmmi']['program']['5']['params']['type'] = 'all';
$lang->block->default['cmmi']['program']['5']['params']['num'] = '15';
@@ -101,23 +114,24 @@ $lang->block->default['cmmi']['program']['6']['block'] = 'dynamic';
$lang->block->default['cmmi']['program']['6']['grid'] = 4;
$lang->block->default['cmmi']['program']['6']['source'] = '';
$lang->block->default['cmmi']['program']['7']['title'] = '项目风险';
$lang->block->default['cmmi']['program']['7']['block'] = 'cmmirisk';
$lang->block->default['cmmi']['program']['7']['grid'] = 8;
$lang->block->default['cmmi']['program']['7']['title'] = '项目风险';
$lang->block->default['cmmi']['program']['7']['block'] = 'cmmirisk';
$lang->block->default['cmmi']['program']['7']['source'] = 'program';
$lang->block->default['cmmi']['program']['7']['grid'] = 8;
$lang->block->default['cmmi']['program']['7']['params']['type'] = 'all';
$lang->block->default['cmmi']['program']['7']['params']['num'] = '15';
$lang->block->default['cmmi']['program']['7']['params']['orderBy'] = 'id_desc';
$lang->block->default['scrum']['program']['1']['title'] = '项目整体情况';
$lang->block->default['scrum']['program']['1']['title'] = '项目整体情况';
$lang->block->default['scrum']['program']['1']['block'] = 'scrumoverall';
$lang->block->default['scrum']['program']['1']['grid'] = 8;
$lang->block->default['scrum']['program']['2']['title'] = '进行中的迭代';
$lang->block->default['scrum']['program']['2']['block'] = 'scrumprogress';
$lang->block->default['scrum']['program']['2']['title'] = $lang->projectCommon . '列表';
$lang->block->default['scrum']['program']['2']['block'] = 'scrumlist';
$lang->block->default['scrum']['program']['2']['grid'] = 8;
$lang->block->default['scrum']['program']['3']['title'] = '产品路线图';
$lang->block->default['scrum']['program']['3']['title'] = $lang->productCommon . '路线图';
$lang->block->default['scrum']['program']['3']['block'] = 'scrumroadmap';
$lang->block->default['scrum']['program']['3']['grid'] = 8;
@@ -129,11 +143,11 @@ $lang->block->default['scrum']['program']['4']['params']['type'] = 'all';
$lang->block->default['scrum']['program']['4']['params']['num'] = '15';
$lang->block->default['scrum']['program']['4']['params']['orderBy'] = 'id_desc';
$lang->block->default['scrum']['program']['5']['title'] = '产品总览';
$lang->block->default['scrum']['program']['5']['title'] = $lang->productCommon . '总览';
$lang->block->default['scrum']['program']['5']['block'] = 'scrumproduct';
$lang->block->default['scrum']['program']['5']['grid'] = 4;
$lang->block->default['scrum']['program']['6']['title'] = '迭代总览';
$lang->block->default['scrum']['program']['6']['title'] = $lang->projectCommon . '总览';
$lang->block->default['scrum']['program']['6']['block'] = 'scrumproject';
$lang->block->default['scrum']['program']['6']['grid'] = 4;
@@ -252,10 +266,12 @@ $lang->block->default['full']['my']['4']['grid'] = 8;
$lang->block->default['full']['my']['5']['title'] = '个人贡献';
$lang->block->default['full']['my']['5']['block'] = 'contribute';
$lang->block->default['full']['my']['5']['source'] = '';
$lang->block->default['full']['my']['5']['grid'] = 4;
$lang->block->default['full']['my']['6']['title'] = '我的近期项目';
$lang->block->default['full']['my']['6']['block'] = 'recentprogram';
$lang->block->default['full']['my']['6']['source'] = 'program';
$lang->block->default['full']['my']['6']['grid'] = 8;
$lang->block->default['full']['my']['7']['title'] = '指派给我';
@@ -270,9 +286,10 @@ $lang->block->default['full']['my']['8']['title'] = '项目人力投入';
$lang->block->default['full']['my']['8']['block'] = 'programteam';
$lang->block->default['full']['my']['8']['grid'] = 8;
$lang->block->default['full']['my']['9']['title'] = '项目列表';
$lang->block->default['full']['my']['9']['block'] = 'program';
$lang->block->default['full']['my']['9']['grid'] = 8;
$lang->block->default['full']['my']['9']['title'] = '项目列表';
$lang->block->default['full']['my']['9']['block'] = 'program';
$lang->block->default['full']['my']['9']['source'] = 'program';
$lang->block->default['full']['my']['9']['grid'] = 8;
$lang->block->default['full']['my']['9']['params']['orderBy'] = 'id_desc';
$lang->block->default['full']['my']['9']['params']['num'] = '15';
@@ -294,6 +311,7 @@ $lang->block->availableBlocks->plan = '计划列表';
$lang->block->availableBlocks->release = '发布列表';
$lang->block->availableBlocks->build = '版本列表';
$lang->block->availableBlocks->testtask = '测试版本列表';
$lang->block->availableBlocks->risk = '我的风险';
$lang->block->moduleList['program'] = '项目';
$lang->block->moduleList['product'] = $lang->productCommon;
@@ -303,16 +321,18 @@ $lang->block->moduleList['todo'] = '待办';
$lang->block->modules['program'] = new stdclass();
$lang->block->modules['program']->availableBlocks = new stdclass();
$lang->block->modules['program']->availableBlocks->list = '项目列表';
$lang->block->modules['program']->availableBlocks->program = '项目列表';
$lang->block->modules['program']->availableBlocks->recentprogram = '近期项目';
$lang->block->modules['program']->availableBlocks->statistic = '项目统计';
$lang->block->modules['scrum']['index'] = new stdclass();
$lang->block->modules['scrum']['index']->availableBlocks = new stdclass();
$lang->block->modules['scrum']['index']->availableBlocks->scrumoverall = '项目整体情况';
$lang->block->modules['scrum']['index']->availableBlocks->scrumprogress = '进行中的迭代';
$lang->block->modules['scrum']['index']->availableBlocks->scrumproject = '迭代总览';
$lang->block->modules['scrum']['index']->availableBlocks->scrumproduct = '产品总览';
$lang->block->modules['scrum']['index']->availableBlocks->scrumlist = $lang->projectCommon . '列表';
$lang->block->modules['scrum']['index']->availableBlocks->scrumproject = $lang->projectCommon . '总览';
$lang->block->modules['scrum']['index']->availableBlocks->scrumproduct = $lang->productCommon . '总览';
$lang->block->modules['scrum']['index']->availableBlocks->scrumtest = '待测版本';
$lang->block->modules['scrum']['index']->availableBlocks->scrumroadmap = '产品路线图';
$lang->block->modules['scrum']['index']->availableBlocks->scrumroadmap = $lang->productCommon . '路线图';
$lang->block->modules['cmmi']['index'] = new stdclass();
$lang->block->modules['cmmi']['index']->availableBlocks = new stdclass();
@@ -402,6 +422,7 @@ $lang->block->orderByList->story['stage_desc'] = '阶段倒序';
$lang->block->todoNum = '待办数';
$lang->block->taskNum = '任务数';
$lang->block->bugNum = 'Bug数';
$lang->block->riskNum = '风险数';
$lang->block->typeList = new stdclass();
@@ -434,12 +455,32 @@ $lang->block->typeList->project['doing'] = '进行中';
$lang->block->typeList->project['all'] = '全部';
$lang->block->typeList->project['involved'] = '我参与的';
$lang->block->typeList->scrum['undone'] = '未完成';
$lang->block->typeList->scrum['doing'] = '进行中';
$lang->block->typeList->scrum['all'] = '全部';
$lang->block->typeList->scrum['involved'] = '我参与的';
$lang->block->typeList->testtask['wait'] = '待测版本';
$lang->block->typeList->testtask['doing'] = '测试中版本';
$lang->block->typeList->testtask['blocked'] = '阻塞版本';
$lang->block->typeList->testtask['done'] = '已测版本';
$lang->block->typeList->testtask['all'] = '全部';
$lang->block->modules['program']->moreLinkList = new stdclass();
$lang->block->modules['program']->moreLinkList->recentprogram = 'program|browse|';
$lang->block->modules['program']->moreLinkList->statistic = 'program|browse|';
$lang->block->modules['program']->moreLinkList->program = 'program|browse|';
$lang->block->modules['program']->moreLinkList->cmmireport = 'weekly|index|';
$lang->block->modules['program']->moreLinkList->cmmiestimate = 'workestimation|index|';
$lang->block->modules['program']->moreLinkList->cmmiissue = 'issue|browse|';
$lang->block->modules['program']->moreLinkList->cmmirisk = 'risk|browse|';
$lang->block->modules['program']->moreLinkList->scrumlist = 'project|all|';
$lang->block->modules['program']->moreLinkList->scrumroadmap = 'product|all|';
$lang->block->modules['program']->moreLinkList->scrumtest = 'testtask|browse|';
$lang->block->modules['program']->moreLinkList->scrumproduct = 'product|all|';
$lang->block->modules['program']->moreLinkList->scrumproject = 'project|all|';
$lang->block->modules['program']->moreLinkList->scrumdynamic = 'company|dynamic|';
$lang->block->modules['product']->moreLinkList = new stdclass();
$lang->block->modules['product']->moreLinkList->list = 'product|all|product=&line=0&status=%s';
$lang->block->modules['product']->moreLinkList->story = 'my|story|type=%s';
+1
View File
@@ -252,6 +252,7 @@ $lang->block->availableBlocks->plan = '計劃列表';
$lang->block->availableBlocks->release = '發佈列表';
$lang->block->availableBlocks->build = '版本列表';
$lang->block->availableBlocks->testtask = '測試版本列表';
$lang->block->availableBlocks->risk = '我的風險';
$lang->block->moduleList['product'] = $lang->productCommon;
$lang->block->moduleList['project'] = $lang->projectCommon;
+158 -29
View File
@@ -59,6 +59,8 @@ class blockModel extends model
unset($_SESSION['album'][$uid]);
}
if(strpos($data->block, 'cmmi') !== false) $data->type = 'cmmi';
if(strpos($data->block, 'scrum') !== false) $data->type = 'scrum';
$data->params = helper::jsonEncode($data->params);
$this->dao->replace(TABLE_BLOCK)->data($data)->exec();
if(!dao::isError()) $this->loadModel('score')->create('block', 'set');
@@ -129,11 +131,12 @@ class blockModel extends model
* @access public
* @return void
*/
public function getBlockList($module = 'my')
public function getBlockList($module = 'my', $type = '')
{
$blocks = $this->dao->select('*')->from(TABLE_BLOCK)->where('account')->eq($this->app->user->account)
->andWhere('module')->eq($module)
->andWhere('hidden')->eq(0)
->beginIF($type)->andWhere('type')->eq($type)->fi()
->beginIF($this->config->global->flow == 'onlyStory')->andWhere('source')->notin('project,qa')->fi()
->beginIF($this->config->global->flow == 'onlyTask')->andWhere('source')->notin('product,qa')->fi()
->beginIF($this->config->global->flow == 'onlyTest')->andWhere('source')->notin('product,project')->fi()
@@ -233,6 +236,7 @@ class blockModel extends model
{
$block['order'] = $index;
$block['module'] = $module;
$block['type'] = $type;
$block['account'] = $account;
$block['params'] = isset($block['params']) ? helper::jsonEncode($block['params']) : '';
if(!isset($block['source'])) $block['source'] = $module;
@@ -446,6 +450,26 @@ class blockModel extends model
return json_encode($params);
}
/**
* Get program params.
*
* @access public
* @return json
*/
public function getProgramParams()
{
$this->app->loadLang('program');
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->program->featureBar;
$params->type['control'] = 'select';
$params->orderBy['name'] = $this->lang->block->orderBy;
$params->orderBy['options'] = $this->lang->block->orderByList->product;
$params->orderBy['control'] = 'select';
return json_encode($this->onlyNumParams($params));
}
/**
* Get Build params.
*
@@ -547,6 +571,17 @@ class blockModel extends model
return json_encode($params);
}
/**
* Get recent program pararms.
*
* @access public
* @return string
*/
public function getRecentprogramParams()
{
return false;
}
/**
* Get product overview pararms.
*
@@ -558,6 +593,102 @@ class blockModel extends model
return false;
}
/**
* Get cmmi program report pararms.
*
* @access public
* @return string
*/
public function getCmmireportParams()
{
return false;
}
/**
* Get program estimate pararms.
*
* @access public
* @return string
*/
public function getCmmiestimateParams()
{
return false;
}
/**
* Get program gantt pararms.
*
* @access public
* @return string
*/
public function getCmmiganttParams()
{
return false;
}
/**
* Get program progress pararms.
*
* @access public
* @return string
*/
public function getCmmiprogressParams()
{
return false;
}
/**
* Get cmmi issue params.
*
* @param string $module
* @access public
* @return void
*/
public function getCmmiissueParams($module = '')
{
$this->app->loadLang('issue');
$params = new stdclass();
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->issue->labelList;
$params->type['control'] = 'select';
$params->num['name'] = $this->lang->block->num;
$params->num['default'] = 20;
$params->num['control'] = 'input';
$params->orderBy['name'] = $this->lang->block->orderBy;
$params->orderBy['options'] = $this->lang->block->orderByList->product;
$params->orderBy['control'] = 'select';
return json_encode($params);
}
/**
* Get cmmi risk params.
*
* @param string $module▫
* @access public
* @return void
*/
public function getCmmiriskParams($module = '')
{
$this->app->loadLang('risk');
$params = new stdclass();
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->risk->featureBar['browse'];
$params->type['control'] = 'select';
$params->num['name'] = $this->lang->block->num;
$params->num['default'] = 20;
$params->num['control'] = 'input';
$params->orderBy['name'] = $this->lang->block->orderBy;
$params->orderBy['options'] = $this->lang->block->orderByList->product;
$params->orderBy['control'] = 'select';
return json_encode($params);
}
/**
* Get project params.
*
@@ -587,6 +718,10 @@ class blockModel extends model
$params->bugNum['default'] = 20;
$params->bugNum['control'] = 'input';
$params->riskNum['name'] = $this->lang->block->riskNum;
$params->riskNum['default'] = 20;
$params->riskNum['control'] = 'input';
return json_encode($params);
}
@@ -709,40 +844,14 @@ class blockModel extends model
return $key == $hash;
}
/**
* Get cmmi issue params.
*
* @param string $module▫
* @access public
* @return void
*/
public function getCmmiissueParams($module = '')
{
$this->app->loadLang('issue');
$params = new stdclass();
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->issue->labelList;
$params->type['control'] = 'select';
$params->num['name'] = $this->lang->block->num;
$params->num['default'] = 20;
$params->num['control'] = 'input';
$params->orderBy['name'] = $this->lang->block->orderBy;
$params->orderBy['options'] = $this->lang->block->orderByList->product;
$params->orderBy['control'] = 'select';
return json_encode($params);
}
/**
* Get testtask params.
*▫
* @param string $module▫
* @param string $module
* @access public
* @return void
*/
public function getScrumtestParams($module = '')
public function getScrumtestParams($module = '')
{
$params = new stdclass();
$params->type['name'] = $this->lang->block->type;
@@ -756,4 +865,24 @@ class blockModel extends model
return json_encode($params);
}
/**
* Get scrum project list params.
*▫
* @param string $module
* @access public
* @return void
*/
public function getScrumListParams($module = '')
{
$params = new stdclass();
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->block->typeList->scrum;
$params->type['control'] = 'select';
$params->num['name'] = $this->lang->block->num;
$params->num['default'] = 20;
$params->num['control'] = 'input';
return json_encode($params);
}
}
+4 -7
View File
@@ -1,10 +1,7 @@
<div class="panel-body">
<style>
.block-cmmiprogress #chartUnit {position: absolute; color: #999; top: 80px; left: 15px;}
.block-cmmiprogress #chartLegend {position: absolute; right: 0; width: 80px; height: 60px; top: 50%; margin-top: -30px; line-height: 30px; color: #838A9D; font-size: 12px;}
.block-cmmiprogress #chartLegend > div {position: relative; padding-left: 30px;}
.block-cmmiprogress #chartLegend > div > .barline {position: absolute; width: 20px; left: 0; top: 13px; height: 3px;}
.block-cmmiprogress #chartLegend .line-pv .barline{background: #1183fb}
.block-cmmiprogress #chartLegend .line-ev .barline{background: rgb(0, 218, 136)}
.block-cmmiprogress #chartLegend .line-ac .barline{background: rgb(255, 145, 0)}
.block-cmmiprogress .milestone-chart {box-shadow: none}
.block-cmmiprogress .milestone-chart.has-scrollbar {margin-bottom: -10px}
</style>
<?php include '../../milestone/view/chart.html.php';?>
</div>
@@ -55,6 +55,10 @@ html[lang="en"] .product-info .type-info {color: #A6AAB8; text-align: center; po
.block-statistic.block-sm .nav-secondary > li.active > a.btn-view {width: auto; left: 0; right: 0;}
.block-statistic.block-sm .nav-secondary > li.active > a.btn-view > i {display: none;}
.block-statistic.block-sm .nav-secondary > li.active > a.btn-view:hover {cursor: pointer; background: rgba(0,0,0,.1)}
.block-statistic .program-info .info span+span{margin-left: 15px}
.block-statistic .project-info{margin-top: 25px}
.block-statistic .project-info .col-xs-5, .block-statistic .project-info .col-xs-7{margin-top: 8px}
.block-statistic .project-info .col-xs-5{padding-left: 0px;}
.status-count{margin:auto}
.status-count tr:first-child td:last-child{color:#000;font-weight:bold}
@@ -106,6 +110,7 @@ $(function()
<?php foreach($programs as $program):?>
<div class="tab-pane fade<?php if($program->id == $selected) echo ' active in';?>" id="tab3Content<?php echo $program->id;?>">
<div class="table-row">
<?php if($program->template == 'scrum'):?>
<div class="col-5 text-middle text-center">
<div class="progress-pie inline-block space" data-value="<?php echo $program->progress;?>" data-doughnut-size="84">
<canvas width="120" height="120"></canvas>
@@ -133,16 +138,32 @@ $(function()
</div>
<div class="col-7">
<div class="program-info">
<div class='title'><?php echo $lang->program->allInput;?></div>
<h4><?php echo $lang->program->allInput;?></h4>
<div class='info'>
<span><i class='icon icon-group'></i> <?php echo $program->countMembers;?></span>
<span><i class='icon icon-clock'></i> <?php echo $program->consumed;?></span>
<span><i class='icon icon-cost'></i> <?php echo $program->budget;?></span>
<span><i class='icon icon-group'></i> <?php echo $program->teamCount;?></span>
<span><i class='icon icon-clock'></i> <?php echo $program->estimate;?></span>
<span><i class='icon icon-cost'></i> <?php echo $program->budget . ' ' . zget($lang->program->unitList, $program->budgetUnit);?></span>
</div>
</div>
<div class="project-info">
<?php $i = 0;?>
<h4><?php echo $lang->program->lastIteration;?></h4>
<?php foreach($program->projects as $project):?>
<?php $i ++;?>
<?php if($i > 3) break;?>
<div class='col-xs-5'><?php echo $project->name;?></div>
<div class='col-xs-7'>
<div class='progress progress-text-left'>
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="<?php echo $project->hours->progress;?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $project->hours->progress;?>%">
<span class='progress-text'><?php echo $project->hours->progress . '%';?></span>
</div>
</div>
</div>
<?php endforeach;?>
</div>
</div>
<?php else:?>
<?php endif;?>
</div>
</div>
<?php endforeach;?>
+49
View File
@@ -0,0 +1,49 @@
<?php if(empty($risks)): ?>
<div class='empty-tip'><?php echo $lang->block->emptyTip;?></div>
<?php else:?>
<style>
.block-risks .c-id {width: 50px;}
.block-risks .c-pri {width: 50px;text-align: center;}
.block-risks .c-identifiedDate {width: 95px;}
.block-risks .c-category {width: 80px;}
.block-risks .c-status {width: 80px;}
.block-risks.block-sm .c-status {text-align: center;}
</style>
<div class='panel-body has-table scrollbar-hover'>
<table class='table table-borderless table-fixed table-fixed-head table-hover tablesorter block-risks <?php if(!$longBlock) echo 'block-sm'?>'>
<thead>
<tr>
<th class='c-id'><?php echo $lang->idAB?></th>
<th class='c-name'><?php echo $lang->risk->name?></th>
<?php if($longBlock):?>
<th class='c-pri'><?php echo $lang->priAB?></th>
<th class='c-category'><?php echo $lang->risk->category;?></th>
<th class='c-identifiedDate'><?php echo $lang->risk->identifiedDate;?></th>
<?php endif;?>
<th class='c-status'><?php echo $lang->risk->status;?></th>
</tr>
</thead>
<tbody>
<?php foreach($risks as $risk):?>
<?php
$appid = isset($_GET['entry']) ? "class='app-btn' data-id='{$this->get->entry}'" : '';
$viewLink = $this->createLink('risk', 'view', "riskID={$risk->id}");
?>
<tr data-url='<?php echo empty($sso) ? $viewLink : $sso . $sign . 'referer=' . base64_encode($viewLink); ?>' <?php echo $appid?>>
<td class='c-id-xs'><?php echo sprintf('%03d', $risk->id);?></td>
<td class='c-name' title='<?php echo $risk->name?>'><?php echo $risk->name?></td>
<?php if($longBlock):?>
<td class='c-pri'><?php echo zget($lang->risk->priList, $risk->pri)?></td>
<td class='c-category'><?php echo zget($lang->risk->categoryList, $risk->category)?></td>
<td class='c-identifiedDate'><?php echo $risk->identifiedDate == '0000-00-00' ? '' : $risk->identifiedDate;?></td>
<?php endif;?>
<?php $status = $this->processStatus('risk', $risk);?>
<td class='c-status' title='<?php echo $status;?>'>
<span class="status-risk status-<?php echo $risk->status?>"><?php echo $status;?></span>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
<?php endif;?>
@@ -1,10 +1,6 @@
<?php if(empty($actions)): ?>
<div class='empty-tip'><?php echo $lang->block->emptyTip;?></div>
<?php else:?>
<style>
.block-dynamic .timeline > li .timeline-text {display: block; overflow: hidden; text-overflow: ellipsis; max-height: 20px; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; }
.block-dynamic .panel-body {padding-top: 0;}
</style>
<div class='panel-body scrollbar-hover'>
<ul class="timeline timeline-tag-left no-margin">
<?php
+73
View File
@@ -0,0 +1,73 @@
<?php
/**
* The project block view file of block module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package block
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php if(empty($projectStats)): ?>
<div class='empty-tip'><?php common::printLink('project', 'create', '', "<i class='icon-plus'></i> " . $lang->project->create, '', "class='btn btn-primary'")?></div>
<?php else:?>
<div class="panel-body has-table scrollbar-hover">
<table class='table table-borderless table-hover table-fixed table-fixed-head tablesorter block-projects tablesorter'>
<thead>
<tr class='text-center'>
<th class='c-name text-left'><?php echo $lang->project->name;?></th>
<th class="c-date"><?php echo $lang->project->end;?></th>
<?php if($longBlock):?>
<?php $thClass = common::checkNotCN() ? 'w-85px' : 'c-hours';?>
<th class="c-status"><?php echo $lang->statusAB;?></th>
<th class='<?php echo $thClass?>'><?php echo $lang->project->totalEstimate;?></th>
<th class="c-hours"><?php echo $lang->project->totalConsumed;?></th>
<th class="c-hours"><?php echo $lang->project->totalLeft;?></th>
<?php endif;?>
<th class="c-progress"><?php echo $lang->project->progress;?></th>
<?php if($longBlock):?>
<th><?php echo $lang->project->burn;?></th>
<?php endif;?>
</tr>
</thead>
<tbody class="text-center">
<?php $id = 0; ?>
<?php foreach($projectStats as $project):?>
<?php
$appid = isset($_GET['entry']) ? "class='app-btn text-center' data-id='{$this->get->entry}'" : "class='text-center'";
$viewLink = $this->createLink('project', 'task', 'project=' . $project->id);
?>
<tr data-url='<?php echo empty($sso) ? $viewLink : $sso . $sign . 'referer=' . base64_encode($viewLink); ?>' <?php echo $appid?>>
<td class='c-name text-left' title='<?php echo $project->name;?>'><nobr><?php echo html::a($this->createLink('project', 'task', 'project=' . $project->id), $project->name, '', "title='$project->name'");?></nobr></td>
<td class="c-date"><?php echo $project->end;?></td>
<?php if($longBlock):?>
<td class="w-70px">
<?php if(isset($project->delay)):?>
<span class="status-project status-delayed" title='<?php echo $lang->project->delayed;?>'><?php echo $lang->project->delayed;?></span>
<?php else:?>
<?php $statusName = $this->processStatus('project', $project);?>
<span class="status-project status-<?php echo $project->status?>" title='<?php echo $statusName;?>'><?php echo $statusName;?></span>
<?php endif;?>
</td>
<td class="c-hours"><?php echo $project->hours->totalEstimate;?></td>
<td class="c-hours"><?php echo $project->hours->totalConsumed;?></td>
<td class="c-hours"><?php echo $project->hours->totalLeft;?></td>
<?php endif;?>
<td class="c-progress">
<div class="progress progress-text-left">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="<?php echo $project->hours->progress;?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $project->hours->progress;?>%">
<span class="progress-text"><?php echo $project->hours->progress;?>%</span>
</div>
</div>
</td>
<?php if($longBlock):?>
<td id='spark-<?php echo $id++?>' class='no-padding text-left sparkline' values='<?php echo join(',', $project->burns);?>'></td>
<?php endif;?>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
<?php endif;?>
@@ -0,0 +1,43 @@
<?php
/**
* The project block view file of block module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package block
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php if(empty($products)): ?>
<div class='empty-tip'><?php common::printLink('product', 'create', '', "<i class='icon-plus'></i> " . $lang->product->create, '', "class='btn btn-primary'")?></div>
<?php else:?>
<div class="panel-body has-table scrollbar-hover">
<table class='table table-borderless table-hover table-fixed table-fixed-head tablesorter block-projects tablesorter'>
<thead>
<tr class='text-center'>
<th class='c-num'><?php echo $lang->block->productName;?></th>
<th class='c-num'><?php echo $lang->block->totalStory;?></th>
<th class='c-num'><?php echo $lang->block->totalBug;?></th>
<th class='c-num'><?php echo $lang->block->totalRelease;?></th>
</tr>
</thead>
<tbody class="text-center">
<?php $id = 0; ?>
<?php foreach($products as $id => $name):?>
<?php
$appid = isset($_GET['entry']) ? "class='app-btn' data-id='{$this->get->entry}'" : "";
$viewLink = $this->createLink('product', 'browse', 'productID=' . $id);
?>
<tr class='text-center' data-url='<?php echo empty($sso) ? $viewLink : $sso . $sign . 'referer=' . base64_encode($viewLink); ?>' <?php echo $appid?>>
<td class="c-num text-ellipsis" title="<?php echo $name;?>"><?php echo $name;?></td>
<td class="c-num"><?php echo empty($stories[$id]) ? 0: $stories[$id];?></td>
<td class="c-num"><?php echo empty($bugs[$id]) ? 0: $bugs[$id];?></td>
<td class="c-num"><?php echo empty($releases[$id]) ? 0: $releases[$id];?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
<?php endif;?>
+8 -8
View File
@@ -10,7 +10,7 @@
* @link http://www.zentao.net
*/
?>
<?php if(empty($projectOverview)): ?>
<?php if(empty($summary)): ?>
<div class='empty-tip'><?php echo $lang->block->emptyTip;?></div>
<?php else:?>
<style>
@@ -27,19 +27,19 @@
<div class="panel-body table-row">
<div class="col-4 text-middle text-center">
<div class="tile">
<div class="tile-title">所有阶段</div>
<div class="tile-amount">25</div>
<div class="tile-title"><?php echo $lang->block->allProject;?></div>
<div class="tile-amount"><?php echo $summary->total;?></div>
</div>
</div>
<div class="col-8 text-middle">
<ul class="status-bars" style="transform: rotate(90deg);">
<ul class="status-bars all-statistics">
<li>
<span class="bar" style="height: 0%"><span class="value">0</span></span>
<span class="title">进行中</span>
<span class="bar" style="height: <?php echo empty($summary->doing) ? 0 : round(($summary->doing/$summary->total) * 100);?>%"><span class="value"><?php echo $summary->doing;?></span></span>
<span class="title"><?php echo $lang->block->doingProject;?></span>
</li>
<li>
<span class="bar" style="height: 100%"><span class="value">100</span></span>
<span class="title">已挂起</span>
<span class="bar" style="height: <?php echo empty($summary->finish) ? 0 : round(($summary->finish/$summary->total) * 100);?>%"><span class="value"><?php echo $summary->finish;?></span></span>
<span class="title"><?php echo $lang->block->finishProject;?></span>
</li>
</ul>
</div>
@@ -0,0 +1,53 @@
<?php
/**
* The roadmap view file of product module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package product
* @version $Id: roadmap.html.php 4129 2013-01-18 01:58:14Z wwccss $
* @link http://www.zentao.net
*/
?>
<div class="panel-body">
<div class="release-path">
<ul class="release-line">
<li>
<a href="/index.php?m=release&amp;f=view&amp;releaseID=2&amp;pgm=7">
<span class="title" title="发布二">渠成一期V1.1.2</span>
<span class="date">2020/08/01-09/01</span>
<span class="date">总消耗 120h</span>
</a>
</li>
<li>
<a href="/index.php?m=release&amp;f=view&amp;releaseID=2&amp;pgm=7">
<span class="title" title="发布二">渠成一期V1.1.2</span>
<span class="date">2020/08/01-09/01</span>
<span class="date">总消耗 120h</span>
</a>
</li>
<li>
<a href="/index.php?m=release&amp;f=view&amp;releaseID=2&amp;pgm=7">
<span class="title" title="发布二">渠成一期V1.1.2</span>
<span class="date">2020/08/01-09/01</span>
<span class="date">总消耗 120h</span>
</a>
</li>
<li>
<a href="/index.php?m=release&amp;f=view&amp;releaseID=2&amp;pgm=7">
<span class="title" title="发布二">渠成一期V1.1.2</span>
<span class="date">2020/08/01-09/01</span>
<span class="date">总消耗 120h</span>
</a>
</li>
<li>
<a href="/index.php?m=release&amp;f=view&amp;releaseID=2&amp;pgm=7">
<span class="title" title="发布二">渠成一期V1.1.2</span>
<span class="date">2020/08/01-09/01</span>
<span class="date">总消耗 120h</span>
</a>
</li>
</ul>
</div>
</div>
+4 -4
View File
@@ -35,14 +35,14 @@
$viewLink = $this->createLink('testtask', 'view', "testtaskID={$testtask->id}");
?>
<tr class='text-center' data-url='<?php echo empty($sso) ? $viewLink : $sso . $sign . 'referer=' . base64_encode($viewLink); ?>' <?php echo $appid?>>
<td class='text-left' title='<?php echo $testtask->name?>'><?php echo $testtask->name?></td>
<td class='text-left text-ellipsis' title='<?php echo $testtask->name?>'><?php echo $testtask->name?></td>
<?php if($longBlock):?>
<td class='text-left' title='<?php echo $testtask->productName?>'><?php echo $testtask->productName?></td>
<td class='text-left text-ellipsis' title='<?php echo $testtask->productName?>'><?php echo $testtask->productName?></td>
<?php endif;?>
<?php if($longBlock):?>
<td class='text-left' title='<?php echo $testtask->projectName?>'><?php echo $testtask->projectName?></td>
<td class='text-left text-ellipsis' title='<?php echo $testtask->projectName?>'><?php echo $testtask->projectName?></td>
<?php endif;?>
<td class='text-left' title='<?php echo $testtask->buildName?>'><?php echo $testtask->buildName?></td>
<td class='text-left text-ellipsis' title='<?php echo $testtask->buildName?>'><?php echo $testtask->buildName?></td>
<td><?php echo zget($lang->testtask->statusList, $testtask->status)?></td>
</tr>
<?php endforeach;?>
+1 -1
View File
@@ -27,7 +27,7 @@
.block-welcome .progress-group{margin-top: 20px;}
.block-welcome .progress{margin-top: 10px; width: 85%}
</style>
<?php $progress = $tasks == 0 ? 0 : ceil($doneTasks / $tasks) * 100;?>
<?php $progress = $tasks == 0 ? 0 : round($doneTasks / $tasks, 3) * 100;?>
<div class='panel-move-handler'></div>
<div class="panel-body conatiner-fluid">
<div class="table-row">
+2 -1
View File
@@ -33,7 +33,8 @@ $lang->my->menuOrder[75] = 'score';
$lang->todo->menuOrder = $lang->my->menuOrder;
/* product menu order. */
$lang->product->menuOrder[0] = 'plan';
$lang->product->menuOrder[0] = 'plan';
$lang->product->menuOrder[1] = 'requirement';
$lang->product->menuOrder[5] = 'story';
$lang->product->menuOrder[15] = 'release';
$lang->product->menuOrder[20] = 'roadmap';
+2 -3
View File
@@ -1179,9 +1179,8 @@ $lang->cmmiproduct->menu->requirement = '用户需求|product|browse|product={PR
$lang->cmmiproduct->menu->story = '软件需求|product|browse|product={PRODUCT}&branch=&browseType=unclosed&queryID=0&storyType=story';
$lang->cmmiproduct->menu->track = '跟踪矩阵|story|track|product={PRODUCT}';
$lang->story->menu = $lang->cmmiproduct->menu;
$lang->milestone->menu = $lang->weekly->menu;
$lang->nc->menu = $lang->auditplan->menu;
$lang->milestone->menu = $lang->weekly->menu;
$lang->nc->menu = $lang->auditplan->menu;
$lang->noMenuModule = array('my', 'todo', 'effort', 'program', 'attend', 'leave', 'makeup', 'overtime', 'lieu', 'holiday', 'custom', 'auditcl', 'subject', 'admin', 'mail', 'extension', 'dev', 'backup', 'action', 'cron', 'issue', 'risk', 'pssp', 'sms', 'message', 'webhook', 'search');
$lang->haveMenuMethod = array('custom');
+1
View File
@@ -2213,6 +2213,7 @@ EOD;
{
$lang->product->menu = $lang->cmmiproduct->menu;
$lang->productplan->menu = $lang->cmmiproduct->menu;
$lang->story->menu = $lang->cmmiproduct->menu;
$lang->$moduleName->menu = self::processMenuVars($lang->$moduleName->menu);
}
}
+79 -34
View File
@@ -1,35 +1,47 @@
<div class='cell table-row chart-row'>
<div class='chart-wrapper text-center'>
<h4><?php echo $lang->milestone->chart->title;?></h4>
<div class='chart-canvas'><canvas id='chart-line' width='500' height='140' data-responsive='true'></canvas></div>
<div class='milestone-chart' id='milestoneChart'>
<div class='chart-canvas scrollbar-hover'>
<div class='chart-wrapper'>
<canvas width='400' height='120' data-responsive='true'></canvas>
</div>
</div>
<div id="chartUnit"><?php echo "({$lang->project->workHour})";?></div>
<div id="chartLegend">
<div class="line-pv"><div class='barline bg-primary'></div>PV</div>
<div class="line-ev"><div class='barline'></div>EV</div>
<div class="line-ac"><div class='barline'></div>AC</div>
<div class='chart-unit'><?php echo "({$lang->project->workHour})";?></div>
<div class='chart-legend'>
<span class="barline line-pv">PV</span>
<span class="barline line-ev">EV</span>
<span class="barline line-ac">AC</span>
</div>
</div>
<style>
.milestone-chart {position: relative}
.milestone-chart .chart-canvas {overflow: auto; max-width: 1002px}
.milestone-chart .chart-wrapper {background: none; padding: 15px 0 0 0}
.milestone-chart .chart-unit {position: absolute; left: 10px; top: 0;}
.milestone-chart .chart-legend {position: absolute; right: 5px; top: 0;}
.milestone-chart .barline {padding-left: 20px; position: relative; display: inline-block; line-height: 20px}
.milestone-chart .barline + .barline {margin-left: 5px}
.milestone-chart .barline:before {content: ' '; display: block; position: absolute; top: 8px; left: 0; width: 16px; height: 3px; background: #0c64eb}
.milestone-chart .barline.line-ev:before {background: rgb(0, 218, 136)}
.milestone-chart .barline.line-ac:before {background: rgb(255, 145, 0)}
</style>
<script>
function initChar()
function initMilestoneChart()
{
var themePrimaryColor = $.getThemeColor('primary');
var data =
{
labels: <?php echo json_encode($charts['labels'])?>,
datasets: [
{
label: "PV",
color: themePrimaryColor,
pointColor: themePrimaryColor,
pointStrokeColor: themePrimaryColor,
pointHighlightStroke: themePrimaryColor,
label: 'PV',
color: '#0c64eb',
pointColor: '#0c64eb',
pointStrokeColor: '#0c64eb',
pointHighlightStroke: '#0c64eb',
fillColor: 'rgba(0,106,241, .07)',
pointHighlightFill: '#fff',
data: <?php echo $charts['PV']?>
},
{
label: "EV",
label: 'EV',
color: 'rgb(0, 218, 136)',
pointColor: 'rgb(0, 218, 136)',
pointStrokeColor: 'rgb(0, 218, 136)',
@@ -39,7 +51,7 @@ function initChar()
data: <?php echo $charts['EV']?>
},
{
label: "AC",
label: 'AC',
color: 'rgb(255, 145, 0)',
pointColor: 'rgb(255, 145, 0)',
pointStrokeColor: 'rgb(255, 145, 0)',
@@ -50,22 +62,55 @@ function initChar()
}]
};
var chartLine= $("#chart-line").lineChart(data,
var betterWidth = data.labels.length * 15;
var renderChart = function()
{
pointDotStrokeWidth: 2,
pointDotRadius: 3,
datasetStrokeWidth: 3,
datasetFill: true,
datasetStroke: true,
scaleShowBeyondLine: false,
responsive: true,
bezierCurve: false,
scaleFontColor: '#838A9D',
tooltipXPadding: 10,
tooltipYPadding: 10,
multiTooltipTitleTemplate: '<%= label %> <?php echo $lang->project->workHour;?> /h',
multiTooltipTemplate: "<%if (datasetLabel){%><%=datasetLabel%>: <%}%><%= value %>",
});
var $chart = $('#milestoneChart');
var $wrapper = $chart.find('.chart-wrapper');
var $canvas = $chart.find('canvas');
var $chartCanvas = $chart.find('.chart-canvas');
if (betterWidth > 400)
{
var updateWrapperSize = function()
{
$wrapper.hide();
$chartCanvas.css('max-width', 'initial');
var maxWidth = $chartCanvas.width();
$chartCanvas.css('max-width', maxWidth);
$chart.toggleClass('has-scrollbar', maxWidth < betterWidth);
$wrapper.show();
};
updateWrapperSize();
$(window).on('resize', updateWrapperSize);
$wrapper.css('min-width', betterWidth);
$canvas.attr(
{
width: betterWidth,
height: Math.min(200, Math.floor(betterWidth / 4))
});
}
$canvas.lineChart(data,
{
animation: betterWidth < 400,
pointDotStrokeWidth: 1,
pointDotRadius: 2,
datasetStrokeWidth: 2,
datasetFill: false,
datasetStroke: true,
scaleShowBeyondLine: true,
responsive: true,
bezierCurve: false,
scaleFontColor: '#838A9D',
tooltipXPadding: 10,
tooltipYPadding: 10,
multiTooltipTitleTemplate: '<%= label %> <?php echo $lang->project->workHour;?> /h',
multiTooltipTemplate: '<%if (datasetLabel){%><%=datasetLabel%>: <%}%><%= value %>',
});
}
if(betterWidth > 200) setTimeout(renderChart, 100);
else renderChart();
}
initChar();
initMilestoneChart();
</script>
+1 -1
View File
@@ -11,7 +11,7 @@ table .btn.addItem, table .btn.delItem{padding: 3px 8px; font-size: 12px; line-h
<div class="main-table">
<?php include 'basicinfo.html.php';?>
<?php include 'process.html.php';?>
<?php include 'chart.html.php';?>
<div class="cell"><?php include 'chart.html.php';?></div>
<?php include 'productquality.html.php';?>
<?php include 'workhour.html.php';?>
<?php include 'progress.html.php';?>
+1 -1
View File
@@ -43,7 +43,7 @@
<tr class='text-center'>
<td><?php echo $program->id;?></td>
<td class='text-left'><?php echo $program->code;?></td>
<td class='text-left'><?php echo html::a($this->createLink('program', 'index', "programID=$program->id"), $program->name);?></td>
<td class='text-left'><?php echo html::a($this->createLink('program', 'index', "programID=$program->id", '', '', $program->id), $program->name);?></td>
<td><?php echo $program->begin;?></td>
<td><?php echo $program->end;?></td>
<td class="c-status">
+3
View File
@@ -1,5 +1,8 @@
$(function()
{
$('#subNavbar .nav li').removeClass('active');
$("#subNavbar .nav li[data-id=" + storyType + ']').addClass('active');
if($('#storyList thead th.c-title').width() < 150) $('#storyList thead th.c-title').width(150);
$('#storyList td.has-child .story-toggle').each(function()
{
+7 -5
View File
@@ -23,6 +23,8 @@ $config->product->browse->unfoldID = zget($config->product->browse->unfoldID, $p
js::set('unfoldID', $config->product->browse->unfoldID);
js::set('unfoldAll', $lang->project->treeLevel['all']);
js::set('foldAll', $lang->project->treeLevel['root']);
js::set('storyType', $storyType);
$lang->story->create = $storyType == 'story' ? $lang->story->createStory : $lang->story->createRequirement;
?>
<div id="mainMenu" class="clearfix">
<div id="sidebarHeader">
@@ -95,7 +97,7 @@ js::set('foldAll', $lang->project->treeLevel['root']);
</ul>
</div>
<?php if(!common::checkNotCN()):?>
<?php if(common::hasPriv('story', 'batchCreate')) echo html::a($this->createLink('story', 'batchCreate', "productID=$productID&branch=$branch&moduleID=$moduleID"), "<i class='icon icon-plus'></i> {$lang->story->batchCreate}", '', "class='btn btn btn-secondary'");?>
<?php if(common::hasPriv('story', 'batchCreate')) echo html::a($this->createLink('story', 'batchCreate', "productID=$productID&branch=$branch&moduleID=$moduleID&storyID=0&project=0&plan=0&type=$storyType"), "<i class='icon icon-plus'></i> {$lang->story->batchCreate}", '', "class='btn btn btn-secondary'");?>
<?php
if(commonModel::isTutorialMode())
{
@@ -105,7 +107,7 @@ js::set('foldAll', $lang->project->treeLevel['root']);
}
else
{
$link = $this->createLink('story', 'create', "productID=$productID&branch=$branch&moduleID=$moduleID");
$link = $this->createLink('story', 'create', "productID=$productID&branch=$branch&moduleID=$moduleID&storyID=0&projectID=0&bugID=0&planID=0&todoID=0&extra=&type=$storyType");
if(common::hasPriv('story', 'create')) echo html::a($link, "<i class='icon icon-plus'></i> {$lang->story->create}", '', "class='btn btn-primary'");
}
?>
@@ -120,7 +122,7 @@ js::set('foldAll', $lang->project->treeLevel['root']);
}
else
{
$link = $this->createLink('story', 'create', "product=$productID&branch=$branch&moduleID=$moduleID");
$link = $this->createLink('story', 'create', "product=$productID&branch=$branch&moduleID=$moduleID&storyID=0&projectID=0&bugID=0&planID=0&todoID=0&extra=&type=$storyType");
$disabled = '';
if(!common::hasPriv('story', 'create'))
{
@@ -134,7 +136,7 @@ js::set('foldAll', $lang->project->treeLevel['root']);
<?php $disabled = common::hasPriv('story', 'batchCreate') ? '' : "class='disabled'";?>
<li <?php echo $disabled?>>
<?php
$batchLink = $this->createLink('story', 'batchCreate', "productID=$productID&branch=$branch&moduleID=$moduleID");
$batchLink = $this->createLink('story', 'batchCreate', "productID=$productID&branch=$branch&moduleID=$moduleID&storyID=0&project=0&plan=0&type=$storyType");
echo "<li>" . html::a($batchLink, "<i class='icon icon-plus'></i>" . $lang->story->batchCreate) . "</li>";
?>
</li>
@@ -168,7 +170,7 @@ js::set('foldAll', $lang->project->treeLevel['root']);
<p>
<span class="text-muted"><?php echo $lang->story->noStory;?></span>
<?php if(common::hasPriv('story', 'create')):?>
<?php echo html::a($this->createLink('story', 'create', "productID={$productID}&branch={$branch}&moduleID={$moduleID}"), "<i class='icon icon-plus'></i> " . $lang->story->create, '', "class='btn btn-info'");?>
<?php echo html::a($this->createLink('story', 'create', "productID={$productID}&branch={$branch}&moduleID={$moduleID}&storyID=0&projectID=0&bugID=0&planID=0&todoID=0&extra=&type=$storyType"), "<i class='icon icon-plus'></i> " . $lang->story->create, '', "class='btn btn-info'");?>
<?php endif;?>
</p>
</div>
+5
View File
@@ -11,3 +11,8 @@ $config->program->editor->suspend = array('id' => 'comment', 'tools' => 'simple
$config->program->list = new stdclass();
$config->program->list->exportFields = 'id,name,code,template,category,status,begin,end,budget,PM,end,desc';
$config->program->create = new stdclass();
$config->program->edit = new stdclass();
$config->program->create->requiredFields = 'name,code,begin,end';
$config->program->edit->requiredFields = 'name,code,begin,end';
+16 -11
View File
@@ -44,6 +44,8 @@ class program extends control
{
if(common::hasPriv('program', 'createGuide')) $this->lang->pageActions = html::a($this->createLink('program', 'createGuide'), "<i class='icon icon-sm icon-plus'></i> " . $this->lang->program->create, '', "class='btn btn-primary' data-toggle=modal");
$this->app->session->set('programList', $this->app->getURI(true));
$programType = $this->cookie->programType ? $this->cookie->programType : 'bylist';
$this->app->loadClass('pager', $static = true);
@@ -151,30 +153,33 @@ class program extends control
/**
* Edit a program.
*
* @param int $projectID
* @param int $programID
* @access public
* @return void
*/
public function edit($projectID = 0)
public function edit($programID = 0)
{
$project = $this->project->getByID($projectID);
$program = $this->project->getByID($programID);
if($_POST)
{
$changes = $this->project->update($projectID);
$changes = $this->program->update($programID);
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => $this->processErrors(dao::getError())));
if($changes)
{
$actionID = $this->loadModel('action')->create('project', $projectID, 'edited');
$actionID = $this->loadModel('action')->create('program', $programID, 'edited');
$this->action->logHistory($actionID, $changes);
}
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
$url = $this->session->programList ? $this->session->programList : inlink('browse');
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $url));
}
$this->view->pmUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst', $project->PM);
$this->view->title = $this->lang->project->edit;
$this->view->position[] = $this->lang->project->edit;
$this->view->project = $project;
$this->view->pmUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst', $program->PM);
$this->view->title = $this->lang->program->edit;
$this->view->position[] = $this->lang->program->edit;
$this->view->program = $program;
$this->view->parents = $this->program->getParentPairs();
$this->view->groups = $this->loadModel('group')->getPairs();
$this->display();
}
@@ -689,7 +694,7 @@ class program extends control
public function ajaxGetDropMenu($programID, $module, $method, $extra)
{
$this->loadModel('project');
$this->view->link = $this->createLink('program', 'index', "programID=$programID");
$this->view->link = $this->createLink('program', 'index', "programID=$programID", '', '', $programID);
$this->view->programID = $programID;
$this->view->module = $module;
$this->view->method = $method;
+2
View File
@@ -103,3 +103,5 @@ $lang->program->cmmiDesc = '<strong>简介:</strong>按阶段规范
$lang->program->cannotCreateChild = '该项目已经有实际的内容,无法直接添加子项目。您可以为当前项目创建一个父项目,然后在新的父项目下面添加子项目。';
$lang->program->hasChildren = '该项目有子项目存在,不能删除。';
$lang->program->confirmDelete = "您确定删除项目[%s]吗?";
$lang->program->cannotChangeToCat = "该项目已经有实际的内容,无法修改为父项目";
$lang->program->cannotCancelCat = "该项目下已经有子项目,无法取消父项目标记";
+236 -20
View File
@@ -1,6 +1,15 @@
<?php
class programModel extends model
{
/**
* Get program list.
*
* @param varchar $status
* @param varchar $orderBy
* @param object $pager
* @access public
* @return void
*/
public function getList($status = 'all', $orderBy = 'id_desc', $pager = NULL)
{
return $this->dao->select('*')->from(TABLE_PROJECT)
@@ -20,6 +29,12 @@ class programModel extends model
->fetchAll('id');
}
/**
* Get program pairs.
*
* @access public
* @return void
*/
public function getPairs()
{
return $this->dao->select('id, name')->from(TABLE_PROJECT)
@@ -30,6 +45,13 @@ class programModel extends model
->fetchPairs();
}
/**
* Get program pairs by template.
*
* @param varchar $template
* @access public
* @return void
*/
public function getPairsByTemplate($template)
{
return $this->dao->select('id, name')->from(TABLE_PROJECT)
@@ -41,6 +63,15 @@ class programModel extends model
->fetchPairs();
}
/**
* Get user programs for block.
*
* @param varchar $status
* @param varchar $orderBy
* @param int $limit
* @access public
* @return void
*/
public function getUserPrograms($status = 'all', $orderBy = 'id_desc', $limit = 15)
{
$programs = $this->dao->select('*')->from(TABLE_PROJECT)
@@ -57,7 +88,7 @@ class programModel extends model
if(empty($programs)) return array();
$programIdList = array_keys($programs);
$consumes = $this->dao->select('program, sum(consumed) as consumed')->from(TABLE_TASK)
$hours = $this->dao->select('program, sum(consumed) as consumed, sum(estimate) as estimate')->from(TABLE_TASK)
->where('program')->in($programIdList)
->andWhere('deleted')->eq(0)
->andWhere('parent')->lt(1)
@@ -76,6 +107,21 @@ class programModel extends model
->groupBy('program')
->fetchAll('program');
$allStories = $this->dao->select('program, count(*) as allStories')->from(TABLE_STORY)
->where('program')->in($programIdList)
->andWhere('deleted')->eq(0)
->andWhere('status')->ne('draft')
->groupBy('program')
->fetchAll('program');
$doneStories = $this->dao->select('program, count(*) as doneStories')->from(TABLE_STORY)
->where('program')->in($programIdList)
->andWhere('deleted')->eq(0)
->andWhere('status')->eq('closed')
->andWhere('closedReason')->eq('done')
->groupBy('program')
->fetchAll('program');
$leftStories = $this->dao->select('program, count(*) as leftStories')->from(TABLE_STORY)
->where('program')->in($programIdList)
->andWhere('deleted')->eq(0)
@@ -93,10 +139,13 @@ class programModel extends model
foreach($programs as $programID => $program)
{
$program->teamCount = isset($teams[$programID]) ? $teams[$programID]->count : 0;
$program->consumed = isset($consumes[$programID]) ? $consumes[$programID] : 0;
$program->leftTasks = isset($leftTasks[$programID]) ? $leftTasks[$programID] : 0;
$program->leftStories = isset($leftStories[$programID]) ? $leftStories[$programID] : 0;
$program->leftBugs = isset($leftBugs[$programID]) ? $leftBugs[$programID] : 0;
$program->consumed = isset($hours[$programID]) ? $hours[$programID]->consumed : 0;
$program->estimate = isset($hours[$programID]) ? $hours[$programID]->estimate : 0;
$program->leftTasks = isset($leftTasks[$programID]) ? $leftTasks[$programID]->leftTasks : 0;
$program->allStories = isset($allStories[$programID]) ? $allStories[$programID]->allStories : 0;
$program->doneStories = isset($doneStories[$programID]) ? $doneStories[$programID]->doneStories : 0;
$program->leftStories = isset($leftStories[$programID]) ? $leftStories[$programID]->leftStories : 0;
$program->leftBugs = isset($leftBugs[$programID]) ? $leftBugs[$programID]->leftBugs : 0;
}
return $programs;
@@ -166,9 +215,14 @@ class programModel extends model
die(js::locate('back'));
}
/**
* Create a program.
*
* @access private
* @return void
*/
public function create()
{
$this->lang->project->team = $this->lang->project->teamname;
$project = fixer::input('post')
->setDefault('status', 'wait')
->add('type', 'program')
@@ -178,14 +232,14 @@ class programModel extends model
->setDefault('team', substr($this->post->name,0, 30))
->join('whitelist', ',')
->cleanInt('budget')
->stripTags($this->config->project->editor->create['id'], $this->config->allowedTags)
->stripTags($this->config->program->editor->create['id'], $this->config->allowedTags)
->remove('products, workDays, delta, branch, uid, plans')
->get();
$project = $this->loadModel('file')->processImgURL($project, $this->config->project->editor->create['id'], $this->post->uid);
$project = $this->loadModel('file')->processImgURL($project, $this->config->program->editor->create['id'], $this->post->uid);
$this->dao->insert(TABLE_PROJECT)->data($project)
->autoCheck()
->batchcheck($this->config->project->create->requiredFields, 'notempty')
->batchcheck($this->config->program->create->requiredFields, 'notempty')
->check('name', 'unique', "deleted='0'")
->check('code', 'unique', "deleted='0'")
->exec();
@@ -249,6 +303,72 @@ class programModel extends model
}
}
/**
* Update program.
*
* @param int $programID
* @access public
* @return array
*/
public function update($programID)
{
$programID = (int)$programID;
$oldProgram = $this->dao->findById($programID)->from(TABLE_PROJECT)->fetch();
$program = fixer::input('post')
->setIF($this->post->begin == '0000-00-00', 'begin', '')
->setIF($this->post->end == '0000-00-00', 'end', '')
->setIF($this->post->acl != 'custom', 'whitelist', '')
->setIF($this->post->acl == 'custom' and !isset($_POST['whitelist']), 'whitelist', '')
->setDefault('team', $this->post->name)
->join('whitelist', ',')
->stripTags($this->config->program->editor->edit['id'], $this->config->allowedTags)
->remove('products, branch, uid, plans')
->get();
$program = $this->loadModel('file')->processImgURL($program, $this->config->program->editor->edit['id'], $this->post->uid);
if(!empty($program->isCat) and $this->checkHasContent($programID)) dao::$errors['isCat'] = $this->lang->program->cannotChangeToCat;
if(empty($program->isCat) and $this->checkHasChildren($programID)) dao::$errors['isCat'] = $this->lang->program->cannotCancelCat;
if(dao::isError()) return false;
$this->dao->update(TABLE_PROJECT)->data($program)
->autoCheck($skipFields = 'begin,end')
->batchcheck($this->config->program->edit->requiredFields, 'notempty')
->checkIF($program->begin != '', 'begin', 'date')
->checkIF($program->end != '', 'end', 'date')
->checkIF($program->end != '', 'end', 'gt', $program->begin)
->check('name', 'unique', "id!=$programID and deleted='0'")
->check('code', 'unique', "id!=$programID and deleted='0'")
->where('id')->eq($programID)
->limit(1)
->exec();
if(!dao::isError())
{
$this->file->updateObjectID($this->post->uid, $programID, 'project');
if($program->acl != 'open' and ($program->acl != $oldProject->acl or $program->whitelist != $oldProgram->whitelist))
{
$this->loadModel('user')->updateUserView($programID, 'program');
}
if($oldProgram->parent != $program->parent) $this->moveNode($programID, $program->parent, $oldProgram->path, $oldProgram->grade);
return common::createChanges($oldProgram, $program);
}
}
/*
* Get program swapper.
*
* @param object $programs
* @param int $programID
* @param varchar $currentModule
* @param varchar $currentMethod
* @param varchar $extra
* @access private
* @return void
*/
public function getSwapper($programs, $programID, $currentModule, $currentMethod, $extra = '')
{
$this->loadModel('project');
@@ -270,24 +390,36 @@ class programModel extends model
return $output;
}
public static function isClickable($project, $action)
/**
* Judge an action is clickable or not.
*
* @param object $project
* @param string $action
* @access public
* @return bool
*/
public static function isClickable($program, $action)
{
$action = strtolower($action);
if($action == 'start') return $project->status == 'wait' or $project->status == 'suspended';
if($action == 'finish') return $project->status == 'wait' or $project->status == 'doing';
if($action == 'close') return $project->status != 'closed';
if($action == 'suspend') return $project->status == 'wait' or $project->status == 'doing';
if($action == 'activate') return $project->status == 'done';
if(empty($program)) return true;
if($action == 'start') return $program->status == 'wait' or $program->status == 'suspended';
if($action == 'finish') return $program->status == 'wait' or $program->status == 'doing';
if($action == 'close') return $program->status != 'closed';
if($action == 'suspend') return $program->status == 'wait' or $program->status == 'doing';
if($action == 'activate') return $program->status == 'done';
return true;
}
public function getProducts($program)
{
return $this->dao->select('*')->from(TABLE_PRODUCT)->where('project')->eq($program)->fetchAll('id');
}
/**
* Check has content for program
*
* @param int $programID
* @access public
* @return bool
*/
public function checkHasContent($programID)
{
$count = 0;
@@ -312,6 +444,26 @@ class programModel extends model
return $count > 0;
}
/**
* Check has children project.
*
* @param int $programID
* @access public
* @return bool
*/
public function checkHasChildren($programID)
{
$count = $this->dao->select('count(*) as count')->from(TABLE_PROJECT)->where('parent')->eq($programID)->fetch('count');
return $count > 0;
}
/**
* Set program tree path.
*
* @param int $programID
* @access public
* @return bool
*/
public function setTreePath($programID)
{
$program = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($programID)->fetch();
@@ -327,5 +479,69 @@ class programModel extends model
$path['grade'] = $parent->grade + 1;
}
$this->dao->update(TABLE_PROJECT)->set('path')->eq($path['path'])->set('grade')->eq($path['grade'])->where('id')->eq($program->id)->exec();
return !dao::isError();
}
/**
* Get program parent pairs
*
* @access public
* @return array
*/
public function getParentPairs()
{
$stmt = $this->dao->select('id,name,parent,path,grade')->from(TABLE_PROJECT)->where('isCat')->eq(1)->andWhere('deleted')->eq(0)->orderBy('grade, `order`')->query();
$pairs = array();
$pairs[0] = '/';
while($program = $stmt->fetch())
{
if($program->grade == 1)
{
$pairs[$program->id] = '/' . $program->name;
continue;
}
$programName = '/' . $program->name;
$pairs[$program->id] = isset($pairs[$program->parent]) ? $pairs[$program->parent] . $programName : $programName;
}
return $pairs;
}
/**
* Move project node.
*
* @param int $programID
* @param int $parentID
* @param string $oldPath
* @param int $oldGrade
* @access public
* @return bool
*/
public function moveNode($programID, $parentID, $oldPath, $oldGrade)
{
$parent = $this->dao->select('id,parent,path,grade')->from(TABLE_PROJECT)->where('id')->eq($parentID)->fetch();
$childNodes = $this->dao->select('id,parent,path,grade')->from(TABLE_PROJECT)
->where('path')->like("{$oldPath}%")
->andWhere('deleted')->eq(0)
->andWhere('template')->ne('')
->orderBy('grade')
->fetchAll();
/* Process child node path and grade field. */
foreach($childNodes as $childNode)
{
$path = substr($childNode->path, strpos($childNode->path, ",{$programID},"));
$grade = $oldGrade - $childNode->grade + 1;
if($parent)
{
$path = rtrim($parent->path, ',') . $path;
$grade = $parent->grade + $grade;
}
$this->dao->update(TABLE_PROJECT)->set('path')->eq($path)->set('grade')->eq($grade)->where('id')->eq($childNode->id)->exec();
}
return !dao::isError();
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
<div class='row cell' id='cards'>
<?php foreach ($programs as $programID => $program):?>
<div class='col' data-id='<?php echo $programID?>'>
<div class='panel' data-url='<?php echo $this->createLink('program', 'index', "programID=$program->id");?>'>
<div class='panel' data-url='<?php echo $this->createLink('program', 'index', "programID=$program->id", '', '', $program->id);?>'>
<div class='panel-heading'>
<strong class='program-name' title='<?php echo $program->name;?>'><?php echo $program->name;?></strong>
<?php if($program->template === 'cmmi'): ?>
+1 -1
View File
@@ -28,7 +28,7 @@
</td>
<td class='text-left'><?php echo $program->code;?></td>
<td class='text-left pgm-title' title='<?php echo $program->name?>'>
<?php echo html::a(inlink('index', "programID=$program->id"), $program->name);?>
<?php echo html::a($this->createLink('program', 'index', "programID=$program->id", '', '', $program->id), $program->name);?>
</td>
<td class='c-status'><span class="status-program status-<?php echo $program->status?>"><?php echo zget($lang->project->statusList, $program->status, '');?></span></td>
<td class='text-center'><?php echo $program->begin;?></td>
+33 -23
View File
@@ -1,11 +1,11 @@
<?php
/**
* The create view of project module of ZenTaoPMS.
* The edit view of program module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package project
* @package program
* @version $Id: create.html.php 4728 2013-05-03 06:14:34Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
@@ -21,46 +21,56 @@
<form class='form-indicator main-form form-ajax' method='post' target='hiddenwin' id='dataform'>
<table class='table table-form'>
<tr>
<th class='w-120px'><?php echo $lang->program->name;?></th>
<td class="col-main"><?php echo html::input('name', $project->name, "class='form-control' required");?></td>
<th class='w-120px'><?php echo $lang->program->parent;?></th>
<td class="col-main"><?php echo html::select('parent', $parents, $program->parent, "class='form-control chosen'");?></td>
<td></td><td></td>
</tr>
<tr>
<th><?php echo $lang->program->code;?></th>
<td><?php echo html::input('code', $project->code, "class='form-control' required");?></td><td></td><td></td>
<th class='w-120px'><?php echo $lang->program->name;?></th>
<td class="col-main"><?php echo html::input('name', $program->name, "class='form-control' required");?></td>
<td>
<div class="checkbox-primary">
<input type="checkbox" name="isCat" value="1" id="isCat" <?php if($program->isCat) echo "checked";?>>
<label for="isCat"><?php echo $lang->program->parent;?></label>
</div>
</td><td></td>
</tr>
<?php if($project->template == 'cmmi'):?>
<tr>
<th><?php echo $lang->program->code;?></th>
<td><?php echo html::input('code', $program->code, "class='form-control' required");?></td><td></td><td></td>
</tr>
<?php if($program->template == 'cmmi'):?>
<tr>
<th><?php echo $lang->program->category;?></th>
<td><?php echo html::select('category', $lang->program->categoryList, $project->category, "class='form-control'");?></td><td></td><td></td>
<td><?php echo html::select('category', $lang->program->categoryList, $program->category, "class='form-control'");?></td><td></td><td></td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->program->PM;?></th>
<td><?php echo html::select('PM', $pmUsers, $project->PM, "class='form-control chosen'");?></td>
<td><?php echo html::select('PM', $pmUsers, $program->PM, "class='form-control chosen'");?></td>
</tr>
<tr>
<th><?php echo $lang->program->budget;?></th>
<td><?php echo html::input('budget', $project->budget, "class='form-control'");?></td>
<td style='float:left'><?php echo html::select('budgetUnit', $lang->program->unitList, $project->budgetUnit, "class='form-control'");?></td><td></td>
<td><?php echo html::input('budget', $program->budget, "class='form-control'");?></td>
<td style='float:left'><?php echo html::select('budgetUnit', $lang->program->unitList, $program->budgetUnit, "class='form-control'");?></td><td></td>
</tr>
<tr>
<th><?php echo $lang->program->dateRange;?></th>
<td>
<div class='input-group'>
<?php echo html::input('begin', $project->begin, "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->program->begin . "' required");?>
<?php echo html::input('begin', $program->begin, "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->program->begin . "' required");?>
<span class='input-group-addon'><?php echo $lang->program->to;?></span>
<?php echo html::input('end', $project->end, "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->program->end . "' required");?>
<?php echo html::input('end', $program->end, "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->program->end . "' required");?>
</div>
</td>
<td colspan='2'></td>
</tr>
<?php if($project->template == 'scrum'):?>
<?php if($program->template == 'scrum'):?>
<tr>
<th><?php echo $lang->project->days;?></th>
<td>
<div class='input-group'>
<?php echo html::input('days', $project->days, "class='form-control'");?>
<?php echo html::input('days', $program->days, "class='form-control'");?>
<span class='input-group-addon'><?php echo $lang->project->day;?></span>
</div>
</td><td></td><td></td>
@@ -68,30 +78,30 @@
<?php endif;?>
<tr>
<th><?php echo $lang->program->realStarted;?></th>
<td><?php echo html::input('realStarted', $project->realStarted, "class='form-control form-date'");?></td><td></td><td></td>
<td><?php echo html::input('realStarted', $program->realStarted, "class='form-control form-date'");?></td><td></td><td></td>
</tr>
<tr>
<th><?php echo $lang->project->teamname;?></th>
<td><?php echo html::input('team', $project->team, "class='form-control'");?></td><td></td><td></td>
<td><?php echo html::input('team', $program->team, "class='form-control'");?></td><td></td><td></td>
</tr>
<tr>
<th><?php echo $lang->program->desc;?></th>
<td colspan='3'>
<?php echo $this->fetch('user', 'ajaxPrintTemplates', 'type=project&link=desc');?>
<?php echo html::textarea('desc', $project->desc, "rows='6' class='form-control kindeditor' hidefocus='true'");?>
<?php echo $this->fetch('user', 'ajaxPrintTemplates', 'type=program&link=desc');?>
<?php echo html::textarea('desc', $program->desc, "rows='6' class='form-control kindeditor' hidefocus='true'");?>
</td>
</tr>
<tr>
<th><?php echo $lang->program->privway;?></th>
<td colspan='3'><?php echo html::radio('privway', $lang->program->privwayList, $project->privway, '', 'block');?></td>
<td colspan='3'><?php echo html::radio('privway', $lang->program->privwayList, $program->privway, '', 'block');?></td>
</tr>
<tr>
<th><?php echo $lang->project->acl;?></th>
<td colspan='3'><?php echo nl2br(html::radio('acl', $lang->program->aclList, $project->acl, "onclick='setWhite(this.value);'", 'block'));?></td>
<td colspan='3'><?php echo nl2br(html::radio('acl', $lang->program->aclList, $program->acl, "onclick='setWhite(this.value);'", 'block'));?></td>
</tr>
<tr id='whitelistBox' <?php if($project->acl != 'custom') echo "class='hidden'";?>>
<tr id='whitelistBox' <?php if($program->acl != 'custom') echo "class='hidden'";?>>
<th><?php echo $lang->project->whitelist;?></th>
<td colspan='3'><?php echo html::checkbox('whitelist', $groups, $project->whitelist, '', '', 'inline');?></td>
<td colspan='3'><?php echo html::checkbox('whitelist', $groups, $program->whitelist, '', '', 'inline');?></td>
</tr>
<tr>
<td colspan='4' class='text-center form-actions'>
+4 -2
View File
@@ -935,11 +935,12 @@ class project extends control
* @access public
* @return void
*/
public function burn($projectID = 0, $type = 'noweekend', $interval = 0)
public function burn($projectID = 0, $type = 'noweekend', $interval = 0, $burnBy = 'left')
{
$this->loadModel('report');
$project = $this->commonAction($projectID);
$projectID = $project->id;
$burnBy = $this->cookie->burnBy ? $this->cookie->burnBy : $burnBy;
/* Header and position. */
$title = $project->name . $this->lang->colon . $this->lang->project->burn;
@@ -949,7 +950,7 @@ class project extends control
/* Get date list. */
$projectInfo = $this->project->getByID($projectID);
list($dateList, $interval) = $this->project->getDateList($projectInfo->begin, $projectInfo->end, $type, $interval, 'Y-m-d');
$chartData = $this->project->buildBurnData($projectID, $dateList, $type);
$chartData = $this->project->buildBurnData($projectID, $dateList, $type, $burnBy);
$dayList = array_fill(1, floor($project->days / $this->config->project->maxBurnDay) + 5, '');
foreach($dayList as $key => $val) $dayList[$key] = $this->lang->project->interval . ($key + 1) . $this->lang->day;
@@ -958,6 +959,7 @@ class project extends control
$this->view->title = $title;
$this->view->position = $position;
$this->view->tabID = 'burn';
$this->view->burnBy = $burnBy;
$this->view->projectID = $projectID;
$this->view->projectName = $project->name;
$this->view->type = $type;
+2
View File
@@ -5,3 +5,5 @@
#burnLegend > div {position: relative; padding-left: 30px;}
#burnLegend > div > .barline {position: absolute; width: 20px; left: 0; top: 13px; height: 3px; background: #EEEEEE;}
#burnLegend .line-real .bg-primary{background: #1183fb}
.pull-left .input-control{margin-right: 10px}
+6
View File
@@ -117,6 +117,12 @@ $lang->project->aclList['open'] = "默认设置(有{$lang->projectCommon}视
$lang->project->aclList['private'] = "私有{$lang->projectCommon}(只有{$lang->projectCommon}团队成员才能访问)";
$lang->project->aclList['custom'] = "自定义白名单(团队成员和白名单的成员可以访问)";
$lang->project->storyPoint = '故事点';
$lang->project->burnByList['left'] = '按剩余工时查看';
$lang->project->burnByList['estimate'] = '按计划工时查看';
$lang->project->burnByList['storyPoint'] = '按故事点查看';
/* 方法列表。*/
$lang->project->index = "{$lang->projectCommon}主页";
$lang->project->task = '任务列表';
+33 -5
View File
@@ -1969,6 +1969,23 @@ class projectModel extends model
->andWhere('status')->eq('closed')
->groupBy('project')
->fetchAll('project');
$finishedEstimates = $this->dao->select("project, sum(`estimate`) AS `estimate`")->from(TABLE_TASK)
->where('project')->in(array_keys($projects))
->andWhere('deleted')->eq('0')
->andWhere('parent')->ge('0')
->andWhere('status')->eq('done')
->orWhere('status')->eq('closed')
->groupBy('project')
->fetchAll('project');
$storyPoints = $this->dao->select('t1.project, sum(t2.estimate) AS `storyPoint`')->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t2.product = t3.id')
->where('t1.project')->in(array_keys($projects))
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.status')->ne('closed')
->andWhere('t2.stage')->in('wait,planned,projected,developing')
->groupBy('project')
->fetchAll('project');
foreach($burns as $projectID => $burn)
{
@@ -1978,6 +1995,14 @@ class projectModel extends model
$burn->left -= (int)$closedLeft->left;
}
if(isset($finishedEstimates[$projectID]))
{
$finishedEstimate = $finishedEstimates[$projectID];
$burn->estimate -= (int)$finishedEstimate->estimate;
}
if(isset($storyPoints[$projectID])) $burn->storyPoint = $storyPoints[$projectID]->storyPoint;
$this->dao->replace(TABLE_BURN)->data($burn)->exec();
$burn->projectName = $projects[$burn->project];
}
@@ -2013,16 +2038,17 @@ class projectModel extends model
* Get burn data for flot
*
* @param int $projectID
* @param string $burnBy
* @access public
* @return array
*/
public function getBurnDataFlot($projectID = 0)
public function getBurnDataFlot($projectID = 0, $burnBy = '')
{
/* Get project and burn counts. */
$project = $this->getById($projectID);
/* If the burnCounts > $itemCounts, get the latest $itemCounts records. */
$sets = $this->dao->select('date AS name, `left` AS value, estimate')->from(TABLE_BURN)->where('project')->eq((int)$projectID)->andWhere('task')->eq(0)->orderBy('date DESC')->fetchAll('name');
$sets = $this->dao->select("date AS name, `$burnBy` AS value, `$burnBy`")->from(TABLE_BURN)->where('project')->eq((int)$projectID)->andWhere('task')->eq(0)->orderBy('date DESC')->fetchAll('name');
$count = 0;
$burnData = array();
@@ -2757,19 +2783,21 @@ class projectModel extends model
* @param int $projectID
* @param array $dateList
* @param string $type
* @param string $burnBy
* @access public
* @return array
*/
public function buildBurnData($projectID, $dateList, $type)
public function buildBurnData($projectID, $dateList, $type, $burnBy = 'left')
{
$this->loadModel('report');
$burnBy = $burnBy ? $burnBy : 'left';
$sets = $this->getBurnDataFlot($projectID);
$sets = $this->getBurnDataFlot($projectID, $burnBy);
$limitJSON = '[]';
$baselineJSON = '[]';
$firstBurn = empty($sets) ? 0 : reset($sets);
$firstTime = !empty($firstBurn->estimate) ? $firstBurn->estimate : (!empty($firstBurn->value) ? $firstBurn->value : 0);
$firstTime = !empty($firstBurn->$burnBy) ? $firstBurn->$burnBy : (!empty($firstBurn->value) ? $firstBurn->value : 0);
$days = count($dateList) - 1;
$rate = $firstTime / $days;
$baselineJSON = '[';
+12 -2
View File
@@ -26,6 +26,9 @@
common::printLink('project', 'fixFirst', "project=$project->id", $lang->project->fixFirst, '', "class='btn btn-link iframe' data-width='700'");
echo $lang->project->howToUpdateBurn;
?>
<div class='input-control w-150px'>
<?php echo html::select('burnBy', $lang->project->burnByList, $burnBy, "class='form-control chosen'");?>
</div>
<?php if($interval):?>
<div class='input-control thWidth'>
<?php echo html::select('interval', $dayList, $interval, "class='form-control chosen'");?>
@@ -37,12 +40,12 @@
</div>
</div>
<div id='mainContent' class='main-content'>
<h2 class='text-center'><?php echo $projectName . ' ' . $this->lang->project->burn;?></h2>
<h2 class='text-center'><?php echo $projectName . ' ' . $this->lang->project->burn . '(' . zget($lang->project->burnByList, $burnBy) . ')';?></h2>
<div id="burnWrapper">
<div id="burnChart">
<canvas id="burnCanvas"></canvas>
</div>
<div id="burnYUnit"><?php echo "({$lang->project->workHour})";?></div>
<div id="burnYUnit"><?php echo $burnBy == 'storyPoint' ? "({$lang->project->storyPoint})" : "({$lang->project->workHour})";?></div>
<div id="burnLegend">
<div class="line-ref"><div class='barline'></div><?php echo $lang->project->charts->burn->graph->reference;?></div>
<div class="line-real"><div class='barline bg-primary'></div><?php echo $lang->project->charts->burn->graph->actuality;?></div>
@@ -50,6 +53,13 @@
</div>
</div>
<script>
$('#burnBy').change(function()
{
$.cookie('burnBy', $(this).val(), {expires:config.cookieLife, path:config.webRoot});
var interval = typeof($('#interval').val()) == 'undefined' ? 0 : $('#interval').val() ;
location.href = createLink('project', 'burn', 'projectID=' + projectID + '&type=' + type + '&interval=' + interval + '&burnBy=' + $(this).val());
});
function initBurnChar()
{
var themePrimaryColor = $.getThemeColor('primary');
+2
View File
@@ -208,6 +208,8 @@ class riskModel extends model
{
return $this->dao->select('*')->from(TABLE_RISK)
->where('program')->eq($this->session->program)
->beginIF($browseType != 'all' and $browseType != 'assignTo')->andWhere('status')->eq($browseType)->fi()
->beginIF($browseType == 'assignTo')->andWhere('assignedTo')->eq($this->app->user->account)->fi()
->andWhere('deleted')->eq('0')
->orderBy($orderBy)
->limit($limit)
+7
View File
@@ -1,3 +1,10 @@
$(function()
{
if(typeof(storyType) == 'undefined') storyType = '';
$('#subNavbar .nav li').removeClass('active');
$("#subNavbar .nav li[data-id=" + storyType + ']').addClass('active');
})
function getStatus(method, params)
{
$.get(createLink('story', 'ajaxGetStatus', "method=" + method + '&params=' + params), function(status)
+45 -43
View File
@@ -9,49 +9,51 @@
* @version $Id: zh-cn.php 5141 2013-07-15 05:57:15Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
$lang->story->create = "提{$lang->storyCommon}";
$lang->story->batchCreate = "批量创建";
$lang->story->change = "变更";
$lang->story->changeAction = "变更{$lang->storyCommon}";
$lang->story->changed = "{$lang->storyCommon}变更";
$lang->story->assignTo = '指派';
$lang->story->assignAction = "指派{$lang->storyCommon}";
$lang->story->review = '评审';
$lang->story->reviewAction = "评审{$lang->storyCommon}";
$lang->story->needReview = '需要评审';
$lang->story->batchReview = '批量评审';
$lang->story->edit = "编辑";
$lang->story->batchEdit = "批量编辑";
$lang->story->subdivide = '细分';
$lang->story->subdivideAction = "细分{$lang->storyCommon}";
$lang->story->splitRequirent = '拆分';
$lang->story->close = '关闭';
$lang->story->closeAction = "关闭{$lang->storyCommon}";
$lang->story->batchClose = '批量关闭';
$lang->story->activate = '激活';
$lang->story->activateAction = "激活{$lang->storyCommon}";
$lang->story->delete = "删除";
$lang->story->deleteAction = "删除{$lang->storyCommon}";
$lang->story->view = "{$lang->storyCommon}详情";
$lang->story->setting = "设置";
$lang->story->tasks = "相关任务";
$lang->story->bugs = "相关Bug";
$lang->story->cases = "相关用例";
$lang->story->taskCount = '任务数';
$lang->story->bugCount = 'Bug数';
$lang->story->caseCount = '用例数';
$lang->story->taskCountAB = 'T';
$lang->story->bugCountAB = 'B';
$lang->story->caseCountAB = 'C';
$lang->story->linkStory = "关联{$lang->storyCommon}";
$lang->story->unlinkStory = "移除相关{$lang->storyCommon}";
$lang->story->export = "导出数据";
$lang->story->exportAction = "导出{$lang->storyCommon}";
$lang->story->zeroCase = "零用例{$lang->storyCommon}";
$lang->story->zeroTask = "只列零任务{$lang->storyCommon}";
$lang->story->reportChart = "统计报表";
$lang->story->reportAction = "统计报表";
$lang->story->copyTitle = "同{$lang->storyCommon}名称";
$lang->story->create = "提{$lang->storyCommon}";
$lang->story->createStory = '添加软需';
$lang->story->createRequirement = '添加用需';
$lang->story->batchCreate = "批量创建";
$lang->story->change = "变更";
$lang->story->changeAction = "变更{$lang->storyCommon}";
$lang->story->changed = "{$lang->storyCommon}变更";
$lang->story->assignTo = '指派';
$lang->story->assignAction = "指派{$lang->storyCommon}";
$lang->story->review = '评审';
$lang->story->reviewAction = "评审{$lang->storyCommon}";
$lang->story->needReview = '需要评审';
$lang->story->batchReview = '批量评审';
$lang->story->edit = "编辑";
$lang->story->batchEdit = "批量编辑";
$lang->story->subdivide = '细分';
$lang->story->subdivideAction = "细分{$lang->storyCommon}";
$lang->story->splitRequirent = '拆分';
$lang->story->close = '关闭';
$lang->story->closeAction = "关闭{$lang->storyCommon}";
$lang->story->batchClose = '批量关闭';
$lang->story->activate = '激活';
$lang->story->activateAction = "激活{$lang->storyCommon}";
$lang->story->delete = "删除";
$lang->story->deleteAction = "删除{$lang->storyCommon}";
$lang->story->view = "{$lang->storyCommon}详情";
$lang->story->setting = "设置";
$lang->story->tasks = "相关任务";
$lang->story->bugs = "相关Bug";
$lang->story->cases = "相关用例";
$lang->story->taskCount = '任务数';
$lang->story->bugCount = 'Bug数';
$lang->story->caseCount = '用例数';
$lang->story->taskCountAB = 'T';
$lang->story->bugCountAB = 'B';
$lang->story->caseCountAB = 'C';
$lang->story->linkStory = "关联{$lang->storyCommon}";
$lang->story->unlinkStory = "移除相关{$lang->storyCommon}";
$lang->story->export = "导出数据";
$lang->story->exportAction = "导出{$lang->storyCommon}";
$lang->story->zeroCase = "零用例{$lang->storyCommon}";
$lang->story->zeroTask = "只列零任务{$lang->storyCommon}";
$lang->story->reportChart = "统计报表";
$lang->story->reportAction = "统计报表";
$lang->story->copyTitle = "同{$lang->storyCommon}名称";
$lang->story->batchChangePlan = "批量修改计划";
$lang->story->batchChangeBranch = "批量修改分支";
$lang->story->batchChangeStage = "批量修改阶段";
+51 -18
View File
@@ -993,29 +993,62 @@ class storyModel extends model
{
$now = helper::now();
$oldStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch();
if($oldStory->type == 'requirement')
{
foreach($stories as $id)
{
$data = new stdclass();
$data->product = $oldStory->product;
$data->AType = 'requirement';
$data->relation = 'subdivideinto';
$data->BType = 'story';
$data->AID = $storyID;
$data->BID = $id;
$data->AVersion = $oldStory->version;
$data->BVersion = 1;
$data->extra = 1;
/* Set parent to child story. */
$this->dao->update(TABLE_STORY)->set('parent')->eq($storyID)->where('id')->in($stories)->exec();
$this->computeEstimate($storyID);
$this->dao->insert(TABLE_RELATION)->data($data)->autoCheck()->exec();
/* Set childStories. */
$childStories = join(',', $stories);
$data->AType = 'story';
$data->relation = 'subdividedfrom';
$data->BType = 'requirement';
$data->AID = $id;
$data->BID = $storyID;
$data->AVersion = 1;
$data->BVersion = $oldStory->version;
$newStory = new stdClass();
$newStory->parent = '-1';
$newStory->plan = 0;
$newStory->lastEditedBy = $this->app->user->account;
$newStory->lastEditedDate = $now;
$newStory->childStories = trim($oldStory->childStories . ',' . $childStories, ',');
$this->dao->insert(TABLE_RELATION)->data($data)->autoCheck()->exec();
}
/* Subdivide story. */
$this->dao->update(TABLE_STORY)->data($newStory)->autoCheck()->where('id')->eq($storyID)->exec();
$changes = common::createChanges($oldStory, $newStory);
if($changes)
if(dao::isError()) die(js::error(dao::getError()));
die(js::locate(helper::createLink('product', 'browse', "productID=$oldStory->product&branch=0&browseType=unclosed&queryID=0&type=story"), 'parent.parent'));
}
else
{
$actionID = $this->loadModel('action')->create('story', $storyID, 'createChildrenStory', '', $childStories);
$this->action->logHistory($actionID, $changes);
/* Set parent to child story. */
$this->dao->update(TABLE_STORY)->set('parent')->eq($storyID)->where('id')->in($stories)->exec();
$this->computeEstimate($storyID);
/* Set childStories. */
$childStories = join(',', $stories);
$newStory = new stdClass();
$newStory->parent = '-1';
$newStory->plan = 0;
$newStory->lastEditedBy = $this->app->user->account;
$newStory->lastEditedDate = $now;
$newStory->childStories = trim($oldStory->childStories . ',' . $childStories, ',');
/* Subdivide story. */
$this->dao->update(TABLE_STORY)->data($newStory)->autoCheck()->where('id')->eq($storyID)->exec();
$changes = common::createChanges($oldStory, $newStory);
if($changes)
{
$actionID = $this->loadModel('action')->create('story', $storyID, 'createChildrenStory', '', $childStories);
$this->action->logHistory($actionID, $changes);
}
}
}
+16
View File
@@ -57,6 +57,7 @@
</div>
</td>
</tr>
<?php if($type == 'story'):?>
<tr>
<th class='planTh'><?php echo $lang->story->planAB;?></th>
<td colspan="2">
@@ -88,6 +89,7 @@
</td>
<?php endif;?>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->story->reviewedBy;?></th>
<td><?php echo html::select('assignedTo', $users, empty($needReview) ? $product->PO : '', "class='form-control chosen'");?></td>
@@ -99,6 +101,20 @@
</div>
</td>
<?php endif;?>
<?php if($type == 'requirement'):?>
<?php if(strpos(",$showFields,", ',source,') !== false):?>
<td colspan="2" class='sourceTd'>
<div class="input-group">
<div class="input-group">
<div class="input-group-addon"><?php echo $lang->story->source;?></div>
<?php echo html::select('source', $lang->story->sourceList, $source, "class='form-control chosen'");?>
<span class='input-group-addon'><?php echo $lang->story->sourceNote;?></span>
<?php echo html::input('sourceNote', $sourceNote, "class='form-control' style='width:140px;'");?>
</div>
</div>
</td>
<?php endif;?>
<?php endif;?>
</tr>
<tr>
<th><?php echo $lang->story->title;?></th>
+1
View File
@@ -3804,6 +3804,7 @@ class upgradeModel extends model
if(dao::isError()) return false;
$programID = $this->dao->lastInsertId();
$this->dao->update(TABLE_PROJECT)->set('grade')->eq(1)->set('path')->eq(",{$programID},")->where('id')->eq($programID)->exec();
if($pgmAdmins)
{
+2 -1
View File
@@ -17,8 +17,9 @@ class weekly extends control
$this->view->users = $this->loadModel('user')->getPairs('noletter');
}
public function index($program, $date = '')
public function index($program = 0, $date = '')
{
$program = $program ? $program : $this->session->program;
if(!$date) $date = helper::today();
$date = date('Y-m-d', strtotime($date));
+9 -9
View File
@@ -110,7 +110,7 @@ class weeklyModel extends model
if(!$date) $date = date('Y-m-d');
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $program);
$projectIdList = array_keys($projects);
return $this->dao->select('count(distinct t1.account) as count')
@@ -128,7 +128,7 @@ class weeklyModel extends model
$monday = $this->getThisMonday($date);
$sunday = $this->getThisSunday($date);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $program);
$projectIdList = array_keys($projects);
$tasks = $this->dao->select('*')
@@ -148,7 +148,7 @@ class weeklyModel extends model
$sunday = $this->getThisSunday($date);
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $program);
$projectIdList = array_keys($projects);
$unFinished = $this->dao->select('*')
->from(TABLE_TASK)
@@ -177,7 +177,7 @@ class weeklyModel extends model
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$sencondMondy = date('Y-m-d', strtotime("$sunday +8 days"));
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $program);
$projectIdList = array_keys($projects);
$tasks = $this->dao->select('*')
@@ -197,7 +197,7 @@ class weeklyModel extends model
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$sencondMondy = date('Y-m-d', strtotime("$sunday +8 days"));
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $program);
$projectIdList = array_keys($projects);
return $this->dao->select('type, sum(cast(estimate as decimal(10,2))) as workload')
@@ -213,7 +213,7 @@ class weeklyModel extends model
$monday = $this->getThisMonday($date);
$nextMonday = date('Y-m-d', strtotime("$monday +7 days"));
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $program);
$projectIdList = array_keys($projects);
return $this->dao->select('*')
@@ -237,7 +237,7 @@ class weeklyModel extends model
$nextMonday = date('Y-m-d', strtotime("$sunday +1 days"));
$workdays = $this->loadModel('holiday')->getActualWorkingDays($monday, $sunday);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program->id);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $program->id);
$projectIdList = array_keys($projects);
$tasks = $this->dao->select('*')->from(TABLE_TASK)
@@ -269,7 +269,7 @@ class weeklyModel extends model
$report = $this->getFromDB($program, $date);
if(!empty($report)) return $report->ev;
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $program);
$projectIdList = array_keys($projects);
if(!$date) $date = date('Y-m-d');
@@ -310,7 +310,7 @@ class weeklyModel extends model
$monday = $this->getThisMonday($date);
$nextMonday = date('Y-m-d', strtotime("$monday +7 days"));
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $type = 'project', $program);
$projects = $this->loadModel('project')->getList($status = 'all', $limit = 0, $productID = 0, $branch = 0, $program);
$projectIdList = array_keys($projects);
$AC = $this->dao->select('sum(t1.consumed) as consumed')
+2 -1
View File
@@ -11,8 +11,9 @@
*/
class workestimation extends control
{
public function index($program)
public function index($program = 0)
{
$program = $program ? $program : $this->session->program;
if($_POST)
{
$result = $this->workestimation->save($program);