devextreme
Version:
JavaScript/TypeScript Component Suite for Responsive Web Development
1,057 lines (1,056 loc) • 103 kB
JavaScript
/**
* DevExtreme (cjs/__internal/scheduler/scheduler.js)
* Version: 26.1.4
* Build date: Fri Jul 24 2026
*
* Copyright (c) 2012 - 2026 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 _m_selectors = require("../core/utils/m_selectors");
var _m_short = require("../events/m_short");
var _a11y_status_render = require("./a11y_status/a11y_status_render");
var _a11y_status_text = require("./a11y_status/a11y_status_text");
var _appointment_drag_controller = require("./appointment_drag_controller");
var _form = require("./appointment_popup/form");
var _popup = require("./appointment_popup/popup");
var _m_appointment_collection = _interopRequireDefault(require("./appointments/m_appointment_collection"));
var _appointments = require("./appointments_new/appointments");
var _get_appointment_date_range = require("./appointments_new/resizing/get_appointment_date_range");
var _get_delta_time = require("./appointments_new/resizing/get_delta_time");
var _get_resizable_config = require("./appointments_new/resizing/get_resizable_config");
var _get_resized_dates = require("./appointments_new/resizing/get_resized_dates");
var _widget_notify_scheduler = _interopRequireDefault(require("./base/widget_notify_scheduler"));
var _constants = require("./constants");
var _header = require("./header/header");
var _loading = require("./loading");
var _m_compact_appointments_helper = require("./m_compact_appointments_helper");
var _m_subscribes = _interopRequireDefault(require("./m_subscribes"));
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 _desktop_tooltip_strategy = require("./tooltip_strategies/desktop_tooltip_strategy");
var _mobile_tooltip_strategy = require("./tooltip_strategies/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 _resource_manager = require("./utils/resource_manager/resource_manager");
var _utils_time_zone = _interopRequireDefault(require("./utils_time_zone"));
var _appointments_layout_manager = _interopRequireDefault(require("./view_model/appointments_layout_manager"));
var _m_appointment_data_source = require("./view_model/m_appointment_data_source");
var _agenda = _interopRequireDefault(require("./workspaces/agenda"));
var _timeline_day = _interopRequireDefault(require("./workspaces/timeline_day"));
var _timeline_month = _interopRequireDefault(require("./workspaces/timeline_month"));
var _timeline_week = _interopRequireDefault(require("./workspaces/timeline_week"));
var _work_space_day = _interopRequireDefault(require("./workspaces/work_space_day"));
var _work_space_month = _interopRequireDefault(require("./workspaces/work_space_month"));
var _work_space_week = _interopRequireDefault(require("./workspaces/work_space_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: _work_space_day.default,
renderingStrategy: "vertical"
},
week: {
workSpace: _work_space_week.default,
renderingStrategy: "vertical"
},
workWeek: {
workSpace: _work_space_week.default,
renderingStrategy: "vertical"
},
month: {
workSpace: _work_space_month.default,
renderingStrategy: "horizontalMonth"
},
timelineDay: {
workSpace: _timeline_day.default,
renderingStrategy: "horizontal"
},
timelineWeek: {
workSpace: _timeline_week.default,
renderingStrategy: "horizontal"
},
timelineWorkWeek: {
workSpace: _timeline_week.default,
renderingStrategy: "horizontal"
},
timelineMonth: {
workSpace: _timeline_month.default,
renderingStrategy: "horizontalMonthLine"
},
agenda: {
workSpace: _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.timeZoneCalculatorInstance = null;
this.appointmentResizeInitialSize = null;
this.asyncTemplatesTimers = [];
this.updatingAppointments = new Set;
this.subscribes = _m_subscribes.default
}
get timeZoneCalculator() {
if (!this.timeZoneCalculatorInstance) {
this.timeZoneCalculatorInstance = (0, _index.createTimeZoneCalculator)(this.option("timeZone"))
}
return this.timeZoneCalculatorInstance
}
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))
}, void 0);
const resolveCallbacks = (0, _deferred.Deferred)();
whenLoaded.done(() => {
resolveCallbacks.resolve()
});
this.postponeDataSourceLoading(whenLoaded);
return resolveCallbacks
}
_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.updateOption("header", "startViewDate", this.getStartViewDate());
this.createAppointmentPopupForm();
break;
case "currentDate": {
const dateValue = this.getViewOption("currentDate");
this.option("selectedCellData", []);
this.updateOption("workSpace", name, dateValue);
this.updateOption("header", name, dateValue);
this.updateOption("header", "startViewDate", this.getStartViewDate());
this._appointments.option("items", []);
this.setRemoteFilterIfNeeded();
this.postponeDataSourceLoading();
break
}
case "dataSource":
this._initDataSource();
this.postponeResourceLoading().done(() => {
if (this._dataSource) {
if (this.appointmentDataSource) {
this.appointmentDataSource.setDataSource(this._dataSource)
} else {
this.createAppointmentDataSource()
}
}
this.setRemoteFilterIfNeeded();
this.updateOption("workSpace", "showAllDayPanel", this.option("showAllDayPanel"))
});
break;
case "min":
case "max": {
const viewValue = "min" === args.name ? this.getViewOption("min") : this.getViewOption("max");
this.updateOption("header", args.name, viewValue);
this.updateOption("workSpace", args.name, viewValue);
break
}
case "views":
if (this.currentView) {
this.repaint()
} else {
this.updateOption("header", "views", this.views)
}
break;
case "hiddenWeekDays":
this.repaint();
break;
case "useDropDownViewSwitcher":
this.updateOption("header", name, value);
break;
case "currentView":
if (this.option("_newAppointments")) {
this._appointments.option({
currentView: value,
viewModel: [],
appointmentTemplate: this.getViewOption("appointmentTemplate"),
appointmentCollectorTemplate: this.getViewOption("appointmentCollectorTemplate")
})
} else {
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.setRemoteFilterIfNeeded();
if (!this.option("_newAppointments")) {
this._appointments.option("allowAllDayResize", "day" !== value)
}
});
this.postponedOperations.callPostponedOperations();
break;
case "appointmentTemplate":
if (this.option("_newAppointments")) {
this._appointments.option("appointmentTemplate", this.getViewOption("appointmentTemplate"))
} else {
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.setRemoteFilterIfNeeded()
});
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.createAppointmentPopupForm();
this.postponeResourceLoading().done(() => {
this._appointments.option("items", []);
this.refreshWorkSpace();
this.setRemoteFilterIfNeeded()
});
break;
case "startDayHour":
case "endDayHour":
this.updateAppointmentDataSource();
this._appointments.option("items", []);
this.updateOption("workSpace", name, value);
if (!this.option("_newAppointments")) {
this._appointments.repaint()
}
this.setRemoteFilterIfNeeded();
this.postponeDataSourceLoading();
this.createAppointmentPopupForm();
break;
case "offset":
this.updateAppointmentDataSource();
this._appointments.option("items", []);
this.updateOption("workSpace", "viewOffset", this.normalizeViewOffsetValue(value));
if (!this.option("_newAppointments")) {
this._appointments.repaint()
}
this.setRemoteFilterIfNeeded();
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":
case "onSelectionEnd": {
const schedulerAction = this.createSchedulerAction(name);
this.actions[name] = schedulerAction;
break
}
case "onAppointmentRendered":
if (this.option("_newAppointments")) {
this.actions.onAppointmentRendered = this.createSchedulerAction("onAppointmentRendered")
} else {
this._appointments.option("onItemRendered", this.getAppointmentRenderedAction())
}
break;
case "onAppointmentClick":
if (this.option("_newAppointments")) {
this.actions.onAppointmentClick = this.createSchedulerAction("onAppointmentClick")
} else {
this._appointments.option("onItemClick", this._createActionByOption("onAppointmentClick"))
}
break;
case "onAppointmentDblClick":
if (this.option("_newAppointments")) {
this.actions.onAppointmentDblClick = this.createSchedulerAction("onAppointmentDblClick")
} else {
this._appointments.option("onAppointmentDblClick", this._createActionByOption("onAppointmentDblClick"))
}
break;
case "onAppointmentContextMenu":
if (this.option("_newAppointments")) {
this.actions.onAppointmentContextMenu = this.createSchedulerAction("onAppointmentContextMenu")
} else {
this._appointments.option("onItemContextMenu", this._createActionByOption("onAppointmentContextMenu"))
}
this.appointmentTooltip._options.onItemContextMenu = this._createActionByOption("onAppointmentContextMenu");
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 "snapToCellsMode":
this._appointments.option("items", []);
if (this.readyToRenderAppointments) {
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: editing
} = this;
if (this.option("_newAppointments")) {
this._appointments.option("allowDelete", this.editing.allowDeleting)
} else {
this.bringEditingModeToAppointments(editing)
}
this.hideAppointmentTooltip();
this.createAppointmentPopupForm();
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 "skippedDays":
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":
if (this.option("_newAppointments")) {
this._appointments.option("appointmentCollectorTemplate", this.getViewOption("appointmentCollectorTemplate"))
} else {
this.repaint()
}
break;
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 "_draggingMode":
this.updateOption("workSpace", "draggingMode", value);
break;
case "toolbar":
if (this.header) {
this.header.onToolbarOptionChanged(args.fullName, value)
} else {
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()
}
canDragAppointment(appointmentData) {
return this.allowDragging() && !this._isAppointmentBeingUpdated(appointmentData)
}
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()
}
setRemoteFilterIfNeeded() {
const dataSource = this._dataSource;
const remoteFiltering = this.option("remoteFiltering");
if (!this._workSpace || !remoteFiltering || !dataSource) {
return
}
const dateRange = this._workSpace.getDateRange();
const startDate = this.timeZoneCalculator.createDate(dateRange[0], "fromGrid");
const endDate = this.timeZoneCalculator.createDate(dateRange[1], "fromGrid");
const dateSerializationFormat = this.option("dateSerializationFormat");
const dataSourceFilter = dataSource.filter();
const filter = (0, _remote.combineRemoteFilter)({
dataSourceFilter: dataSourceFilter,
dataAccessors: this._dataAccessors,
min: startDate,
max: endDate,
dateSerializationFormat: dateSerializationFormat,
forceIsoDateParsing: (0, _config.default)().forceIsoDateParsing
});
dataSource.filter(filter)
}
reloadDataSource() {
const result = (0, _deferred.Deferred)();
if (this._dataSource) {
(0, _deferred.when)((0, _deferred.fromPromise)(this._dataSource.load())).done(() => {
(0, _loading.hide)().catch(_common.noop);
this._fireContentReadyAction(result)
}).fail(() => {
(0, _loading.hide)().catch(_common.noop);
result.reject()
});
if (this._dataSource.isLoading()) {
(0, _loading.show)({
container: this.$element().get(0),
position: {
of: this.$element()
}
}).catch(_common.noop)
}
} 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 ((0, _type.isDeferred)(this.workSpaceRecalculation)) {
this.workSpaceRecalculation.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 element = this.$element().get(0);
const {
width: width
} = (0, _position.getBoundingRect)(element);
this.$element().toggleClass(WIDGET_SMALL_CLASS, width < 400)
}
toggleAdaptiveClass() {
this.$element().toggleClass(WIDGET_ADAPTIVE_CLASS, this.option("adaptivityEnabled"))
}
_visibilityChanged(visible) {
if (visible) {
this._dimensionChanged(null, true)
}
}
_dataSourceOptions() {
return {
paginate: false
}
}
initAllDayPanel() {
if ("hidden" === this.option("allDayPanelMode")) {
this.option("showAllDayPanel", false)
}
}
_init() {
this.timeZonesPromise = _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 _widget_notify_scheduler.default({
scheduler: this
});
this.appointmentDragController = new _appointment_drag_controller.AppointmentDragController({
component: this,
$draggableContainer: () => this.$draggableContainer ?? this.$element(),
canDragAppointment: this.canDragAppointment.bind(this),
getCellFromDragTarget: $dragTarget => this._workSpace.getCellFromDragTarget($dragTarget),
getCellFromPoint: (x, y) => this._workSpace.getCellFromPoint(x, y),
getDroppableCell: () => this._workSpace.getDroppableCell(),
createComponent: this._createComponent.bind(this),
hideAppointmentTooltip: this.hideAppointmentTooltip.bind(this),
getAppointmentDraggingConfig: () => this.option("appointmentDragging") ?? {},
getUpdatedItemData: this.getUpdatedData.bind(this),
updateAppointmentOnDrop: this.updateAppointmentOnDrop.bind(this)
})
}
createAppointmentDataSource() {
var _this$appointmentData;
null === (_this$appointmentData = this.appointmentDataSource) || void 0 === _this$appointmentData || _this$appointmentData.destroy();
if (!this._dataSource) {
return
}
this.appointmentDataSource = new _m_appointment_data_source.AppointmentDataSource(this._dataSource)
}
updateAppointmentDataSource() {
this.timeZoneCalculatorInstance = 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() {
var _this$appointmentData2;
const workspace = this.getWorkSpace();
this._layoutManager.filterAppointments();
null === workspace || void 0 === workspace || workspace.option("allDayExpanded", this.isAllDayExpanded());
const viewModel = this._isVisible() ? this._layoutManager.generateViewModel() : [];
this._appointments.option("items", viewModel);
null === (_this$appointmentData2 = this.appointmentDataSource) || void 0 === _this$appointmentData2 || _this$appointmentData2.cleanState();
if (this.isAgenda()) {
var _this$_workSpace$rend, _this$_workSpace;
null === (_this$_workSpace$rend = (_this$_workSpace = this._workSpace).renderAgendaLayout) || void 0 === _this$_workSpace$rend || _this$_workSpace$rend.call(_this$_workSpace, 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)
};
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$appointmentTool, _this$recurrenceDialo;
null === (_this$resourceManager2 = this.resourceManager) || void 0 === _this$resourceManager2 || _this$resourceManager2.dispose();
null === (_this$appointmentTool = this.appointmentTooltip) || void 0 === _this$appointmentTool || _this$appointmentTool.dispose();
null === (_this$recurrenceDialo = this.recurrenceDialog) || void 0 === _this$recurrenceDialo || _this$recurrenceDialo.hide(RECURRENCE_EDITING_MODE.CANCEL);
this.hideAppointmentPopup();
this.hideAppointmentTooltip();
this.asyncTemplatesTimers.forEach(clearTimeout);
this.asyncTemplatesTimers = [];
_index3.macroTaskArray.dispose();
super._dispose()
}
createSchedulerAction(optionName, actionConfig) {
return this._createActionByOption(optionName, actionConfig)
}
initActions() {
this.actions = {
onAppointmentAdding: this.createSchedulerAction(StoreEventNames.ADDING),
onAppointmentAdded: this.createSchedulerAction(StoreEventNames.ADDED),
onAppointmentUpdating: this.createSchedulerAction(StoreEventNames.UPDATING),
onAppointmentUpdated: this.createSchedulerAction(StoreEventNames.UPDATED),
onAppointmentDeleting: this.createSchedulerAction(StoreEventNames.DELETING),
onAppointmentDeleted: this.createSchedulerAction(StoreEventNames.DELETED),
onAppointmentFormOpening: this.createSchedulerAction("onAppointmentFormOpening"),
onAppointmentTooltipShowing: this.createSchedulerAction("onAppointmentTooltipShowing"),
onSelectionEnd: this.createSchedulerAction("onSelectionEnd"),
onAppointmentRendered: this.createSchedulerAction("onAppointmentRendered"),
onAppointmentClick: this.createSchedulerAction("onAppointmentClick"),
onAppointmentDblClick: this.createSchedulerAction("onAppointmentDblClick"),
onAppointmentContextMenu: this.createSchedulerAction("onAppointmentContextMenu")
}
}
getAppointmentRenderedAction() {
return this.createSchedulerAction("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: "application"
})
}
initMarkupOnResourceLoaded() {
if (!this._disposed) {
this.initMarkupCore();
this.reloadDataSource().catch(_common.noop)
}
}
_initMarkup() {
var _this = this;
super._initMarkup();
this.renderA11yStatus();
this.renderMainContainer();
this.renderHeader();
this.toggleAdaptiveClass();
this._layoutManager = new _appointments_layout_manager.default(this);
this.appointmentTooltip = new(this.option("adaptivityEnabled") ? _mobile_tooltip_strategy.MobileTooltipStrategy : _desktop_tooltip_strategy.DesktopTooltipStrategy)(this.getAppointmentTooltipOptions());
if (this.option("_newAppointments")) {
const appointmentsConfig = {
tabIndex: this.option("tabIndex"),
currentView: this.option("currentView"),
allowDelete: this.editing.allowDeleting,
appointmentTemplate: this.getViewOption("appointmentTemplate"),
appointmentCollectorTemplate: this.getViewOption("appointmentCollectorTemplate"),
onAppointmentRendered: function() {
return _this.actions.onAppointmentRendered(...arguments)
},
onAppointmentClick: args => this.actions.onAppointmentClick(args),
onAppointmentDblClick: function() {
return _this.actions.onAppointmentDblClick(...arguments)
},
onAppointmentContextMenu: function() {
return _this.actions.onAppointmentContextMenu(...arguments)
},
onDeleteKeyPress: e => {
this.checkAndDeleteAppointment(e.appointmentData, e.targetedAppointmentData)
},
focusFallbackAfterDelete: () => this.focusFallbackAfterDelete(),
getResizableConfig: viewModel => this.createAppointmentResizableConfig(viewModel),
getResourceManager: () => this.resourceManager,
getAppointmentDataSource: () => this.appointmentDataSource,
getDataAccessor: () => this._dataAccessors,
getStartViewDate: () => this.getStartViewDate(),
getSortedItems: () => this._layoutManager.sortedItems,
isVirtualScrolling: () => this.isVirtualScrolling(),
scrollTo: this.scrollTo.bind(this),
showAppointmentTooltip: this.showAppointmentTooltipCore.bind(this),
isTooltipShownForTarget: target => this.appointmentTooltip.isShownForTarget(target),
updateAppointmentTooltip: (target, data) => {
this.appointmentTooltip.setTarget(target);
this.appointmentTooltip.setListItems(data)
},
hideAppointmentTooltip: () => this.hideAppointmentTooltip(),
showEditAppointmentPopup: (appointmentData, targetedAppointmentData) => {
this.showAppointmentPopup(appointmentData, false, targetedAppointmentData)
}
};
this._appointments = this._createComponent("<div>", _appointments.Appointments, appointmentsConfig)
} else {
this._appointments = this._createComponent("<div>", _m_appointment_collection.default, this.appointmentsConfig());
this._appointments.option("itemTemplate", this.getAppointmentTemplate("appointmentTemplate"))
}
this.createAppointmentPopupForm();
if (this.isDataSourceLoaded() || this._isDataSourceLoading()) {
var _this$_dataSource2;
this.initMarkupCore();
this._dataSourceChangedHandler((null === (_this$_dataSource2 = this._dataSource) || void 0 === _this$_dataSource2 ? void 0 : _this$_dataSource2.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()).catch(_common.noop)
} else {
this.initMarkupOnResourceLoaded()
}
}
}
createAppointmentPopupForm() {
var _this$appointmentPopu;
if (this.appointmentForm) {
this.appointmentForm.dispose()
}
this.appointmentForm = this.createAppointmentForm();
null === (_this$appointmentPopu = this.appointmentPopup) || void 0 === _this$appointmentPopu || _this$appointmentPopu.dispose();
this.appointmentPopup = this.createAppointmentPopup(this.appointmentForm)
}
renderMainContainer() {
this.mainContainer = (0, _renderer.default)("<div>").addClass("dx-scheduler-container");
this.$draggableContainer = (0, _renderer.default)("<div>").addClass("dx-scheduler-draggable-container").appendTo(this.mainContainer);
this.$element().append(this.mainContainer)
}
createAppointmentForm() {
const appointmentFormConfig = {
dataAccessors: this._dataAccessors,
editing: this.editing,
resourceManager: this.resourceManager,
firstDayOfWeek: this.getFirstDayOfWeek(),
startDayHour: this.option("startDayHour") ?? 0,
createComponent: this._createComponent.bind(this),
getCalculatedEndDate: startDateWithStartHour => this._workSpace.calculateEndDate(startDateWithStartHour)
};
return new _form.AppointmentForm(appointmentFormConfig)
}
createAppointmentPopup(form) {
const scheduler = {
getElement: () => this.$element(),
createComponent: this._createComponent.bind(this),
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)
};
return new _popup.AppointmentPopup(scheduler, form)
}
scrollToAppointment(appointment) {
const adapter = new _appointment_adapter.AppointmentAdapter(appointment, this._dataAccessors);
const {
startDate: startDate,
endDate: endDate,
allDay: allDay
} = adapter;
if (!startDate) {
return
}
const startTime = startDate.getTime();
const endTime = endDate ? endDate.getTime() : startTime;
const dayInMs = toMs("day");
const inAllDayRow = allDay || endTime - startTime >= dayInMs;
const appointmentGroupValues = (0, _appointment_groups_utils.getAppointmentGroupValues)(appointment, this.resourceManager.resources);
this._workSpace.updateScrollPosition(startDate, appointmentGroupValues, inAllDayRow)
}
saveAppointmentAndScroll(saveAction, appointment) {
return (0, _deferred.when)(saveAction()).done(() => {
this.scrollToAppointment(appointment)
}).promise()
}
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 ?? appointment, format),
getAppointmentDisabled: appointment => this._dataAccessors.get("disabled", appointment),
onItemContextMenu: this._createActionByOption("onAppointmentContextMenu"),
createEventArgs: this._createEventArgs.bind(this),
newAppointments: Boolean(this.option("_newAppointments")),
onAppointmentClick: args => this.actions.onAppointmentClick(args),
onListInitialized: e => {
if (this.option("_newAppointments") && e.element) {
this.appointmentDragController.createTooltipDraggable((0, _renderer.default)(e.element), {
dragTemplate: this._appointments.renderDragClone.bind(this._appointments)
})
}
},
onListDisposing: () => {
this.appointmentDragController.disposeTooltipDraggable()
}
}
}
_createEventArgs(e) {
var _e$itemData, _e$itemData2;
const itemData = null === (_e$itemData = e.itemData) || void 0 === _e$itemData ? void 0 : _e$itemData.appointment;
if (!itemData) {
throw _ui.default.Error("E0001")
}
const eventConfig = {
itemData: itemData,
itemElement: (0, _renderer.default)(e.itemElement),
targetedAppointment: null === (_e$itemData2 = e.itemData) || void 0 === _e$itemData2 ? void 0 : _e$itemData2.targetedAppointment
};
const mappedFields = this.fire("mapAppointmentFields", eventConfig);
return (0, _extend.extend)({}, mappedFields, {
component: e.component,
element: e.element,
event: e.event,
model: e.model
})
}
focusFallbackAfterDelete() {
var _this$header2, _this$_workSpace2;
const $headerFocusable = null === (_t