Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ Building and integrating DHTMLX React Gantt (`@dhtmlx/trial-react-gantt` and `@d

Building and integrating DHTMLX Angular Gantt (`@dhtmlx/trial-angular-gantt` and `@dhx/angular-gantt`) - wrapper-specific setup, data ownership and persistence patterns (`data.save` / `data.batchSave`), and theming approach, with known failure modes and concrete fixes.

### `dhtmlx-js-scheduler`

Building and integrating the core DHTMLX JavaScript Scheduler in JavaScript and TypeScript applications. Recognises all delivery channels (`dhtmlx-scheduler` Standard/GPL, `@dhx/trial-scheduler`, `@dhx/scheduler`, `<script>`/CDN) and adapts setup, data, and theming guidance to each.

### `dhtmlx-react-scheduler`

Building and integrating DHTMLX React Scheduler (`@dhtmlx/trial-react-scheduler` and `@dhx/react-scheduler`) - wrapper setup, event state and persistence, scheduler views, resources, lightboxes, and conflict checks.
Expand All @@ -32,6 +36,7 @@ Building and integrating DHTMLX React Scheduler (`@dhtmlx/trial-react-scheduler`
npx skills add DHTMLX/skills --skill dhtmlx-js-gantt
npx skills add DHTMLX/skills --skill dhtmlx-react-gantt
npx skills add DHTMLX/skills --skill dhtmlx-angular-gantt
npx skills add DHTMLX/skills --skill dhtmlx-js-scheduler
npx skills add DHTMLX/skills --skill dhtmlx-react-scheduler
```

Expand All @@ -42,6 +47,7 @@ git clone https://github.com/DHTMLX/skills
cp -r skills/dhtmlx-js-gantt ~/.claude/skills/
cp -r skills/dhtmlx-react-gantt ~/.claude/skills/
cp -r skills/dhtmlx-angular-gantt ~/.claude/skills/
cp -r skills/dhtmlx-js-scheduler ~/.claude/skills/
cp -r skills/dhtmlx-react-scheduler ~/.claude/skills/
```

Expand Down
110 changes: 110 additions & 0 deletions dhtmlx-js-scheduler/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
name: dhtmlx-js-scheduler
description: >
Builds and integrates core DHTMLX JavaScript Scheduler into JavaScript or
TypeScript applications. Covers setup, initialization, lifecycle,
scheduler.parse/scheduler.load, templates, events, plugins, DataProcessor,
event CRUD, recurring events, timeline views, units views, locale/i18n,
styling, and theming for dhtmlx-scheduler (Standard/GPL),
@dhx/trial-scheduler, and @dhx/scheduler. Applies when working with booking
calendars, event scheduling, event CRUD, resource scheduling, recurring
events, timeline views, or units views, regardless of whether "DHTMLX" is
mentioned by name. Provides verified API guidance rather than guessing core
Scheduler APIs and surfaces edition limits before scaffolding.
---

## Source Of Truth

Use only:
1. The current project's files, structure, and established patterns
2. DHTMLX MCP for core Scheduler API details: https://docs.dhtmlx.com/mcp
3. Official DHTMLX Scheduler docs as fallback: https://docs.dhtmlx.com/scheduler/

Never invent config names, template callbacks, event names, method signatures, data shapes, plugin names, or backend behavior.

If any core Scheduler API detail is unclear, resolve it through DHTMLX MCP before writing code.

## Preflight

Before writing code, identify:
- **delivery**: npm package (`dhtmlx-scheduler`, `@dhx/trial-scheduler`, `@dhx/scheduler`) — check `package.json`, imports, lockfiles. Or script tag / CDN — check `<script>` tags in HTML, vendored `dhtmlxscheduler.js`, the `@license` banner inside that file.
- **edition**: `dhtmlx-scheduler` means Standard/GPL (PRO-only features unavailable); everything else is Professional. See [references/editions.md](references/editions.md) for the full detection procedure and the PRO-only feature list.
- **runtime**: plain JavaScript, TypeScript, Vite, browser-only `<script>`, or another app setup
- **outbound changes**: no persistence, `scheduler.createDataProcessor`, or custom backend/API clients
- **inbound changes**: none, hard reload (`scheduler.clearAll` + `scheduler.parse`), dynamic loading, or incremental external updates
- **inbound changes**: none, hard reload (`scheduler.clearAll` + `scheduler.parse`), dynamic loading via `scheduler.setLoadMode`, or incremental updates via scheduler API calls — see [references/data-and-crud.md](references/data-and-crud.md). For real-time streams use `scheduler.ext.liveUpdates` — see [references/live-updates.md](references/live-updates.md).

## Workflow

1. Confirm the installed DHTMLX Scheduler package and import path.
2. Decide the outbound and inbound change strategies before implementing CRUD or external sync.
3. Read only the reference file needed for the task:
- Editions, package detection, and PRO-only feature list: [references/editions.md](references/editions.md)
- Setup: [references/setup.md](references/setup.md)
- CRUD, state, and persistence: [references/data-and-crud.md](references/data-and-crud.md)
- Failure cases and guardrails: [references/known-failures.md](references/known-failures.md)
- Advanced patterns (plugins, views, resources, readonly, validation, undo/redo, schema): [references/advanced-patterns.md](references/advanced-patterns.md)
- Real-time / multi-user / external change streams (`scheduler.ext.liveUpdates`): [references/live-updates.md](references/live-updates.md)
- Styling, skins, CSS variables, selectors, and template-based visual customization: [references/styling-and-theming.md](references/styling-and-theming.md)
4. Use DHTMLX MCP before relying on advanced or unfamiliar APIs.
5. Implement with documented APIs only.

## MCP Server

This skill relies on DHTMLX MCP for API verification. If the `dhtmlx-mcp` tool is not available, ask the user to add it:

Claude Code:
```bash
claude mcp add --transport http dhtmlx-mcp https://docs.dhtmlx.com/mcp
```

Codex:
```bash
codex mcp add dhtmlx-mcp --url https://docs.dhtmlx.com/mcp
```

If MCP is not available, use the official docs at https://docs.dhtmlx.com/scheduler/ as fallback.

## Consult MCP First For

Consult DHTMLX MCP before using or changing:
- template callbacks you have not already verified
- lifecycle patterns around multiple instances or repeated mount/unmount
- DataProcessor modes, router signatures, delete confirmation, id replacement, and error handling
- recurring event payload shape (`rrule`, `duration`, `recurring_event_id`, `original_start`, `deleted`)
- lightbox section types and `map_to` conventions
- `scheduler.plugins({...})` extension loading and plugin-specific APIs
- timeline/units view configuration (`property`, `y_property`, `x_unit`, `x_step`, `x_size`, section lists)
- dynamic loading via `scheduler.setLoadMode`
- theme/skin values and CSS variable names
- locale and i18n customization
- `scheduler.ext.liveUpdates` (`RemoteEvents`, `remoteUpdates`) and the multi-user backend WebSocket protocol

## Hard Rules

- The Scheduler container must have explicit height.
- Import the matching Scheduler CSS.
- Use the app theme as the single source of truth.
- Prefer documented config, templates, events, and methods over undocumented internals.
- Keep Scheduler init/parse/events/DataProcessor cleanup in one lifecycle boundary.
- Activate extensions with `scheduler.plugins({...})` before using extension APIs.
- Normalize `start_date` and `end_date` before persistence.
- Build backend payloads explicitly from normalized event models.
- Return `{ id: databaseId }` or `{ tid: databaseId }` after creates when the backend assigns a real id.
- If not using DataProcessor, call `scheduler.changeEventId(tempId, databaseId)` after create persistence.
- Scheduler template return values are injected as raw HTML. Sanitize or HTML-escape every user-supplied string before it enters Scheduler or before returning it from templates.
- Enforce permissions on the backend/DataProcessor boundary. Scheduler readonly mode controls UI behavior and should not be treated as a security mechanism.
- When the installed package is Standard/GPL and the requested feature appears in the PRO-only list in [references/editions.md](references/editions.md), warn the user before scaffolding, then still scaffold the requested code.

## Quick Checklist

- [ ] Correct package identified
- [ ] Edition determined and PRO-only usage flagged for Standard installs
- [ ] Matching CSS import used
- [ ] Explicit height provided
- [ ] Singleton vs multi-instance model chosen
- [ ] Plugins enabled before dependent APIs
- [ ] Outbound and inbound change strategies decided
- [ ] Dates normalized before persistence
- [ ] DataProcessor return values handled
- [ ] Advanced APIs verified with MCP
216 changes: 216 additions & 0 deletions dhtmlx-js-scheduler/references/advanced-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# Advanced Patterns

Use this file when implementing Scheduler plugins, advanced views, resources, validation, undo/redo, or database schema.

## Contents
- Plugins
- Views And Resources
- Multiple Scheduler Instances On One Page (**PRO only**)
- Live Updates
- Validation And Collision Checks
- Undo/Redo With State Management
- Backend Schema Template
- Dynamic Loading

## Plugins

Many Scheduler features are gated behind `scheduler.plugins({...})`. Enable the extensions a feature needs before using the related APIs:

```ts
scheduler.plugins({
recurring: true,
tooltip: true,
collision: true,
});
```

Enable only the plugins required by the feature being implemented. Verify plugin requirements with MCP when working with unfamiliar Scheduler APIs or views.

## Views And Resources

Built-in calendar views:
- `day`
- `week`
- `month`

Additional views:
- `year`
- `agenda`
- `week_agenda` (PRO)
- `timeline` (PRO)
- `units` (PRO)
- `grid` (PRO)
- `map`

Resource-based scheduling is typically implemented with Timeline and Units views.

### Timeline View (PRO)

Timeline is PRO-only.

```ts
scheduler.plugins({ timeline: true });

scheduler.createTimelineView({
name: "timeline",
x_unit: "minute",
x_date: "%H:%i",
x_step: 30,
x_size: 24,
x_start: 16,
x_length: 48,
y_unit: [
{ key: 1, label: "Room A" },
{ key: 2, label: "Room B" },
],
y_property: "section_id",
render: "bar",
});
```

Rules:
- event objects must include the mapped `y_property` field
- tree timeline requires the Tree Timeline extension
- days timeline requires the Days Timeline extension
- timeline-specific templates are created or overwritten by `createTimelineView`, so configure them after the view is created
- for dynamic sections loaded from a backend, use `scheduler.serverList(...)` and `scheduler.updateCollection(...)`

### Units View (PRO)

Units is PRO-only.

```ts
scheduler.createUnitsView({
name: "unit",
property: "unit_id",
list: [
{ key: 1, label: "Room A" },
{ key: 2, label: "Room B" },
],
});
```

Rules:
- events must include the configured `property`, such as `unit_id`
- `list.key` values must match event property values
- for multi-section events, enable `multisection` (PRO) and align persistence with the selected data shape

## Multiple Scheduler Instances On One Page

**PRO only** (Commercial since Oct 6 2021, Enterprise, Ultimate). Use the factory pattern:

```ts
const schedulerA = Scheduler.getSchedulerInstance();
const schedulerB = Scheduler.getSchedulerInstance();

schedulerA.init("schedulerA_here", new Date(2026, 4, 1), "week");
schedulerB.init("schedulerB_here", new Date(2026, 4, 1), "month");
```

Each instance has its own configuration, templates, events, data, and DataProcessor. Do not mix the global `scheduler` singleton and factory instances in the same module — wire each feature against a single chosen reference.

On non-PRO packages, fall back to a single instance.

## Live Updates (`scheduler.ext.liveUpdates`)

For real-time collaboration, server push, or any external change stream, use `scheduler.ext.liveUpdates`. The extension exposes `remoteUpdates` (apply incoming event change messages) and `RemoteEvents` (client for the documented multi-user backend protocol).

Both integration modes — the native multi-user backend protocol and custom change sources — are covered in [live-updates.md](live-updates.md).

`RemoteEvents` supports subscriptions and custom handlers, while `remoteUpdates` applies the documented `add-event`, `update-event`, and `delete-event` messages automatically.

## Validation And Collision Checks

Client-side validation is UX only. Backend validation is authoritative.

Blockable validation hooks:
- `onBeforeEventChanged`
- `onEventSave`
- `onBeforeEventCreated`

Post-change notification events:
- `onEventAdded`
- `onEventChanged`
- `onEventDeleted`

Collision control:

```ts
scheduler.plugins({ collision: true });
```

Use collision checks for immediate feedback, but still enforce no-overlap constraints in the backend when the product requires them.

## Undo/Redo With State Management

Scheduler has delete-specific undo UI behavior via `scheduler.config.undo_deleted`, but full undo/redo should be designed at the application state level.

Rules:
- decide whether undo/redo is Scheduler-delete-only, app-managed, or both
- if using app-level history, store serializable event snapshots, not live Scheduler objects
- normalize date values before storing snapshots
- ensure undo/redo updates persistence if state must survive reload
- avoid wiping app-level undo/redo history during save or refetch unless intended
- after app-managed undo/redo, reparse Scheduler from the current store snapshot

## Backend Schema Template

Recommended practical schema for a writable Scheduler-backed app with events and optional resources. This is not a DHTMLX-mandated contract. Adjust the field names and tables to fit the app and backend.

Events table:
- `id` - UUID or integer primary key
- `calendar_id` or `project_id` - recommended foreign key for multi-calendar apps
- `text` - event title/description
- `start_date` - timestamp, not null
- `end_date` - timestamp, not null
- custom resource fields such as `resource_id`, `room_id`, `unit_id`, or `section_id`
- `created_at`
- `updated_at`

Recurring fields when recurring is enabled:
- `rrule` - text, nullable
- `duration` - duration of each occurrence in seconds, nullable
- `recurring_event_id` - nullable parent series id
- `original_start` - timestamp of the original occurrence, nullable
- `deleted` - boolean, default false

Recommended constraints:
- `end_date > start_date` for normal events
- foreign keys for calendar/project/resource references
- self-reference from `recurring_event_id` to events
- application-specific no-overlap constraints when required

Recommended indexes:
- calendar/project id
- `start_date`
- `end_date`
- resource field(s)
- `recurring_event_id`

Recurring server logic:
- if a deleted occurrence is inserted, respond with `deleted` status
- when a series is modified, remove its modified/deleted exception rows
- when a series is deleted, delete its exception rows according to product behavior
- when an exception row is deleted, update it to `deleted = true` rather than physically removing it

## Dynamic Loading

For large datasets, enable dynamic loading after `scheduler.init(...)` and before `scheduler.load(...)`:

```ts
scheduler.config.show_loading = true;

scheduler.init("scheduler_here", new Date(2026, 4, 1), "month");
scheduler.setLoadMode("month");
scheduler.load("/api/events");
```

Valid load modes: `"day"`, `"week"`, `"month"`, `"year"`.

Scheduler will request URLs with `from` and `to` query parameters:

```text
/api/events?from=...&to=...
```

Use `scheduler.config.load_date` when the backend expects a specific date format for generated `from` and `to` values.
Loading