UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

445 lines (442 loc) • 21 kB
/** * DevExtreme (cjs/__internal/scheduler/appointment_popup/m_form.js) * Version: 24.2.6 * Build date: Mon Mar 17 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.AppointmentForm = exports.APPOINTMENT_FORM_GROUP_NAMES = void 0; require("../m_recurrence_editor"); require("../../../ui/text_area"); require("../../../ui/tag_box"); require("../../../ui/switch"); require("../../../ui/select_box"); var _message = _interopRequireDefault(require("../../../common/core/localization/message")); var _data_source = _interopRequireDefault(require("../../../common/data/data_source")); var _devices = _interopRequireDefault(require("../../../core/devices")); var _renderer = _interopRequireDefault(require("../../../core/renderer")); var _date = _interopRequireDefault(require("../../../core/utils/date")); var _date_serialization = _interopRequireDefault(require("../../../core/utils/date_serialization")); var _extend = require("../../../core/utils/extend"); var _form = _interopRequireDefault(require("../../../ui/form")); var _themes = require("../../../ui/themes"); var _m_expression_utils = require("../../scheduler/m_expression_utils"); var _m_appointment_adapter = require("../m_appointment_adapter"); var _m_utils_time_zone = _interopRequireDefault(require("../m_utils_time_zone")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e } } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function(n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) { ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]) } } return n }, _extends.apply(null, arguments) } const SCREEN_SIZE_OF_SINGLE_COLUMN = 600; const APPOINTMENT_FORM_GROUP_NAMES = exports.APPOINTMENT_FORM_GROUP_NAMES = { Main: "mainGroup", Recurrence: "recurrenceGroup" }; const E2E_TEST_CLASSES = { form: "e2e-dx-scheduler-form", textEditor: "e2e-dx-scheduler-form-text", descriptionEditor: "e2e-dx-scheduler-form-description", startDateEditor: "e2e-dx-scheduler-form-start-date", endDateEditor: "e2e-dx-scheduler-form-end-date", startDateTimeZoneEditor: "e2e-dx-scheduler-form-start-date-timezone", endDateTimeZoneEditor: "e2e-dx-scheduler-form-end-date-timezone", allDaySwitch: "e2e-dx-scheduler-form-all-day-switch", recurrenceSwitch: "e2e-dx-scheduler-form-recurrence-switch" }; const DEFAULT_TIMEZONE_EDITOR_DATA_SOURCE_OPTIONS = { paginate: true, pageSize: 10 }; const getStylingModeFunc = () => (0, _themes.isFluent)((0, _themes.current)()) ? "filled" : void 0; const getStartDateWithStartHour = (startDate, startDayHour) => new Date(new Date(startDate).setHours(startDayHour)); const validateAppointmentFormDate = (editor, value, previousValue) => { const isCurrentDateCorrect = null === value || !!value; const isPreviousDateCorrect = null === previousValue || !!previousValue; if (!isCurrentDateCorrect && isPreviousDateCorrect) { editor.option("value", previousValue) } }; const updateRecurrenceItemVisibility = (recurrenceRuleExpr, value, form) => { var _form$getEditor; form.itemOption(APPOINTMENT_FORM_GROUP_NAMES.Recurrence, "visible", value); null === (_form$getEditor = form.getEditor(recurrenceRuleExpr)) || void 0 === _form$getEditor || _form$getEditor.changeValueByVisibility(value) }; class AppointmentForm { constructor(scheduler) { this.isFormUpdating = false; this.scheduler = scheduler; this.form = null } get dxForm() { return this.form } set readOnly(value) { this.form.option("readOnly", value); const { recurrenceRuleExpr: recurrenceRuleExpr } = this.scheduler.getDataAccessors().expr; const recurrenceEditor = this.form.getEditor(recurrenceRuleExpr); null === recurrenceEditor || void 0 === recurrenceEditor || recurrenceEditor.option("readOnly", value) } get formData() { return this.form.option("formData") } set formData(value) { this.form.option("formData", value) } create(triggerResize, changeSize, formData) { const { allowTimeZoneEditing: allowTimeZoneEditing } = this.scheduler.getEditingConfig(); const dataAccessors = this.scheduler.getDataAccessors(); const { expr: expr } = dataAccessors; const isRecurrence = !!_m_expression_utils.ExpressionUtils.getField(dataAccessors, "recurrenceRule", formData); const colSpan = isRecurrence ? 1 : 2; const mainItems = [...this._createMainItems(expr, triggerResize, changeSize, allowTimeZoneEditing), ...this.scheduler.createResourceEditorModel()]; changeSize(isRecurrence); const items = [{ itemType: "group", name: APPOINTMENT_FORM_GROUP_NAMES.Main, colCountByScreen: { lg: 2, xs: 1 }, colSpan: colSpan, items: mainItems }, { itemType: "group", name: APPOINTMENT_FORM_GROUP_NAMES.Recurrence, visible: isRecurrence, colSpan: colSpan, items: this._createRecurrenceEditor(expr) }]; const element = (0, _renderer.default)("<div>"); this.scheduler.createComponent(element, _form.default, { items: items, showValidationSummary: true, scrollingEnabled: true, colCount: "auto", colCountByScreen: { lg: 2, xs: 1 }, formData: formData, showColonAfterLabel: false, labelLocation: "top", onInitialized: e => { this.form = e.component }, screenByWidth: width => width < 600 || "desktop" !== _devices.default.current().deviceType ? "xs" : "lg", elementAttr: { class: E2E_TEST_CLASSES.form } }) } _createAppointmentAdapter(rawAppointment) { return (0, _m_appointment_adapter.createAppointmentAdapter)(rawAppointment, this.scheduler.getDataAccessors()) } _dateBoxValueChanged(args, dateExpr, isNeedCorrect) { validateAppointmentFormDate(args.component, args.value, args.previousValue); const value = _date_serialization.default.deserializeDate(args.value); const previousValue = _date_serialization.default.deserializeDate(args.previousValue); const dateEditor = this.form.getEditor(dateExpr); const dateValue = _date_serialization.default.deserializeDate(dateEditor.option("value")); if (!this.isFormUpdating && dateValue && value && isNeedCorrect(dateValue, value)) { const duration = previousValue ? dateValue.getTime() - previousValue.getTime() : 0; dateEditor.option("value", new Date(value.getTime() + duration)) } } _createTimezoneEditor(timeZoneExpr, secondTimeZoneExpr, visibleIndex, colSpan, isMainTimeZone, cssClass) { let visible = arguments.length > 6 && void 0 !== arguments[6] ? arguments[6] : false; const noTzTitle = _message.default.format("dxScheduler-noTimezoneTitle"); return { name: this.normalizeEditorName(timeZoneExpr), dataField: timeZoneExpr, editorType: "dxSelectBox", visibleIndex: visibleIndex, colSpan: colSpan, cssClass: cssClass, label: { text: " " }, editorOptions: { displayExpr: "title", valueExpr: "id", placeholder: noTzTitle, searchEnabled: true, onValueChanged: args => { const { form: form } = this; const secondTimezoneEditor = form.getEditor(secondTimeZoneExpr); if (isMainTimeZone) { secondTimezoneEditor.option("value", args.value) } } }, visible: visible } } _createDateBoxItems(dataExprs, allowTimeZoneEditing) { const colSpan = allowTimeZoneEditing ? 2 : 1; const firstDayOfWeek = this.scheduler.getFirstDayOfWeek(); return [this.createDateBoxEditor(dataExprs.startDateExpr, colSpan, firstDayOfWeek, "dxScheduler-editorLabelStartDate", E2E_TEST_CLASSES.startDateEditor, (args => { this._dateBoxValueChanged(args, dataExprs.endDateExpr, ((endValue, startValue) => endValue < startValue)) })), this._createTimezoneEditor(dataExprs.startDateTimeZoneExpr, dataExprs.endDateTimeZoneExpr, 1, colSpan, true, E2E_TEST_CLASSES.startDateTimeZoneEditor, allowTimeZoneEditing), this.createDateBoxEditor(dataExprs.endDateExpr, colSpan, firstDayOfWeek, "dxScheduler-editorLabelEndDate", E2E_TEST_CLASSES.endDateEditor, (args => { this._dateBoxValueChanged(args, dataExprs.startDateExpr, ((startValue, endValue) => endValue < startValue)) })), this._createTimezoneEditor(dataExprs.endDateTimeZoneExpr, dataExprs.startDateTimeZoneExpr, 3, colSpan, false, E2E_TEST_CLASSES.endDateTimeZoneEditor, allowTimeZoneEditing)] } _changeFormItemDateType(name, groupName, isAllDay) { const editorPath = this.getEditorPath(name, groupName); const itemEditorOptions = this.form.itemOption(editorPath).editorOptions; const type = isAllDay ? "date" : "datetime"; const newEditorOption = _extends({}, itemEditorOptions, { type: type }); this.form.itemOption(editorPath, "editorOptions", newEditorOption) } _createMainItems(dataExprs, triggerResize, changeSize, allowTimeZoneEditing) { return [{ name: this.normalizeEditorName(dataExprs.textExpr), dataField: dataExprs.textExpr, cssClass: E2E_TEST_CLASSES.textEditor, editorType: "dxTextBox", colSpan: 2, label: { text: _message.default.format("dxScheduler-editorLabelTitle") }, editorOptions: { stylingMode: getStylingModeFunc() } }, { itemType: "group", colSpan: 2, colCountByScreen: { lg: 2, xs: 1 }, items: this._createDateBoxItems(dataExprs, allowTimeZoneEditing) }, { itemType: "group", colSpan: 2, colCountByScreen: { lg: 2, xs: 2 }, items: [{ name: this.normalizeEditorName(dataExprs.allDayExpr), dataField: dataExprs.allDayExpr, cssClass: `dx-appointment-form-switch ${E2E_TEST_CLASSES.allDaySwitch}`, editorType: "dxSwitch", label: { text: _message.default.format("dxScheduler-allDay"), location: "right" }, editorOptions: { onValueChanged: args => { const { value: value } = args; const startDateEditor = this.form.getEditor(dataExprs.startDateExpr); const endDateEditor = this.form.getEditor(dataExprs.endDateExpr); const startDate = _date_serialization.default.deserializeDate(startDateEditor.option("value")); if (!this.isFormUpdating && startDate) { if (value) { const allDayStartDate = _date.default.trimTime(startDate); startDateEditor.option("value", new Date(allDayStartDate)); endDateEditor.option("value", new Date(allDayStartDate)) } else { const startDateWithStartHour = getStartDateWithStartHour(startDate, this.scheduler.getStartDayHour()); const endDate = this.scheduler.getCalculatedEndDate(startDateWithStartHour); startDateEditor.option("value", startDateWithStartHour); endDateEditor.option("value", endDate) } } this._changeFormItemDateType(dataExprs.startDateExpr, "Main", value); this._changeFormItemDateType(dataExprs.endDateExpr, "Main", value) } } }, { editorType: "dxSwitch", dataField: "repeat", cssClass: `dx-appointment-form-switch ${E2E_TEST_CLASSES.recurrenceSwitch}`, name: "visibilityChanged", label: { text: _message.default.format("dxScheduler-editorLabelRecurrence"), location: "right" }, editorOptions: { onValueChanged: args => { const { form: form } = this; const colSpan = args.value ? 1 : 2; form.itemOption(APPOINTMENT_FORM_GROUP_NAMES.Main, "colSpan", colSpan); form.itemOption(APPOINTMENT_FORM_GROUP_NAMES.Recurrence, "colSpan", colSpan); updateRecurrenceItemVisibility(dataExprs.recurrenceRuleExpr, args.value, form); changeSize(args.value); triggerResize() } } }] }, { itemType: "empty", colSpan: 2 }, { name: this.normalizeEditorName(dataExprs.descriptionExpr), dataField: dataExprs.descriptionExpr, cssClass: E2E_TEST_CLASSES.descriptionEditor, editorType: "dxTextArea", colSpan: 2, label: { text: _message.default.format("dxScheduler-editorLabelDescription") }, editorOptions: { stylingMode: getStylingModeFunc() } }, { itemType: "empty", colSpan: 2 }] } _createRecurrenceEditor(dataExprs) { return [{ name: this.normalizeEditorName(dataExprs.recurrenceRuleExpr), dataField: dataExprs.recurrenceRuleExpr, editorType: "dxRecurrenceEditor", editorOptions: { firstDayOfWeek: this.scheduler.getFirstDayOfWeek(), timeZoneCalculator: this.scheduler.getTimeZoneCalculator(), getStartDateTimeZone: () => this._createAppointmentAdapter(this.formData).startDateTimeZone }, label: { text: " ", visible: false } }] } setEditorsType(allDay) { const { startDateExpr: startDateExpr, endDateExpr: endDateExpr } = this.scheduler.getDataAccessors().expr; const startDateItemPath = this.getEditorPath(startDateExpr, "Main"); const endDateItemPath = this.getEditorPath(endDateExpr, "Main"); const startDateFormItem = this.form.itemOption(startDateItemPath); const endDateFormItem = this.form.itemOption(endDateItemPath); if (startDateFormItem && endDateFormItem) { const startDateEditorOptions = startDateFormItem.editorOptions; const endDateEditorOptions = endDateFormItem.editorOptions; startDateEditorOptions.type = endDateEditorOptions.type = allDay ? "date" : "datetime"; this.form.itemOption(startDateItemPath, "editorOptions", startDateEditorOptions); this.form.itemOption(endDateItemPath, "editorOptions", endDateEditorOptions) } } updateRecurrenceEditorStartDate(date, expression) { const options = { startDate: date }; this.setEditorOptions(expression, "Recurrence", options) } setEditorOptions(name, groupName, options) { const editorPath = this.getEditorPath(name, groupName); const editor = this.form.itemOption(editorPath); editor && this.form.itemOption(editorPath, "editorOptions", (0, _extend.extend)({}, editor.editorOptions, options)) } scheduleTimezoneEditorDataSourceUpdate(editorName, dataSource, selectedTimezoneLabel, date) { _m_utils_time_zone.default.getTimeZoneLabelsAsyncBatch(date).catch((() => [])).then((async timezones => { const store = dataSource.store(); await store.remove(null === selectedTimezoneLabel || void 0 === selectedTimezoneLabel ? void 0 : selectedTimezoneLabel.id); const insertPromises = timezones.reduce(((result, timezone) => { result.push(store.insert(timezone)); return result }), []); await Promise.all(insertPromises); dataSource.reload(); this.setEditorOptions(editorName, "Main", { dataSource: dataSource }) })).catch((() => {})) } setupTimezoneEditorDataSource(editorName, selectedTimezoneId, date) { const selectedTimezoneLabel = selectedTimezoneId ? _m_utils_time_zone.default.getTimeZoneLabel(selectedTimezoneId, date) : null; const dataSource = new _data_source.default(_extends({}, DEFAULT_TIMEZONE_EDITOR_DATA_SOURCE_OPTIONS, { store: selectedTimezoneLabel ? [selectedTimezoneLabel] : [] })); this.setEditorOptions(editorName, "Main", { dataSource: dataSource }); this.scheduleTimezoneEditorDataSourceUpdate(editorName, dataSource, selectedTimezoneLabel, date) } updateFormData(formData) { this.isFormUpdating = true; this.form.option("formData", formData); const dataAccessors = this.scheduler.getDataAccessors(); const { expr: expr } = dataAccessors; const rawStartDate = _m_expression_utils.ExpressionUtils.getField(dataAccessors, "startDate", formData); const rawEndDate = _m_expression_utils.ExpressionUtils.getField(dataAccessors, "endDate", formData); const startDateTimezone = _m_expression_utils.ExpressionUtils.getField(dataAccessors, "startDateTimeZone", formData) ?? null; const endDateTimezone = _m_expression_utils.ExpressionUtils.getField(dataAccessors, "endDateTimeZone", formData) ?? null; const allDay = _m_expression_utils.ExpressionUtils.getField(dataAccessors, "allDay", formData); const startDate = new Date(rawStartDate); const endDate = new Date(rawEndDate); this.setupTimezoneEditorDataSource(expr.startDateTimeZoneExpr, startDateTimezone, startDate); this.setupTimezoneEditorDataSource(expr.endDateTimeZoneExpr, endDateTimezone, endDate); this.updateRecurrenceEditorStartDate(startDate, expr.recurrenceRuleExpr); this.setEditorsType(allDay); this.isFormUpdating = false } createDateBoxEditor(dataField, colSpan, firstDayOfWeek, label, cssClass, onValueChanged) { return { editorType: "dxDateBox", name: this.normalizeEditorName(dataField), dataField: dataField, colSpan: colSpan, cssClass: cssClass, label: { text: _message.default.format(label) }, validationRules: [{ type: "required" }], editorOptions: { stylingMode: getStylingModeFunc(), width: "100%", calendarOptions: { firstDayOfWeek: firstDayOfWeek }, onValueChanged: onValueChanged, useMaskBehavior: true } } } getEditorPath(name, groupName) { const normalizedName = this.normalizeEditorName(name); return `${APPOINTMENT_FORM_GROUP_NAMES[groupName]}.${normalizedName}` } normalizeEditorName(name) { return name ? name.replace(/\./g, "_") : name } } exports.AppointmentForm = AppointmentForm;