* Finish task #7951. Fix bug 3369.
This commit is contained in:
+20
-6
@@ -1232,11 +1232,27 @@ EOD;
|
||||
*/
|
||||
public function getPreAndNextObject($type, $objectID)
|
||||
{
|
||||
$preAndNextObject = new stdClass();
|
||||
$preAndNextObject = new stdClass();
|
||||
$preAndNextObject->pre = '';
|
||||
$preAndNextObject->next = '';
|
||||
|
||||
/* Use existObject when the preAndNextObject of this objectID has exist in session. */
|
||||
$existObject = $type . 'PreAndNext';
|
||||
if(isset($_SESSION[$existObject]) and $_SESSION[$existObject]['objectID'] == $objectID) return $_SESSION[$existObject]['preAndNextObject'];
|
||||
if($type == 'story' and !empty($_SESSION['planStoryOrder']))
|
||||
{
|
||||
$objects = explode(',', $_SESSION['planStoryOrder']);
|
||||
$key = array_search($objectID, $objects);
|
||||
|
||||
if($key > 0)
|
||||
{
|
||||
$preObjectID = $objects[$key - 1];
|
||||
$preAndNextObject->pre = $this->loadModel('story')->getByID($preObjectID);
|
||||
}
|
||||
if($key < (count($objects) - 1))
|
||||
{
|
||||
$nextObjectID = $objects[$key + 1];
|
||||
$preAndNextObject->next = $this->loadModel('story')->getByID($nextObjectID);
|
||||
}
|
||||
return $preAndNextObject;
|
||||
}
|
||||
|
||||
/* Get objectIDList. */
|
||||
$table = $this->config->objectTables[$type];
|
||||
@@ -1258,8 +1274,6 @@ EOD;
|
||||
}
|
||||
|
||||
$preObj = false;
|
||||
$preAndNextObject->pre = '';
|
||||
$preAndNextObject->next = '';
|
||||
while($object = $queryObjects->fetch())
|
||||
{
|
||||
$key = (!$this->session->$typeOnlyCondition and $type == 'testcase' and isset($object->case)) ? 'case' : 'id';
|
||||
|
||||
@@ -112,6 +112,7 @@ class product extends control
|
||||
/* Save session. */
|
||||
$this->session->set('storyList', $this->app->getURI(true));
|
||||
$this->session->set('productList', $this->app->getURI(true));
|
||||
$this->session->set('planStoryOrder', '');
|
||||
|
||||
/* Set product, module and query. */
|
||||
$productID = $this->product->saveState($productID, $this->products);
|
||||
|
||||
@@ -259,6 +259,10 @@ class productplan extends control
|
||||
$orderBy = str_replace('order', 'id', $orderBy);
|
||||
$reSort = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->session->set('planStoryOrder', '');
|
||||
}
|
||||
|
||||
/* Append id for secend sort. */
|
||||
$sort = $this->loadModel('common')->appendOrder($orderBy);
|
||||
@@ -266,26 +270,26 @@ class productplan extends control
|
||||
$this->commonAction($plan->product, $plan->branch);
|
||||
$products = $this->product->getPairs();
|
||||
|
||||
$bugPager = new pager(0, $recPerPage, $type == 'bug' ? $pageID : 1);
|
||||
$storyPager = new pager(0, $recPerPage, $type == 'story' ? $pageID : 1);
|
||||
$planStories = $this->loadModel('story')->getPlanStories($planID, 'all', $type == 'story' ? $sort : 'id_desc', $storyPager);
|
||||
$bugPager = new pager(0, $recPerPage, $type == 'bug' ? $pageID : 1);
|
||||
$storyPager = new pager(0, $recPerPage, $type == 'story' ? $pageID : 1);
|
||||
|
||||
$this->loadModel('story');
|
||||
if(!$reSort or empty($plan->order)) $planStories = $this->story->getPlanStories($planID, 'all', $type == 'story' ? $sort : 'id_desc', $storyPager);
|
||||
|
||||
if($reSort)
|
||||
{
|
||||
if(!empty($plan->order))
|
||||
{
|
||||
$stories = array();
|
||||
$order = explode(',', $plan->order);
|
||||
if(strpos($orderBy, 'desc') !== false) $order = array_reverse($order, true);
|
||||
foreach($order as $id)
|
||||
{
|
||||
if(empty($id)) continue;
|
||||
if(!isset($planStories[$id])) continue;
|
||||
$stories[$id] = $planStories[$id];
|
||||
unset($planStories[$id]);
|
||||
}
|
||||
if($planStories) $stories += $planStories;
|
||||
$planStories = $stories;
|
||||
unset($stories);
|
||||
$planStories = $this->story->getPlanStories($planID, 'all', $sort);
|
||||
$planStories = $this->story->sortPlanStory($planStories, $plan->order, $orderBy);
|
||||
|
||||
$storyIDList = implode(',', array_keys($planStories));
|
||||
$this->session->set('planStoryOrder', $storyIDList);
|
||||
|
||||
$storyPager->recTotal = count($planStories);
|
||||
|
||||
$frontCount = $storyPager->recPerPage * ($storyPager->pageID - 1);
|
||||
$planStories = array_slice($planStories, $frontCount, $storyPager->recPerPage);
|
||||
}
|
||||
$orderBy = str_replace('id', 'order', $orderBy);
|
||||
}
|
||||
@@ -330,9 +334,9 @@ class productplan extends control
|
||||
{
|
||||
$plans = $this->productplan->getPairs($productID, $branch);
|
||||
|
||||
$planName = $number === '' ? 'plan' : "plan[$number]";
|
||||
$plans = empty($plans) ? array('' => '') : $plans;
|
||||
die(html::select($planName, $plans, '', "class='form-control'"));
|
||||
$planName = $number === '' ? 'plan' : "plan[$number]";
|
||||
$plans = empty($plans) ? array('' => '') : $plans;
|
||||
die(html::select($planName, $plans, '', "class='form-control'"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -346,7 +350,12 @@ class productplan extends control
|
||||
public function ajaxStorySort($planID = 0)
|
||||
{
|
||||
if(empty($planID)) return true;
|
||||
$this->dao->update(TABLE_PRODUCTPLAN)->set('`order`')->eq($this->post->storys)->where('id')->eq((int)$planID)->exec();
|
||||
|
||||
$plan = $this->productplan->getByID($planID, true);
|
||||
$order = $this->loadModel('story')->getAllStorySort($planID, $plan->order);
|
||||
|
||||
$this->dao->update(TABLE_PRODUCTPLAN)->set('`order`')->eq($order)->where('id')->eq((int)$planID)->exec();
|
||||
$this->session->set('planStoryOrder', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,7 +71,7 @@ $(function()
|
||||
{
|
||||
var list = '';
|
||||
for(i = 0; i < data.list.length; i++) list += $(data.list[i].item).attr('data-id') + ',';
|
||||
$.post(createLink('productplan', 'ajaxStorySort', 'planID=' + planID), {'storys' : list, 'orderBy' : orderBy}, function()
|
||||
$.post(createLink('productplan', 'ajaxStorySort', 'planID=' + planID), {'stories' : list, 'orderBy' : orderBy, 'pageID' : storyPageID, 'recPerPage' : storyRecPerPage, 'recTotal' : storyRecTotal}, function()
|
||||
{
|
||||
var $target = $(data.element[0]);
|
||||
$target.hide();
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
<?php js::set('confirmUnlinkStory', $lang->productplan->confirmUnlinkStory)?>
|
||||
<?php js::set('confirmUnlinkBug', $lang->productplan->confirmUnlinkBug)?>
|
||||
<?php js::set('planID', $plan->id);?>
|
||||
<?php js::set('storyPageID', $storyPager->pageID);?>
|
||||
<?php js::set('storyRecPerPage', $storyPager->recPerPage);?>
|
||||
<?php js::set('storyRecTotal', $storyPager->recTotal);?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
<?php $browseLink = $this->session->productPlanList ? $this->session->productPlanList : inlink('browse', "planID=$plan->id");?>
|
||||
|
||||
@@ -689,6 +689,7 @@ class project extends control
|
||||
|
||||
/* Save session. */
|
||||
$this->app->session->set('storyList', $this->app->getURI(true));
|
||||
$this->session->set('planStoryOrder', '');
|
||||
|
||||
/* Process the order by field. */
|
||||
if(!$orderBy) $orderBy = $this->cookie->projectStoryOrder ? $this->cookie->projectStoryOrder : 'pri';
|
||||
|
||||
+143
-49
@@ -211,6 +211,12 @@ class storyModel extends model
|
||||
$this->file->updateObjectID($this->post->uid, $storyID, 'story');
|
||||
$this->file->saveUpload('story', $storyID, $extra = 1);
|
||||
|
||||
if(!empty($story->plan))
|
||||
{
|
||||
$plan[$story->plan][] = $storyID;
|
||||
$this->updatePlanStoryOrder($plan);
|
||||
}
|
||||
|
||||
$data = new stdclass();
|
||||
$data->story = $storyID;
|
||||
$data->version = 1;
|
||||
@@ -361,6 +367,8 @@ class storyModel extends model
|
||||
$data[$i] = $story;
|
||||
}
|
||||
|
||||
$planStories = array();
|
||||
|
||||
foreach($data as $i => $story)
|
||||
{
|
||||
$this->dao->insert(TABLE_STORY)->data($story)->autoCheck()->exec();
|
||||
@@ -373,6 +381,8 @@ class storyModel extends model
|
||||
$storyID = $this->dao->lastInsertID();
|
||||
$this->setStage($storyID);
|
||||
|
||||
if($story->plan) $planStories[$story->plan][] = $storyID;
|
||||
|
||||
$specData = new stdclass();
|
||||
$specData->story = $storyID;
|
||||
$specData->version = 1;
|
||||
@@ -423,6 +433,9 @@ class storyModel extends model
|
||||
$mails[$i]->actionID = $actionID;
|
||||
}
|
||||
|
||||
/* Update product plan stories order. */
|
||||
if(!empty($planStories)) $this->updatePlanStoryOrder($planStories);
|
||||
|
||||
/* Remove upload image file and session. */
|
||||
if(!empty($stories->uploadImage) and $this->session->storyImagesFile)
|
||||
{
|
||||
@@ -786,6 +799,29 @@ class storyModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update plan story order.
|
||||
*
|
||||
* @param int $planStories
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function updatePlanStoryOrder($planStories)
|
||||
{
|
||||
$planIDList = array_keys($planStories);
|
||||
$plans = $this->dao->select('id, `order`')->from(TABLE_PRODUCTPLAN)->where('id')->in($planIDList)->fetchAll('id');
|
||||
|
||||
foreach($planStories as $planID => $stories)
|
||||
{
|
||||
$data = new stdClass();
|
||||
$data->order = implode(',', $stories);
|
||||
$productPlan = $plans[$planID];
|
||||
if(!empty($productPlan->order)) $data->order = $data->order . ',' . $productPlan->order;
|
||||
|
||||
$this->dao->update(TABLE_PRODUCTPLAN)->data($data)->where('id')->eq($planID)->exec();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute parent story estimate.
|
||||
*
|
||||
@@ -2294,6 +2330,34 @@ class storyModel extends model
|
||||
return $allStories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all story sort.
|
||||
*
|
||||
* @param int $planID
|
||||
* @param int $planOrder
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getAllStorySort($planID, $planOrder)
|
||||
{
|
||||
$orderBy = $this->post->orderBy;
|
||||
if(strpos($orderBy, 'order') !== false) $orderBy = str_replace('order', 'id', $orderBy);
|
||||
|
||||
$stories = $this->loadModel('story')->getPlanStories($planID, 'all');
|
||||
$storyIDList = array_keys($stories);
|
||||
|
||||
if(strpos($this->post->orderBy, 'order') !== false and !empty($planOrder)) $stories = $this->sortPlanStory($stories, $planOrder, $orderBy);
|
||||
|
||||
$frontCount = (int)$this->post->recPerPage * ((int)$this->post->pageID - 1);
|
||||
$behindCount = (int)$this->post->recPerPage * (int)$this->post->pageID;
|
||||
$frontIDList = array_slice($storyIDList, 0, $frontCount);
|
||||
$behindIDList = array_slice($storyIDList, $behindCount, count($storyIDList) - $behindCount);
|
||||
|
||||
$frontIDList = !empty($frontIDList) ? implode(',', $frontIDList) . ',' : '';
|
||||
$behindIDList = !empty($behindIDList) ? implode(',', $behindIDList) : '';
|
||||
return $frontIDList . $this->post->stories . $behindIDList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch get story stage.
|
||||
*
|
||||
@@ -2700,6 +2764,67 @@ class storyModel extends model
|
||||
return $storyGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mail subject.
|
||||
*
|
||||
* @param object $story
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getSubject($story)
|
||||
{
|
||||
$productName = $this->loadModel('product')->getById($story->product)->name;
|
||||
return 'STORY #' . $story->id . ' ' . $story->title . ' - ' . $productName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get toList and ccList.
|
||||
*
|
||||
* @param object $story
|
||||
* @param string $actionType
|
||||
* @access public
|
||||
* @return bool|array
|
||||
*/
|
||||
public function getToAndCcList($story, $actionType)
|
||||
{
|
||||
/* Set toList and ccList. */
|
||||
$toList = $story->assignedTo;
|
||||
$ccList = str_replace(' ', '', trim($story->mailto, ','));
|
||||
|
||||
/* If the action is changed or reviewed, mail to the project team. */
|
||||
if(strtolower($actionType) == 'changed' or strtolower($actionType) == 'reviewed')
|
||||
{
|
||||
$prjMembers = $this->getProjectMembers($story->id);
|
||||
if($prjMembers)
|
||||
{
|
||||
$ccList .= ',' . join(',', $prjMembers);
|
||||
$ccList = ltrim($ccList, ',');
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($toList))
|
||||
{
|
||||
if(empty($ccList)) return false;
|
||||
if(strpos($ccList, ',') === false)
|
||||
{
|
||||
$toList = $ccList;
|
||||
$ccList = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$commaPos = strpos($ccList, ',');
|
||||
$toList = substr($ccList, 0, $commaPos);
|
||||
$ccList = substr($ccList, $commaPos + 1);
|
||||
}
|
||||
}
|
||||
elseif($toList == 'closed')
|
||||
{
|
||||
$toList = $story->openedBy;
|
||||
}
|
||||
|
||||
return array($toList, $ccList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the action clickable.
|
||||
*
|
||||
@@ -3150,63 +3275,32 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mail subject.
|
||||
* Sort product plan story.
|
||||
*
|
||||
* @param object $story
|
||||
* @param int $planStories
|
||||
* @param string $order
|
||||
* @param string $orderBy
|
||||
* @access public
|
||||
* @return string
|
||||
* @return array
|
||||
*/
|
||||
public function getSubject($story)
|
||||
public function sortPlanStory($planStories, $order = '', $orderBy = 'order_asc')
|
||||
{
|
||||
$productName = $this->loadModel('product')->getById($story->product)->name;
|
||||
return 'STORY #' . $story->id . ' ' . $story->title . ' - ' . $productName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get toList and ccList.
|
||||
*
|
||||
* @param object $story
|
||||
* @param string $actionType
|
||||
* @access public
|
||||
* @return bool|array
|
||||
*/
|
||||
public function getToAndCcList($story, $actionType)
|
||||
{
|
||||
/* Set toList and ccList. */
|
||||
$toList = $story->assignedTo;
|
||||
$ccList = str_replace(' ', '', trim($story->mailto, ','));
|
||||
|
||||
/* If the action is changed or reviewed, mail to the project team. */
|
||||
if(strtolower($actionType) == 'changed' or strtolower($actionType) == 'reviewed')
|
||||
$stories = array();
|
||||
if(!empty($order))
|
||||
{
|
||||
$prjMembers = $this->getProjectMembers($story->id);
|
||||
if($prjMembers)
|
||||
if(is_string($order)) $order = explode(',', $order);
|
||||
if(strpos($orderBy, 'desc') !== false) $order = array_reverse($order, true);
|
||||
|
||||
foreach($order as $id)
|
||||
{
|
||||
$ccList .= ',' . join(',', $prjMembers);
|
||||
$ccList = ltrim($ccList, ',');
|
||||
if(empty($id)) continue;
|
||||
if(!isset($planStories[$id])) continue;
|
||||
$stories[$id] = $planStories[$id];
|
||||
unset($planStories[$id]);
|
||||
}
|
||||
if($planStories) $stories += $planStories;
|
||||
}
|
||||
|
||||
if(empty($toList))
|
||||
{
|
||||
if(empty($ccList)) return false;
|
||||
if(strpos($ccList, ',') === false)
|
||||
{
|
||||
$toList = $ccList;
|
||||
$ccList = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$commaPos = strpos($ccList, ',');
|
||||
$toList = substr($ccList, 0, $commaPos);
|
||||
$ccList = substr($ccList, $commaPos + 1);
|
||||
}
|
||||
}
|
||||
elseif($toList == 'closed')
|
||||
{
|
||||
$toList = $story->openedBy;
|
||||
}
|
||||
|
||||
return array($toList, $ccList);
|
||||
return $stories;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user