diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index 1df83f794f..5e9a4885be 100755
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -123,7 +123,7 @@ $lang->common->common = '公有模块';
$lang->mainNav = new stdclass();
$lang->mainNav->my = ' 地盘|my|index|';
$lang->mainNav->program = ' 项目集|program|pgmindex|';
-$lang->mainNav->product = ' 产品|product|all|';
+$lang->mainNav->product = ' 产品|product|productlist|';
$lang->mainNav->project = ' 项目|program|prjbrowse|';
$lang->mainNav->system = ' 组织|custom|estimate|';
$lang->mainNav->admin = ' 后台|admin|index|';
diff --git a/module/product/control.php b/module/product/control.php
index 33600f8155..b25e469808 100644
--- a/module/product/control.php
+++ b/module/product/control.php
@@ -30,8 +30,8 @@ class product extends control
$this->loadModel('user');
/* Get all products, if no, goto the create page. */
- $this->products = $this->product->getPairs('nocode', $this->session->PRJ);
- if(empty($this->products) and strpos(',create,index,showerrornone,', $this->methodName) === false and $this->app->getViewType() != 'mhtml') $this->locate($this->createLink('product', 'create'));
+ $this->products = $this->product->getPairs('nocode', $this->session->program);
+ if(empty($this->products) and strpos(',productlist,create,index,showerrornone,', $this->methodName) === false and $this->app->getViewType() != 'mhtml') $this->locate($this->createLink('product', 'create'));
$this->view->products = $this->products;
}
@@ -871,4 +871,42 @@ class product extends control
$this->session->set('product', (int)$productID);
$this->send(array('result' => 'success', 'productID' => $this->session->product));
}
+
+ /**
+ * Products under project set.
+ *
+ * @param int $programID
+ * @param string $browseType
+ * @param int $param
+ * @param string $orderBy
+ * @param int $recTotal
+ * @param int $recPerPage
+ * @param int $pageID
+ * @access public
+ * @return void
+ */
+ public function productList($programID = 0, $browseType = 'all', $param = 0, $orderBy = 'order_desc', $recTotal = 0, $recPerPage = 15, $pageID = 1)
+ {
+ $this->session->set('program', $programID);
+ $this->loadModel('program');
+
+ /* Load pager and get tasks. */
+ $this->app->loadClass('pager', $static = true);
+ $pager = new pager($recTotal, $recPerPage, $pageID);
+
+ $program = $programID ? $this->program->getPGMByID($programID) : 0;
+
+ $this->view->title = $this->lang->product->common;
+ $this->view->position[] = $this->lang->product->common;
+
+ $this->view->productStats = $this->product->getStats($orderBy, $pager, $browseType);
+ $this->view->lines = array('') + $this->tree->getLinePairs();
+ $this->view->orderBy = $orderBy;
+ $this->view->pager = $pager;
+ $this->view->programTree = $this->program->getPGMTreeMenu($programID, true);
+ $this->view->programID = $programID;
+ $this->view->program = $program;
+ $this->view->browseType = $browseType;
+ $this->display();
+ }
}
diff --git a/module/product/css/productlist.css b/module/product/css/productlist.css
new file mode 100644
index 0000000000..eb3cf03202
--- /dev/null
+++ b/module/product/css/productlist.css
@@ -0,0 +1,35 @@
+.side-col .detail-content{padding-left: 10px; margin-top: 0px}
+.tree li.has-list.open:before {border-left: none;}
+#programTree li {padding: 0 0 0 8px;}
+#programTree li.has-list {padding-left: 20px;}
+#programTree li > a {display: block; padding: 5px 0; border-radius: 2px; padding-left: 6px; height: 30px;}
+#programTree li > a > span {display: inline-block;}
+#programTree li > a > span + span {margin-left: 8px;}
+#programTree li.selected > a {background-color: #E8F3FC;}
+#programTree li.selected > a > span.title {color: #006AF1;}
+#programTree .label-id {border-color: #cbd0db; color: #7d8599}
+#programTree .label.label-type {background: #fff; border: 1px solid #7d8599; color:#7d8599}
+
+#programTree li > a > span.title {color: #3C4353; white-space: nowrap; max-width: 60%; overflow: hidden; text-overflow: ellipsis; vertical-align: middle;}
+#programTree li > a > span.user {color: #838a9d;}
+#programTree li > a > span.user > .icon-person {font-size: 14px; position: relative; top: -1px; color: #a6aab8}
+
+#programTree li > .list-toggle {transform: rotate(0deg); width: 16px; height: 16px; border: 4px solid #a6aab8; border-radius: 2px; top: 7px;}
+#programTree li > .list-toggle:before {content: ' '; display: block; position: absolute; border: 1px solid #a6aab8; top: 2px; left: -3px; right: -3px; bottom: 2px; min-width: 0; transition: all .2s;}
+#programTree li > .list-toggle:hover:before,
+#programTree li > .list-toggle:hover {border-color: #006AF1;}
+#programTree li.open > .list-toggle {width: 12px; height: 12px; top: 9px; background-color: #a6aab8; border-width: 3px; left: 3px;}
+#programTree li.open > .list-toggle:before {border: none; height: 2px; width: 6px; left: 0; top: 2px; background: #fff;}
+#programTree li.open > .list-toggle:hover {background: #006AF1;}
+
+#programTree ul > li:after {display: block; position: absolute; content: ' '; border-top: 2px solid #cbd0db; top: 14px; left: -12px; z-index: 1; width: 10px;}
+#programTree ul > li:before,
+#programTree ul > li.has-list:before {background: none; content: ' '; display: block; position: absolute; width: auto; height: auto; border: none; border-left: 2px solid #cbd0db; top: -13px; bottom: 12px; left: -12px;}
+#programTree ul > li:last-child:before {bottom: auto; height: 29px;}
+#programTree ul > li:first-child:before {top: -9px;}
+#programTree ul > li.has-list:first-child:before {top: -13px;}
+#programTree ul > li.tree-single-item:before {height: 23px;}
+#programTree ul > li.has-list:after {width: 14px;}
+#programTree ul > li.item-meas a.selected{color: #0c64eb;}
+.side-col {padding-right: 20px; width: 18%}
+#sidebar>.cell {width: 100%;}
diff --git a/module/product/js/productlist.js b/module/product/js/productlist.js
new file mode 100644
index 0000000000..3fca145aad
--- /dev/null
+++ b/module/product/js/productlist.js
@@ -0,0 +1,13 @@
+$("#" + browseType + "Tab").addClass('btn-active-text');
+$('#programTree').tree();
+$('#program' + programID).addClass('active');
+$(".tree .active").parent('li').addClass('active');
+$(function()
+{
+ $('#productTableList').on('sort.sortable', function(e, data)
+ {
+ var list = '';
+ for(i = 0; i < data.list.length; i++) list += $(data.list[i].item).attr('data-id') + ',';
+ $.post(createLink('product', 'updateOrder'), {'products' : list, 'orderBy' : orderBy});
+ });
+});
diff --git a/module/product/lang/zh-cn.php b/module/product/lang/zh-cn.php
index 5d55d37cd4..007cecde83 100644
--- a/module/product/lang/zh-cn.php
+++ b/module/product/lang/zh-cn.php
@@ -30,8 +30,6 @@ $lang->product->orderAction = "{$lang->productCommon}排序";
$lang->product->all = "所有{$lang->productCommon}";
$lang->product->export = '导出数据';
$lang->product->exportAction = "导出{$lang->productCommon}";
-$lang->product->stack = '项目集';
-$lang->product->createstack = '创建项目集';
$lang->product->basicInfo = '基本信息';
$lang->product->otherInfo = '其他信息';
diff --git a/module/product/model.php b/module/product/model.php
index 5fe566e874..d3a0eb1e7e 100644
--- a/module/product/model.php
+++ b/module/product/model.php
@@ -912,7 +912,7 @@ class productModel extends model
$this->loadModel('story');
$this->loadModel('bug');
- $products = $this->getList($this->session->PRJ, $status, $limit = 0, $line);
+ $products = $this->getList($this->session->program, $status, $limit = 0, $line);
$products = $this->dao->select('*')->from(TABLE_PRODUCT)
->where('id')->in(array_keys($products))
->orderBy($orderBy)
@@ -965,6 +965,7 @@ class productModel extends model
->andWhere('product')->in(array_keys($products))
->groupBy('product')
->fetchPairs();
+
$unResolved = $this->dao->select('product,count(*) AS count')
->from(TABLE_BUG)
->where('deleted')->eq(0)
@@ -972,6 +973,7 @@ class productModel extends model
->andWhere('product')->in(array_keys($products))
->groupBy('product')
->fetchPairs();
+
$assignToNull = $this->dao->select('product,count(*) AS count')
->from(TABLE_BUG)
->where('deleted')->eq(0)
diff --git a/module/product/view/productlist.html.php b/module/product/view/productlist.html.php
new file mode 100644
index 0000000000..38fb270506
--- /dev/null
+++ b/module/product/view/productlist.html.php
@@ -0,0 +1,112 @@
+
+ * @package ZenTaoPMS
+ * @version $Id
+ */
+?>
+
+
+
+
+
+ product->featureBar['all'] as $key => $label):?>
+ {$label}", '', "class='btn btn-link' id='{$key}Tab'");?>
+
+
+
+ ' . $lang->product->create, '', 'class="btn btn-primary"');?>
+
+
+
+
+
+
+
diff --git a/module/program/model.php b/module/program/model.php
index 931e5b95dd..19eb2ded78 100644
--- a/module/program/model.php
+++ b/module/program/model.php
@@ -712,11 +712,12 @@ class programModel extends model
/**
* Get the treemenu of program.
*
- * @param int $programID
+ * @param int $programID
+ * @param int $productList
* @access public
* @return string
*/
- public function getPGMTreeMenu($programID = 0)
+ public function getPGMTreeMenu($programID = 0, $productList = false)
{
$programMenu = array();
$query = $this->dao->select('*')->from(TABLE_PROJECT)
@@ -727,7 +728,9 @@ class programModel extends model
while($program = $stmt->fetch())
{
- $linkHtml = html::a(helper::createLink('program', 'pgmview', "programID=$program->id", '', '', $program->id), " " . $program->name);
+ $link = helper::createLink('program', 'pgmview', "programID=$program->id", '', '', $program->id);
+ if($productList) $link = helper::createLink('product', 'productlist', "programID=$program->id", '', '', $program->id);
+ $linkHtml = html::a($link, " " . $program->name, '', "id='program$program->id'");
if(isset($programMenu[$program->id]) and !empty($programMenu[$program->id]))
{
@@ -1084,7 +1087,8 @@ class programModel extends model
if($program) $path = $program->path;
return $this->dao->select('*')->from(TABLE_PROJECT)
- ->beginIF($projectID > 0)->where('path')->like($path . '%')->fi()
+ ->where('type')->in('project,program')
+ ->beginIF($projectID > 0)->andWhere('path')->like($path . '%')->fi()
->orderBy('grade desc, `order`')
->get();
}