@@ -256,6 +256,22 @@
{
$param = "executionID={$execution->id}&story={$story->id}&moduleID={$story->module}";
+ $story->reviewer = isset($story->reviewer) ? $story->reviewer : array();
+ $story->notReview = isset($story->notReview) ? $story->notReview : array();
+
+ if(common::hasPriv('story', 'review'))
+ {
+ $reviewDisabled = in_array($app->user->account, $story->notReview) and ($story->status == 'draft' or $story->status == 'changed') ? '' : 'disabled';
+ $story->from = 'execution';
+ common::printIcon('story', 'review', "story={$story->id}&from=story", $story, 'list', 'search', '', $reviewDisabled, false, "data-group=execution");
+ }
+
+ if(common::hasPriv('story', 'recall'))
+ {
+ $recallDisabled = empty($story->reviewedBy) and strpos('draft,changed', $story->status) !== false and !empty($story->reviewer) ? '' : 'disabled';
+ common::printIcon('story', 'recall', "story={$story->id}", $story, 'list', 'back', 'hiddenwin', $recallDisabled, '', '', $lang->story->recall);
+ }
+
$lang->task->create = $lang->execution->wbs;
$toTaskDisabled = strpos('draft,closed', $story->status) !== false ? 'disabled' : '';
if(commonModel::isTutorialMode())
diff --git a/module/my/lang/de.php b/module/my/lang/de.php
index b70fb5fe7c..b558580030 100644
--- a/module/my/lang/de.php
+++ b/module/my/lang/de.php
@@ -86,18 +86,21 @@ if($config->systemMode == 'new') $lang->my->executionLink = 'Execution Default P
$lang->my->programLinkList = array();
$lang->my->programLinkList['program-browse'] = 'By default, you go to the program list, where you can view all of the programs';
$lang->my->programLinkList['program-project'] = 'By default, you go to the list of items in the most recent program, and you can view all items under the current program';
+if($config->systemMode == 'new') $lang->my->programLinkList['program-kanban'] = 'Enter the Program Kanban by default, and check the progress of all Programs';
$lang->my->productLinkList = array();
$lang->my->productLinkList['product-index'] = 'The default access to the product home page, you can understand the company’s overall product status';
$lang->my->productLinkList['product-all'] = 'By default, you go to the product list, where you can view all the products';
$lang->my->productLinkList['product-dashboard'] = 'By default, go to the latest product dashboard to see the current product overview';
$lang->my->productLinkList['product-browse'] = 'By default, go to the list of requirements for the most recent product and see the requirements under the current product';
+$lang->my->productLinkList['product-kanban'] = 'Enter the Product Kanban by default, and check the progress of all Products';
global $config;
$lang->my->projectLinkList = array();
$lang->my->projectLinkList['project-browse'] = 'By default, you go to the project list, where you can view all the projects';
$lang->my->projectLinkList['project-execution'] = 'Go to Project-Exection by default. You can check all information in Execution';
$lang->my->projectLinkList['project-index'] = 'By default, go to the most recent project dashboard to see the current project overview';
+if($config->systemMode == 'new') $lang->my->projectLinkList['project-kanban'] = 'Enter the Project Kanban by default, and check the progress of all Projects';
$lang->my->executionLinkList = array();
if($config->systemMode == 'new')
diff --git a/module/my/lang/en.php b/module/my/lang/en.php
index 5795a6a935..97b83bca18 100644
--- a/module/my/lang/en.php
+++ b/module/my/lang/en.php
@@ -93,18 +93,21 @@ if($config->systemMode == 'new') $lang->my->executionLink = 'Execution Default P
$lang->my->programLinkList = array();
$lang->my->programLinkList['program-browse'] = 'By default, you go to the program list, where you can view all of the programs';
$lang->my->programLinkList['program-project'] = 'By default, you go to the list of items in the most recent program, and you can view all items under the current program';
+if($config->systemMode == 'new') $lang->my->programLinkList['program-kanban'] = 'Enter the Program Kanban by default, and check the progress of all Programs';
$lang->my->productLinkList = array();
$lang->my->productLinkList['product-index'] = 'The default access to the product home page, you can understand the company’s overall product status';
$lang->my->productLinkList['product-all'] = 'By default, you go to the product list, where you can view all the products';
$lang->my->productLinkList['product-dashboard'] = 'By default, go to the latest product dashboard to see the current product overview';
$lang->my->productLinkList['product-browse'] = 'By default, go to the list of requirements for the most recent product and see the requirements under the current product';
+$lang->my->productLinkList['product-kanban'] = 'Enter the Product Kanban by default, and check the progress of all Products';
global $config;
$lang->my->projectLinkList = array();
$lang->my->projectLinkList['project-browse'] = 'By default, you go to the project list, where you can view all the projects';
$lang->my->projectLinkList['project-execution'] = 'Go to Project-Exection by default. You can check all information in Execution';
$lang->my->projectLinkList['project-index'] = 'By default, go to the most recent project dashboard to see the current project overview';
+if($config->systemMode == 'new') $lang->my->projectLinkList['project-kanban'] = 'Enter the Project Kanban by default, and check the progress of all Projects';
$lang->my->executionLinkList = array();
if($config->systemMode == 'new')
diff --git a/module/my/lang/fr.php b/module/my/lang/fr.php
index b70fb5fe7c..b558580030 100644
--- a/module/my/lang/fr.php
+++ b/module/my/lang/fr.php
@@ -86,18 +86,21 @@ if($config->systemMode == 'new') $lang->my->executionLink = 'Execution Default P
$lang->my->programLinkList = array();
$lang->my->programLinkList['program-browse'] = 'By default, you go to the program list, where you can view all of the programs';
$lang->my->programLinkList['program-project'] = 'By default, you go to the list of items in the most recent program, and you can view all items under the current program';
+if($config->systemMode == 'new') $lang->my->programLinkList['program-kanban'] = 'Enter the Program Kanban by default, and check the progress of all Programs';
$lang->my->productLinkList = array();
$lang->my->productLinkList['product-index'] = 'The default access to the product home page, you can understand the company’s overall product status';
$lang->my->productLinkList['product-all'] = 'By default, you go to the product list, where you can view all the products';
$lang->my->productLinkList['product-dashboard'] = 'By default, go to the latest product dashboard to see the current product overview';
$lang->my->productLinkList['product-browse'] = 'By default, go to the list of requirements for the most recent product and see the requirements under the current product';
+$lang->my->productLinkList['product-kanban'] = 'Enter the Product Kanban by default, and check the progress of all Products';
global $config;
$lang->my->projectLinkList = array();
$lang->my->projectLinkList['project-browse'] = 'By default, you go to the project list, where you can view all the projects';
$lang->my->projectLinkList['project-execution'] = 'Go to Project-Exection by default. You can check all information in Execution';
$lang->my->projectLinkList['project-index'] = 'By default, go to the most recent project dashboard to see the current project overview';
+if($config->systemMode == 'new') $lang->my->projectLinkList['project-kanban'] = 'Enter the Project Kanban by default, and check the progress of all Projects';
$lang->my->executionLinkList = array();
if($config->systemMode == 'new')
diff --git a/module/my/lang/vi.php b/module/my/lang/vi.php
index b70fb5fe7c..b558580030 100644
--- a/module/my/lang/vi.php
+++ b/module/my/lang/vi.php
@@ -86,18 +86,21 @@ if($config->systemMode == 'new') $lang->my->executionLink = 'Execution Default P
$lang->my->programLinkList = array();
$lang->my->programLinkList['program-browse'] = 'By default, you go to the program list, where you can view all of the programs';
$lang->my->programLinkList['program-project'] = 'By default, you go to the list of items in the most recent program, and you can view all items under the current program';
+if($config->systemMode == 'new') $lang->my->programLinkList['program-kanban'] = 'Enter the Program Kanban by default, and check the progress of all Programs';
$lang->my->productLinkList = array();
$lang->my->productLinkList['product-index'] = 'The default access to the product home page, you can understand the company’s overall product status';
$lang->my->productLinkList['product-all'] = 'By default, you go to the product list, where you can view all the products';
$lang->my->productLinkList['product-dashboard'] = 'By default, go to the latest product dashboard to see the current product overview';
$lang->my->productLinkList['product-browse'] = 'By default, go to the list of requirements for the most recent product and see the requirements under the current product';
+$lang->my->productLinkList['product-kanban'] = 'Enter the Product Kanban by default, and check the progress of all Products';
global $config;
$lang->my->projectLinkList = array();
$lang->my->projectLinkList['project-browse'] = 'By default, you go to the project list, where you can view all the projects';
$lang->my->projectLinkList['project-execution'] = 'Go to Project-Exection by default. You can check all information in Execution';
$lang->my->projectLinkList['project-index'] = 'By default, go to the most recent project dashboard to see the current project overview';
+if($config->systemMode == 'new') $lang->my->projectLinkList['project-kanban'] = 'Enter the Project Kanban by default, and check the progress of all Projects';
$lang->my->executionLinkList = array();
if($config->systemMode == 'new')
diff --git a/module/my/lang/zh-cn.php b/module/my/lang/zh-cn.php
index 6fd0e3f26e..6eef0eb79e 100644
--- a/module/my/lang/zh-cn.php
+++ b/module/my/lang/zh-cn.php
@@ -93,18 +93,21 @@ if($config->systemMode == 'new') $lang->my->executionLink = '执行默认着陆
$lang->my->programLinkList = array();
$lang->my->programLinkList['program-browse'] = '默认进入项目集列表,可以查看所有的项目集';
$lang->my->programLinkList['program-project'] = '默认进入最近一个项目集的项目列表,可以查看当前项目集下所有项目';
+if($config->systemMode == 'new') $lang->my->programLinkList['program-kanban'] = '默认进入项目集看板,可以可视化的查看到所有项目集的进展情况';
$lang->my->productLinkList = array();
$lang->my->productLinkList['product-index'] = '默认进入产品主页,可以了解公司整体的产品状况';
$lang->my->productLinkList['product-all'] = '默认进入产品列表,可以查看所有的产品';
$lang->my->productLinkList['product-dashboard'] = '默认进入最近一个产品仪表盘,可以查看当前产品概况';
$lang->my->productLinkList['product-browse'] = '默认进入最近一个产品的需求列表,可以查看当前产品下的需求信息';
+$lang->my->productLinkList['product-kanban'] = '默认进入产品看板,可以可视化的查看到所有产品的进展情况';
global $config;
$lang->my->projectLinkList = array();
$lang->my->projectLinkList['project-browse'] = '默认进入项目列表,可以查看所有的项目';
$lang->my->projectLinkList['project-execution'] = '默认进入项目下所有执行列表,查看所有执行信息';
$lang->my->projectLinkList['project-index'] = '默认进入最近一个项目仪表盘,可以查看当前项目概况';
+if($config->systemMode == 'new') $lang->my->projectLinkList['project-kanban'] = '默认进入项目看板,可以可视化的查看到所有项目的进展情况';
$lang->my->executionLinkList = array();
if($config->systemMode == 'new')
diff --git a/module/my/lang/zh-tw.php b/module/my/lang/zh-tw.php
index c0b822232a..2eb7d3cded 100644
--- a/module/my/lang/zh-tw.php
+++ b/module/my/lang/zh-tw.php
@@ -93,18 +93,21 @@ if($config->systemMode == 'new') $lang->my->executionLink = '執行預設着陸
$lang->my->programLinkList = array();
$lang->my->programLinkList['program-browse'] = '預設進入項目集列表,可以查看所有的項目集';
$lang->my->programLinkList['program-project'] = '預設進入最近一個項目集的項目列表,可以查看當前項目集下所有項目';
+if($config->systemMode == 'new') $lang->my->programLinkList['program-kanban'] = '默認進入項目集看板,可以視覺化的查看到所有項目集的進展情况';
$lang->my->productLinkList = array();
$lang->my->productLinkList['product-index'] = '預設進入產品主頁,可以瞭解公司整體的產品狀況';
$lang->my->productLinkList['product-all'] = '預設進入產品列表,可以查看所有的產品';
$lang->my->productLinkList['product-dashboard'] = '預設進入最近一個產品儀表盤,可以查看當前產品概況';
$lang->my->productLinkList['product-browse'] = '預設進入最近一個產品的需求列表,可以查看當前產品下的需求信息';
+$lang->my->productLinkList['product-kanban'] = '默認進入產品看板,可以視覺化的查看到所有產品的進展情况';
global $config;
$lang->my->projectLinkList = array();
$lang->my->projectLinkList['project-browse'] = '預設進入項目列表,可以查看所有的項目';
$lang->my->projectLinkList['project-execution'] = '預設進入項目下所有執行列表,查看所有執行信息';
$lang->my->projectLinkList['project-index'] = '預設進入最近一個項目儀表盤,可以查看當前項目概況';
+if($config->systemMode == 'new') $lang->my->projectLinkList['project-kanban'] = '默認進入項目看板,可以視覺化的查看到所有項目的進展情况';
$lang->my->executionLinkList = array();
if($config->systemMode == 'new')
diff --git a/module/product/control.php b/module/product/control.php
index 58bdeeace2..ac802686b3 100644
--- a/module/product/control.php
+++ b/module/product/control.php
@@ -1159,31 +1159,25 @@ class product extends control
$kanbanGroup = $this->product->getStats4Kanban();
extract($kanbanGroup);
- $products = array();
$myProducts = array();
$otherProducts = array();
foreach($productList as $productID => $product)
{
- if($product->status == 'normal' and $product->PO == $this->app->user->account)
- {
- $myProducts[$product->program][$productID] = $productID;
- }
- elseif($product->status == 'normal' and !($product->PO == $this->app->user->account))
- {
- $otherProducts[$product->program][$productID] = $productID;
- }
+ if($product->status != 'normal') continue;
+ if($product->PO == $this->app->user->account) $myProducts[$product->program][] = $productID;
+ else $otherProducts[$product->program][] = $productID;
}
- $products['myProducts'] = $myProducts;
- $products['otherProducts'] = $otherProducts;
+ $kanbanList = array();
+ if(!empty($myProducts)) $kanbanList['my'] = $myProducts;
+ if(!empty($otherProducts)) $kanbanList['other'] = $otherProducts;
$this->view->title = $this->lang->product->kanban;
- $this->view->products = $products;
+ $this->view->kanbanList = $kanbanList;
$this->view->programList = array(0 => $this->lang->product->emptyProgram) + $programList;
$this->view->productList = $productList;
$this->view->planList = $planList;
$this->view->projectList = $projectList;
- $this->view->executionList = $executionList;
$this->view->projectProduct = $projectProduct;
$this->view->latestExecutions = $projectLatestExecutions;
$this->view->hourList = $hourList;
diff --git a/module/product/css/kanban.css b/module/product/css/kanban.css
index eba3633328..e69de29bb2 100644
--- a/module/product/css/kanban.css
+++ b/module/product/css/kanban.css
@@ -1,30 +0,0 @@
-#kanban {padding: 10px;}
-.table caption {background: #fff; border-top-left-radius: 2px; border-top-right-radius: 2px; margin-bottom: 0; font-weight: 500; padding-top: 0;}
-.table th {border: 2px solid #fff;}
-.table td {border-top: 5px solid #fff; border-bottom: 5px solid #fff; border-left: 2px solid #fff; border-right: 2px solid #fff;}
-.table tbody tr:last-child td {border-bottom: unset;}
-td.plan, td.release, td.project, td.execution, td.classicProject {vertical-align: top !important;}
-td.program {padding-top: 10px !important; padding-bottom: 10px !important;}
-.main-table tbody>tr>td:first-child, .main-table thead>tr>th:first-child {padding: 0 4px 10px 4px;}
-
-.main-table tbody>tr>td {padding: 0 10px 10px;}
-.table .program {writing-mode: vertical-lr; padding-left: 4px !important; color: #fff;}
-td.product {padding-top: 10px !important;}
-td.project, td.execution {padding: 0 0 10px 0 !important;}
-td > div:not(.board) > .board-item:first-child {margin-top: 10px;}
-td > div.board:first-child {margin-top: 5px;}
-.fix-table-copy-wrapper thead > tr > th:first-child {background: none!important;}
-
-.board-item {border: 1px solid #ebebeb; padding: 3px 10px; cursor: default; border-radius: 2px; background-color: #fff; text-align: left;}
-.board-item:hover {border-color: #ccc;}
-.board {padding: 0 10px;}
-.board + .board {margin-top: 5px;}
-.board-item + .board-item {margin-top: 10px;}
-.project .board, .execution .board {padding-top: 5px; border-top: 2px solid #fff;}
-.project .board:first-child, .execution .board:first-child {padding-top: 5px; border-top: unset;}
-.release .board-item {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center;}
-.emptyBoard {padding: 3px 10px; cursor: default;}
-
-.project .table-row > .table-col:last-child, .execution .table-row > .table-col:last-child, .classicProject .table-row > .table-col:last-child{width: 24px; padding-top: 2px;}
-
-.scroll {overflow-x: hidden; overflow-y: auto;}
diff --git a/module/product/js/kanban.js b/module/product/js/kanban.js
new file mode 100644
index 0000000000..5a2a2b5b40
--- /dev/null
+++ b/module/product/js/kanban.js
@@ -0,0 +1,108 @@
+/**
+ * Process kanban data
+ * @param {string} key Kanban key, used as kanban id
+ * @param {Object} programsData Programs data
+ * @returns {Object} kanban data
+ */
+function processKanbanData(key, programsData)
+{
+ var kanbanId = key;
+
+ /* Generate columns */
+ var columns = [];
+ $.each(kanbanColumns, function(_, column)
+ {
+ columns.push($.extend({}, column,
+ {
+ kanban: kanbanId,
+ id: kanbanId + '-' + column.type,
+ }));
+ });
+
+ /* Format lanes data */
+ var lanes = [];
+ $.each(programsData, function(programId, programProducts)
+ {
+ var programName = programList[programId];
+ var subLanes = [];
+ programProducts.forEach(function(productID)
+ {
+ var product = productList[productID];
+ var items = {};
+
+ /* unclosed products */
+ var productItem = {id: 'product-' + productID, _id: productID, name: product.name};
+ items.unclosedProduct = [productItem];
+
+ /* plans */
+ items.unexpiredPlan = [];
+ var plans = planList[productID];
+ if(plans)
+ {
+ $.each(plans, function(planID, plan)
+ {
+ items.unexpiredPlan.push($.extend({}, plan, {id: 'plan-' + planID, _id: planID}));
+ });
+ }
+
+ /* doing projects */
+ if(kanbanColumns.doingProject)
+ {
+ items.doingProject = [];
+ var productProjects = projectProduct[productID];
+ if(productProjects)
+ {
+ $.each(productProjects, function(projectID)
+ {
+ var project = projectList[projectID];
+ if(!project) return;
+ var projectItem = $.extend({}, project, {id: 'project-' + projectID, _id: projectID});
+ items.doingProject.push(projectItem);
+ });
+ }
+ }
+
+ /* doing execution */
+ items.doingExecution = [];
+ var productProjects = projectProduct[productID];
+ if(productProjects)
+ {
+ $.each(productProjects, function(projectID)
+ {
+ var execution = latestExecutions[projectID];
+ if(!execution) return;
+ var executionItem = $.extend({}, execution, {id: 'execution-' + execution.id, _id: execution.id});
+ items.doingExecution.push(executionItem);
+ });
+ }
+
+ /* normal release */
+ items.normalRelease = [];
+ var releases = releaseList[productID];
+ if(releases)
+ {
+ $.each(releases, function(releaseID, release)
+ {
+ if(!release) return;
+ var releaseItem = $.extend({}, release, {id: 'release-' + releaseID, _id: releaseID});
+ items.normalRelease.push(releaseItem);
+ });
+ }
+
+ subLanes.push({id: kanbanId + '-' + programId + '-' + productID, items: items});
+ });
+
+ lanes.push({id: programId, kanban: kanbanId, name: programName, subLanes: subLanes});
+ });
+
+ return {id: kanbanId, columns: columns, lanes: lanes};
+}
+
+$(function()
+{
+ /* Init all kanbans */
+ $.each(kanbanList, function(key, programsData)
+ {
+ $('#kanban-' + key).kanban({data: processKanbanData(key, programsData)});
+ });
+});
diff --git a/module/product/view/kanban.html.php b/module/product/view/kanban.html.php
index 7170d30f43..eb4591bc68 100644
--- a/module/product/view/kanban.html.php
+++ b/module/product/view/kanban.html.php
@@ -2,228 +2,64 @@
/**
* The html product kanban file of kanban method of product module of ZenTaoPMS.
*
- * @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
+ * @copyright Copyright 2021-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
- * @author Fangzhou Hu
+ * @author Hao Sun
* @package ZenTaoPMS
* @version $Id
*/
?>
-