This commit is contained in:
holan20180123
2020-08-26 10:21:09 +08:00
9 changed files with 147 additions and 45 deletions

View File

@@ -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');
}
}
/**

View File

@@ -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) );
}
})
}

View File

@@ -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();

View File

@@ -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;?>

View File

@@ -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();
}

View File

@@ -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;}

View File

@@ -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父项目的完成日期不能小于子项目的最大完成日期";

View File

@@ -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;
}

View File

@@ -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';?>