* [perf story #72339] Adjust type field for programplan create for ipd.
This commit is contained in:
@@ -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. */
|
||||
|
||||
@@ -78,6 +78,7 @@ window.handleRenderRow = function($row, index, data)
|
||||
$row.attr('data-level', level);
|
||||
$row.find(nestedTextSelector).attr('title', text).text(text).append(`<input type="hidden" name="level[${index + 1}]" value="${level}">`); // 创建隐藏表单域用于向服务器提交当前行层级信息。
|
||||
|
||||
/* 追加 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("<input type='hidden' name='" + $checkbox.attr('name') + "' value='on' class='hidden'/>")
|
||||
|
||||
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("<input type='hidden' name='" + $checkbox.attr('name') + "' value='off' class='hidden'/>")
|
||||
$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("<input type='hidden' name='" + $checkbox.attr('name') + "' value='on' class='hidden'/>");
|
||||
$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("<input type='hidden' name='" + $nextCheckbox.attr('name') + "' value='off' class='hidden'/>")
|
||||
}
|
||||
|
||||
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("<input type='hidden' name='" + $nextCheckbox.attr('name') + "' value='on' class='hidden'/>");
|
||||
|
||||
$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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user