UNPKG

@syncfusion/ej2-gantt

Version:
1,031 lines (1,028 loc) 2.68 MB
import { isNullOrUndefined, extend, getValue, setValue, EventHandler, formatUnit, createElement, removeClass, addClass, closest, Browser, append, merge, remove, deleteObject, initializeCSPTemplate, Property, ChildProperty, Collection, Complex, SanitizeHtmlHelper, compile, isObject, Internationalization, L10n, KeyboardEvents, isUndefined, isObjectArray, Event, NotifyPropertyChanges, Component, classList } from '@syncfusion/ej2-base'; import { Tooltip as Tooltip$1, createSpinner, showSpinner, hideSpinner, Dialog } from '@syncfusion/ej2-popups'; import { DataManager, ODataAdaptor, ODataV4Adaptor, WebApiAdaptor, WebMethodAdaptor, CacheAdaptor, RemoteSaveAdaptor, UrlAdaptor, Query, DataUtil, Deferred } from '@syncfusion/ej2-data'; import { click, Predicate, getActualProperties, getObject, ExcelExport as ExcelExport$1, PdfExport as PdfExport$1, Print, Search, Toolbar as Toolbar$1, RowDD as RowDD$1, DetailRow, Reorder as Reorder$1, Resize as Resize$1, ContextMenu as ContextMenu$1, ColumnMenu as ColumnMenu$1, ColumnChooser, Aggregate, Edit as Edit$2, Group, Page, Sort as Sort$1, Filter as Filter$1, Grid, ForeignKey, filterAfterOpen, getFilterMenuPostion, getCustomDateFormat, setCssInGridPopUp, parentsUntil as parentsUntil$1, ValueFormatter, getForeignData } from '@syncfusion/ej2-grids'; import { TreeGrid, Edit as Edit$1, VirtualScroll as VirtualScroll$1, Toolbar as Toolbar$2, Selection as Selection$2, RowDD as RowDD$2, Reorder as Reorder$2, Resize as Resize$2, Aggregate as Aggregate$1, Page as Page$1, Sort as Sort$2, Filter as Filter$2, ContextMenu as ContextMenu$3, ExcelExport as ExcelExport$2, ColumnMenu as ColumnMenu$2 } from '@syncfusion/ej2-treegrid'; import { AutoComplete, DropDownList, ComboBox, MultiSelect, CheckBoxSelection } from '@syncfusion/ej2-dropdowns'; import { SvgRenderer } from '@syncfusion/ej2-svg-base'; import { Splitter as Splitter$1 } from '@syncfusion/ej2-layouts'; import { Tab, Toolbar as Toolbar$4, ContextMenu as ContextMenu$2 } from '@syncfusion/ej2-navigations'; import { RichTextEditor, MarkdownEditor, FormatPainter, FileManager, EmojiPicker, Table, Image, Toolbar as Toolbar$3, Link, HtmlEditor, QuickToolbar, Count } from '@syncfusion/ej2-richtexteditor'; import { MaskedTextBox, NumericTextBox, TextBox, FormValidator } from '@syncfusion/ej2-inputs'; import { CheckBox, RadioButton } from '@syncfusion/ej2-buttons'; import { DatePicker, DateTimePicker } from '@syncfusion/ej2-calendars'; import { PdfColor, PdfFontFamily, PdfPen, PdfDashStyle, PdfStringFormat, PdfBorderOverlapStyle, RectangleF, PdfLayoutBreakType, PointF, SizeF, PdfLayoutType, RowLayoutResult, ElementLayouter, PdfLayoutResult, PdfLayoutFormat, PdfLayoutElement, PdfStringLayouter, PdfStandardFont, PdfFontStyle, PdfSolidBrush, PdfImage, PdfBitmap, PdfTextWebLink, PdfTextAlignment, PdfLineCap, PdfVerticalAlignment, PdfPageTemplateElement, PdfPageNumberField, PdfPageCountField, PdfCompositeField, PdfLinearGradientBrush, PdfPath, PdfBrushes, PdfWordWrapType, PdfPage, PdfDocument, PdfPageSettings, PdfPageOrientation } from '@syncfusion/ej2-pdf-export'; /** * Common methods used in Gantt */ /** * @param {Element} elem . * @param {string} selector . * @param {boolean} isID . * @returns {Element} . * @hidden */ function parentsUntil(elem, selector, isID) { var parent = elem; while (parent) { if (isID ? parent.id === selector : parent.classList.contains(selector)) { break; } parent = parent.parentElement; } return parent; } /** * @param {ITaskData} ganttProp . * @returns {boolean} . * @hidden */ function isScheduledTask(ganttProp) { if (isNullOrUndefined(ganttProp.startDate) && isNullOrUndefined(ganttProp.endDate) && isNullOrUndefined(ganttProp.duration)) { return null; } else if (isNullOrUndefined(ganttProp.startDate) || isNullOrUndefined(ganttProp.endDate) || isNullOrUndefined(ganttProp.duration)) { return false; } else { return true; } } /** * @param {Gantt} parent . * @returns {boolean} . * @hidden */ function isCountRequired(parent) { if (parent.dataSource && !(parent.dataSource instanceof DataManager) && 'result' in parent.dataSource) { return true; } return false; } /** * @param {object} obj . * @returns {object} . * @hidden */ function getSwapKey(obj) { var temp = {}; for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) { var key = _a[_i]; temp[obj[key]] = key; } return temp; } /** * @param {object} obj . * @returns {boolean} . * @hidden */ function isEmptyObject(obj) { if (isNullOrUndefined(obj) || typeof obj !== 'object') { return false; } return Object.keys(obj).length === 0; } /** * @param {Date} date . * @returns {number} . * @hidden */ function getUniversalTime(date) { var year = date.getFullYear(); var month = date.getMonth(); var day = date.getDate(); var hours = date.getHours(); var minutes = date.getMinutes(); var seconds = date.getSeconds(); var milliseconds = date.getMilliseconds(); return Date.UTC(year, month, day, hours, minutes, seconds, milliseconds); } /** * @param {object} dataSource . * @returns {boolean} . * @hidden */ function isRemoteData(dataSource) { if (dataSource instanceof DataManager) { var adaptor = dataSource.adaptor; return (adaptor instanceof ODataAdaptor || (adaptor instanceof ODataV4Adaptor) || (adaptor instanceof WebApiAdaptor) || (adaptor instanceof WebMethodAdaptor) || (adaptor instanceof CacheAdaptor) || (adaptor instanceof RemoteSaveAdaptor) || adaptor instanceof UrlAdaptor); } return false; } /** * @param {IGanttData[]} records . * @param {boolean} isNotExtend . * @param {ITaskAddedEventArgs} eventArgs . * @param {Gantt} parent . * @returns {object[]} . * @hidden */ function getTaskData(records, isNotExtend, eventArgs, parent) { if (eventArgs) { var result = void 0; for (var i = 0; i < records.length; i++) { var data = isNotExtend ? (records[parseInt(i.toString(), 10)].taskData) : extend({}, records[parseInt(i.toString(), 10)].taskData, {}, true); result = (data); } return result; } else { var result = []; for (var i = 0; i < records.length; i++) { if (!isNullOrUndefined(parent) && parent.timezone) { updateDates(records[i], parent); } var data = isNotExtend ? (records[parseInt(i.toString(), 10)].taskData) : extend({}, records[parseInt(i.toString(), 10)].taskData, {}, true); result.push(data); } return result; } } /** * @param {IGanttData} record . * @param {Gantt} parent . * @returns {null} . * @hidden */ function updateDates(record, parent) { // let startDate: Date = (record as IGanttData).taskData[parent.taskFields.startDate]; if (record && !isNullOrUndefined(record.ganttProperties)) { record.taskData[parent.taskFields.startDate] = parent.dateValidationModule.remove(record.ganttProperties.startDate, parent.timezone); if (parent.taskFields.endDate !== null) { record.taskData[parent.taskFields.endDate] = parent.dateValidationModule.remove(record.ganttProperties.endDate, parent.timezone); } if (parent.taskFields.baselineEndDate || parent.taskFields.baselineStartDate) { record.taskData[parent.taskFields.baselineStartDate] = parent.dateValidationModule.remove(record.ganttProperties.baselineStartDate, parent.timezone); record.taskData[parent.taskFields.baselineEndDate] = parent.dateValidationModule.remove(record.ganttProperties.baselineEndDate, parent.timezone); } } return null; } /** * @param {string} str . * @param {string[]} args . * @returns {string} . * @hidden */ function formatString(str, args) { var regx; for (var i = 0; i < args.length; i++) { // eslint-disable-next-line security/detect-non-literal-regexp regx = new RegExp('\\{' + (i) + '\\}', 'gm'); str = str.replace(regx, args[i].toString()); } return str; } /** * @param {any} value . * @param {string} key1 . * @param {any} collection . * @param {string} key2 * @returns {number} . * @hidden */ /* eslint-disable-next-line */ function getIndex(value, key1, collection, key2) { var index = -1; for (var i = 0; i < collection.length; i++) { if (getValue(key1, collection[i]) === getValue(key1, value) && isNullOrUndefined(key2) || (!isNullOrUndefined(key2) && getValue(key1, collection[i]) === getValue(key1, value) && getValue(key2, collection[i]) === getValue(key2, value))) { index = i; break; } } return index; } /** * @param {number} value . * @returns {number} . * @hidden */ function pixelToPoint(value) { return (value * 76) / 92; } /** * @param {number} value . * @returns {number} . * @hidden */ function pointToPixel(value) { return (value * 92) / 76; } var uid = 0; /** * @returns {number} . * @hidden */ function getUid() { return uid++; } /** * Defines the constraint types used for task scheduling. * * Available values: * - `0`: AsSoonAsPossible (ASAP) – Task starts as early as possible. Default for auto-scheduled tasks. * - `1`: AsLateAsPossible (ALAP) – Task finishes as late as possible without delaying dependents. * - `2`: MustStartOn (MSO) – Task must start on the specified date. * - `3`: MustFinishOn (MFO) – Task must finish on the specified date. * - `4`: StartNoEarlierThan (SNET) – Task cannot start before the specified date. * - `5`: StartNoLaterThan (SNLT) – Task must start on or before the specified date. * - `6`: FinishNoEarlierThan (FNET) – Task cannot finish before the specified date. * - `7`: FinishNoLaterThan (FNLT) – Task must finish on or before the specified date. */ var ConstraintType; (function (ConstraintType) { ConstraintType[ConstraintType["AsSoonAsPossible"] = 0] = "AsSoonAsPossible"; ConstraintType[ConstraintType["AsLateAsPossible"] = 1] = "AsLateAsPossible"; ConstraintType[ConstraintType["MustStartOn"] = 2] = "MustStartOn"; ConstraintType[ConstraintType["MustFinishOn"] = 3] = "MustFinishOn"; ConstraintType[ConstraintType["StartNoEarlierThan"] = 4] = "StartNoEarlierThan"; ConstraintType[ConstraintType["StartNoLaterThan"] = 5] = "StartNoLaterThan"; ConstraintType[ConstraintType["FinishNoEarlierThan"] = 6] = "FinishNoEarlierThan"; ConstraintType[ConstraintType["FinishNoLaterThan"] = 7] = "FinishNoLaterThan"; })(ConstraintType || (ConstraintType = {})); /** * Date processor is used to handle date of task data. */ var DateProcessor = /** @__PURE__ @class */ (function () { function DateProcessor(parent) { this.fromSegments = false; this.mondayTimeRangeLength = 0; this.tuesdayTimeRangeLength = 0; this.wednesdayTimeRangeLength = 0; this.thursdayTimeRangeLength = 0; this.fridayTimeRangeLength = 0; this.saturdayTimeRangeLength = 0; this.sundayTimeRangeLength = 0; this.parent = parent; } /** * @param {ITaskData} ganttProp . * @returns {boolean} . */ DateProcessor.prototype.isValidateNonWorkDays = function (ganttProp) { return (!isNullOrUndefined(ganttProp) && ganttProp.isAutoSchedule && (!this.parent.includeWeekend || this.parent.totalHolidayDates.length > 0)) || (isNullOrUndefined(ganttProp) && (!this.parent.includeWeekend || this.parent.totalHolidayDates.length > 0)); }; /** * Method to convert given date value as valid start date * * @param {Date} date . * @param {ITaskData} ganttProp . * @param {boolean} validateAsMilestone . * @param {boolean} isLoad . * @returns {Date} . * @private */ DateProcessor.prototype.checkStartDate = function (date, ganttProp, validateAsMilestone, isLoad) { if (isNullOrUndefined(date)) { return null; } var currentDay = new Date(date.getTime()); var dayStartTime = this.parent['getCurrentDayStartTime'](currentDay); var dayEndTime = this.parent['getCurrentDayEndTime'](currentDay); var cloneStartDate = new Date(date.getTime()); var hour = this.getSecondsInDecimal(cloneStartDate); validateAsMilestone = isNullOrUndefined(validateAsMilestone) ? !isNullOrUndefined(ganttProp) ? ganttProp.isMilestone : false : validateAsMilestone; if (hour < dayStartTime && (!validateAsMilestone || isLoad)) { this.setTime(dayStartTime, cloneStartDate); } else if (hour < dayStartTime && validateAsMilestone) { this.setTime(dayStartTime, cloneStartDate); } else if ((hour === dayEndTime && (!ganttProp || !validateAsMilestone)) || hour > dayEndTime) { cloneStartDate.setDate(cloneStartDate.getDate() + 1); dayStartTime = this.parent['getCurrentDayStartTime'](cloneStartDate); this.setTime(dayStartTime, cloneStartDate); } else if (hour > dayStartTime && hour < dayEndTime) { var workingRange = this.parent.workingTimeRanges; if (this.parent.weekWorkingTime.length > 0) { workingRange = this.parent['getWorkingRange'](cloneStartDate); } for (var index = 0; index < workingRange.length; index++) { var value = workingRange[index]; if (hour >= value.to && (workingRange[index + 1] && hour < workingRange[index + 1].from)) { // milestone can fall at end any interval time if ((hour === value.to && (!ganttProp || !validateAsMilestone)) || hour !== value.to) { this.setTime(workingRange[index + 1].from, cloneStartDate); } break; } } } var tStartDate; if (this.parent.autoCalculateDateScheduling && !(this.parent.isLoad && this.parent.treeGrid.loadChildOnDemand && this.parent.taskFields.hasChildMapping)) { do { tStartDate = new Date(cloneStartDate.getTime()); var holidayLength = this.parent.totalHolidayDates.length; // check holidays and weekends if (this.isValidateNonWorkDays(ganttProp)) { dayStartTime = this.parent['getCurrentDayStartTime'](tStartDate); if (ganttProp) { dayEndTime = this.parent['getCurrentDayEndTime'](ganttProp.endDate ? ganttProp.isAutoSchedule ? ganttProp.endDate : ganttProp.autoEndDate : tStartDate); } var startTime = (!validateAsMilestone || isLoad) ? dayStartTime : dayEndTime; if (!this.parent.includeWeekend) { var tempDate = new Date(cloneStartDate.getTime()); cloneStartDate = this.getNextWorkingDay(cloneStartDate); startTime = this.parent['getCurrentDayStartTime'](cloneStartDate); if (tempDate.getTime() !== cloneStartDate.getTime() && !validateAsMilestone) { this.setTime(startTime, cloneStartDate); } } for (var count = 0; count < holidayLength; count++) { var holidayFrom = this.getDateFromFormat(new Date(this.parent.totalHolidayDates[count])); var holidayTo = new Date(holidayFrom.getTime()); holidayFrom.setHours(0, 0, 0, 0); holidayTo.setHours(23, 59, 59, 59); if (cloneStartDate.getTime() >= holidayFrom.getTime() && cloneStartDate.getTime() < holidayTo.getTime()) { cloneStartDate.setDate(cloneStartDate.getDate() + 1); startTime = this.parent['getCurrentDayStartTime'](cloneStartDate); this.setTime(startTime, cloneStartDate); } } } } while (tStartDate.getTime() !== cloneStartDate.getTime()); return new Date(cloneStartDate.getTime()); } else { return new Date(cloneStartDate.getTime()); } }; DateProcessor.prototype.getDateByConstraint = function (ganttData, date, restrictConstraint, validPredecessor) { var ganttProp = ganttData['ganttProperties'] ? ganttData['ganttProperties'] : ganttData; var constraintDate = new Date(ganttProp.constraintDate); var isLoad = this.parent.isLoad; if (isNullOrUndefined(validPredecessor)) { validPredecessor = true; } if ((!constraintDate || !date) && validPredecessor) { return null; } constraintDate = this.parent['assignTimeToDate'](constraintDate, this.parent['getCurrentDayStartTime'](constraintDate)); switch (ganttProp.constraintType) { case ConstraintType.AsSoonAsPossible: if (isLoad) { return date; } else { ganttProp.constraintDate = null; var parentRecord = this.parent.getRecordByID(ganttProp.taskId).parentItem; if (ganttProp.predecessor && ganttProp.predecessor.length > 0) { return this.parent['assignTimeToDate'](date, this.parent['getCurrentDayStartTime'](date)); } else if (parentRecord) { return this.parent.getRecordByID(parentRecord.taskId).ganttProperties.startDate; } else { return this.parent.dateValidationModule.checkStartDate(new Date(this.parent.projectStartDate)); } } case ConstraintType.AsLateAsPossible: if (isLoad) { return date; } else { var parentRecord = this.parent.getRecordByID(ganttProp.taskId).parentItem; if (parentRecord) { var checkedEnd = this.parent.dateValidationModule.checkEndDate(this.parent.getRecordByID(parentRecord.taskId).ganttProperties.endDate); var start = this.parent.dateValidationModule.getStartDate(checkedEnd, ganttProp.duration, ganttProp.durationUnit, ganttProp); return start; } else { var checkedEnd = this.parent.dateValidationModule.checkEndDate(new Date(this.parent.projectEndDate)); var start = this.parent.dateValidationModule.getStartDate(checkedEnd, ganttProp.duration, ganttProp.durationUnit, ganttProp); return start; } } case ConstraintType.MustStartOn: { var isViolation = constraintDate.getTime() !== ganttProp.startDate.getTime(); var constraintValue = void 0; if (this.parent.editModule && this.parent.editModule.dialogModule) { constraintValue = this.parent.editModule.dialogModule['dialogConstraintValue']; } var isConstraintTypeRestricted = isNullOrUndefined(constraintValue) || constraintValue === 2 || constraintValue === 3; if (isViolation && !isLoad && isConstraintTypeRestricted) { this.parent.constraintViolationType = 'MustStartOn'; } constraintValue = null; if (isLoad) { return this.parent.dateValidationModule.checkStartDate(new Date(constraintDate)); } else { return this.parent['assignTimeToDate'](date, this.parent['getCurrentDayStartTime'](date)); } } case ConstraintType.MustFinishOn: { var isViolation = constraintDate.getTime() !== ganttProp.endDate.getTime(); var endDate = new Date(constraintDate); endDate.setDate(endDate.getDate() + 1); var checkedEnd = this.parent.dateValidationModule.checkEndDate(endDate); var start = this.parent.dateValidationModule.getStartDate(checkedEnd, ganttProp.duration, ganttProp.durationUnit, ganttProp); if (isViolation && !isLoad) { this.parent.constraintViolationType = 'MustFinishOn'; } if (restrictConstraint) { return date; } return start; } case ConstraintType.StartNoEarlierThan: { if (constraintDate.getTime() < date.getTime() || !isLoad) { return this.parent['assignTimeToDate'](date, this.parent['getCurrentDayStartTime'](date)); } return this.parent.dateValidationModule.checkStartDate(new Date(constraintDate)); } case ConstraintType.StartNoLaterThan: { var isViolation = constraintDate.getTime() !== ganttProp.startDate.getTime(); if (isViolation && !isLoad) { this.parent.constraintViolationType = 'StartNoLaterThan'; } if (!isLoad) { return this.parent['assignTimeToDate'](date, this.parent['getCurrentDayStartTime'](date)); } return (ganttProp.predecessor && ganttProp.predecessor.length > 0) ? date : this.parent.dateValidationModule.checkStartDate(new Date(this.parent.projectStartDate)); } case ConstraintType.FinishNoEarlierThan: { if (constraintDate.getTime() < date.getTime()) { return this.parent['assignTimeToDate'](date, this.parent['getCurrentDayEndTime'](date)); } else { var adjustedDate = new Date(constraintDate); adjustedDate.setDate(adjustedDate.getDate() + 1); var checkedEnd = this.parent.dateValidationModule.checkEndDate(adjustedDate); return this.parent.dateValidationModule.getStartDate(checkedEnd, ganttProp.duration, ganttProp.durationUnit, ganttProp); } } case ConstraintType.FinishNoLaterThan: { var isViolation = constraintDate.getTime() !== ganttProp.endDate.getTime(); if (isViolation && !isLoad) { this.parent.constraintViolationType = 'FinishNoLaterThan'; } if (!isLoad) { return this.parent['assignTimeToDate'](date, this.parent['getCurrentDayEndTime'](date)); } return (ganttProp.predecessor && ganttProp.predecessor.length > 0) ? date : this.parent.dateValidationModule.checkStartDate(new Date(this.parent.projectStartDate)); } default: return date; } }; /** * To update given date value to valid end date * * @param {Date} date . * @param {ITaskData} ganttProp . * @param {boolean} validateAsMilestone . * @returns {Date} . * @private */ DateProcessor.prototype.checkEndDate = function (date, ganttProp, validateAsMilestone) { if (isNullOrUndefined(date)) { return null; } var dayStartTime; var dayEndTime; if (this.parent.weekWorkingTime.length > 0) { var currentDay = date; if (!this.parent.includeWeekend && ganttProp && ganttProp.isAutoSchedule || (this.parent.editModule && this.parent.editModule.taskbarEditModule && this.parent.editModule.taskbarEditModule.taskBarEditRecord && !this.parent.editModule.taskbarEditModule.taskBarEditRecord.ganttProperties.isAutoSchedule)) { currentDay = this.getNextWorkingDay(date); } dayStartTime = this.parent['getStartTime'](currentDay); dayEndTime = this.parent['getEndTime'](currentDay); } else { dayStartTime = this.parent.defaultStartTime; dayEndTime = this.parent.defaultEndTime; } var cloneEndDate = new Date(date.getTime()); var hour = this.getSecondsInDecimal(cloneEndDate); if (hour > dayEndTime) { this.setTime(dayEndTime, cloneEndDate); } else if (hour <= dayStartTime && dayEndTime !== 86400 && !validateAsMilestone) { var taskfields = this.parent.taskFields; if (this.parent.editModule && this.parent.editModule['editedRecord'] && (!this.parent.editModule['editedRecord'][taskfields.startDate] && this.parent.editModule['editedRecord'][taskfields.endDate])) { cloneEndDate.setDate(cloneEndDate.getDate()); } else { cloneEndDate.setDate(cloneEndDate.getDate() - 1); } dayEndTime = this.parent['getCurrentDayEndTime'](cloneEndDate); this.setTime(dayEndTime, cloneEndDate); } else if (hour > dayStartTime && hour < dayEndTime) { for (var index = 0; index < this.parent.workingTimeRanges.length; index++) { var value = this.parent.workingTimeRanges[index]; if (hour > value.to && (this.parent.workingTimeRanges[index + 1] && hour <= this.parent.workingTimeRanges[index + 1].from)) { this.setTime(this.parent.workingTimeRanges[index].to, cloneEndDate); break; } } } var tempCheckDate; if (this.parent.autoCalculateDateScheduling && !(this.parent.isLoad && this.parent.treeGrid.loadChildOnDemand && this.parent.taskFields.hasChildMapping)) { do { tempCheckDate = new Date(cloneEndDate.getTime()); var holidayLength = this.parent.totalHolidayDates.length; if (this.isValidateNonWorkDays(ganttProp)) { if (!this.parent.includeWeekend) { var tempDate = new Date(cloneEndDate.getTime()); cloneEndDate = this.getPreviousWorkingDay(cloneEndDate); dayEndTime = this.parent['getCurrentDayEndTime'](cloneEndDate); if (tempDate.getTime() !== cloneEndDate.getTime()) { this.setTime(dayEndTime, cloneEndDate); } } for (var count = 0; count < holidayLength; count++) { var holidayFrom = this.getDateFromFormat(new Date(this.parent.totalHolidayDates[count])); var holidayTo = new Date(holidayFrom.getTime()); var tempHoliday = new Date(cloneEndDate.getTime()); tempHoliday.setMinutes(cloneEndDate.getMilliseconds() - 2); holidayFrom.setHours(0, 0, 0, 0); holidayTo.setHours(23, 59, 59, 59); if (cloneEndDate.getTime() >= holidayFrom.getTime() && cloneEndDate.getTime() < holidayTo.getTime() || tempHoliday.getTime() >= holidayFrom.getTime() && tempHoliday.getTime() < holidayTo.getTime()) { cloneEndDate.setDate(cloneEndDate.getDate() - 1); dayEndTime = this.parent['getCurrentDayEndTime'](cloneEndDate); if (!(cloneEndDate.getTime() === holidayFrom.getTime() && dayEndTime === 86400 && this.getSecondsInDecimal(cloneEndDate) === 0)) { this.setTime(dayEndTime, cloneEndDate); } } } } } while (tempCheckDate.getTime() !== cloneEndDate.getTime()); return new Date(cloneEndDate.getTime()); } else { if (!isNullOrUndefined(cloneEndDate) && this.parent.defaultEndTime !== 86400) { dayEndTime = this.parent['getCurrentDayEndTime'](date); this.setTime(dayEndTime, cloneEndDate); } return new Date(cloneEndDate.getTime()); } }; /** * To validate the baseline start date * * @param {Date} date . * @param {ITaskData} ganttProp . * @returns {Date} . * @private */ DateProcessor.prototype.checkBaselineStartDate = function (date, ganttProp) { if (isNullOrUndefined(date)) { return null; } else { var dayStartTime = this.parent['getCurrentDayStartTime'](date); var dayEndTime = this.parent['getCurrentDayEndTime'](ganttProp ? ganttProp.endDate ? ganttProp.isAutoSchedule ? ganttProp.endDate : ganttProp.autoEndDate : date : date); var cloneDate = new Date(date.getTime()); var hour = this.getSecondsInDecimal(cloneDate); if (hour < dayStartTime) { this.setTime(dayStartTime, cloneDate); } else if (hour > dayEndTime) { cloneDate.setDate(cloneDate.getDate() + 1); if (this.parent.weekWorkingTime.length > 0) { dayStartTime = this.parent['getStartTime'](cloneDate); } else { dayStartTime = this.parent.defaultStartTime; } this.setTime(dayStartTime, cloneDate); } else if (hour > dayStartTime && hour < dayEndTime) { for (var i = 0; i < this.parent.workingTimeRanges.length; i++) { var value = this.parent.workingTimeRanges[i]; if (hour > value.to && (this.parent.workingTimeRanges[i + 1] && hour < this.parent.workingTimeRanges[i + 1].from)) { this.setTime(this.parent.workingTimeRanges[i + 1].from, cloneDate); break; } } } return cloneDate; } }; /** * To validate baseline end date * * @param {Date} date . * @param {ITaskData} ganttProp . * @returns {Date} . * @private */ DateProcessor.prototype.checkBaselineEndDate = function (date, ganttProp) { if (isNullOrUndefined(date)) { return null; } else { var dayEndTime = this.parent['getCurrentDayEndTime'](date); var dayStartTime = this.parent['getCurrentDayStartTime'](ganttProp ? ganttProp.startDate ? ganttProp.isAutoSchedule ? ganttProp.startDate : ganttProp.autoStartDate : date : date); var cloneDate = new Date(date.getTime()); var hour = this.getSecondsInDecimal(cloneDate); if (hour > dayEndTime) { this.setTime(dayEndTime, cloneDate); } else if (hour < dayStartTime && !isNullOrUndefined(ganttProp) && !ganttProp.isMilestone) { cloneDate.setDate(cloneDate.getDate() - 1); dayEndTime = this.parent['getCurrentDayEndTime'](cloneDate); this.setTime(dayEndTime, cloneDate); } else if (hour > dayStartTime && hour < dayEndTime) { for (var i = 0; i < this.parent.workingTimeRanges.length; i++) { var value = this.parent.workingTimeRanges[i]; if (hour > value.to && (this.parent.workingTimeRanges[i + 1] && hour <= this.parent.workingTimeRanges[i + 1].from)) { this.setTime(this.parent.workingTimeRanges[i].to, cloneDate); break; } } } if (ganttProp && ganttProp.baselineStartDate && cloneDate && ganttProp.baselineStartDate.getTime() > cloneDate.getTime()) { cloneDate.setDate(cloneDate.getDate() + 1); } return cloneDate; } }; /** * To calculate start date value from duration and end date * * @param {IGanttData} ganttData - Defines the gantt data. * @returns {void} . * @private */ DateProcessor.prototype.calculateStartDate = function (ganttData) { var ganttProp = ganttData.ganttProperties; var tempStartDate = null; if (!isNullOrUndefined(ganttProp.endDate) && !isNullOrUndefined(ganttProp.duration)) { tempStartDate = this.getStartDate(ganttProp.endDate, ganttProp.duration, ganttProp.durationUnit, ganttProp); } this.parent.setRecordValue('startDate', tempStartDate, ganttProp, true); if (this.parent.taskFields.startDate) { this.parent.dataOperation.updateMappingData(ganttData, 'startDate'); } }; /** * * @param {IGanttData} ganttData - Defines the gantt data. * @returns {void} . * @private */ DateProcessor.prototype.calculateEndDate = function (ganttData) { var ganttProp = ganttData.ganttProperties; var tempEndDate = null; var dayStartTime; var dayEndTime; if (!isNullOrUndefined(ganttProp.startDate)) { if (!isNullOrUndefined(ganttProp.endDate) && isNullOrUndefined(ganttProp.duration)) { if (this.compareDates(ganttProp.startDate, ganttProp.endDate) === 1) { this.parent.setRecordValue('startDate', new Date(ganttProp.endDate.getTime()), ganttProp, true); dayStartTime = this.parent['getCurrentDayStartTime'](ganttProp.isAutoSchedule ? ganttProp.autoStartDate : ganttProp.startDate); dayEndTime = this.parent['getCurrentDayEndTime'](ganttProp.isAutoSchedule ? ganttProp.autoEndDate : ganttProp.endDate); this.setTime(dayStartTime, ganttProp.startDate); } this.calculateDuration(ganttData); } if (!isNullOrUndefined(ganttProp.duration)) { var duration = !isNullOrUndefined(ganttProp.segments) && ganttProp.segments.length > 1 ? this.totalDuration(ganttProp.segments) : ganttProp.duration; tempEndDate = this.getEndDate(ganttProp.startDate, duration, ganttProp.durationUnit, ganttProp, false); } this.parent.setRecordValue('endDate', tempEndDate, ganttProp, true); } else { tempEndDate = ganttData[this.parent.taskFields.endDate]; if (!isNullOrUndefined(tempEndDate)) { dayEndTime = this.parent['getCurrentDayEndTime'](tempEndDate); this.setTime(dayEndTime, tempEndDate); } this.parent.setRecordValue('endDate', tempEndDate, ganttProp, true); } if (this.parent.taskFields.endDate) { this.parent.dataOperation.updateMappingData(ganttData, 'endDate'); } }; DateProcessor.prototype.totalDuration = function (segments) { var duration = 0; for (var i = 0; i < segments.length; i++) { duration += segments[i].duration + segments[i].offsetDuration; } return duration; }; /** * To calculate duration from start date and end date * * @param {IGanttData} ganttData - Defines the gantt data. * @returns {void} . */ DateProcessor.prototype.calculateDuration = function (ganttData) { var ganttProperties = ganttData.ganttProperties; var tDuration; if (!isNullOrUndefined(ganttProperties.segments) && ganttProperties.segments.length > 0 && !isNullOrUndefined(this.parent.editModule.taskbarEditModule)) { tDuration = this.parent.editModule.taskbarEditModule.sumOfDuration(ganttProperties.segments); } else { if ((!isNullOrUndefined(this.parent.taskFields.milestone)) && (!isNullOrUndefined(ganttProperties.startDate)) && !isNullOrUndefined(ganttProperties.endDate) && (ganttProperties.startDate).getTime() === (ganttProperties.endDate).getTime() && (ganttData.taskData[this.parent.taskFields.milestone] === false)) { tDuration = 1; } else { tDuration = this.getDuration(ganttProperties.startDate, ganttProperties.endDate, ganttProperties.durationUnit, ganttProperties.isAutoSchedule, ganttProperties.isMilestone); } } this.parent.setRecordValue('duration', tDuration, ganttProperties, true); var col = this.parent.columnByField[this.parent.columnMapping.duration]; if (!isNullOrUndefined(this.parent.editModule) && !isNullOrUndefined(this.parent.editModule.cellEditModule) && !this.parent.editModule.cellEditModule.isCellEdit && !isNullOrUndefined(col)) { if (!isNullOrUndefined(col.edit) && !isNullOrUndefined(col.edit.read)) { var dialog = this.parent.editModule.dialogModule.dialog; if (!isNullOrUndefined(dialog)) { var textBox = dialog.querySelector('#' + this.parent.element.id + 'Duration') .ej2_instances[0]; if (!isNullOrUndefined(textBox) && textBox.value !== tDuration.toString()) { textBox.value = tDuration.toString(); textBox.dataBind(); } } } if (this.parent.taskFields.duration) { this.parent.dataOperation.updateMappingData(ganttData, 'duration'); if (this.parent.taskFields.durationUnit) { this.parent.dataOperation.updateMappingData(ganttData, 'durationUnit'); } } } }; /** * * @param {Date} sDate Method to get total nonworking time between two date values * @param {Date} eDate . * @param {boolean} isAutoSchedule . * @param {boolean} isCheckTimeZone . * @returns {number} . */ DateProcessor.prototype.getNonworkingTime = function (sDate, eDate, isAutoSchedule, isCheckTimeZone) { isCheckTimeZone = isNullOrUndefined(isCheckTimeZone) ? true : isCheckTimeZone; var weekendCount = (!this.parent.includeWeekend && this.parent.autoCalculateDateScheduling && !(this.parent.isLoad && this.parent.treeGrid.loadChildOnDemand && this.parent.taskFields.hasChildMapping)) && isAutoSchedule ? this.getWeekendCount(sDate, eDate) : 0; var totalHours = this.getNumberOfSeconds(sDate, eDate, isCheckTimeZone); var holidaysCount = (isAutoSchedule && this.parent.autoCalculateDateScheduling && !(this.parent.isLoad && this.parent.treeGrid.loadChildOnDemand && this.parent.taskFields.hasChildMapping)) ? this.getHolidaysCount(sDate, eDate) : 0; var totWorkDays = (totalHours - (weekendCount * 86400) - (holidaysCount * 86400)) / 86400; // working days between two dates var nonWorkHours = this.getNonWorkingSecondsOnDate(sDate, eDate, isAutoSchedule); var totalNonWorkTime = (this.parent.weekWorkingTime.length > 0 ? this.nonWorkingSeconds(sDate, eDate, isAutoSchedule, totWorkDays) : (totWorkDays * (86400 - this.parent.secondsPerDay))) + (weekendCount * 86400) + (holidaysCount * 86400) + nonWorkHours; return totalNonWorkTime; }; DateProcessor.prototype.nonWorkingSeconds = function (sDate, eDate, isAutoSchedule, workDays, fromDuration) { var newStartDate = sDate.getTime() > eDate.getTime() ? new Date(eDate.getTime()) : new Date(sDate.getTime()); var newEndDate = sDate.getTime() > eDate.getTime() ? new Date(sDate.getTime()) : new Date(eDate.getTime()); var timeDiff = 0; var count = 0; if (fromDuration) { var dayStartTime = this.parent['getCurrentDayStartTime'](newStartDate); var dayEndTime = this.parent['getCurrentDayEndTime'](newStartDate); if (!(newStartDate.getHours() < dayEndTime / 3600 && newStartDate.getHours() >= dayStartTime / 3600)) { newStartDate.setDate(newStartDate.getDate() + 1); } } else { newStartDate.setDate(newStartDate.getDate() + 1); newStartDate.setHours(0, 0, 0, 0); newEndDate.setHours(0, 0, 0, 0); } if (workDays > 0 || isNullOrUndefined(workDays)) { while ((fromDuration && newStartDate.getTime() <= newEndDate.getTime()) || (!fromDuration && newStartDate.getTime() < newEndDate.getTime())) { if (isAutoSchedule) { if (this.isOnHolidayOrWeekEnd(newStartDate, true)) { do { newStartDate.setDate(newStartDate.getDate() + 1); } while (this.isOnHolidayOrWeekEnd(newStartDate, true)); } if (!this.parent.includeWeekend) { this.getNextWorkingDay(newStartDate); } } if (newStartDate.getTime() <= newEndDate.getTime()) { count++; var currentDaySeconds = this.parent['getSecondsPerDay'](newStartDate); if (fromDuration) { timeDiff += currentDaySeconds; } else { timeDiff += 86400 - currentDaySeconds; } newStartDate.setDate(newStartDate.getDate() + 1); if (isAutoSchedule) { if (this.isOnHolidayOrWeekEnd(newStartDate, true)) { do { newStartDate.setDate(newStartDate.getDate() + 1); } while (this.isOnHolidayOrWeekEnd(newStartDate, true)); } if (!this.parent.includeWeekend) { this.getNextWorkingDay(newStartDate); } } } } } else { return 0; } if (fromDuration) { if (timeDiff > 0) { timeDiff = timeDiff / count; } else { timeDiff = this.parent.secondsPerDay; } } return timeDiff; }; /** * * @param {Date} startDate . * @param {Date} endDate . * @param {string} durationUnit . * @param {boolean} isAutoSchedule . * @param {boolean} isMilestone . * @param {boolean} isCheckTimeZone . * @returns {number} . * @private */ DateProcessor.prototype.getDuration = function (startDate, endDate, durationUnit, isAutoSchedule, isMilestone, isCheckTimeZone) { if (isCheckTimeZone === void 0) { isCheckTimeZone = true; } if (!startDate || !endDate) { return null; } var durationValue = 0; var isSameDay = this.parent.getFormatedDate(startDate) === this.parent.getFormatedDate(endDate); var totSeconds; if (this.parent.weekWorkingTime.length > 0) { var tempStartDate = new Date(startDate); totSeconds = this.nonWorkingSeconds(startDate, endDate, isAutoSchedule, undefined, true); var totalDurationInDays = 0; while (tempStartDate <= endDate) { var currentDateString = this.parent.getFormatedDate(tempStartDate); var dayWorkingSeconds = this.parent['getSecondsPerDay'](tempStartDate); var currentStartDate = new Date(tempStartDate); var currentEndDate = new Date(tempStartDate); currentStartDate.setHours(0, 0, 0, 0); currentEndDate.setHours(0, 0, 0, 0); currentStartDate.setSeconds(this.parent['getCurrentDayStartTime'](tempStartDate)); currentEndDate.setSeconds(this.parent['getCurrentDayEndTime'](tempStartDate)); if (currentDateString === this.parent.getFormatedDate(startDate)) { currentStartDate.setTime(startDate.getTime()); } if (currentDateString === this.parent.getFormatedDate(endDate)) { currentEndDate.setTime(endDate.getTime()); } var timeDiffSeconds = this.getTimeDifference(currentStartDate, currentEndDate, isCheckTimeZone) / 1000; var nonWorkSeconds = this.getNonworkingTime(currentStartDate, currentEndDate, isAutoSchedule, isCheckTimeZone); totalDurationInDays += Math.max(0, timeDiffSeconds - nonWorkSeconds) / dayWorkingSeconds; tempStartDate.setDate(tempStartDate.getDate() + 1); } if (!(isMilestone && isSameDay)) { durationValue = this.calculateDurationValue(durationUnit, totalDurationInDays, totSeconds); } } else { totSeconds = this.parent.secondsPerDay; var timeDiff = this.getTimeDifference(startDate, endDate, isCheckTimeZone) / 1000; var nonWorkHours = this.getNonworkingTime(startDate, endDate, isAutoSchedule, isCheckTimeZone); var durationHours = timeDiff - nonWorkHours; if (!(isMilestone && isSameDay)) { durationValue = this.calculateDurationValue(durationUnit, durationHours / totSeconds, totSeconds); } } return parseFloat(durationValue.toString()); }; DateProcessor.prototype.calculateDurationValue = function (durationUnit, duration, totSeconds) { if (!durationUnit || durationUnit === 'day') { return duration; } else if (durationUnit === 'minute') { return duration * (totSeconds / 60); } else { return duration * (totSeconds / 3600); } }; /** * * @param {number} duration . * @param {string} durationUnit . * @param {Date} date . * @returns {number} . */ DateProcessor.prototype.getDurationAsSeconds = function (duration, durationUnit, date) { var value = 0; var totSeconds; if (this.parent.weekWorkingTime.length > 0) { totSeconds = this.parent['getSecondsPerDay'](date); } else { totSeconds = this.parent.secondsPerDay; } if (!durationUnit || durationUnit.toLocaleLowerCase() === 'day') { value = totSeconds * duration; } else if (durationUnit.toLocaleLowerCase() === 'hour') { value = duration * 3600; } else { value = duration * 60; } return value; }; /** * To get date from start date and duration * * @param {Date} startDate . * @param {number} duration . * @param {string} durationUnit . * @param {ITaskData} ganttProp . * @param {boolean} validateAsMilestone . * @returns {Date} . * @private */ DateProcessor.prototype.getEndDate = function (startDate, duration, durationUnit, ganttProp, validateAsMilestone) { var tempStart = new Date(startDate.getTime()); var endDate = new Date(startDate.getTime()); var sDate = new Date(startDate.getTime()); var secondDuration; if (this.parent.weekWorkingTime.length > 0 && (!durationUnit || durationUnit.toLocaleLowerCase() === 'day')) { secondDuration = this.calculateSecondDuration(duration, sDate, secondDuration, startDate, true); } else { secondDuration = this.getDurationAsSeconds(duration, durationUnit, startDate); } var nonWork = 0; var workHours = 0; while (secondDuration > 0) { endDate.setSeconds(endDate.getSeconds() + secondDuration); nonWork = this.getNonworkingTime(tempStart, endDate, ganttProp.isAutoSchedule, true); workHours = secondDuration - nonWork; secondDuration = secondDuration - workHours; if (secondDuration > 0) { endDate = this.checkStartDate(endDate, ganttProp, validateAsMilestone); } tempStart = new Date(endDate.getTime()); } return endDate; }; /** * Calculate start date based on end date and duration. * * @param {Date} endDate - To calculate start date value from end date and duration. * @param {number} duration - The duration value. * @param {string} durationUnit - The unit of duration. * @param {ITaskData} ganttProp - The Gantt task properties. * @param {boolean} fromValidation - A flag indicating if the calculation is from validation. * @returns {Date} The calculated start date. * @private */ DateProcessor.prototype.getStartDate = function (endDate, duration, durationUnit, ganttProp, fromValidation) { var tempEnd = new Date(endDate.getTime()); var startDate = new Date(endDate.getTime()); var secondDuration; var eDate = new Date(tempEnd.getTime()); if (this.parent.weekWorkingTime.length > 0) { secondDuration = this.calculateSecondDuration(duration, eDate, secondDuration, tempEnd, false); } else { secondDuration = this.getDurationAsSeconds(dur