diff --git a/config/config.php b/config/config.php index f8a7993985..fef6e3bc31 100644 --- a/config/config.php +++ b/config/config.php @@ -130,6 +130,7 @@ define('TABLE_TESTRESULT', '`' . $config->db->prefix . 'testresult`'); define('TABLE_USERTPL', '`' . $config->db->prefix . 'usertpl`'); define('TABLE_PRODUCT', '`' . $config->db->prefix . 'product`'); +define('TABLE_BRANCH', '`' . $config->db->prefix . 'branch`'); define('TABLE_STORY', '`' . $config->db->prefix . 'story`'); define('TABLE_STORYSPEC', '`' . $config->db->prefix . 'storyspec`'); define('TABLE_PRODUCTPLAN', '`' . $config->db->prefix . 'productplan`'); diff --git a/db/update7.3.sql b/db/update7.3.sql index e99585ea65..9c80ac0ff4 100644 --- a/db/update7.3.sql +++ b/db/update7.3.sql @@ -1,3 +1,20 @@ ALTER TABLE `zt_action` CHANGE `extra` `extra` text COLLATE 'utf8_general_ci' NOT NULL AFTER `comment`; ALTER TABLE `zt_release` ADD `leftBugs` text COLLATE 'utf8_general_ci' NOT NULL AFTER `bugs`; ALTER TABLE `zt_release` ADD `status` varchar(20) COLLATE 'utf8_general_ci' NOT NULL DEFAULT 'normal' AFTER `desc`; +ALTER TABLE `zt_product` ADD `type` varchar(30) COLLATE 'utf8_general_ci' NOT NULL DEFAULT 'normal' AFTER `code`; + +ALTER TABLE `zt_projectproduct` ADD `branch` mediumint(8) unsigned NOT NULL; +ALTER TABLE `zt_productplan` ADD `branch` mediumint(8) unsigned NOT NULL AFTER `product`; +ALTER TABLE `zt_build` ADD `branch` mediumint(8) unsigned NOT NULL AFTER `product`; +ALTER TABLE `zt_release` ADD `branch` mediumint(8) unsigned NOT NULL AFTER `product`; +ALTER TABLE `zt_bug` ADD `branch` mediumint(8) unsigned NOT NULL AFTER `product`; +ALTER TABLE `zt_case` ADD `branch` mediumint(8) unsigned NOT NULL AFTER `product`; +ALTER TABLE `zt_module` ADD `branch` varchar(50) COLLATE 'utf8_general_ci' unsigned NOT NULL AFTER `root`; +ALTER TABLE `zt_story` ADD `branch` varchar(50) COLLATE 'utf8_general_ci' NOT NULL AFTER `product`; + +CREATE TABLE `zt_branch` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, + `product` mediumint unsigned NOT NULL, + `name` varchar(255) COLLATE 'utf8_general_ci' NOT NULL, + `deleted` enum('0','1') COLLATE 'utf8_general_ci' NOT NULL DEFAULT '0' +); diff --git a/module/branch/control.php b/module/branch/control.php new file mode 100644 index 0000000000..243754caae --- /dev/null +++ b/module/branch/control.php @@ -0,0 +1,51 @@ + + * @package branch + * @version $Id$ + * @link http://www.zentao.net + */ +class branch extends control +{ + public function manage($productID) + { + if($_POST) + { + $this->branch->manage($productID); + die(js::reload('parent')); + } + $this->view->title = $this->lang->branch->manage; + $this->view->position[] = $this->lang->branch->manage; + + $this->loadModel('product')->setMenu($this->product->getPairs('nocode'), $productID); + + $this->view->product = $this->product->getById($productID); + $this->view->branches = $this->branch->getPairs($productID, 'noempty'); + $this->display(); + } + + public function ajaxGetDropMenu($productID, $module, $method, $extra) + { + $this->view->link = $this->loadModel('product')->getProductLink($module, $method, $extra, true); + $this->view->productID = $productID; + $this->view->module = $module; + $this->view->method = $method; + $this->view->extra = $extra; + $this->view->branches = $this->branch->getPairs($productID); + $this->display(); + } + + public function ajaxGetMatchedItems($keywords, $module, $method, $extra, $objectID) + { + $this->view->link = $this->loadModel('product')->getProductLink($module, $method, $extra, true); + $this->view->branches = $this->dao->select('*')->from(TABLE_BRANCH)->where('deleted')->eq(0)->andWhere('product')->eq($objectID)->andWhere('name')->like("%$keywords%")->orderBy('id desc')->fetchPairs('id', 'name'); + $this->view->productID = $objectID; + $this->view->keywords = $keywords; + $this->display(); + } +} + diff --git a/module/branch/lang/zh-cn.php b/module/branch/lang/zh-cn.php new file mode 100644 index 0000000000..180dd612a0 --- /dev/null +++ b/module/branch/lang/zh-cn.php @@ -0,0 +1,4 @@ +branch->manage = '分支管理'; + +$lang->branch->all = '所有'; diff --git a/module/branch/model.php b/module/branch/model.php new file mode 100644 index 0000000000..08d6c74f04 --- /dev/null +++ b/module/branch/model.php @@ -0,0 +1,41 @@ + + * @package branch + * @version $Id$ + * @link http://www.zentao.net + */ +class branchModel extends model +{ + public function getPairs($productID, $params = '') + { + $branches = $this->dao->select('*')->from(TABLE_BRANCH)->where('product')->eq($productID)->andWhere('deleted')->eq(0)->orderBy('id_desc')->fetchPairs('id', 'name'); + if(strpos($params, 'noempty') === false) $branches = array('0' => $this->lang->branch->all) + $branches; + return $branches; + } + + public function manage($productID) + { + $oldBranches = $this->getPairs($productID, 'noempty'); + $data = fixer::input('post')->get(); + if(isset($data->branch)) + { + foreach($data->branch as $branchID => $branch) + { + if($oldBranches[$branchID] != $branch) $this->dao->update(TABLE_BRANCH)->set('name')->eq($branch)->where('id')->eq($branchID)->exec(); + } + } + foreach($data->newbranch as $branch) + { + if(empty($branch)) continue; + $this->dao->insert(TABLE_BRANCH)->set('name')->eq($branch)->set('product')->eq($productID)->exec(); + } + + return dao::isError(); + } +} + diff --git a/module/branch/view/ajaxgetdropmenu.html.php b/module/branch/view/ajaxgetdropmenu.html.php new file mode 100644 index 0000000000..8a270cd345 --- /dev/null +++ b/module/branch/view/ajaxgetdropmenu.html.php @@ -0,0 +1,17 @@ + + + + +search->common;?>'/> +
+
+ +
+
diff --git a/module/branch/view/ajaxgetmatcheditems.html.php b/module/branch/view/ajaxgetmatcheditems.html.php new file mode 100644 index 0000000000..e35a6c00ab --- /dev/null +++ b/module/branch/view/ajaxgetmatcheditems.html.php @@ -0,0 +1,11 @@ +
+ +
diff --git a/module/branch/view/manage.html.php b/module/branch/view/manage.html.php new file mode 100644 index 0000000000..da4dc294eb --- /dev/null +++ b/module/branch/view/manage.html.php @@ -0,0 +1,42 @@ + + * @package branch + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+
+
branch->manage?>
+
+
+ + $branch):?> + + + + + + + + + + + + + + + + + +
+
+
+ + diff --git a/module/common/lang/menuOrder.php b/module/common/lang/menuOrder.php index c9c0088771..b263388432 100644 --- a/module/common/lang/menuOrder.php +++ b/module/common/lang/menuOrder.php @@ -35,11 +35,12 @@ $lang->product->menuOrder[20] = 'release'; $lang->product->menuOrder[25] = 'roadmap'; $lang->product->menuOrder[30] = 'doc'; $lang->product->menuOrder[35] = 'project'; -$lang->product->menuOrder[40] = 'module'; -$lang->product->menuOrder[45] = 'view'; -$lang->product->menuOrder[50] = 'order'; -$lang->product->menuOrder[55] = 'create'; -$lang->product->menuOrder[60] = 'all'; +$lang->product->menuOrder[40] = 'branch'; +$lang->product->menuOrder[45] = 'module'; +$lang->product->menuOrder[50] = 'view'; +$lang->product->menuOrder[55] = 'order'; +$lang->product->menuOrder[60] = 'create'; +$lang->product->menuOrder[65] = 'all'; $lang->story->menuOrder = $lang->product->menuOrder; $lang->productplan->menuOrder = $lang->product->menuOrder; $lang->release->menuOrder = $lang->product->menuOrder; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index af76deac50..1916a19737 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -177,6 +177,7 @@ $lang->product->menu->plan = array('link' => '计划|productplan|browse|produ $lang->product->menu->release = array('link' => '发布|release|browse|productID=%s', 'subModule' => 'release'); $lang->product->menu->roadmap = '路线图|product|roadmap|productID=%s'; $lang->product->menu->doc = array('link' => '文档|product|doc|productID=%s', 'subModule' => 'doc'); +$lang->product->menu->branch = '分支|branch|manage|productID=%s'; $lang->product->menu->module = '模块|tree|browse|productID=%s&view=story'; $lang->product->menu->view = array('link' => '概况|product|view|productID=%s', 'alias' => 'edit'); $lang->product->menu->project = "{$lang->projectCommon}|product|project|status=all&productID=%s"; @@ -186,7 +187,9 @@ $lang->product->menu->all = array('link' => "  $lang->story = new stdclass(); $lang->productplan = new stdclass(); $lang->release = new stdclass(); +$lang->branch = new stdclass(); +$lang->branch->menu = $lang->product->menu; $lang->story->menu = $lang->product->menu; $lang->productplan->menu = $lang->product->menu; $lang->release->menu = $lang->product->menu; diff --git a/module/product/control.php b/module/product/control.php index eddbee8c29..f63e692f93 100644 --- a/module/product/control.php +++ b/module/product/control.php @@ -79,9 +79,9 @@ class product extends control * @access public * @return void */ - public function project($status = 'all', $productID = 0) + public function project($status = 'all', $productID = 0, $branch = 0) { - $this->product->setMenu($this->products, $productID); + $this->product->setMenu($this->products, $productID, $branch); $this->app->loadLang('my'); $this->view->projectStats = $this->loadModel('project')->getProjectStats($status, $productID); @@ -106,7 +106,7 @@ class product extends control * @access public * @return void */ - public function browse($productID = 0, $browseType = 'unclosed', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1) + public function browse($productID = 0, $branch = 0, $browseType = 'unclosed', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1) { /* Lower browse type. */ $browseType = strtolower($browseType); @@ -117,11 +117,12 @@ class product extends control /* Set product, module and query. */ $productID = $this->product->saveState($productID, $this->products); + if(empty($branch)) $branch = $this->session->branch; $moduleID = ($browseType == 'bymodule') ? (int)$param : 0; $queryID = ($browseType == 'bysearch') ? (int)$param : 0; /* Set menu. */ - $this->product->setMenu($this->products, $productID); + $this->product->setMenu($this->products, $productID, $branch); /* Process the order by field. */ if(!$orderBy) $orderBy = $this->cookie->productStoryOrder ? $this->cookie->productStoryOrder : 'id_desc'; @@ -146,26 +147,26 @@ class product extends control { $unclosedStatus = $this->lang->story->statusList; unset($unclosedStatus['closed']); - $stories = $this->story->getProductStories($productID, 0, array_keys($unclosedStatus), $sort, $pager); + $stories = $this->story->getProductStories($productID, $branch, 0, array_keys($unclosedStatus), $sort, $pager); } - if($browseType == 'allstory') $stories = $this->story->getProductStories($productID, 0, 'all', $sort, $pager); - if($browseType == 'bymodule') $stories = $this->story->getProductStories($productID, $this->tree->getAllChildID($moduleID), 'all', $sort, $pager); + if($browseType == 'allstory') $stories = $this->story->getProductStories($productID, $branch, 0, 'all', $sort, $pager); + if($browseType == 'bymodule') $stories = $this->story->getProductStories($productID, $branch, $this->tree->getAllChildID($moduleID), 'all', $sort, $pager); if($browseType == 'bysearch') $stories = $this->story->getBySearch($productID, $queryID, $sort, $pager); - if($browseType == 'assignedtome')$stories = $this->story->getByAssignedTo($productID, $this->app->user->account, $sort, $pager); - if($browseType == 'openedbyme') $stories = $this->story->getByOpenedBy($productID, $this->app->user->account, $sort, $pager); - if($browseType == 'reviewedbyme')$stories = $this->story->getByReviewedBy($productID, $this->app->user->account, $sort, $pager); - if($browseType == 'closedbyme') $stories = $this->story->getByClosedBy($productID, $this->app->user->account, $sort, $pager); - if($browseType == 'draftstory') $stories = $this->story->getByStatus($productID, 'draft', $sort, $pager); - if($browseType == 'activestory') $stories = $this->story->getByStatus($productID, 'active', $sort, $pager); - if($browseType == 'changedstory')$stories = $this->story->getByStatus($productID, 'changed', $sort, $pager); - if($browseType == 'willclose') $stories = $this->story->getWillClose($productID, $sort, $pager); - if($browseType == 'closedstory') $stories = $this->story->getByStatus($productID, 'closed', $sort, $pager); + if($browseType == 'assignedtome')$stories = $this->story->getByAssignedTo($productID, $branch, $this->app->user->account, $sort, $pager); + if($browseType == 'openedbyme') $stories = $this->story->getByOpenedBy($productID, $branch, $this->app->user->account, $sort, $pager); + if($browseType == 'reviewedbyme')$stories = $this->story->getByReviewedBy($productID, $branch, $this->app->user->account, $sort, $pager); + if($browseType == 'closedbyme') $stories = $this->story->getByClosedBy($productID, $branch, $this->app->user->account, $sort, $pager); + if($browseType == 'draftstory') $stories = $this->story->getByStatus($productID, $branch, 'draft', $sort, $pager); + if($browseType == 'activestory') $stories = $this->story->getByStatus($productID, $branch, 'active', $sort, $pager); + if($browseType == 'changedstory')$stories = $this->story->getByStatus($productID, $branch, 'changed', $sort, $pager); + if($browseType == 'willclose') $stories = $this->story->getWillClose($productID, $branch, $sort, $pager); + if($browseType == 'closedstory') $stories = $this->story->getByStatus($productID, $branch, 'closed', $sort, $pager); /* Process the sql, get the conditon partion, save it to session. */ $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); /* Build search form. */ - $this->config->product->search['actionURL'] = $this->createLink('product', 'browse', "productID=$productID&browseType=bySearch&queryID=myQueryID"); + $this->config->product->search['actionURL'] = $this->createLink('product', 'browse', "productID=$productID&branch=$branch&browseType=bySearch&queryID=myQueryID"); $this->config->product->search['queryID'] = $queryID; $this->config->product->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs($productID); $this->config->product->search['params']['product']['values'] = array($productID => $this->products[$productID], 'all' => $this->lang->product->allProduct); @@ -185,6 +186,7 @@ class product extends control $this->view->orderBy = $orderBy; $this->view->browseType = $browseType; $this->view->moduleID = $moduleID; + $this->view->branch = $branch; $this->display(); } diff --git a/module/product/lang/zh-cn.php b/module/product/lang/zh-cn.php index 2e93bad680..82a375b6c3 100644 --- a/module/product/lang/zh-cn.php +++ b/module/product/lang/zh-cn.php @@ -58,6 +58,7 @@ $lang->product->company = '所属公司'; $lang->product->name = "{$lang->productCommon}名称"; $lang->product->code = "{$lang->productCommon}代号"; $lang->product->order = '排序'; +$lang->product->type = "{$lang->productCommon}类型"; $lang->product->status = '状态'; $lang->product->desc = "{$lang->productCommon}描述"; $lang->product->PO = "{$lang->productCommon}负责人"; @@ -83,6 +84,11 @@ $lang->product->allStory = '全部需求'; $lang->product->allProduct = '全部' . $lang->productCommon; $lang->product->allProductsOfProject = '全部关联' . $lang->productCommon; +$lang->product->typeList[''] = ''; +$lang->product->typeList['normal'] = '正常'; +$lang->product->typeList['branch'] = '多分支'; +$lang->product->typeList['platform'] = '多平台'; + $lang->product->statusList[''] = ''; $lang->product->statusList['normal'] = '正常'; $lang->product->statusList['closed'] = '结束'; diff --git a/module/product/model.php b/module/product/model.php index d2b851e951..aee245a32c 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -22,7 +22,7 @@ class productModel extends model * @access public * @return void */ - public function setMenu($products, $productID, $extra = '') + public function setMenu($products, $productID, $branch = '', $extra = '') { /* Has access privilege?. */ if($products and !isset($products[$productID]) and !$this->checkPriv($this->getById($productID))) @@ -38,7 +38,7 @@ class productModel extends model if($currentModule == 'story' and $currentMethod != 'create' and $currentMethod != 'batchcreate') $currentModule = 'product'; if($currentMethod == 'report') $currentMethod = 'browse'; - $selectHtml = $this->select($products, $productID, $currentModule, $currentMethod, $extra); + $selectHtml = $this->select($products, $productID, $currentModule, $currentMethod, $extra, $branch); foreach($this->lang->product->menu as $key => $menu) { $replace = $key == 'list' ? $selectHtml : $productID; @@ -57,13 +57,21 @@ class productModel extends model * @access public * @return string */ - public function select($products, $productID, $currentModule, $currentMethod, $extra = '') + public function select($products, $productID, $currentModule, $currentMethod, $extra = '', $branch = '') { if(!$productID) return; setCookie("lastProduct", $productID, $this->config->cookieLife, $this->config->webRoot); + setCookie("lastBranch", $branch, $this->config->cookieLife, $this->config->webRoot); $currentProduct = $this->getById($productID); - $output = "{$currentProduct->name}
"; + $output = "{$currentProduct->name}
"; + if($currentProduct->type != 'normal') + { + $branches = $this->loadModel('branch')->getPairs($productID); + $branchName = isset($branches[$branch]) ? $branches[$branch] : $branches[0]; + $output .= '
  • '; + $output .= "{$branchName}
    "; + } return $output; } @@ -80,6 +88,7 @@ class productModel extends model if($productID > 0) $this->session->set('product', (int)$productID); if($productID == 0 and $this->cookie->lastProduct) $this->session->set('product', (int)$this->cookie->lastProduct); if($productID == 0 and $this->session->product == '') $this->session->set('product', key($products)); + if($this->cookie->lastBranch) $this->session->set('branch', (int)$this->cookie->lastBranch); if(!isset($products[$this->session->product])) $this->session->set('product', key($products)); return $this->session->product; } @@ -662,19 +671,23 @@ class productModel extends model * @access public * @return void */ - public function getProductLink($module, $method, $extra) + public function getProductLink($module, $method, $extra, $branch = false) { $link = ''; if(strpos('product,roadmap,bug,testcase,testtask,story', $module) !== false) { if($module == 'product' && $method == 'project') { - $link = helper::createLink($module, $method, "status=all&productID=%s"); + $link = helper::createLink($module, $method, "status=all&productID=%s" . ($branch ? "&branch=%s" : '')); } elseif($module == 'product' && $method == 'index') { $link = helper::createLink($module, $method, "locate=no&productID=%s"); } + elseif($module == 'product' && $method == 'browse') + { + $link = helper::createLink($module, $method, "productID=%s" . ($branch ? "&branch=%s" : '')); + } else { $link = helper::createLink($module, $method, "productID=%s"); @@ -683,11 +696,11 @@ class productModel extends model else if($module == 'productplan' || $module == 'release') { if($method != 'browse' && $method != 'create') $method = 'browse'; - $link = helper::createLink($module, $method, "productID=%s"); + $link = helper::createLink($module, $method, "productID=%s" . ($branch ? "&branch=%s" : '')); } else if($module == 'tree') { - $link = helper::createLink($module, $method, "productID=%s&type=$extra"); + $link = helper::createLink($module, $method, "productID=%s&type=$extra" . ($branch ? "&branch=%s" : '')); } return $link; } diff --git a/module/product/view/browse.html.php b/module/product/view/browse.html.php index 2be2cb6fff..85210b309e 100644 --- a/module/product/view/browse.html.php +++ b/module/product/view/browse.html.php @@ -15,17 +15,17 @@
    @@ -74,7 +74,7 @@ - recTotal}&recPerPage={$pager->recPerPage}";?> + recTotal}&recPerPage={$pager->recPerPage}";?> diff --git a/module/product/view/create.html.php b/module/product/view/create.html.php index 04cb35cbfe..59dc8c93da 100644 --- a/module/product/view/create.html.php +++ b/module/product/view/create.html.php @@ -41,6 +41,10 @@ + + + + diff --git a/module/product/view/edit.html.php b/module/product/view/edit.html.php index 201494a4bf..d665866660 100644 --- a/module/product/view/edit.html.php +++ b/module/product/view/edit.html.php @@ -42,6 +42,10 @@ + + + + diff --git a/module/product/view/view.html.php b/module/product/view/view.html.php index ca66c7814c..21a25cfe5f 100644 --- a/module/product/view/view.html.php +++ b/module/product/view/view.html.php @@ -81,6 +81,10 @@ + + + + diff --git a/module/productplan/control.php b/module/productplan/control.php index 1fe52294b5..4f0b3a7115 100644 --- a/module/productplan/control.php +++ b/module/productplan/control.php @@ -290,7 +290,7 @@ class productplan extends control } else { - $allStories = $this->story->getProductStories($this->view->product->id, $moduleID = '0', $status = 'draft,active,changed'); + $allStories = $this->story->getProductStories($this->view->product->id, $plan->branch, $moduleID = '0', $status = 'draft,active,changed'); } $this->view->allStories = $allStories; diff --git a/module/project/model.php b/module/project/model.php index a5b16ad328..fb7d5ed343 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -551,7 +551,7 @@ class projectModel extends model * @access public * @return array */ - public function getList($status = 'all', $limit = 0, $productID = 0) + public function getList($status = 'all', $limit = 0, $productID = 0, $branch = 0) { if($productID != 0) { @@ -563,6 +563,7 @@ class projectModel extends model ->andWhere('t2.deleted')->eq(0) ->andWhere('t2.iscat')->eq(0) ->beginIF($status == 'undone')->andWhere('t2.status')->ne('done')->fi() + ->beginIF($branch != 0)->andWhere('t1.branch')->like(",$branch,")->fi() ->beginIF($status == 'isdoing')->andWhere('t2.status')->ne('done')->andWhere('t2.status')->ne('suspended')->fi() ->beginIF($status != 'all' and $status != 'isdoing' and $status != 'undone')->andWhere('status')->in($status)->fi() ->orderBy('order_desc') @@ -630,10 +631,10 @@ class projectModel extends model * @access public * @return void */ - public function getProjectStats($status = 'undone', $productID = 0, $itemCounts = 30, $orderBy = 'order_desc', $pager = null) + public function getProjectStats($status = 'undone', $productID = 0, $branch, $itemCounts = 30, $orderBy = 'order_desc', $pager = null) { /* Init vars. */ - $projects = $this->getList($status, 0, $productID); + $projects = $this->getList($status, 0, $productID, $branch); foreach($projects as $projectID => $project) { if(!$this->checkPriv($project)) unset($projects[$projectID]); diff --git a/module/story/model.php b/module/story/model.php index 771b3467eb..1f8502f1e1 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -926,14 +926,15 @@ class storyModel extends model * @access public * @return array */ - public function getProductStories($productID = 0, $moduleIds = 0, $status = 'all', $orderBy = 'id_desc', $pager = null) + public function getProductStories($productID = 0, $branch = 0, $moduleIds = 0, $status = 'all', $orderBy = 'id_desc', $pager = null) { return $this->dao->select('t1.*, t2.title as planTitle') ->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id') ->where('t1.product')->in($productID) - ->beginIF(!empty($moduleIds))->andWhere('module')->in($moduleIds)->fi() - ->beginIF($status and $status != 'all')->andWhere('status')->in($status)->fi() + ->beginIF(!empty($branch))->andWhere("CONCAT(',', t1.branch, ',')")->like("%,$branch,%")->fi() + ->beginIF(!empty($moduleIds))->andWhere('t1.module')->in($moduleIds)->fi() + ->beginIF($status and $status != 'all')->andWhere('t1.status')->in($status)->fi() ->andWhere('t1.deleted')->eq(0) ->orderBy($orderBy)->page($pager)->fetchAll(); } @@ -974,9 +975,9 @@ class storyModel extends model * @access public * @return array */ - public function getByAssignedTo($productID, $account, $orderBy, $pager) + public function getByAssignedTo($productID, $branch, $account, $orderBy, $pager) { - return $this->getByField($productID, 'assignedTo', $account, $orderBy, $pager); + return $this->getByField($productID, $branch, 'assignedTo', $account, $orderBy, $pager); } /** @@ -989,9 +990,9 @@ class storyModel extends model * @access public * @return array */ - public function getByOpenedBy($productID, $account, $orderBy, $pager) + public function getByOpenedBy($productID, $branch, $account, $orderBy, $pager) { - return $this->getByField($productID, 'openedBy', $account, $orderBy, $pager); + return $this->getByField($productID, $branch, 'openedBy', $account, $orderBy, $pager); } /** @@ -1004,9 +1005,9 @@ class storyModel extends model * @access public * @return array */ - public function getByReviewedBy($productID, $account, $orderBy, $pager) + public function getByReviewedBy($productID, $branch, $account, $orderBy, $pager) { - return $this->getByField($productID, 'reviewedBy', $account, $orderBy, $pager, 'include'); + return $this->getByField($productID, $branch, 'reviewedBy', $account, $orderBy, $pager, 'include'); } /** @@ -1018,9 +1019,9 @@ class storyModel extends model * @param object $pager * @return array */ - public function getByClosedBy($productID, $account, $orderBy, $pager) + public function getByClosedBy($productID, $branch, $account, $orderBy, $pager) { - return $this->getByField($productID, 'closedBy', $account, $orderBy, $pager); + return $this->getByField($productID, $branch, 'closedBy', $account, $orderBy, $pager); } /** @@ -1033,9 +1034,9 @@ class storyModel extends model * @access public * @return array */ - public function getByStatus($productID, $status, $orderBy, $pager) + public function getByStatus($productID, $branch, $status, $orderBy, $pager) { - return $this->getByField($productID, 'status', $status, $orderBy, $pager); + return $this->getByField($productID, $branch, 'status', $status, $orderBy, $pager); } /** @@ -1050,13 +1051,14 @@ class storyModel extends model * @access public * @return array */ - public function getByField($productID, $fieldName, $fieldValue, $orderBy, $pager, $operator = 'equal') + public function getByField($productID, $branch, $fieldName, $fieldValue, $orderBy, $pager, $operator = 'equal') { return $this->dao->select('t1.*, t2.title as planTitle') ->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id') ->where('t1.product')->in($productID) ->andWhere('t1.deleted')->eq(0) + ->beginIF(!empty($branch))->andWhere("CONCAT(',', t1.branch, ',')")->like("%,$branch,%")->fi() ->beginIF($operator == 'equal')->andWhere($fieldName)->eq($fieldValue)->fi() ->beginIF($operator == 'include')->andWhere($fieldName)->like("%$fieldValue%")->fi() ->orderBy($orderBy) @@ -1073,7 +1075,7 @@ class storyModel extends model * @access public * @return array */ - public function getWillClose($productID, $orderBy, $pager) + public function getWillClose($productID, $branch, $orderBy, $pager) { return $this->dao->select('t1.*, t2.title as planTitle') ->from(TABLE_STORY)->alias('t1') @@ -1099,7 +1101,7 @@ class storyModel extends model * @access public * @return array */ - public function getBySearch($productID, $queryID, $orderBy, $pager = null, $projectID = '') + public function getBySearch($productID, $branch, $queryID, $orderBy, $pager = null, $projectID = '') { if($projectID != '') { @@ -1367,7 +1369,7 @@ class storyModel extends model */ public function getZeroCase($productID, $orderBy = 'id_desc') { - $allStories = $this->getProductStories($productID, 0, 'all', $orderBy); + $allStories = $this->getProductStories($productID, 0, 0, 'all', $orderBy); $casedStories = $this->dao->select('DISTINCT story')->from(TABLE_CASE)->where('product')->eq($productID)->andWhere('story')->ne(0)->andWhere('deleted')->eq(0)->fetchAll('story'); foreach($allStories as $key => $story) diff --git a/www/js/my.full.js b/www/js/my.full.js index b651f1ff01..3fc58f0412 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -93,10 +93,11 @@ function shortcut() */ function showDropMenu(objectType, objectID, module, method, extra) { - var li = $('#currentItem').closest('li'); + var itemID = objectType == 'branch' ? '#currentBranch' : '#currentItem'; + var li = $(itemID).closest('li'); if(li.hasClass('show')) {li.removeClass('show'); return;} - var $dropMenu = $('#dropMenu'); + var $dropMenu = li.find('#dropMenu'); if(!li.data('showagain')) { li.data('showagain', true); @@ -105,7 +106,7 @@ function showDropMenu(objectType, objectID, module, method, extra) $dropMenu.on('keydown', '#search', function(e){ var code = e.which; - var $this = $('#searchResult > .search-list > ul > li.active'); + var $this = $dropMenu.find('#searchResult > .search-list > ul > li.active'); if(code === 38) // up { $this.removeClass('active'); @@ -122,7 +123,7 @@ function showDropMenu(objectType, objectID, module, method, extra) return; } } - $('#searchResult > .search-list > ul > li:not(.heading):last').addClass('active'); + $dropMenu.find('#searchResult > .search-list > ul > li:not(.heading):last').addClass('active'); } else if(code === 40) // down { @@ -140,7 +141,7 @@ function showDropMenu(objectType, objectID, module, method, extra) return; } } - $('#searchResult > .search-list > ul > li:not(.heading):first').addClass('active'); + $dropMenu.find('#searchResult > .search-list > ul > li:not(.heading):first').addClass('active'); } else if(code === 13) // enter { @@ -158,14 +159,14 @@ function showDropMenu(objectType, objectID, module, method, extra) searchItems(searchKey, objectType, objectID, module, method, extra); }, 200)); }).on('mouseenter', '#searchResult .search-list > ul > li', function(){ - $('#searchResult > .search-list > ul > li.active').removeClass('active'); + $dropMenu.find('#searchResult > .search-list > ul > li.active').removeClass('active'); $(this).addClass('active'); }); } $.get(createLink(objectType, 'ajaxGetDropMenu', "objectID=" + objectID + "&module=" + module + "&method=" + method + "&extra=" + extra), function(data) { $dropMenu.html(data).find('#search').focus(); - $('#searchResult > .search-list > ul > li:not(.heading)').removeClass('active').first().addClass('active'); + $dropMenu.find('#searchResult > .search-list > ul > li:not(.heading)').removeClass('active').first().addClass('active'); }); li.addClass('show'); @@ -184,11 +185,14 @@ function showDropMenu(objectType, objectID, module, method, extra) */ function showDropResult(objectType, objectID, module, method, extra) { + var itemID = objectType == 'branch' ? '#currentBranch' : '#currentItem'; + var li = $(itemID).closest('li'); + var $dropMenu = li.find('#dropMenu'); $.get(createLink(objectType, 'ajaxGetDropMenu', "objectID=" + objectID + "&module=" + module + "&method=" + method + "&extra=" + extra), function(data) { - $('#dropMenu').html(data); - setTimeout(function(){$("#dropMenu #search").focus();}, 200); - $('#searchResult > .search-list > ul > li:not(.heading)').removeClass('active').first().addClass('active'); + $dropMenu.html(data); + setTimeout(function(){$dropMenu.find("#search").focus();}, 200); + $dropMenu.find('#searchResult > .search-list > ul > li:not(.heading)').removeClass('active').first().addClass('active'); }); } @@ -213,10 +217,13 @@ function searchItems(keywords, objectType, objectID, module, method, extra) } else { + var itemID = objectType == 'branch' ? '#currentBranch' : '#currentItem'; + var li = $(itemID).closest('li'); + var $dropMenu = li.find('#dropMenu'); keywords = encodeURI(keywords); - if(keywords != '-') $.get(createLink(objectType, 'ajaxGetMatchedItems', "keywords=" + keywords + "&module=" + module + "&method=" + method + "&extra=" + extra), function(data) + if(keywords != '-') $.get(createLink(objectType, 'ajaxGetMatchedItems', "keywords=" + keywords + "&module=" + module + "&method=" + method + "&extra=" + extra + "&objectID=" + objectID), function(data) { - $('#searchResult').html(data).find('.search-list > ul > li:not(.heading)').removeClass('active').first().addClass('active'); + $dropMenu.find('#searchResult').html(data).find('.search-list > ul > li:not(.heading)').removeClass('active').first().addClass('active'); }); } }
    idAB);?> priAB);?> story->title);?>product->RD;?>
    product->type;?>product->typeList, 'normal', "class='form-control'");?>
    product->desc;?> product->RD;?> RD, "class='form-control chosen'");?>
    product->type;?>product->typeList, $product->type, "class='form-control'");?>
    product->status;?> product->statusList, $product->status, "class='form-control'");?>product->RD;?> RD];?>
    product->type;?>product->typeList[$product->type];?>
    product->status;?> product->statusList[$product->status];?>