@@ -100,14 +100,30 @@
id)); else printf('%03d', $story->id);?>
story->priList, $story->pri, $story->pri);?>'>story->priList, $story->pri, $story->pri)?> |
-
title);?> |
+
+ branch) echo "{$branches[$story->branch]}"?>
+ title);?>
+ |
planTitle;?> |
story->sourceList[$story->source];?> |
openedBy, $story->openedBy);?> |
assignedTo, $story->assignedTo);?> |
estimate;?> |
story->statusList[$story->status];?> |
-
story->stageList[$story->stage];?> |
+
+ id]) ? " class='popoverStage' data-toggle='popover' data-placement='bottom' data-target='\$next'" : '') . "'>";
+ echo $lang->story->stageList[$story->stage];
+ if(isset($storyStages[$story->id])) echo "";
+ echo '';
+ if(isset($storyStages[$story->id]))
+ {
+ echo " ";
+ foreach($storyStages[$story->id] as $storyBranch => $storyStage) echo $branches[$storyBranch] . ": " . $lang->story->stageList[$storyStage->stage] . ' ';
+ echo " ";
+ }
+ ?>
+ |
id}";
diff --git a/module/release/model.php b/module/release/model.php
index 791410527a..7db0f3edf4 100644
--- a/module/release/model.php
+++ b/module/release/model.php
@@ -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);
}
}
diff --git a/module/story/model.php b/module/story/model.php
index 0586671dc6..8bd99e2f90 100644
--- a/module/story/model.php
+++ b/module/story/model.php
@@ -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. */
diff --git a/module/tree/control.php b/module/tree/control.php
index 760f9a6797..c34909b326 100644
--- a/module/tree/control.php
+++ b/module/tree/control.php
@@ -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);
diff --git a/module/tree/js/browse.js b/module/tree/js/browse.js
index 9a9e395070..9ff2e8ba4e 100644
--- a/module/tree/js/browse.js
+++ b/module/tree/js/browse.js
@@ -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);
}
})
diff --git a/module/tree/model.php b/module/tree/model.php
index 547664fb03..ac40473241 100644
--- a/module/tree/model.php
+++ b/module/tree/model.php
@@ -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] . '- ' . $linkHtml;
+ $firstBranch = false;
+ }
$lastMenu .= "
- $linkHtml
" . @array_shift($treeMenu) . " \n";
}
else
@@ -298,6 +304,7 @@ class treeModel extends model
}
}
+ if(!$firstBranch) $lastMenu .= ' ';
$lastMenu = "\n";
return $lastMenu;
}
diff --git a/module/tree/view/browse.html.php b/module/tree/view/browse.html.php
index a5cd44701d..ed43bb7f75 100644
--- a/module/tree/view/browse.html.php
+++ b/module/tree/view/browse.html.php
@@ -86,7 +86,7 @@
echo html::input("modules[]", '', 'class="form-control"');
if($hasBranch) echo '' . html::select("branch[]", $branches, $branch, 'class="form-control"');
echo "";
- echo "";
+ echo "";
echo '';
}
?>
|