* Finish task #96497.

This commit is contained in:
sunguangming
2023-07-04 18:26:29 +08:00
parent d98f2aa9d1
commit 25840602af
8 changed files with 399 additions and 166 deletions
+2
View File
@@ -0,0 +1,2 @@
.items-center {align-items: center !important}
#ignore {text-decoration: underline; cursor: pointer; color: #ef7b0f;}
+344
View File
@@ -0,0 +1,344 @@
window.ignoreTips = {
'beyondBudgetTip' : false,
'dateTip' : false
};
var batchEditDateTips = new Array();
/**
* 设置计划结束时间。
* Set plan end date.
*
* @access public
* @return void
*/
function setDate()
{
const delta = $('input[name=delta]:checked').val();
computeEndDate(delta);
}
/**
* 计算两个时间的天数。
* Compute delta of two days.
*
* @param string date1
* @param string date2
* @access public
* @return int
*/
function computeDaysDelta(date1, date2)
{
date1 = convertStringToDate(date1);
date2 = convertStringToDate(date2);
delta = (date2 - date1) / (1000 * 60 * 60 * 24) + 1;
if(isNaN(delta)) return;
weekEnds = 0;
for(i = 0; i < delta; i++)
{
if((weekend == 2 && date1.getDay() == 6) || date1.getDay() == 0) weekEnds ++;
date1 = date1.valueOf();
date1 += 1000 * 60 * 60 * 24;
date1 = new Date(date1);
}
return delta - weekEnds;
}
/**
* 计算可用工作日天数。
* Compute work days.
*
* @param string currentID
* @access public
* @return void
*/
window.computeWorkDays = function(e)
{
isBactchEdit = false;
let currentID = typeof e == 'object' ? $(e.target).attr('id') : '';
if(currentID)
{
index = currentID.replace('begins[', '');
index = index.replace('ends[', '');
index = index.replace(']', '');
if(!isNaN(index)) isBactchEdit = true;
}
if(isBactchEdit)
{
beginDate = $('#begins\\[' + index + '\\]').val();
endDate = $('#ends\\[' + index + '\\]').val();
}
else
{
beginDate = $('#begin').val();
endDate = $('#end').val();
var begin = new Date(beginDate.replace(/-/g,"/"));
var end = new Date(endDate.replace(/-/g,"/"));
var time = end.getTime() - begin.getTime();
var days = parseInt(time / (1000 * 60 * 60 * 24)) + 1;
if(days != $("input[name='delta']:checked").val()) $("input[name='delta']:checked").attr('checked', false);
if(endDate == longTime) $("#delta999").prop('checked', true);
}
outOfDateTip(isBactchEdit ? index : 0);
}
/**
* 计算并设置计划完成时间。
* Compute the end date for project.
*
* @param int delta
* @access public
* @return void
*/
function computeEndDate(delta)
{
beginDate = $('#begin').val();
if(!beginDate) return;
delta = parseInt(delta);
if(delta == 999)
{
$('#end').val('').attr('disabled', true);
outOfDateTip();
return false;
}
$('#end').removeAttr('disabled');
$('#days').closest('.form-row').removeClass('hidden');
beginDate = convertStringToDate(beginDate);
if((delta == 7 || delta == 14) && (beginDate.getDay() == 1))
{
delta = (weekend == 2) ? (delta - 2) : (delta - 1);
}
endDate = formatDate(beginDate, delta - 1);
$('#end').val(endDate);
computeWorkDays();
}
/**
* 给指定日期加上具体天数,并返回格式化后的日期.
*
* @param string dateString
* @param int days
* @access public
* @return date
*/
function formatDate(dateString, days)
{
const date = new Date(dateString);
date.setDate(date.getDate() + days);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
/**
* Convert a date string like 2011-11-11 to date object in js.
*
* @param string dateString
* @access public
* @return date
*/
function convertStringToDate(dateString)
{
dateString = dateString.split('-');
return new Date(dateString[0], dateString[1] - 1, dateString[2]);
}
/**
* If future is checked, disable budget input.
*
* @param object e
* @access public
* @return void
*/
window.toggleBudget = function(e)
{
const future = e.target;
if($(future).prop('checked'))
{
$('#budget').val('').attr('disabled', 'disabled');
}
else
{
$('#budget').removeAttr('disabled');
}
}
/**
* If change multiple, set delta.
*
* @param object e
* @access public
* @return void
*/
window.toggleMultiple = function(e)
{
const multiple = e.target;
$('#delta_999').closest('.radio-primary').toggle($(multiple).val() != 0);
if($('#delta_999').prop('checked') && $(multiple).val() == 0)
{
$('#delta_999').prop('checked', false);
$('#end').removeAttr('disabled').val('');
$('#days').closest('.form-row').removeClass('hidden');
}
}
/**
* compare childlish date.
*
* @access public
* @return void
*/
function compareChildDate()
{
if(window.ignoreTips['dateTip']) return;
if(page == 'create') return;
var end = $('#end').val();
var begin = $('#begin').val();
var selectedProgramID = $('#parent').val();
if($('#dateTip').length > 0) $('#dateTip').closest('.form-row').remove();
if(end == longTime) end = LONG_TIME;
if(end.length > 0 && begin.length > 0)
{
var programEnd = new Date(end);
var programBegin = new Date(begin);
$.get($.createLink('project', 'ajaxGetProjectFormInfo', 'objectType=program&objectID=' + programID + '&selectedProgramID=' + selectedProgramID), function(data)
{
var childInfo = JSON.parse(data);
if(childInfo.maxChildEnd == '' || childInfo.minChildBegin == '') return;
var childBegin = new Date(childInfo.minChildBegin);
var childEnd = new Date(childInfo.maxChildEnd);
if(programBegin <= childBegin && programEnd >= childEnd) return;
var dateTip = '';
if(programBegin > childBegin)
{
dateTip = "<tr><td></td><td colspan='2'><span id='dateTip' class='text-remind'><p>" + beginGreateChild + childInfo.minChildBegin + "</p><p id='ignore' onclick='ignoreTip(this)'>" + ignore + "</p></span></td></tr>";
}
else if(programEnd < childEnd)
{
dateTip = "<tr><td></td><td colspan='2'><span id='dateTip' class='text-remind'><p>" + endLetterChild + childInfo.maxChildEnd + "</p><p id='ignore' onclick='ignoreTip(this)'>" + ignore + "</p></span></td></tr>";
}
$('#dateBox').parent().parent().after(dateTip);
$('#dateTip').parent().css('line-height', '0');
});
}
}
/**
*The date is out of the range of the parent project set, and a prompt is given.
*
* @param string $currentID
* @access public
* @return void
*/
function outOfDateTip(currentID)
{
if(window.ignoreTips['dateTip']) return;
var end = $('#end').val();
var begin = $('#begin').val();
if($('#dateTip').length > 0) $('#dateTip').closest('.form-row').remove();
if(end == longTime) end = LONG_TIME;
if(end.length > 0 && begin.length > 0)
{
var selectedProgramID = $('#parent').val();
var programEnd = new Date(end);
var programBegin = new Date(begin);
if(selectedProgramID == 0)
{
compareChildDate();
return;
}
if(typeof(programID) == 'undefined') programID = 0;
$.get($.createLink('project', 'ajaxGetProjectFormInfo', 'objectType=program&objectID=' + programID + "&selectedProgramID=" + selectedProgramID), function(data)
{
var dateTip = '';
var data = JSON.parse(data);
var parentEnd = new Date(data.selectedProgramEnd);
var parentBegin = new Date(data.selectedProgramBegin);
if(programBegin >= parentBegin && programEnd <= parentEnd)
{
compareChildDate();
return;
}
if(programBegin < parentBegin)
{
dateTip = "<div class='form-row' id='dateTipBox'><div class='form-group'><div class='input-group'><span id='dateTip' class='text-remind'><p>" + beginLetterParent + data.selectedProgramBegin + "</p><p id='ignore' onclick='ignoreTip(this)'>" + ignore + "</p></span></div></div></div>";
}
else if(programEnd > parentEnd)
{
dateTip = "<div class='form-row' id='dateTipBox'><div class='form-group'><div class='input-group'><span id='dateTip' class='text-remind'><p>" + endGreaterParent + data.selectedProgramEnd + "</p><p id='ignore' onclick='ignoreTip(this)'>" + ignore + "</p></span></div></div></div>";
}
$('#begin').closest('.form-row').after(dateTip);
});
}
}
/**
* Append prompt when the budget exceeds the parent project set.
*
* @access public
* @return void
*/
window.budgetOverrunTips = function(e)
{
if(window.ignoreTips['beyondBudgetTip']) return;
var selectedProgramID = $('#parent').val();
var budget = $('#budget').val();
if(selectedProgramID == 0)
{
if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').closest('.form-row').remove();
return false;
}
if(typeof(programID) == 'undefined') programID = 0;
$.get($.createLink('project', 'ajaxGetProjectFormInfo', 'objectType=program&objectID=' + programID + "&selectedProgramID=" + selectedProgramID), function(data)
{
var data = JSON.parse(data);
var tip = "";
if(budget !=0 && budget !== null && budget > data.availableBudget) var tip = "<div class='form-row'><div class='form-group'><div class='input-group'><span id='beyondBudgetTip' class='text-remind'><p>" + budgetOverrun + currencySymbol[data.budgetUnit] + data.availableBudget + "</p><p id='ignore' onclick='ignoreTip(this)'>" + ignore + "</p></span></div></div></div>";
if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').closest('.form-row').remove();
$('#budgetRow').after(tip);
});
}
/**
* Make this prompt no longer appear.
*
* @param string $obj
* @access public
* @return void
*/
window.ignoreTip = function(obj)
{
var parentID = obj.parentNode.id;
$('#' + parentID).closest('.form-row').remove();
if(parentID == 'dateTip') window.ignoreTips['dateTip'] = true;
if(parentID == 'beyondBudgetTip') window.ignoreTips['beyondBudgetTip'] = true;
}
-119
View File
@@ -5,17 +5,6 @@ function onParentChange(event)
loadPage(url, '#budgetRow>*, #acl');
}
function onBudgetChange(event)
{
const $budget = $(event.target);
const currentBudget = $budget.val();
const budgetLeft = $budget.data('budget-left');
if(currentBudget > budgetLeft)
{
$('<div class="form-tip text-warning" id="budgetTip"></div>').text(lang.budgetOverrun + $budget.data('currency-symbol') + budgetLeft).append($('<a class="text-inherit ml-2 underline"></a>').text(lang.ignore).on('click', () => $('#budgetTip').remove())).appendTo($budget.closest('.form-group'));
}
}
window.onFutureChange = (event) =>
{
$('#budget,#budgetUnit').attr('disabled', $(event.target).prop('checked') ? 'disabled' : null);
@@ -27,114 +16,6 @@ window.outOfDateTip = function()
console.warn('The method outOfDateTip is not implemented.');
};
/**
* Compute delta of two days.
*
* @param string date1
* @param string date2
* @access public
* @return int
*/
function computeDaysDelta(date1, date2)
{
date1 = zui.createDate(date1);
date2 = zui.createDate(date2);
const delta = (date2 - date1) / (1000 * 60 * 60 * 24) + 1;
let weekEnds = 0;
for(i = 0; i < delta; i++)
{
if((weekend == 2 && date1.getDay() == 6) || date1.getDay() == 0) weekEnds ++;
date1 = date1.valueOf();
date1 += 1000 * 60 * 60 * 24;
date1 = new Date(date1);
}
return delta - weekEnds;
}
/**
* Compute work days.
*
* @param string currentID
* @access public
* @return void
*/
window.computeWorkDays = function(currentID)
{
if(typeof currentID === 'object') currentID = $(currentID.target).val();
let isBactchEdit = false;
let index;
if(currentID)
{
index = currentID.replace('begins[', '');
index = index.replace('ends[', '');
index = index.replace(']', '');
if(!isNaN(index)) isBactchEdit = true;
}
let beginDate;
let endDate;
if(isBactchEdit)
{
beginDate = $('#begins\\[' + index + '\\]').val();
endDate = $('#ends\\[' + index + '\\]').val();
}
else
{
beginDate = $('#begin').val();
endDate = $('#end').val();
var begin = new Date(beginDate.replace(/-/g,"/"));
var end = new Date(endDate.replace(/-/g,"/"));
var time = end.getTime() - begin.getTime();
var days = parseInt(time / (1000 * 60 * 60 * 24)) + 1;
if(days != $('input[name="delta"]:checked').val()) $('input[name="delta"]:checked').attr('checked', false);
if(endDate == LONG_TIME) $('#delta999').prop('checked', true);
}
if(beginDate && endDate)
{
if(isBactchEdit) $('#dayses\\[' + index + '\\]').val(computeDaysDelta(beginDate, endDate));
else $('#days').val(computeDaysDelta(beginDate, endDate));
}
else if($('input[checked="true"]').val())
{
computeEndDate();
}
outOfDateTip();
};
/**
* Compute the end date for project.
*
* @param int $delta
* @access public
* @return void
*/
window.computeEndDate = function(delta)
{
delta = +$('input[name="delta"]:checked').val();
let beginDate = $('#begin').val();
if(!beginDate) return;
if(delta === 999)
{
$('#end').val(LONG_TIME);
outOfDateTip();
return false;
}
beginDate = zui.createDate(beginDate);
if((delta === 7 || delta === 14) && (beginDate.getDay() === 1))
{
delta = (weekend === 2) ? (delta - 2) : (delta - 1);
}
const endDate = zui.formatDate(beginDate.getTime() + ((delta - 1) * zui.TIME_DAY), 'yyyy-MM-dd');
$('#end').val(endDate);
computeWorkDays();
};
window.onAclChange = () =>
{
$('#whitelistRow').toggleClass('hidden', $('#acl_open').prop('checked'));
+3 -3
View File
@@ -146,16 +146,16 @@ $lang->program->endList[186] = 'Half year';
$lang->program->endList[365] = 'One year';
$lang->program->endList[999] = 'Longtime';
$lang->program->aclList['private'] = "Private (accessible to {$lang->projectCommon} portfolio holders and stakeholders, stakeholders can follow up maintenance)";
$lang->program->aclList['open'] = "Default(user who can visit the program can access it)";
$lang->program->aclList['private'] = "Private (accessible to {$lang->projectCommon} portfolio holders and stakeholders, stakeholders can follow up maintenance)";
$lang->program->subAclList['private'] = "Private (accessible to this program set leader and stakeholders, stakeholders can follow up maintenance)";
$lang->program->subAclList['open'] = "Default (user who can visit the program can access it)";
$lang->program->subAclList['program'] = "Open within the program (accessible to all higher-level program directors and affiliates, as well as to this program director and affiliates)";
$lang->program->subAclList['private'] = "Private (accessible to this program set leader and stakeholders, stakeholders can follow up maintenance)";
$lang->program->subAcls['private'] = 'Private';
$lang->program->subAcls['open'] = 'Default';
$lang->program->subAcls['program'] = 'Open within the program';
$lang->program->subAcls['private'] = 'Private';
$lang->program->authList['extend'] = 'Inherit (program privileges and company privileges)';
$lang->program->authList['reset'] = 'Reset (program privileges only)';
+3 -3
View File
@@ -146,16 +146,16 @@ $lang->program->endList[186] = 'Half year';
$lang->program->endList[365] = 'One year';
$lang->program->endList[999] = 'Longtime';
$lang->program->aclList['private'] = "Private (accessible to {$lang->projectCommon} portfolio holders and stakeholders, stakeholders can follow up maintenance)";
$lang->program->aclList['open'] = "Default(user who can visit the program can access it)";
$lang->program->aclList['private'] = "Private (accessible to {$lang->projectCommon} portfolio holders and stakeholders, stakeholders can follow up maintenance)";
$lang->program->subAclList['private'] = "Private (accessible to this program set leader and stakeholders, stakeholders can follow up maintenance)";
$lang->program->subAclList['open'] = "Default (user who can visit the program can access it)";
$lang->program->subAclList['program'] = "Open within the program (accessible to all higher-level program directors and affiliates, as well as to this program director and affiliates)";
$lang->program->subAclList['private'] = "Private (accessible to this program set leader and stakeholders, stakeholders can follow up maintenance)";
$lang->program->subAcls['private'] = 'Private';
$lang->program->subAcls['open'] = 'Default';
$lang->program->subAcls['program'] = 'Open within the program';
$lang->program->subAcls['private'] = 'Private';
$lang->program->authList['extend'] = 'Inherit (program privileges and company privileges)';
$lang->program->authList['reset'] = 'Reset (program privileges only)';
+3 -3
View File
@@ -146,16 +146,16 @@ $lang->program->endList[186] = 'Half year';
$lang->program->endList[365] = 'One year';
$lang->program->endList[999] = 'Longtime';
$lang->program->aclList['private'] = "Private (accessible to {$lang->projectCommon} portfolio holders and stakeholders, stakeholders can follow up maintenance)";
$lang->program->aclList['open'] = "Default(user who can visit the program can access it)";
$lang->program->aclList['private'] = "Private (accessible to {$lang->projectCommon} portfolio holders and stakeholders, stakeholders can follow up maintenance)";
$lang->program->subAclList['private'] = "Private (accessible to this program set leader and stakeholders, stakeholders can follow up maintenance)";
$lang->program->subAclList['open'] = "Default (user who can visit the program can access it)";
$lang->program->subAclList['program'] = "Open within the program (accessible to all higher-level program directors and affiliates, as well as to this program director and affiliates)";
$lang->program->subAclList['private'] = "Private (accessible to this program set leader and stakeholders, stakeholders can follow up maintenance)";
$lang->program->subAcls['private'] = 'Private';
$lang->program->subAcls['open'] = 'Default';
$lang->program->subAcls['program'] = 'Open within the program';
$lang->program->subAcls['private'] = 'Private';
$lang->program->authList['extend'] = 'Inherit (program privileges and company privileges)';
$lang->program->authList['reset'] = 'Reset (program privileges only)';
+3 -3
View File
@@ -146,16 +146,16 @@ $lang->program->endList[186] = '半年';
$lang->program->endList[365] = '一年';
$lang->program->endList[999] = '长期';
$lang->program->aclList['private'] = "私有(项目集负责人和干系人可访问,干系人可后续维护)";
$lang->program->aclList['open'] = "公开(有项目集视图权限,即可访问)";
$lang->program->aclList['private'] = "私有(项目集负责人和干系人可访问,干系人可后续维护)";
$lang->program->subAclList['private'] = "私有(本项目集负责人和干系人可访问,干系人可后续维护)";
$lang->program->subAclList['open'] = "全部公开(有项目集视图权限,即可访问)";
$lang->program->subAclList['program'] = "项目集内公开(所有上级项目集负责人和干系人、本项目集负责人和干系人可访问)";
$lang->program->subAclList['private'] = "私有(本项目集负责人和干系人可访问,干系人可后续维护)";
$lang->program->subAcls['private'] = '私有';
$lang->program->subAcls['open'] = '全部公开';
$lang->program->subAcls['program'] = '项目集内公开';
$lang->program->subAcls['private'] = '私有';
$lang->program->authList['extend'] = "继承 (取{$lang->projectCommon}权限与组织权限的并集)";
$lang->program->authList['reset'] = "重新定义 (只取{$lang->projectCommon}权限)";
+41 -35
View File
@@ -7,16 +7,31 @@ $aclList = $parentProgram ? $lang->program->subAclList : $lang->progra
$budgetPlaceholder = $parentProgram ? $lang->program->parentBudget . zget($lang->project->currencySymbol, $parentProgram->budgetUnit) . $budgetLeft : '';
$budgetAvaliable = !$parentID || $budgetLeft;
jsVar('LONG_TIME', LONG_TIME);
jsVar('lang', ['budgetOverrun' => $lang->project->budgetOverrun, 'currencySymbol' => $lang->project->currencySymbol, 'ignore' => $lang->program->ignore]);
jsVar('longTime', $lang->project->longTime);
jsVar('weekend', $config->execution->weekend);
jsVar('page', 'create');
jsVar('parentBudget', $lang->program->parentBudget);
jsVar('beginLetterParent', $lang->program->beginLetterParent);
jsVar('endGreaterParent', $lang->program->endGreaterParent);
jsVar('ignore', $lang->program->ignore);
jsVar('currencySymbol', $lang->project->currencySymbol);
jsVar('budgetOverrun', $lang->project->budgetOverrun);
set::title($parentID ? $lang->program->children : $lang->program->create);
$currency = $parentProgram ? $parentProgram->budgetUnit : $config->project->defaultCurrency;
formPanel
(
to::heading
(
div
(
setClass('panel-title text-lg'),
$title
)
),
on::change('#parent', 'onParentChange'),
on::change('#budget', 'onBudgetChange'),
on::change('#budget', 'budgetOverrunTips'),
on::change('#future', 'onFutureChange'),
on::change('#acl', 'onAclChange'),
formGroup
@@ -24,7 +39,6 @@ formPanel
set::width('1/2'),
set::name('parent'),
set::label($lang->program->parent),
set::disabled($parentID),
set::value($parentID),
set::items($parents),
),
@@ -47,37 +61,27 @@ formPanel
set::id('budgetRow'),
formGroup
(
set::width('1/2'),
set::label($lang->program->budget),
inputGroup
set::width('1/4'),
set::name('budget'),
set::label($lang->project->budget),
set::control(array
(
set::seg(true),
input
(
set::name('budget'),
set::placeholder($budgetPlaceholder),
set::disabled(!$budgetAvaliable),
set('data-budget-left', $budgetLeft),
set('data-currency-symbol', $parentProgram ? zget($lang->project->currencySymbol, $parentProgram->budgetUnit) : NULL),
),
select
(
zui::width('1/3'),
set::name('budgetUnit'),
set::disabled($parentID || !$budgetAvaliable),
set::items($budgetUnitList),
set::value($currency)
)
)
'type' => 'inputControl',
'prefix' => zget($lang->project->currencySymbol, $currency),
'prefixWidth' => 'icon',
'suffix' => $lang->project->tenThousandYuan,
'suffixWidth' => 60,
)),
$parentProgram ? null : formHidden('budgetUnit', $config->project->defaultCurrency)
),
formHidden('budgetUnit', $currency),
formGroup
(
set::width('1/4'),
set::name('future'),
set::value('1'),
set::disabled(!$budgetAvaliable),
set::control(['type' => 'checkbox', 'rootClass' => 'ml-4', 'text' => $lang->project->future, 'checked' => !$budgetAvaliable])
),
set::class('items-center'),
set::control(array('type' => 'checkList', 'inline' => true)),
set::items(array('1' => $lang->project->future)),
)
),
formRow
(
@@ -93,6 +97,7 @@ formPanel
(
set::type('date'),
set::name('begin'),
set::id('begin'),
set::value(date('Y-m-d')),
set::placeholder($lang->project->begin),
set::required(true),
@@ -103,21 +108,21 @@ formPanel
(
set::type('date'),
set::name('end'),
set::id('end'),
set::placeholder($lang->project->end),
set::required(true),
on::change('outOfDateTip')
on::change('computeWorkDays')
),
)
),
formGroup
(
set::name('delta'),
set::class('pl-4'),
set::class('pl-4 items-center'),
set::control(['type' => 'radioList', 'inline' => true, 'rootClass' => 'ml-4', 'items' => $lang->program->endList]),
on::change('computeEndDate')
on::change('setDate'),
),
),
/* TODO: printExtendFields() */
formGroup
(
set::name('desc'),
@@ -129,13 +134,14 @@ formPanel
(
set::name('acl'),
set::label($lang->program->acl),
set::value('private'),
set::value('open'),
set::items($aclList),
set::control('radioList'),
),
formRow
(
set::id('whitelistRow'),
setClass('hidden'),
formGroup
(
set::width('3/4'),