diff --git a/docs/api/config/js_eventcalendar_config_config.md b/docs/api/config/js_eventcalendar_config_config.md index c94eeb9..64e42f9 100644 --- a/docs/api/config/js_eventcalendar_config_config.md +++ b/docs/api/config/js_eventcalendar_config_config.md @@ -25,6 +25,7 @@ config?: { eventsOverlay?: boolean, autoSave?: boolean, readonly?: boolean, + highlightReadonly?: boolean, dimPastEvents?: boolean, dateClick?: boolean | string, // (true/false or "day" | "week" | "month" | "year" | "agenda" | "timeline") dateTitle?: (date, [start, end]) => string, @@ -82,7 +83,7 @@ config?: { step?: array, // [number, "day" | "week" | "month" | "year" | "hour" | "minute"] header?: [ { - unit: string, // "year" | "month" | "quarter" | "month" | "week" | "day" | "hour" | "minute" + unit: string, // "year" | "month" | "quarter" | "week" | "day" | "hour" | "minute" format: string, // date-fns format step: number }, @@ -95,8 +96,8 @@ config?: { // ... other custom parameters }, // other sections config - ], - }, + ] + } }, // other views config ] @@ -116,6 +117,7 @@ In the **config** object you can specify the following parameters: - `eventsOverlay` - (optional) enables/disables an ability to overlay events - `autoSave` - (optional) enables/disables an ability to auto save event data (via the editor) - `readonly` - (optional) enables/disables an ability to perform operations on events +- `highlightReadonly` - (optional) enables/disables highlighting the readonly events - `dimPastEvents` - (optional) enables/disables an ability to dim past events - `dateClick` - (optional) defines a behavior of clicking on the date in a grid cell in the following way: - ***true/false*** - enables/disables an ability to click on the date in a grid cell to go to the corresponding day @@ -167,7 +169,7 @@ calendarValidation: calendar => { - `views` - (optional) an array of configuration objects of the specific (custom) view modes. For each view mode you can specify the following settings: - `id` - (required) an ID of the view mode - `label` - (required) a label of the view mode - - `layout` - (required) a predefined layout of the view mode. Here you can specify the following values: *"year" | "month" | "quarter" | "month" | "week" | "day" | "hour" | "minute"* + - `layout` - (required) a predefined layout of the view mode. Here you can specify the following values: *"year" | "month" | "week" | "day" | "agenda" | "timeline"* - `config` - (optional) an object of the custom view mode settings :::note @@ -217,11 +219,18 @@ const getMonday = (date) => { // ..., views: [ - // ..., - getBounds: (date) => { - const weekStart = getMonday(date); - return [weekStart, new Date(weekStart.getFullYear(), weekStart.getMonth(), weekStart.getDate() + 7)]; - }, + { + id: 'timeline', + label: 'Timeline', + layout: 'timeline', + config: { + getBounds: (date) => { + const weekStart = getMonday(date); + return [weekStart, new Date(weekStart.getFullYear(), weekStart.getMonth(), weekStart.getDate() + 7)]; + }, + //... + } + } ] ~~~ @@ -251,7 +260,7 @@ step: [8, "hour"], // "day" | "week" | "month" | "year" | "hour" | "minute" ~~~ - `header?: array` - defines headers for the Timeline grid. In this array you can specify objects with the following parameters: - - `unit: string` - a timeline unit. Here you can specify one of the following values: *"year" | "month" | "quarter" | "month" | "week" | "day" | "hour" | "minute"* + - `unit: string` - a timeline unit. Here you can specify one of the following values: *"year" | "month" | "quarter" | "week" | "day" | "hour" | "minute"* - `format: string` - a time format (use a [date-fns](https://date-fns.org/) format) - `step: number` - a time duration @@ -291,12 +300,11 @@ sections: [ ~~~jsx {} const defaultWeekConfig = { eventHorizontalSpace: 3, - columnPadding: "8px", - + columnPadding: "8px" }; const defaultMonthConfig = { - maxEventsPerCell: 4, + maxEventsPerCell: 4 }; const defaultTimelineConfig = { @@ -322,7 +330,7 @@ const defaultTimelineConfig = { { id: "8", label: "Section 8" }, { id: "9", label: "Section 9" }, ], - unassignedCol: false, + unassignedCol: false }; const defaultConfig = { @@ -337,6 +345,7 @@ const defaultConfig = { eventsOverlay: false, autoSave: true, readonly: false, + highlightReadonly: true, tableHeaderHeight: 32, eventHeight: 24, @@ -369,7 +378,7 @@ const defaultConfig = { }, { id: "year", label: "Year", layout: "year" }, { id: "agenda", label: "Agenda", layout: "agenda" }, - ], + ] }; ~~~ @@ -380,13 +389,14 @@ To set the **config** property dynamically, you can use the ### Example -~~~jsx {3-50} +~~~jsx {3-51} // create Event Calendar new eventCalendar.EventCalendar("#root", { config: { autoSave: false, dragResize: false, readonly: true, + highlightReadonly: false, dragMove: false, viewControl: "toggle", dimPastEvents: true, @@ -429,7 +439,7 @@ new eventCalendar.EventCalendar("#root", { }, }, // other custom views config - ], + ] }, // other configuration parameters }); @@ -442,3 +452,4 @@ new eventCalendar.EventCalendar("#root", { - The ***dateTitle***, ***eventVerticalSpace*** and ***eventHorizontalSpace*** properties were added in v2.1 - The ***eventMargin*** property was deprecated in v2.1 - The ***calendarValidation*** and ***defaultEditorValues*** properties were added in v2.2 +- The ***highlightReadonly*** property was added in v2.3 diff --git a/docs/api/config/js_eventcalendar_templates_config.md b/docs/api/config/js_eventcalendar_templates_config.md index 1028e59..2ae26b3 100644 --- a/docs/api/config/js_eventcalendar_templates_config.md +++ b/docs/api/config/js_eventcalendar_templates_config.md @@ -63,9 +63,10 @@ To set the templates dynamically, you can use the ### Example -~~~jsx {5-14,16-22,24-30,32-44,46-55,57-63,65-73,75-88,90-97} +~~~jsx {6-15,17-23,25-31,33-45,47-56,58-64,66-74,76-89,91-97} +const { dateFns, EventCalendar } = eventCalendar; const { format } = dateFns; // date-fns library (https://date-fns.org/) -new eventCalendar.EventCalendar("#root", { // create Event Calendar +new EventCalendar("#root", { // create Event Calendar templates: { // the event template of the "Week" and "Day" modes weekEvent: ({ event, calendar }) => { diff --git a/docs/api/events/js_eventcalendar_editevent_event.md b/docs/api/events/js_eventcalendar_editevent_event.md index 91170dd..bca2b40 100644 --- a/docs/api/events/js_eventcalendar_editevent_event.md +++ b/docs/api/events/js_eventcalendar_editevent_event.md @@ -84,3 +84,5 @@ calendar.api.on("edit-event", (obj) => { console.log(obj); }); ~~~ + +**Related sample:** [Event Calendar. Configuring editor fields at runtime](https://snippet.dhtmlx.com/22vzkltn?tag=event_calendar) diff --git a/docs/guides/configuration.md b/docs/guides/configuration.md index 57620de..e26b170 100644 --- a/docs/guides/configuration.md +++ b/docs/guides/configuration.md @@ -1,10 +1,10 @@ --- -sidebar_label: Configuration -title: Configuration +sidebar_label: Common Configuration +title: Common Configuration description: You can learn about the configuration in the documentation of the DHTMLX JavaScript Event Calendar library. Browse developer guides and API reference, try out code examples and live demos, and download a free 30-day evaluation version of DHTMLX Event Calendar. --- -# Configuration +# Common Configuration You can configure the *Event Calendar* appearance and functionality via corresponding API. The available parameters will allow you to: diff --git a/docs/guides/views.md b/docs/guides/views.md new file mode 100644 index 0000000..370f6cc --- /dev/null +++ b/docs/guides/views.md @@ -0,0 +1,543 @@ +--- +sidebar_label: View Configuration +title: View Configuration +description: You can learn about the available Views in the documentation of the DHTMLX JavaScript Event Calendar library. Browse developer guides and API reference, try out code examples and live demos, and download a free 30-day evaluation version of DHTMLX Event Calendar. +--- + +# View Configuration + +The DHTMLX Event Calendar provides six built-in views: **day**, **week**, **month**, **year**, **agenda**, and **timeline**. To configure these views, use the [`config.views`](api/config/js_eventcalendar_config_config.md) property. You can flexible navigate between these views dynamically. + +Each view requires three essential properties: + +- **id** - the view id used for programmatic access +- **label** - the label displayed in the change view control +- **layout** - the predefined layout of the view mode. Here you can specify the following values: *"year" | "month" | "week" | "day" | "agenda" | "timeline"* + +~~~jsx +const calendar = new eventCalendar.EventCalendar("#root", { + config: { + views: [ + { + id: "week", + label: "Week", + layout: "week" + }, + { + id: "day", + label: "Day", + layout: "day" + }, + { + id: "month", + label: "Month", + layout: "month" + }, + { + id: "year", + label: "Year", + layout: "year" + }, + { + id: "agenda", + label: "Agenda", + layout: "agenda" + } + ] + }, + events: [/* event data */], + date: new Date() +}); +~~~ + +By default, the available view controls are displayed in the top-right part of the user interface. View controls appear in the order they are defined in the `views` configuration array. You can use the [`config.viewControl`](api/config/js_eventcalendar_config_config.md) property to change the appearance of a view control. + +Optionally, each view can accept it's own `config` object with extra settings, that allow you to configure a view: + +~~~jsx {8-10} +const calendar = new eventCalendar.EventCalendar("#root", { + config: { + views: [ + { + id: "day", + label: "Day", + layout: "day", + config: [ + timeRange: [8, 17] + ] + } + ] + }, + events: [], + date: new Date() +}); +~~~ + +Settings that should be applied to multiple views can be specified at the global `config`: + +~~~jsx {2-16} +const calendar = new eventCalendar.EventCalendar("#root", { + config: { + timeRange: [8, 17], + views: [ + { + id: "day", + label: "Day", + layout: "day" + }, + { + id: "week", + label: "Week", + layout: "week" + } + ] + }, + events: [/* event data */], + date: new Date() +}); +~~~ + +And vice-versa, view-level settings can override the global `config`: + +~~~jsx {14-17} +const calendar = new eventCalendar.EventCalendar("#root", { + config: { + timeRange: [8, 17], + views: [ + { + id: "day", + label: "Day", + layout: "day" + }, + { + id: "week", + label: "Week", + layout: "week", + config: { + readonly: true, + timeRange: [0,24] + } + } + ] + }, + events: [], + date: new Date() +}); +~~~ + +For more details about the `config` object, please refer to the [Configuration Guide](guides/configuration.md/#configuring-view-modes). + +## Built-in Views + +Below is the detailed list of default views, including their configuration options. + +### Day + +The **Day** view shows events for a single day. + +#### Short configuration + +~~~jsx +config: { + views: [ + { id: "day", label: "Day", layout: "day" } + ] +} +~~~ + +#### Extended configuration + +~~~jsx +config: { + views: [ + { + id: "day", + label: "Day", + layout: "day", + config: { + dateTitle?: (currentDate: Date, bounds: [Date, Date]) => string; + getBounds?: (date: Date, config: Config) => [Date, Date]; + getNext?: (date: Date, config: Config) => Date; + getPrev?: (date: Date, config: Config) => Date; + + cellCss?: (date: Date) => string; + template?: (event: Event) => string; + + eventHeight?: number; + timeRange?: [number, number]; + timeStep?: number; + eventsOverlay?: false; + eventVerticalSpace?: number; + eventHorizontalSpace?: string; + columnPadding?: string; + weekStartsOn?: number; + } + } + ] +} +~~~ + +You can find more detailed description of the configuration object [here](api/config/js_eventcalendar_config_config.md). + +### Week + +The **Week** view displays events for the entire week. + +#### Short configuration + +~~~jsx +config: { + views: [ + { id: "week", label: "Week", layout: "week" } + ] +} +~~~ + +#### Extended configuration + +~~~jsx +config: { + views: [ + { + id: "week", + label: "Week", + layout: "week", + config: { + dateTitle?: (currentDate: Date, bounds: [Date, Date]) => string; + getBounds?: (date: Date, config: Config) => [Date, Date]; + getNext?: (date: Date, config: Config) => Date; + getPrev?: (date: Date, config: Config) => Date; + + cellCss?: (date: Date) => string; + template?: (event: Event) => string; + + eventHeight?: number; + timeRange?: [number, number]; + timeStep?: number; + eventsOverlay?: false; + eventVerticalSpace?: number; + eventHorizontalSpace?: string; + columnPadding?: string; + weekStartsOn?: number; + } + } + ] +} +~~~ + +You can find more detailed description of the configuration object [here](api/config/js_eventcalendar_config_config.md). + +### Month + +The **Month** view displays events for the entire month. + +#### Short configuration + +~~~jsx +config: { + views: [ + { id: "month", label: "Month", layout: "month" } + ] +} +~~~ + +#### Extended configuration + +~~~jsx +config: { + views: [ + { + id: "month", + label: "Month", + layout: "month", + config: { + dateTitle?: (currentDate: Date, bounds: [Date, Date]) => string; + getBounds?: (date: Date, config: Config) => [Date, Date]; + getNext?: (date: Date, config: Config) => Date; + getPrev?: (date: Date, config: Config) => Date; + + weekStartsOn?: number; + maxEventsPerCell?: number; + eventVerticalSpace?: number; + } + } + ] +} +~~~ + +You can find more detailed description of the configuration object [here](api/config/js_eventcalendar_config_config.md). + +### Year + +The **Year** view displays events for the entire year. + +#### Short configuration + +~~~jsx +config: { + views: [ + { id: "year", label: "Year", layout: "year" } + ] +} +~~~ + +#### Extended configuration + +~~~jsx +config: { + views: [ + { + id: "year", + label: "Year", + layout: "year", + config: { + dateTitle?: (currentDate: Date, bounds: [Date, Date]) => string; + getBounds?: (date: Date, config: Config) => [Date, Date]; + getNext?: (date: Date, config: Config) => Date; + getPrev?: (date: Date, config: Config) => Date; + } + } + ] +} +~~~ + +You can find more detailed description of the configuration object [here](api/config/js_eventcalendar_config_config.md). + +### Agenda + +The **Agenda** view lists upcoming events starting from the current date. + +#### Short configuration + +~~~jsx +config: { + views: [ + { id: "agenda", label: "Agenda", layout: "agenda" } + ] +} +~~~ + +#### Extended configuration + +~~~jsx +config: { + views: [ + { + id: "agenda", + label: "Agenda", + layout: "agenda", + config: { + dateTitle?: (currentDate: Date, bounds: [Date, Date]) => string; + getBounds?: (date: Date, config: Config) => [Date, Date]; + getNext?: (date: Date, config: Config) => Date; + getPrev?: (date: Date, config: Config) => Date; + } + } + ] +} +~~~ + +You can find more detailed description of the configuration object [here](api/config/js_eventcalendar_config_config.md). + +### Timeline + +The **Timeline** view is ideal for visualizing events across multiple resources or time units. + +#### Short configuration + +~~~jsx +config: { + views: [ + { id: "timeline", label: "Timeline", layout: "timeline" } + ] +} +~~~ + +#### Extended configuration + +~~~jsx +config: { + views: [ + { + id: "timeline", + label: "Timeline", + layout: "timeline", + config: { + dateTitle?: (currentDate: Date, bounds: [Date, Date]) => string; + getBounds?: (date: Date, config: Config) => [Date, Date]; + getNext?: (date: Date, config: Config) => Date; + getPrev?: (date: Date, config: Config) => Date; + + colsCount?: number; + colsWidth?: number; + minEventWidth?: number; + eventVerticalSpace?: number; + minSectionHeight?: number; + sectionWidth?: number; + step?: [number, "day" | "week" | "month" | "year" | "hour" | "minute"]; + header?: ITimelineHeader[]; + sections?: ISection[]; + key?: string; + unassignedCol?: boolean; + } + } + ] +} +~~~ + +Where `ITimelineHeader` and `ISection` are defined as following: + +~~~jsx +export interface ITimelineHeader { + unit: string; + format: string; + step: number; +} + +export interface ISection { + id: TID; + label?: string; + [key: string]: any; +} +~~~ + +You can find more detailed description of the configuration object [here](api/config/js_eventcalendar_config_config.md). + +### Custom Views + +Custom views can be created by extending one of the built-in views and overriding its configuration. + +A fundamental customization available for all views. This is achieved by defining the `getBounds`, `getNext`, and `getPrev` properties within the views `config`: + +- `getBounds?: (date: Date, config: Config) => [Date, Date]` - this function takes a date and returns an array with two dates that define the time range to be displayed in the view.. +- `getNext?: (date: Date, config: Config) => Date` - this function is triggered when the user clicks the "Next" button in the calendar header to move to the next interval. It takes the current date of the Event Calendar as an argument and must return the `start date` of the next interval. +- `getPrev?: (date: Date, config: Config) => Date` - this function is triggered when the user clicks the "Previous" button in the calendar header to move to the previous interval. It takes the current date of the Event Calendar as an argument and must return the `start date` of the previous interval. + +The result of the `getNext` and `getPrev` functions is passed to the `getBounds` method to calculate the new interval. + +In all cases, the `config` of the view is passed as the second argument to these functions, allowing for more flexible and context-aware customizations. + +For example, you can create a custom 5-day view by taking the `week` base view and redefining the `getBounds` method. This method adjusts the displayed range to only show **Monday** to **Friday**. + +~~~jsx +const { dateFns, EventCalendar } = eventCalendar; +const calendar = new EventCalendar("#root", { + config: { + views: [ + { + id: "custom-week", + label: "Custom Week", + layout: "week", + config: { + getBounds: (date) => { + const start = dateFns.startOfWeek(date, { weekStartsOn: 1 }); + return [start, dateFns.addDays(start, 4)]; + } + } + } + ] + }, + mode: "custom-week", + date: new Date("2025-02-12T00:00:00") +}); +~~~ + +**Related sample:** [Event Calendar. 5-Day Workweek View](https://snippet.dhtmlx.com/af32gon8?tag=event_calendar) + +Note that we didn't redefine the `getNext()` and `getPrev()` methods. This is because the default behavior of the base week view works seamlessly, moving forward or backward by one week. If you need to implement custom navigation behavior, you can override these methods. + +Consider another example, Two-Week View with the appropriate navigation step. In this case you need to override the navigation methods (`getNext()` and `getPrev()`) in addition to `getBounds()`. + +~~~jsx +const { dateFns, EventCalendar } = eventCalendar; +const calendar = new EventCalendar("#root", { + config: { + views: [ + { + id: "two-weeks", + label: "Two Weeks", + layout: "week", + config: { + getBounds: (date) => { + const start = dateFns.startOfWeek(date); + return [start, dateFns.addDays(start, 13)]; + }, + getNext: (date) => dateFns.addDays(date, 14), + getPrev: (date) => dateFns.addDays(date, -14) + } + } + ] + }, + mode: "two-weeks", + date: new Date("2025-02-12T00:00:00") +}); +~~~ + +**Related sample:** [Event Calendar. 2-Week View](https://snippet.dhtmlx.com/jst2oh35?tag=event_calendar) + +#### Customizing the Agenda view + +By default, the **Agenda** view displays upcoming events starting from the active date. You can redefine this behavior to display events for an entire month, with navigation moving one month at a time. + +~~~jsx +const { dateFns, EventCalendar } = eventCalendar; +const calendar = new EventCalendar("#root", { + config: { + views: [ + { + id: "agenda-month", + label: "Monthly Agenda", + layout: "agenda", + config: { + dateTitle: (date) => dateFns.format(date, "MMMM yyyy"), + getBounds: (date) => { + const start = dateFns.startOfMonth(date); + return [start, dateFns.endOfMonth(start)]; + }, + getNext: (date) => dateFns.addMonths(date, 1), + getPrev: (date) => dateFns.addMonths(date, -1) + } + } + ] + }, + mode: "agenda", + date: new Date("2025-02-12T00:00:00") +}); +~~~ + +**Related sample:** [Event Calendar. Customized Agenda View](https://snippet.dhtmlx.com/wo24gdez?tag=event_calendar) + +#### Customizing the Timeline view + +The **Timeline** view can be customized to show data at finer time intervals. For instance, you can create a timeline that breaks the day into hours and groups events by sections. + +~~~jsx +const calendar = new EventCalendar("#root", { + config: { + views: [ + { + id: "hour_timeline", + label: "Hour Timeline", + layout: "timeline", + config: { + unassignedCol: true, + key: "sectionId", + sections: [ + { id: "1", label: "Section 1" }, + { id: "2", label: "Section 2" } + ], + step: [1, "hour"], // Hourly steps + header: [ + { unit: "day", step: 1, format: "d MMM" }, + { unit: "hour", step: 1, format: "H" } + ] + } + } + ] + }, + mode: "hour_timeline", + date: new Date("2025-02-12T00:00:00") +}); +~~~ + +**Related sample:** [Event Calendar. Customized Timeline View](https://snippet.dhtmlx.com/85jez8mn?tag=event_calendar) diff --git a/docs/howtos.md b/docs/howtos.md index b8ad985..8ee3888 100644 --- a/docs/howtos.md +++ b/docs/howtos.md @@ -148,6 +148,103 @@ Explore the [**Format**](https://date-fns.org/v3.3.1/docs/format) topic for more To get more information on how to configure the time and date format in the Event Calendar, refer to the [**Time and Date format**](/guides/localization/#time-and-date-format) section. +### Configuring editor fields at runtime + +You have an ability to rebuild or modify editor form if a user fills input fields. For this purpose, you need to handle the ["edit-event"](/api/events/js_eventcalendar_editevent_event/) event as shown in the following code snippet: + +~~~jsx {} +// The user dataset for Type 1 +const users_dataset_1 = [ + { id: '1', label: 'Steve Smith', avatar: 'https://snippet.dhtmlx.com/codebase/data/kanban/01/img/user-1.jpg' }, + { id: '2', label: 'Aaron Long', avatar: 'https://snippet.dhtmlx.com/codebase/data/kanban/01/img/user-2.jpg' }, + { id: '3', label: 'Angela Allen', avatar: 'https://snippet.dhtmlx.com/codebase/data/kanban/01/img/user-3.jpg' }, + { id: '4', label: 'Angela Long', avatar: 'https://snippet.dhtmlx.com/codebase/data/kanban/01/img/user-4.jpg' } +]; +// The user dataset for Type 2 +const users_dataset_2 = [ + { id: '1', label: 'Steve Smith', avatar: 'https://snippet.dhtmlx.com/codebase/data/kanban/01/img/user-1.jpg' }, + { id: '2', label: 'Aaron Long', avatar: 'https://snippet.dhtmlx.com/codebase/data/kanban/01/img/user-2.jpg' } +]; + +// The dataset for Task Type selector +const task_types = [ + { id: 'type1', label: 'Type 1' }, + { id: 'type2', label: 'Type 2' } +]; + +// Specify configuration for Editor fields +const editorShapeConfig = [ + ...eventCalendar.defaultEditorShape, + { // The selector for task types + type: 'combo', + key: 'task_type', + label: 'Task Type', + options: task_types, + config: { disabled: false, placeholder: "Select task type" } + }, + { // The selector for users. This selector changes its dataset depending on the selected Task Type + type: 'multiselect', + key: 'users', + label: 'Users', + options: users_dataset_1, + template: optionTemplate, + config: { + disabled: false, + placeholder: "Select user" + } + } +]; + +// The template that displays users in the Users selector +function optionTemplate(option) { + return `