From fd6f9f5ac9fc6be7fa37e540feb6fa1fa33a3a07 Mon Sep 17 00:00:00 2001
From: holan20180123 <56391770@qq.com>
Date: Mon, 28 Sep 2020 10:46:14 +0800
Subject: [PATCH] * Finish task #7951.
---
module/common/model.php | 27 +++++++--
module/product/control.php | 1 +
module/productplan/control.php | 49 ++++++++-------
module/productplan/js/view.js | 2 +-
module/productplan/view/view.html.php | 3 +
module/project/control.php | 1 +
module/story/model.php | 86 +++++++++++++++++++++++++++
7 files changed, 142 insertions(+), 27 deletions(-)
diff --git a/module/common/model.php b/module/common/model.php
index 920e38de2d..60fb288711 100644
--- a/module/common/model.php
+++ b/module/common/model.php
@@ -1425,11 +1425,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];
@@ -1451,8 +1467,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';
@@ -1474,6 +1488,7 @@ EOD;
if($preObj !== true) $preObj = $object;
}
+ $existObject = $type . 'PreAndNext';
$this->session->set($existObject, array('objectID' => $objectID, 'preAndNextObject' => $preAndNextObject));
return $preAndNextObject;
}
diff --git a/module/product/control.php b/module/product/control.php
index d335963e7d..4e71b4e927 100644
--- a/module/product/control.php
+++ b/module/product/control.php
@@ -116,6 +116,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);
diff --git a/module/productplan/control.php b/module/productplan/control.php
index fc938de088..e9a1e95d83 100644
--- a/module/productplan/control.php
+++ b/module/productplan/control.php
@@ -262,6 +262,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);
@@ -269,26 +273,26 @@ class productplan extends control
$this->commonAction($plan->product, $plan->branch);
$products = $this->product->getPairs('', $this->session->PRJ);
- $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);
}
@@ -333,9 +337,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'"));
}
/**
@@ -349,7 +353,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);
}
/**
diff --git a/module/productplan/js/view.js b/module/productplan/js/view.js
index 623342a598..0e0d2e64f7 100644
--- a/module/productplan/js/view.js
+++ b/module/productplan/js/view.js
@@ -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();
diff --git a/module/productplan/view/view.html.php b/module/productplan/view/view.html.php
index 13585279a6..264df106ab 100644
--- a/module/productplan/view/view.html.php
+++ b/module/productplan/view/view.html.php
@@ -16,6 +16,9 @@
productplan->confirmUnlinkStory)?>
productplan->confirmUnlinkBug)?>
id);?>
+pageID);?>
+recPerPage);?>
+recTotal);?>
session->productPlanList ? $this->session->productPlanList : inlink('browse', "planID=$plan->id");?>
diff --git a/module/project/control.php b/module/project/control.php
index 4e8a7a21a3..a1381d1292 100644
--- a/module/project/control.php
+++ b/module/project/control.php
@@ -690,6 +690,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';
diff --git a/module/story/model.php b/module/story/model.php
index 2dd1320525..31b418114d 100644
--- a/module/story/model.php
+++ b/module/story/model.php
@@ -229,6 +229,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;
@@ -410,6 +416,8 @@ class storyModel extends model
$data[$i] = $story;
}
+ $planStories = array();
+
foreach($data as $i => $story)
{
$this->dao->insert(TABLE_STORY)->data($story)->autoCheck()->exec();
@@ -422,6 +430,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;
@@ -472,6 +482,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)
{
@@ -881,6 +894,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.
*
@@ -2478,6 +2514,26 @@ class storyModel extends model
return $stories;
}
+ 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.
*
@@ -3631,4 +3687,34 @@ class storyModel extends model
return $relations;
}
+
+ /**
+ * sortPlanStory
+ *
+ * @param int $planStories
+ * @param string $order
+ * @param string $orderBy
+ * @access public
+ * @return void
+ */
+ public function sortPlanStory($planStories, $order = '', $orderBy = 'order_asc')
+ {
+ $stories = array();
+ if(!empty($order))
+ {
+ if(is_string($order)) $order = explode(',', $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;
+ }
+ return $stories;
+ }
}