diff --git a/module/project/control.php b/module/project/control.php
index 52d6916bec..df07cc71d1 100755
--- a/module/project/control.php
+++ b/module/project/control.php
@@ -722,9 +722,8 @@ class project extends control
$withProgram = $this->config->systemMode == 'ALM' ? true : false;
- $linkedBranches = array();
$linkedBranchList = array();
- $productPlans = array(0 => '');
+ $productPlans = array();
$branches = $this->project->getBranchesByProject($projectID);
$linkedProductIdList = empty($branches) ? '' : array_keys($branches);
$allProducts = $this->program->getProductPairs($project->parent, 'all', 'noclosed', '', 0, $withProgram);
@@ -743,11 +742,10 @@ class project extends control
if(!isset($allProducts[$productID])) $allProducts[$productID] = $linkedProduct->name;
foreach($branches[$productID] as $branchID => $branch)
{
- $linkedBranchList[$branchID] = $branchID;
- $linkedBranches[$productID][$branchID] = $branchID;
+ $linkedBranchList[$branchID] = $branchID;
- if($branch != BRANCH_MAIN) $productPlans[$productID][$branchID] = isset($plans[$productID][BRANCH_MAIN]) ? $plans[$productID][BRANCH_MAIN] : array();
- $productPlans[$productID][$branchID] += isset($plans[$productID][$branchID]) ? $plans[$productID][$branchID] : array();
+ if($branch != BRANCH_MAIN) $productPlans[$productID] = isset($plans[$productID][BRANCH_MAIN]) ? $plans[$productID][BRANCH_MAIN] : array();
+ $productPlans[$productID] += isset($plans[$productID][$branchID]) ? $plans[$productID][$branchID] : array();
if(!empty($projectStories[$productID][$branchID]) or !empty($projectBranches[$productID][$branchID]))
{
@@ -773,7 +771,6 @@ class project extends control
$this->view->multiBranchProducts = $this->loadModel('product')->getMultiBranchPairs();
$this->view->productPlans = array_filter($productPlans);
$this->view->linkedProducts = $linkedProducts;
- $this->view->linkedBranches = $linkedBranches;
$this->view->branches = $branches;
$this->view->executions = $this->execution->getPairs($projectID);
$this->view->unmodifiableProducts = $unmodifiableProducts;
@@ -1286,7 +1283,6 @@ class project extends control
$this->view->branchOption = $branchOption;
$this->view->branchTagOption = $branchTagOption;
$this->view->executions = $executions;
- $this->view->plans = $this->loadModel('productplan')->getPairs($productID ? $productID : array_keys($products));
$this->view->stories = $storyList;
$this->view->tasks = $taskList;
$this->view->projectPairs = $this->project->getPairsByProgram();
diff --git a/module/project/css/edit.css b/module/project/css/edit.css
index e586511016..12113d5d32 100644
--- a/module/project/css/edit.css
+++ b/module/project/css/edit.css
@@ -5,5 +5,4 @@
#dateRange, .futureBox {vertical-align: top !important; padding-top: 13px !important;}
#endList {vertical-align: top; padding-top: 13px;}
#linkPlan {padding-top: 25px !important;}
-#productsBox .row .col-sm-4.required::after {right: -5px;}
#projectType {padding-top: 7px !important;}
diff --git a/module/project/js/common.js b/module/project/js/common.js
index 9234174496..7af601555d 100644
--- a/module/project/js/common.js
+++ b/module/project/js/common.js
@@ -138,134 +138,6 @@ function computeEndDate(delta)
$('#days').trigger('mousedown');
}
-/**
- * Load branches.
- *
- * @param object product
- * @access public
- * @return void
- */
-function loadBranches(product)
-{
- /* When selecting a product, delete a plan that is empty by default. */
- $("#planDefault").remove();
-
- var chosenProducts = [];
- $("#productsBox select[name^='products']").each(function()
- {
- var $product = $(product);
- var productID = $(this).val();
- if(productID > 0 && chosenProducts.indexOf(productID) == -1) chosenProducts.push(productID);
- if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id') && !multiBranchProducts[$product.val()])
- {
- bootbox.alert(errorSameProducts);
- $product.val(0);
- $product.trigger("chosen:updated");
- return false;
- }
- });
-
- chosenProducts.length > 1 ? $('.division').removeClass('hide') : $('.division').addClass('hide');
-
- if($('#productsBox .input-group:last select:first').val() != 0)
- {
- var length = $('#productsBox .row .input-group').size();
- $('#productsBox .row').append('
' + $('#productsBox .col-sm-4:last').html() + '
');
- if($('#productsBox .input-group:last select').size() >= 2) $('#productsBox .input-group:last select:last').remove();
- $('#productsBox .input-group:last .chosen-container').remove();
- $('#productsBox .input-group:last select:first').attr('name', 'products[' + length + ']').attr('id', 'products' + length);
- $('#productsBox .input-group:last .chosen').chosen();
-
- adjustProductBoxMargin();
- }
-
- var $inputgroup = $(product).closest('.input-group');
- if($inputgroup.find('select').size() >= 2) $inputgroup.removeClass('has-branch').find('select:last').remove();
- if($inputgroup.find('.chosen-container').size() >= 2) $inputgroup.find('.chosen-container:last').remove();
-
- var index = $inputgroup.find('select:first').attr('id').replace('products' , '');
- var oldBranch = $(product).attr('data-branch') !== undefined ? $(product).attr('data-branch') : 0;
- $.get(createLink('branch', 'ajaxGetBranches', "productID=" + $(product).val() + "&oldBranch=" + oldBranch + "¶m=active"), function(data)
- {
- if(data)
- {
- $inputgroup.addClass('has-branch').append(data);
- $inputgroup.find('select:last').attr('name', 'branch[' + index + ']').attr('id', 'branch' + index).attr('onchange', "loadPlans('#products" + index + "', this.value)").chosen();
-
- $inputgroup.find('select:last').each(disableSelectedBranch);
- disableSelectedProduct();
- }
-
- var branchID = $('#branch' + index).val();
- loadPlans(product, branchID);
- });
-
- if(!multiBranchProducts[$(product).val()]) disableSelectedProduct();
-
- $("input[name='products[" + index + "]']").remove();
- $("input[name='branch[" + index + "]']").remove();
-}
-
-function loadPlans(product, branchID)
-{
- if($('#plansBox').size() == 0) return false;
-
- var productID = $(product).val();
- var branchID = typeof(branchID) == 'undefined' ? 0 : branchID;
- var planID = $(product).attr('data-plan') !== undefined ? $(product).attr('data-plan') : 0;
- var index = $(product).attr('id').replace('products', '');
-
- $("input[name='products[" + index + "]']").remove();
- $("input[name='branch[" + index + "]']").remove();
-
- $.get(createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=0,' + branchID + '&planID=' + planID + '&fieldID&needCreate=&expired=unexpired,noclosed¶m=skipParent,multiple'), function(data)
- {
- if(data)
- {
- if($("div#plan" + index).size() == 0) $("#plansBox .row").append('');
- $("div#plan" + index).html(data).find('select').attr('name', 'plans[' + productID + ']' + '[' + branchID + '][]').attr('id', 'plans' + productID).chosen();
-
- adjustPlanBoxMargin();
- }
- });
-}
-
-/**
- * Adjust the layout of product selection.
- *
- * @access public
- * @return void
- */
-function adjustProductBoxMargin()
-{
- var productRows = Math.ceil($('#productsBox > .row > .col-sm-4').length / 3);
- if(productRows > 1)
- {
- for(i = 1; i <= productRows - 1; i++)
- {
- $('#productsBox .col-sm-4:lt(' + (i * 3) + ')').css('margin-bottom', '10px');
- }
- }
-}
-
-/**
- * Adjust the layout of the plan selection.
- *
- * @access public
- * @return void
- */
-function adjustPlanBoxMargin()
-{
- var planRows = Math.ceil($('#plansBox > .row > .col-sm-4').length / 3);
- if(planRows > 1)
- {
- for(j = 1; j <= planRows - 1; j++)
- {
- $('#plansBox .col-sm-4:lt(' + (j * 3) + ')').css('margin-bottom', '10px');
- }
- }
-}
-
/**
* Initialization operation.
*
diff --git a/module/project/js/create.js b/module/project/js/create.js
index 7bce25f5f7..ee7393ff6e 100644
--- a/module/project/js/create.js
+++ b/module/project/js/create.js
@@ -370,7 +370,7 @@ function loadBranches(product)
function loadPlans(product, branch)
{
var productID = $(product).val();
- var branchID = $(branch).val() == null ? 0 : $(branch).val();
+ var branchID = $(branch).val() == null ? 0 : '0,' + $(branch).val();
var planID = $(product).attr('data-plan') !== undefined ? $(product).attr('data-plan') : 0;
var index = $(product).attr('id').replace('products', '');
@@ -380,7 +380,7 @@ function loadPlans(product, branch)
{
$("div#plan" + index).find("select[name^='plans']").replaceWith(data);
$("div#plan" + index).find('.chosen-container').remove();
- $("div#plan" + index).find('select').attr('name', 'plans[' + productID + '][' + branchID + '][]').attr('id', 'plans' + productID).chosen();
+ $("div#plan" + index).find('select').attr('name', 'plans[' + productID + ']' + '[]').attr('id', 'plans' + productID).chosen();
}
});
}
diff --git a/module/project/js/edit.js b/module/project/js/edit.js
index 73d391e9c5..e676a6a499 100644
--- a/module/project/js/edit.js
+++ b/module/project/js/edit.js
@@ -32,9 +32,6 @@ $(function()
});
});
- adjustProductBoxMargin();
- adjustPlanBoxMargin();
-
$(document).on('change', '[name*=products]', function()
{
var current = $(this).val();
@@ -173,3 +170,127 @@ function setAclList(programID)
$('.aclBox').html($('#projectAcl').html());
}
}
+
+/**
+ * Load branches.
+ *
+ * @param int $product
+ * @access public
+ * @return void
+ */
+function loadBranches(product)
+{
+ /* When selecting a product, delete a plan that is empty by default. */
+ $("#planDefault").remove();
+
+ var chosenProducts = [];
+ $(".productsBox select[name^='products']").each(function()
+ {
+ var $product = $(product);
+ var productID = $(this).val();
+ if(productID > 0 && chosenProducts.indexOf(productID) == -1) chosenProducts.push(productID);
+ if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id') && !multiBranchProducts[$product.val()])
+ {
+ bootbox.alert(errorSameProducts);
+ $product.val(0);
+ $product.trigger("chosen:updated");
+ return false;
+ }
+ });
+
+ (chosenProducts.length > 1 && model == 'waterfall') ? $('.division').removeClass('hide') : $('.division').addClass('hide');
+
+ var $tableRow = $(product).closest('.table-row');
+ var index = $tableRow.find('select:first').attr('id').replace('products' , '');
+ var oldBranch = $(product).attr('data-branch') !== undefined ? $(product).attr('data-branch') : 0;
+
+ if(!multiBranchProducts[$(product).val()])
+ {
+ $tableRow.find('.table-col:last select').val('').trigger('chosen:updated');
+ $tableRow.find('.table-col:last').addClass('hidden');
+ }
+
+ $.get(createLink('branch', 'ajaxGetBranches', "productID=" + $(product).val() + "&oldBranch=" + oldBranch + "¶m=active"), function(data)
+ {
+ if(data)
+ {
+ $tableRow.find("select[name^='branch']").replaceWith(data);
+ $tableRow.find('.table-col:last .chosen-container').remove();
+ $tableRow.find('.table-col:last').removeClass('hidden');
+ $tableRow.find("select[name^='branch']").attr('multiple', '').attr('name', 'branch[' + index + '][]').attr('id', 'branch' + index).attr('onchange', "loadPlans('#products" + index + "', this)").chosen();
+
+ disableSelectedProduct();
+ }
+
+ var branch = $('#branch' + index);
+ loadPlans(product, branch);
+ });
+}
+
+/**
+ * Load plans.
+ *
+ * @param obj $product
+ * @param obj $branchID
+ * @access public
+ * @return void
+ */
+function loadPlans(product, branch)
+{
+ var productID = $(product).val();
+ var branchID = $(branch).val() == null ? 0 : '0,' + $(branch).val();
+ var planID = $(product).attr('data-plan') !== undefined ? $(product).attr('data-plan') : 0;
+ var index = $(product).attr('id').replace('products', '');
+
+ $.get(createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=' + branchID + '&planID=' + planID + '&fieldID&needCreate=&expired=unexpired,noclosed¶m=skipParent,multiple'), function(data)
+ {
+ if(data)
+ {
+ $("div#plan" + index).find("select[name^='plans']").replaceWith(data);
+ $("div#plan" + index).find('.chosen-container').remove();
+ $("div#plan" + index).find('select').attr('name', 'plans[' + productID + ']' + '[]').attr('id', 'plans' + productID).chosen();
+ }
+ });
+}
+
+/**
+ * Add new line for link product.
+ *
+ * @param obj $obj
+ * @access public
+ * @return void
+ */
+function addNewLine(obj)
+{
+ var newLine = $(obj).closest('tr').clone();
+ var index = 0;
+ $(".productsBox select[name^='products']").each(function()
+ {
+ var id = $(this).attr('id').replace('products' , '');
+
+ id = parseInt(id);
+ id ++;
+
+ index = id > index ? id : index;
+ })
+
+ newLine.addClass('newLine');
+ newLine.find('th').html('');
+ newLine.find('.removeLine').css('visibility', 'visible');
+ newLine.find('.chosen-container').remove();
+ newLine.find('.productsBox .table-col:last').addClass('hidden');
+ newLine.find("select[name^='products']").attr('name', 'products[' + index + ']').attr('id', 'products' + index).val('').chosen();
+ newLine.find("select[name^='plans']").attr('name', 'plans[' + index + '][' + 0 + '][]').chosen();
+ newLine.find("div[id^='plan']").attr('id', 'plan' + index);
+
+ $(obj).closest('tr').after(newLine);
+ var product = newLine.find("select[name^='products']");
+ var branch = newLine.find("select[name^='branch']");
+ loadPlans(product, branch);
+ disableSelectedProduct();
+}
+
+function removeLine(obj)
+{
+ $(obj).closest('tr').remove();
+}
diff --git a/module/project/lang/de.php b/module/project/lang/de.php
index e09b2f5b08..00cdcccc94 100644
--- a/module/project/lang/de.php
+++ b/module/project/lang/de.php
@@ -42,6 +42,7 @@ $lang->project->addWhitelist = 'Project Add Whitelist';
$lang->project->unbindWhitelist = 'Project Remove Whitelist';
$lang->project->manageProducts = 'Manage Products';
$lang->project->manageOtherProducts = 'Manage Other Products';
+$lang->project->manageProductPlan = 'Manage Products And Plans';
$lang->project->copyTitle = 'Please select an project to copy';
$lang->project->errorSameProducts = 'Project cannot be associated with multiple identical products.';
$lang->project->errorSameBranches = 'Project cannot be associated with multiple identical branches.';
diff --git a/module/project/lang/en.php b/module/project/lang/en.php
index bd8aea81c6..378f35cebc 100644
--- a/module/project/lang/en.php
+++ b/module/project/lang/en.php
@@ -42,6 +42,7 @@ $lang->project->addWhitelist = 'Project Add Whitelist';
$lang->project->unbindWhitelist = 'Project Remove Whitelist';
$lang->project->manageProducts = 'Manage Products';
$lang->project->manageOtherProducts = 'Manage Other Products';
+$lang->project->manageProductPlan = 'Manage Products And Plans';
$lang->project->copyTitle = 'Please select an project to copy';
$lang->project->errorSameProducts = 'Project cannot be associated with multiple identical products.';
$lang->project->errorSameBranches = 'Project cannot be associated with multiple identical branches.';
diff --git a/module/project/lang/fr.php b/module/project/lang/fr.php
index 2ee664d94a..114555b75d 100644
--- a/module/project/lang/fr.php
+++ b/module/project/lang/fr.php
@@ -42,6 +42,7 @@ $lang->project->addWhitelist = 'Project Add Whitelist';
$lang->project->unbindWhitelist = 'Project Remove Whitelist';
$lang->project->manageProducts = 'Manage Products';
$lang->project->manageOtherProducts = 'Manage Other Products';
+$lang->project->manageProductPlan = 'Manage Products And Plans';
$lang->project->copyTitle = 'Please select an project to copy';
$lang->project->errorSameProducts = 'Project cannot be associated with multiple identical products.';
$lang->project->errorSameBranches = 'Project cannot be associated with multiple identical branches.';
diff --git a/module/project/lang/vi.php b/module/project/lang/vi.php
index e6b35cab56..f2284e3c3f 100644
--- a/module/project/lang/vi.php
+++ b/module/project/lang/vi.php
@@ -42,6 +42,7 @@ $lang->project->addWhitelist = 'Project Add Whitelist';
$lang->project->unbindWhitelist = 'Project Remove Whitelist';
$lang->project->manageProducts = 'Manage Products';
$lang->project->manageOtherProducts = 'Manage Other Products';
+$lang->project->manageProductPlan = 'Manage Products And Plans';
$lang->project->copyTitle = 'Please select an project to copy';
$lang->project->errorSameProducts = 'Project cannot be associated with multiple identical products.';
$lang->project->errorSameBranches = 'Project cannot be associated with multiple identical branches.';
diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php
index c440a69b35..9a9cc0e98c 100644
--- a/module/project/lang/zh-cn.php
+++ b/module/project/lang/zh-cn.php
@@ -42,6 +42,7 @@ $lang->project->addWhitelist = '项目添加白名单';
$lang->project->unbindWhitelist = '项目删除白名单';
$lang->project->manageProducts = '关联产品';
$lang->project->manageOtherProducts = '关联其他产品';
+$lang->project->manageProductPlan = '关联产品和计划';
$lang->project->copyTitle = '请选择要复制的项目';
$lang->project->errorSameProducts = '项目不能关联多个相同的产品。';
$lang->project->errorSameBranches = '项目不能关联多个相同的分支。';
diff --git a/module/project/model.php b/module/project/model.php
index 81b3bc3dd9..4dfe09b2b3 100644
--- a/module/project/model.php
+++ b/module/project/model.php
@@ -2420,7 +2420,7 @@ class projectModel extends model
$data->project = $projectID;
$data->product = $productID;
$data->branch = $branchID;
- $data->plan = isset($plans[$productID][$branchID]) ? implode(',', $plans[$productID][$branchID]) : $oldPlan;
+ $data->plan = isset($plans[$productID]) ? implode(',', $plans[$productID]) : $oldPlan;
$data->plan = trim($data->plan, ',');
$data->plan = empty($data->plan) ? 0 : ",$data->plan,";
diff --git a/module/project/view/create.html.php b/module/project/view/create.html.php
index 5c1b77ab19..d7cde1dc6c 100755
--- a/module/project/view/create.html.php
+++ b/module/project/view/create.html.php
@@ -139,7 +139,7 @@
| |
- | 关联产品和计划 |
+ project->manageProductPlan;?> |
+
|
hasProduct and $this->config->vision != 'lite'):?>
+
+
- | project->manageProducts;?> |
-
+ | project->manageProductPlan;?> |
+
-
-
- type != 'normal' and isset($branchGroups[$product->id]);?>
- id] as $branchID => $branch):?>
- |
-
- | execution->linkPlan;?> |
-
-
-
-
- id] as $branchID => $branch):?>
- id][$branchID]) ? $productPlans[$product->id][$branchID] : array();?>
- id}][{$branchID}][]", $plans, $branches[$product->id][$branchID]->plan, "class='form-control chosen' multiple");?>
-
-
-
-
-
- |
-
+
+
model == 'waterfall'):?>
division and count($linkedProducts) < 2) ? 'hide' : '';?>