diff --git a/config/config.php b/config/config.php index 6f5ea7b059..6271d1a45d 100644 --- a/config/config.php +++ b/config/config.php @@ -17,6 +17,7 @@ if(!function_exists('getWebRoot')){function getWebRoot(){}} /* 基本设置。Basic settings. */ $config->version = '16.5'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. +$config->liteVersion = '1.0'; // 迅捷版版本。 The version of Lite. $config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP. $config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time. $config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php. diff --git a/db/update16.4.sql b/db/update16.4.sql index 52133e1dd2..d87b04cf5d 100644 --- a/db/update16.4.sql +++ b/db/update16.4.sql @@ -27,3 +27,5 @@ UPDATE `zt_user` SET `visions`='rnd,lite'; INSERT INTO `zt_group` (`vision`, `name`, `role`, `desc`) VALUES ('lite', '迅捷版用户分组', 'liteUser', '迅捷版用户分组'); + +ALTER TABLE `zt_productplan` ADD `closedReason` varchar(20) NOT NULL AFTER `order`; diff --git a/db/zentao.sql b/db/zentao.sql index e3bf243fa3..da0ec62693 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -984,6 +984,7 @@ CREATE TABLE IF NOT EXISTS `zt_productplan` ( `begin` date NOT NULL, `end` date NOT NULL, `order` text NOT NULL, + `closedReason` varchar(20) NOT NULL `deleted` enum('0','1') NOT NULL default '0', PRIMARY KEY (`id`), KEY `product` (`product`), diff --git a/framework/base/control.class.php b/framework/base/control.class.php index 8246a8a1a1..01212eb037 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -413,25 +413,23 @@ class baseControl * 首先找sitecode下的扩展文件,如果没有,再找ext下的扩展文件。 * Find extViewFile in ext/_$siteCode/view first, then try ext/view/. */ - if($this->app->siteCode) - { - $extPath = dirname(dirname(realpath($viewFile))) . "/ext/_{$this->app->siteCode}/view"; - $extViewFile = $extPath . basename($viewFile); + $moduleName = basename(dirname(dirname(realpath($viewFile)))); + $extPath = $this->app->getModuleExtPath('', $moduleName, 'view'); - if(file_exists($extViewFile)) + $checkedOrder = array('site', 'common', 'xuan', 'vision', 'custom'); + foreach($checkedOrder as $checkedType) + { + if(!empty($extPath[$checkedType])) { - helper::cd($extPath); - return $extViewFile; + $extViewFile = $extPath[$checkedType] . basename($viewFile); + if(file_exists($extViewFile)) + { + helper::cd($extPath[$checkedType]); + return $extViewFile; + } } } - $extPath = dirname(dirname(realpath($viewFile))) . '/ext/view/'; - $extViewFile = $extPath . basename($viewFile); - if(file_exists($extViewFile)) - { - helper::cd($extPath); - return $extViewFile; - } return false; } diff --git a/lib/feishuapi/feishuapi.class.php b/lib/feishuapi/feishuapi.class.php index 138c5572f0..d25126517d 100644 --- a/lib/feishuapi/feishuapi.class.php +++ b/lib/feishuapi/feishuapi.class.php @@ -73,7 +73,7 @@ class feishuapi $pageToken = ''; while(true) { - $response = $this->queryAPI($this->apiUrl . "contact/v3/users?department_id={$deptID}" . ($pageToken ? "&page_token={$pageToken}" : ''), '', array(CURLOPT_CUSTOMREQUEST => "GET")); + $response = $this->queryAPI($this->apiUrl . "contact/v3/users?department_id={$deptID}&page_size=50" . ($pageToken ? "&page_token={$pageToken}" : ''), '', array(CURLOPT_CUSTOMREQUEST => "GET")); if(isset($response->data->items)) { foreach($response->data->items as $user) $users[$user->name] = $user->open_id; @@ -164,7 +164,7 @@ class feishuapi $index = 0; while(true) { - $response = $this->queryAPI($this->apiUrl . "contact/v3/departments?parent_department_id=0" . ($pageToken ? "&page_token={$pageToken}" : '') . "&fetch_child=true", '', array(CURLOPT_CUSTOMREQUEST => "GET")); + $response = $this->queryAPI($this->apiUrl . "contact/v3/departments?parent_department_id=0" . ($pageToken ? "&page_token={$pageToken}" : '') . "&fetch_child=true&page_size=50", '', array(CURLOPT_CUSTOMREQUEST => "GET")); if(isset($response->data->items)) { foreach($response->data->items as $key => $dept) diff --git a/module/branch/model.php b/module/branch/model.php index 01dff6d983..ba2f199afb 100644 --- a/module/branch/model.php +++ b/module/branch/model.php @@ -85,8 +85,6 @@ class branchModel extends model $mainBranch->desc = sprintf($this->lang->branch->mainBranch, $this->lang->product->branchName[$product->type]); $mainBranch->order = 0; - if($productID) $product = $this->loadModel('product')->getById($productID); - if(isset($product) and $product->type == 'normal') return $branchList; return array($mainBranch) + $branchList; } @@ -351,16 +349,115 @@ class branchModel extends model /** * Unlink branches for projects when product type is normal. * - * @param int $productIDList + * @param int|array $productIDList * @access public * @return void */ public function unlinkBranch4Project($productIDList) { + $productLinkedProject = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT) + ->where('product')->in($productIDList) + ->andWhere('branch')->gt(0) + ->fetchGroup('product', 'project'); + $this->dao->delete()->from(TABLE_PROJECTPRODUCT) ->where('product')->in($productIDList) ->andWhere('branch')->gt(0) ->exec(); + + foreach($productLinkedProject as $productID => $projectList) + { + foreach($projectList as $projectID => $project) + { + $data = new stdClass(); + $data->product = $productID; + $data->project = $projectID; + $data->branch = 0; + $data->plan = 0; + + $this->dao->replace(TABLE_PROJECTPRODUCT)->data($data)->exec(); + } + } + } + + /** + * Link branches for projects when product type is not normal. + * + * @param int $productID + * @access public + * @return void + */ + public function linkBranch4Project($productID) + { + if(is_array($productID)) + { + foreach($productID as $id) $this->linkBranch4Project($id); + } + + $linkedBranchProject = array(); + + $storyLinkedBranchProject = $this->dao->select('project,branch')->from(TABLE_PROJECTSTORY) + ->where('product')->eq($productID) + ->andWhere('branch')->gt(0) + ->fetchGroup('project', 'branch'); + foreach($storyLinkedBranchProject as $projectID => $branchList) + { + foreach($branchList as $branchID => $branch) $linkedBranchProject[$projectID][$branchID] = $branchID; + } + + $bugLinkedBranchProject = $this->dao->select('project,branch')->from(TABLE_BUG) + ->where('product')->eq($productID) + ->andWhere('branch')->gt(0) + ->andWhere('project')->ne(0) + ->fetchGroup('project', 'branch'); + foreach($bugLinkedBranchProject as $projectID => $branchList) + { + foreach($branchList as $branchID => $branch) $linkedBranchProject[$projectID][$branchID] = $branchID; + } + + $bugLinkedBranchExecution = $this->dao->select('execution,branch')->from(TABLE_BUG) + ->where('product')->eq($productID) + ->andWhere('branch')->gt(0) + ->andWhere('execution')->ne(0) + ->fetchGroup('execution', 'branch'); + foreach($bugLinkedBranchExecution as $executionID => $branchList) + { + foreach($branchList as $branchID => $branch) $linkedBranchProject[$executionID][$branchID] = $branchID; + } + + $caseLinkedBranchProject = $this->dao->select('project,branch')->from(TABLE_CASE) + ->where('product')->eq($productID) + ->andWhere('branch')->gt(0) + ->andWhere('project')->ne(0) + ->fetchGroup('project', 'branch'); + foreach($caseLinkedBranchProject as $projectID => $branchList) + { + foreach($branchList as $branchID => $branch) $linkedBranchProject[$projectID][$branchID] = $branchID; + } + + $caseLinkedBranchExecution = $this->dao->select('execution,branch')->from(TABLE_CASE) + ->where('product')->eq($productID) + ->andWhere('branch')->gt(0) + ->andWhere('execution')->ne(0) + ->fetchGroup('execution', 'branch'); + foreach($caseLinkedBranchExecution as $executionID => $branchList) + { + foreach($branchList as $branchID => $branch) $linkedBranchProject[$executionID][$branchID] = $branchID; + } + + foreach($linkedBranchProject as $projectID => $branchList) + { + foreach($branchList as $branchID) + { + $data = new stdClass(); + $data->product = $productID; + $data->project = $projectID; + $data->branch = $branchID; + $data->plan = 0; + + $this->dao->replace(TABLE_PROJECTPRODUCT)->data($data)->exec(); + } + } } /** diff --git a/module/bug/control.php b/module/bug/control.php index 8d555f63c6..3844061cd9 100644 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -89,16 +89,23 @@ class bug extends control $this->loadModel('datatable'); $productID = $this->product->saveState($productID, $this->products); + $product = $this->product->getById($productID); + if($product->type != 'normal') + { + /* Set productID, moduleID, queryID and branch. */ + $branch = ($this->cookie->preBranch !== '' and $branch === '') ? $this->cookie->preBranch : $branch; + setcookie('preProductID', $productID, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true); + setcookie('preBranch', $branch, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true); + } + else + { + $branch = 'all'; + } + $this->qa->setMenu($this->products, $productID, $branch); /* Set browse type. */ $browseType = strtolower($browseType); - - /* Set productID, moduleID, queryID and branch. */ - $branch = ($this->cookie->preBranch !== '' and $branch === '') ? $this->cookie->preBranch : $branch; - setcookie('preProductID', $productID, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true); - setcookie('preBranch', $branch, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true); - if($this->cookie->preProductID != $productID or $this->cookie->preBranch != $branch or $browseType == 'bybranch') { $_COOKIE['bugModule'] = 0; @@ -191,19 +198,22 @@ class bug extends control $showModule = !empty($this->config->datatable->bugBrowse->showModule) ? $this->config->datatable->bugBrowse->showModule : ''; $productName = ($productID and isset($this->products[$productID])) ? $this->products[$productID] : $this->lang->product->allProduct; - $product = $this->product->getById($productID); - /* Display of branch label. */ - $showBranch = $this->loadModel('branch')->showBranch($productID); - - /* Display status of branch. */ - $branches = $this->loadModel('branch')->getList($productID, 0, 'all'); + $showBranch = false; $branchOption = array(); $branchTagOption = array(); - foreach($branches as $branchInfo) + if($product and $product->type != 'normal') { - $branchOption[$branchInfo->id] = $branchInfo->name; - $branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''); + /* Display of branch label. */ + $showBranch = $this->loadModel('branch')->showBranch($productID); + + /* Display status of branch. */ + $branches = $this->loadModel('branch')->getList($productID, 0, 'all'); + foreach($branches as $branchInfo) + { + $branchOption[$branchInfo->id] = $branchInfo->name; + $branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''); + } } /* Set view. */ @@ -743,6 +753,18 @@ class bug extends control $projectID = $this->lang->navGroup->bug == 'project' ? $this->session->project : (isset($execution) ? $execution->project : 0); + /* Get branches. */ + if($executionID) + { + $productBranches = $product->type != 'normal' ? $this->execution->getBranchByProduct($productID, $executionID) : array(); + $branches = isset($productBranches[$productID]) ? $productBranches[$productID] : array(); + $branch = key($branches); + } + else + { + $branches = $product->type != 'normal' ? $this->loadModel('branch')->getPairs($productID, 'active') : array(); + } + $this->view->customFields = $customFields; $this->view->showFields = $showFields; @@ -761,7 +783,7 @@ class bug extends control $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $branch === 'all' ? 0 : $branch); $this->view->moduleID = $moduleID; $this->view->branch = $branch; - $this->view->branches = $this->loadModel('branch')->getPairs($productID, 'active'); + $this->view->branches = $branches; $this->display(); } @@ -985,13 +1007,16 @@ class bug extends control $branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''); } + $moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $bug->branch); + if(!isset($moduleOptionMenu[$bug->module])) $moduleOptionMenu += $this->tree->getModulesName($bug->module); + $this->view->bug = $bug; $this->view->productID = $productID; $this->view->product = $product; $this->view->productName = $this->products[$productID]; $this->view->plans = $this->loadModel('productplan')->getPairs($productID, $bug->branch, '', true); $this->view->projects = array(0 => '') + $this->product->getProjectPairsByProduct($productID, $bug->branch, $bug->project); - $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $bug->branch); + $this->view->moduleOptionMenu = $moduleOptionMenu; $this->view->currentModuleID = $currentModuleID; $this->view->executions = array(0 => '') + $this->product->getExecutionPairsByProduct($bug->product, $bug->branch, 'id_desc', $bug->project); $this->view->stories = $bug->execution ? $this->story->getExecutionStoryPairs($bug->execution) : $this->story->getProductStoryPairs($bug->product, $bug->branch); @@ -1065,57 +1090,58 @@ class bug extends control $plans = array('' => '', 'ditto' => $this->lang->bug->ditto) + $plans; /* Set branches and modules. */ - $branches = array(); + $branches = 0; $branchTagOption = array(); - $modules = array(); + $modules = array(); if($product->type != 'normal') { $branches = $this->loadModel('branch')->getList($productID, 0 ,'all'); - foreach($branches as $branchInfo) - { - $branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''); - } - foreach($branchTagOption as $branchID => $branchName) - { - $modules[$productID][$branchID] = $this->tree->getOptionMenu($productID, 'bug', 0, $branchID); - } - } - else - { - $modules[$productID][0] = $this->tree->getOptionMenu($productID, 'bug'); + foreach($branches as $branchInfo) $branchTagOption[$productID][$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''); + $branches = array_keys($branches); } + $modulePairs = $this->tree->getOptionMenu($productID, 'bug', 0, $branches); + $modules[$productID] = $product->type != 'normal' ? $modulePairs : array(0 => $modulePairs); + /* Set product menu. */ $this->qa->setMenu($this->products, $productID, $branch); - $this->view->title = $product->name . $this->lang->colon . "BUG" . $this->lang->bug->batchEdit; - $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID&branch=$branch"), $this->products[$productID]); - $this->view->plans = $plans; - $this->view->branchTagOption = $branchTagOption; - $this->view->modules = $modules; + $this->view->title = $product->name . $this->lang->colon . "BUG" . $this->lang->bug->batchEdit; + $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID&branch=$branch"), $this->products[$productID]); + $this->view->plans = $plans; } /* The bugs of my. */ else { - $branchProduct = false; - $productIdList = array(); + $branchProduct = false; + $productIdList = array(); + $branchTagOption = array(); foreach($bugs as $bug) $productIdList[$bug->product] = $bug->product; - $products = $this->product->getByIdList($productIdList); - foreach($products as $product) + $productList = $this->product->getByIdList($productIdList); + foreach($productList as $product) { + $branches = 0; if($product->type != 'normal') { + $branches = $this->loadModel('branch')->getList($product->id, 0 ,'all'); + foreach($branches as $branchInfo) $branchTagOption[$product->id][$branchInfo->id] = '/' . $product->name . '/' . $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''); + + $branches = array_keys($branches); $branchProduct = true; - break; } + + $modulePairs = $this->tree->getOptionMenu($product->id, 'bug', 0, $branches); + $modules[$product->id] = $product->type != 'normal' ? $modulePairs : array(0 => $modulePairs); } $this->app->loadLang('my'); $this->lang->task->menu = $this->lang->my->menu->work; $this->lang->my->menu->work['subModule'] = 'bug'; - $this->view->position[] = html::a($this->createLink('my', 'bug'), $this->lang->my->bug); - $this->view->title = "BUG" . $this->lang->bug->batchEdit; + $this->view->position[] = html::a($this->createLink('my', 'bug'), $this->lang->my->bug); + $this->view->title = "BUG" . $this->lang->bug->batchEdit; + $this->view->plans = $this->loadModel('productplan')->getPairs($product->id, $branch); + $this->view->productList = $productList; } /* Judge whether the editedBugs is too large and set session. */ @@ -1134,25 +1160,29 @@ class bug extends control { $appendUsers[$bug->assignedTo] = $bug->assignedTo; $appendUsers[$bug->resolvedBy] = $bug->resolvedBy; + + if(!isset($modules[$bug->product][$bug->branch])) $modules[$bug->product][$bug->branch] = $modules[$bug->product][0] + $this->tree->getModulesName($bug->module); } $users = $this->user->getPairs('devfirst', $appendUsers, $this->config->maxCount); $users = array('' => '', 'ditto' => $this->lang->bug->ditto) + $users; /* Assign. */ - $this->view->position[] = $this->lang->bug->common; - $this->view->position[] = $this->lang->bug->batchEdit; - $this->view->productID = $productID; - $this->view->branchProduct = $branchProduct; - $this->view->severityList = array('ditto' => $this->lang->bug->ditto) + $this->lang->bug->severityList; - $this->view->typeList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->typeList; - $this->view->priList = array('0' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->priList; - $this->view->resolutionList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->resolutionList; - $this->view->statusList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->statusList; - $this->view->osList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->osList; - $this->view->browserList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->browserList; - $this->view->bugs = $bugs; - $this->view->branch = $branch; - $this->view->users = $users; + $this->view->position[] = $this->lang->bug->common; + $this->view->position[] = $this->lang->bug->batchEdit; + $this->view->productID = $productID; + $this->view->branchProduct = $branchProduct; + $this->view->severityList = array('ditto' => $this->lang->bug->ditto) + $this->lang->bug->severityList; + $this->view->typeList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->typeList; + $this->view->priList = array('0' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->priList; + $this->view->resolutionList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->resolutionList; + $this->view->statusList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->statusList; + $this->view->osList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->osList; + $this->view->browserList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->browserList; + $this->view->bugs = $bugs; + $this->view->branch = $branch; + $this->view->users = $users; + $this->view->modules = $modules; + $this->view->branchTagOption = $branchTagOption; $this->display(); } diff --git a/module/bug/view/batchedit.html.php b/module/bug/view/batchedit.html.php index 859a2abcb9..985b4645c4 100644 --- a/module/bug/view/batchedit.html.php +++ b/module/bug/view/batchedit.html.php @@ -74,24 +74,6 @@ $bug):?> config->user->moreLink)) $this->config->moreLinks["assignedTos[$bugID]"] = $this->config->user->moreLink; - if(!$productID) - { - $branchTagOption = array(); - $product = $this->product->getByID($bug->product); - $plans = $this->loadModel('productplan')->getPairs($bug->product, $branch); - $branches = $product->type == 'normal' ? array() : $this->loadModel('branch')->getList($product->id, 0 ,'all'); - foreach($branches as $branchInfo) - { - $branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''); - } - - $modules[$bug->product][0] = $this->tree->getOptionMenu($bug->product, 'bug'); - if($product->type != 'normal') - { - foreach($branchTagOption as $branchID => $branchName) $branchTagOption[$branchID] = '/' . $product->name . '/' . $branchName; - $modules[$bug->product][$bug->branch] = $this->tree->getOptionMenu($bug->product, 'bug', 0, $bug->branch); - } - } ?> @@ -114,12 +96,11 @@ - id;?> - type == 'normal') ? "disabled='disabled'" : '';?> - branch, "class='form-control chosen' $disabled onchange='setBranchRelated(this.value, $bug->product, $bug->id)'");?> + product]->type == 'normal') ? "disabled='disabled'" : '';?> + product], $bug->branch, "class='form-control chosen' $disabled onchange='setBranchRelated(this.value, $bug->product, $bug->id)'");?> - product][$bug->branch], $bug->module, "class='form-control chosen'");?> + product][$bug->branch]) ? $modules[$bug->product][$bug->branch] : array(0 => '/'), $bug->module, "class='form-control chosen'");?> ' style='overflow:visible'>plan, "class='form-control chosen'");?> ' style='overflow:visible'>assignedTo, "class='form-control chosen'");?> ' style='overflow:visible'>deadline, "class='form-control form-date'");?> diff --git a/module/build/control.php b/module/build/control.php index 230a033659..7dc41b3449 100644 --- a/module/build/control.php +++ b/module/build/control.php @@ -428,7 +428,7 @@ class build extends control $isJsonView = $this->app->getViewType() == 'json'; if($varName == 'openedBuild') { - if(empty($executionID)) $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $index, $type); + if(empty($executionID)) return $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $index, $type); $params = ($type == 'all') ? 'noempty' : 'noempty, noterminate, nodone'; $builds = $this->build->getBuildPairs($productID, $branch, $params, $executionID, 'execution', $build); @@ -437,7 +437,7 @@ class build extends control } if($varName == 'openedBuilds') { - if(empty($executionID)) $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $index, $type); + if(empty($executionID)) return $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $index, $type); $builds = $this->build->getBuildPairs($productID, $branch, 'noempty', $executionID, 'execution'); if($isJsonView) return print(json_encode($builds)); @@ -445,7 +445,7 @@ class build extends control } if($varName == 'resolvedBuild') { - if(empty($executionID)) $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $index, $type); + if(empty($executionID)) return $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $index, $type); $params = ($type == 'all') ? '' : 'noterminate, nodone'; $builds = $this->build->getBuildPairs($productID, $branch, $params, $executionID, 'execution', $build); diff --git a/module/common/lang/en.php b/module/common/lang/en.php index 6a7f7e9bad..78c7628741 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -30,6 +30,7 @@ $lang->zentaoPMS = 'ZenTao'; $lang->pmsName = 'ALM'; $lang->proName = 'Pro'; $lang->bizName = 'Biz'; +$lang->liteName = 'Lite'; $lang->logoImg = 'zt-logo-en.png'; $lang->welcome = "%s ALM"; $lang->logout = 'Logout'; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 4e56bd276a..bba59f58c1 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -30,6 +30,7 @@ $lang->zentaoPMS = '禅道'; $lang->pmsName = '开源版'; $lang->proName = '专业版'; $lang->bizName = '企业版'; +$lang->liteName = '迅捷版'; $lang->logoImg = 'zt-logo.png'; $lang->welcome = "%s项目管理系统"; $lang->logout = '退出'; diff --git a/module/common/model.php b/module/common/model.php index 177c82bc41..91957915f1 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -473,16 +473,18 @@ class commonModel extends model */ public static function printVisionSwitcher() { - global $lang, $app; + global $lang, $app, $config; if(isset($app->user)) { $currentVision = $app->config->vision; $userVisions = array_filter(explode(',', $app->user->visions)); + $configVisions = array_filter(explode(',', trim($config->visions, ','))); if($app->config->systemMode != 'new') return print("
{$lang->visionList['rnd']}
"); - if(count($userVisions) < 2) return print("
{$lang->visionList[$currentVision]}
"); + if(count($userVisions) < 2) return print("
{$lang->visionList[$currentVision]}
"); + if(count($configVisions) < 2) return print("
{$lang->visionList[$currentVision]}
"); echo "\n"; return $activeMenu; diff --git a/module/custom/model.php b/module/custom/model.php index 2d4163fd63..9531bf8d96 100644 --- a/module/custom/model.php +++ b/module/custom/model.php @@ -245,6 +245,7 @@ class customModel extends model list($label, $module, $method) = $link; $hasPriv = commonModel::hasPriv($module, $method); if($module == 'execution' and $method == 'more') $hasPriv = true; + if($module == 'project' and $method == 'other') $hasPriv = true; } if($isTutorialMode || $hasPriv) diff --git a/module/dept/model.php b/module/dept/model.php index fc13b9926f..a7dae8c5af 100644 --- a/module/dept/model.php +++ b/module/dept/model.php @@ -383,6 +383,8 @@ class deptModel extends model ->beginIF($browseType == 'inside')->andWhere('type')->eq('inside')->fi() ->beginIF($browseType == 'outside')->andWhere('type')->eq('outside')->fi() ->beginIF($deptID)->andWhere('dept')->in($deptID)->fi() + ->beginIF($this->config->vision == 'lite')->andWhere('visions')->eq('lite')->fi() + ->beginIF($this->config->vision != 'lite')->andWhere('visions')->ne('lite')->fi() ->orderBy($orderBy) ->page($pager) ->fetchAll(); @@ -408,6 +410,8 @@ class deptModel extends model ->where('deleted')->eq(0) ->beginIF(strpos($params, 'all') === false)->andWhere('type')->eq($type)->fi() ->beginIF($childDepts)->andWhere('dept')->in($childDepts)->fi() + ->beginIF($this->config->vision == 'lite')->andWhere('visions')->eq('lite')->fi() + ->beginIF($this->config->vision != 'lite')->andWhere('visions')->ne('lite')->fi() ->orderBy('account') ->fetchPairs(); } diff --git a/module/execution/control.php b/module/execution/control.php index d99c5acd37..ec7ffd8eab 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -515,6 +515,13 @@ class execution extends control $mails = $this->execution->importBug($executionID); if(dao::isError()) return print(js::error(dao::getError())); + /* If link from no head then reload. */ + if(isonlybody()) + { + $kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all'); + return print(js::reload('parent')); + } + return print(js::locate($this->createLink('execution', 'importBug', "executionID=$executionID"), 'parent')); } @@ -2048,12 +2055,15 @@ class execution extends control $productID = 0; $branchID = 0; $products = $this->loadModel('product')->getProducts($executionID); + $productNames = array(); if($products) { $productID = key($products); $branches = $this->loadModel('branch')->getPairs($productID, '', $executionID); if($branches) $branchID = key($branches); } + foreach($products as $product) $productNames[$product->id] = $product->name; + $plans = $this->execution->getPlans($products, 'skipParent', $executionID); $allPlans = array('' => ''); @@ -2066,11 +2076,14 @@ class execution extends control $this->view->users = $users; $this->view->regions = $kanbanData; $this->view->execution = $execution; + $this->view->executionID = $executionID; $this->view->userList = $userList; $this->view->browseType = $browseType; $this->view->orderBy = $orderBy; $this->view->groupBy = $groupBy; $this->view->productID = $productID; + $this->view->productNames = $productNames; + $this->view->productNum = count($products); $this->view->branchID = $branchID; $this->view->projectID = $this->loadModel('task')->getProjectID($execution->id); $this->view->allPlans = $allPlans; @@ -2123,9 +2136,11 @@ class execution extends control $canBeChanged = common::canModify('execution', $execution); /* Get execution's product. */ - $productID = 0; - $products = $this->loadModel('product')->getProducts($executionID); + $productID = 0; + $productNames = array(); + $products = $this->loadModel('product')->getProducts($executionID); if($products) $productID = key($products); + foreach($products as $product) $productNames[$product->id] = $product->name; $plans = $this->execution->getPlans($products); $allPlans = array('' => ''); @@ -2147,6 +2162,8 @@ class execution extends control $this->view->orderBy = 'id_asc'; $this->view->executionID = $executionID; $this->view->productID = $productID; + $this->view->productNames = $productNames; + $this->view->productNum = count($products); $this->view->allPlans = $allPlans; $this->view->browseType = $browseType; $this->view->kanbanGroup = $kanbanGroup; @@ -2576,8 +2593,8 @@ class execution extends control $this->view->unmodifiableProducts = $unmodifiableProducts; $this->view->unmodifiableBranches = $unmodifiableBranches; $this->view->linkedBranches = $linkedBranches; - $this->view->branchGroups = $this->execution->getBranchByProduct(array_keys($allProducts), $this->config->systemMode == 'new' ? $execution->project : 0); - $this->view->allBranches = $this->execution->getBranchByProduct(array_keys($allProducts), $this->config->systemMode == 'new' ? $execution->project : 0, 'all'); + $this->view->branchGroups = $this->execution->getBranchByProduct(array_keys($allProducts), $this->config->systemMode == 'new' ? $execution->project : 0, 'ignoreNormal|noclosed'); + $this->view->allBranches = $this->execution->getBranchByProduct(array_keys($allProducts), $this->config->systemMode == 'new' ? $execution->project : 0, 'ignoreNormal'); $this->display(); } @@ -2792,6 +2809,13 @@ class execution extends control { if(isset($linkedStories[$story->id])) unset($allStories[$id]); if($story->parent < 0) unset($allStories[$id]); + + if(!isset($modules[$story->module])) + { + $storyModule = $this->tree->getModulesName($story->module); + $productName = count($products) > 1 ? $products[$story->product]->name : ''; + $modules[$story->module] = $productName . $storyModule[$story->module]; + } } /* Pager. */ diff --git a/module/execution/css/kanban.css b/module/execution/css/kanban.css index ca89881d63..a987329020 100644 --- a/module/execution/css/kanban.css +++ b/module/execution/css/kanban.css @@ -106,4 +106,5 @@ #mainMenu .divider {margin: 10px} -.kanbanRegion {margin:5px} +.kanbanRegion {margin: 5px} +.modal-header {padding: 15px 0;} diff --git a/module/execution/js/importbug.js b/module/execution/js/importbug.js index cdaccc8e08..3eb40fb373 100644 --- a/module/execution/js/importbug.js +++ b/module/execution/js/importbug.js @@ -1,4 +1,18 @@ $(function() { + $(".preview").modalTrigger({width:1000, type:'iframe'}); $('#' + browseType + 'Tab').addClass('active'); + + if(isonlybody == true) parent.$('#triggerModal .modal-content .modal-header .close').hide(); }); + +/** + * Go back. + * + * @access public + * @return void + */ +function goback() +{ + parent.location.reload(); +} diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js index 151ee611b4..31a8769e4d 100644 --- a/module/execution/js/kanban.js +++ b/module/execution/js/kanban.js @@ -1,3 +1,13 @@ +$(function() +{ + $('#products').change(function() + { + var selectProductID = $('#products').val(); + var attr = createLink('story', 'batchCreate', 'productID=' + selectProductID + '&branch=0' + '&moduleID=0&story=0&execution=' + executionID, '', true); + $('#batchCreateStoryButton').attr('href',attr); + }); +}) + /** * When execution status change. * @@ -263,14 +273,18 @@ function createColumnCreateMenu(options) if(col.type == 'backlog') { if(priv.canCreateStory) items.push({label: storyLang.create, url: $.createLink('story', 'create', 'productID=' + productID + '&branch=0&moduleID=0&storyID=0&objectID=' + executionID + '&bugID=0&planID=0&todoID=0&extra=laneID=' + laneID + ',columnID=' + col.id, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}}); - if(priv.canBatchCreateStory) items.push({label: executionLang.batchCreateStroy, url: $.createLink('story', 'batchcreate', 'productID=' + productID + '&branch=0&moduleID=0&storyID=0&executionID=' + executionID + '&plan=0&type=story&extra=laneID=' + laneID + ',columnID=' + col.id, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '90%'}}); + if(priv.canBatchCreateStory) items.push({label: executionLang.batchCreateStory, url: productCount > 1 ? '#batchCreateStory' : $.createLink('story', 'batchcreate', 'productID=' + productID + '&branch=0&moduleID=0&storyID=0&executionID=' + executionID + '&plan=0&type=story&extra=laneID=' + laneID + ',columnID=' + col.id, '', true), className: 'iframe',attrs: {'data-toggle': 'modal', 'data-width': '90%'}}); if(priv.canLinkStory) items.push({label: executionLang.linkStory, url: $.createLink('execution', 'linkStory', 'executionID=' + executionID + '&browseType=¶m=0&recTotal=0&recPerPage=50,&pageID=1&extra=laneID=' + laneID + ',columnID=' + col.id, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '90%'}}); if(priv.canLinkStoryByPlan) items.push({label: executionLang.linkStoryByPlan, url: '#linkStoryByPlan', 'attrs' : {'data-toggle': 'modal', 'data-target': '#linkStoryByPlan','data-col' : col.id, 'data-lane' : laneID, 'class' : 'linkStoryByPlanButton'}}); } else if(col.type == 'unconfirmed') { if(priv.canCreateBug) items.push({label: bugLang.create, url: $.createLink('bug', 'create', 'productID=0&moduleID=0&extra=laneID=' + laneID + ',columnID=' + col.id + ',executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}}); - if(priv.canBatchCreateBug) items.push({label: bugLang.batchCreate, url: $.createLink('bug', 'batchcreate', 'productID=' + productID + '&branch=&executionID=' + executionID + '&module=0&extra=laneID=' + laneID + ',columnID=' + col.id, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '90%'}}); + if(priv.canBatchCreateBug) + { + if(productNum > 1) items.push({label: bugLang.batchCreate, url: '#batchCreateBug', 'attrs' : {'data-toggle': 'modal'}}); + else items.push({label: bugLang.batchCreate, url: $.createLink('bug', 'batchcreate', 'productID=' + productID + '&branch=&executionID=' + executionID + '&module=0&extra=laneID=' + laneID + ',columnID=' + col.id, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '90%'}}); + } } else if(col.type == 'wait') { @@ -1237,6 +1251,16 @@ $(function() } }); + $('#product').change(function() + { + var product = $('#product').val(); + if(product) + { + var link = createLink('bug', 'batchCreate', 'productID=' + product + '&branch=&executionID=' + executionID, '', true); + $('#batchCreateBugButton').attr('href', link); + } + }); + $(document).on('click', '#splitTable .btn-plus', function() { var tr = $(this).closest('tr'); diff --git a/module/execution/js/taskkanban.js b/module/execution/js/taskkanban.js index 4192960f87..d10800f92b 100644 --- a/module/execution/js/taskkanban.js +++ b/module/execution/js/taskkanban.js @@ -803,7 +803,11 @@ function createColumnCreateMenu(options) else if(col.laneType == 'bug') { if(priv.canCreateBug) items.push({label: bugLang.create, url: $.createLink('bug', 'create', 'productID=0&moduleID=0&extra=executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-width': '80%'}}); - if(priv.canBatchCreateBug) items.push({label: bugLang.batchCreate, url: $.createLink('bug', 'batchcreate', 'productID=' + productID + '&moduleID=0&executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-width': '90%'}}); + if(priv.canBatchCreateBug) + { + if(productNum > 1) items.push({label: bugLang.batchCreate, url: '#batchCreateBug', 'attrs' : {'data-toggle': 'modal'}}); + else items.push({label: bugLang.batchCreate, url: $.createLink('bug', 'batchcreate', 'productID=' + productID + '&moduleID=0&executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-width': '90%'}}); + } } else { @@ -1074,6 +1078,16 @@ $(function() } }); + $('#product').change(function() + { + var product = $('#product').val(); + if(product) + { + var link = createLink('bug', 'batchCreate', 'productID=' + product + '&branch=&executionID=' + executionID, '', true); + $('#batchCreateBugButton').attr('href', link); + } + }); + $('#type_chosen .chosen-single span').prepend(''); $('#group_chosen .chosen-single span').prepend(kanbanLang.laneGroup + ': '); diff --git a/module/execution/lang/en.php b/module/execution/lang/en.php index a7de4f68fc..0e5b371ead 100644 --- a/module/execution/lang/en.php +++ b/module/execution/lang/en.php @@ -107,7 +107,7 @@ $lang->execution->unfoldClosed = 'Unfold Closed'; $lang->execution->editName = 'Edit Name'; $lang->execution->setWIP = 'WIP Settings'; $lang->execution->sortColumn = 'Kanban Card Sorting'; -$lang->execution->batchCreateStroy = "Batch create {$lang->SRCommon}"; +$lang->execution->batchCreateStory = "Batch create {$lang->SRCommon}"; $lang->execution->batchCreateTask = 'Batch create task'; $lang->execution->kanbanNoLinkProduct = "Kanban not linked {$lang->productCommon}"; @@ -292,44 +292,45 @@ $lang->execution->aboveAllProduct = "All the above {$lang->productCommon}s"; $lang->execution->aboveAllExecution = "All the above {$lang->executionCommon}s"; /* Page prompt. */ -$lang->execution->linkStoryByPlanTips = "This action will link all stories in this plan to the {$lang->executionCommon}."; -$lang->execution->selectExecution = "Select {$lang->executionCommon}"; -$lang->execution->beginAndEnd = 'Duration'; -$lang->execution->lblStats = 'Efforts'; -$lang->execution->stats = 'Available: %s(h). Estimates: %s(h). Cost: %s(h). Left: %s(h).'; -$lang->execution->taskSummary = "Total tasks on this page:%s. Waiting: %s. Doing: %s.     Estimates: %s(h). Cost: %s(h). Left: %s(h)."; -$lang->execution->pageSummary = "Total tasks: %total%. Waiting: %wait%. Doing: %doing%. Estimates: %estimate%(h). Cost: %consumed%(h). Left: %left%(h)."; -$lang->execution->checkedSummary = "Selected: %total%. Waiting: %wait%. Doing: %doing%. Estimates: %estimate%(h). Cost: %consumed%(h). Left: %left%(h)."; -$lang->execution->memberHoursAB = "%s has %s hours."; -$lang->execution->memberHours = '
%s Available Hours
%s
'; -$lang->execution->countSummary = '
Tasks
%s
Doing
%s
Waiting
%s
'; -$lang->execution->timeSummary = '
Estimates
%s
Cost
%s
Left
%s
'; -$lang->execution->groupSummaryAB = "
Tasks %s :Waiting %s   Doing %s
Estimates %s :Cost %s   Left %s
"; -$lang->execution->wbs = "Create Task"; -$lang->execution->batchWBS = "Batch Create Tasks"; -$lang->execution->howToUpdateBurn = "Help "; -$lang->execution->whyNoStories = "No story can be linked. Please check whether there is any story in {$lang->executionCommon} which is linked to {$lang->productCommon} and make sure it has been reviewed."; -$lang->execution->productStories = "Stories linked to {$lang->executionCommon} are the subeset of stories linked to {$lang->productCommon}. Stories can only be linked after they pass the review. Link Stories now."; -$lang->execution->haveDraft = "%s stories in draft, so they can't be linked."; -$lang->execution->doneExecutions = 'Finished'; -$lang->execution->selectDept = 'Select Department'; -$lang->execution->selectDeptTitle = 'Select User'; -$lang->execution->copyTeam = 'Copy Team'; -$lang->execution->copyFromTeam = "Copy from {$lang->execution->common} Team: %s"; -$lang->execution->noMatched = "No {$lang->execution->common} including '%s'can be found."; -$lang->execution->copyTitle = "Choose a {$lang->execution->common} to copy."; -$lang->execution->copyNoExecution = "No {$lang->execution->common} can be copied."; -$lang->execution->copyFromExecution = "Copy from {$lang->execution->common} %s"; -$lang->execution->cancelCopy = 'Cancel Copy'; -$lang->execution->byPeriod = 'By Time'; -$lang->execution->byUser = 'By User'; -$lang->execution->noExecution = "No {$lang->executionCommon}. "; -$lang->execution->noExecutions = "No {$lang->execution->common}."; -$lang->execution->noPrintData = "No data can be printed."; -$lang->execution->noMembers = 'No team members yet. '; -$lang->execution->workloadTotal = "The cumulative workload ratio should not exceed 100, and the total workload under the current product is: %s"; -// $lang->execution->linkProjectStoryTip = "(Link {$lang->SRCommon} comes from {$lang->SRCommon} linked under the execution)"; -$lang->execution->linkAllStoryTip = "({$lang->SRCommon} has never been linked under the execution, and can be directly linked with {$lang->SRCommon} of the product linked with the sprint/stage)"; +$lang->execution->linkStoryByPlanTips = "This action will link all stories in this plan to the {$lang->executionCommon}."; +$lang->execution->batchCreateStoryTips = "Please select the product that needs to be created in batches"; +$lang->execution->selectExecution = "Select {$lang->executionCommon}"; +$lang->execution->beginAndEnd = 'Duration'; +$lang->execution->lblStats = 'Efforts'; +$lang->execution->stats = 'Available: %s(h). Estimates: %s(h). Cost: %s(h). Left: %s(h).'; +$lang->execution->taskSummary = "Total tasks on this page:%s. Waiting: %s. Doing: %s.     Estimates: %s(h). Cost: %s(h). Left: %s(h)."; +$lang->execution->pageSummary = "Total tasks: %total%. Waiting: %wait%. Doing: %doing%. Estimates: %estimate%(h). Cost: %consumed%(h). Left: %left%(h)."; +$lang->execution->checkedSummary = "Selected: %total%. Waiting: %wait%. Doing: %doing%. Estimates: %estimate%(h). Cost: %consumed%(h). Left: %left%(h)."; +$lang->execution->memberHoursAB = "%s has %s hours."; +$lang->execution->memberHours = '
%s Available Hours
%s
'; +$lang->execution->countSummary = '
Tasks
%s
Doing
%s
Waiting
%s
'; +$lang->execution->timeSummary = '
Estimates
%s
Cost
%s
Left
%s
'; +$lang->execution->groupSummaryAB = "
Tasks %s :Waiting %s   Doing %s
Estimates %s :Cost %s   Left %s
"; +$lang->execution->wbs = "Create Task"; +$lang->execution->batchWBS = "Batch Create Tasks"; +$lang->execution->howToUpdateBurn = "Help "; +$lang->execution->whyNoStories = "No story can be linked. Please check whether there is any story in {$lang->executionCommon} which is linked to {$lang->productCommon} and make sure it has been reviewed."; +$lang->execution->productStories = "Stories linked to {$lang->executionCommon} are the subeset of stories linked to {$lang->productCommon}. Stories can only be linked after they pass the review. Link Stories now."; +$lang->execution->haveDraft = "%s stories in draft, so they can't be linked."; +$lang->execution->doneExecutions = 'Finished'; +$lang->execution->selectDept = 'Select Department'; +$lang->execution->selectDeptTitle = 'Select User'; +$lang->execution->copyTeam = 'Copy Team'; +$lang->execution->copyFromTeam = "Copy from {$lang->execution->common} Team: %s"; +$lang->execution->noMatched = "No {$lang->execution->common} including '%s'can be found."; +$lang->execution->copyTitle = "Choose a {$lang->execution->common} to copy."; +$lang->execution->copyNoExecution = "No {$lang->execution->common} can be copied."; +$lang->execution->copyFromExecution = "Copy from {$lang->execution->common} %s"; +$lang->execution->cancelCopy = 'Cancel Copy'; +$lang->execution->byPeriod = 'By Time'; +$lang->execution->byUser = 'By User'; +$lang->execution->noExecution = "No {$lang->executionCommon}. "; +$lang->execution->noExecutions = "No {$lang->execution->common}."; +$lang->execution->noPrintData = "No data can be printed."; +$lang->execution->noMembers = 'No team members yet. '; +$lang->execution->workloadTotal = "The cumulative workload ratio should not exceed 100, and the total workload under the current product is: %s"; +// $lang->execution->linkProjectStoryTip = "(Link {$lang->SRCommon} comes from {$lang->SRCommon} linked under the execution)"; +$lang->execution->linkAllStoryTip = "({$lang->SRCommon} has never been linked under the execution, and can be directly linked with {$lang->SRCommon} of the product linked with the sprint/stage)"; if($config->systemMode == 'classic') $lang->execution->copyTeamTitle = "Choose a {$lang->execution->common} Team to copy."; if($config->systemMode == 'new') $lang->execution->copyTeamTitle = "Choose a {$lang->project->common} or {$lang->execution->common} Team to copy."; diff --git a/module/execution/lang/zh-cn.php b/module/execution/lang/zh-cn.php index 61b7bf3e66..c47309f24b 100644 --- a/module/execution/lang/zh-cn.php +++ b/module/execution/lang/zh-cn.php @@ -107,7 +107,7 @@ $lang->execution->unfoldClosed = '展开已结束'; $lang->execution->editName = '编辑名称'; $lang->execution->setWIP = '在制品数量设置(WIP)'; $lang->execution->sortColumn = '看板列卡片排序'; -$lang->execution->batchCreateStroy = "批量新建{$lang->SRCommon}"; +$lang->execution->batchCreateStory = "批量新建{$lang->SRCommon}"; $lang->execution->batchCreateTask = '批量建任务'; $lang->execution->kanbanNoLinkProduct = "看板没有关联{$lang->productCommon}"; @@ -292,44 +292,45 @@ $lang->execution->aboveAllProduct = "以上所有{$lang->productCommon}"; $lang->execution->aboveAllExecution = "以上所有{$lang->executionCommon}"; /* 页面提示。*/ -$lang->execution->linkStoryByPlanTips = "此操作会将所选计划下面的{$lang->SRCommon}全部关联到此{$lang->executionCommon}中"; -$lang->execution->selectExecution = "请选择{$lang->execution->common}"; -$lang->execution->beginAndEnd = '起止时间'; -$lang->execution->lblStats = '工时统计'; -$lang->execution->stats = '可用工时 %s 工时,总共预计 %s 工时,已经消耗 %s 工时,预计剩余 %s 工时'; -$lang->execution->taskSummary = "本页共 %s 个任务,未开始 %s,进行中 %s,总预计 %s 工时,已消耗 %s 工时,剩余 %s 工时。"; -$lang->execution->pageSummary = "本页共 %total% 个任务,未开始 %wait%,进行中 %doing%,总预计 %estimate% 工时,已消耗 %consumed% 工时,剩余 %left% 工时。"; -$lang->execution->checkedSummary = "选中 %total% 个任务,未开始 %wait%,进行中 %doing%,总预计 %estimate% 工时,已消耗 %consumed% 工时,剩余 %left% 工时。"; -$lang->execution->memberHoursAB = "
%s有 %s 工时
"; -$lang->execution->memberHours = '
%s可用工时
%s
'; -$lang->execution->countSummary = '
总任务
%s
进行中
%s
未开始
%s
'; -$lang->execution->timeSummary = '
总预计
%s
已消耗
%s
剩余
%s
'; -$lang->execution->groupSummaryAB = "
总任务 %s : 未开始 %s   进行中 %s
总预计 %s : 已消耗 %s   剩余 %s
"; -$lang->execution->wbs = "分解任务"; -$lang->execution->batchWBS = "批量分解"; -$lang->execution->howToUpdateBurn = "帮助 "; -$lang->execution->whyNoStories = "看起来没有{$lang->SRCommon}可以关联。请检查下{$lang->executionCommon}关联的{$lang->productCommon}中有没有{$lang->SRCommon},而且要确保它们已经审核通过。"; -$lang->execution->productStories = "{$lang->executionCommon}关联的{$lang->SRCommon}是{$lang->productCommon}{$lang->SRCommon}的子集,并且只有评审通过的{$lang->SRCommon}才能关联。请关联{$lang->SRCommon}。"; -$lang->execution->haveDraft = "有%s条草稿状态的{$lang->SRCommon}无法关联到该{$lang->executionCommon}"; -$lang->execution->doneExecutions = '已结束'; -$lang->execution->selectDept = '选择部门'; -$lang->execution->selectDeptTitle = '选择一个部门的成员'; -$lang->execution->copyTeam = '复制团队'; -$lang->execution->copyFromTeam = "复制自{$lang->execution->common}团队: %s"; -$lang->execution->noMatched = "找不到包含'%s'的{$lang->execution->common}"; -$lang->execution->copyTitle = "请选择一个{$lang->execution->common}来复制"; -$lang->execution->copyNoExecution = "没有可用的{$lang->execution->common}来复制"; -$lang->execution->copyFromExecution = "复制自{$lang->execution->common} %s"; -$lang->execution->cancelCopy = '取消复制'; -$lang->execution->byPeriod = '按时间段'; -$lang->execution->byUser = '按用户'; -$lang->execution->noExecution = "暂时没有{$lang->executionCommon}。"; -$lang->execution->noExecutions = "暂时没有{$lang->execution->common}。"; -$lang->execution->noPrintData = "暂无数据可打印"; -$lang->execution->noMembers = '暂时没有团队成员。'; -$lang->execution->workloadTotal = "工作量占比累计不应当超过100, 当前产品下的工作量之和为%s"; +$lang->execution->linkStoryByPlanTips = "此操作会将所选计划下面的{$lang->SRCommon}全部关联到此{$lang->executionCommon}中"; +$lang->execution->batchCreateStoryTips = '请选择需要批量新建研发需求的产品'; +$lang->execution->selectExecution = "请选择{$lang->execution->common}"; +$lang->execution->beginAndEnd = '起止时间'; +$lang->execution->lblStats = '工时统计'; +$lang->execution->stats = '可用工时 %s 工时,总共预计 %s 工时,已经消耗 %s 工时,预计剩余 %s 工时'; +$lang->execution->taskSummary = "本页共 %s 个任务,未开始 %s,进行中 %s,总预计 %s 工时,已消耗 %s 工时,剩余 %s 工时。"; +$lang->execution->pageSummary = "本页共 %total% 个任务,未开始 %wait%,进行中 %doing%,总预计 %estimate% 工时,已消耗 %consumed% 工时,剩余 %left% 工时。"; +$lang->execution->checkedSummary = "选中 %total% 个任务,未开始 %wait%,进行中 %doing%,总预计 %estimate% 工时,已消耗 %consumed% 工时,剩余 %left% 工时。"; +$lang->execution->memberHoursAB = "
%s有 %s 工时
"; +$lang->execution->memberHours = '
%s可用工时
%s
'; +$lang->execution->countSummary = '
总任务
%s
进行中
%s
未开始
%s
'; +$lang->execution->timeSummary = '
总预计
%s
已消耗
%s
剩余
%s
'; +$lang->execution->groupSummaryAB = "
总任务 %s : 未开始 %s   进行中 %s
总预计 %s : 已消耗 %s   剩余 %s
"; +$lang->execution->wbs = "分解任务"; +$lang->execution->batchWBS = "批量分解"; +$lang->execution->howToUpdateBurn = "帮助 "; +$lang->execution->whyNoStories = "看起来没有{$lang->SRCommon}可以关联。请检查下{$lang->executionCommon}关联的{$lang->productCommon}中有没有{$lang->SRCommon},而且要确保它们已经审核通过。"; +$lang->execution->productStories = "{$lang->executionCommon}关联的{$lang->SRCommon}是{$lang->productCommon}{$lang->SRCommon}的子集,并且只有评审通过的{$lang->SRCommon}才能关联。请关联{$lang->SRCommon}。"; +$lang->execution->haveDraft = "有%s条草稿状态的{$lang->SRCommon}无法关联到该{$lang->executionCommon}"; +$lang->execution->doneExecutions = '已结束'; +$lang->execution->selectDept = '选择部门'; +$lang->execution->selectDeptTitle = '选择一个部门的成员'; +$lang->execution->copyTeam = '复制团队'; +$lang->execution->copyFromTeam = "复制自{$lang->execution->common}团队: %s"; +$lang->execution->noMatched = "找不到包含'%s'的{$lang->execution->common}"; +$lang->execution->copyTitle = "请选择一个{$lang->execution->common}来复制"; +$lang->execution->copyNoExecution = "没有可用的{$lang->execution->common}来复制"; +$lang->execution->copyFromExecution = "复制自{$lang->execution->common} %s"; +$lang->execution->cancelCopy = '取消复制'; +$lang->execution->byPeriod = '按时间段'; +$lang->execution->byUser = '按用户'; +$lang->execution->noExecution = "暂时没有{$lang->executionCommon}。"; +$lang->execution->noExecutions = "暂时没有{$lang->execution->common}。"; +$lang->execution->noPrintData = "暂无数据可打印"; +$lang->execution->noMembers = '暂时没有团队成员。'; +$lang->execution->workloadTotal = "工作量占比累计不应当超过100, 当前产品下的工作量之和为%s"; // $lang->execution->linkProjectStoryTip = "(关联{$lang->SRCommon}来源于项目下所关联的{$lang->SRCommon})"; -$lang->execution->linkAllStoryTip = "(项目下还未关联{$lang->SRCommon},可直接关联该{$lang->execution->common}所关联产品的{$lang->SRCommon})"; +$lang->execution->linkAllStoryTip = "(项目下还未关联{$lang->SRCommon},可直接关联该{$lang->execution->common}所关联产品的{$lang->SRCommon})"; if($config->systemMode == 'classic') $lang->execution->copyTeamTitle = "选择一个{$lang->execution->common}团队来复制"; if($config->systemMode == 'new') $lang->execution->copyTeamTitle = "选择一个{$lang->project->common}或{$lang->execution->common}团队来复制"; diff --git a/module/execution/lang/zh-tw.php b/module/execution/lang/zh-tw.php index d13a43b35f..39047bd819 100644 --- a/module/execution/lang/zh-tw.php +++ b/module/execution/lang/zh-tw.php @@ -107,7 +107,7 @@ $lang->execution->unfoldClosed = '展開已結束'; $lang->execution->editName = '編輯名稱'; $lang->execution->setWIP = '在製品數量設置(WIP)'; $lang->execution->sortColumn = '看板列卡片排序'; -$lang->execution->batchCreateStroy = "批量新建{$lang->SRCommon}"; +$lang->execution->batchCreateStory = "批量新建{$lang->SRCommon}"; $lang->execution->batchCreateTask = '批量建任務'; /* Fields of zt_team. */ diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 98525faf8e..ec59ec90d7 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -44,7 +44,7 @@ createLink('programplan', 'create', "projectID=$projectID&productID=$productID"), " " . $lang->programplan->create, '', "class='btn btn-primary'");?> - createLink('execution', 'create', "projectID=$projectID"), " " . ((($from == 'execution') and ($config->systemMode == 'new')) ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-primary create-execution-btn' data-app='$from'");?> + createLink('execution', 'create', "projectID=$projectID"), " " . ((($from == 'execution') and ($config->systemMode == 'new')) ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-primary create-execution-btn' data-app='execution'");?> diff --git a/module/execution/view/importbug.html.php b/module/execution/view/importbug.html.php index 18e8a86bb7..0a1a030c45 100755 --- a/module/execution/view/importbug.html.php +++ b/module/execution/view/importbug.html.php @@ -13,10 +13,8 @@ - + + + + diff --git a/module/execution/view/story.html.php b/module/execution/view/story.html.php index 8a7c66e1d0..d95e2bffaa 100644 --- a/module/execution/view/story.html.php +++ b/module/execution/view/story.html.php @@ -284,7 +284,7 @@ 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); + common::printIcon('story', 'recall', "story={$story->id}", $story, 'list', 'undo', 'hiddenwin', $recallDisabled, '', '', $lang->story->recall); } $lang->task->create = $lang->execution->wbs; diff --git a/module/execution/view/taskkanban.html.php b/module/execution/view/taskkanban.html.php index be4d9adccc..0c16c7506e 100644 --- a/module/execution/view/taskkanban.html.php +++ b/module/execution/view/taskkanban.html.php @@ -74,7 +74,7 @@ $checkObject = new stdclass(); $checkObject->execution = $executionID; $canCreateTask = common::hasPriv('task', 'create', $checkObject); - $canBatchCreateTask = common::hasPriv('task', 'batchCreate', $checkObject); + $canBatchCreateTask = common::hasPriv('task', 'batchCreate', $checkObject); $canCreateBug = common::hasPriv('bug', 'create'); $canBatchCreateBug = common::hasPriv('bug', 'batchCreate'); $canImportBug = common::hasPriv('execution', 'importBug'); @@ -91,12 +91,17 @@