diff --git a/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.component.css b/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.component.css new file mode 100644 index 000000000000..95736308e283 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.component.css @@ -0,0 +1,55 @@ +.hidden-days-demo { + display: flex; + gap: 20px; +} + +.scheduler-container { + flex: 1; + min-width: 0; +} + +.options { + display: flex; + flex-direction: column; + flex-shrink: 0; + width: 220px; + box-sizing: border-box; + padding: 20px; + background-color: rgba(191, 191, 191, 0.15); + gap: 12px; +} + +.caption { + font-weight: 500; + font-size: 18px; +} + +.option { + display: flex; + flex-direction: column; +} + +.validation-message { + display: none; + margin-top: 8px; + padding: 10px 12px; + background: #fdf3f4; + border-left: 3px solid #c50f1f; + border-radius: 4px; + color: #c50f1f; + font-size: 13px; + line-height: 1.4; +} + +::ng-deep .hidden-days-demo.is-invalid .validation-message { + display: block; +} + +::ng-deep .hidden-days-demo.is-invalid .option .dx-checkbox-icon { + border-color: #c50f1f; +} + +::ng-deep .hidden-days-demo.is-invalid .dx-scheduler-work-space { + opacity: 0.4; + pointer-events: none; +} diff --git a/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.component.html b/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.component.html new file mode 100644 index 000000000000..248cda44647b --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.component.html @@ -0,0 +1,32 @@ +
+
+ + +
+ +
+
Visible Week Days
+ @for (day of dayLabels; track day.index) { +
+ + +
+ } +
+ {{ validationMessage }} +
+
+
diff --git a/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.component.ts b/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.component.ts new file mode 100644 index 000000000000..41b1ae46ae97 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.component.ts @@ -0,0 +1,80 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core'; +import { DxSchedulerModule, DxSchedulerTypes } from 'devextreme-angular/ui/scheduler'; +import { DxCheckBoxModule, DxCheckBoxTypes } from 'devextreme-angular/ui/check-box'; +import { ArrayStore } from 'devextreme-angular/common/data'; +import { DataService } from './app.service'; + +if (!/localhost/.test(document.location.host)) { + enableProdMode(); +} + +let modulePrefix = ''; +// @ts-ignore +if (window && window.config?.packageConfigPaths) { + modulePrefix = '/app'; +} + +interface DayLabel { + index: DxSchedulerTypes.DayOfWeek; + label: string; + visible: boolean; +} + +@Component({ + selector: 'demo-app', + templateUrl: `.${modulePrefix}/app.component.html`, + styleUrls: [`.${modulePrefix}/app.component.css`], + providers: [DataService], + imports: [ + DxSchedulerModule, + DxCheckBoxModule, + ], +}) +export class AppComponent { + dataSource: ArrayStore; + + currentDate = new Date(2021, 3, 26); + + validationMessage = 'The hiddenWeekDays option cannot hide all days of the week. At least one day must remain visible.'; + + dayLabels: DayLabel[] = [ + { index: 0, label: 'Sunday', visible: true }, + { index: 1, label: 'Monday', visible: true }, + { index: 2, label: 'Tuesday', visible: true }, + { index: 3, label: 'Wednesday', visible: false }, + { index: 4, label: 'Thursday', visible: true }, + { index: 5, label: 'Friday', visible: false }, + { index: 6, label: 'Saturday', visible: true }, + ]; + + hiddenWeekDays: DxSchedulerTypes.DayOfWeek[] = []; + + isInvalid = false; + + constructor(dataService: DataService) { + this.dataSource = new ArrayStore({ + key: 'id', + data: dataService.getAppointments(), + }); + this.hiddenWeekDays = this.computeHiddenWeekDays(); + } + + onDayToggled(e: DxCheckBoxTypes.ValueChangedEvent, dayIndex: number): void { + this.dayLabels[dayIndex].visible = e.value; + this.isInvalid = this.dayLabels.every((d) => !d.visible); + this.hiddenWeekDays = this.computeHiddenWeekDays(); + } + + private computeHiddenWeekDays(): DxSchedulerTypes.DayOfWeek[] { + return this.dayLabels + .filter((d) => !d.visible) + .map((d) => d.index); + } +} + +bootstrapApplication(AppComponent, { + providers: [ + provideZoneChangeDetection({ eventCoalescing: true, runCoalescing: true }), + ], +}); diff --git a/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.service.ts b/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.service.ts new file mode 100644 index 000000000000..b1f6e319614e --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/Angular/app/app.service.ts @@ -0,0 +1,121 @@ +import { Injectable } from '@angular/core'; + +export class Appointment { + id: number; + + text: string; + + startDate: Date; + + endDate: Date; + + allDay?: boolean; +} + +const appointments: Appointment[] = [ + { + id: 1, + text: 'Website Re-Design Plan', + startDate: new Date('2021-04-26T16:30:00.000Z'), + endDate: new Date('2021-04-26T18:30:00.000Z'), + }, + { + id: 2, + text: 'Book Flights to San Fran for Sales Trip', + startDate: new Date('2021-04-26T19:00:00.000Z'), + endDate: new Date('2021-04-26T20:00:00.000Z'), + allDay: true, + }, + { + id: 3, + text: 'Install New Router in Dev Room', + startDate: new Date('2021-04-26T21:30:00.000Z'), + endDate: new Date('2021-04-26T22:30:00.000Z'), + }, + { + id: 4, + text: 'Approve Personal Computer Upgrade Plan', + startDate: new Date('2021-04-27T17:00:00.000Z'), + endDate: new Date('2021-04-27T18:00:00.000Z'), + }, + { + id: 5, + text: 'Final Budget Review', + startDate: new Date('2021-04-27T19:00:00.000Z'), + endDate: new Date('2021-04-27T20:35:00.000Z'), + }, + { + id: 6, + text: 'New Brochures', + startDate: new Date('2021-04-27T21:30:00.000Z'), + endDate: new Date('2021-04-27T22:45:00.000Z'), + }, + { + id: 7, + text: 'Install New Database', + startDate: new Date('2021-04-28T16:45:00.000Z'), + endDate: new Date('2021-04-28T18:15:00.000Z'), + }, + { + id: 8, + text: 'Approve New Online Marketing Strategy', + startDate: new Date('2021-04-28T19:00:00.000Z'), + endDate: new Date('2021-04-28T21:00:00.000Z'), + }, + { + id: 9, + text: 'Upgrade Personal Computers', + startDate: new Date('2021-04-28T22:15:00.000Z'), + endDate: new Date('2021-04-28T23:30:00.000Z'), + }, + { + id: 10, + text: 'Customer Workshop', + startDate: new Date('2021-04-29T18:00:00.000Z'), + endDate: new Date('2021-04-29T19:00:00.000Z'), + allDay: true, + }, + { + id: 11, + text: 'Prepare 2021 Marketing Plan', + startDate: new Date('2021-04-29T18:00:00.000Z'), + endDate: new Date('2021-04-29T20:30:00.000Z'), + }, + { + id: 12, + text: 'Brochure Design Review', + startDate: new Date('2021-04-29T21:00:00.000Z'), + endDate: new Date('2021-04-29T22:30:00.000Z'), + }, + { + id: 13, + text: 'Create Icons for Website', + startDate: new Date('2021-04-30T17:00:00.000Z'), + endDate: new Date('2021-04-30T18:30:00.000Z'), + }, + { + id: 14, + text: 'Upgrade Server Hardware', + startDate: new Date('2021-04-30T21:30:00.000Z'), + endDate: new Date('2021-04-30T23:00:00.000Z'), + }, + { + id: 15, + text: 'Submit New Website Design', + startDate: new Date('2021-04-30T23:30:00.000Z'), + endDate: new Date('2021-05-01T01:00:00.000Z'), + }, + { + id: 16, + text: 'Launch New Website', + startDate: new Date('2021-04-30T19:20:00.000Z'), + endDate: new Date('2021-04-30T21:00:00.000Z'), + }, +]; + +@Injectable() +export class DataService { + getAppointments(): Appointment[] { + return appointments; + } +} diff --git a/apps/demos/Demos/Scheduler/HiddenDays/Angular/index.html b/apps/demos/Demos/Scheduler/HiddenDays/Angular/index.html new file mode 100644 index 000000000000..1ab1fb54a1df --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/Angular/index.html @@ -0,0 +1,26 @@ + + + + DevExtreme Demo + + + + + + + + + + + + + + + +
+ Loading... +
+ + diff --git a/apps/demos/Demos/Scheduler/HiddenDays/React/App.tsx b/apps/demos/Demos/Scheduler/HiddenDays/React/App.tsx new file mode 100644 index 000000000000..5ecbbeba4e84 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/React/App.tsx @@ -0,0 +1,69 @@ +import React, { useCallback, useMemo, useState } from 'react'; + +import Scheduler, { type SchedulerTypes } from 'devextreme-react/scheduler'; +import CheckBox, { type CheckBoxTypes } from 'devextreme-react/check-box'; +import { ArrayStore } from 'devextreme-react/common/data'; +import { data } from './data.ts'; + +const dataSource = new ArrayStore({ + key: 'id', + data, +}); + +const allDays: SchedulerTypes.DayOfWeek[] = [0, 1, 2, 3, 4, 5, 6]; +const dayLabels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; +const defaultVisible: SchedulerTypes.DayOfWeek[] = [0, 1, 2, 4, 6]; +const views: SchedulerTypes.Properties['views'] = ['week', 'workWeek', 'month', 'timelineWeek', 'agenda']; +const currentDate = new Date(2021, 3, 26); +const VALIDATION_MESSAGE = 'The hiddenWeekDays option cannot hide all days of the week. At least one day must remain visible.'; + +const App = () => { + const [visibleDays, setVisibleDays] = useState(defaultVisible); + + const isInvalid = visibleDays.length === 0; + + const hiddenWeekDays = useMemo( + () => allDays.filter((d) => !visibleDays.includes(d)), + [visibleDays], + ); + + const onDayToggle = useCallback((dayIndex: SchedulerTypes.DayOfWeek, e: CheckBoxTypes.ValueChangedEvent) => { + setVisibleDays((prev) => (e.value + ? [...prev, dayIndex] + : prev.filter((d) => d !== dayIndex))); + }, []); + + return ( +
+
+ +
+
+
Visible Week Days
+ {dayLabels.map((label, idx) => ( +
+ onDayToggle(idx as SchedulerTypes.DayOfWeek, e)} + /> +
+ ))} +
+ {VALIDATION_MESSAGE} +
+
+
+ ); +}; + +export default App; diff --git a/apps/demos/Demos/Scheduler/HiddenDays/React/data.ts b/apps/demos/Demos/Scheduler/HiddenDays/React/data.ts new file mode 100644 index 000000000000..89072595cc2d --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/React/data.ts @@ -0,0 +1,87 @@ +import type { SchedulerTypes } from 'devextreme-react/scheduler'; + +export const data: SchedulerTypes.Appointment[] = [ + { + id: 1, + text: 'Website Re-Design Plan', + startDate: new Date('2021-04-26T16:30:00.000Z'), + endDate: new Date('2021-04-26T18:30:00.000Z'), + }, { + id: 2, + text: 'Book Flights to San Fran for Sales Trip', + startDate: new Date('2021-04-26T19:00:00.000Z'), + endDate: new Date('2021-04-26T20:00:00.000Z'), + allDay: true, + }, { + id: 3, + text: 'Install New Router in Dev Room', + startDate: new Date('2021-04-26T21:30:00.000Z'), + endDate: new Date('2021-04-26T22:30:00.000Z'), + }, { + id: 4, + text: 'Approve Personal Computer Upgrade Plan', + startDate: new Date('2021-04-27T17:00:00.000Z'), + endDate: new Date('2021-04-27T18:00:00.000Z'), + }, { + id: 5, + text: 'Final Budget Review', + startDate: new Date('2021-04-27T19:00:00.000Z'), + endDate: new Date('2021-04-27T20:35:00.000Z'), + }, { + id: 6, + text: 'New Brochures', + startDate: new Date('2021-04-27T21:30:00.000Z'), + endDate: new Date('2021-04-27T22:45:00.000Z'), + }, { + id: 7, + text: 'Install New Database', + startDate: new Date('2021-04-28T16:45:00.000Z'), + endDate: new Date('2021-04-28T18:15:00.000Z'), + }, { + id: 8, + text: 'Approve New Online Marketing Strategy', + startDate: new Date('2021-04-28T19:00:00.000Z'), + endDate: new Date('2021-04-28T21:00:00.000Z'), + }, { + id: 9, + text: 'Upgrade Personal Computers', + startDate: new Date('2021-04-28T22:15:00.000Z'), + endDate: new Date('2021-04-28T23:30:00.000Z'), + }, { + id: 10, + text: 'Customer Workshop', + startDate: new Date('2021-04-29T18:00:00.000Z'), + endDate: new Date('2021-04-29T19:00:00.000Z'), + allDay: true, + }, { + id: 11, + text: 'Prepare 2021 Marketing Plan', + startDate: new Date('2021-04-29T18:00:00.000Z'), + endDate: new Date('2021-04-29T20:30:00.000Z'), + }, { + id: 12, + text: 'Brochure Design Review', + startDate: new Date('2021-04-29T21:00:00.000Z'), + endDate: new Date('2021-04-29T22:30:00.000Z'), + }, { + id: 13, + text: 'Create Icons for Website', + startDate: new Date('2021-04-30T17:00:00.000Z'), + endDate: new Date('2021-04-30T18:30:00.000Z'), + }, { + id: 14, + text: 'Upgrade Server Hardware', + startDate: new Date('2021-04-30T21:30:00.000Z'), + endDate: new Date('2021-04-30T23:00:00.000Z'), + }, { + id: 15, + text: 'Submit New Website Design', + startDate: new Date('2021-04-30T23:30:00.000Z'), + endDate: new Date('2021-05-01T01:00:00.000Z'), + }, { + id: 16, + text: 'Launch New Website', + startDate: new Date('2021-04-30T19:20:00.000Z'), + endDate: new Date('2021-04-30T21:00:00.000Z'), + }, +]; diff --git a/apps/demos/Demos/Scheduler/HiddenDays/React/index.html b/apps/demos/Demos/Scheduler/HiddenDays/React/index.html new file mode 100644 index 000000000000..ee451f8288ff --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/React/index.html @@ -0,0 +1,24 @@ + + + + DevExtreme Demo + + + + + + + + + + + + + +
+
+
+ + diff --git a/apps/demos/Demos/Scheduler/HiddenDays/React/index.tsx b/apps/demos/Demos/Scheduler/HiddenDays/React/index.tsx new file mode 100644 index 000000000000..8acbec4b6179 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/React/index.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; + +import App from './App.tsx'; + +ReactDOM.render( + , + document.getElementById('app'), +); diff --git a/apps/demos/Demos/Scheduler/HiddenDays/React/styles.css b/apps/demos/Demos/Scheduler/HiddenDays/React/styles.css new file mode 100644 index 000000000000..82a48bdf0b98 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/React/styles.css @@ -0,0 +1,55 @@ +.hidden-days-demo { + display: flex; + gap: 20px; +} + +.scheduler-container { + flex: 1; + min-width: 0; +} + +.options { + display: flex; + flex-direction: column; + flex-shrink: 0; + width: 220px; + box-sizing: border-box; + padding: 20px; + background-color: rgba(191, 191, 191, 0.15); + gap: 12px; +} + +.caption { + font-weight: 500; + font-size: 18px; +} + +.option { + display: flex; + flex-direction: column; +} + +.validation-message { + display: none; + margin-top: 8px; + padding: 10px 12px; + background: #fdf3f4; + border-left: 3px solid #c50f1f; + border-radius: 4px; + color: #c50f1f; + font-size: 13px; + line-height: 1.4; +} + +.hidden-days-demo.is-invalid .validation-message { + display: block; +} + +.hidden-days-demo.is-invalid .option .dx-checkbox-icon { + border-color: #c50f1f; +} + +.hidden-days-demo.is-invalid .dx-scheduler-work-space { + opacity: 0.4; + pointer-events: none; +} diff --git a/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/App.js b/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/App.js new file mode 100644 index 000000000000..f6447c013062 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/App.js @@ -0,0 +1,61 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import Scheduler from 'devextreme-react/scheduler'; +import CheckBox from 'devextreme-react/check-box'; +import { ArrayStore } from 'devextreme-react/common/data'; +import { data } from './data.js'; + +const dataSource = new ArrayStore({ + key: 'id', + data, +}); +const allDays = [0, 1, 2, 3, 4, 5, 6]; +const dayLabels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; +const defaultVisible = [0, 1, 2, 4, 6]; +const views = ['week', 'workWeek', 'month', 'timelineWeek', 'agenda']; +const currentDate = new Date(2021, 3, 26); +const VALIDATION_MESSAGE = + 'The hiddenWeekDays option cannot hide all days of the week. At least one day must remain visible.'; +const App = () => { + const [visibleDays, setVisibleDays] = useState(defaultVisible); + const isInvalid = visibleDays.length === 0; + const hiddenWeekDays = useMemo( + () => allDays.filter((d) => !visibleDays.includes(d)), + [visibleDays], + ); + const onDayToggle = useCallback((dayIndex, e) => { + setVisibleDays((prev) => (e.value ? [...prev, dayIndex] : prev.filter((d) => d !== dayIndex))); + }, []); + return ( +
+
+ +
+
+
Visible Week Days
+ {dayLabels.map((label, idx) => ( +
+ onDayToggle(idx, e)} + /> +
+ ))} +
{VALIDATION_MESSAGE}
+
+
+ ); +}; +export default App; diff --git a/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/data.js b/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/data.js new file mode 100644 index 000000000000..55832c8e21a3 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/data.js @@ -0,0 +1,100 @@ +export const data = [ + { + id: 1, + text: 'Website Re-Design Plan', + startDate: new Date('2021-04-26T16:30:00.000Z'), + endDate: new Date('2021-04-26T18:30:00.000Z'), + }, + { + id: 2, + text: 'Book Flights to San Fran for Sales Trip', + startDate: new Date('2021-04-26T19:00:00.000Z'), + endDate: new Date('2021-04-26T20:00:00.000Z'), + allDay: true, + }, + { + id: 3, + text: 'Install New Router in Dev Room', + startDate: new Date('2021-04-26T21:30:00.000Z'), + endDate: new Date('2021-04-26T22:30:00.000Z'), + }, + { + id: 4, + text: 'Approve Personal Computer Upgrade Plan', + startDate: new Date('2021-04-27T17:00:00.000Z'), + endDate: new Date('2021-04-27T18:00:00.000Z'), + }, + { + id: 5, + text: 'Final Budget Review', + startDate: new Date('2021-04-27T19:00:00.000Z'), + endDate: new Date('2021-04-27T20:35:00.000Z'), + }, + { + id: 6, + text: 'New Brochures', + startDate: new Date('2021-04-27T21:30:00.000Z'), + endDate: new Date('2021-04-27T22:45:00.000Z'), + }, + { + id: 7, + text: 'Install New Database', + startDate: new Date('2021-04-28T16:45:00.000Z'), + endDate: new Date('2021-04-28T18:15:00.000Z'), + }, + { + id: 8, + text: 'Approve New Online Marketing Strategy', + startDate: new Date('2021-04-28T19:00:00.000Z'), + endDate: new Date('2021-04-28T21:00:00.000Z'), + }, + { + id: 9, + text: 'Upgrade Personal Computers', + startDate: new Date('2021-04-28T22:15:00.000Z'), + endDate: new Date('2021-04-28T23:30:00.000Z'), + }, + { + id: 10, + text: 'Customer Workshop', + startDate: new Date('2021-04-29T18:00:00.000Z'), + endDate: new Date('2021-04-29T19:00:00.000Z'), + allDay: true, + }, + { + id: 11, + text: 'Prepare 2021 Marketing Plan', + startDate: new Date('2021-04-29T18:00:00.000Z'), + endDate: new Date('2021-04-29T20:30:00.000Z'), + }, + { + id: 12, + text: 'Brochure Design Review', + startDate: new Date('2021-04-29T21:00:00.000Z'), + endDate: new Date('2021-04-29T22:30:00.000Z'), + }, + { + id: 13, + text: 'Create Icons for Website', + startDate: new Date('2021-04-30T17:00:00.000Z'), + endDate: new Date('2021-04-30T18:30:00.000Z'), + }, + { + id: 14, + text: 'Upgrade Server Hardware', + startDate: new Date('2021-04-30T21:30:00.000Z'), + endDate: new Date('2021-04-30T23:00:00.000Z'), + }, + { + id: 15, + text: 'Submit New Website Design', + startDate: new Date('2021-04-30T23:30:00.000Z'), + endDate: new Date('2021-05-01T01:00:00.000Z'), + }, + { + id: 16, + text: 'Launch New Website', + startDate: new Date('2021-04-30T19:20:00.000Z'), + endDate: new Date('2021-04-30T21:00:00.000Z'), + }, +]; diff --git a/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/index.html b/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/index.html new file mode 100644 index 000000000000..db31b0fd60c6 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/index.html @@ -0,0 +1,44 @@ + + + + DevExtreme Demo + + + + + + + + + + + + + +
+
+
+ + diff --git a/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/index.js b/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/index.js new file mode 100644 index 000000000000..b853e0be8242 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/index.js @@ -0,0 +1,5 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App.js'; + +ReactDOM.render(, document.getElementById('app')); diff --git a/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/styles.css b/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/styles.css new file mode 100644 index 000000000000..82a48bdf0b98 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/ReactJs/styles.css @@ -0,0 +1,55 @@ +.hidden-days-demo { + display: flex; + gap: 20px; +} + +.scheduler-container { + flex: 1; + min-width: 0; +} + +.options { + display: flex; + flex-direction: column; + flex-shrink: 0; + width: 220px; + box-sizing: border-box; + padding: 20px; + background-color: rgba(191, 191, 191, 0.15); + gap: 12px; +} + +.caption { + font-weight: 500; + font-size: 18px; +} + +.option { + display: flex; + flex-direction: column; +} + +.validation-message { + display: none; + margin-top: 8px; + padding: 10px 12px; + background: #fdf3f4; + border-left: 3px solid #c50f1f; + border-radius: 4px; + color: #c50f1f; + font-size: 13px; + line-height: 1.4; +} + +.hidden-days-demo.is-invalid .validation-message { + display: block; +} + +.hidden-days-demo.is-invalid .option .dx-checkbox-icon { + border-color: #c50f1f; +} + +.hidden-days-demo.is-invalid .dx-scheduler-work-space { + opacity: 0.4; + pointer-events: none; +} diff --git a/apps/demos/Demos/Scheduler/HiddenDays/Vue/App.vue b/apps/demos/Demos/Scheduler/HiddenDays/Vue/App.vue new file mode 100644 index 000000000000..d336bb3a406f --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/Vue/App.vue @@ -0,0 +1,66 @@ + + diff --git a/apps/demos/Demos/Scheduler/HiddenDays/Vue/data.ts b/apps/demos/Demos/Scheduler/HiddenDays/Vue/data.ts new file mode 100644 index 000000000000..cc369e2b2d66 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/Vue/data.ts @@ -0,0 +1,85 @@ +export const data = [ + { + id: 1, + text: 'Website Re-Design Plan', + startDate: new Date('2021-04-26T16:30:00.000Z'), + endDate: new Date('2021-04-26T18:30:00.000Z'), + }, { + id: 2, + text: 'Book Flights to San Fran for Sales Trip', + startDate: new Date('2021-04-26T19:00:00.000Z'), + endDate: new Date('2021-04-26T20:00:00.000Z'), + allDay: true, + }, { + id: 3, + text: 'Install New Router in Dev Room', + startDate: new Date('2021-04-26T21:30:00.000Z'), + endDate: new Date('2021-04-26T22:30:00.000Z'), + }, { + id: 4, + text: 'Approve Personal Computer Upgrade Plan', + startDate: new Date('2021-04-27T17:00:00.000Z'), + endDate: new Date('2021-04-27T18:00:00.000Z'), + }, { + id: 5, + text: 'Final Budget Review', + startDate: new Date('2021-04-27T19:00:00.000Z'), + endDate: new Date('2021-04-27T20:35:00.000Z'), + }, { + id: 6, + text: 'New Brochures', + startDate: new Date('2021-04-27T21:30:00.000Z'), + endDate: new Date('2021-04-27T22:45:00.000Z'), + }, { + id: 7, + text: 'Install New Database', + startDate: new Date('2021-04-28T16:45:00.000Z'), + endDate: new Date('2021-04-28T18:15:00.000Z'), + }, { + id: 8, + text: 'Approve New Online Marketing Strategy', + startDate: new Date('2021-04-28T19:00:00.000Z'), + endDate: new Date('2021-04-28T21:00:00.000Z'), + }, { + id: 9, + text: 'Upgrade Personal Computers', + startDate: new Date('2021-04-28T22:15:00.000Z'), + endDate: new Date('2021-04-28T23:30:00.000Z'), + }, { + id: 10, + text: 'Customer Workshop', + startDate: new Date('2021-04-29T18:00:00.000Z'), + endDate: new Date('2021-04-29T19:00:00.000Z'), + allDay: true, + }, { + id: 11, + text: 'Prepare 2021 Marketing Plan', + startDate: new Date('2021-04-29T18:00:00.000Z'), + endDate: new Date('2021-04-29T20:30:00.000Z'), + }, { + id: 12, + text: 'Brochure Design Review', + startDate: new Date('2021-04-29T21:00:00.000Z'), + endDate: new Date('2021-04-29T22:30:00.000Z'), + }, { + id: 13, + text: 'Create Icons for Website', + startDate: new Date('2021-04-30T17:00:00.000Z'), + endDate: new Date('2021-04-30T18:30:00.000Z'), + }, { + id: 14, + text: 'Upgrade Server Hardware', + startDate: new Date('2021-04-30T21:30:00.000Z'), + endDate: new Date('2021-04-30T23:00:00.000Z'), + }, { + id: 15, + text: 'Submit New Website Design', + startDate: new Date('2021-04-30T23:30:00.000Z'), + endDate: new Date('2021-05-01T01:00:00.000Z'), + }, { + id: 16, + text: 'Launch New Website', + startDate: new Date('2021-04-30T19:20:00.000Z'), + endDate: new Date('2021-04-30T21:00:00.000Z'), + }, +]; diff --git a/apps/demos/Demos/Scheduler/HiddenDays/Vue/index.html b/apps/demos/Demos/Scheduler/HiddenDays/Vue/index.html new file mode 100644 index 000000000000..7b884ccdeda8 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/Vue/index.html @@ -0,0 +1,30 @@ + + + + DevExtreme Demo + + + + + + + + + + + + + + + +
+
+
+ + diff --git a/apps/demos/Demos/Scheduler/HiddenDays/Vue/index.ts b/apps/demos/Demos/Scheduler/HiddenDays/Vue/index.ts new file mode 100644 index 000000000000..684d04215d72 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/Vue/index.ts @@ -0,0 +1,4 @@ +import { createApp } from 'vue'; +import App from './App.vue'; + +createApp(App).mount('#app'); diff --git a/apps/demos/Demos/Scheduler/HiddenDays/Vue/styles.css b/apps/demos/Demos/Scheduler/HiddenDays/Vue/styles.css new file mode 100644 index 000000000000..82a48bdf0b98 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/Vue/styles.css @@ -0,0 +1,55 @@ +.hidden-days-demo { + display: flex; + gap: 20px; +} + +.scheduler-container { + flex: 1; + min-width: 0; +} + +.options { + display: flex; + flex-direction: column; + flex-shrink: 0; + width: 220px; + box-sizing: border-box; + padding: 20px; + background-color: rgba(191, 191, 191, 0.15); + gap: 12px; +} + +.caption { + font-weight: 500; + font-size: 18px; +} + +.option { + display: flex; + flex-direction: column; +} + +.validation-message { + display: none; + margin-top: 8px; + padding: 10px 12px; + background: #fdf3f4; + border-left: 3px solid #c50f1f; + border-radius: 4px; + color: #c50f1f; + font-size: 13px; + line-height: 1.4; +} + +.hidden-days-demo.is-invalid .validation-message { + display: block; +} + +.hidden-days-demo.is-invalid .option .dx-checkbox-icon { + border-color: #c50f1f; +} + +.hidden-days-demo.is-invalid .dx-scheduler-work-space { + opacity: 0.4; + pointer-events: none; +} diff --git a/apps/demos/Demos/Scheduler/HiddenDays/jQuery/data.js b/apps/demos/Demos/Scheduler/HiddenDays/jQuery/data.js new file mode 100644 index 000000000000..cabf71cfd630 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/jQuery/data.js @@ -0,0 +1,85 @@ +const data = [ + { + id: 1, + text: 'Website Re-Design Plan', + startDate: new Date('2021-04-26T16:30:00.000Z'), + endDate: new Date('2021-04-26T18:30:00.000Z'), + }, { + id: 2, + text: 'Book Flights to San Fran for Sales Trip', + startDate: new Date('2021-04-26T19:00:00.000Z'), + endDate: new Date('2021-04-26T20:00:00.000Z'), + allDay: true, + }, { + id: 3, + text: 'Install New Router in Dev Room', + startDate: new Date('2021-04-26T21:30:00.000Z'), + endDate: new Date('2021-04-26T22:30:00.000Z'), + }, { + id: 4, + text: 'Approve Personal Computer Upgrade Plan', + startDate: new Date('2021-04-27T17:00:00.000Z'), + endDate: new Date('2021-04-27T18:00:00.000Z'), + }, { + id: 5, + text: 'Final Budget Review', + startDate: new Date('2021-04-27T19:00:00.000Z'), + endDate: new Date('2021-04-27T20:35:00.000Z'), + }, { + id: 6, + text: 'New Brochures', + startDate: new Date('2021-04-27T21:30:00.000Z'), + endDate: new Date('2021-04-27T22:45:00.000Z'), + }, { + id: 7, + text: 'Install New Database', + startDate: new Date('2021-04-28T16:45:00.000Z'), + endDate: new Date('2021-04-28T18:15:00.000Z'), + }, { + id: 8, + text: 'Approve New Online Marketing Strategy', + startDate: new Date('2021-04-28T19:00:00.000Z'), + endDate: new Date('2021-04-28T21:00:00.000Z'), + }, { + id: 9, + text: 'Upgrade Personal Computers', + startDate: new Date('2021-04-28T22:15:00.000Z'), + endDate: new Date('2021-04-28T23:30:00.000Z'), + }, { + id: 10, + text: 'Customer Workshop', + startDate: new Date('2021-04-29T18:00:00.000Z'), + endDate: new Date('2021-04-29T19:00:00.000Z'), + allDay: true, + }, { + id: 11, + text: 'Prepare 2021 Marketing Plan', + startDate: new Date('2021-04-29T18:00:00.000Z'), + endDate: new Date('2021-04-29T20:30:00.000Z'), + }, { + id: 12, + text: 'Brochure Design Review', + startDate: new Date('2021-04-29T21:00:00.000Z'), + endDate: new Date('2021-04-29T22:30:00.000Z'), + }, { + id: 13, + text: 'Create Icons for Website', + startDate: new Date('2021-04-30T17:00:00.000Z'), + endDate: new Date('2021-04-30T18:30:00.000Z'), + }, { + id: 14, + text: 'Upgrade Server Hardware', + startDate: new Date('2021-04-30T21:30:00.000Z'), + endDate: new Date('2021-04-30T23:00:00.000Z'), + }, { + id: 15, + text: 'Submit New Website Design', + startDate: new Date('2021-04-30T23:30:00.000Z'), + endDate: new Date('2021-05-01T01:00:00.000Z'), + }, { + id: 16, + text: 'Launch New Website', + startDate: new Date('2021-04-30T19:20:00.000Z'), + endDate: new Date('2021-04-30T21:00:00.000Z'), + }, +]; diff --git a/apps/demos/Demos/Scheduler/HiddenDays/jQuery/index.html b/apps/demos/Demos/Scheduler/HiddenDays/jQuery/index.html new file mode 100644 index 000000000000..6c8d0efe8ebf --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/jQuery/index.html @@ -0,0 +1,28 @@ + + + + DevExtreme Demo + + + + + + + + + + + + +
+
+
+
+
+
+
Visible Week Days
+
+
+
+ + diff --git a/apps/demos/Demos/Scheduler/HiddenDays/jQuery/index.js b/apps/demos/Demos/Scheduler/HiddenDays/jQuery/index.js new file mode 100644 index 000000000000..64f1be225395 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/jQuery/index.js @@ -0,0 +1,48 @@ +$(() => { + const dayLabels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + let visibleDays = [0, 1, 2, 4, 6]; + const VALIDATION_MESSAGE = 'The hiddenWeekDays option cannot hide all days of the week. At least one day must remain visible.'; + + function computeHiddenWeekDays() { + return [0, 1, 2, 3, 4, 5, 6].filter((d) => !visibleDays.includes(d)); + } + + function refreshValidity() { + $('.hidden-days-demo').toggleClass('is-invalid', visibleDays.length === 0); + } + + const scheduler = $('#scheduler').dxScheduler({ + timeZone: 'America/Los_Angeles', + dataSource: new DevExpress.data.ArrayStore({ + key: 'id', + data, + }), + views: ['week', 'workWeek', 'month', 'timelineWeek', 'agenda'], + hiddenWeekDays: computeHiddenWeekDays(), + currentView: 'week', + currentDate: new Date(2021, 3, 26), + startDayHour: 9, + height: 730, + }).dxScheduler('instance'); + + const $optionsPanel = $('.options'); + dayLabels.forEach((label, idx) => { + const $cb = $('
').appendTo($optionsPanel); + $cb.dxCheckBox({ + text: label, + value: visibleDays.includes(idx), + onValueChanged(e) { + if (e.value) { + visibleDays = [...visibleDays, idx]; + } else { + visibleDays = visibleDays.filter((d) => d !== idx); + } + refreshValidity(); + scheduler.option('hiddenWeekDays', computeHiddenWeekDays()); + }, + }); + }); + + $('
').text(VALIDATION_MESSAGE).appendTo($optionsPanel); + refreshValidity(); +}); diff --git a/apps/demos/Demos/Scheduler/HiddenDays/jQuery/styles.css b/apps/demos/Demos/Scheduler/HiddenDays/jQuery/styles.css new file mode 100644 index 000000000000..82a48bdf0b98 --- /dev/null +++ b/apps/demos/Demos/Scheduler/HiddenDays/jQuery/styles.css @@ -0,0 +1,55 @@ +.hidden-days-demo { + display: flex; + gap: 20px; +} + +.scheduler-container { + flex: 1; + min-width: 0; +} + +.options { + display: flex; + flex-direction: column; + flex-shrink: 0; + width: 220px; + box-sizing: border-box; + padding: 20px; + background-color: rgba(191, 191, 191, 0.15); + gap: 12px; +} + +.caption { + font-weight: 500; + font-size: 18px; +} + +.option { + display: flex; + flex-direction: column; +} + +.validation-message { + display: none; + margin-top: 8px; + padding: 10px 12px; + background: #fdf3f4; + border-left: 3px solid #c50f1f; + border-radius: 4px; + color: #c50f1f; + font-size: 13px; + line-height: 1.4; +} + +.hidden-days-demo.is-invalid .validation-message { + display: block; +} + +.hidden-days-demo.is-invalid .option .dx-checkbox-icon { + border-color: #c50f1f; +} + +.hidden-days-demo.is-invalid .dx-scheduler-work-space { + opacity: 0.4; + pointer-events: none; +} diff --git a/apps/demos/menuMeta.json b/apps/demos/menuMeta.json index 1f6ce3a3bc46..c4677e60cb4f 100644 --- a/apps/demos/menuMeta.json +++ b/apps/demos/menuMeta.json @@ -3704,6 +3704,13 @@ "/Models/SampleData/AppointmentsWorkHours.cs" ], "DemoType": "Web" + }, + { + "Title": "Hidden Week Days", + "Name": "HiddenDays", + "Widget": "Scheduler", + "Equivalents": "", + "DemoType": "Web" } ] }, diff --git a/apps/demos/testing/etalons/Scheduler-HiddenDays (fluent.blue.light).png b/apps/demos/testing/etalons/Scheduler-HiddenDays (fluent.blue.light).png new file mode 100644 index 000000000000..b4e879eeeae5 Binary files /dev/null and b/apps/demos/testing/etalons/Scheduler-HiddenDays (fluent.blue.light).png differ diff --git a/apps/demos/testing/etalons/Scheduler-HiddenDays (material.blue.light).png b/apps/demos/testing/etalons/Scheduler-HiddenDays (material.blue.light).png new file mode 100644 index 000000000000..b042cae98854 Binary files /dev/null and b/apps/demos/testing/etalons/Scheduler-HiddenDays (material.blue.light).png differ