Merge branch 'master' of github.com:easysoft/zentaopms
This commit is contained in:
@@ -42,7 +42,9 @@ class branchModel extends model
|
||||
$branches = $this->dao->select('*')->from(TABLE_BRANCH)->where('product')->eq($productID)->andWhere('deleted')->eq(0)->orderBy('id_asc')->fetchPairs('id', 'name');
|
||||
if(strpos($params, 'noempty') === false)
|
||||
{
|
||||
$product = $this->loadModel('product')->getById($productID);
|
||||
$product = $this->loadModel('product')->getById($productID);
|
||||
if($product->type == 'normal') return array();
|
||||
|
||||
$branches = array('0' => $this->lang->branch->all . $this->lang->product->branchName[$product->type]) + $branches;
|
||||
}
|
||||
return $branches;
|
||||
|
||||
@@ -183,13 +183,16 @@ class product extends control
|
||||
}
|
||||
$this->loadModel('search')->setSearchParams($this->config->product->search);
|
||||
|
||||
$storyIdList = array();
|
||||
foreach($stories as $story) $storyIdList[$story->id] = $story->id;
|
||||
|
||||
$this->view->productID = $productID;
|
||||
$this->view->productName = $this->products[$productID];
|
||||
$this->view->moduleID = $moduleID;
|
||||
$this->view->stories = $stories;
|
||||
$this->view->plans = $this->loadModel('productplan')->getPairs($productID, $branch);
|
||||
$this->view->summary = $this->product->summary($stories);
|
||||
$this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'story', $startModuleID = 0, array('treeModel', 'createStoryLink'));
|
||||
$this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'story', $startModuleID = 0, array('treeModel', 'createStoryLink'), '', $branch);
|
||||
$this->view->parentModules = $this->tree->getParents($moduleID);
|
||||
$this->view->pager = $pager;
|
||||
$this->view->users = $this->user->getPairs('nodeleted|noletter|pofirst');
|
||||
@@ -197,6 +200,8 @@ class product extends control
|
||||
$this->view->browseType = $browseType;
|
||||
$this->view->moduleID = $moduleID;
|
||||
$this->view->branch = $branch;
|
||||
$this->view->branches = $this->loadModel('branch')->getPairs($productID);
|
||||
$this->view->storyStages = $this->story->getStoryStages($storyIdList);
|
||||
$this->display();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,4 +17,7 @@ $(function()
|
||||
$option.toggleClass('hide', $option.text().toString().toLowerCase().indexOf(val) < 0 && $option.data('key').toString().toLowerCase().indexOf(val) < 0);
|
||||
});
|
||||
});
|
||||
|
||||
$('.popoverStage').mouseover(function(){$(this).popover('show')});
|
||||
$('.popoverStage').mouseout(function(){$(this).popover('hide')});
|
||||
})
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<a class='side-handle' data-id='productTree'><i class='icon-caret-left'></i></a>
|
||||
<div class='side-body'>
|
||||
<div class='panel panel-sm'>
|
||||
<div class='panel-heading nobr'><?php echo html::icon($lang->icons['product']);?> <strong><?php echo $productName;?></strong></div>
|
||||
<div class='panel-heading nobr'><?php echo html::icon($lang->icons['product']);?> <strong><?php echo $branch ? $branches[$branch] : $productName;?></strong></div>
|
||||
<div class='panel-body'>
|
||||
<?php echo $moduleTree;?>
|
||||
<div class='text-right'>
|
||||
@@ -100,14 +100,30 @@
|
||||
<?php if($canView) echo html::a($viewLink, sprintf('%03d', $story->id)); else printf('%03d', $story->id);?>
|
||||
</td>
|
||||
<td><span class='<?php echo 'pri' . zget($lang->story->priList, $story->pri, $story->pri);?>'><?php echo zget($lang->story->priList, $story->pri, $story->pri)?></span></td>
|
||||
<td class='text-left' title="<?php echo $story->title?>"><nobr><?php echo html::a($viewLink, $story->title);?></nobr></td>
|
||||
<td class='text-left' title="<?php echo $story->title?>"><nobr>
|
||||
<?php if($story->branch) echo "<span class='label label-info label-badge'>{$branches[$story->branch]}</span>"?>
|
||||
<?php echo html::a($viewLink, $story->title);?>
|
||||
</nobr></td>
|
||||
<td title="<?php echo $story->planTitle?>"><?php echo $story->planTitle;?></td>
|
||||
<td><?php echo $lang->story->sourceList[$story->source];?></td>
|
||||
<td><?php echo zget($users, $story->openedBy, $story->openedBy);?></td>
|
||||
<td><?php echo zget($users, $story->assignedTo, $story->assignedTo);?></td>
|
||||
<td><?php echo $story->estimate;?></td>
|
||||
<td class='story-<?php echo $story->status;?>'><?php echo $lang->story->statusList[$story->status];?></td>
|
||||
<td><?php echo $lang->story->stageList[$story->stage];?></td>
|
||||
<td>
|
||||
<?php
|
||||
echo "<div" . (isset($storyStages[$story->id]) ? " class='popoverStage' data-toggle='popover' data-placement='bottom' data-target='\$next'" : '') . "'>";
|
||||
echo $lang->story->stageList[$story->stage];
|
||||
if(isset($storyStages[$story->id])) echo "<span class='pull-right'><i class='icon icon-caret-down'></i></span>";
|
||||
echo '</div>';
|
||||
if(isset($storyStages[$story->id]))
|
||||
{
|
||||
echo "<div class='popover'>";
|
||||
foreach($storyStages[$story->id] as $storyBranch => $storyStage) echo $branches[$storyBranch] . ": " . $lang->story->stageList[$storyStage->stage] . '<br />';
|
||||
echo "</div>";
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td class='text-right'>
|
||||
<?php
|
||||
$vars = "story={$story->id}";
|
||||
|
||||
@@ -177,8 +177,8 @@ class releaseModel extends model
|
||||
$this->dao->update(TABLE_RELEASE)->set('stories')->eq($release->stories)->where('id')->eq((int)$releaseID)->exec();
|
||||
if($release->stories)
|
||||
{
|
||||
$this->dao->update(TABLE_STORY)->set('stage')->eq('released')->where('id')->in($release->stories)->exec();
|
||||
$this->dao->update(TABLE_STORYSTAGE)->set('stage')->eq('released')->where('story')->in($release->stories)->andWhere('branch')->eq($release->branch)->exec();
|
||||
$this->loadModel('story');
|
||||
foreach($this->post->stories as $storyID) $this->story->setStage($storyID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -850,43 +850,46 @@ class storyModel extends model
|
||||
* Set stage of a story.
|
||||
*
|
||||
* @param int $storyID
|
||||
* @param string $customStage
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function setStage($storyID, $customStage = '')
|
||||
public function setStage($storyID)
|
||||
{
|
||||
$storyID = (int)$storyID;
|
||||
/* Custom stage defined, use it. */
|
||||
if($customStage)
|
||||
{
|
||||
$this->dao->update(TABLE_STORY)->set('stage')->eq($customStage)->where('id')->eq((int)$storyID)->exec();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Get projects which status is doing. */
|
||||
$this->dao->delete()->from(TABLE_STORYSTAGE)->where('story')->eq($storyID)->exec();
|
||||
$story = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch();
|
||||
$product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fetch();
|
||||
$projects = $this->dao->select('t1.project,t3.branch')->from(TABLE_PROJECTSTORY)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
|
||||
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t3')->on('t1.project = t3.project')
|
||||
->where('t1.story')->eq($storyID)
|
||||
->andWhere('t2.status')->ne('done')
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->fetchPairs('project', 'branch');
|
||||
|
||||
$hasBranch = ($product->type != 'normal' and empty($story->branch));
|
||||
$stages = array();
|
||||
if($hasBranch and $story->plan)
|
||||
{
|
||||
$plans = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('id')->in($story->plan)->fetchPairs('branch', 'branch');
|
||||
foreach($plans as $branch) $stages[$branch] = 'planned';
|
||||
}
|
||||
|
||||
/* If no projects, in plan, stage is planned. No plan, wait. */
|
||||
if(!$projects)
|
||||
{
|
||||
$this->dao->update(TABLE_STORY)->set('stage')->eq('wait')->where('id')->eq($storyID)->andWhere('plan')->eq('')->exec();
|
||||
|
||||
foreach($stages as $branch => $stage) $this->dao->insert(TABLE_STORYSTAGE)->set('story')->eq($storyID)->set('branch')->eq($branch)->set('stage')->eq($stage)->exec();
|
||||
$this->dao->update(TABLE_STORY)->set('stage')->eq('planned')->where('id')->eq($storyID)->andWhere('plan')->ne('')->exec();
|
||||
return true;
|
||||
}
|
||||
|
||||
$story = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch();
|
||||
$product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fetch();
|
||||
$branches = array();
|
||||
foreach($projects as $projectID => $branch) $branches[$branch] = $branch;
|
||||
unset($branches[0]);
|
||||
if($hasBranch)
|
||||
{
|
||||
foreach($projects as $projectID => $branch) $stages[$branch] = 'projected';
|
||||
}
|
||||
|
||||
/* Search related tasks. */
|
||||
$tasks = $this->dao->select('type,project,status')->from(TABLE_TASK)
|
||||
@@ -898,19 +901,14 @@ class storyModel extends model
|
||||
->fetchGroup('type');
|
||||
|
||||
/* No tasks, then the stage is projected. */
|
||||
$hasBranch = ($product->type != 'normal' and empty($story->branch) and $branches);
|
||||
if(!$tasks)
|
||||
{
|
||||
if($hasBranch)
|
||||
{
|
||||
foreach($branches as $branch) $this->dao->insert(TABLE_STORYSTAGE)->set('story')->eq($storyID)->set('branch')->eq($branch)->set('stage')->eq('projected')->exec();
|
||||
}
|
||||
foreach($stages as $branch => $stage) $this->dao->insert(TABLE_STORYSTAGE)->set('story')->eq($storyID)->set('branch')->eq($branch)->set('stage')->eq('projected')->exec();
|
||||
$this->dao->update(TABLE_STORY)->set('stage')->eq('projected')->where('id')->eq($storyID)->exec();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Get current stage and set as default value. */
|
||||
$taskProjects = array();
|
||||
$currentStage = $story->stage;
|
||||
$stage = $currentStage;
|
||||
|
||||
@@ -930,15 +928,14 @@ class storyModel extends model
|
||||
$branch = $projects[$task->project];
|
||||
if(!isset($branchStatusList[$branch])) $branchStatusList[$branch] = $statusList;
|
||||
$branchStatusList[$branch][$task->type][$status] ++;
|
||||
$taskProjects[$task->project] = $task->project;
|
||||
if($type == 'devel')
|
||||
{
|
||||
if(!isset($develTasks[$branch])) $develTasks[$branch] = 0;
|
||||
if(!isset($branchDevelTasks[$branch])) $branchDevelTasks[$branch] = 0;
|
||||
$branchDevelTasks[$branch] ++;
|
||||
}
|
||||
elseif($type == 'test')
|
||||
{
|
||||
if(!isset($testTasks[$branch])) $testTasks[$branch] = 0;
|
||||
if(!isset($branchTestTasks[$branch])) $branchTestTasks[$branch] = 0;
|
||||
$branchTestTasks[$branch] ++;
|
||||
}
|
||||
}
|
||||
@@ -963,14 +960,31 @@ class storyModel extends model
|
||||
if(($statusList['devel']['wait'] > 0 or $statusList['devel']['doing'] > 0) and $statusList['test']['done'] == $testTasks and $testTasks > 0) $stage = 'testing';
|
||||
if($statusList['devel']['done'] == $develTasks and $develTasks > 0 and $statusList['test']['done'] == $testTasks and $testTasks > 0) $stage = 'tested';
|
||||
|
||||
if($hasBranch and $branch) $this->dao->insert(TABLE_STORYSTAGE)->set('story')->eq($storyID)->set('branch')->eq($branch)->set('stage')->eq($stage)->exec();
|
||||
$this->dao->update(TABLE_STORY)->set('stage')->eq($stage)->where('id')->eq($storyID)->exec();
|
||||
$stages[$branch] = $stage;
|
||||
}
|
||||
|
||||
foreach($projects as $projectID => $branch)
|
||||
$releases = $this->dao->select('*')->from(TABLE_RELEASE)->where("CONCAT(',', stories, ',')")->like("%,$storyID,%")->andWhere('deleted')->eq(0)->fetchPairs('branch', 'branch');
|
||||
foreach($releases as $branch) $stages[$branch] = 'released';
|
||||
|
||||
if($hasBranch)
|
||||
{
|
||||
if(isset($taskProjects[$projectID])) continue;
|
||||
$this->dao->insert(TABLE_STORYSTAGE)->set('story')->eq($storyID)->set('branch')->eq($branch)->set('stage')->eq('projected')->exec();
|
||||
$stageList = join(',', array_keys($this->lang->story->stageList));
|
||||
$minStagePos = strlen($stageList);
|
||||
$minStage = '';
|
||||
foreach($stages as $branch => $stage)
|
||||
{
|
||||
$this->dao->insert(TABLE_STORYSTAGE)->set('story')->eq($storyID)->set('branch')->eq($branch)->set('stage')->eq($stage)->exec();
|
||||
if(strpos($stageList, $stage) !== false and strpos($stageList, $stage) < $minStagePos)
|
||||
{
|
||||
$minStage = $stage;
|
||||
$minStagePos = strpos($stageList, $stage);
|
||||
}
|
||||
}
|
||||
$this->dao->update(TABLE_STORY)->set('stage')->eq($minStage)->where('id')->eq($storyID)->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->dao->update(TABLE_STORY)->set('stage')->eq(current($stages))->where('id')->eq($storyID)->exec();
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -993,10 +1007,11 @@ class storyModel extends model
|
||||
{
|
||||
unset($branch[0]);
|
||||
$branch = join(',', $branch);
|
||||
if($branch) $branch = "0,$branch";
|
||||
}
|
||||
$stories = $this->dao->select('*')->from(TABLE_STORY)
|
||||
->where('product')->in($productID)
|
||||
->beginIF($branch)->andWhere("branch")->in("0,$branch")->fi()
|
||||
->beginIF($branch)->andWhere("branch")->in("$branch")->fi()
|
||||
->beginIF(!empty($moduleIds))->andWhere('module')->in($moduleIds)->fi()
|
||||
->beginIF($status and $status != 'all')->andWhere('status')->in($status)->fi()
|
||||
->andWhere('deleted')->eq(0)
|
||||
@@ -1476,6 +1491,20 @@ class storyModel extends model
|
||||
return $allStories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get story stages.
|
||||
*
|
||||
* @param array $stories
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getStoryStages($stories)
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_STORYSTAGE)
|
||||
->where('story')->in($stories)
|
||||
->fetchGroup('story', 'branch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check need confirm.
|
||||
*
|
||||
@@ -1826,16 +1855,27 @@ class storyModel extends model
|
||||
public function mergePlanTitle($productID, $stories, $branch = 0)
|
||||
{
|
||||
$query = $this->dao->get();
|
||||
if(is_array($branch))
|
||||
{
|
||||
unset($branch[0]);
|
||||
$branch = join(',', $branch);
|
||||
if($branch) $branch = "0,$branch";
|
||||
}
|
||||
$plans = $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN)
|
||||
->where('product')->in($productID)
|
||||
->beginIF($branch)->andWhere('branch')->in("0,$branch")->fi()
|
||||
->beginIF($branch)->andWhere('branch')->in($branch)->fi()
|
||||
->andWhere('deleted')->eq(0)
|
||||
->fetchPairs('id', 'title');
|
||||
$stages = $this->dao->select('*')->from(TABLE_STORYSTAGE)->where('branch')->in($branch)->fetchGroup('story', 'branch');
|
||||
|
||||
$branch = trim(str_replace(',0,', '', ",$branch,"), ',');
|
||||
$branch = empty($branch) ? 0 : $branch;
|
||||
foreach($stories as $story)
|
||||
{
|
||||
$story->planTitle = '';
|
||||
$storyPlans = explode(',', trim($story->plan, ','));
|
||||
foreach($storyPlans as $planID) $story->planTitle .= zget($plans, $planID) . ' ';
|
||||
if(empty($story->branch) and isset($stages[$story->id][$branch])) $story->stage = $stages[$story->id][$branch]->stage;
|
||||
}
|
||||
|
||||
/* For save session query. */
|
||||
|
||||
@@ -30,7 +30,6 @@ class tree extends control
|
||||
$product = $this->loadModel('product')->getById($rootID);
|
||||
if($product->type != 'normal') $this->view->branches = $this->loadModel('branch')->getPairs($product->id);
|
||||
$this->view->root = $product;
|
||||
$this->view->productModules = $this->tree->getOptionMenu($rootID, 'story');
|
||||
}
|
||||
/* The viewType is doc. */
|
||||
elseif(strpos($viewType, 'doc') !== false)
|
||||
@@ -65,6 +64,7 @@ class tree extends control
|
||||
|
||||
$this->view->allProduct = $products;
|
||||
$this->view->currentProduct = $currentProduct;
|
||||
$this->view->productModules = $this->tree->getOptionMenu($currentProduct, 'story');
|
||||
|
||||
$title = $product->name . $this->lang->colon . $this->lang->tree->manageProduct;
|
||||
$position[] = html::a($this->createLink('product', 'browse', "product=$rootID"), $product->name);
|
||||
|
||||
@@ -22,7 +22,7 @@ function syncModule(rootID, type)
|
||||
{
|
||||
if(value)
|
||||
{
|
||||
$('#sonModule .input-group:last').after($inputgroup);
|
||||
$('#sonModule').append($inputgroup);
|
||||
$('#sonModule .input-group:last input').val(value);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -271,15 +271,16 @@ class treeModel extends model
|
||||
{
|
||||
$branches = array($branch => '');
|
||||
$manage = $userFunc[1] == 'createManageLink' ? true : false;
|
||||
$product = $this->loadModel('product')->getById($rootID);
|
||||
if(strpos('story|bug|case', $type) !== false and empty($branch))
|
||||
{
|
||||
$product = $this->loadModel('product')->getById($rootID);
|
||||
if($product->type != 'normal') $branches = array('null' => '') + $this->loadModel('branch')->getPairs($rootID, 'noempty');
|
||||
}
|
||||
|
||||
/* Add for task #1945. check the module has case or no. */
|
||||
if($type == 'case' and !empty($extra)) $this->loadModel('testtask');
|
||||
$lastMenu = '';
|
||||
$lastMenu = '';
|
||||
$firstBranch = true;
|
||||
foreach($branches as $branchID => $branch)
|
||||
{
|
||||
$treeMenu = array();
|
||||
@@ -290,6 +291,11 @@ class treeModel extends model
|
||||
if(!empty($branchID) and $branch and $branchID != 'null')
|
||||
{
|
||||
$linkHtml = $manage ? html::a(inlink('browse', "root=$rootID&viewType=$type¤tModuleID=0&branch=$branchID"), $branch) : $this->createBranchLink($type, $rootID, $branchID, $branch);
|
||||
if($firstBranch and $product->type != 'normal')
|
||||
{
|
||||
$linkHtml = $this->lang->product->branchName[$product->type] . '<ul><li>' . $linkHtml;
|
||||
$firstBranch = false;
|
||||
}
|
||||
$lastMenu .= "<li>$linkHtml<ul>" . @array_shift($treeMenu) . "</ul></li>\n";
|
||||
}
|
||||
else
|
||||
@@ -298,6 +304,7 @@ class treeModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
if(!$firstBranch) $lastMenu .= '</li></ul>';
|
||||
$lastMenu = "<ul class='tree'>$lastMenu</ul>\n";
|
||||
return $lastMenu;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
echo html::input("modules[]", '', 'class="form-control"');
|
||||
if($hasBranch) echo '<span class="input-group-addon fix-border" style="padding:0px"></span>' . html::select("branch[]", $branches, $branch, 'class="form-control"');
|
||||
echo "<span class='input-group-addon fix-border'><a href='javascript:;' onclick='addItem(this)'><i class='icon icon-plus'></i></a></span>";
|
||||
echo "<span class='input-group-addon fix-border'><a href='javascript:;' onclick='deleteItem(this)'><i class='icon icon-remove'></i></a></span>";
|
||||
echo "<span class='input-group-addon'><a href='javascript:;' onclick='deleteItem(this)'><i class='icon icon-remove'></i></a></span>";
|
||||
echo '</div>';
|
||||
}
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user