diff --git a/module/programplan/control.php b/module/programplan/control.php
index 67bd8eb8a7..e9486c28ff 100644
--- a/module/programplan/control.php
+++ b/module/programplan/control.php
@@ -113,23 +113,15 @@ class programplan extends control
$project = $this->project->getById($projectID);
$programPlan = $this->project->getById($planID);
$productList = $this->session->hasProduct ? $this->product->getProductPairsByProject($projectID) : array();
- $executions = !empty($planID) ? $this->loadModel('execution')->getChildExecutions($planID, 'order_asc,grade_asc', 'all') : array();
- $plans = $this->programplan->getStage($planID ?: $projectID, $this->productID, 'all', 'order_asc,grade_asc');
- if(!empty($planID) and in_array($project->model, array('ipd', 'waterfallplus')))
+ $plans = $this->programplan->getStage($projectID, $this->productID, 'all', 'order_asc,grade_asc');
+ if($planID)
{
- if(!empty($plans))
+ foreach($plans as $planID => $plan)
{
- $executionType = 'stage';
- unset($this->lang->programplan->typeList['agileplus']);
- }
- elseif(!empty($executions))
- {
- $executionType = 'agileplus';
- unset($this->lang->programplan->typeList['stage']);
+ if($plan->path == $programPlan->path || strpos($plan->path, $programPlan->path) !== 0) unset($plans[$planID]);
}
}
- if(!empty($executions)) $plans = $executions;
$plans = $this->programplanZen->sortPlans($plans);
/* Set programplan typeList. */
diff --git a/module/programplan/js/create.ui.js b/module/programplan/js/create.ui.js
index 0a28abf4af..5ecff95a3c 100644
--- a/module/programplan/js/create.ui.js
+++ b/module/programplan/js/create.ui.js
@@ -78,6 +78,7 @@ window.handleRenderRow = function($row, index, data)
$row.attr('data-level', level);
$row.find(nestedTextSelector).attr('title', text).text(text).append(``); // 创建隐藏表单域用于向服务器提交当前行层级信息。
+ /* 追加 parent 属性,以记录父级index。 */
$row.attr('data-parent', '-1');
if($prevRow.length == 1)
{
@@ -110,21 +111,25 @@ window.handleRenderRow = function($row, index, data)
{
let $typePicker = info[0];
- let dataExist = (typeof data != 'undefined' && typeof data.id != 'undefined');
- let options = {};
- options.disabled = level == 0 ? true : false;
+ let dataExist = (typeof data != 'undefined' && typeof data.type != 'undefined');
+ let options = {};
+ options.disabled = (planID == 0 && level == 0) ? true : false;
if(dataExist) options.disabled = true;
+ let prevType = '';
if(level > 0)
{
- let parentID = $row.attr('data-parent');
- let $parentRow = $row.parent().find('tr[data-index="' + parentID + '"]');
- let $firstChildRow = $parentRow.next();
- if($firstChildRow.attr('data-index') != $row.attr('data-index'))
+ let parentID = $row.attr('data-parent');
+ let $parentRow = $row.parent().find('tr[data-index="' + parentID + '"]');
+ let $firstChild = $parentRow.next();
+ if($firstChild.length > 0)
{
- let pickerOptions = JSON.parse($firstChildRow.find('[data-name="type"]').find('.picker-box').attr('zui-create-picker'));
- let prevType = pickerOptions.defaultValue;
- options.items = [];
+ let $firstType = $firstChild.find('[data-name="type"]').find('[name^=type]');
+ if($firstType.length > 0) prevType = $firstType.val();
+ }
+ if(prevType && $firstChild.attr('data-index') != $row.attr('data-index'))
+ {
+ options.items = [];
for(i in $typePicker.options.items)
{
let item = $typePicker.options.items[i];
@@ -134,15 +139,30 @@ window.handleRenderRow = function($row, index, data)
}
}
}
+ else if(level == 0 && planID && $row.attr('data-index') > 0)
+ {
+ options.items = [];
+ for(i in $typePicker.options.items)
+ {
+ let item = $typePicker.options.items[i];
+ if(item.value == '') continue;
+ if(initType == 'stage' && item.value == 'stage') options.items.push(item);
+ if(initType != 'stage' && item.value != 'stage') options.items.push(item);
+ }
+ }
+
$typePicker.render(options);
- if(!dataExist && typeof prevType != 'undefined' && prevType != 'stage') $typePicker.$.setValue('sprint');
+ if(!dataExist)
+ {
+ if(level > 0 && prevType != '' && prevType != 'stage') $typePicker.$.setValue('sprint');
+ if(level == 0 && planID) $typePicker.$.setValue(initType);
+ }
});
if(project.model == 'ipd')
{
- $row.find('[data-name="ACTIONS"]').find('[data-type="sort"]').addClass('hidden');
- if(level == 0) $row.find('[data-name="ACTIONS"]').find('[data-type="addSibling"]').addClass('disabled').prop('disabled', true);
- if(level == 0) $row.find('[data-name="type"]').find('.picker-box').on('inited', function(e, info){ info[0].render({disabled: true}); });
+ if(planID == 0)$row.find('[data-name="ACTIONS"]').find('[data-type="sort"]').addClass('hidden');
+ if(level == 0 && planID == 0) $row.find('[data-name="ACTIONS"]').find('[data-type="addSibling"]').addClass('disabled').prop('disabled', true);
$row.find('[data-name="attribute"]').find('.picker-box').on('inited', function(e, info){ info[0].render({disabled: true}); });
@@ -175,13 +195,15 @@ window.handleRenderRow = function($row, index, data)
info[0].render({items: items, disabled: disabled});
});
- if(level > 0)
+ const $enabled = $row.find('td[data-name=enabled]');
+ if($enabled.length > 0)
{
- const $enabled = $row.find('td[data-name=enabled]');
const $checkbox = $enabled.find('input[type=checkbox]');
- $checkbox.attr('disabled', 'disabled').attr('title', cropStageTip);
+ if(level > 0) $checkbox.attr('disabled', 'disabled').attr('title', cropStageTip);
- $rootRow = $prevRow;
+ if($enabled.find('input.hidden').length == 0) $enabled.append("")
+
+ let $rootRow = $row;
while($rootRow.length == 1)
{
if($rootRow.attr('data-level') == 0) break;
@@ -191,7 +213,7 @@ window.handleRenderRow = function($row, index, data)
{
$row.addClass('disabled');
$checkbox.prop('checked', false);
- $enabled.append("")
+ $enabled.find('input.hidden').val('off');
}
}
@@ -287,6 +309,10 @@ window.changeEnabled = function(obj)
const $row = $target.closest('tr');
$row.toggleClass('disabled', !$target.prop('checked'))
+ let $checkbox = $row.find('[data-name=enabled]').find('input[type=checkbox]');
+ if($row.find('[data-name=enabled]').find('input.hidden') == 0) $row.find('[data-name=enabled]').append("");
+ $row.find('[data-name=enabled]').find('input.hidden').val($target.prop('checked') ? 'on' : 'off');
+
let $nextRow = $row.next();
while(true)
{
@@ -294,17 +320,12 @@ window.changeEnabled = function(obj)
if($nextRow.attr('data-level') == 0) break;
$nextRow.toggleClass('disabled', !$target.prop('checked'))
- if($target.prop('checked'))
- {
- $nextRow.find('[data-name=enabled]').find('input[type=checkbox]').prop('checked', true);
- $nextRow.find('[data-name=enabled]').find('input.hidden').remove();
- }
- else
- {
- let $nextCheckbox = $nextRow.find('[data-name=enabled]').find('input[type=checkbox]');
- $nextCheckbox.prop('checked', false);
- $nextRow.find('[data-name=enabled]').append("")
- }
+
+ let $nextCheckbox = $nextRow.find('[data-name=enabled]').find('input[type=checkbox]');
+ if($nextRow.find('[data-name=enabled]').find('input.hidden') == 0) $nextRow.find('[data-name=enabled]').append("");
+
+ $nextCheckbox.prop('checked', $target.prop('checked'));
+ $nextRow.find('[data-name=enabled]').find('input.hidden').val($target.prop('checked') ? 'on' : 'off');
$nextRow = $nextRow.next();
}
@@ -363,7 +384,6 @@ window.changeType = function(obj)
}
}
-
$nextRow = $row.next();
if($nextRow.length == 0) return;
if($nextRow.attr('data-level') < level) return;
@@ -372,7 +392,9 @@ window.changeType = function(obj)
$nextRow.find('[data-name="ACTIONS"]').find('[data-type="addSub"]').toggleClass('disabled', type != 'stage').prop('disabled', type != 'stage');
let $nextTypePicker = $nextRow.find('.picker-box[data-name=type]').zui('picker');
- let nextTypeItems = [];
+ if($nextTypePicker == undefined) return;
+
+ let nextTypeItems = [];
for(i in typeList)
{
if(i == '') continue;
diff --git a/module/programplan/ui/create.html.php b/module/programplan/ui/create.html.php
index 64b029c7b1..b854e9cc29 100644
--- a/module/programplan/ui/create.html.php
+++ b/module/programplan/ui/create.html.php
@@ -66,77 +66,28 @@ $fnGenerateStageByProductList = function() use ($productID, $productList, $proje
/* Generate checkboxes for sub-stage management. */
$fnGenerateSubPlanManageFields = function() use ($lang, $planID, $project, $executionType, $canParallel)
{
- if((empty($planID) && $project->model != 'ipd') || !in_array($project->model, array('waterfallplus', 'ipd'))) return div();
+ if(!(empty($planID) && $project->model == 'ipd')) return div();
- if(empty($planID) && $project->model == 'ipd')
+ foreach($lang->programplan->parallelList as $key => $value)
{
- foreach($lang->programplan->parallelList as $key => $value)
- {
- $items[] = div(setClass('px-1'), checkbox
- (
- set::type('radio'),
- set::name('parallel'),
- set::text($value),
- set::value($key),
- set::checked($key == $project->parallel),
- set::disabled($canParallel),
- on::change('window.onChangeParallel')
- ));
- }
-
- return div
+ $items[] = div(setClass('px-1'), checkbox
(
- setClass('flex w-1/2 items-center'),
- div(setClass('font-bold'), $lang->programplan->parallel . ':'),
- $items,
- html($lang->programplan->parallelTip)
- );
+ set::type('radio'),
+ set::name('parallel'),
+ set::text($value),
+ set::value($key),
+ set::checked($key == $project->parallel),
+ set::disabled($canParallel),
+ on::change('window.onChangeParallel')
+ ));
}
- $typeList = $lang->programplan->typeList;
-
- $items = array();
- if(count($typeList) > 1)
- {
- foreach($typeList as $key => $value)
- {
- $items[] = div(setClass('px-1'), checkbox
- (
- set::type('radio'),
- set::name('executionType'),
- set::text($value),
- set::value($key),
- on::change('window.onChangeExecutionType'),
- set::checked($key == $executionType)
- ));
- }
- }
- else
- {
- $items[] = div(setClass('px-1'), zget($typeList, $executionType));
- }
-
- /* Append method tip. */
- $items[] = icon(
- 'help',
- setID('methodTip'),
- setClass('ml-2 text-gray'),
- setData(array('toggle' => 'tooltip', 'title' => $lang->programplan->methodTip, 'placement' => 'right', 'type' => 'white', 'class-name' => 'text-gray border border-light')),
- );
-
- $items[] = tooltip(
- set::_to('#methodTip'),
- set::title($lang->programplan->methodTip),
- set::placement('right'),
- set::type('white'),
- setClass('text-darker border border-light')
- );
-
return div
(
setClass('flex w-1/2 items-center'),
- div(setClass('font-bold'), $lang->programplan->subPlanManage . ':'),
- $items
+ div(setClass('font-bold'), $lang->programplan->parallel . ':'),
+ $items,
+ html($lang->programplan->parallelTip)
);
};
@@ -185,9 +136,9 @@ $fnGenerateFields = function() use ($config, $lang, $requiredFields, $showFields
}
/* Field for agileplus. */
- if($name == 'type' && !empty($planID) && in_array($project->model, array('waterfallplus', 'ipd')))
+ if($name == 'type' && in_array($project->model, array('waterfallplus', 'ipd')))
{
- $field['hidden'] = $executionType == 'stage';
+ $field['hidden'] = false;
$field['items'] = $lang->execution->typeList;
}
if($name == 'milestone') $field['width'] = '100px';
@@ -274,6 +225,7 @@ jsVar('planID', $planID);
jsVar('type', $executionType);
jsVar('project', $project);
jsVar('plans', $plans);
+jsVar('initType', ($planID && $plans) ? reset($plans)->type : 'stage');
jsVar('planGrade', $programPlan ? $programPlan->grade + 1 : 1);
jsVar('syncData', $syncData);
jsVar('cropStageTip', $lang->programplan->cropStageTip);
diff --git a/module/programplan/zen.php b/module/programplan/zen.php
index f00ee46df5..d23184e624 100644
--- a/module/programplan/zen.php
+++ b/module/programplan/zen.php
@@ -355,8 +355,8 @@ class programplanZen extends programplan
if($field) $visibleFields[$field] = '';
}
- if($viewData->project->model == 'waterfallplus' && $viewData->executionType == 'stage') $createRequiredFields = 'type,' . trim($createRequiredFields, ',');
- if($viewData->project->model == 'ipd' && $viewData->executionType == 'stage' ) $createRequiredFields = 'enabled,point,type,' . trim($createRequiredFields, ',');
+ if($viewData->project->model == 'waterfallplus') $createRequiredFields = 'type,' . trim($createRequiredFields, ',');
+ if($viewData->project->model == 'ipd') $createRequiredFields = ($viewData->planID ? 'type,' : 'enabled,point,type,') . trim($createRequiredFields, ',');
foreach(explode(',', $createRequiredFields) as $field)
{
if($field)