diff --git a/api/v1/entries/modules.php b/api/v1/entries/modules.php new file mode 100644 index 0000000000..f38e90383a --- /dev/null +++ b/api/v1/entries/modules.php @@ -0,0 +1,43 @@ + + * @package entries + * @version 1 + * @link http://www.zentao.net + */ +class modulesEntry extends Entry +{ + /** + * Get method. + * + * @access public + * @return void + */ + public function get() + { + $objectType = $this->param('type', ''); + $objectID = $this->param('id', ''); + + if(!$objectType or !$objectID) return $this->sendError(400, 'Need id and type.'); + if(!in_array($objectType, array('story', 'task', 'bug', 'case'))) return $this->sendError(400, 'Type is not allowed'); + + if($objectType == 'task') + { + $control = $this->loadController('tree', 'browsetask'); + $control->browseTask($objectID); + } + else + { + $control = $this->loadController('tree', 'browse'); + $control->browse($objectID, $objectType); + } + $data = $this->getData(); + if(isset($data->status) and $data->status == 'success') return $this->send(200, array('modules' => $data->data->tree)); + + return $this->send400(isset($data->message) ? $data->message: 'error'); + } +} diff --git a/config/routes.php b/config/routes.php index 324765ae4d..a484abdcda 100644 --- a/config/routes.php +++ b/config/routes.php @@ -140,6 +140,8 @@ $routes['/docs/:id'] = 'doc'; $routes['/repos'] = 'repos'; $routes['/repos/rules'] = 'reporules'; +$routes['/modules'] = 'modules'; + $routes['/reports'] = 'reports'; $routes['/z/folders'] = 'zfolders'; diff --git a/module/bug/view/create.html.php b/module/bug/view/create.html.php index c30415c621..def2c34a4b 100644 --- a/module/bug/view/create.html.php +++ b/module/bug/view/create.html.php @@ -124,9 +124,7 @@ if($this->app->tab == 'project') js::set('objectID', $projectID);
bug->openedBuild?> - -
bug->allBuilds, "class='btn' id='all' data-toggle='tooltip' onclick='loadAllBuilds()'")?>
diff --git a/module/execution/control.php b/module/execution/control.php index 964df20efa..f248464ce5 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1317,7 +1317,7 @@ class execution extends control $this->view->title = $this->lang->execution->tips; $this->view->tips = $this->fetch('execution', 'tips', "executionID=$executionID"); - $this->view->defaultURL = isset($this->session->closeTipsList) ? $this->session->closeTipsList : $this->createLink('execution', 'task', 'executionID=' . $executionID); + $this->view->defaultURL = $this->session->closeTipsList ? $this->session->closeTipsList : $this->createLink('execution', 'task', 'executionID=' . $executionID); $this->view->executionID = $executionID; $this->view->projectID = $projectID; $this->view->project = $project; diff --git a/module/kanban/css/createspace.css b/module/kanban/css/createspace.css index ac6894793f..f5ad743eb1 100644 --- a/module/kanban/css/createspace.css +++ b/module/kanban/css/createspace.css @@ -1 +1 @@ -#mainContent {padding-left: 0px;} +#mainContent {padding-left: 0px; height: 500px;} diff --git a/module/kanban/css/editspace.css b/module/kanban/css/editspace.css index ac6894793f..f5ad743eb1 100644 --- a/module/kanban/css/editspace.css +++ b/module/kanban/css/editspace.css @@ -1 +1 @@ -#mainContent {padding-left: 0px;} +#mainContent {padding-left: 0px; height: 500px;} diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index 346329d0d7..531b664c2c 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -1587,3 +1587,8 @@ function resetRegionHeight(fold) $('.region').css('height', regionHeaderHeight); } } + +$('.dropdown-menu').click(function() +{ + $.zui.ContextMenu.hide(); +}) diff --git a/module/kanban/model.php b/module/kanban/model.php index b6a9ce85dd..f88d8b4f7d 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1647,14 +1647,14 @@ class kanbanModel extends model public function getSpacePairs($browseType = 'private') { $account = $this->app->user->account; - $spaceIdList = $this->getCanViewObjects('kanbanspace'); + $spaceIdList = $this->getCanViewObjects('kanbanspace', $browseType); return $this->dao->select('id,name')->from(TABLE_KANBANSPACE) ->where('deleted')->eq(0) + ->andWhere('id')->in($spaceIdList) ->beginIF(in_array($browseType, array('private', 'cooperation', 'public')))->andWhere('type')->eq($browseType)->fi() ->beginIF($browseType == 'involved')->andWhere('owner')->ne($account)->fi() ->beginIF($this->cookie->showClosed == 0 and $browseType != 'showClosed')->andWhere('status')->ne('closed')->fi() - ->beginIF(!$this->app->user->admin)->andWhere('id')->in($spaceIdList)->fi() ->orderBy('id_desc') ->fetchPairs('id'); } @@ -1694,7 +1694,7 @@ class kanbanModel extends model $spaceList = $objectType == 'kanban' ? $this->dao->select('id,owner,type')->from(TABLE_KANBANSPACE)->fetchAll('id') : array(); - if($this->app->user->admin and strpos('private,involved', $param) === false) return array_keys($objects); + if($param and $this->app->user->admin and strpos('private,involved', $param) === false) return array_keys($objects); $account = $this->app->user->account; foreach($objects as $objectID => $object) diff --git a/module/kanban/view/editcard.html.php b/module/kanban/view/editcard.html.php index 26f9bd2d4c..22c6b4eb4a 100644 --- a/module/kanban/view/editcard.html.php +++ b/module/kanban/view/editcard.html.php @@ -71,6 +71,7 @@ + progress):?> kanbancard->progress;?> @@ -80,6 +81,7 @@ + diff --git a/module/kanban/view/viewcard.html.php b/module/kanban/view/viewcard.html.php index 24399cc0e3..57c58922cb 100644 --- a/module/kanban/view/viewcard.html.php +++ b/module/kanban/view/viewcard.html.php @@ -114,10 +114,12 @@ kanbancard->estimate;?> estimate, 2) . ' ' . $lang->kanbancard->lblHour;?> + progress):?> kanbancard->progress;?> progress, 2) . ' %';?> + diff --git a/module/tree/control.php b/module/tree/control.php index 878886378a..330004dece 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -50,7 +50,12 @@ class tree extends control if(strpos('story|bug|case', $viewType) !== false) { $product = $this->loadModel('product')->getById($rootID); - if(empty($product)) $this->locate($this->createLink('product', 'create')); + if(empty($product)) + { + if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'fail', 'message' => 'No product.')); + $this->locate($this->createLink('product', 'create')); + } + if(!empty($product->type) && $product->type != 'normal') { $branches = $this->loadModel('branch')->getPairs($product->id); diff --git a/test/class/bug.class.php b/test/class/bug.class.php index 8167405ecb..6e9777b89f 100644 --- a/test/class/bug.class.php +++ b/test/class/bug.class.php @@ -1841,4 +1841,118 @@ class bugTest return $array; } } + + /** + * Test form customed bugs. + * + * @param array $bugIDList + * @access public + * @return array + */ + public function formCustomedBugsTest($bugIDList) + { + $bugs = $this->objectModel->getByList($bugIDList); + $array = $this->objectModel->formCustomedBugs($bugs); + + if(dao::isError()) + { + return dao::getError(); + } + else + { + return $array; + } + } + + /** + * Test adjust the action is clickable. + * + * @param object $bug + * @param string $action + * @access public + * @return int + */ + public function isClickableTest($bug, $action) + { + $object = $this->objectModel->isClickable($bug, $action); + + if(dao::isError()) + { + return dao::getError(); + } + else + { + return $object ? 1 : 2; + } + } + + /** + * Test link bug to build and release. + * + * @param array $bugIDList + * @param int $resolvedBuild + * @access public + * @return object + */ + public function linkBugToBuildTest($bugIDList, $resolvedBuild) + { + $this->objectModel->linkBugToBuild($bugIDList, $resolvedBuild); + + global $tester; + $release = $tester->dao->select('id,bugs')->from(TABLE_RELEASE)->where('build')->eq($resolvedBuild)->andWhere('deleted')->eq('0')->fetch(); + + if(dao::isError()) + { + return dao::getError(); + } + else + { + return $release; + } + } + + /** + * Test get project list. + * + * @param int $productID + * @access public + * @return string + */ + public function getProjectsTest($productID) + { + $array = $this->objectModel->getProjects($productID); + + $title = ''; + foreach($array as $id => $project) $title .= ',' . $project; + $title = trim($title, ','); + + if(dao::isError()) + { + return dao::getError(); + } + else + { + return $title; + } + } + + /** + * Test get id list of all projects. + * + * @access public + * @return array + */ + public function getAllProjectIdsTest() + { + $array = $this->objectModel->getAllProjectIds(); + + if(dao::isError()) + { + return dao::getError(); + } + else + { + return $array; + } + } } diff --git a/test/model/bug/formcustomedbugs.php b/test/model/bug/formcustomedbugs.php new file mode 100755 index 0000000000..b962f4bb80 --- /dev/null +++ b/test/model/bug/formcustomedbugs.php @@ -0,0 +1,32 @@ +#!/usr/bin/env php +formCustomedBugs(); +cid=1 +pid=1 + +获取bug 1 2的module story task case execution名称 >> 产品模块1,软件需求2,0,0,迭代1;产品模块2,软件需求6,0,0,迭代1 +获取bug 3 4的module story task case execution名称 >> 产品模块3,软件需求10,0,0,迭代1;产品模块5,软件需求14,0,0,迭代2 +获取bug 5 6的module story task case execution名称 >> 产品模块6,软件需求18,0,0,迭代2;产品模块7,软件需求22,0,0,迭代2 +获取bug 7 8的module story task case execution名称 >> 产品模块11,软件需求26,0,0,迭代3;产品模块12,软件需求30,0,0,迭代3 +获取bug 9 10的module story task case execution名称 >> 产品模块13,软件需求34,0,0,迭代3;0,软件需求38,0,0,迭代4 + +*/ + +$bugIDList1 = array('1', '2'); +$bugIDList2 = array('3', '4'); +$bugIDList3 = array('5', '6'); +$bugIDList4 = array('7', '8'); +$bugIDList5 = array('9', '10'); + +$bug = new bugTest(); +r($bug->formCustomedBugsTest($bugIDList1)) && p('1:module,story,task,case,execution;2:module,story,task,case,execution') && e('产品模块1,软件需求2,0,0,迭代1;产品模块2,软件需求6,0,0,迭代1'); // 获取bug 1 2的module story task case execution名称 +r($bug->formCustomedBugsTest($bugIDList2)) && p('3:module,story,task,case,execution;4:module,story,task,case,execution') && e('产品模块3,软件需求10,0,0,迭代1;产品模块5,软件需求14,0,0,迭代2'); // 获取bug 3 4的module story task case execution名称 +r($bug->formCustomedBugsTest($bugIDList3)) && p('5:module,story,task,case,execution;6:module,story,task,case,execution') && e('产品模块6,软件需求18,0,0,迭代2;产品模块7,软件需求22,0,0,迭代2'); // 获取bug 5 6的module story task case execution名称 +r($bug->formCustomedBugsTest($bugIDList4)) && p('7:module,story,task,case,execution;8:module,story,task,case,execution') && e('产品模块11,软件需求26,0,0,迭代3;产品模块12,软件需求30,0,0,迭代3'); // 获取bug 7 8的module story task case execution名称 +r($bug->formCustomedBugsTest($bugIDList5)) && p('9:module,story,task,case,execution;10:module,story,task,case,execution') && e('产品模块13,软件需求34,0,0,迭代3;0,软件需求38,0,0,迭代'); // 获取bug 9 10的module story task case execution名称 diff --git a/test/model/bug/getallprojectids.php b/test/model/bug/getallprojectids.php new file mode 100755 index 0000000000..dd6ff6101d --- /dev/null +++ b/test/model/bug/getallprojectids.php @@ -0,0 +1,29 @@ +#!/usr/bin/env php +getAllProjectIds(); +cid=1 +pid=1 + +测试projectId为11的项目 >> 11 +测试projectId为12的项目 >> 12 +测试projectId为13的项目 >> 13 +测试projectId为41的项目 >> 41 +测试projectId为51的项目 >> 51 +测试projectId为91的项目 >> 91 + +*/ + +$projectIDList = array('11', '12', '13', '41', '51', '91'); + +$bug=new bugTest(); +r($bug->getAllProjectIdsTest()) && p("$projectIDList[0]") && e('11'); // 测试projectId为11的项目 +r($bug->getAllProjectIdsTest()) && p("$projectIDList[1]") && e('12'); // 测试projectId为12的项目 +r($bug->getAllProjectIdsTest()) && p("$projectIDList[2]") && e('13'); // 测试projectId为13的项目 +r($bug->getAllProjectIdsTest()) && p("$projectIDList[3]") && e('41'); // 测试projectId为41的项目 +r($bug->getAllProjectIdsTest()) && p("$projectIDList[4]") && e('51'); // 测试projectId为51的项目 +r($bug->getAllProjectIdsTest()) && p("$projectIDList[5]") && e('91'); // 测试projectId为91的项目 diff --git a/test/model/bug/getprojects.php b/test/model/bug/getprojects.php new file mode 100755 index 0000000000..d5d899256c --- /dev/null +++ b/test/model/bug/getprojects.php @@ -0,0 +1,32 @@ +#!/usr/bin/env php +getProjects(); +cid=1 +pid=1 + +测试获取productID为1的项目 >> 项目1,项目11 +测试获取productID为2的项目 >> 项目2,项目12 +测试获取productID为3的项目 >> 项目3,项目13 +测试获取productID为4的项目 >> 项目4,项目14 +测试获取productID为5的项目 >> 项目5,项目15 +测试获取productID为6的项目 >> 项目6,项目16 +测试获取不存在的product的项目 >> 0 + +*/ + + +$productIDList = array('1', '2', '3', '4','5', '6', '1000001'); + +$bug=new bugTest(); +r($bug->getProjectsTest($productIDList[0])) && p() && e('项目1,项目11'); // 测试获取productID为1的项目 +r($bug->getProjectsTest($productIDList[1])) && p() && e('项目2,项目12'); // 测试获取productID为2的项目 +r($bug->getProjectsTest($productIDList[2])) && p() && e('项目3,项目13'); // 测试获取productID为3的项目 +r($bug->getProjectsTest($productIDList[3])) && p() && e('项目4,项目14'); // 测试获取productID为4的项目 +r($bug->getProjectsTest($productIDList[4])) && p() && e('项目5,项目15'); // 测试获取productID为5的项目 +r($bug->getProjectsTest($productIDList[5])) && p() && e('项目6,项目16'); // 测试获取productID为6的项目 +r($bug->getProjectsTest($productIDList[6])) && p() && e('0'); // 测试获取不存在的product的项目 diff --git a/test/model/bug/isclickable.php b/test/model/bug/isclickable.php new file mode 100755 index 0000000000..18ae54ae11 --- /dev/null +++ b/test/model/bug/isclickable.php @@ -0,0 +1,82 @@ +#!/usr/bin/env php +isClickable(); +cid=1 +pid=1 + +状态为active confirmed为0的bug能否执行confirmbug动作 >> 1 +状态为active confirmed为0的bug能否执行resolve动作 >> 1 +状态为active confirmed为0的bug能否执行close动作 >> 2 +状态为active confirmed为0的bug能否执行activate动作 >> 2 +状态为active confirmed为0的bug能否执行tostory动作 >> 1 +状态为active confirmed为0的bug能否执行test动作 >> 1 +状态为active confirmed为1的bug能否执行confirmbug动作 >> 2 +状态为active confirmed为1的bug能否执行resolve动作 >> 1 +状态为active confirmed为1的bug能否执行close动作 >> 2 +状态为active confirmed为1的bug能否执行activate动作 >> 2 +状态为active confirmed为1的bug能否执行tostory动作 >> 1 +状态为active confirmed为1的bug能否执行test动作 >> 1 +状态为resolved的bug能否执行confirmbug动作 >> 2 +状态为resolved的bug能否执行resolve动作 >> 2 +状态为resolved的bug能否执行close动作 >> 1 +状态为resolved的bug能否执行activate动作 >> 1 +状态为resolved的bug能否执行tostory动作 >> 2 +状态为resolved的bug能否执行test动作 >> 1 +状态为closed的bug能否执行confirmbug动作 >> 2 +状态为closed的bug能否执行resolve动作 >> 2 +状态为closed的bug能否执行close动作 >> 2 +状态为closed的bug能否执行activate动作 >> 1 +状态为closed的bug能否执行tostory动作 >> 2 +状态为closed的bug能否执行test动作 >> 1 + +*/ + +$object1 = new stdclass(); +$object1->status = 'active'; +$object1->confirmed = 0; + + +$object2 = new stdclass(); +$object2->status = 'active'; +$object2->confirmed = 1; + +$object3 = new stdclass(); +$object3->status = 'resolved'; + +$object4 = new stdclass(); +$object4->status = 'closed'; + +$actionList = array('confirmbug', 'resolve', 'close', 'activate', 'tostory', 'test'); + +$bug=new bugTest(); + +r($bug->isClickableTest($object1, $actionList[0])) && p() && e('1'); // 状态为active confirmed为0的bug能否执行confirmbug动作 +r($bug->isClickableTest($object1, $actionList[1])) && p() && e('1'); // 状态为active confirmed为0的bug能否执行resolve动作 +r($bug->isClickableTest($object1, $actionList[2])) && p() && e('2'); // 状态为active confirmed为0的bug能否执行close动作 +r($bug->isClickableTest($object1, $actionList[3])) && p() && e('2'); // 状态为active confirmed为0的bug能否执行activate动作 +r($bug->isClickableTest($object1, $actionList[4])) && p() && e('1'); // 状态为active confirmed为0的bug能否执行tostory动作 +r($bug->isClickableTest($object1, $actionList[5])) && p() && e('1'); // 状态为active confirmed为0的bug能否执行test动作 +r($bug->isClickableTest($object2, $actionList[0])) && p() && e('2'); // 状态为active confirmed为1的bug能否执行confirmbug动作 +r($bug->isClickableTest($object2, $actionList[1])) && p() && e('1'); // 状态为active confirmed为1的bug能否执行resolve动作 +r($bug->isClickableTest($object2, $actionList[2])) && p() && e('2'); // 状态为active confirmed为1的bug能否执行close动作 +r($bug->isClickableTest($object2, $actionList[3])) && p() && e('2'); // 状态为active confirmed为1的bug能否执行activate动作 +r($bug->isClickableTest($object2, $actionList[4])) && p() && e('1'); // 状态为active confirmed为1的bug能否执行tostory动作 +r($bug->isClickableTest($object2, $actionList[5])) && p() && e('1'); // 状态为active confirmed为1的bug能否执行test动作 +r($bug->isClickableTest($object3, $actionList[0])) && p() && e('2'); // 状态为resolved的bug能否执行confirmbug动作 +r($bug->isClickableTest($object3, $actionList[1])) && p() && e('2'); // 状态为resolved的bug能否执行resolve动作 +r($bug->isClickableTest($object3, $actionList[2])) && p() && e('1'); // 状态为resolved的bug能否执行close动作 +r($bug->isClickableTest($object3, $actionList[3])) && p() && e('1'); // 状态为resolved的bug能否执行activate动作 +r($bug->isClickableTest($object3, $actionList[4])) && p() && e('2'); // 状态为resolved的bug能否执行tostory动作 +r($bug->isClickableTest($object3, $actionList[5])) && p() && e('1'); // 状态为resolved的bug能否执行test动作 +r($bug->isClickableTest($object4, $actionList[0])) && p() && e('2'); // 状态为closed的bug能否执行confirmbug动作 +r($bug->isClickableTest($object4, $actionList[1])) && p() && e('2'); // 状态为closed的bug能否执行resolve动作 +r($bug->isClickableTest($object4, $actionList[2])) && p() && e('2'); // 状态为closed的bug能否执行close动作 +r($bug->isClickableTest($object4, $actionList[3])) && p() && e('1'); // 状态为closed的bug能否执行activate动作 +r($bug->isClickableTest($object4, $actionList[4])) && p() && e('2'); // 状态为closed的bug能否执行tostory动作 +r($bug->isClickableTest($object4, $actionList[5])) && p() && e('1'); // 状态为closed的bug能否执行test动作 diff --git a/test/model/bug/linkbugtobuild.php b/test/model/bug/linkbugtobuild.php new file mode 100755 index 0000000000..83b22681f5 --- /dev/null +++ b/test/model/bug/linkbugtobuild.php @@ -0,0 +1,36 @@ +#!/usr/bin/env php +linkBugToBuild(); +cid=1 +pid=1 + +把bug 1 2关联到build 1 >> 1,2 +把bug 3 4关联到build 3 >> 3,4 +把bug 5 6关联到build 4 >> 5,6 +把bug 7 8关联到build 1 >> 1,2,7,8 +把bug 9 10关联到build 1 >> 1,2,7,8,9,10 + + +*/ + +$bugIDList1 = array('1', '2'); +$bugIDList2 = array('3', '4'); +$bugIDList3 = array('5', '6'); +$bugIDList4 = array('7', '8'); +$bugIDList5 = array('9', '10'); + +$buildList = array('1', '3', '5'); + +$bug = new bugTest(); +r($bug->linkBugToBuildTest($bugIDList1, $buildList[0])) && p('bugs') && e('1,2'); // 把bug 1 2关联到build 1 +r($bug->linkBugToBuildTest($bugIDList2, $buildList[1])) && p('bugs') && e('3,4'); // 把bug 3 4关联到build 3 +r($bug->linkBugToBuildTest($bugIDList3, $buildList[2])) && p('bugs') && e('5,6'); // 把bug 5 6关联到build 5 +r($bug->linkBugToBuildTest($bugIDList4, $buildList[0])) && p('bugs') && e('1,2,7,8'); // 把bug 5 6关联到build 1 +r($bug->linkBugToBuildTest($bugIDList5, $buildList[0])) && p('bugs') && e('1,2,7,8,9,10'); // 把bug 5 6关联到build 1 +system("./ztest init"); diff --git a/www/js/my.full.js b/www/js/my.full.js index c3b7069b6b..630874d86e 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -900,5 +900,12 @@ $(document).ready(function() $('#globalCreate').hover(function() { $(this).prev().removeClass('open'); + $(this).addClass('dropdown-hover'); + }); + + /* Hide create button when global create menu is clicked. */ + $('#globalCreate').click(function() + { + $(this).removeClass('dropdown-hover'); }); });