devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
1,640 lines • 80 kB
JavaScript
/**
* DevExtreme (cjs/__internal/scheduler/m_scheduler.js)
* Version: 25.2.3
* Build date: Fri Dec 12 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.POPUP_DIALOG_CLASS = void 0;
var _visibility_change = require("../../common/core/events/visibility_change");
var _date = _interopRequireDefault(require("../../common/core/localization/date"));
var _message = _interopRequireDefault(require("../../common/core/localization/message"));
var _component_registrator = _interopRequireDefault(require("../../core/component_registrator"));
var _config = _interopRequireDefault(require("../../core/config"));
var _element = require("../../core/element");
var _renderer = _interopRequireDefault(require("../../core/renderer"));
var _bindable_template = require("../../core/templates/bindable_template");
var _empty_template = require("../../core/templates/empty_template");
var _callbacks = _interopRequireDefault(require("../../core/utils/callbacks"));
var _common = require("../../core/utils/common");
var _data = require("../../core/utils/data");
var _date2 = _interopRequireDefault(require("../../core/utils/date"));
var _date_serialization = _interopRequireDefault(require("../../core/utils/date_serialization"));
var _deferred = require("../../core/utils/deferred");
var _extend = require("../../core/utils/extend");
var _position = require("../../core/utils/position");
var _type = require("../../core/utils/type");
var _window = require("../../core/utils/window");
var _data_helper = _interopRequireDefault(require("../../data_helper"));
var _dialog = require("../../ui/dialog");
var _ui = _interopRequireDefault(require("../../ui/widget/ui.errors"));
var _date3 = require("../core/utils/date");
var _a11y_status_render = require("./a11y_status/a11y_status_render");
var _a11y_status_text = require("./a11y_status/a11y_status_text");
var _m_form = require("./appointment_popup/m_form");
var _m_legacy_form = require("./appointment_popup/m_legacy_form");
var _m_legacy_popup = require("./appointment_popup/m_legacy_popup");
var _m_popup = require("./appointment_popup/m_popup");
var _m_appointment_collection = _interopRequireDefault(require("./appointments/m_appointment_collection"));
var _m_widget_notify_scheduler = _interopRequireDefault(require("./base/m_widget_notify_scheduler"));
var _m_header = require("./header/m_header");
var _m_compact_appointments_helper = require("./m_compact_appointments_helper");
var _m_loading = require("./m_loading");
var _m_subscribes = _interopRequireDefault(require("./m_subscribes"));
var _m_utils = require("./m_utils");
var _m_utils_time_zone = _interopRequireDefault(require("./m_utils_time_zone"));
var _remote = require("./r1/filterting/remote");
var _index = require("./r1/timezone_calculator/index");
var _index2 = require("./r1/utils/index");
var _validate_rule = require("./recurrence/validate_rule");
var _scheduler_options_base_widget = require("./scheduler_options_base_widget");
var _m_desktop_tooltip_strategy = require("./tooltip_strategies/m_desktop_tooltip_strategy");
var _m_mobile_tooltip_strategy = require("./tooltip_strategies/m_mobile_tooltip_strategy");
var _appointment_adapter = require("./utils/appointment_adapter/appointment_adapter");
var _appointment_data_accessor = require("./utils/data_accessor/appointment_data_accessor");
var _get_targeted_appointment = require("./utils/get_targeted_appointment");
var _index3 = require("./utils/index");
var _is_agenda_workpace_component = require("./utils/is_agenda_workpace_component");
var _constants_view = require("./utils/options/constants_view");
var _appointment_groups_utils = require("./utils/resource_manager/appointment_groups_utils");
var _popup_utils = require("./utils/resource_manager/popup_utils");
var _resource_manager = require("./utils/resource_manager/resource_manager");
var _appointments_layout_manager = _interopRequireDefault(require("./view_model/appointments_layout_manager"));
var _m_appointment_data_source = require("./view_model/m_appointment_data_source");
var _m_agenda = _interopRequireDefault(require("./workspaces/m_agenda"));
var _m_timeline_day = _interopRequireDefault(require("./workspaces/m_timeline_day"));
var _m_timeline_month = _interopRequireDefault(require("./workspaces/m_timeline_month"));
var _m_timeline_week = _interopRequireDefault(require("./workspaces/m_timeline_week"));
var _m_timeline_work_week = _interopRequireDefault(require("./workspaces/m_timeline_work_week"));
var _m_work_space_day = _interopRequireDefault(require("./workspaces/m_work_space_day"));
var _m_work_space_month = _interopRequireDefault(require("./workspaces/m_work_space_month"));
var _m_work_space_week = _interopRequireDefault(require("./workspaces/m_work_space_week"));
var _m_work_space_work_week = _interopRequireDefault(require("./workspaces/m_work_space_work_week"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : {
default: e
}
}
const toMs = _date2.default.dateToMilliseconds;
const WIDGET_CLASS = "dx-scheduler";
const WIDGET_SMALL_CLASS = `${WIDGET_CLASS}-small`;
const WIDGET_ADAPTIVE_CLASS = `${WIDGET_CLASS}-adaptive`;
const WIDGET_READONLY_CLASS = `${WIDGET_CLASS}-readonly`;
const POPUP_DIALOG_CLASS = exports.POPUP_DIALOG_CLASS = "dx-dialog";
const WIDGET_SMALL_WIDTH = 400;
const FULL_DATE_FORMAT = "yyyyMMddTHHmmss";
const UTC_FULL_DATE_FORMAT = `${FULL_DATE_FORMAT}Z`;
const VIEWS_CONFIG = {
day: {
workSpace: _m_work_space_day.default,
renderingStrategy: "vertical"
},
week: {
workSpace: _m_work_space_week.default,
renderingStrategy: "vertical"
},
workWeek: {
workSpace: _m_work_space_work_week.default,
renderingStrategy: "vertical"
},
month: {
workSpace: _m_work_space_month.default,
renderingStrategy: "horizontalMonth"
},
timelineDay: {
workSpace: _m_timeline_day.default,
renderingStrategy: "horizontal"
},
timelineWeek: {
workSpace: _m_timeline_week.default,
renderingStrategy: "horizontal"
},
timelineWorkWeek: {
workSpace: _m_timeline_work_week.default,
renderingStrategy: "horizontal"
},
timelineMonth: {
workSpace: _m_timeline_month.default,
renderingStrategy: "horizontalMonthLine"
},
agenda: {
workSpace: _m_agenda.default,
renderingStrategy: "agenda"
}
};
const StoreEventNames = {
ADDING: "onAppointmentAdding",
ADDED: "onAppointmentAdded",
DELETING: "onAppointmentDeleting",
DELETED: "onAppointmentDeleted",
UPDATING: "onAppointmentUpdating",
UPDATED: "onAppointmentUpdated"
};
const RECURRENCE_EDITING_MODE = {
SERIES: "editSeries",
OCCURRENCE: "editOccurrence",
CANCEL: "cancel"
};
class Scheduler extends _scheduler_options_base_widget.SchedulerOptionsBaseWidget {
constructor() {
super(...arguments);
this._updatingAppointments = new Set
}
get timeZoneCalculator() {
if (!this._timeZoneCalculator) {
this._timeZoneCalculator = (0, _index.createTimeZoneCalculator)(this.option("timeZone"))
}
return this._timeZoneCalculator
}
_postponeDataSourceLoading(promise) {
this.postponedOperations.add("_reloadDataSource", this._reloadDataSource.bind(this), promise)
}
_postponeResourceLoading() {
let forceReload = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : false;
const whenLoaded = this.postponedOperations.add("loadResources", (() => {
const groups = this.getViewOption("groups");
return (0, _deferred.fromPromise)(this.resourceManager.loadGroupResources(groups, forceReload))
}));
const resolveCallbacks = new _deferred.Deferred;
whenLoaded.done((() => {
resolveCallbacks.resolve()
}));
this._postponeDataSourceLoading(whenLoaded);
return resolveCallbacks.promise()
}
_optionChanged(args) {
var _this$resourceManager;
this.schedulerOptionChanged(args);
const {
value: value,
name: name
} = args;
switch (args.name) {
case "customizeDateNavigatorText":
this._updateOption("header", name, value);
break;
case "firstDayOfWeek":
this._updateOption("workSpace", name, value);
this._updateOption("header", name, value);
this._cleanPopup();
break;
case "currentDate": {
const dateValue = this.getViewOption(name);
this.option("selectedCellData", []);
this._updateOption("workSpace", name, dateValue);
this._updateOption("header", name, dateValue);
this._updateOption("header", "startViewDate", this.getStartViewDate());
this._appointments.option("items", []);
this._filterAppointmentsByDate();
this._postponeDataSourceLoading();
break
}
case "dataSource":
this._initDataSource();
this._postponeResourceLoading().done((() => {
this.appointmentDataSource.setDataSource(this._dataSource);
this._filterAppointmentsByDate();
this._updateOption("workSpace", "showAllDayPanel", this.option("showAllDayPanel"))
}));
break;
case "min":
case "max": {
const value = this.getViewOption(name);
this._updateOption("header", name, value);
this._updateOption("workSpace", name, value);
break
}
case "views":
if (this.currentView) {
this.repaint()
} else {
this._updateOption("header", "views", this.views)
}
break;
case "useDropDownViewSwitcher":
this._updateOption("header", name, value);
break;
case "currentView":
this._appointments.option({
items: [],
allowDrag: this._allowDragging(),
allowResize: this._allowResizing(),
itemTemplate: this._getAppointmentTemplate("appointmentTemplate")
});
this._postponeResourceLoading().done((() => {
var _this$_header;
this._refreshWorkSpace();
null === (_this$_header = this._header) || void 0 === _this$_header || _this$_header.option(this._headerConfig());
this._filterAppointmentsByDate();
this._appointments.option("allowAllDayResize", "day" !== value)
}));
this.postponedOperations.callPostponedOperations();
break;
case "appointmentTemplate":
this._appointments.option("itemTemplate", value);
break;
case "dateCellTemplate":
case "resourceCellTemplate":
case "dataCellTemplate":
case "timeCellTemplate":
this.repaint();
break;
case "groups":
this._postponeResourceLoading().done((() => {
this._refreshWorkSpace();
this._filterAppointmentsByDate()
}));
break;
case "resources":
null === (_this$resourceManager = this.resourceManager) || void 0 === _this$resourceManager || _this$resourceManager.dispose();
this.resourceManager = new _resource_manager.ResourceManager(this.option("resources"));
this.updateAppointmentDataSource();
this._postponeResourceLoading().done((() => {
this._appointments.option("items", []);
this._refreshWorkSpace();
this._filterAppointmentsByDate();
this._createAppointmentPopupForm()
}));
break;
case "startDayHour":
case "endDayHour":
this.updateAppointmentDataSource();
this._appointments.option("items", []);
this._updateOption("workSpace", name, value);
this._appointments.repaint();
this._filterAppointmentsByDate();
this._postponeDataSourceLoading();
break;
case "offset":
this.updateAppointmentDataSource();
this._appointments.option("items", []);
this._updateOption("workSpace", "viewOffset", this.normalizeViewOffsetValue(value));
this._appointments.repaint();
this._filterAppointmentsByDate();
this._postponeDataSourceLoading();
break;
case StoreEventNames.ADDING:
case StoreEventNames.ADDED:
case StoreEventNames.UPDATING:
case StoreEventNames.UPDATED:
case StoreEventNames.DELETING:
case StoreEventNames.DELETED:
case "onAppointmentFormOpening":
case "onAppointmentTooltipShowing":
this._actions[name] = this._createActionByOption(name);
break;
case "onAppointmentRendered":
this._appointments.option("onItemRendered", this._getAppointmentRenderedAction());
break;
case "onAppointmentClick":
this._appointments.option("onItemClick", this._createActionByOption(name));
break;
case "onAppointmentDblClick":
this._appointments.option(name, this._createActionByOption(name));
break;
case "onAppointmentContextMenu":
this._appointments.option("onItemContextMenu", this._createActionByOption(name));
this._appointmentTooltip._options.onItemContextMenu = this._createActionByOption(name);
break;
case "noDataText":
case "allowMultipleCellSelection":
case "selectedCellData":
case "accessKey":
case "onCellClick":
case "onCellContextMenu":
this._updateOption("workSpace", name, value);
break;
case "crossScrollingEnabled":
this._postponeResourceLoading().done((() => {
this._appointments.option("items", []);
this._refreshWorkSpace();
if (this._readyToRenderAppointments) {
this._appointments.option("items", this._layoutManager.generateViewModel())
}
}));
break;
case "cellDuration":
this._updateOption("workSpace", name, value);
this._appointments.option("items", []);
if (this._readyToRenderAppointments) {
this._updateOption("workSpace", "hoursInterval", value / 60);
this._appointments.option("items", this._layoutManager.generateViewModel())
}
break;
case "tabIndex":
case "focusStateEnabled":
this._updateOption("header", name, value);
this._updateOption("workSpace", name, value);
this._appointments.option(name, value);
super._optionChanged(args);
break;
case "width":
this._updateOption("header", name, value);
if (this.option("crossScrollingEnabled")) {
this._updateOption("workSpace", "width", value)
}
this._updateOption("workSpace", "schedulerWidth", value);
super._optionChanged(args);
this._dimensionChanged(null, true);
break;
case "height":
super._optionChanged(args);
this._dimensionChanged(null, true);
this._updateOption("workSpace", "schedulerHeight", value);
break;
case "editing": {
this._initEditing();
const editing = this._editing;
this._bringEditingModeToAppointments(editing);
this.hideAppointmentTooltip();
this._cleanPopup();
break
}
case "showAllDayPanel":
this.updateAppointmentDataSource();
this.repaint();
break;
case "showCurrentTimeIndicator":
case "indicatorUpdateInterval":
case "shadeUntilCurrentTime":
case "groupByDate":
this._updateOption("workSpace", name, value);
this.repaint();
break;
case "indicatorTime":
this._updateOption("workSpace", name, value);
this._updateOption("header", name, value);
this.repaint();
break;
case "appointmentDragging":
case "appointmentTooltipTemplate":
case "appointmentPopupTemplate":
case "recurrenceEditMode":
case "remoteFiltering":
case "timeZone":
this.updateAppointmentDataSource();
this.repaint();
break;
case "appointmentCollectorTemplate":
case "_appointmentTooltipOffset":
this.repaint();
break;
case "dateSerializationFormat":
break;
case "maxAppointmentsPerCell":
this.repaint();
break;
case "startDateExpr":
case "endDateExpr":
case "startDateTimeZoneExpr":
case "endDateTimeZoneExpr":
case "textExpr":
case "descriptionExpr":
case "allDayExpr":
case "recurrenceRuleExpr":
case "recurrenceExceptionExpr":
case "disabledExpr":
case "visibleExpr":
this._updateExpression(name, value);
this._initAppointmentTemplate();
this.repaint();
break;
case "adaptivityEnabled":
this._toggleAdaptiveClass();
this.repaint();
break;
case "scrolling":
this.option("crossScrollingEnabled", this._isHorizontalVirtualScrolling() || this.option("crossScrollingEnabled"));
this._updateOption("workSpace", args.fullName, value);
break;
case "allDayPanelMode":
this.updateAppointmentDataSource();
this._updateOption("workSpace", args.fullName, value);
break;
case "renovateRender":
this._updateOption("workSpace", name, value);
break;
case "_draggingMode":
this._updateOption("workSpace", "draggingMode", value);
break;
case "toolbar":
this._header ? this._header.onToolbarOptionChanged(args.fullName, value) : this.repaint();
break;
default:
super._optionChanged(args)
}
}
_bringEditingModeToAppointments(editing) {
const editingConfig = {
allowDelete: editing.allowUpdating && editing.allowDeleting
};
if (!this._isAgenda()) {
editingConfig.allowDrag = editing.allowDragging;
editingConfig.allowResize = editing.allowResizing;
editingConfig.allowAllDayResize = editing.allowResizing && this._supportAllDayResizing()
}
this._appointments.option(editingConfig);
this.repaint()
}
_isAgenda() {
return "agenda" === this.currentView.type
}
_allowDragging() {
return this._editing.allowDragging && !this._isAgenda()
}
_allowResizing() {
return this._editing.allowResizing && !this._isAgenda()
}
_allowAllDayResizing() {
return this._editing.allowResizing && this._supportAllDayResizing()
}
_supportAllDayResizing() {
return "day" !== this.currentView.type || this.currentView.intervalCount > 1
}
_isAllDayExpanded() {
return this.option("showAllDayPanel") && this._layoutManager.hasAllDayAppointments()
}
_filterAppointmentsByDate() {
if (!this._workSpace) {
return
}
const dateRange = this._workSpace.getDateRange();
const startDate = this.timeZoneCalculator.createDate(dateRange[0], "fromGrid");
const endDate = this.timeZoneCalculator.createDate(dateRange[1], "fromGrid");
this.setRemoteFilter(startDate, endDate, this.option("remoteFiltering"), this.option("dateSerializationFormat"))
}
setRemoteFilter(min, max) {
let remoteFiltering = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : false;
let dateSerializationFormat = arguments.length > 3 ? arguments[3] : void 0;
const dataSource = this._dataSource;
const dataAccessors = this._dataAccessors;
if (!dataSource || !remoteFiltering) {
return
}
const dataSourceFilter = dataSource.filter();
const filter = (0, _remote.combineRemoteFilter)({
dataSourceFilter: dataSourceFilter,
dataAccessors: dataAccessors,
min: min,
max: max,
dateSerializationFormat: dateSerializationFormat,
forceIsoDateParsing: (0, _config.default)().forceIsoDateParsing
});
dataSource.filter(filter)
}
_reloadDataSource() {
const result = new _deferred.Deferred;
if (this._dataSource) {
this._dataSource.load().done((() => {
(0, _m_loading.hide)();
this._fireContentReadyAction(result)
})).fail((() => {
(0, _m_loading.hide)();
result.reject()
}));
this._dataSource.isLoading() && (0, _m_loading.show)({
container: this.$element(),
position: {
of: this.$element()
}
})
} else {
this._fireContentReadyAction(result)
}
return result.promise()
}
_fireContentReadyAction(result) {
const contentReadyBase = super._fireContentReadyAction.bind(this);
const fireContentReady = () => {
contentReadyBase();
null === result || void 0 === result || result.resolve()
};
if (this._workSpaceRecalculation) {
var _this$_workSpaceRecal;
null === (_this$_workSpaceRecal = this._workSpaceRecalculation) || void 0 === _this$_workSpaceRecal || _this$_workSpaceRecal.done((() => {
fireContentReady()
}))
} else {
fireContentReady()
}
}
_dimensionChanged(value) {
let isForce = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : false;
const isFixedHeight = "number" === typeof this.option("height");
const isFixedWidth = "number" === typeof this.option("width");
if (!this._isVisible()) {
return
}
this._toggleSmallClass();
const workspace = this.getWorkSpace();
if (!this._isAgenda() && this._layoutManager && workspace && !(0, _is_agenda_workpace_component.isAgendaWorkspaceComponent)(workspace)) {
if (isForce || !isFixedHeight || !isFixedWidth) {
workspace.option("allDayExpanded", this._isAllDayExpanded());
workspace._dimensionChanged();
const appointments = this._layoutManager.generateViewModel();
this._appointments.option("items", appointments)
}
}
this.hideAppointmentTooltip();
this._appointmentPopup.triggerResize();
this._appointmentPopup.updatePopupFullScreenMode()
}
_clean() {
this._cleanPopup();
super._clean()
}
_toggleSmallClass() {
const {
width: width
} = (0, _position.getBoundingRect)(this.$element().get(0));
this.$element().toggleClass(WIDGET_SMALL_CLASS, width < 400)
}
_toggleAdaptiveClass() {
this.$element().toggleClass(WIDGET_ADAPTIVE_CLASS, this.option("adaptivityEnabled"))
}
_visibilityChanged(visible) {
visible && this._dimensionChanged(null, true)
}
_dataSourceOptions() {
return {
paginate: false
}
}
_initAllDayPanel() {
if ("hidden" === this.option("allDayPanelMode")) {
this.option("showAllDayPanel", false)
}
}
_init() {
this._timeZonesPromise = _m_utils_time_zone.default.cacheTimeZones();
this._initExpressions({
startDateExpr: this.option("startDateExpr"),
endDateExpr: this.option("endDateExpr"),
startDateTimeZoneExpr: this.option("startDateTimeZoneExpr"),
endDateTimeZoneExpr: this.option("endDateTimeZoneExpr"),
allDayExpr: this.option("allDayExpr"),
textExpr: this.option("textExpr"),
descriptionExpr: this.option("descriptionExpr"),
recurrenceRuleExpr: this.option("recurrenceRuleExpr"),
recurrenceExceptionExpr: this.option("recurrenceExceptionExpr"),
disabledExpr: this.option("disabledExpr"),
visibleExpr: this.option("visibleExpr")
});
super._init();
this._initAllDayPanel();
this._initDataSource();
this._customizeDataSourceLoadOptions();
this.$element().addClass(WIDGET_CLASS);
this._initEditing();
this.updateAppointmentDataSource();
this._initActions();
this._compactAppointmentsHelper = new _m_compact_appointments_helper.CompactAppointmentsHelper(this);
this._asyncTemplatesTimers = [];
this._dataSourceLoadedCallback = (0, _callbacks.default)();
this._subscribes = _m_subscribes.default;
this.resourceManager = new _resource_manager.ResourceManager(this.option("resources"));
this._notifyScheduler = new _m_widget_notify_scheduler.default({
scheduler: this
})
}
createAppointmentDataSource() {
var _this$appointmentData;
null === (_this$appointmentData = this.appointmentDataSource) || void 0 === _this$appointmentData || _this$appointmentData.destroy();
this.appointmentDataSource = new _m_appointment_data_source.AppointmentDataSource(this._dataSource)
}
updateAppointmentDataSource() {
this._timeZoneCalculator = null;
if (this.getWorkSpace()) {
this.createAppointmentDataSource()
}
}
_customizeDataSourceLoadOptions() {
var _this$_dataSource;
null === (_this$_dataSource = this._dataSource) || void 0 === _this$_dataSource || _this$_dataSource.on("customizeStoreLoadOptions", (_ref => {
let {
storeLoadOptions: storeLoadOptions
} = _ref;
storeLoadOptions.startDate = this.getStartViewDate();
storeLoadOptions.endDate = this.getEndViewDate()
}))
}
_initTemplates() {
this._initAppointmentTemplate();
this._templateManager.addDefaultTemplates({
appointmentTooltip: new _empty_template.EmptyTemplate,
dropDownAppointment: new _empty_template.EmptyTemplate
});
super._initTemplates()
}
_initAppointmentTemplate() {
const {
expr: expr
} = this._dataAccessors;
const createGetter = property => (0, _data.compileGetter)(`appointmentData.${property}`);
const getDate = getter => data => {
const value = getter(data);
if (value instanceof Date) {
return value.valueOf()
}
return value
};
this._templateManager.addDefaultTemplates({
item: new _bindable_template.BindableTemplate((($container, data, model) => this.getAppointmentsInstance()._renderAppointmentTemplate($container, data, model)), ["html", "text", "startDate", "endDate", "allDay", "description", "recurrenceRule", "recurrenceException", "startDateTimeZone", "endDateTimeZone"], this.option("integrationOptions.watchMethod"), {
text: createGetter(expr.textExpr),
startDate: getDate(createGetter(expr.startDateExpr)),
endDate: getDate(createGetter(expr.endDateExpr)),
startDateTimeZone: createGetter(expr.startDateTimeZoneExpr),
endDateTimeZone: createGetter(expr.endDateTimeZoneExpr),
allDay: createGetter(expr.allDayExpr),
recurrenceRule: createGetter(expr.recurrenceRuleExpr)
})
})
}
_renderContent() {
this._renderContentImpl()
}
_dataSourceChangedHandler(result) {
if (this._readyToRenderAppointments) {
this._workSpaceRecalculation.done((() => {
this._layoutManager.prepareAppointments(result);
this._renderAppointments();
this._updateA11yStatus()
}))
}
}
isVirtualScrolling() {
const workspace = this.getWorkSpace();
if (workspace) {
return workspace.isVirtualScrolling()
}
const scrolling = this.getViewOption("scrolling");
return "virtual" === (null === scrolling || void 0 === scrolling ? void 0 : scrolling.mode)
}
_renderAppointments() {
const workspace = this.getWorkSpace();
this._layoutManager.filterAppointments();
workspace.option("allDayExpanded", this._isAllDayExpanded());
const viewModel = this._isVisible() ? this._layoutManager.generateViewModel() : [];
this._appointments.option("items", viewModel);
this.appointmentDataSource.cleanState();
if (this._isAgenda()) {
this._workSpace.renderAgendaLayout(viewModel)
}
}
_initExpressions(fields) {
this._dataAccessors = new _appointment_data_accessor.AppointmentDataAccessor(fields, Boolean((0, _config.default)().forceIsoDateParsing), this.option("dateSerializationFormat"))
}
_updateExpression(name, value) {
this._dataAccessors.updateExpression(name, value)
}
_initEditing() {
const editing = this.option("editing");
this._editing = {
allowAdding: Boolean(editing),
allowUpdating: Boolean(editing),
allowDeleting: Boolean(editing),
allowResizing: Boolean(editing),
allowDragging: Boolean(editing),
legacyForm: false
};
if ((0, _type.isObject)(editing)) {
this._editing = (0, _extend.extend)(this._editing, editing)
}
this._editing.allowDragging = this._editing.allowDragging && this._editing.allowUpdating;
this._editing.allowResizing = this._editing.allowResizing && this._editing.allowUpdating;
const isReadOnly = Object.values(Object.assign({}, this._editing, {
form: void 0,
popup: void 0
})).every((value => !value));
this.$element().toggleClass(WIDGET_READONLY_CLASS, isReadOnly)
}
_dispose() {
var _this$resourceManager2, _this$_appointmentToo, _this$_recurrenceDial;
null === (_this$resourceManager2 = this.resourceManager) || void 0 === _this$resourceManager2 || _this$resourceManager2.dispose();
null === (_this$_appointmentToo = this._appointmentTooltip) || void 0 === _this$_appointmentToo || _this$_appointmentToo.dispose();
null === (_this$_recurrenceDial = this._recurrenceDialog) || void 0 === _this$_recurrenceDial || _this$_recurrenceDial.hide(RECURRENCE_EDITING_MODE.CANCEL);
this.hideAppointmentPopup();
this.hideAppointmentTooltip();
this._asyncTemplatesTimers.forEach(clearTimeout);
this._asyncTemplatesTimers = [];
_index3.macroTaskArray.dispose();
super._dispose()
}
_initActions() {
this._actions = {
onAppointmentAdding: this._createActionByOption(StoreEventNames.ADDING),
onAppointmentAdded: this._createActionByOption(StoreEventNames.ADDED),
onAppointmentUpdating: this._createActionByOption(StoreEventNames.UPDATING),
onAppointmentUpdated: this._createActionByOption(StoreEventNames.UPDATED),
onAppointmentDeleting: this._createActionByOption(StoreEventNames.DELETING),
onAppointmentDeleted: this._createActionByOption(StoreEventNames.DELETED),
onAppointmentFormOpening: this._createActionByOption("onAppointmentFormOpening"),
onAppointmentTooltipShowing: this._createActionByOption("onAppointmentTooltipShowing")
}
}
_getAppointmentRenderedAction() {
return this._createActionByOption("onAppointmentRendered", {
excludeValidators: ["disabled", "readOnly"]
})
}
_renderFocusTarget() {
return (0, _common.noop)()
}
_updateA11yStatus() {
const dateRange = this._workSpace.getDateRange();
const indicatorTime = this.option("showCurrentTimeIndicator") ? (0, _index2.getToday)(this.option("indicatorTime"), this.timeZoneCalculator) : void 0;
const label = (0, _a11y_status_text.getA11yStatusText)(this.currentView, dateRange[0], dateRange[1], this._layoutManager.filteredItems.length, indicatorTime);
this.setAria({
label: label
});
this._a11yStatus.text(label)
}
_renderA11yStatus() {
this._a11yStatus = (0, _a11y_status_render.createA11yStatusContainer)();
this._a11yStatus.prependTo(this.$element());
this.setAria({
role: "group"
})
}
_initMarkupOnResourceLoaded() {
if (!this._disposed) {
this._initMarkupCore();
this._reloadDataSource()
}
}
_initMarkup() {
super._initMarkup();
this._renderA11yStatus();
this._renderMainContainer();
this._renderHeader();
this._toggleAdaptiveClass();
this._layoutManager = new _appointments_layout_manager.default(this);
this._appointments = this._createComponent("<div>", _m_appointment_collection.default, this._appointmentsConfig());
this._appointments.option("itemTemplate", this._getAppointmentTemplate("appointmentTemplate"));
this._appointmentTooltip = new(this.option("adaptivityEnabled") ? _m_mobile_tooltip_strategy.MobileTooltipStrategy : _m_desktop_tooltip_strategy.DesktopTooltipStrategy)(this._getAppointmentTooltipOptions());
this._createAppointmentPopupForm();
if (this._isDataSourceLoaded() || this._isDataSourceLoading()) {
this._initMarkupCore();
this._dataSourceChangedHandler(this._dataSource.items());
this._fireContentReadyAction()
} else {
const groups = this.getViewOption("groups");
if (null !== groups && void 0 !== groups && groups.length) {
this.resourceManager.loadGroupResources(groups, true).then((() => this._initMarkupOnResourceLoaded()))
} else {
this._initMarkupOnResourceLoaded()
}
}
}
_createAppointmentPopupForm() {
var _this$_appointmentPop;
if (this._appointmentForm) {
var _this$_appointmentFor;
null === (_this$_appointmentFor = this._appointmentForm.form) || void 0 === _this$_appointmentFor || _this$_appointmentFor.dispose()
}
this._appointmentForm = this.createAppointmentForm();
null === (_this$_appointmentPop = this._appointmentPopup) || void 0 === _this$_appointmentPop || _this$_appointmentPop.dispose();
this._appointmentPopup = this.createAppointmentPopup(this._appointmentForm)
}
_renderMainContainer() {
this._mainContainer = (0, _renderer.default)("<div>").addClass("dx-scheduler-container");
this.$element().append(this._mainContainer)
}
createAppointmentForm() {
const scheduler = {
getResourceById: () => this.resourceManager.resourceById,
getDataAccessors: () => this._dataAccessors,
createComponent: (element, component, options) => this._createComponent(element, component, options),
getEditingConfig: () => this._editing,
getResourceManager: () => this.resourceManager,
getFirstDayOfWeek: () => this.option("firstDayOfWeek"),
getStartDayHour: () => this.option("startDayHour"),
getCalculatedEndDate: startDateWithStartHour => this._workSpace.calculateEndDate(startDateWithStartHour),
getTimeZoneCalculator: () => this.timeZoneCalculator
};
if (this._editing.legacyForm) {
scheduler.createResourceEditorModel = () => (0, _popup_utils.createResourceEditorModel)(this.resourceManager.resourceById);
return new _m_legacy_form.AppointmentForm(scheduler)
}
return new _m_form.AppointmentForm(scheduler)
}
createAppointmentPopup(form) {
const scheduler = {
getElement: () => this.$element(),
createComponent: (element, component, options) => this._createComponent(element, component, options),
focus: () => this.focus(),
getResourceManager: () => this.resourceManager,
getEditingConfig: () => this._editing,
getTimeZoneCalculator: () => this.timeZoneCalculator,
getDataAccessors: () => this._dataAccessors,
getAppointmentFormOpening: () => this._actions.onAppointmentFormOpening,
processActionResult: (arg, canceled) => this._processActionResult(arg, canceled),
addAppointment: appointment => this.addAppointment(appointment),
updateAppointment: (sourceAppointment, updatedAppointment) => this.updateAppointment(sourceAppointment, updatedAppointment),
updateScrollPosition: (startDate, appointmentGroupValues, inAllDayRow) => {
this._workSpace.updateScrollPosition(startDate, appointmentGroupValues, inAllDayRow)
}
};
return this._editing.legacyForm ? new _m_legacy_popup.AppointmentPopup(scheduler, form) : new _m_popup.AppointmentPopup(scheduler, form)
}
_getAppointmentTooltipOptions() {
return {
createComponent: this._createComponent.bind(this),
container: this.$element(),
getScrollableContainer: this.getWorkSpaceScrollableContainer.bind(this),
addDefaultTemplates: this._templateManager.addDefaultTemplates.bind(this._templateManager),
getAppointmentTemplate: this._getAppointmentTemplate.bind(this),
showAppointmentPopup: this.showAppointmentPopup.bind(this),
checkAndDeleteAppointment: this.checkAndDeleteAppointment.bind(this),
isAppointmentInAllDayPanel: this.isAppointmentInAllDayPanel.bind(this),
createFormattedDateText: (appointment, targetedAppointment, format) => this.fire("createFormattedDateText", appointment, targetedAppointment, format),
getAppointmentDisabled: appointment => this._dataAccessors.get("disabled", appointment),
onItemContextMenu: this._createActionByOption("onAppointmentContextMenu"),
createEventArgs: this._createEventArgs.bind(this)
}
}
_createEventArgs(e) {
const config = {
itemData: e.itemData.appointment,
itemElement: e.itemElement,
targetedAppointment: e.itemData.targetedAppointment
};
return (0, _extend.extend)({}, this.fire("mapAppointmentFields", config), {
component: e.component,
element: e.element,
event: e.event,
model: e.model
})
}
checkAndDeleteAppointment(appointment, targetedAppointment) {
const targetedAdapter = new _appointment_adapter.AppointmentAdapter(targetedAppointment, this._dataAccessors);
const deletingOptions = this.fireOnAppointmentDeleting(appointment, targetedAdapter);
this._checkRecurringAppointment(appointment, targetedAppointment, targetedAdapter.startDate, (() => {
this.processDeleteAppointment(appointment, deletingOptions)
}), true)
}
_getExtraAppointmentTooltipOptions() {
return {
rtlEnabled: this.option("rtlEnabled"),
focusStateEnabled: this.option("focusStateEnabled"),
editing: this.option("editing"),
offset: this.option("_appointmentTooltipOffset")
}
}
isAppointmentInAllDayPanel(appointmentData) {
const workSpace = this._workSpace;
const itTakesAllDay = this.appointmentTakesAllDay(appointmentData);
return itTakesAllDay && workSpace.supportAllDayRow() && workSpace.option("showAllDayPanel")
}
_initMarkupCore() {
this._readyToRenderAppointments = (0, _window.hasWindow)();
this._workSpace && this._cleanWorkspace();
this._renderWorkSpace();
this._appointments.option({
fixedContainer: this._workSpace.getFixedContainer(),
allDayContainer: this._workSpace.getAllDayContainer()
});
this._waitAsyncTemplate((() => {
var _this$_workSpaceRecal2;
return null === (_this$_workSpaceRecal2 = this._workSpaceRecalculation) || void 0 === _this$_workSpaceRecal2 ? void 0 : _this$_workSpaceRecal2.resolve()
}));
this.createAppointmentDataSource();
this._filterAppointmentsByDate();
this._validateKeyFieldIfAgendaExist();
this._updateA11yStatus()
}
_isDataSourceLoaded() {
var _this$_dataSource2;
return null === (_this$_dataSource2 = this._dataSource) || void 0 === _this$_dataSource2 ? void 0 : _this$_dataSource2.isLoaded()
}
_render() {
var _this$getWorkSpace;
null === (_this$getWorkSpace = this.getWorkSpace()) || void 0 === _this$getWorkSpace || _this$getWorkSpace.updateHeaderEmptyCellWidth();
super._render()
}
_renderHeader() {
var _toolbarOptions$items;
const toolbarOptions = this.option("toolbar");
const isHeaderShown = Boolean(toolbarOptions.visible ?? (null === (_toolbarOptions$items = toolbarOptions.items) || void 0 === _toolbarOptions$items ? void 0 : _toolbarOptions$items.length));
if (isHeaderShown) {
const $header = (0, _renderer.default)("<div>").appendTo(this._mainContainer);
const headerOptions = this._headerConfig();
this._header = this._createComponent($header, _m_header.SchedulerHeader, headerOptions)
}
}
_headerConfig() {
return {
currentView: this.currentView,
views: this.views,
currentDate: this.getViewOption("currentDate"),
min: this.getViewOption("min"),
max: this.getViewOption("max"),
indicatorTime: this.option("indicatorTime"),
startViewDate: this.getStartViewDate(),
tabIndex: this.option("tabIndex"),
focusStateEnabled: this.option("focusStateEnabled"),
useDropDownViewSwitcher: this.option("useDropDownViewSwitcher"),
firstDayOfWeek: this.getFirstDayOfWeek(),
toolbar: this.option("toolbar"),
customizeDateNavigatorText: this.option("customizeDateNavigatorText"),
onCurrentViewChange: name => {
this.option("currentView", name)
},
onCurrentDateChange: date => {
this.option("currentDate", date)
}
}
}
_appointmentsConfig() {
const config = {
getResourceManager: () => this.resourceManager,
getAppointmentDataSource: () => this.appointmentDataSource,
dataAccessors: this._dataAccessors,
notifyScheduler: this._notifyScheduler,
onItemRendered: this._getAppointmentRenderedAction(),
onItemClick: this._createActionByOption("onAppointmentClick"),
onItemContextMenu: this._createActionByOption("onAppointmentContextMenu"),
onAppointmentDblClick: this._createActionByOption("onAppointmentDblClick"),
tabIndex: this.option("tabIndex"),
focusStateEnabled: this.option("focusStateEnabled"),
allowDrag: this._allowDragging(),
allowDelete: this._editing.allowUpdating && this._editing.allowDeleting,
allowResize: this._allowResizing(),
allowAllDayResize: this._allowAllDayResizing(),
rtlEnabled: this.option("rtlEnabled"),
groups: this.getViewOption("groups"),
groupByDate: this.getViewOption("groupByDate"),
timeZoneCalculator: this.timeZoneCalculator,
getResizableStep: () => this._workSpace ? this._workSpace.positionHelper.getResizableStep() : 0,
getDOMElementsMetaData: () => {
var _this$_workSpace;
return null === (_this$_workSpace = this._workSpace) || void 0 === _this$_workSpace ? void 0 : _this$_workSpace.getDOMElementsMetaData()
},
getViewDataProvider: () => {
var _this$_workSpace2;
return null === (_this$_workSpace2 = this._workSpace) || void 0 === _this$_workSpace2 ? void 0 : _this$_workSpace2.viewDataProvider
},
isVerticalGroupedWorkSpace: () => this._workSpace._isVerticalGroupedWorkSpace(),
isDateAndTimeView: () => (0, _index2.isDateAndTimeView)(this._workSpace.type),
onContentReady: () => {
var _this$_workSpace3;
null === (_this$_workSpace3 = this._workSpace) || void 0 === _this$_workSpace3 || _this$_workSpace3.option("allDayExpanded", this._isAllDayExpanded())
}
};
return config
}
_renderWorkSpace() {
const currentViewOptions = this.currentView;
if (!currentViewOptions) {
return
}
if (this._isAgenda()) {
this.renderAgendaWorkspace()
} else {
this.renderGridWorkspace()
}
this._recalculateWorkspace();
if (currentViewOptions.startDate) {
this._updateOption("header", "currentDate", this._workSpace._getHeaderDate())
}
}
renderGridWorkspace() {
if (this._readyToRenderAppointments) {
this._toggleSmallClass();
Promise.resolve().then((() => {
var _this$_workSpace4;
this._toggleSmallClass();
null === (_this$_workSpace4 = this._workSpace) || void 0 === _this$_workSpace4 || _this$_workSpace4.updateHeaderEmptyCellWidth()
}))
}
const $workSpace = (0, _renderer.default)("<div>").appendTo(this._mainContainer);
const currentViewType = this.currentView.type;
const workSpaceComponent = VIEWS_CONFIG[currentViewType].workSpace;
const workSpaceConfig = this._workSpaceConfig(this.currentView);
this._workSpace = this._createComponent($workSpace, workSpaceComponent, workSpaceConfig);
this._allowDragging() && this._workSpace.initDragBehavior(this, this._all);
this._workSpace._attachTablesEvents();
this._workSpace.getWorkArea().append(this._appointments.$element())
}
renderAgendaWorkspace() {
const $workSpace = (0, _renderer.default)("<div>").appendTo(this._mainContainer);
const workSpaceConfig = this._workSpaceConfig(this.currentView);
const workSpaceComponent = VIEWS_CONFIG.agenda.workSpace;
this._workSpace = this._createComponent($workSpace, workSpaceComponent, workSpaceConfig);
this._workSpace.getWorkArea().append(this._appointments.$element())
}
_recalculateWorkspace() {
this._workSpaceRecalculation = new _deferred.Deferred;
this._waitAsyncTemplate((() => {
(0, _visibility_change.triggerResizeEvent)(this._workSpace.$element());
this._workSpace.renderCurrentDateTimeLineAndShader()
}))
}
_workSpaceConfig(currentViewOptions) {
const scrolling = this.getViewOption("scrolling");
const isVirtualScrolling = "virtual" === scrolling.mode;
const horizontalVirtualScrollingAllowed = isVirtualScrolling && (!(0, _type.isDefined)(scrolling.orientation) || ["horizontal", "both"].includes(scrolling.orientation));
const crossScrollingEnabled = this.option("crossScrollingEnabled") || horizontalVirtualScrollingAllowed || (0, _index2.isTimelineView)(currentViewOptions.type);
const result = (0, _extend.extend)({
resources: this.option("resources"),
getResourceManager: () => this.resourceManager,
getFilteredItems: () => this._layoutManager.filteredItems,
noDataText: this.option("noDataText"),
firstDayOfWeek: this.option("firstDayOfWeek"),
startDayHour: this.option("startDayHour"),
endDayHour: this.option("endDayHour"),
viewOffset: this.getViewOffsetMs(),
tabIndex: this.option("tabIndex"),
accessKey: this.option("accessKey"),
focusStateEnabled: this.option("focusStateEnabled"),
cellDuration: this.option("cellDuration"),
showAllDayPanel: this.option("showAllDayPanel"),
showCurrentTimeIndicator: this.option("showCurrentTimeIndicator"),
indicatorTime: this.option("indicatorTime"),
indicatorUpdateInterval: this.option("indicatorUpdateInterval"),
shadeUntilCurrentTime: this.option("shadeUntilCurrentTime"),
crossScrollingEnabled: crossScrollingEnabled,
dataCellTemplate: this.option("dataCellTemplate"),
timeCellTemplate: this.option("timeCellTemplate"),
resourceCellTemplate: this.option("resourceCellTemplate"),
dateCellTemplate: this.option("dateCellTemplate"),
allowMultipleCellSelection: this.option("allowMultipleCellSelection"),
selectedCellData: this.option("selectedCellData"),
onSelectionChanged: args => {
this.option("selectedCellData", args.selectedCellData)
},
groupByDate: this.getViewOption("groupByDate"),
scrolling: scrolling,
draggingMode: this.option("_draggingMode"),
timeZoneCalculator: this.timeZoneCalculator,
schedulerHeight: this.option("height"),
schedulerWidth: this.option("width"),
allDayPanelMode: this.option("allDayPanelMode"),
onSelectedCellsClick: this.showAddAppointmentPopup.bind(this),
onRenderAppointments: () => {
this._renderAppointments()
},
onShowAllDayPanel: value => this.option("showAllDayPanel", value),
getHeaderHeight: () => _m_utils.utils.DOM.getHeaderHeight(this._header),
onScrollEnd: () => this._appointments.updateResizableArea(),
renovateRender: this._isRenovatedRender(isVirtualScrolling)
}, currentViewOptions);
result.notifyScheduler = this._notifyScheduler;
result.groups = this.resourceManager.groupResources();
result.onCellClick = this._createActionByOption("onCellClick");
result.onCellContextMenu = this._createActionByOption("onCellContextMenu");
result.currentDate = this.getViewOption("currentDate");
result.hoursInterval = result.cellDuration / 60;
result.allDayExpanded = false;
result.dataCellTemplate = result.dataCellTemplate ? this._getTemplate(result.dataCellTemplate) : null;
result.timeCellTemplate = result.timeCellTemplate ? this._getTemplate(result.timeCellTemplate) : null;
result.resourceCellTemplate = result.resourceCellTemplate ? this._getTemplate(result.resourceCellTemplate) : null;
result.dateCellTemplate = result.dateCellTemplate ? this._getTemplate(result.dateCellTemplate) : null;
return result
}
_isRenovatedRender(isVirtualScrolling) {
return this.option("renovateRender") && (0, _window.hasWindow)() || isVirtualScrolling
}
_waitAsyncTemplate(callback) {
if (this._options.silent("templatesRenderAsynchronously")) {
const timer = setTimeout((() => {
callback();
clearTimeout(timer)
}));
this._asyncTemplatesTimers.push(timer)
} else {
callback()
}
}
_getAppointmentTemplate(optionName) {
var _this$currentView;
if (null !== (_this$currentView = this.currentView) && void 0 !== _this$currentView && _this$currentView[optionName]) {
return this._getTemplate(this.currentView[optionName])
}
return this._getTemplateByOption(optionName)
}
_updateOption(viewName, optionName, value) {
var _this;
null === (_this = this[`_${viewName}`]) || void 0 === _this || _this.option(optionName, value)
}
_refreshWorkSpace() {
this._cleanWorkspace();
delete this._workSpace;
this._renderWorkSpace();
if (this._readyToRenderAppointments) {
this._appointments.option({
fixedContainer: this._workSpace.getFixedContainer(),
allDayContainer: this._workSpace.getAllDayContainer()
});
this._waitAsyncTemplate((() => this._workSpaceRecalculation.resolve()))
}
}
_cleanWorkspace() {
this._appointments.$element().detach();
this._workSpace._dispose();
this._workSpace.$element().remove();
this.option("selectedCellData", [])
}
getWorkSpaceScrollable() {
return this._workSpace.getScrollable()
}
getWorkSpaceScrollableContainer() {
return this._workSpace.getScrollableContainer()
}
getWorkSpace() {
return this._workSpace
}
getHeader() {
return this._header
}
_cleanPopup() {
var _this$_appointmentPop2;
null === (_this$_appointmentPop2 = this._appointmentPopup) || void 0 === _this$_appointmentPop2 || _this$_appointmentPop2.dispose()
}
_checkRecurringAppointment(rawAppointment, singleAppointment, exceptionDate, callback, isDeleted, isPopupEditing, dragEvent, recurrenceEditMode) {
const recurrenceRule = this._dataAccessors.get("recurrenceRule", rawAppointment);
if (!(0, _validate_rule.validateRRule)(recurrenceRule) || !this._editing.allowUpdating) {
callback();
return
}
const editMode = recurrenceEditMode || this.option("recurrenceEditMode");
switch (editMode) {
case "series":
callback();
break;
case "occurrence":
this._excludeAppointmentFromSeries(rawAppointment, singleAppointment, exceptionDate, isDeleted, isPopupEditing, dragEvent);
break;
default:
if (dragEvent) {
dragEvent.cancel = new _deferred.Deferred
}
this._showRecurrenceChangeConfirm(isDeleted).done((editingMode => {
editingMode === RECURRENCE_EDITING_MODE.SERIES && callback();
editingMode === RECURRENCE_EDITING_MODE.OCCURRENCE && this._excludeAppointmentFromSeries(rawAppointment, singleAppointment, exceptionDate, isDeleted, isPopupEditing, dragEvent)
})).fail((() => this._appointments.moveAppointmentBack(dragEvent)))
}
}
_excludeAppointmentFromSeries(rawAppointment, newRawAppointment, exceptionDate, isDeleted, isPopupEditing, dragEvent) {
const appointment = (0, _index2.excludeFromRecurrence)(rawAppointment, exceptionDate, this._dataAccessors);
const singleRawAppointment = Object.assign({}, newRawAppointment);
delete singleRawAppointment[this._dataAccessors.expr.recurrenceExceptionExpr];
delete singleRawAppointment[this._dataAccessors.expr.recurrenceRuleExpr];
const keyPropertyName = this.appointmentDataSource.keyName;
delete singleRawAppointment[keyPropertyName];
const canCreateNewAppointment = !isDeleted && !isPopupEditing;
if (canCreateNewAppointment) {
this.addAppointment(singleRawAppointment)
}
if (isPopupEditing) {
this._appointmentPopup.show(singleRawAppointment, {
isToolbarVisible: true,
action: _m_legacy_popup.ACTION_TO_APPOINTMENT.EXCLUDE_FROM_SERIES,
excludeInfo: {
sourceAppointment: rawAppointment,
updatedAppointment: appointment.source
}
});
this._editAppointmentData = rawAppointment
} else {
this._updateAppointment(rawAppointment, appointment.source, (() => {
this._appointments.moveAppointmentBack(dragEvent)
}), dragEvent)
}
}
_createRecurrenceException(appointment, exceptionDate) {
const result = [];
if (appointment.recurrenceException) {
result.push(appointment.recurrenceException)
}
result.push(this._getSerializedDate(exceptionDate, appointment.startDate, appointment.allDay));
return result.join()
}
_getSerializedDate(date, startDate, isAllDay) {
isAllDay && date.setHours(startDate.getHours(), startDate.getMinutes(), startDate.getSeconds(), startDate.getMilliseconds());
return _date_serialization.default.serializeDate(date, UTC_FULL_DATE_FORMAT)
}
_showRecurrenceChangeConfirm(isDeleted) {
const title = _message.default.format(isDeleted ? "dxScheduler-confirmRecurrenceDeleteTitle" : "dxScheduler-confirmRecurrenceEditTitle");
const message = _message.default.format(isDeleted ? "dxScheduler-confirmRecurrenceDeleteMessage" : "dxScheduler-confirmRecurrenceEditMessage");
const seriesText = _message.default.format(isDeleted ? "dxScheduler-confirmRecurrenceDeleteSeries" : "dxScheduler-confirmRecurrenceEditSeries");
const occurrenceText = _message.default.format(isDeleted ? "dxScheduler-confirmRecurrenceDeleteOccurrence" : "dxScheduler-confirmRecurrenceEditOccurrence");
this._recurrenceDialog = (0, _dialog.custom)({
title: title,
messageHtml: message,
showCloseButton: true,
showTitle: true,
buttons: [{
text: seriesText,
onClick: () => RECURRENCE_EDITING_MODE.SERIES
}, {
text: occurrenceText,
onClick: () => RECURRENCE_EDITING_MODE.OCCURRENCE
}],
popupOptions: {
wrapperAttr: {
class: POPUP_DIALOG_CLASS
},
onHidden: () => {
var _this$_appointments;
null === (_this$_appointments = this._appointments) || void 0 === _this$_appointments || _this$_appointments.focus()
}
}
});
return this._recurrenceDialog.show()
}
_getUpdatedData(rawAppointment) {
const viewOffset = this.getViewOffsetMs();
const getConvertedFromGrid = date => {
if (!date) {
return
}
const result = this.timeZoneCalculator.createDate(date, "fromGrid");
return _date3.dateUtilsTs.addOffsets(result, -viewOffset)
};
const targetCell = this.getTargetCellData();
const appointment = new _appointment_adapter.AppointmentAdapter(rawAppointment, this._dataAccessors);
const cellStartDate = getConvertedFromGrid(targetCell.startDate);
const cellEndDate = getConvertedFromGrid(targetCell.endDate);
let appointmentStartDate = new Date(appointment.startDate);
appointmentStartDate = _date3.dateUtilsTs.addOffsets(appointmentStartDate, -viewOffset);
let appointmentEndDate = new Date(appointment.endDate);
appointmentEndDate = _date3.dateUtilsTs.addOffsets(appointmentEndDate, -viewOffset);
let resultedStartDate = cellStartDate ?? appointmentStartDate;
if (!_date3.dateUtilsTs.isValidDate(appointmentStartDate)) {
appointmentStartDate = resultedStartDate
}
if (!_date3.dateUtilsTs.isValidDate(appointmentEndDate)) {
appointmentEndDate = cellEndDate
}
const duration = appointmentEndDate.getTime() - appointmentStartDate.getTime();
const isKeepAppointmentHours = this._workSpace.keepOriginalHours() && _date3.dateUtilsTs.isValidDate(appointment.startDate) && _date3.dateUtilsTs.isValidDate(cellStartDate);
if (isKeepAppointmentHours) {
const startDate = this.timeZoneCalculator.createDate(appointmentStartDate, "toGrid");
const timeInMs = startDate.getTime() - _date2.default.trimTime(startDate).getTime();
const targetCellStartDate = _date3.dateUtilsTs.addOffsets(targetCell.startDate, -viewOffset);
resultedStartDate = new Date(_date2.default.trimTime(targetCellStartDate).getTime() + timeInMs);
resultedStartDate = this.timeZoneCalculator.createDate(resultedStartDate, "fromGrid")
}
const result = new _appointment_adapter.AppointmentAdapter({}, this._dataAccessors);
if (void 0 !== targetCell.allDay) {
result.allDay = targetCell.allDay
}
result.startDate = resultedStartDate;
let resultedEndDate = new Date(resultedStartDate.getTime() + duration);
if (this.appointmentTakesAllDay(rawAppointment) && !result.allDay && this._workSpace.supportAllDayRow()) {
resultedEndDate = this._workSpace.calculateEndDate(resultedStartDate)
}
if (appointment.allDay && !this._workSpace.supportAllDayRow() && !this._workSpace.keepOriginalHours()) {
const dateCopy = new Date(resultedStartDate);
dateCopy.setHours(0);
resultedEndDate = new Date(dateCopy.getTime() + duration);
if (0 !== resultedEndDate.getHours()) {
resultedEndDate.setHours(this.getViewOption("endDayHour"))
}
}
result.startDate = _date3.dateUtilsTs.addOffsets(result.startDate, viewOffset);
result.endDate = _date3.dateUtilsTs.addOffsets(resultedEndDate, viewOffset);
const rawResult = result.source;
(0, _appointment_groups_utils.setAppointmentGroupValues)(rawResult, this.resourceManager.resourceById, targetCell.groups);
return rawResult
}
getTargetedAppointment(appointment, element) {
const settings = _m_utils.utils.dataAccessors.getAppointmentSettings(element);
return (0, _get_targeted_appointment.getTargetedAppointment)(appointment, settings, this._dataAccessors, this.resourceManager)
}
subscribe(subject, action) {
this._subscribes[subject] = _m_subscribes.default[subject] = action
}
fire(subject) {
const callback = this._subscribes[subject];
if (!(0, _type.isFunction)(callback)) {
throw _ui.default.Error("E1031", subject)
}
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key]
}
return callback.call(this, ...args)
}
getTargetCellData() {
return this._workSpace.getDataByDroppableCell()
}
_updateAppointment(target, rawAppointment, onUpdatePrevented, dragEvent) {
const updatingOptions = {
newData: rawAppointment,
oldData: (0, _extend.extend)({}, target),
cancel: false
};
const performFailAction = function(err) {
if (onUpdatePrevented) {
onUpdatePrevented.call(this)
}
if (err && "Error" === err.name) {
throw err
}
}.bind(this);
this._actions[StoreEventNames.UPDATING](updatingOptions);
if (dragEvent && !(0, _type.isDeferred)(dragEvent.cancel)) {
dragEvent.cancel = new _deferred.Deferred
}
if ((0, _type.isPromise)(updatingOptions.cancel) && dragEvent) {
this._updatingAppointments.add(target)
}
return this._processActionResult(updatingOptions, (function(canceled) {
let deferred = new _deferred.Deferred;
if (!canceled) {
this._expandAllDayPanel(rawAppointment);
try {
deferred = this.appointmentDataSource.update(target, rawAppointment).done((() => {
null === dragEvent || void 0 === dragEvent || dragEvent.cancel.resolve(false)
})).always((storeAppointment => {
this._updatingAppointments.delete(target);
this._onDataPromiseCompleted(StoreEventNames.UPDATED, storeAppointment)
})).fail((() => performFailAction()))
} catch (err) {
performFailAction(err);
this._updatingAppointments.delete(target);
deferred.resolve()
}
} else {
performFailAction();
this._updatingAppointments.delete(target);
deferred.resolve()
}
return deferred.promise()
}))
}
_processActionResult(actionOptions, callback) {
const deferred = new _deferred.Deferred;
const resolveCallback = callbackResult => {
(0, _deferred.when)((0, _deferred.fromPromise)(callbackResult)).always(deferred.resolve)
};
if ((0, _type.isPromise)(actionOptions.cancel)) {
(0, _deferred.when)((0, _deferred.fromPromise)(actionOptions.cancel)).always((cancel => {
if (!(0, _type.isDefined)(cancel)) {
cancel = "rejected" === actionOptions.cancel.state()
}
resolveCallback(callback.call(this, cancel))
}))
} else {
resolveCallback(callback.call(this, actionOptions.cancel))
}
return deferred.promise()
}
_expandAllDayPanel(appointment) {
if (!this._isAllDayExpanded() && this.appointmentTakesAllDay(appointment)) {
this._updateOption("workSpace", "allDayExpanded", true)
}
}
_onDataPromiseCompleted(handlerName, storeAppointment, appointment) {
const args = {
appointmentData: appointment || storeAppointment
};
if (storeAppointment instanceof Error) {
args.error = storeAppointment
} else {
this._appointmentPopup.visible && this._appointmentPopup.hide()
}
this._actions[handlerName](args);
this._fireContentReadyAction()
}
getAppointmentsInstance() {
return this._appointments
}
getLayoutManager() {
return this._layoutManager
}
getActions() {
return this._actions
}
appointmentTakesAllDay(rawAppointment) {
const appointment = new _appointment_adapter.AppointmentAdapter(rawAppointment, this._dataAccessors);
return (0, _index2.isAppointmentTakesAllDay)(appointment, this.getViewOption("allDayPanelMode"))
}
dayHasAppointment(day, rawAppointment, trimTime) {
const getConvertedToTimeZone = date => this.timeZoneCalculator.createDate(date, "toGrid");
const appointment = new _appointment_adapter.AppointmentAdapter(rawAppointment, this._dataAccessors);
let startDate = new Date(appointment.startDate);
let endDate = new Date(appointment.endDate);
startDate = getConvertedToTimeZone(startDate);
endDate = getConvertedToTimeZone(endDate);
if (day.getTime() === endDate.getTime()) {
return startDate.getTime() === endDate.getTime()
}
if (trimTime) {
day = _date2.default.trimTime(day);
startDate = _date2.default.trimTime(startDate);
endDate = _date2.default.trimTime(endDate)
}
const dayTimeStamp = day.getTime();
const startDateTimeStamp = startDate.getTime();
const endDateTimeStamp = endDate.getTime();
return startDateTimeStamp <= dayTimeStamp && dayTimeStamp <= endDateTimeStamp
}
getStartViewDate() {
var _this$_workSpace5;
return null === (_this$_workSpace5 = this._workSpace) || void 0 === _this$_workSpace5 ? void 0 : _this$_workSpace5.getStartViewDate()
}
getEndViewDate() {
return this._workSpace.getEndViewDate()
}
showAddAppointmentPopup(cellData, cellGroups) {
const appointmentAdapter = new _appointment_adapter.AppointmentAdapter({}, this._dataAccessors);
appointmentAdapter.allDay = Boolean(cellData.allDay);
appointmentAdapter.startDate = cellData.startDateUTC;
appointmentAdapter.endDate = cellData.endDateUTC;
const resultAppointment = (0, _extend.extend)(appointmentAdapter.source, cellGroups);
this.showAppointmentPopup(resultAppointment, true)
}
showAppointmentPopup(rawAppointment, createNewAppointment, rawTargetedAppointment) {
const newRawTargetedAppointment = Object.assign({}, rawTargetedAppointment);
if (newRawTargetedAppointment) {
delete newRawTargetedAppointment.displayStartDate;
delete newRawTargetedAppointment.displayEndDate
}
const newTargetedAppointment = (0, _extend.extend)({}, rawAppointment, newRawTargetedAppointment);
const isCreateAppointment = createNewAppointment ?? (0, _type.isEmptyObject)(rawAppointment);
if ((0, _type.isEmptyObject)(rawAppointment)) {
rawAppointment = this.createPopupAppointment()
}
if (isCreateAppointment) {
delete this._editAppointmentData;
this._editing.allowAdding && this._appointmentPopup.show(rawAppointment, {
isToolbarVisible: true,
action: _m_legacy_popup.ACTION_TO_APPOINTMENT.CREATE
})
} else {
const startDate = this._dataAccessors.get("startDate", newRawTargetedAppointment || rawAppointment);
this._checkRecurringAppointment(rawAppointment, newTargetedAppointment, startDate, (() => {
this._editAppointmentData = rawAppointment;
this._appointmentPopup.show(rawAppointment, {
isToolbarVisible: this._editing.allowUpdating,
action: _m_legacy_popup.ACTION_TO_APPOINTMENT.UPDATE
})
}), false, true)
}
}
createPopupAppointment() {
const result = {};
const toMs = _date2.default.dateToMilliseconds;
const startDate = new Date(this.option("currentDate"));
const endDate = new Date(startDate.getTime() + this.option("cellDuration") * toMs("minute"));
this._dataAccessors.set("startDate", result, startDate);
this._dataAccessors.set("endDate", result, endDate);
return result
}
hideAppointmentPopup(saveChanges) {
var _this$_appointmentPop3;
if (null !== (_this$_appointmentPop3 = this._appointmentPopup) && void 0 !== _this$_appointmentPop3 && _this$_appointmentPop3.visible) {
saveChanges && this._appointmentPopup.saveChangesAsync();
this._appointmentPopup.hide()
}
}
showAppointmentTooltip(appointment, element, targetedAppointment) {
if (appointment) {
const settings = _m_utils.utils.dataAccessors.getAppointmentSettings(element);
const appointmentConfig = {
itemData: targetedAppointment ?? appointment,
groupIndex: null === settings || void 0 === settings ? void 0 : settings.groupIndex
};
const info = {
appointment: appointment,
targetedAppointment: targetedAppointment,
color: this.resourceManager.getAppointmentColor(appointmentConfig)
};
this.showAppointmentTooltipCore(element, [info])
}
}
showAppointmentTooltipCore(target, data, options) {
const arg = {
cancel: false,
appointments: data.map((item => ({
appointmentData: item.appointment,
currentAppointmentData: Object.assign({}, item.targetedAppointment),
color: item.color
}))),
targetElement: (0, _element.getPublicElement)(target)
};
this._createActionByOption("onAppointmentTooltipShowing")(arg);
if (this._appointmentTooltip.isAlreadyShown(target)) {
this.hideAppointmentTooltip()
} else {
this._processActionResult(arg, (canceled => {
!canceled && this._appointmentTooltip.show(target, data, Object.assign({}, this._getExtraAppointmentTooltipOptions(), options))
}))
}
}
hideAppointmentTooltip() {
var _this$_appointmentToo2;
null === (_this$_appointmentToo2 = this._appointmentTooltip) || void 0 === _this$_appointmentToo2 || _this$_appointmentToo2.hide()
}
scrollTo(date, groupValues, allDay) {
this._workSpace.scrollTo(date, groupValues, allDay)
}
_isHorizontalVirtualScrolling() {
const scrolling = this.option("scrolling");
const {
orientation: orientation,
mode: mode
} = scrolling;
const isVirtualScrolling = "virtual" === mode;
return isVirtualScrolling && ("horizontal" === orientation || "both" === orientation)
}
addAppointment(rawAppointment) {
const appointment = new _appointment_adapter.AppointmentAdapter(rawAppointment, this._dataAccessors);
appointment.text = appointment.text || "";
const serializedAppointment = appointment.serialize().source;
const addingOptions = {
appointmentData: serializedAppointment,
cancel: false
};
this._actions[StoreEventNames.ADDING](addingOptions);
return this._processActionResult(addingOptions, (canceled => {
if (canceled) {
return (new _deferred.Deferred).resolve()
}
this._expandAllDayPanel(serializedAppointment);
return this.appointmentDataSource.add(serializedAppointment).always((storeAppointment => this._onDataPromiseCompleted(StoreEventNames.ADDED, storeAppointment)))
}))
}
updateAppointment(target, appointment) {
return this._updateAppointment(target, appointment)
}
deleteAppointment(rawAppointment) {
const deletingOptions = this.fireOnAppointmentDeleting(rawAppointment);
this.processDeleteAppointment(rawAppointment, deletingOptions)
}
fireOnAppointmentDeleting(rawAppointment, targetedAppointmentData) {
const deletingOptions = {
appointmentData: rawAppointment,
targetedAppointmentData: targetedAppointmentData,
cancel: false
};
this._actions[StoreEventNames.DELETING](deletingOptions);
return deletingOptions
}
processDeleteAppointment(rawAppointment, deletingOptions) {
this._processActionResult(deletingOptions, (function(canceled) {
if (!canceled) {
this.appointmentDataSource.remove(rawAppointment).always((storeAppointment => this._onDataPromiseCompleted(StoreEventNames.DELETED, storeAppointment, rawAppointment)))
}
}))
}
deleteRecurrence(appointment, date, recurrenceEditMode) {
if ("string" === typeof date) {
date = new Date(date)
}
this._checkRecurringAppointment(appointment, {}, date, (() => {
this.processDeleteAppointment(appointment, {
cancel: false
})
}), true, false, null, recurrenceEditMode)
}
focus() {
if (this._editAppointmentData) {
this._appointments.focus()
} else {
this._workSpace.focus()
}
}
getFirstDayOfWeek() {
return (0, _type.isDefined)(this.getViewOption("firstDayOfWeek")) ? this.getViewOption("firstDayOfWeek") : _date.default.firstDayOfWeekIndex()
}
_validateKeyFieldIfAgendaExist() {
if (!this.appointmentDataSource.isDataSourceInit) {
return
}
const hasAgendaView = this.hasAgendaView();
const isKeyNotExist = !this.appointmentDataSource.keyName;
if (hasAgendaView && isKeyNotExist) {
_ui.default.log("W1023")
}
}
_getDragBehavior() {
return this._workSpace.dragBehavior
}
_isAppointmentBeingUpdated(appointmentData) {
return this._updatingAppointments.has(appointmentData)
}
getViewOffsetMs() {
const offsetFromOptions = this.getViewOption("offset");
return this.normalizeViewOffsetValue(offsetFromOptions)
}
normalizeViewOffsetValue(viewOffset) {
var _this$currentView2;
if (!(0, _type.isDefined)(viewOffset) || (null === (_this$currentView2 = this.currentView) || void 0 === _this$currentView2 ? void 0 : _this$currentView2.type) === _constants_view.VIEWS.AGENDA) {
return 0
}
return viewOffset * toMs("minute")
}
}
Scheduler.include(_data_helper.default);
(0, _component_registrator.default)("dxScheduler", Scheduler);
var _default = exports.default = Scheduler;