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 strong> hours.";
-$lang->execution->memberHours = '';
-$lang->execution->countSummary = '';
-$lang->execution->timeSummary = '';
-$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 strong> hours.";
+$lang->execution->memberHours = '';
+$lang->execution->countSummary = '';
+$lang->execution->timeSummary = '';
+$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 = '';
-$lang->execution->countSummary = '';
-$lang->execution->timeSummary = '';
-$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 = '';
+$lang->execution->countSummary = '';
+$lang->execution->timeSummary = '';
+$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 @@
-
+
+
@@ -70,18 +68,20 @@ var browseType = '';
-
-
diff --git a/module/execution/view/kanban.html.php b/module/execution/view/kanban.html.php
index 0cdc984525..cc5d7bbb0d 100644
--- a/module/execution/view/kanban.html.php
+++ b/module/execution/view/kanban.html.php
@@ -43,11 +43,14 @@ js::set('noAssigned', $lang->kanbancard->noAssigned);
js::set('users', $users);
js::set('entertime', time());
js::set('displayCards', $execution->displayCards);
+js::set('productNum', $productNum);
js::set('fluidBoard', $execution->fluidBoard);
js::set('colorListLang', $lang->kanbancard->colorList);
js::set('colorList', $this->config->kanban->cardColorList);
js::set('projectID', $projectID);
js::set('vision', $this->config->vision);
+js::set('productCount', count($productNames));
+js::set('executionID', $execution->id);
$canSortRegion = commonModel::hasPriv('kanban', 'sortRegion') && count($regions) > 1;
$canEditRegion = commonModel::hasPriv('kanban', 'editRegion');
@@ -163,12 +166,30 @@ js::set('hasTaskButton', $hasTaskButton);
lang->create;?>
+
+
+
+
+
+
+
+ id", '', true), $lang->execution->batchCreateStory, '', "class='btn btn-primary iframe' data-width='90%' id='batchCreateStoryButton' data-dismiss='modal'");?>
+
+
+
+
+
+
+
+
+
+
+
+
+ bug->batchCreate, '', "id='batchCreateBugButton' class='btn btn-primary iframe' data-dismiss='modal' data-width='90%'");?>
+
+
+
+
+
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 @@
lang->create;?>