diff --git a/module/execution/config.php b/module/execution/config.php index ec4ef74386..69eeeb5f7d 100644 --- a/module/execution/config.php +++ b/module/execution/config.php @@ -11,6 +11,9 @@ $config->execution->list->exportFields = 'id,name,projectName,code,PM,end,status $config->execution->modelList['scrum'] = 'sprint'; $config->execution->modelList['waterfall'] = 'stage'; +$config->execution->modelList['kanban'] = 'kanban'; + +$config->execution->statusActions = array('start', 'putoff', 'suspend', 'close', 'activate'); global $lang, $app; $app->loadLang('task'); diff --git a/module/execution/control.php b/module/execution/control.php index 5df0d4b454..8da0e8c60a 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1397,6 +1397,7 @@ class execution extends control $this->loadModel('kanban')->createRDKanban($execution); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + if($this->app->tab == 'project') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('project', 'index', "projectID=$projectID"))); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('kanban', "executionID=$executionID"))); } @@ -1476,6 +1477,7 @@ class execution extends control $this->app->loadLang('stage'); $this->app->loadLang('programplan'); $browseExecutionLink = $this->createLink('execution', 'browse', "executionID=$executionID"); + $execution = $this->execution->getById($executionID); if(!empty($_POST)) { @@ -1527,6 +1529,7 @@ class execution extends control $this->executeHooks($executionID); if($_POST['status'] == 'doing') $this->loadModel('common')->syncPPEStatus($executionID); + if($execution->type == 'kanban') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent')); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "executionID=$executionID"))); } @@ -1534,7 +1537,6 @@ class execution extends control $this->execution->setMenu($executionID); $executions = array('' => '') + $this->executions; - $execution = $this->execution->getById($executionID); $managers = $this->execution->getDefaultManagers($executionID); $project = $this->project->getByID($execution->project); @@ -1721,6 +1723,7 @@ class execution extends control { $execution = $this->commonAction($executionID); $executionID = $execution->id; + if($execution->type == 'kanban') $this->lang->executionCommon = $this->lang->execution->kanban; if(!empty($_POST)) { @@ -1793,6 +1796,7 @@ class execution extends control { $execution = $this->commonAction($executionID); $executionID = $execution->id; + if($execution->type == 'kanban') $this->lang->executionCommon = $this->lang->execution->kanban; if(!empty($_POST)) { @@ -1828,6 +1832,7 @@ class execution extends control { $execution = $this->commonAction($executionID); $executionID = $execution->id; + if($execution->type == 'kanban') $this->lang->executionCommon = $this->lang->execution->kanban; if(!empty($_POST)) { @@ -1870,6 +1875,7 @@ class execution extends control { $execution = $this->commonAction($executionID); $executionID = $execution->id; + if($execution->type == 'kanban') $this->lang->executionCommon = $this->lang->execution->kanban; if(!empty($_POST)) { @@ -1967,13 +1973,18 @@ class execution extends control */ public function kanban($executionID, $browseType = 'all', $orderBy = 'id_asc', $groupBy = 'all') { - unset($this->lang->execution->menu); + $this->lang->execution->menu = new stdclass(); + $execution = $this->commonAction($executionID); + $kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $browseType, $orderBy, $groupBy); + $executionActions = array(); - $users = $this->loadModel('user')->getPairs('noletter|nodeleted'); - $kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $browseType, $orderBy, $groupBy); - $execution = $this->execution->getById($executionID); + foreach($this->config->execution->statusActions as $action) + { + if($this->execution->isClickable($execution, $action)) $executionActions[] = $action; + } $userList = array(); + $users = $this->loadModel('user')->getPairs('noletter|nodeleted'); $avatarPairs = $this->dao->select('account, avatar')->from(TABLE_USER)->where('deleted')->eq(0)->fetchPairs(); foreach($avatarPairs as $account => $avatar) { @@ -1993,16 +2004,17 @@ class execution extends control foreach($plans as $plan) $allPlans += $plan; } - $this->view->title = $this->lang->kanban->view; - $this->view->users = $users; - $this->view->regions = $kanbanData; - $this->view->execution = $execution; - $this->view->userList = $userList; - $this->view->browseType = $browseType; - $this->view->orderBy = $orderBy; - $this->view->groupBy = $groupBy; - $this->view->productID = $productID; - $this->view->allPlans = $allPlans; + $this->view->title = $this->lang->kanban->view; + $this->view->users = $users; + $this->view->regions = $kanbanData; + $this->view->execution = $execution; + $this->view->userList = $userList; + $this->view->browseType = $browseType; + $this->view->orderBy = $orderBy; + $this->view->groupBy = $groupBy; + $this->view->productID = $productID; + $this->view->allPlans = $allPlans; + $this->view->executionActions = $executionActions; $this->display(); } @@ -2397,6 +2409,7 @@ class execution extends control else { /* Delete execution. */ + $execution = $this->execution->getByID($executionID); $this->dao->update(TABLE_EXECUTION)->set('deleted')->eq(1)->where('id')->eq($executionID)->exec(); $this->loadModel('action')->create('execution', $executionID, 'deleted', '', ACTIONMODEL::CAN_UNDELETED); $this->execution->updateUserView($executionID); @@ -2405,7 +2418,8 @@ class execution extends control $this->executeHooks($executionID); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess)); - die(js::reload('parent')); + if($execution->type == 'kanban') return print(js::locate($this->createLink('execution', 'all'), 'parent')); + return print(js::reload('parent')); } } @@ -2959,7 +2973,7 @@ class execution extends control $projects = $this->loadModel('program')->getProjectList(0, 'all', 0, 'order_asc', null, 0, 0, true); $executionGroups = $this->dao->select('*')->from(TABLE_EXECUTION) ->where('deleted')->eq(0) - ->andWhere('type')->in('sprint,stage') + ->andWhere('type')->in('sprint,stage,kanban') ->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->sprints)->fi() ->beginIF($this->config->systemMode == 'new')->andWhere('project')->in(array_keys($projects))->fi() ->orderBy('id_desc') diff --git a/module/execution/css/kanban.css b/module/execution/css/kanban.css index df132b1ab1..ec349e5541 100644 --- a/module/execution/css/kanban.css +++ b/module/execution/css/kanban.css @@ -108,3 +108,4 @@ #kanbanScaleControl > .input-group-btn:first-child > .btn {border-radius: 16px 0 0 16px; border-right-color: transparent;} #kanbanScaleControl > .input-group-btn:last-child > .btn {border-radius: 0 16px 16px 0; border-left-color: transparent;} #kanbanScaleControl > .input-group-btn > .btn:hover {border-color: #b8bfce;} +#kanbanActionMenu {top: 24px; right: 28px;} diff --git a/module/execution/model.php b/module/execution/model.php index 53652b26b0..fd0ac79003 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -65,7 +65,7 @@ class executionModel extends model { if(!$this->app->user->admin and strpos(",{$this->app->user->view->sprints},", ",$executionID,") === false and !defined('TUTORIAL') and $executionID != 0) die(js::error($this->lang->execution->accessDenied) . js::locate('back')); - $executions = $this->loadModel('execution')->getPairs(0, 'all', 'nocode'); + $executions = $this->getPairs(0, 'all', 'nocode'); if(!$executionID and $this->session->execution) $executionID = $this->session->execution; if(!$executionID or !in_array($executionID, array_keys($executions))) $executionID = key($executions); $this->session->set('execution', $executionID); @@ -1054,7 +1054,7 @@ class executionModel extends model /* Order by status's content whether or not done */ $executions = $this->dao->select('*, IF(INSTR("done,closed", status) < 2, 0, 1) AS isDone, INSTR("doing,wait,suspended,closed", status) AS sortStatus')->from(TABLE_EXECUTION) ->where('deleted')->eq(0) - ->beginIF($type == 'all')->andWhere('type')->in('stage,sprint')->fi() + ->beginIF($type == 'all')->andWhere('type')->in('stage,sprint,kanban')->fi() ->beginIF($projectID and $this->config->systemMode == 'new')->andWhere('project')->eq($projectID)->fi() ->beginIF($type != 'all' and $this->config->systemMode == 'new')->andWhere('type')->eq($type)->fi() ->beginIF(strpos($mode, 'withdelete') === false)->andWhere('deleted')->eq(0)->fi() @@ -1319,7 +1319,7 @@ class executionModel extends model $module = 'execution'; $method = 'task'; } - if($module == 'testcase' and ($method == 'view' || $method == 'edit' || $method == 'batchedit')) + if($module == 'testcase' and ($method == 'view' or $method == 'edit' or $method == 'batchedit')) { $module = 'execution'; $method = 'testcase'; @@ -1329,7 +1329,7 @@ class executionModel extends model $module = 'execution'; $method = 'testtask'; } - if($module == 'build' and ($method == 'edit' || $method= 'view')) + if($module == 'build' and ($method == 'edit' or $method == 'view')) { $module = 'execution'; $method = 'build'; @@ -3038,7 +3038,9 @@ class executionModel extends model */ public static function isClickable($execution, $action) { - $action = strtolower($action); + $action = strtolower($action); + $clickable = commonModel::hasPriv('execution', $action); + if(!$clickable) return false; if($action == 'start') return $execution->status == 'wait'; if($action == 'close') return $execution->status != 'closed'; diff --git a/module/execution/view/ajaxgetdropmenu.html.php b/module/execution/view/ajaxgetdropmenu.html.php index e5ac0900c0..c52d2687f1 100644 --- a/module/execution/view/ajaxgetdropmenu.html.php +++ b/module/execution/view/ajaxgetdropmenu.html.php @@ -75,6 +75,11 @@ foreach($executions as $projectID => $projectExecutions) $selected = $execution->id == $executionID ? 'selected' : ''; if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account]))) { + $kanbanLink = $this->createLink('execution', 'kanban', "executionID=%s"); + $taskLink = $this->createLink('execution', 'task', "executionID=%s"); + if($execution->type != 'kanban' and $link == $kanbanLink) $link = $taskLink; + if($execution->type == 'kanban' and $link != $kanbanLink) $link = $kanbanLink; + $myExecutionsHtml .= '