diff --git a/docs/guides/cdn-links-list.md b/docs/guides/cdn-links-list.md index a2058032..a6ec3777 100644 --- a/docs/guides/cdn-links-list.md +++ b/docs/guides/cdn-links-list.md @@ -55,11 +55,11 @@ The `[version_number]` specifies `major.minor` version of the package, for examp Separate skin files are available in v6.0 and earlier. Starting from v7.0, all skins are included in `dhtmlxscheduler.css` and selected via `scheduler.skin`/`scheduler.setSkin()`, please check the [Migration guide](migration.md) for more details. -- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/skins/dhtmlxscheduler_terrace.css -- Flat: https://cdn.dhtmlx.com/scheduler/6.0/skins/dhtmlxscheduler_flat.css -- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/skins/dhtmlxscheduler_contrast_black.css -- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/skins/dhtmlxscheduler_contrast_white.css -- Material: https://cdn.dhtmlx.com/scheduler/6.0/skins/dhtmlxscheduler_material.css +- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_terrace.css +- Flat: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_flat.css +- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_contrast_black.css +- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_contrast_white.css +- Material: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_material.css ## Particular Scheduler version, Uncompressed @@ -82,8 +82,8 @@ Starting from v7.0, all skins are included in `dhtmlxscheduler.css` and selected Uncompressed skin files: -- Terrace: https://cdn.dhtmlx.com/scheduler/8.0/sources/skins/dhtmlxscheduler_terrace.css -- Flat: https://cdn.dhtmlx.com/scheduler/8.0/sources/skins/dhtmlxscheduler_flat.css -- Contrast Black: https://cdn.dhtmlx.com/scheduler/8.0/sources/skins/dhtmlxscheduler_contrast_black.css -- Contrast White: https://cdn.dhtmlx.com/scheduler/8.0/sources/skins/dhtmlxscheduler_contrast_white.css -- Material: https://cdn.dhtmlx.com/scheduler/8.0/sources/skins/dhtmlxscheduler_material.css +- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_terrace.css +- Flat: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_flat.css +- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_contrast_black.css +- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_contrast_white.css +- Material: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_material.css diff --git a/docs/integrations/google-calendar/google-calendar-sync.md b/docs/integrations/google-calendar/google-calendar-sync.md index 0b1e75a8..45af867e 100644 --- a/docs/integrations/google-calendar/google-calendar-sync.md +++ b/docs/integrations/google-calendar/google-calendar-sync.md @@ -35,7 +35,7 @@ The complete source code is [available on GitHub](https://github.com/DHTMLX/sche ## Demo repository A complete working project that matches this guide is available on GitHub: -- https://github.com/DHTMLX/scheduler-google-auth-demo +- https://github.com/DHTMLX/scheduler-google-calendar-demo The guide explains the key steps and shows the integration code that matters. The repository is the "full runnable reference". @@ -50,8 +50,8 @@ Do one of the following: - Clone the repository: ~~~bash title="Terminal" -git clone https://github.com/DHTMLX/scheduler-google-auth-demo.git -cd scheduler-google-auth-demo +git clone https://github.com/DHTMLX/scheduler-google-calendar-demo.git +cd scheduler-google-calendar-demo ~~~ If your project installs `@dhx/*` packages from the private registry, configure npm: @@ -164,7 +164,7 @@ In this step you will separate responsibilities so Scheduler stays a UI componen A typical structure: ~~~text title="Project structure" -scheduler-google-auth-demo/ +scheduler-google-calendar-demo/ client/ index.ejs main.ts diff --git a/docs/integrations/react/starhive-integration.md b/docs/integrations/react/starhive-integration.md index 2bfa8857..a0a4633c 100644 --- a/docs/integrations/react/starhive-integration.md +++ b/docs/integrations/react/starhive-integration.md @@ -103,7 +103,7 @@ Go to **Settings → API Connectors**. Select the `Scheduler` space, set the lan Extract the zip, locate the `starhive` folder under `project/src/io/`, and copy it into `lib/starhive/` in your Next.js project. The generated files contain workspace-specific UUIDs, so you'll repeat this step whenever the schema changes or you switch workspaces. :::note -At the time of writing, the Starhive TypeScript generator produces output that does not pass strict TypeScript: a missing `Sla.ts` reference, a missing `visitSlaAttribute` implementation in the inline `AttributeVisitor` literal, and a `client.request` call against an `any`-typed field (TS2347). The companion demo repo ships three minimal patches that work around these; see [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/PATCHES.md) for the diffs. Re-apply the same patches whenever you regenerate the schema, until Starhive ships a fix. +At the time of writing, the Starhive TypeScript generator produces output that does not pass strict TypeScript: a missing `Sla.ts` reference, a missing `visitSlaAttribute` implementation in the inline `AttributeVisitor` literal, and a `client.request` call against an `any`-typed field (TS2347). The companion demo repo ships three minimal patches that work around these; see [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/) for the diffs. Re-apply the same patches whenever you regenerate the schema, until Starhive ships a fix. ::: ## Step 5. Configure the Starhive client @@ -449,7 +449,7 @@ Open `http://localhost:3000`, drag an event to a new time, edit its text, and de ## Notes on Starhive integration - **Server-side credentials only.** `STARHIVE_API_TOKEN` and `STARHIVE_WORKSPACE_ID` are read inside Route Handlers (`getStarhiveClient`); they never reach the browser bundle. Don't move the Starhive client into a Client Component or expose the token via a `NEXT_PUBLIC_*` variable. -- **Schema regeneration.** Whenever you add or rename attributes in Starhive, regenerate the TypeScript schema and replace `lib/starhive/`. Re-apply the patches in [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/PATCHES.md) if `next build` complains about the same upstream issues. +- **Schema regeneration.** Whenever you add or rename attributes in Starhive, regenerate the TypeScript schema and replace `lib/starhive/`. Re-apply the patches in [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/) if `next build` complains about the same upstream issues. - **No realtime sync.** Unlike the Firebase integration, Starhive doesn't push changes to connected clients. Multiple users editing the same Scheduler will overwrite each other's changes. For multi-user scenarios, add polling on the client - or wire up Starhive webhooks to push invalidation events through SSE / WebSockets and refresh `events` state on remote changes. - **Dynamic loading for larger datasets.** The `/api/load` route loads every event in the workspace. For production, accept `from` / `to` query parameters in the GET handler, filter on `start_date` / `end_date`, and call `scheduler.setLoadMode("day")` on the client so only the visible range is fetched. - **Reference attributes carry arrays.** `Events.getResourceId()` returns `string[] | undefined` because Starhive's reference attributes are multi-valued. The demo flattens via `?.[0] || null`. If you allow events to belong to multiple resources, change the timeline view's `y_property` resolution and the normalize / builder calls accordingly. diff --git a/docs/integrations/react/state/valtio.md b/docs/integrations/react/state/valtio.md index f615f0e1..33ba6e01 100644 --- a/docs/integrations/react/state/valtio.md +++ b/docs/integrations/react/state/valtio.md @@ -15,7 +15,7 @@ By the end, you will have a Scheduler with: - snapshot-based undo/redo (events + config) :::note -The complete source code is [available on GitHub](https://github.com/nicetip/react-scheduler-valtio-starter). +The complete source code is [available on GitHub](https://github.com/DHTMLX/react-scheduler-valtio-starter). ::: ## Prerequisites diff --git a/docs/integrations/vue/installation.md b/docs/integrations/vue/installation.md index a60d8f02..33a9814b 100644 --- a/docs/integrations/vue/installation.md +++ b/docs/integrations/vue/installation.md @@ -39,7 +39,7 @@ This build is fully functional, but shows a message indicating that the library ### Optional: Start a full evaluation period (recommended) Although the trial package installs without restrictions, you may also start an official evaluation through the website at -[https://dhtmlx.com/docs/products/dhtmlxScheduler-for-Vuejs/download.shtml](https://dhtmlx.com/docs/products/dhtmlxScheduler-for-Vuejs/download.shtml). +[https://dhtmlx.com/docs/products/dhtmlxScheduler/download.shtml](https://dhtmlx.com/docs/products/dhtmlxScheduler/download.shtml). Starting a formal evaluation gives you free technical support during the trial period. diff --git a/i18n/de/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md b/i18n/de/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md index 00b934cb..33cfadc3 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md @@ -1,63 +1,89 @@ --- title: "Vollständige Liste der CDN-Links" -sidebar_label: "Vollständige Liste der CDN-Links" +sidebar_label: "CDN-Links" --- # Vollständige Liste der CDN-Links -Dieser Artikel bietet eine vollständige Sammlung von Links, um die Scheduler-Funktionalität über das CDN einzubinden. Jeder Abschnitt ist einer bestimmten Scheduler-Version gewidmet: +Dieser Artikel führt CDN-Links auf, um **dhtmlxScheduler** in Ihrer Anwendung einzubinden. -- Core-Dateien - die *dhtmlxscheduler.js*- und *dhtmlxscheduler.css*-Dateien, die die Hauptfunktionen enthalten -- Skins - Links zu allen verfügbaren [Skins](guides/skins.md) +Scheduler besteht aus zwei Kern-Dateien: -:::note -Ab Version v6.0 sind alle [Erweiterungen](guides/extensions-list.md) im *dhtmlxscheduler.js*-File gebündelt. Wenn Sie dhtmlxScheduler 5.3 oder älter verwenden, lesen Sie bitte den [Migrationsartikel](migration.md#53---60). -::: +- **JavaScript:** `dhtmlxscheduler.js` +- **Styles:** `dhtmlxscheduler.css` -## Neueste Scheduler-Version -Um die neueste Version der Bibliothek zu verwenden, setzen Sie den Quellpfad auf **https://cdn.dhtmlx.com/scheduler/edge/...** +## Neueste Scheduler-Version (edge) -Core-Dateien: [JS](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.css) +Verwenden Sie: -Skins: [Terrace](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_contrast_white.css). +`https://cdn.dhtmlx.com/scheduler/edge/...` -## Neueste Scheduler-Version, Unkomprimiert +### Kernel-Dateien -Für unkomprimierte Quellen der neuesten Version verwenden Sie den Pfad **https://cdn.dhtmlx.com/scheduler/edge/sources/...** +- JS: https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.css -Core-Dateien: [JS](https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.css) -Skins: [Terrace](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_contrast_white.css). +## Neueste Scheduler-Version (edge), Unkomprimiert + +Verwenden Sie: + +`https://cdn.dhtmlx.com/scheduler/edge/sources/...` + +### Kern-Dateien + +- JS: https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.css + ## Bestimmte Scheduler-Version -Um auf eine bestimmte Version der Bibliothek zu verweisen, setzen Sie den Quellpfad auf **https://cdn.dhtmlx.com/scheduler/[version_number]/...** +Verwenden Sie: + +`https://cdn.dhtmlx.com/scheduler/[version_number]/...` + +Die `[version_number]` gibt die major.minor-Version des Pakets an, zum Beispiel **7.0**, **6.0**, **5.3** usw. Unser CDN stellt immer die neueste Patch-Version für jede major/minor-Veröffentlichung bereit. + +### Kern-Dateien + +- JS: https://cdn.dhtmlx.com/scheduler/7.0/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/7.0/dhtmlxscheduler.css + +### Skins (nur für v6.0 und älter) + +Getrennte Skin-Dateien sind in v6.0 und älter verfügbar. +Ab Version v7.0 sind alle Skins in `dhtmlxscheduler.css` enthalten und über `scheduler.skin`/`scheduler.setSkin()` auswählbar, bitte prüfen Sie den [Migrationsleitfaden](migration.md) für weitere Details. + +- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_terrace.css +- Flat: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_flat.css +- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_contrast_black.css +- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_contrast_white.css +- Material: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_material.css + +## Bestimmte Scheduler-Version, Unkomprimiert + +Verwenden Sie: + +`https://cdn.dhtmlx.com/scheduler/[version_number]/sources/...` + +Die `[version_number]` gibt die major.minor-Version des Pakets an, zum Beispiel **7.0**, **6.0**, **5.3** usw. Unser CDN liefert immer die neueste Patch-Version für jede major/minor-Veröffentlichung. + +### Kern-Dateien -Core-Dateien: [JS](https://cdn.dhtmlx.com/scheduler/4.3/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/4.3/dhtmlxscheduler.css) +- JS: https://cdn.dhtmlx.com/scheduler/7.0/sources/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/7.0/sources/dhtmlxscheduler.css -Skins: [Terrace](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_contrast_white.css). -## Bestimmte Scheduler-Version, Unkomprimiert +### Skins (nur für v6.0 und älter) -Um unkomprimierte Quellen einer bestimmten Version zu verwenden, setzen Sie den Pfad auf **https://cdn.dhtmlx.com/scheduler/[version_number]/sources/...** +Getrennte Skin-Dateien sind in v6.0 und älter verfügbar. +Ab Version v7.0 sind alle Skins in `dhtmlxscheduler.css` enthalten und über `scheduler.skin`/`scheduler.setSkin()` auswählbar, bitte prüfen Sie den [Migrationsleitfaden](migration.md) für weitere Details. -Core-Dateien: [JS](https://cdn.dhtmlx.com/scheduler/4.3/sources/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/4.3/sources/skins/dhtmlxscheduler.css) +Unkomprimierte Skin-Dateien: -Skins: [Terrace](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_contrast_white.css). +- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_terrace.css +- Flat: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_flat.css +- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_contrast_black.css +- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_contrast_white.css +- Material: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_material.css \ No newline at end of file diff --git a/i18n/de/docusaurus-plugin-content-docs/current/guides/initialization.md b/i18n/de/docusaurus-plugin-content-docs/current/guides/initialization.md index bfd8b849..3dd8e4b4 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/guides/initialization.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/guides/initialization.md @@ -21,7 +21,7 @@ Dieser Leitfaden beschreibt die Initialisierung von dhtmlxScheduler in reinem JS - +
Angular
@@ -29,7 +29,7 @@ Dieser Leitfaden beschreibt die Initialisierung von dhtmlxScheduler in reinem JS
- +
Vue
diff --git a/i18n/de/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md b/i18n/de/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md index 88a9bf37..0a38c188 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md @@ -35,7 +35,7 @@ Der vollständige Quellcode ist auf GitHub verfügbar: [https://github.com/DHTML ## Demo-Repository Ein vollständiges, funktionsfähiges Projekt, das dieser Anleitung entspricht, ist auf GitHub verfügbar: -- https://github.com/dhtmlx/scheduler-google-auth-demo +- https://github.com/DHTMLX/scheduler-google-calendar-demo Die Anleitung erläutert die wichtigsten Schritte und zeigt den relevanten Integrationscode. Das Repository ist die „voll funktionsfähige Referenz“. @@ -50,8 +50,8 @@ Führen Sie eine der folgenden Optionen aus: - Das Repository klonen: ~~~bash title="Terminal" -git clone https://github.com/dhtmlx/scheduler-google-auth-demo.git -cd scheduler-google-auth-demo +git clone https://github.com/dhtmlx/scheduler-google-calendar-demo.git +cd scheduler-google-calendar-demo ~~~ Wenn Ihr Projekt `@dhx/*`-Pakete aus dem privaten Registry installiert, konfigurieren Sie npm: @@ -164,7 +164,7 @@ In diesem Schritt trennen Sie die Verantwortlichkeiten, sodass Scheduler eine UI Eine typische Struktur: ~~~text title="Project structure" -scheduler-google-auth-demo/ +scheduler-google-calendar-demo/ client/ index.ejs main.ts diff --git a/i18n/de/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md b/i18n/de/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md new file mode 100644 index 00000000..8f457ceb --- /dev/null +++ b/i18n/de/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md @@ -0,0 +1,462 @@ +--- +title: React Scheduler und Starhive-Integration +sidebar_label: Starhive Schnellstart +description: "DHTMLX React Scheduler mit einem Starhive NoSQL-Backend über Next.js API-Routen verbinden." +--- + +# React Scheduler und Starhive-Integration + +Diese Anleitung verbindet **React Scheduler** mit einem **Starhive** NoSQL-Backend über Next.js Route-Handler. Starhive bietet ein typisiertes Schema und einen generierten TypeScript-Client, sodass die API-Schicht minimal bleibt: ein Endpunkt lädt Ereignisse und Ressourcen, ein anderer erledigt Create / Update / Delete. + +Sie werden Folgendes erstellen: + +- eine Next.js-Seite, die den Scheduler in einer Client-Komponente hostet +- `/api/load` – lädt beim ersten Rendern Ereignisse und Ressourcen von Starhive +- `/api/event` (POST) und `/api/event/[id]` (PUT, DELETE) – Schreibpfade, die vom Scheduler `dataBridge` verwendet werden + +:::note +Der vollständige Quellcode ist [auf GitHub verfügbar](https://github.com/DHTMLX/react-scheduler-starhive-demo). +::: + +## Voraussetzungen + +- Grundlagen zu Next.js + React + TypeScript +- Node.js 18+ +- Ein [Starhive](https://starhive.com/) Konto (die 30-tägige Testversion reicht aus) + +## Schritt 1. Projekt erstellen + +```bash +npx create-next-app@latest react-scheduler-starhive-demo +cd react-scheduler-starhive-demo +``` + +Installieren Sie den React Scheduler wie im [Installationsleitfaden für den React Scheduler](integrations/react/installation.md) beschrieben. Zur Evaluation: + +```bash +npm install @dhtmlx/trial-react-scheduler +``` + +Wenn Sie bereits das Professional-Paket verwenden, ersetzen Sie `@dhtmlx/trial-react-scheduler` durch `@dhx/react-scheduler` in Befehlen und Imports. + +Außerdem benötigen Sie `axios` – es ist eine Peer-Abhängigkeit des generierten Starhive TypeScript-Clients. + +```bash +npm install axios +``` + +## Schritt 2. Starhive Space einrichten + +Nach dem Anmelden klicken Sie rechts oben auf **+ Create** und benennen den Space mit `Scheduler`. + +Im Space erstellen Sie zwei Typen: `Resources` und `Events`. Resources halten die Zeilen der Timeline (Teams, Personen, Räume usw.). Events beziehen sich jeweils auf eine Resource. + +Fügen Sie die folgenden Attribute über die Schaltfläche **+ Attribute** hinzu. Starhive erzeugt automatisch die `id` für jeden Eintrag, daher müssen Sie sie nicht deklarieren. + +**Resources type** + +| Feld | Typ | +| ------- | ---- | +| `label` | Text | + +**Events type** + +| Feld | Typ | +| ------------- | -------------------------- | +| `text` | Text | +| `start_date` | Datum & Uhrzeit | +| `end_date` | Datum & Uhrzeit | +| `resource_id` | Referenz → Resources | + +## Schritt 3. Beispieldaten importieren + +Erstellen Sie `scheduler_resources.csv`: + +```csv +label +"Frontend Team" +"Backend Team" +"QA Team" +"DevOps" +"Security Team" +``` + +Und `scheduler_events.csv`: + +```csv +text,start_date,end_date,resource_id +"Development","2026-04-01T08:00:00","2026-04-01T10:30:00","Frontend Team" +"Code Review","2026-04-01T09:00:00","2026-04-01T11:30:00","Backend Team" +"QA Testing","2026-04-01T10:00:00","2026-04-01T13:00:00","QA Team" +"Deployment","2026-04-01T11:00:00","2026-04-01T13:30:00","DevOps" +"Incident Response","2026-04-01T12:00:00","2026-04-01T15:00:00","DevOps" +"Maintenance Window","2026-04-01T08:30:00","2026-04-01T11:00:00","Backend Team" +"Security Scan","2026-04-01T13:00:00","2026-04-01T15:30:00","Security Team" +``` + +Im Starhive UI öffnen Sie den Typ und klicken Sie für jeden Datei den CSV-Import. + +## Schritt 4. Schema generieren und kopieren + +Gehen Sie zu **Settings → API Connectors**. Wählen Sie den Space `Scheduler`, setzen Sie die Sprache auf TypeScript, klicken Sie auf **Generate**, dann **Download**. + +Entpacken Sie das Archiv, lokalisieren Sie den Ordner `starhive` unter `project/src/io/` und kopieren Sie ihn nach `lib/starhive/` in Ihr Next.js-Projekt. Die generierten Dateien enthalten arbeitsbereichsspezifische UUIDs, daher führen Sie diesen Schritt jedes Mal erneut aus, wenn sich das Schema ändert oder Sie zwischen Arbeitsbereichen wechseln. + +:::note +Zum Zeitpunkt des Verfassens erzeugt der Starhive TypeScript-Generator eine Ausgabe, die kein strenges TypeScript erfüllt: ein fehlender `Sla.ts`-Verweis, eine fehlende Implementierung von `visitSlaAttribute` im Inline-`AttributeVisitor`-Literal und ein `client.request`-Aufruf gegen ein Feld vom Typ `any` (TS2347). Das Begleit-Demo-Repo enthält drei minimale Patches, die diese Probleme umgehen; siehe [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/) für die Diffs. Wenden Sie dieselben Patches erneut an, wenn Sie das Schema regenerieren, bis Starhive einen Fix liefert. +::: + +## Schritt 5. Starhive-Client konfigurieren + +Erstellen Sie `lib/starhiveClient.ts`: + +```ts title="lib/starhiveClient.ts" +import { StarhiveClient } from "./starhive/client/StarhiveClient"; +import { JSON_DECODERS } from "./starhive/schema/JsonDecoders"; + +let starhiveClient: StarhiveClient | null = null; + +export function getStarhiveClient() { + if (starhiveClient) return starhiveClient; + + const workspaceId = process.env.STARHIVE_WORKSPACE_ID; + const apiKey = process.env.STARHIVE_API_TOKEN; + + if (!workspaceId || !apiKey) { + throw new Error("Missing Starhive configuration (workspaceId or API token)"); + } + + starhiveClient = new StarhiveClient(apiKey, workspaceId, JSON_DECODERS); + return starhiveClient; +} +``` + +Die Funktion cacht den Client im Modul-Scope, sodass Route-Handler eine einzige Instanz teilen. + +Fügen Sie `.env.local` (oder `.env`) im Projektstamm hinzu: + +```env title=".env.local" +STARHIVE_API_TOKEN=your-api-token +STARHIVE_WORKSPACE_ID=your-workspace-id +``` + +Generieren Sie den API-Token unter **Settings → Personal access tokens**. Die Workspace-ID ist der Pfadabschnitt in `https://app.starhive.com/workspace//home`. + +## Schritt 6. Ereignisse und Ressourcen laden + +Erstellen Sie `app/api/load/route.ts`: + +```ts title="app/api/load/route.ts" +import { NextResponse } from 'next/server'; +import { getStarhiveClient } from '@/lib/starhiveClient'; +import { Events } from '@/lib/starhive/schema/Events'; +import { Resources } from '@/lib/starhive/schema/Resources'; + +function normalizeEvents(events: Events[]) { + return events.map(ev => ({ + id: ev.getId() || '', + text: ev.getText(), + start_date: ev.getStartDate(), + end_date: ev.getEndDate(), + resource_id: ev.getResourceId()?.[0] || null, + })); +} + +export async function GET() { + try { + const client = getStarhiveClient(); + const [events, resources] = await Promise.all([ + client.search(Events.TYPE_ID, ""), + client.search(Resources.TYPE_ID, "") + ]); + + return NextResponse.json({ + events: normalizeEvents(events.result), + resources: resources.result.map((r) => ({ + key: r.getId(), + label: r.getLabel(), + })), + }); + } catch (error) { + return NextResponse.json({ error: 'Failed to load data' }, { status: 500 }); + } +} +``` + +`normalizeEvents` wandelt jedes Starhive-Objekt in die Form um, die der React Scheduler erwartet: `{ id, text, start_date, end_date, resource_id }`. Ressourcen werden zu `{ key, label }` zusammengefasst, was von der Timeline-Ansicht als `y_unit` konsumiert wird. + +Rufen Sie nach dem Starten des Entwicklungsservers die URL `http://localhost:3000/api/load` auf, um die JSON-Form zu überprüfen. + +## Schritt 7. Scheduler rendern und Ereignisse laden + +Erstellen Sie `app/page.tsx`: + +```tsx title="app/page.tsx" +'use client'; + +import { useEffect, useMemo, useState } from 'react'; +import ReactScheduler, { + type Event, + type SchedulerViewsProp, +} from '@dhtmlx/trial-react-scheduler'; +import '@dhtmlx/trial-react-scheduler/dist/react-scheduler.css'; + +type Resource = { key: string; label: string }; + +export default function Scheduler() { + const [resources, setResources] = useState([]); + const [events, setEvents] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetch('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/api/load') + .then((response) => response.json()) + .then((data) => { + setResources(data.resources); + setEvents(data.events); + }) + .catch((error) => { + console.error('Failed to load resources data:', error); + }) + .finally(() => { + setLoading(false); + }); + }, []); + + const views: SchedulerViewsProp = useMemo( + () => ({ + timeline: [ + { + name: "timeline", + x_unit: "hour", + x_date: "%H:%i", + x_step: 1, + x_start: 8, + x_size: 13, + x_length: 13, + event_dy: 50, + event_min_dy: 50, + y_property: "resource_id", + render: "bar", + y_unit: resources, + }, + ], + }), + [resources] + ); + + if (loading) { + return
Loading...
; + } + + return ( +
+ +
+ ); +} +``` + +Ein `loading`-Flag ist vorzuziehen gegenüber dem Prüfen von `events.length` oder `resources.length`: Ein Workspace, der tatsächlich zero Events hat, sollte dennoch den leeren Scheduler rendern statt in der Ladeanzeige hängen zu bleiben. + +Führen Sie `npm run dev` aus – die Timeline erscheint mit den importierten Ereignissen, gruppiert nach Ressource. + +## Schritt 8. Die CRUD-Endpunkte implementieren + +Die Scheduler-`dataBridge` ruft drei Endpunkte auf – POST für Create, PUT für Update, DELETE für Delete – und erwartet bestimmte Antwortformen: + +| HTTP-Methode | Endpoint | Antwort | +| ----------- | ------------------------- | --------------------------------- | +| `GET` | `/api/load` | `{ events, resources }` | +| `POST` | `/api/event` | `{ action: "inserted", tid: id }` | +| `PUT` | `/api/event/{event_id}` | `{ action: "updated" }` | +| `DELETE` | `/api/event/{event_id}` | `{ action: "deleted" }` | + +Erstellen Sie den POST-Handler unter `app/api/event/route.ts`: + +```ts title="app/api/event/route.ts" +import { NextRequest, NextResponse } from 'next/server'; +import { getStarhiveClient } from '@/lib/starhiveClient'; +import { Events } from '@/lib/starhive/schema/Events'; + +export async function POST(req: NextRequest) { + try { + const { text, start_date, end_date, resource_id } = await req.json(); + const client = getStarhiveClient(); + + const event = Events.builder() + .text(text) + .startDate(new Date(start_date)) + .endDate(new Date(end_date)) + .resourceId([resource_id]) + .build(); + + const result = await client.createObject(event); + return NextResponse.json({ action: 'inserted', tid: result.getId() }); + } catch (error) { + return NextResponse.json({ error: 'Create failed' }, { status: 500 }); + } +} +``` + +Und die dynamischen PUT/DELETE-Handler unter `app/api/event/[id]/route.ts`: + +```ts title="app/api/event/[id]/route.ts" +import { NextRequest, NextResponse } from 'next/server'; +import { Events } from "@/lib/starhive/schema/Events"; +import { getStarhiveClient } from "@/lib/starhiveClient"; + +export async function PUT( + request: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + try { + const { id } = await params; + const body = await request.json(); + const client = getStarhiveClient(); + + const existingEvent = await client.getObject(id, Events.TYPE_ID); + if (!existingEvent) { + return NextResponse.json({ error: 'Event not found' }, { status: 404 }); + } + + const updatedEvent = Events.builder() + .id(id) + .text(body.text) + .startDate(new Date(body.start_date)) + .endDate(new Date(body.end_date)) + .resourceId([body.resource_id]) + .build(); + + await client.updateObject(updatedEvent); + return NextResponse.json({ action: 'updated' }); + } catch (error: any) { + console.error('Update error:', error); + return NextResponse.json( + { error: 'Update failed', details: error.message }, + { status: 500 } + ); + } +} + +export async function DELETE( + request: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + try { + const { id } = await params; + const client = getStarhiveClient(); + await client.deleteObjectsInBulk([id]); + + return NextResponse.json({ action: 'deleted' }); + } catch (error: any) { + console.error('Delete error:', error); + return NextResponse.json( + { error: 'Delete failed', details: error.message }, + { status: 500 } + ); + } +} +``` + +:::note +In Next.js 15+ ist das `params`-Argument dynamischer Routen-Handler ein `Promise`. Typisieren Sie es immer als `Promise<{...}>` und warten Sie darauf, bevor Sie die Segmentwerte lesen – das Weglassen der `Promise<>`-Umhüllung kompiliert in einigen Setups, schlägt aber im Strict-Modus fehlt. +::: + +## Schritt 9. Den dataBridge anschließen + +Erstellen Sie eine kleine client-seitige Hilfsfunktion unter `services/scheduler.ts`: + +```ts title="services/scheduler.ts" +import type { Event } from '@dhtmlx/trial-react-scheduler'; + +async function request(url: string, options: RequestInit): Promise { + const res = await fetch(url, options); + if (!res.ok) throw new Error(`Request failed: ${res.status}`); + return res.json(); +} + +export function createEvent(event: Event) { + return request('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/api/event', { + method: 'POST', + body: JSON.stringify(event), + headers: { 'Content-Type': 'application/json' }, + }); +} + +export function updateEvent(event: Event) { + return request(`/api/event/${event.id}`, { + method: 'PUT', + body: JSON.stringify(event), + headers: { 'Content-Type': 'application/json' }, + }); +} + +export function deleteEvent(id: string | number) { + return request(`/api/event/${id}`, { + method: 'DELETE', + }); +} +``` + +Schließen Sie den `dataBridge` an die Seite an. Aktualisieren Sie `app/page.tsx` mit den Imports und einer `data`-Eigenschaft auf ``: + +```tsx title="app/page.tsx" +import { createEvent, deleteEvent, updateEvent } from '@/services/scheduler'; + +// inside the Scheduler component: +const dataBridge = useMemo(() => ({ + save: (entity: string, action: string, payload: Event, id: string | number) => { + if (entity !== "event") return; + + switch (action) { + case "update": + return updateEvent(payload); + case "create": + return createEvent(payload); + case "delete": + return deleteEvent(id); + default: + console.warn(`Unknown action: ${action}`); + return; + } + }, +}), []); + +// an ReactScheduler übergeben: + +``` + +## Testen + +```bash +npm run dev +``` + +Öffnen Sie `http://localhost:3000`, ziehen Sie ein Ereignis in eine neue Zeitspanne, bearbeiten Sie dessen Text und löschen Sie eines. Jede Änderung sollte sofort in der Starhive-Oberfläche unter dem Typ `Events` erscheinen. + +## Hinweise zur Starhive-Integration + +- **Nur serverseitige Anmeldeinformationen.** `STARHIVE_API_TOKEN` und `STARHIVE_WORKSPACE_ID` werden in Route-Handlern (`getStarhiveClient`) gelesen; sie gelangen nie in das Browser-Bundle. Verschieben Sie den Starhive-Client nicht in eine Client-Komponente oder geben Sie das Token nicht über eine `NEXT_PUBLIC_*`-Variable weiter. +- **Schema-Neugenerierung.** Wann immer Sie Attribute in Starhive hinzufügen oder umbenennen, regenerieren Sie das TypeScript-Schema und ersetzen Sie `lib/starhive/`. Wenden Sie ggf. die Patches in [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/) erneut an, falls `next build` dieselben upstream-Probleme meldet. +- **Kein Echtzeit-Sync.** Im Gegensatz zur Firebase-Integration sendet Starhive keine Änderungen sofort an verbundene Clients. Mehrere Benutzer, die denselben Scheduler bearbeiten, überschreiben gegenseitig ihre Änderungen. Für Mehrbenutzer-Szenarien fügen Sie auf dem Client Polling hinzu – oder verbinden Sie Starhive-Webhooks mit SSE/WebSockets, um Invalidation-Ereignisse auszulösen und den `events`-Zustand bei entfernten Änderungen zu aktualisieren. +- **Dynamisches Laden großer Datensätze.** Die `/api/load`-Route lädt alle Ereignisse im Workspace. Für die Produktion akzeptieren Sie `from` / `to`-Abfrageparameter im GET-Handler, filtern Sie nach `start_date` / `end_date` und rufen Sie `scheduler.setLoadMode("day")` auf dem Client auf, damit nur der sichtbare Bereich abgerufen wird. +- **Referenzattribute tragen Arrays.** `Events.getResourceId()` gibt `string[] | undefined` zurück, da Starhives Referenzattribute mehrfach vorkommen können. Das Demo-Beispiel flatten dies über `?.[0] || null`. Wenn Sie Ereignisse mehreren Ressourcen zuordnen lassen, passen Sie die Auflösung des Timeline-View-`y_property` sowie die Normalize-/Builder-Aufrufe entsprechend an. + +## Verwandte Seiten + +- [Datenbindung & Grundlagen der Zustandsverwaltung](integrations/react/state/state-management-basics.md) +- [React Scheduler Überblick](integrations/react/overview.md#bindingdata) +- [Server-Integration](guides/server-integration.md) +- [React Scheduler und Firebase-Integration] (integrations/react/firebase-integration.md) – sibling pattern with realtime sync \ No newline at end of file diff --git a/i18n/de/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md b/i18n/de/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md index 78305825..a2e14d3d 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md @@ -15,7 +15,7 @@ Am Ende verfügen Sie über einen Scheduler mit: - snapshotbasierte Undo/Redo (Ereignisse + Konfiguration) :::note -Der vollständige Quellcode ist [auf GitHub verfügbar](https://github.com/nicetip/react-scheduler-valtio-starter). +Der vollständige Quellcode ist [auf GitHub verfügbar](https://github.com/DHTMLX/react-scheduler-valtio-starter). ::: ## Voraussetzungen diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md b/i18n/ko/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md index 4ef5ef06..b5966319 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md @@ -1,63 +1,89 @@ --- title: "CDN 링크 전체 목록" -sidebar_label: "CDN 링크 전체 목록" +sidebar_label: "CDN 링크 목록" --- # CDN 링크 전체 목록 -이 문서에서는 CDN을 통해 Scheduler 기능을 포함할 수 있는 링크의 전체 모음을 제공합니다. 각 섹션은 특정 Scheduler 버전에 할당되어 있습니다: +이 문서는 애플리케이션에 **dhtmlxScheduler**를 포함하기 위한 CDN 링크를 나열합니다. -- 코어 파일 - 주요 기능이 포함된 *dhtmlxscheduler.js* 및 *dhtmlxscheduler.css* 파일 -- 스킨 - 사용 가능한 모든 [스킨](guides/skins.md)에 대한 링크 +Scheduler는 두 개의 핵심 파일로 구성됩니다: -:::note -v6.0부터 모든 [확장 기능](guides/extensions-list.md)이 *dhtmlxscheduler.js* 파일에 번들로 포함됩니다. dhtmlxScheduler 5.3 이하 버전을 사용 중인 경우 [마이그레이션 가이드](migration.md#53---60)를 참고하세요. -::: +- **자바스크립트:** `dhtmlxscheduler.js` +- **스타일:** `dhtmlxscheduler.css` -## 최신 Scheduler 버전 -라이브러리의 최신 버전을 사용하려면, 소스 경로를 **https://cdn.dhtmlx.com/scheduler/edge/...** 로 설정하세요. +## 최신 Scheduler 버전(edge) -코어 파일: [JS](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.css) +다음 형식으로 사용하십시오: -스킨: [Terrace](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_contrast_white.css). +`https://cdn.dhtmlx.com/scheduler/edge/...` -## 최신 Scheduler 버전, 압축 해제됨 +### 핵심 파일 -최신 버전의 압축 해제된 소스를 사용하려면, 경로를 **https://cdn.dhtmlx.com/scheduler/edge/sources/...** 로 설정하세요. +- JS: https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.css -코어 파일: [JS](https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.css) -스킨: [Terrace](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_contrast_white.css). +## 최신 Scheduler 버전(edge), 비압축 + +다음 형식으로 사용하십시오: + +`https://cdn.dhtmlx.com/scheduler/edge/sources/...` + +### 핵심 파일 + +- JS: https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.css + ## 특정 Scheduler 버전 -라이브러리의 특정 버전을 참조하려면, 소스 경로를 **https://cdn.dhtmlx.com/scheduler/[version_number]/...** 로 설정하세요. +다음 형식으로 사용하십시오: + +`https://cdn.dhtmlx.com/scheduler/[version_number]/...` + +`[version_number]`는 패키지의 `major.minor` 버전을 지정합니다. 예: **7.0**, **6.0**, **5.3** 등. CDN은 각 major/minor 릴리스에 대해 항상 최신 패치 버전을 제공합니다. + +### 핵심 파일 + +- JS: https://cdn.dhtmlx.com/scheduler/7.0/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/7.0/dhtmlxscheduler.css + +### 스킨(오직 v6.0 이하 버전용) + +v6.0 이하 버전에서는 별도의 스킨 파일을 제공합니다. +v7.0부터는 모든 스킨이 `dhtmlxscheduler.css`에 포함되며, `scheduler.skin`/`scheduler.setSkin()`으로 선택됩니다. 자세한 내용은 [Migration guide](migration.md)를 확인하십시오. + +- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_terrace.css +- Flat: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_flat.css +- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_contrast_black.css +- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_contrast_white.css +- Material: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_material.css + +## 특정 Scheduler 버전, 비압축 + +다음 형식으로 사용하십시오: + +`https://cdn.dhtmlx.com/scheduler/[version_number]/sources/...` + +`[version_number]`는 패키지의 `major.minor` 버전을 지정합니다. 예: **7.0**, **6.0**, **5.3** 등. CDN은 각 major/minor 릴리스에 대해 항상 최신 패치 버전을 제공합니다. + +### 핵심 파일 -코어 파일: [JS](https://cdn.dhtmlx.com/scheduler/4.3/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/4.3/dhtmlxscheduler.css) +- JS: https://cdn.dhtmlx.com/scheduler/7.0/sources/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/7.0/sources/dhtmlxscheduler.css -스킨: [Terrace](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_contrast_white.css). -## 특정 Scheduler 버전, 압축 해제됨 +### 스킨(오직 v6.0 이하 버전용) -특정 버전의 압축 해제된 소스를 사용하려면, 경로를 **https://cdn.dhtmlx.com/scheduler/[version_number]/sources/...** 로 설정하세요. +v6.0 이하 버전에서는 별도의 스킨 파일이 제공됩니다. +v7.0부터는 모든 스킨이 `dhtmlxscheduler.css`에 포함되며, `scheduler.skin`/`scheduler.setSkin()`으로 선택됩니다. 자세한 내용은 [Migration guide](migration.md)를 확인하십시오. -코어 파일: [JS](https://cdn.dhtmlx.com/scheduler/4.3/sources/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/4.3/sources/skins/dhtmlxscheduler.css) +비압축 스킨 파일: -스킨: [Terrace](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_contrast_white.css). +- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_terrace.css +- Flat: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_flat.css +- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_contrast_black.css +- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_contrast_white.css +- Material: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_material.css \ No newline at end of file diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/guides/configuration.md b/i18n/ko/docusaurus-plugin-content-docs/current/guides/configuration.md index 8b89e288..7d46a6c2 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/guides/configuration.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/guides/configuration.md @@ -7,8 +7,8 @@ sidebar_label: "일반 설정 안내" 스케줄러의 외관을 사용자 정의하려면, 라이브러리는 세 가지 주요 객체를 제공합니다: --
scheduler.config - 날짜, 스케일, 컨트롤 등 다양한 옵션을 설정할 수 있습니다. -- scheduler.templates - 날짜, 제목, 툴팁의 포맷 및 스타일링을 위한 템플릿을 제공합니다. +- [scheduler.config](api/api_overview.md#scheduler-properties) - 날짜, 스케일, 컨트롤 등 다양한 옵션을 설정할 수 있습니다. +- [scheduler.templates](api/api_overview.md#scheduler-templates) - 날짜, 제목, 툴팁의 포맷 및 스타일링을 위한 템플릿을 제공합니다. - [scheduler.xy](api/other/xy.md) - 다양한 스케줄러 요소의 크기를 정의하는 설정입니다. 또한, dhtmlxScheduler는 컴포넌트의 기능을 확장하는 [여러 확장 기능](#extensions)을 포함하고 있습니다. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/guides/multiuser-live-updates.md b/i18n/ko/docusaurus-plugin-content-docs/current/guides/multiuser-live-updates.md index 9b0ed311..155d2310 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/guides/multiuser-live-updates.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/guides/multiuser-live-updates.md @@ -365,4 +365,4 @@ remoteEvents.on({ "value":{"type":"custom-action","value":value}}} ~~~ -이 가이드는 DHTMLX Scheduler에서 실시간 업데이트를 구현하고 사용자 정의하는 기초를 제공합니다. 전체 예제는 [GitHub 저장소](https://github.com/DHTMLX/scheduler-multiuser-backend-demo/.를 참고하십시오. \ No newline at end of file +이 가이드는 DHTMLX Scheduler에서 실시간 업데이트를 구현하고 사용자 정의하는 기초를 제공합니다. 전체 예제는 [GitHub 저장소](https://github.com/DHTMLX/scheduler-multiuser-backend-demo/).를 참고하십시오. \ No newline at end of file diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md b/i18n/ko/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md index 7064fdbe..a57c112c 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md @@ -35,7 +35,7 @@ description: "OAuth 2.0 및 Google Calendar API v3를 사용하는 Node.js + Exp ## 데모 저장소 이 가이드와 일치하는 완전한 작동 프로젝트는 GitHub에서 확인할 수 있습니다: -- https://github.com/dhtmlx/scheduler-google-auth-demo +- https://github.com/dhtmlx/scheduler-google-calendar-demo 가이드는 핵심 단계와 중요한 통합 코드를 설명합니다. 저장소는 “실행 가능한 전체 참조”입니다. @@ -50,8 +50,8 @@ description: "OAuth 2.0 및 Google Calendar API v3를 사용하는 Node.js + Exp - 저장소를 클론합니다: ~~~bash title="Terminal" -git clone https://github.com/dhtmlx/scheduler-google-auth-demo.git -cd scheduler-google-auth-demo +git clone https://github.com/dhtmlx/scheduler-google-calendar-demo.git +cd scheduler-google-calendar-demo ~~~ 프로젝트가 private 레지스트리에서 `@dhx/*` 패키지를 설치한다면 npm을 구성하십시오: @@ -164,7 +164,7 @@ http://localhost:3000 일반적인 구조: ~~~text title="Project structure" -scheduler-google-auth-demo/ +scheduler-google-calendar-demo/ client/ index.ejs main.ts diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md b/i18n/ko/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md new file mode 100644 index 00000000..8c3013dd --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md @@ -0,0 +1,462 @@ +--- +title: 리액트 스케줄러와 Starhive 통합 +sidebar_label: Starhive 빠른 시작 +description: "Next.js API 경로를 통해 DHTMLX React Scheduler를 Starhive NoSQL 백엔드에 연결합니다." +--- + +# 리액트 스케줄러와 Starhive 통합 + +이 자습서는 **React Scheduler**를 **Starhive** NoSQL 백엔드에 Next.js Route Handlers를 통해 연결합니다. Starhive는 타입이 지정된 스키마와 생성된 TypeScript 클라이언트를 제공하므로 API 계층은 최소화됩니다: 이벤트와 리소스를 로드하는 하나의 엔드포인트와 생성/수정/삭제를 처리하는 또 다른 엔드포인트가 있습니다. + +다음과 같은 구성을 구축합니다: + +- 클라이언트 컴포넌트에 Scheduler를 호스팅하는 Next.js 페이지 +- `/api/load` - 첫 렌더링 시 Starhive에서 이벤트와 리소스를 가져옵니다 +- `/api/event` (POST) 및 `/api/event/[id]` (PUT, DELETE) - Scheduler의 `dataBridge`가 사용하는 쓰기 경로 + +:::note +전체 소스 코드는 [GitHub에서 이용 가능](https://github.com/DHTMLX/react-scheduler-starhive-demo)합니다. +::: + +## 전제 조건 + +- Next.js + React + TypeScript 기초 지식 +- Node.js 18+ +- Starhive 계정(30일 체험으로 충분) + +## 1단계. 프로젝트 생성 + +```bash +npx create-next-app@latest react-scheduler-starhive-demo +cd react-scheduler-starhive-demo +``` + +React Scheduler를 [React Scheduler 설치 가이드](integrations/react/installation.md)에 따라 설치합니다. 평가용으로: + +```bash +npm install @dhtmlx/trial-react-scheduler +``` + +이미 Professional 패키지를 사용 중이라면 명령 및 가져오기에 있는 `@dhtmlx/trial-react-scheduler`를 `@dhx/react-scheduler`로 바꿉니다. + +생성된 Starhive TypeScript 클라이언트의 피어 의존성이 필요한 경우도 있으므로 `axios`도 필요합니다. + +```bash +npm install axios +``` + +## 2단계. Starhive 공간 설정 + +로그인 후 우측 상단 모서리에 있는 **+ Create**를 클릭하고 공간 이름을 `Scheduler`로 설정합니다. + +공간 내부에서 두 가지 타입을 만듭니다: `Resources`와 `Events`. Resources는 타임라인의 행을 보유하고(팀, 사람, 방 등), Events는 하나의 Resources를 참조합니다. + +다음 속성을 **+ Attribute** 버튼을 통해 추가합니다. Starhive는 각 항목의 `id`를 자동으로 생성하므로 직접 선언할 필요가 없습니다. + +**Resources type** + +| Field | Type | +| ------- | ---- | +| `label` | Text | + +**Events type** + +| Field | Type | +| ------------- | -------------------------- | +| `text` | Text | +| `start_date` | Date & Time | +| `end_date` | Date & Time | +| `resource_id` | Reference → Resources | + +## 3단계. 샘플 데이터 가져오기 + +`scheduler_resources.csv`를 생성합니다: + +```csv +label +"Frontend Team" +"Backend Team" +"QA Team" +"DevOps" +"Security Team" +``` + +그리고 `scheduler_events.csv`를 생성합니다: + +```csv +text,start_date,end_date,resource_id +"Development","2026-04-01T08:00:00","2026-04-01T10:30:00","Frontend Team" +"Code Review","2026-04-01T09:00:00","2026-04-01T11:30:00","Backend Team" +"QA Testing","2026-04-01T10:00:00","2026-04-01T13:00:00","QA Team" +"Deployment","2026-04-01T11:00:00","2026-04-01T13:30:00","DevOps" +"Incident Response","2026-04-01T12:00:00","2026-04-01T15:00:00","DevOps" +"Maintenance Window","2026-04-01T08:30:00","2026-04-01T11:00:00","Backend Team" +"Security Scan","2026-04-01T13:00:00","2026-04-01T15:30:00","Security Team" +``` + +Starhive UI에서 각 파일의 타입을 열고 **CSV import**를 클릭합니다. + +## 4단계. 스키마 생성 및 복사 + +**Settings → API Connectors**로 이동합니다. `Scheduler` 공간을 선택하고 언어를 TypeScript로 설정한 다음 **Generate**, 그리고 **Download**를 클릭합니다. + +압축을 풀고 `project/src/io/` 아래의 `starhive` 폴더를 찾은 뒤, Next.js 프로젝트의 `lib/starhive/`로 복사합니다. 생성된 파일은 작업공간별 UUID를 포함하고 있어 스키마가 변경되거나 워크스페이스를 전환할 때마다 이 단계를 반복해야 합니다. + +:::note +작성 시점의 Starhive TypeScript 생성기는 엄격한 TypeScript를 통과하지 않는 출력(`Sla.ts` 참조 누락, 인라인 `AttributeVisitor` 리터럴의 구현 누락, `client.request` 호출이 `any`로 타입된 필드에 대해 발생하는 TS2347 등)을 만들 수 있습니다. 보조 데모 저장소에는 이러한 문제를 해결하기 위한 세 가지 최소 패치가 포함되어 있습니다; [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/)에서 차이점을 확인하고 스키마를 재생성할 때마다 동일한 패치를 다시 적용하십시오. Starhive가 수정 사항을 공개할 때까지 계속 적용합니다. +::: + +## 5단계. Starhive 클라이언트 구성 + +`lib/starhiveClient.ts`를 만듭니다: + +```ts title="lib/starhiveClient.ts" +import { StarhiveClient } from "./starhive/client/StarhiveClient"; +import { JSON_DECODERS } from "./starhive/schema/JsonDecoders"; + +let starhiveClient: StarhiveClient | null = null; + +export function getStarhiveClient() { + if (starhiveClient) return starhiveClient; + + const workspaceId = process.env.STARHIVE_WORKSPACE_ID; + const apiKey = process.env.STARHIVE_API_TOKEN; + + if (!workspaceId || !apiKey) { + throw new Error("Missing Starhive configuration (workspaceId or API token)"); + } + + starhiveClient = new StarhiveClient(apiKey, workspaceId, JSON_DECODERS); + return starhiveClient; +} +``` + +함수는 모듈 범위에서 클라이언트를 캐시하므로 라우트 핸들러가 하나의 인스턴스를 공유합니다. + +루트 프로젝트에 `.env.local`(또는 `.env`)를 추가합니다: + +```env title=".env.local" +STARHIVE_API_TOKEN=your-api-token +STARHIVE_WORKSPACE_ID=your-workspace-id +``` + +API 토큰은 설정 → 개인 액세스 토큰에서 생성합니다. 워크스페이스 ID는 `https://app.starhive.com/workspace//home` 경로의 일부입니다. + +## 6단계. 이벤트와 리소스 불러오기 + +`app/api/load/route.ts`를 생성합니다: + +```ts title="app/api/load/route.ts" +import { NextResponse } from 'next/server'; +import { getStarhiveClient } from '@/lib/starhiveClient'; +import { Events } from '@/lib/starhive/schema/Events'; +import { Resources } from '@/lib/starhive/schema/Resources'; + +function normalizeEvents(events: Events[]) { + return events.map(ev => ({ + id: ev.getId() || '', + text: ev.getText(), + start_date: ev.getStartDate(), + end_date: ev.getEndDate(), + resource_id: ev.getResourceId()?.[0] || null, + })); +} + +export async function GET() { + try { + const client = getStarhiveClient(); + const [events, resources] = await Promise.all([ + client.search(Events.TYPE_ID, ""), + client.search(Resources.TYPE_ID, "") + ]); + + return NextResponse.json({ + events: normalizeEvents(events.result), + resources: resources.result.map((r) => ({ + key: r.getId(), + label: r.getLabel(), + })), + }); + } catch (error) { + return NextResponse.json({ error: 'Failed to load data' }, { status: 500 }); + } +} +``` + +`normalizeEvents`는 각 Starhive 객체를 React Scheduler가 기대하는 형태로 평면화합니다: `{ id, text, start_date, end_date, resource_id }`. Resources는 `{ key, label }`로 축약되며 이는 타임라인 뷰의 `y_unit`에서 소비됩니다. + +개발 서버를 시작한 후 `http://localhost:3000/api/load`를 방문해 JSON 형태를 확인합니다. + +## 7단계. Scheduler 렌더링 및 이벤트 불러오기 + +`app/page.tsx`를 생성합니다: + +```tsx title="app/page.tsx" +'use client'; + +import { useEffect, useMemo, useState } from 'react'; +import ReactScheduler, { + type Event, + type SchedulerViewsProp, +} from '@dhtmlx/trial-react-scheduler'; +import '@dhtmlx/trial-react-scheduler/dist/react-scheduler.css'; + +type Resource = { key: string; label: string }; + +export default function Scheduler() { + const [resources, setResources] = useState([]); + const [events, setEvents] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetch('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/api/load') + .then((response) => response.json()) + .then((data) => { + setResources(data.resources); + setEvents(data.events); + }) + .catch((error) => { + console.error('Failed to load resources data:', error); + }) + .finally(() => { + setLoading(false); + }); + }, []); + + const views: SchedulerViewsProp = useMemo( + () => ({ + timeline: [ + { + name: "timeline", + x_unit: "hour", + x_date: "%H:%i", + x_step: 1, + x_start: 8, + x_size: 13, + x_length: 13, + event_dy: 50, + event_min_dy: 50, + y_property: "resource_id", + render: "bar", + y_unit: resources, + }, + ], + }), + [resources] + ); + + if (loading) { + return
Loading...
; + } + + return ( +
+ +
+ ); +} +``` + +로딩 플래그는 이벤트 수를 확인하는 것보다 Scheduler가 비어 있어도 로딩 화면에 머물지 않도록 하는 것이 좋습니다. + +`npm run dev`를 실행하면 imported 이벤트가 리소스별로 그룹화된 타임라인이 표시됩니다. + +## 8단계. CRUD 엔드포인트 구현 + +Scheduler의 `dataBridge`는 생성은 POST, 업데이트는 PUT, 삭제는 DELETE의 세 엔드포인트를 호출하며 다음과 같은 응답 형태를 기대합니다: + +| HTTP 메서드 | 엔드포인트 | 응답 | +| ----------- | ------------------------- | ------------------------------ | +| `GET` | `/api/load` | `{ events, resources }` | +| `POST` | `/api/event` | `{ action: "inserted", tid: id }` | +| `PUT` | `/api/event/{event_id}` | `{ action: "updated" }` | +| `DELETE` | `/api/event/{event_id}` | `{ action: "deleted" }` | + +POST 핸들러를 `app/api/event/route.ts`에 만듭니다: + +```ts title="app/api/event/route.ts" +import { NextRequest, NextResponse } from 'next/server'; +import { getStarhiveClient } from '@/lib/starhiveClient'; +import { Events } from '@/lib/starhive/schema/Events'; + +export async function POST(req: NextRequest) { + try { + const { text, start_date, end_date, resource_id } = await req.json(); + const client = getStarhiveClient(); + + const event = Events.builder() + .text(text) + .startDate(new Date(start_date)) + .endDate(new Date(end_date)) + .resourceId([resource_id]) + .build(); + + const result = await client.createObject(event); + return NextResponse.json({ action: 'inserted', tid: result.getId() }); + } catch (error) { + return NextResponse.json({ error: 'Create failed' }, { status: 500 }); + } +} +``` + +그리고 동적 PUT/DELETE 핸들러를 `app/api/event/[id]/route.ts`에 추가합니다: + +```ts title="app/api/event/[id]/route.ts" +import { NextRequest, NextResponse } from 'next/server'; +import { Events } from "@/lib/starhive/schema/Events"; +import { getStarhiveClient } from "@/lib/starhiveClient"; + +export async function PUT( + request: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + try { + const { id } = await params; + const body = await request.json(); + const client = getStarhiveClient(); + + const existingEvent = await client.getObject(id, Events.TYPE_ID); + if (!existingEvent) { + return NextResponse.json({ error: 'Event not found' }, { status: 404 }); + } + + const updatedEvent = Events.builder() + .id(id) + .text(body.text) + .startDate(new Date(body.start_date)) + .endDate(new Date(body.end_date)) + .resourceId([body.resource_id]) + .build(); + + await client.updateObject(updatedEvent); + return NextResponse.json({ action: 'updated' }); + } catch (error: any) { + console.error('Update error:', error); + return NextResponse.json( + { error: 'Update failed', details: error.message }, + { status: 500 } + ); + } +} + +export async function DELETE( + request: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + try { + const { id } = await params; + const client = getStarhiveClient(); + await client.deleteObjectsInBulk([id]); + + return NextResponse.json({ action: 'deleted' }); + } catch (error: any) { + console.error('Delete error:', error); + return NextResponse.json( + { error: 'Delete failed', details: error.message }, + { status: 500 } + ); + } +} +``` + +:::note +Next.js 15+에서 동적 경로 핸들러의 `params` 인수는 `Promise`입니다. 값을 읽기 전에 반드시 `Promise<{...}>`로 타입을 지정하고 `await`하십시오. 일부 설정에서 `Promise<>` 래퍼를 생략하면 컴파일되지만 엄격 모드에서 실패합니다. +::: + +## 9단계. dataBridge 연결 + +클라이언트 측의 작은 헬퍼를 `services/scheduler.ts`에 생성합니다: + +```ts title="services/scheduler.ts" +import type { Event } from '@dhtmlx/trial-react-scheduler'; + +async function request(url: string, options: RequestInit): Promise { + const res = await fetch(url, options); + if (!res.ok) throw new Error(`Request failed: ${res.status}`); + return res.json(); +} + +export function createEvent(event: Event) { + return request('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/api/event', { + method: 'POST', + body: JSON.stringify(event), + headers: { 'Content-Type': 'application/json' }, + }); +} + +export function updateEvent(event: Event) { + return request(`/api/event/${event.id}`, { + method: 'PUT', + body: JSON.stringify(event), + headers: { 'Content-Type': 'application/json' }, + }); +} + +export function deleteEvent(id: string | number) { + return request(`/api/event/${id}`, { + method: 'DELETE', + }); +} +``` + +그다음 페이지에 dataBridge를 연결합니다. imports를 추가하고 ``에 `data` 속성을 추가합니다: + +```tsx title="app/page.tsx" +import { createEvent, deleteEvent, updateEvent } from '@/services/scheduler'; + +// Scheduler 컴포넌트 내부: +const dataBridge = useMemo(() => ({ + save: (entity: string, action: string, payload: Event, id: string | number) => { + if (entity !== "event") return; + + switch (action) { + case "update": + return updateEvent(payload); + case "create": + return createEvent(payload); + case "delete": + return deleteEvent(id); + default: + console.warn(`Unknown action: ${action}`); + return; + } + }, +}), []); + +// 컴포넌트에 데이터 브리지 전달: + +``` + +테스트 방법 + +```bash +npm run dev +``` + +브라우저에서 http://localhost:3000 를 열고 이벤트를 드래그로 새 시간으로 옮기고, 텍스트를 편집하고 하나를 삭제해 보십시오. 각 변경 사항은 Starhive UI의 `Events` 타입 아래 즉시 반영됩니다. + +## Starhive 통합에 대한 참고사항 + +- 서버 측 자격 증명만 사용합니다. `STARHIVE_API_TOKEN`과 `STARHIVE_WORKSPACE_ID`는 Route Handler 내부에서 읽히며 브라우저 번들에 노출되지 않습니다. 토큰을 Client Component로 올리거나 `NEXT_PUBLIC_*` 변수로 노출하지 마십시오. +- 스키마 재생성. Starhive의 속성을 추가하거나 이름을 바꿀 때는 TypeScript 스키마를 재생성하고 `lib/starhive/`를 교체합니다. 문제가 발생하면 [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/) 경로의 패치를 재적용하십시오. +- 실시간 동기화 없음. Firebase 통합과 달리 Starhive는 연결된 클라이언트에 변경 내용을 푸시하지 않습니다. 여러 사용자가 동일한 Scheduler를 편집하면 서로의 변경 사항이 덮어씌워질 수 있습니다. 다중 사용자 시나리오의 경우 클라이언트 측 폴링을 추가하거나 Starhive 웹훅을 사용해 SSE/웹소켓으로 무효화 이벤트를 보내고 원격 변경 시 `events` 상태를 새로고침하십시오. +- 대용량 데이터 세트의 동적 로딩. `/api/load` 경로는 워크스페이스의 모든 이벤트를 로드합니다. 프로덕션에서는 GET 핸들러에서 `from` / `to` 쿼리 매개변수를 받아 `start_date` / `end_date`를 필터링하고 클라이언트에서 `scheduler.setLoadMode("day")`를 호출하여 보이는 범위의 데이터만 가져오도록 하십시오. +- 참조 속성은 배열을 담습니다. `Events.getResourceId()`는 `string[] | undefined`를 반환합니다. Starhive의 참조 속성은 다-valued이기 때문입니다. 데모는 `?.[0] || null`로 평탄화합니다. 이벤트가 여러 리소스에 속하도록 허용하는 경우 타임라인 뷰의 `y_property` 해상도와 평탄화/빌더 호출을 이에 맞게 조정하십시오. + +## 관련 페이지 + +- [데이터 바인딩 및 상태 관리 기초](integrations/react/state/state-management-basics.md) +- [React Scheduler 개요](integrations/react/overview.md#bindingdata) +- [서버 통합](guides/server-integration.md) +- [React Scheduler와 Firebase 통합](integrations/react/firebase-integration.md) - 실시간 동기화의 형제 패턴 \ No newline at end of file diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md b/i18n/ko/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md index a659b1d9..4d8a4ca8 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md @@ -15,7 +15,7 @@ description: Valtio 프록시 저장소로 React Scheduler의 상태를 관리 - 스냅샷 기반 undo/redo(이벤트 + 구성) :::note -전체 소스 코드는 [GitHub에서 확인 가능](https://github.com/nicetip/react-scheduler-valtio-starter). +전체 소스 코드는 [GitHub에서 확인 가능](https://github.com/DHTMLX/react-scheduler-valtio-starter). ::: ## Prerequisites diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md b/i18n/ru/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md index 9d4241a4..6cf979ce 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md +++ b/i18n/ru/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md @@ -1,63 +1,89 @@ --- title: "Полный список CDN-ссылок" -sidebar_label: "Полный список CDN-ссылок" +sidebar_label: "CDN-ссылки" --- # Полный список CDN-ссылок -В этой статье представлен полный набор ссылок для подключения функционала Scheduler через CDN. Каждый раздел посвящён определённой версии Scheduler: +В этой статье перечислены CDN-ссылки для подключения **dhtmlxScheduler** к вашему приложению. -- Основные файлы - *dhtmlxscheduler.js* и *dhtmlxscheduler.css*, содержащие основные возможности -- Скины - ссылки на все доступные [скины](guides/skins.md) +Scheduler состоит из двух основных файлов: -:::note -Начиная с версии v6.0, все [расширения](guides/extensions-list.md) включены в файл *dhtmlxscheduler.js*. Если вы используете dhtmlxScheduler 5.3 или более раннюю версию, ознакомьтесь со статьёй по [миграции](migration.md#53---60). -::: +- **JavaScript:** `dhtmlxscheduler.js` +- **Стили:** `dhtmlxscheduler.css` -## Последняя версия Scheduler -Чтобы использовать последнюю версию библиотеки, укажите путь **https://cdn.dhtmlx.com/scheduler/edge/...** +## Последняя версия Scheduler (edge) -Основные файлы: [JS](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.css) +Используйте: -Скины: [Terrace](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_contrast_white.css). +`https://cdn.dhtmlx.com/scheduler/edge/...` -## Последняя версия Scheduler, не сжатая +### Основные файлы -Для получения не сжатых исходников последней версии используйте путь **https://cdn.dhtmlx.com/scheduler/edge/sources/...** +- JS: https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.css -Основные файлы: [JS](https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.css) -Скины: [Terrace](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_contrast_white.css). +## Последняя версия Scheduler (edge), Несжатая -## Конкретная версия Scheduler +Используйте: -Чтобы подключить определённую версию библиотеки, укажите путь **https://cdn.dhtmlx.com/scheduler/[version_number]/...** +`https://cdn.dhtmlx.com/scheduler/edge/sources/...` -Основные файлы: [JS](https://cdn.dhtmlx.com/scheduler/4.3/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/4.3/dhtmlxscheduler.css) +### Основные файлы -Скины: [Terrace](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_contrast_white.css). +- JS: https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.css -## Конкретная версия Scheduler, не сжатая -Чтобы использовать не сжатые исходники выбранной версии, укажите путь **https://cdn.dhtmlx.com/scheduler/[version_number]/sources/...** +## Определённая версия Scheduler -Основные файлы: [JS](https://cdn.dhtmlx.com/scheduler/4.3/sources/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/4.3/sources/skins/dhtmlxscheduler.css) +Используйте: -Скины: [Terrace](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_contrast_white.css). +`https://cdn.dhtmlx.com/scheduler/[version_number]/...` + +Значение `[version_number]` задаёт версию пакета в формате `major.minor`, например **7.0**, **6.0**, **5.3** и т. д. Наш CDN всегда предоставляет последнюю патч-версию для каждого выпуска major/minor. + +### Основные файлы + +- JS: https://cdn.dhtmlx.com/scheduler/7.0/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/7.0/dhtmlxscheduler.css + +### Скины (только для v6.0 и более ранних) + +Отдельные файлы скинов доступны в версиях v6.0 и ранее. +Начиная с v7.0, все скины входят в `dhtmlxscheduler.css` и выбираются через `scheduler.skin`/`scheduler.setSkin()`, пожалуйста, ознакомьтесь с [Руководство по миграции](migration.md) для получения более подробной информации. + +- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_terrace.css +- Flat: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_flat.css +- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_contrast_black.css +- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_contrast_white.css +- Material: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_material.css + +## Определённая версия Scheduler, Несжатая + +Используйте: + +`https://cdn.dhtmlx.com/scheduler/[version_number]/sources/...` + +Значение `[version_number]` задаёт версию пакета в формате `major.minor`, например **7.0**, **6.0**, **5.3** и т. д. Наш CDN всегда предоставляет последнюю патч-версию для каждого выпуска major/minor. + +### Основные файлы + +- JS: https://cdn.dhtmlx.com/scheduler/7.0/sources/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/7.0/sources/dhtmlxscheduler.css + + +### Скины (только для v6.0 и более ранних) + +Отдельные файлы скинов доступны в версиях v6.0 и ранее. +Начиная с v7.0, все скины входят в `dhtmlxscheduler.css` и выбираются через `scheduler.skin`/`scheduler.setSkin()`, пожалуйста, ознакомьтесь с [Руководство по миграции](migration.md) для получения более подробной информации. + +Несжатые файлы скинов: + +- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_terrace.css +- Flat: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_flat.css +- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_contrast_black.css +- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_contrast_white.css +- Material: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_material.css \ No newline at end of file diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md b/i18n/ru/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md index af471caa..4cba6ec1 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md +++ b/i18n/ru/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md @@ -35,7 +35,7 @@ description: "Реализуйте интеграцию Node.js + Express, ко ## Демонстрационный репозиторий Полный рабочий проект, соответствующий данному руководству, доступен на GitHub: -- https://github.com/dhtmlx/scheduler-google-auth-demo +- https://github.com/dhtmlx/scheduler-google-calendar-demo Руководство объясняет ключевые шаги и демонстрирует важный код интеграции. Репозиторий является «полной рабочей ссылкой». @@ -50,8 +50,8 @@ description: "Реализуйте интеграцию Node.js + Express, ко - Клонировать репозиторий: ~~~bash title="Terminal" -git clone https://github.com/dhtmlx/scheduler-google-auth-demo.git -cd scheduler-google-auth-demo +git clone https://github.com/dhtmlx/scheduler-google-calendar-demo.git +cd scheduler-google-calendar-demo ~~~ Если ваш проект устанавливает пакеты `@dhx/*` из частного реестра, настройте npm: @@ -164,7 +164,7 @@ http://localhost:3000 Типичная структура: ~~~text title="Project structure" -scheduler-google-auth-demo/ +scheduler-google-calendar-demo/ client/ index.ejs main.ts diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md b/i18n/ru/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md new file mode 100644 index 00000000..3ab5e46f --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md @@ -0,0 +1,462 @@ +--- +title: Интеграция React Scheduler и Starhive +sidebar_label: Быстрый старт Starhive +description: "Подключение DHTMLX React Scheduler к NoSQL-бэкенду Starhive через маршруты API Next.js." +--- + +# Интеграция React Scheduler и Starhive + +Этот учебник подключает **React Scheduler** к NoSQL-бэкенду **Starhive** через обработчики маршрутов Next.js. Starhive предоставляет типизированную схему и сгенерированный клиент TypeScript, поэтому уровень API остаётся минимальным: один конечный пункт загружает события и ресурсы, другой обрабатывает создание / обновление / удаление. + +Вы создадите: + +- страницу Next.js, которая размещает Scheduler в клиентском компоненте +- `/api/load` - получает события и ресурсы из Starhive при первом рендере +- `/api/event` (POST) и `/api/event/[id]` (PUT, DELETE) - пути записи, используемые Scheduler `dataBridge` + +:::note +Полный исходный код доступен на GitHub (ссылка в оригинальном источнике). +::: + +## Требования + +- основы Next.js + React + TypeScript +- Node.js 18+ +- учетная запись [Starhive](https://starhive.com/) (30-дневная пробная версия подходит) + +## Шаг 1. Создайте проект + +```bash +npx create-next-app@latest react-scheduler-starhive-demo +cd react-scheduler-starhive-demo +``` + +Установите React Scheduler согласно руководству по установке [React Scheduler](integrations/react/installation.md). Для оценки: + +```bash +npm install @dhtmlx/trial-react-scheduler +``` + +Если вы уже используете пакет Professional, замените `@dhtmlx/trial-react-scheduler` на `@dhx/react-scheduler` в командах и импортируемых элементах. + +Также потребуется `axios` — это зависимость-партнёр сгенерированного клиентского Starhive TypeScript. + +```bash +npm install axios +``` + +## Шаг 2. Настройте пространство Starhive + +После входа в систему нажмите **+ Create** в правом верхнем углу и назовите пространство как `Scheduler`. + +Внутри пространства создайте два типа: `Resources` и `Events`. Resources хранят строки временной шкалы (команды, люди, комнаты и т. п.). Events ссылаются на один Resource. + +Добавьте следующие атрибуты через кнопку **+ Attribute**. Starhive автоматически создаёт `id` для каждого элемента, поэтому объявлять его не нужно. + +**Resources type** + +| Поле | Тип | +| ------- | ---- | +| `label` | Text | + +**Events type** + +| Поле | Тип | +| ------------- | -------------------------- | +| `text` | Text | +| `start_date` | Date & Time | +| `end_date` | Date & Time | +| `resource_id` | Reference → Resources | + +## Шаг 3. Импорт данных образца + +Создайте `scheduler_resources.csv`: + +```csv +label +"Frontend Team" +"Backend Team" +"QA Team" +"DevOps" +"Security Team" +``` + +И `scheduler_events.csv`: + +```csv +text,start_date,end_date,resource_id +"Development","2026-04-01T08:00:00","2026-04-01T10:30:00","Frontend Team" +"Code Review","2026-04-01T09:00:00","2026-04-01T11:30:00","Backend Team" +"QA Testing","2026-04-01T10:00:00","2026-04-01T13:00:00","QA Team" +"Deployment","2026-04-01T11:00:00","2026-04-01T13:30:00","DevOps" +"Incident Response","2026-04-01T12:00:00","2026-04-01T15:00:00","DevOps" +"Maintenance Window","2026-04-01T08:30:00","2026-04-01T11:00:00","Backend Team" +"Security Scan","2026-04-01T13:00:00","2026-04-01T15:30:00","Security Team" +``` + +В интерфейсе Starhive откройте тип и нажмите CSV импорт для каждого файла. + +## Шаг 4. Сгенерируйте и скопируйте схему + +Перейдите в **Settings → API Connectors**. Выберите пространство `Scheduler`, укажите язык TypeScript, нажмите **Generate**, затем **Download**. + +Распакуйте архив, найдите папку `starhive` в `project/src/io/` и скопируйте её в `lib/starhive/` в вашем проекте Next.js. Сгенерированные файлы содержат рабочие UUID, поэтому повторяйте этот шаг каждый раз, когда схема меняется или вы переключаетесь между рабочими пространствами. + +:::note +На момент написания генератор TypeScript Starhive выводит код, который не проходит строгий TypeScript: отсутствует ссылка на `Sla.ts`, реализация `visitSlaAttribute` в литерале `AttributeVisitor`, и вызов `client.request` против поля типа `any` (TS2347). Со стороны демонстрационного репозитория есть три минимальных патча, которые решают эти проблемы; смотрите [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/) для диффов. Повторно применяйте те же патчи при повторной генерации схемы, пока Starhive не выпустит исправление. +::: + +## Шаг 5. Настройте клиента Starhive + +Создайте `lib/starhiveClient.ts`: + +```ts title="lib/starhiveClient.ts" +import { StarhiveClient } from "./starhive/client/StarhiveClient"; +import { JSON_DECODERS } from "./starhive/schema/JsonDecoders"; + +let starhiveClient: StarhiveClient | null = null; + +export function getStarhiveClient() { + if (starhiveClient) return starhiveClient; + + const workspaceId = process.env.STARHIVE_WORKSPACE_ID; + const apiKey = process.env.STARHIVE_API_TOKEN; + + if (!workspaceId || !apiKey) { + throw new Error("Missing Starhive configuration (workspaceId or API token)"); + } + + starhiveClient = new StarhiveClient(apiKey, workspaceId, JSON_DECODERS); + return starhiveClient; +} +``` + +Функция кэширует клиент на уровне модуля, чтобы обработчики маршрутов использовали один экземпляр. + +Добавьте `.env.local` (или `.env`) в корень проекта: + +```env title=".env.local" +STARHIVE_API_TOKEN=ваш-api-токен +STARHIVE_WORKSPACE_ID=ваш-id-рабочего-пространства +``` + +Сгенерируйте токен API в разделе **Settings → Personal access tokens**. ID рабочего пространства — это фрагмент пути в `https://app.starhive.com/workspace//home`. + +## Шаг 6. Загружайте события и ресурсы + +Создайте `app/api/load/route.ts`: + +```ts title="app/api/load/route.ts" +import { NextResponse } from 'next/server'; +import { getStarhiveClient } from '@/lib/starhiveClient'; +import { Events } from '@/lib/starhive/schema/Events'; +import { Resources } from '@/lib/starhive/schema/Resources'; + +function normalizeEvents(events: Events[]) { + return events.map(ev => ({ + id: ev.getId() || '', + text: ev.getText(), + start_date: ev.getStartDate(), + end_date: ev.getEndDate(), + resource_id: ev.getResourceId()?.[0] || null, + })); +} + +export async function GET() { + try { + const client = getStarhiveClient(); + const [events, resources] = await Promise.all([ + client.search(Events.TYPE_ID, ""), + client.search(Resources.TYPE_ID, "") + ]); + + return NextResponse.json({ + events: normalizeEvents(events.result), + resources: resources.result.map((r) => ({ + key: r.getId(), + label: r.getLabel(), + })), + }); + } catch (error) { + return NextResponse.json({ error: 'Не удалось загрузить данные' }, { status: 500 }); + } +} +``` + +Функция `normalizeEvents` превращает каждый объект Starhive в форму, которую ожидает React Scheduler: `{ id, text, start_date, end_date, resource_id }`. Ресурсы сводятся к `{ key, label }`, что и требуется для `y_unit` у представления временной шкалы. + +После запуска dev-сервера перейдите по адресу `http://localhost:3000/api/load`, чтобы проверить форму JSON. + +## Шаг 7. Рендеринг Scheduler и загрузка событий + +Создайте `app/page.tsx`: + +```tsx title="app/page.tsx" +'use client'; + +import { useEffect, useMemo, useState } from 'react'; +import ReactScheduler, { + type Event, + type SchedulerViewsProp, +} from '@dhtmlx/trial-react-scheduler'; +import '@dhtmlx/trial-react-scheduler/dist/react-scheduler.css'; + +type Resource = { key: string; label: string }; + +export default function Scheduler() { + const [resources, setResources] = useState([]); + const [events, setEvents] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetch('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/api/load') + .then((response) => response.json()) + .then((data) => { + setResources(data.resources); + setEvents(data.events); + }) + .catch((error) => { + console.error('Не удалось загрузить данные ресурсов:', error); + }) + .finally(() => { + setLoading(false); + }); + }, []); + + const views: SchedulerViewsProp = useMemo( + () => ({ + timeline: [ + { + name: "timeline", + x_unit: "hour", + x_date: "%H:%i", + x_step: 1, + x_start: 8, + x_size: 13, + x_length: 13, + event_dy: 50, + event_min_dy: 50, + y_property: "resource_id", + render: "bar", + y_unit: resources, + }, + ], + }), + [resources] + ); + + if (loading) { + return
Loading...
; + } + + return ( +
+ +
+ ); +} +``` + +Флаг `loading` предпочтительнее проверки `events.length` или `resources.length`: рабочее пространство может действительно не содержать событий и тем не менее нужно отрисовать пустой Scheduler, а не показывать загрузчик. + +Запустите `npm run dev` — временная шкала появится вместе с импортированными событиями, сгруппированными по ресурсам. + +## Шаг 8. Реализуйте Endpoints CRUD + +Scheduler `dataBridge` вызывает три endpoint’а — POST для создания, PUT для обновления, DELETE для удаления — и ожидает определённые формы ответов: + +| HTTP-метод | Endpoint | Ответ | +| ----------- | ------------------------- | --------------------------------- | +| `GET` | `/api/load` | `{ events, resources }` | +| `POST` | `/api/event` | `{ action: "inserted", tid: id }` | +| `PUT` | `/api/event/{event_id}` | `{ action: "updated" }` | +| `DELETE` | `/api/event/{event_id}` | `{ action: "deleted" }` | + +Создайте обработчик POST по адресу `app/api/event/route.ts`: + +```ts title="app/api/event/route.ts" +import { NextRequest, NextResponse } from 'next/server'; +import { getStarhiveClient } from '@/lib/starhiveClient'; +import { Events } from '@/lib/starhive/schema/Events'; + +export async function POST(req: NextRequest) { + try { + const { text, start_date, end_date, resource_id } = await req.json(); + const client = getStarhiveClient(); + + const event = Events.builder() + .text(text) + .startDate(new Date(start_date)) + .endDate(new Date(end_date)) + .resourceId([resource_id]) + .build(); + + const result = await client.createObject(event); + return NextResponse.json({ action: 'inserted', tid: result.getId() }); + } catch (error) { + return NextResponse.json({ error: 'Create failed' }, { status: 500 }); + } +} +``` + +И динамические обработчики PUT/DELETE по адресу `app/api/event/[id]/route.ts`: + +```ts title="app/api/event/[id]/route.ts" +import { NextRequest, NextResponse } from 'next/server'; +import { Events } from "@/lib/starhive/schema/Events"; +import { getStarhiveClient } from "@/lib/starhiveClient"; + +export async function PUT( + request: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + try { + const { id } = await params; + const body = await request.json(); + const client = getStarhiveClient(); + + const existingEvent = await client.getObject(id, Events.TYPE_ID); + if (!existingEvent) { + return NextResponse.json({ error: 'Event not found' }, { status: 404 }); + } + + const updatedEvent = Events.builder() + .id(id) + .text(body.text) + .startDate(new Date(body.start_date)) + .endDate(new Date(body.end_date)) + .resourceId([body.resource_id]) + .build(); + + await client.updateObject(updatedEvent); + return NextResponse.json({ action: 'updated' }); + } catch (error: any) { + console.error('Update error:', error); + return NextResponse.json( + { error: 'Update failed', details: error.message }, + { status: 500 } + ); + } +} + +export async function DELETE( + request: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + try { + const { id } = await params; + const client = getStarhiveClient(); + await client.deleteObjectsInBulk([id]); + + return NextResponse.json({ action: 'deleted' }); + } catch (error: any) { + console.error('Delete error:', error); + return NextResponse.json( + { error: 'Delete failed', details: error.message }, + { status: 500 } + ); + } +} +``` + +:::note +В Next.js 15+ аргумент `params` у динамических обработчиков маршрутов является `Promise`. Всегда указывайте тип как `Promise<{...}>` и `await` его перед чтением сегментов — пропуск обёртки `Promise<>` в некоторых сборках может компилироваться, но не проходить строгий режим. +::: + +## Шаг 9. Подключите dataBridge + +Создайте небольшой клиентский помощник на стороне клиента в `services/scheduler.ts`: + +```ts title="services/scheduler.ts" +import type { Event } from '@dhtmlx/trial-react-scheduler'; + +async function request(url: string, options: RequestInit): Promise { + const res = await fetch(url, options); + if (!res.ok) throw new Error(`Request failed: ${res.status}`); + return res.json(); +} + +export function createEvent(event: Event) { + return request('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/api/event', { + method: 'POST', + body: JSON.stringify(event), + headers: { 'Content-Type': 'application/json' }, + }); +} + +export function updateEvent(event: Event) { + return request(`/api/event/${event.id}`, { + method: 'PUT', + body: JSON.stringify(event), + headers: { 'Content-Type': 'application/json' }, + }); +} + +export function deleteEvent(id: string | number) { + return request(`/api/event/${id}`, { + method: 'DELETE', + }); +} +``` + +Затем подключите `dataBridge` к странице. Обновите `app/page.tsx`, добавив импорты и свойство `data` у ``: + +```tsx title="app/page.tsx" +import { createEvent, deleteEvent, updateEvent } from '@/services/scheduler'; + +// внутри компонента Scheduler: +const dataBridge = useMemo(() => ({ + save: (entity: string, action: string, payload: Event, id: string | number) => { + if (entity !== "event") return; + + switch (action) { + case "update": + return updateEvent(payload); + case "create": + return createEvent(payload); + case "delete": + return deleteEvent(id); + default: + console.warn(`Unknown action: ${action}`); + return; + } + }, +}), []); + +// передайте его компоненту: + +``` + +## Протестируйте + +```bash +npm run dev +``` + +Откройте `http://localhost:3000`, перетащите событие в новое время, отредактируйте его текст и удалите одно. Каждое изменение должно немедленно отражаться в интерфейсе Starhive под типом `Events`. + +## Заметки по интеграции Starhive + +- **Серверные креденшлы только на сервере.** `STARHIVE_API_TOKEN` и `STARHIVE_WORKSPACE_ID` читаются внутри обработчиков маршрутов (`getStarhiveClient`); они не попадают в браузерный бандл. Не переносите клиент Starhive в Клиентский компонент и не публикуйте токен через переменные `NEXT_PUBLIC_*`. +- **Регенерация схемы.** Всякий раз, когда вы добавляете или переименовываете атрибуты в Starhive, регенерируйте TypeScript-схему и заменяйте `lib/starhive/`. Повторно применяйте патчи в [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/), если сборка `next build` жалуется на аналогичные upstream-проблемы. +- **Нет привязки к реальному времени.** В отличие от интеграции с Firebase, Starhive не отправляет изменения подключённым клиентам. Несколько пользователей, редактирующих один Scheduler, могут перезаписывать изменения друг друга. Для много-пользовательских сценариев добавляйте опрос на стороне клиента — или подключайте вебхуки Starhive для отправки уведомлений об инвалидации через SSE / WebSockets и обновляйте состояние `events` при удалённых изменениях. +- **Динамическая загрузка больших наборов данных.** Маршрут `/api/load` загружает каждое событие в рабочем пространстве. В продакшне можно принимать параметры запроса `from` / `to` в обработчике GET, фильтровать по `start_date` / `end_date` и вызывать `scheduler.setLoadMode("day")` на клиенте, чтобы подгружался только видимый диапазон. +- **Справочные атрибуты возвращают массивы.** `Events.getResourceId()` возвращает `string[] | undefined`, потому что ссылочные атрибуты Starhive могут быть мультивалентными. Демка разворачивает через `?.[0] || null`. Если вы разрешаете событиям принадлежать нескольким ресурсам, измените разрешение `y_property` у представления timeline и соответствующим образом обновите вызовы `normalize` / `builder`. + +## Связанные страницы + +- [Основы связывания данных и управления состоянием](integrations/react/state/state-management-basics.md) +- [Обзор React Scheduler](integrations/react/overview.md#bindingdata) +- [Серверная интеграция](guides/server-integration.md) +- [React Scheduler и интеграция с Firebase](integrations/react/firebase-integration.md) — соседняя схема с синхронизацией в реальном времени \ No newline at end of file diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md b/i18n/ru/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md index d100dfcf..b3a23323 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md +++ b/i18n/ru/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md @@ -15,7 +15,7 @@ description: Управляйте состоянием React Scheduler с пом - откат/повтор на основе снимков (события + конфигурация) :::note -Полный исходный код доступен [на GitHub](https://github.com/nicetip/react-scheduler-valtio-starter). +Полный исходный код доступен [на GitHub](https://github.com/DHTMLX/react-scheduler-valtio-starter). ::: ## Требования diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md b/i18n/zh/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md index 585f7c4b..0eb6e5d7 100644 --- a/i18n/zh/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md +++ b/i18n/zh/docusaurus-plugin-content-docs/current/guides/cdn-links-list.md @@ -5,61 +5,85 @@ sidebar_label: "CDN 链接完整列表" # CDN 链接完整列表 -本文为您提供了通过 CDN 引入 Scheduler 功能的完整链接集合。每个部分对应特定的 Scheduler 版本: +本文列出在应用中引入 **dhtmlxScheduler** 的 CDN 链接。 -- 核心文件 - 包含主要功能的 *dhtmlxscheduler.js* 和 *dhtmlxscheduler.css* 文件 -- 皮肤 - 所有可用 [皮肤](guides/skins.md) 的链接 +Scheduler 由两个核心文件组成: -:::note -从 v6.0 开始,所有 [扩展](/guides/extensions-list/) 都已集成进 *dhtmlxscheduler.js* 文件。如果您使用的是 dhtmlxScheduler 5.3 或更早版本,请参考 [迁移指南](migration.md#53---60)。 -::: +- **JavaScript:** `dhtmlxscheduler.js` +- **Styles:** `dhtmlxscheduler.css` -## 最新 Scheduler 版本 -如需使用最新版库,请将资源路径设置为 **https://cdn.dhtmlx.com/scheduler/edge/...** +## 最新 Scheduler 版本(edge) -核心文件: [JS](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.css) +使用: -皮肤: [Terrace](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_contrast_white.css)。 +`https://cdn.dhtmlx.com/scheduler/edge/...` -## 最新 Scheduler 版本,未压缩 +### 核心文件 -如需获取最新版未压缩源码,请使用路径 **https://cdn.dhtmlx.com/scheduler/edge/sources/...** +- JS: https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.css -核心文件: [JS](https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.css) -皮肤: [Terrace](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/edge/sources/skins/dhtmlxscheduler_contrast_white.css)。 +## 最新 Scheduler 版本(edge),未压缩 + +使用: + +`https://cdn.dhtmlx.com/scheduler/edge/sources/...` + +### 核心文件 + +- JS: https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/edge/sources/dhtmlxscheduler.css + ## 指定 Scheduler 版本 -如需引用特定版本库,请将资源路径设置为 **https://cdn.dhtmlx.com/scheduler/[version_number]/...** +使用: + +`https://cdn.dhtmlx.com/scheduler/[version_number]/...` + +其中 `[version_number]` 指定软件包的 `major.minor` 版本,例如 **7.0**、**6.0**、**5.3** 等。我们的 CDN 总是为每个 major/minor 版本提供最新的补丁版本。 + +### 核心文件 + +- JS: https://cdn.dhtmlx.com/scheduler/7.0/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/7.0/dhtmlxscheduler.css + +### 皮肤(仅限 v6.0 及更早版本) + +在 v6.0 及更早版本中,提供了单独的皮肤文件。自 v7.0 起,所有皮肤都包含在 `dhtmlxscheduler.css` 中,并通过 `scheduler.skin`/`scheduler.setSkin()` 进行选择,更多细节请查阅 [Migration guide](migration.md)。 + +- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_terrace.css +- Flat: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_flat.css +- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_contrast_black.css +- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_contrast_white.css +- Material: https://cdn.dhtmlx.com/scheduler/6.0/dhtmlxscheduler_material.css + + +## 指定 Scheduler 版本,未压缩 + +使用: + +`https://cdn.dhtmlx.com/scheduler/[version_number]/sources/...` + +其中 `[version_number]` 指定软件包的 `major.minor` 版本,例如 **7.0**、**6.0**、**5.3** 等。我们的 CDN 总是为每个 major/minor 版本提供最新的补丁版本。 -核心文件: [JS](https://cdn.dhtmlx.com/scheduler/4.3/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/4.3/dhtmlxscheduler.css) +### 核心文件 -皮肤: [Terrace](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/5.0/dhtmlxscheduler_contrast_white.css)。 +- JS: https://cdn.dhtmlx.com/scheduler/7.0/sources/dhtmlxscheduler.js +- CSS: https://cdn.dhtmlx.com/scheduler/7.0/sources/dhtmlxscheduler.css -## 指定 Scheduler 版本,未压缩 -如需使用特定版本的未压缩源码,请将路径设置为 **https://cdn.dhtmlx.com/scheduler/[version_number]/sources/...** +### 皮肤(仅限 v6.0 及更早版本) -核心文件: [JS](https://cdn.dhtmlx.com/scheduler/4.3/sources/dhtmlxscheduler.js), [CSS](https://cdn.dhtmlx.com/scheduler/4.3/sources/skins/dhtmlxscheduler.css) +在 v6.0 及更早版本中,提供了单独的皮肤文件。自 v7.0 起,所有皮肤都包含在 `dhtmlxscheduler.css` 中,并通过 `scheduler.skin`/`scheduler.setSkin()` 进行选择,更多细节请查阅 [Migration guide](migration.md)。 -皮肤: [Terrace](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_terrace.css), -[Material](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_material.css), -[Flat](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_flat.css), -[Contrast Black](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_contrast_black.css), -[Contrast White](https://cdn.dhtmlx.com/scheduler/5.0/sources/skins/dhtmlxscheduler_contrast_white.css)。 +未压缩的皮肤文件: +- Terrace: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_terrace.css +- Flat: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_flat.css +- Contrast Black: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_contrast_black.css +- Contrast White: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_contrast_white.css +- Material: https://cdn.dhtmlx.com/scheduler/6.0/sources/skins/dhtmlxscheduler_material.css \ No newline at end of file diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/guides/configuration.md b/i18n/zh/docusaurus-plugin-content-docs/current/guides/configuration.md index f02772a0..b665f420 100644 --- a/i18n/zh/docusaurus-plugin-content-docs/current/guides/configuration.md +++ b/i18n/zh/docusaurus-plugin-content-docs/current/guides/configuration.md @@ -7,8 +7,8 @@ sidebar_label: "通用配置说明" 为了自定义调度器的外观,库提供了三个主要对象: -- scheduler.config - 用于设置日期、视图、控件等选项。 -- scheduler.templates - 用于格式化日期、标题、提示信息和样式的模板。 +- [scheduler.config](api/overview/properties_overview.md) - 用于设置日期、视图、控件等选项。 +- [scheduler.templates](api/api_overview.md#scheduler-templates) - 用于格式化日期、标题、提示信息和样式的模板。 - [scheduler.xy](api/other/xy.md) - 定义调度器各元素尺寸的设置。 此外,dhtmlxScheduler 还包含了[若干扩展](#extensions),以增强组件功能。 diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md b/i18n/zh/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md index cf7774d0..233facd7 100644 --- a/i18n/zh/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md +++ b/i18n/zh/docusaurus-plugin-content-docs/current/integrations/google-calendar/google-calendar-sync.md @@ -35,7 +35,7 @@ description: "实现一个 Node.js + Express 集成,将 DHTMLX Scheduler 事 ## 演示仓库 与本指南匹配的完整可运行项目可在 GitHub 上获取: -- https://github.com/dhtmlx/scheduler-google-auth-demo +- https://github.com/dhtmlx/scheduler-google-calendar-demo 该指南解释了关键步骤并展示了重要的集成代码。仓库是“完整可运行的参考实现”。 @@ -49,8 +49,8 @@ description: "实现一个 Node.js + Express 集成,将 DHTMLX Scheduler 事 - 克隆仓库: ~~~bash title="Terminal" -git clone https://github.com/dhtmlx/scheduler-google-auth-demo.git -cd scheduler-google-auth-demo +git clone https://github.com/dhtmlx/scheduler-google-calendar-demo.git +cd scheduler-google-calendar-demo ~~~ 如果你的项目需要从私有注册表安装 `@dhx/*` 包,请配置 npm: @@ -160,7 +160,7 @@ http://localhost:3000 一个典型的结构是: ~~~text title="Project structure" -scheduler-google-auth-demo/ +scheduler-google-calendar-demo/ client/ index.ejs main.ts diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md b/i18n/zh/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md new file mode 100644 index 00000000..3fd8278a --- /dev/null +++ b/i18n/zh/docusaurus-plugin-content-docs/current/integrations/react/starhive-integration.md @@ -0,0 +1,462 @@ +--- +title: React Scheduler 与 Starhive 集成 +sidebar_label: Starhive 快速入门 +description: "通过 Next.js API 路由,将 DHTMLX React Scheduler 连接到 Starhive NoSQL 后端。" +--- + +# React Scheduler 与 Starhive 集成 + +本教程通过 Next.js Route Handlers 将 **React Scheduler** 连接到一个 **Starhive** NoSQL 后端。Starhive 提供带类型的架构和一个生成的 TypeScript 客户端,因此 API 层保持尽量简洁:一个端点用于加载事件和资源,另一个用于创建 / 更新 / 删除。 + +你将构建: + +- 一个在客户端组件中托管 Scheduler 的 Next.js 页面 +- `/api/load` - 首次渲染时从 Starhive 获取事件与资源 +- `/api/event`(POST)和 `/api/event/[id]`(PUT、DELETE) - Scheduler `dataBridge` 使用的写入路径 + +:::note +完整的源代码可在 [GitHub 上获取](https://github.com/DHTMLX/react-scheduler-starhive-demo)。 +::: + +## 前提条件 + +- Next.js + React + TypeScript 的基础知识 +- Node.js 18+ +- 一个 [Starhive](https://starhive.com/) 帐户(30 天试用即可) + +## 步骤 1. 创建项目 + +```bash +npx create-next-app@latest react-scheduler-starhive-demo +cd react-scheduler-starhive-demo +``` + +按照 [React Scheduler 安装指南](integrations/react/installation.md) 的指引安装 React Scheduler。为了评估: + +```bash +npm install @dhtmlx/trial-react-scheduler +``` + +如果你已使用 Professional 版本,请将命令及导入中的 `@dhtmlx/trial-react-scheduler` 替换为 `@dhx/react-scheduler`。 + +你还需要 `axios` —— 它是生成的 Starhive TypeScript 客户端的对等依赖项。 + +```bash +npm install axios +``` + +## 步骤 2. 设置 Starhive 空间 + +登录后,在右上角点击 **+ Create**,将空间命名为 `Scheduler`。 + +在空间内创建两个类型:`Resources` 与 `Events`。Resources 负责时间线的行(团队、人员、房间等)。Events 参考每一个 Resource。 + +通过 **+ Attribute** 按钮添加以下属性。Starhive 会为每个项自动生成 `id`,因此你不需要显式声明它。 + +**Resources 类型** + +| 字段 | 类型 | +| ---- | ---- | +| `label` | Text | + +**Events 类型** + +| 字段 | 类型 | +| ---- | ---- | +| `text` | Text | +| `start_date` | Date & Time | +| `end_date` | Date & Time | +| `resource_id` | Reference → Resources | + +## 步骤 3. 导入示例数据 + +创建 `scheduler_resources.csv`: + +```csv +label +"Frontend Team" +"Backend Team" +"QA Team" +"DevOps" +"Security Team" +``` + +以及 `scheduler_events.csv`: + +```csv +text,start_date,end_date,resource_id +"Development","2026-04-01T08:00:00","2026-04-01T10:30:00","Frontend Team" +"Code Review","2026-04-01T09:00:00","2026-04-01T11:30:00","Backend Team" +"QA Testing","2026-04-01T10:00:00","2026-04-01T13:00:00","QA Team" +"Deployment","2026-04-01T11:00:00","2026-04-01T13:30:00","DevOps" +"Incident Response","2026-04-01T12:00:00","2026-04-01T15:00:00","DevOps" +"Maintenance Window","2026-04-01T08:30:00","2026-04-01T11:00:00","Backend Team" +"Security Scan","2026-04-01T13:00:00","2026-04-01T15:30:00","Security Team" +``` + +在 Starhive UI 中打开各类型并为每个文件点击 CSV 导入。 + +## 步骤 4. 生成并复制模式 + +前往 Settings → API Connectors。选择 `Scheduler` 空间,将语言设为 TypeScript,点击 Generate,然后 Download。 + +解压缩 ZIP,在 `project/src/io/` 下找到 `starhive` 文件夹,并将其拷贝到你 Next.js 项目的 `lib/starhive/` 目录中。生成的文件包含工作区特定的 UUID,因此每当模式变化或切换工作区时你都需要重复此步骤。 + +:::note +撰写时,Starhive TypeScript 生成器输出的内容尚未通过严格的 TypeScript:存在缺失的 `Sla.ts` 引用、内联 `AttributeVisitor` 字面量中缺失的 `visitSlaAttribute` 实现,以及对一个 **any** 类型字段的 `client.request` 调用(TS2347)。配套的演示仓库提供了三处最小化补丁,能够解决这些问题;请参阅 [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/) 的 diff。在重新生成模式时请再次应用相同补丁,直到 Starhive 提供修复为止。 + ::: + +## 步骤 5. 配置 Starhive 客户端 + +创建 `lib/starhiveClient.ts`: + +```ts title="lib/starhiveClient.ts" +import { StarhiveClient } from "./starhive/client/StarhiveClient"; +import { JSON_DECODERS } from "./starhive/schema/JsonDecoders"; + +let starhiveClient: StarhiveClient | null = null; + +export function getStarhiveClient() { + if (starhiveClient) return starhiveClient; + + const workspaceId = process.env.STARHIVE_WORKSPACE_ID; + const apiKey = process.env.STARHIVE_API_TOKEN; + + if (!workspaceId || !apiKey) { + throw new Error("Missing Starhive configuration (workspaceId or API token)"); + } + + starhiveClient = new StarhiveClient(apiKey, workspaceId, JSON_DECODERS); + return starhiveClient; +} +``` + +该函数在模块作用域缓存客户端,因此路由处理程序共享同一个实例。 + +在项目根目录添加 `.env.local`(或 `.env`): + +```env title=".env.local" +STARHIVE_API_TOKEN=your-api-token +STARHIVE_WORKSPACE_ID=your-workspace-id +``` + +在 Settings → Personal access tokens 下生成 API 令牌。工作区 ID 是在 `https://app.starhive.com/workspace//home` 的路径段。 + +## 步骤 6. 加载事件与资源 + +创建 `app/api/load/route.ts`: + +```ts title="app/api/load/route.ts" +import { NextResponse } from 'next/server'; +import { getStarhiveClient } from '@/lib/starhiveClient'; +import { Events } from '@/lib/starhive/schema/Events'; +import { Resources } from '@/lib/starhive/schema/Resources'; + +function normalizeEvents(events: Events[]) { + return events.map(ev => ({ + id: ev.getId() || '', + text: ev.getText(), + start_date: ev.getStartDate(), + end_date: ev.getEndDate(), + resource_id: ev.getResourceId()?.[0] || null, + })); +} + +export async function GET() { + try { + const client = getStarhiveClient(); + const [events, resources] = await Promise.all([ + client.search(Events.TYPE_ID, ""), + client.search(Resources.TYPE_ID, "") + ]); + + return NextResponse.json({ + events: normalizeEvents(events.result), + resources: resources.result.map((r) => ({ + key: r.getId(), + label: r.getLabel(), + })), + }); + } catch (error) { + return NextResponse.json({ error: 'Failed to load data' }, { status: 500 }); + } +} +``` + +`normalizeEvents` 将每个 Starhive 对象扁平化为 React Scheduler 期望的形状:`{ id, text, start_date, end_date, resource_id }`。Resources 将扁平化为 `{ key, label }`,这是时间线视图中的 `y_unit` 所消耗的格式。 + +在启动开发服务器后访问 `http://localhost:3000/api/load` 以确认 JSON 结构。 + +## 步骤 7. 渲染 Scheduler 并加载事件 + +创建 `app/page.tsx`: + +```tsx title="app/page.tsx" +'use client'; + +import { useEffect, useMemo, useState } from 'react'; +import ReactScheduler, { + type Event, + type SchedulerViewsProp, +} from '@dhtmlx/trial-react-scheduler'; +import '@dhtmlx/trial-react-scheduler/dist/react-scheduler.css'; + +type Resource = { key: string; label: string }; + +export default function Scheduler() { + const [resources, setResources] = useState([]); + const [events, setEvents] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetch('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/api/load') + .then((response) => response.json()) + .then((data) => { + setResources(data.resources); + setEvents(data.events); + }) + .catch((error) => { + console.error('Failed to load resources data:', error); + }) + .finally(() => { + setLoading(false); + }); + }, []); + + const views: SchedulerViewsProp = useMemo( + () => ({ + timeline: [ + { + name: "timeline", + x_unit: "hour", + x_date: "%H:%i", + x_step: 1, + x_start: 8, + x_size: 13, + x_length: 13, + event_dy: 50, + event_min_dy: 50, + y_property: "resource_id", + render: "bar", + y_unit: resources, + }, + ], + }), + [resources] + ); + + if (loading) { + return
Loading...
; + } + + return ( +
+ +
+ ); +} +``` + +使用 `loading` 标志比直接检查 `events.length` 或 `resources.length` 更可靠:一个工作区如果确实没有事件,也应渲染空的 Scheduler 而不是一直处于加载状态。 + +运行 `npm run dev`,时间线将显示并按资源分组导入的事件。 + +## 步骤 8. 实现 CRUD 端点 + +Scheduler 的 `dataBridge` 会调用三个端点 - 创建使用 POST、更新使用 PUT、删除使用 DELETE - 并期望特定的响应结构: + +| HTTP 方法 | Endpoint | Response | +| --------- | ------------------------- | --------------------------------- | +| `GET` | `/api/load` | `{ events, resources }` | +| `POST` | `/api/event` | `{ action: "inserted", tid: id }` | +| `PUT` | `/api/event/{event_id}` | `{ action: "updated" }` | +| `DELETE` | `/api/event/{event_id}` | `{ action: "deleted" }` | + +在 `app/api/event/route.ts` 上创建 POST 处理程序: + +```ts title="app/api/event/route.ts" +import { NextRequest, NextResponse } from 'next/server'; +import { getStarhiveClient } from '@/lib/starhiveClient'; +import { Events } from '@/lib/starhive/schema/Events'; + +export async function POST(req: NextRequest) { + try { + const { text, start_date, end_date, resource_id } = await req.json(); + const client = getStarhiveClient(); + + const event = Events.builder() + .text(text) + .startDate(new Date(start_date)) + .endDate(new Date(end_date)) + .resourceId([resource_id]) + .build(); + + const result = await client.createObject(event); + return NextResponse.json({ action: 'inserted', tid: result.getId() }); + } catch (error) { + return NextResponse.json({ error: 'Create failed' }, { status: 500 }); + } +} +``` + +以及动态 PUT/DELETE 处理程序在 `app/api/event/[id]/route.ts`: + +```ts title="app/api/event/[id]/route.ts" +import { NextRequest, NextResponse } from 'next/server'; +import { Events } from "@/lib/starhive/schema/Events"; +import { getStarhiveClient } from "@/lib/starhiveClient"; + +export async function PUT( + request: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + try { + const { id } = await params; + const body = await request.json(); + const client = getStarhiveClient(); + + const existingEvent = await client.getObject(id, Events.TYPE_ID); + if (!existingEvent) { + return NextResponse.json({ error: 'Event not found' }, { status: 404 }); + } + + const updatedEvent = Events.builder() + .id(id) + .text(body.text) + .startDate(new Date(body.start_date)) + .endDate(new Date(body.end_date)) + .resourceId([body.resource_id]) + .build(); + + await client.updateObject(updatedEvent); + return NextResponse.json({ action: 'updated' }); + } catch (error: any) { + console.error('Update error:', error); + return NextResponse.json( + { error: 'Update failed', details: error.message }, + { status: 500 } + ); + } +} + +export async function DELETE( + request: NextRequest, + { params }: { params: Promise<{ id: string }> }, +) { + try { + const { id } = await params; + const client = getStarhiveClient(); + await client.deleteObjectsInBulk([id]); + + return NextResponse.json({ action: 'deleted' }); + } catch (error: any) { + console.error('Delete error:', error); + return NextResponse.json( + { error: 'Delete failed', details: error.message }, + { status: 500 } + ); + } +} +``` + +:::note +在 Next.js 15+ 中,动态路由处理程序的 `params` 参数是一个 `Promise`。请始终将其类型标注为 `Promise<{...}>`,并在读取段值之前 `await` 它——在某些环境中省略 `Promise<>` 包装会在严格模式下编译失败。 +::: + +## 步骤 9. 将 dataBridge 与前端连接起来 + +在 `services/scheduler.ts` 中创建一个小型客户端辅助工具: + +```ts title="services/scheduler.ts" +import type { Event } from '@dhtmlx/trial-react-scheduler'; + +async function request(url: string, options: RequestInit): Promise { + const res = await fetch(url, options); + if (!res.ok) throw new Error(`Request failed: ${res.status}`); + return res.json(); +} + +export function createEvent(event: Event) { + return request('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/api/event', { + method: 'POST', + body: JSON.stringify(event), + headers: { 'Content-Type': 'application/json' }, + }); +} + +export function updateEvent(event: Event) { + return request(`/api/event/${event.id}`, { + method: 'PUT', + body: JSON.stringify(event), + headers: { 'Content-Type': 'application/json' }, + }); +} + +export function deleteEvent(id: string | number) { + return request(`/api/event/${id}`, { + method: 'DELETE', + }); +} +``` + +接着将 `dataBridge` 连接到页面中。更新 `app/page.tsx`,添加导入并在 `` 上使用 `data` 属性: + +```tsx title="app/page.tsx" +import { createEvent, deleteEvent, updateEvent } from '@/services/scheduler'; + +// Scheduler 组件内部: +const dataBridge = useMemo(() => ({ + save: (entity: string, action: string, payload: Event, id: string | number) => { + if (entity !== "event") return; + + switch (action) { + case "update": + return updateEvent(payload); + case "create": + return createEvent(payload); + case "delete": + return deleteEvent(id); + default: + console.warn(`Unknown action: ${action}`); + return; + } + }, +}), []); + +// 将其传给组件: + +``` + +## 测试 + +```bash +npm run dev +``` + +打开 `http://localhost:3000`,拖动某个事件到新的时间段、编辑文本、删除一个事件。每次修改都会在 Starhive UI 的 `Events` 类型下即时体现。 + +## 关于 Starhive 集成的说明 + +- **服务器端凭据独立。** `STARHIVE_API_TOKEN` 和 `STARHIVE_WORKSPACE_ID` 仅在路由处理程序中读取;它们永远不会进入浏览器打包中。不要将 Starhive 客户端放入客户端组件,或通过 `NEXT_PUBLIC_*` 变量暴露令牌。 +- **模式再生成。** 当你在 Starhive 中添加或重命名属性时,重新生成 TypeScript 模式并替换 `lib/starhive/`。如果在执行 `next build` 时收到相同的上游问题,请按照 [`lib/starhive/PATCHES.md`](https://github.com/DHTMLX/react-scheduler-starhive-demo/blob/main/lib/starhive/) 的 diff 重新应用补丁,直到 Starhive 提供修复。 +- **没有实时同步。** 与 Firebase 集成不同,Starhive 不会将变更推送给已连接的客户端。多用户编辑同一 Scheduler 时会覆盖彼此的改动。若需要支持多用户场景,可以在客户端添加轮询,或将 Starhive 的 Webhooks 连接到 SSE / WebSockets 以在远程变更时刷新 `events` 状态。 +- **大数据集的动态加载。** `/api/load` 路由会加载工作空间中的所有事件。生产环境中,可以在 GET 处理程序中接受 `from` / `to` 查询参数,按 `start_date` / `end_date` 进行筛选,并在客户端调用 `scheduler.setLoadMode("day")`,以便仅获取可见范围的数据。 +- **引用属性携带数组。** `Events.getResourceId()` 返回 `string[] | undefined`,因为 Starhive 的引用属性是多值的。演示中通过 `?.[0] || null` 进行扁平化处理。如果允许事件属于多个资源,请相应地调整时间线视图的 `y_property` 分辨方案以及 normalize / builder 调用。 + +## 相关页面 + +- [数据绑定与状态管理基础](integrations/react/state/state-management-basics.md) +- [React Scheduler 概览](integrations/react/overview.md#bindingdata) +- [服务端集成](guides/server-integration.md) +- [React Scheduler 与 Firebase 集成](integrations/react/firebase-integration.md) - 实时同步的对等模式 \ No newline at end of file diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md b/i18n/zh/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md index 3e3d002f..e3014fb4 100644 --- a/i18n/zh/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md +++ b/i18n/zh/docusaurus-plugin-content-docs/current/integrations/react/state/valtio.md @@ -15,7 +15,7 @@ description: 使用 Valtio 代理存储管理 React Scheduler 的状态,通过 - 基于快照的撤销/重做(事件 + 配置) :::note -完整的源代码可在 GitHub 上查看:[GitHub 演示仓库](https://github.com/nicetip/react-scheduler-valtio-starter)。 +完整的源代码可在 GitHub 上查看:[GitHub 演示仓库](https://github.com/DHTMLX/react-scheduler-valtio-starter)。 ::: ## 前提条件 diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/migration.md b/i18n/zh/docusaurus-plugin-content-docs/current/migration.md index 85ab0e70..6e229898 100644 --- a/i18n/zh/docusaurus-plugin-content-docs/current/migration.md +++ b/i18n/zh/docusaurus-plugin-content-docs/current/migration.md @@ -275,7 +275,7 @@ scheduler.config.day_column_padding = 0; 自 v7.0 起,导入/导出功能已集成至 Scheduler 库中。 -如果之前为在线导出功能引入了 **https://export.dhtmlx.com/scheduler/api.js**,例如: +如果之前为在线导出功能引入了 `https://export.dhtmlx.com/scheduler/api.js`,例如: ~~~js