Merge branch '20.x' of https://github.com/easysoft/zentaopms into 20.x
This commit is contained in:
@@ -1611,20 +1611,29 @@ class block extends control
|
||||
/**
|
||||
* Print srcum road map block.
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function printScrumroadmapBlock()
|
||||
public function printScrumroadmapBlock($productID = 0)
|
||||
{
|
||||
$this->session->set('releaseList', $this->app->getURI(true));
|
||||
$this->session->set('productPlanList', $this->app->getURI(true));
|
||||
$products = $this->loadModel('product')->getPairs();
|
||||
|
||||
ksort($products);
|
||||
$productID = key($products);
|
||||
$this->view->roadmaps = $this->product->getRoadmap($productID, 0, 6);
|
||||
$products = $this->loadModel('product')->getPairs();
|
||||
if(!is_numeric($productID)) $productID = key($products);
|
||||
|
||||
$this->view->roadmaps = $this->product->getRoadmap($productID, 0, 6);
|
||||
|
||||
$this->view->productID = $productID;
|
||||
$this->view->products = $products;
|
||||
$this->view->products = $products;
|
||||
$this->view->sync = 1;
|
||||
|
||||
if($_POST)
|
||||
{
|
||||
$this->view->sync = 0;
|
||||
$this->display('block', 'scrumroadmapblock');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -248,3 +248,21 @@ $(function()
|
||||
refreshBlock($(this).closest('.panel'));
|
||||
});
|
||||
});
|
||||
|
||||
function reloadRoadmap(productID)
|
||||
{
|
||||
$.ajax(
|
||||
{
|
||||
url: createLink('block', 'printScrumroadmapBlock', 'id=' + productID),
|
||||
dataType: "html",
|
||||
async: false,
|
||||
data: {id: productID},
|
||||
type: 'post',
|
||||
success: function(data)
|
||||
{
|
||||
$("#roadMap").html('');
|
||||
$("#roadMap").html(data);
|
||||
$("#createPlanLink").attr('href',createLink('productplan', 'create', 'id=' + productID) );
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -334,7 +334,6 @@ $lang->block->modules['scrum']['index']->availableBlocks->scrumlist = $lang-
|
||||
$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->productCommon . '路线图';
|
||||
|
||||
$lang->block->modules['cmmi']['index'] = new stdclass();
|
||||
$lang->block->modules['cmmi']['index']->availableBlocks = new stdclass();
|
||||
|
||||
@@ -10,19 +10,58 @@
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php if($sync === 1):?>
|
||||
<style>
|
||||
.release-line>li:nth-child(even)>a{height:92px;}
|
||||
.release-line>li:nth-child(odd){padding-top: 87px;}
|
||||
.release-line>li>a .title {overflow: hidden; width:150%; text-overflow: ellipsis;}
|
||||
#dashboard .panel-move-handler{right:78px}
|
||||
#productList{width:28%; position: absolute; top: 6px; left: 96px;}
|
||||
#productList{width:32%; position: absolute; top: 6px; left: 96px;}
|
||||
#createPlan{position: absolute; top: 3px; right:0px;}
|
||||
#createPlan a{padding: 0 5px;line-height: 24px;margin: 3px;color: #3C4353;}
|
||||
</style>
|
||||
<div class="panel-move-handler">
|
||||
<div id="productList"><?php echo html::select('productID', $products, '', 'class="form-control chosen"');?></div>
|
||||
<div id="createPlan"><?php echo html::a($this->createLink('productplan', 'create', 'productID=' . $productID), '<i class="icon icon-sm icon-plus"></i>'. $lang->productplan->create, '', 'class="btn btn-mini" id="createPlan"');?></div>
|
||||
<div id="productList"><?php echo html::select('productID', $products, '', 'class="form-control chosen" onchange="reloadRoadmap(this.options[this.options.selectedIndex].value)"');?></div>
|
||||
<div id="createPlan"><?php echo html::a($this->createLink('productplan', 'create', 'productID=' . $productID), '<i class="icon icon-sm icon-plus"></i>'. $lang->productplan->create, '', 'class="btn btn-mini" id="createPlanLink"');?></div>
|
||||
</div>
|
||||
<div class="panel-body conatiner-fluid">
|
||||
<div class="panel-body conatiner-fluid" id="roadMap">
|
||||
<?php if(empty($roadmaps)):?>
|
||||
<div class='empty-tip'><?php echo $lang->block->emptyTip;?></div>
|
||||
<?php else:?>
|
||||
<div class="release-path">
|
||||
<ul class="release-line">
|
||||
<?php foreach($roadmaps as $year => $mapBranches):?>
|
||||
<?php foreach($mapBranches as $plans):?>
|
||||
<?php foreach($plans as $plan):?>
|
||||
<?php if(isset($plan->begin)):?>
|
||||
<li <?php if(date('Y-m-d') < $plan->begin) echo 'class="active"';?>>
|
||||
<a href="<?php echo $this->createLink('productplan', 'view', "planID={$plan->id}");?>">
|
||||
<span class="title" title="<?php echo $plan->title;?>"><?php echo $plan->title;?></span>
|
||||
<span class="date" title="<?php echo $plan->begin;?>"><?php echo $plan->begin;?></span>
|
||||
<span class="date"><?php echo $lang->block->estimatedHours;?> <?php echo $plan->hour;?> h</span>
|
||||
</a>
|
||||
</li>
|
||||
<?php else:?>
|
||||
<li>
|
||||
<a href="<?php echo $this->createLink('release', 'view', "releaseID={$plan->id}");?>">
|
||||
<span class="title" title="<?php echo $plan->name . " ($plan->buildName)";?>"><?php echo $plan->name . "($plan->buildName)";?></span>
|
||||
<span class="date" title="<?php echo $plan->date;?>"><?php echo $plan->date;?></span>
|
||||
<?php $estimate = empty($plan->stories) ? 0 : $this->block->getStorysEstimateHours(explode(',', $plan->stories));?>
|
||||
<span class="date"><?php echo $lang->block->consumedHours;?> <?php echo empty($estimate) ? 0 : $estimate;?> h</span>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif;?>
|
||||
<?php endforeach;?>
|
||||
<?php endforeach;?>
|
||||
<?php endforeach;?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<?php if(empty($roadmaps)):?>
|
||||
<div class='empty-tip'><?php echo $lang->block->emptyTip;?></div>
|
||||
<?php else:?>
|
||||
<div class="release-path">
|
||||
<ul class="release-line">
|
||||
<?php foreach($roadmaps as $year => $mapBranches):?>
|
||||
@@ -51,4 +90,5 @@
|
||||
<?php endforeach;?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -86,12 +86,12 @@ class program extends control
|
||||
* Create a program.
|
||||
*
|
||||
* @param string $template
|
||||
* @param int $programID
|
||||
* @param int $parentProgramID
|
||||
* @param int $copyProgramID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create($template = 'cmmi', $programID = 0, $copyProgramID = '')
|
||||
public function create($template = 'cmmi', $parentProgramID = 0, $copyProgramID = '')
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
@@ -109,16 +109,16 @@ class program extends control
|
||||
$acl = 'open';
|
||||
$privway = 'extend';
|
||||
|
||||
if($programID)
|
||||
if($parentProgramID)
|
||||
{
|
||||
$program = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($programID)->fetch();
|
||||
if($this->program->checkHasContent($programID))
|
||||
$parentProgram = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($parentProgramID)->fetch();
|
||||
if($this->program->checkHasContent($parentProgramID))
|
||||
{
|
||||
echo js::alert($this->lang->program->cannotCreateChild);
|
||||
die(js::locate('back'));
|
||||
}
|
||||
|
||||
if(empty($template)) $template = $program->template;
|
||||
if(empty($template)) $template = $parentProgram->template;
|
||||
}
|
||||
|
||||
if($copyProgramID)
|
||||
@@ -145,7 +145,7 @@ class program extends control
|
||||
$this->view->acl = $acl;
|
||||
$this->view->privway = $privway;
|
||||
$this->view->whitelist = $whitelist;
|
||||
$this->view->programID = $programID;
|
||||
$this->view->parentProgram = $parentProgramID ? $parentProgram : '';
|
||||
$this->view->copyProgramID = $copyProgramID;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -7,3 +7,4 @@
|
||||
#copyProjectModal a.active {border-color: #00da88; color: #00da88; background-color: #E5FFE6}
|
||||
#copyProjectModal a.active:after {position: absolute; content: '\e92f'; font-family: ZentaoIcon; font-size: 20px; right: 25px;}
|
||||
#copyProjectModal a.cancel {color: #ff5d5d}
|
||||
#budget {border-right:0px;}
|
||||
|
||||
@@ -114,3 +114,9 @@ $lang->program->confirmDelete = "您确定删除项目[%s]吗?";
|
||||
$lang->program->emptyPM = '暂无';
|
||||
$lang->program->cannotChangeToCat = "该项目已经有实际的内容,无法修改为父项目";
|
||||
$lang->program->cannotCancelCat = "该项目下已经有子项目,无法取消父项目标记";
|
||||
$lang->program->parentBeginEnd = "父项目起止时间:%s ~ %s";
|
||||
$lang->program->parentBudget = "父项目预算:%s";
|
||||
$lang->program->beginLetterParent = "父项目的开始日期:%s,开始日期不能小于父项目的开始日期";
|
||||
$lang->program->endGreaterParent = "父项目的完成日期:%s,完成日期不能大于父项目的完成日期";
|
||||
$lang->program->beginGreateChild = "子项目的最小开始日期:%s,父项目的开始日期不能大于子项目的最小开始日期";
|
||||
$lang->program->endLetterChild = "子项目的最大完成日期:%s,父项目的完成日期不能小于子项目的最大完成日期";
|
||||
|
||||
@@ -247,13 +247,21 @@ class programModel extends model
|
||||
->setIF($this->post->acl != 'custom', 'whitelist', '')
|
||||
->setDefault('openedBy', $this->app->user->account)
|
||||
->setDefault('openedDate', helper::now())
|
||||
->setDefault('team', substr($this->post->name,0, 30))
|
||||
->setDefault('team', substr($this->post->name, 0, 30))
|
||||
->join('whitelist', ',')
|
||||
->cleanInt('budget')
|
||||
->stripTags($this->config->program->editor->create['id'], $this->config->allowedTags)
|
||||
->remove('products, workDays, delta, branch, uid, plans')
|
||||
->get();
|
||||
|
||||
if($project->parent)
|
||||
{
|
||||
$parentProgram = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($project->parent)->fetch();
|
||||
if($project->begin < $parentProgram->begin) dao::$errors['begin'] = sprintf($this->lang->program->beginLetterParent, $parentProgram->begin);
|
||||
if($project->end > $parentProgram->end) dao::$errors['end'] = sprintf($this->lang->program->endGreaterParent, $parentProgram->end);
|
||||
if(dao::isError()) return false;
|
||||
}
|
||||
|
||||
$project = $this->loadModel('file')->processImgURL($project, $this->config->program->editor->create['id'], $this->post->uid);
|
||||
$this->dao->insert(TABLE_PROJECT)->data($project)
|
||||
->autoCheck()
|
||||
@@ -345,10 +353,25 @@ class programModel extends model
|
||||
->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;
|
||||
if(!$oldProgram->isCat and !empty($program->isCat) and $this->checkHasContent($programID)) dao::$errors['isCat'] = $this->lang->program->cannotChangeToCat;
|
||||
if($oldProgram->isCat and empty($program->isCat) and $this->checkHasChildren($programID)) dao::$errors['isCat'] = $this->lang->program->cannotCancelCat;
|
||||
|
||||
if(!empty($program->isCat))
|
||||
{
|
||||
$minChildBegin = $this->dao->select('min(begin) as minBegin')->from(TABLE_PROJECT)->where('id')->ne($programID)->andWhere('deleted')->eq(0)->andWhere('path')->like("%,{$programID},%")->fetch('minBegin');
|
||||
$maxChildEnd = $this->dao->select('max(end) as maxEnd')->from(TABLE_PROJECT)->where('id')->ne($programID)->andWhere('deleted')->eq(0)->andWhere('path')->like("%,{$programID},%")->fetch('maxEnd');
|
||||
|
||||
if($minChildBegin and $program->begin > $minChildBegin) dao::$errors['begin'] = sprintf($this->lang->program->beginGreateChild, $minChildBegin);
|
||||
if($maxChildEnd and $program->end < $maxChildEnd) dao::$errors['end'] = sprintf($this->lang->program->endLetterChild, $maxChildEnd);
|
||||
}
|
||||
|
||||
if($program->parent)
|
||||
{
|
||||
$parentProgram = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($program->parent)->fetch();
|
||||
if($parentProgram and $program->begin < $parentProgram->begin) dao::$errors['begin'] = sprintf($this->lang->program->beginLetterParent, $parentProgram->begin);
|
||||
if($parentProgram and $program->end > $parentProgram->end) dao::$errors['end'] = sprintf($this->lang->program->endGreaterParent, $parentProgram->end);
|
||||
}
|
||||
if(dao::isError()) return false;
|
||||
|
||||
$this->dao->update(TABLE_PROJECT)->data($program)
|
||||
->autoCheck($skipFields = 'begin,end')
|
||||
@@ -441,23 +464,23 @@ class programModel extends model
|
||||
public function checkHasContent($programID)
|
||||
{
|
||||
$count = 0;
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_BUDGET)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_BUG)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_CASE)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_DESIGN)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_DOC)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_DURATIONESTIMATION)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_ISSUE)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_PROJECT)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_RELATION)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_RELEASE)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_REPO)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_RISK)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_STORY)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_TESTREPORT)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_TESTSUITE)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_TESTTASK)->where('program')->eq($programID)->fetch('count');
|
||||
$count += $this->dao->select('count(*) as count')->from(TABLE_WORKESTIMATION)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_BUDGET)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_BUG)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_CASE)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_DESIGN)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_DOC)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_DURATIONESTIMATION)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_ISSUE)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_PROJECT)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_RELATION)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_RELEASE)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_REPO)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_RISK)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_STORY)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_TESTREPORT)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_TESTSUITE)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_TESTTASK)->where('program')->eq($programID)->fetch('count');
|
||||
$count += (int)$this->dao->select('count(*) as count')->from(TABLE_WORKESTIMATION)->where('program')->eq($programID)->fetch('count');
|
||||
|
||||
return $count > 0;
|
||||
}
|
||||
|
||||
@@ -75,8 +75,14 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->program->budget;?></th>
|
||||
<td><?php echo html::input('budget', '', "class='form-control'");?></td>
|
||||
<td style='float:left'><?php echo html::select('budgetUnit', $lang->program->unitList, 'yuan', "class='form-control'");?></td><td></td>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php echo html::input('budget', '', "class='form-control'");?>
|
||||
<span class='input-group-addon'></span>
|
||||
<?php echo html::select('budgetUnit', $lang->program->unitList, empty($parentProgram->budgetUnit) ? 'yuan' : $parentProgram->budgetUnit, "class='form-control'");?>
|
||||
</div>
|
||||
</td>
|
||||
<td class='muted'><?php if($parentProgram) printf($lang->program->parentBudget, $parentProgram->budget . zget($lang->program->unitList, $parentProgram->budgetUnit, ''));?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->program->dateRange;?></th>
|
||||
@@ -87,7 +93,7 @@
|
||||
<?php echo html::input('end', '', "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->program->end . "' required");?>
|
||||
</div>
|
||||
</td>
|
||||
<td colspan='2'></td>
|
||||
<td class='muted'><?php if($parentProgram) printf($lang->program->parentBeginEnd, $parentProgram->begin, $parentProgram->end);?></td>
|
||||
</tr>
|
||||
<?php if($template == 'scrum'):?>
|
||||
<tr>
|
||||
@@ -137,7 +143,7 @@
|
||||
<?php echo html::backButton();?>
|
||||
<?php
|
||||
echo html::hidden('template', $template);
|
||||
echo html::hidden('parent', $programID);
|
||||
echo html::hidden('parent', $parentProgram->id);
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -175,5 +181,5 @@
|
||||
</div>
|
||||
</div>
|
||||
<?php js::set('template', $template);?>
|
||||
<?php js::set('programID', $programID);?>
|
||||
<?php js::set('parentProgramID', $parentProgram->id);?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
Reference in New Issue
Block a user