* [perf story #72339] Adjust type field for programplan create for ipd.

This commit is contained in:
wangyidong
2025-04-14 10:41:30 +08:00
committed by 刘刚
parent ffc91ccc72
commit dbc85eef48
4 changed files with 77 additions and 111 deletions
+4 -12
View File
@@ -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. */
+54 -32
View File
@@ -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;
+17 -65
View File
@@ -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);
+2 -2
View File
@@ -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)