@dotcms/uve 0.0.1-beta.32 → 0.0.1-beta.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +495 -230
- package/package.json +1 -1
- package/public.cjs.js +1 -1
- package/public.esm.js +1 -1
- package/src/lib/editor/public.d.ts +3 -3
- package/src/script/utils.d.ts +2 -2
package/README.md
CHANGED
|
@@ -1,324 +1,589 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dotCMS UVE SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The `@dotcms/uve` SDK adds live editing to your JavaScript app using the dotCMS Universal Visual Editor (UVE). It provides low-level tools that power our framework-specific SDKs, such as [`@dotcms/react`](https://github.com/dotCMS/core/blob/main/core-web/libs/sdk/react/README.md) and [`@dotcms/angular`](https://github.com/dotCMS/core/blob/main/core-web/libs/sdk/angular/README.md).
|
|
4
4
|
|
|
5
|
-
> **
|
|
5
|
+
> ⚠️ We **do not recommend using this SDK directly** for most use cases, you should use a [framework SDK that handles setup](#Getting Started: Recommended Examples), rendering, and event wiring for you.
|
|
6
|
+
|
|
7
|
+
With `@dotcms/uve`, framework SDKs are able to:
|
|
8
|
+
- Make pages and contentlets editable
|
|
9
|
+
- Respond to editor events (content updates, mode changes)
|
|
10
|
+
- Trigger modal or inline editing experiences
|
|
11
|
+
- Sync app routing with the dotCMS editor
|
|
6
12
|
|
|
7
13
|
## Table of Contents
|
|
8
14
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
15
|
+
- [Before You Use @dotcms/uve](#before-you-use-dotcmsuve)
|
|
16
|
+
- [Getting Started: Recommended Examples](#getting-started-recommended-examples)
|
|
17
|
+
- [🚩 Custom Setup: Manual Rendering (Not Recommended)](#-custom-setup-manual-rendering-not-recommended)
|
|
18
|
+
- [Prerequisites & Setup](#prerequisites--setup)
|
|
19
|
+
- [Get a dotCMS Environment](#get-a-dotcms-environment)
|
|
20
|
+
- [Create a dotCMS API Key](#create-a-dotcms-api-key)
|
|
21
|
+
- [Installation](#installation)
|
|
22
|
+
- [Using the SDK with TypeScript](#using-the-sdk-with-typescript)
|
|
23
|
+
- [SDK Reference](#sdk-reference)
|
|
24
|
+
- [`initUVE()`](#inituveconfig-dotcmsuveconfig)
|
|
25
|
+
- [`getUVEState()`](#getuvestate)
|
|
26
|
+
- [`createUVESubscription()`](#createuvesubscriptioneventtype-callback)
|
|
27
|
+
- [`editContentlet()`](#editcontentletcontentlet)
|
|
28
|
+
- [`initInlineEditing()`](#initinlineeditingtype-data)
|
|
29
|
+
- [`enableBlockEditorInline()`](#enableblockeditorinlinecontentlet-fieldname)
|
|
30
|
+
- [`updateNavigation()`](#updatenavigationpathname)
|
|
31
|
+
- [`reorderMenu()`](#reordermenuconfig)
|
|
32
|
+
- [`sendMessageToUVE()`](#sendmessagetouvemessage)
|
|
33
|
+
- [Troubleshooting](#troubleshooting)
|
|
34
|
+
- [Common Issues & Solutions](#common-issues--solutions)
|
|
35
|
+
- [Debugging Tips](#debugging-tips)
|
|
36
|
+
- [Still Having Issues?](#still-having-issues)
|
|
37
|
+
- [dotCMS Support](#dotcms-support)
|
|
38
|
+
- [How To Contribute](#how-to-contribute)
|
|
39
|
+
- [Licensing Information](#licensing-information)
|
|
40
|
+
- [Troubleshooting](#troubleshooting)
|
|
41
|
+
|
|
42
|
+
## Before You Use @dotcms/uve
|
|
43
|
+
|
|
44
|
+
### Getting Started: Recommended Examples
|
|
45
|
+
|
|
46
|
+
We strongly recommend using one of our official framework SDKs, which are designed to handle UVE integration, routing, rendering, and more—out of the box. These examples are the best way to get started:
|
|
47
|
+
|
|
48
|
+
- [dotCMS Angular SDK: Angular Example](https://github.com/dotCMS/core/tree/main/examples/angular) – Ideal for Angular apps 🅰️
|
|
49
|
+
- [dotCMS React SDK: NextJS Example](https://github.com/dotCMS/core/tree/main/examples/react) – Ideal for NextJS projects ⚛️
|
|
50
|
+
- [dotCMS React SDK: Astro Example](https://github.com/dotCMS/core/tree/main/examples/astro) – Ideal for Astro projects 🌌
|
|
51
|
+
|
|
52
|
+
These examples handle UVE integration, routing, rendering, and more—out of the box. **If you're building a headless dotCMS front-end, start there.**
|
|
53
|
+
|
|
54
|
+
### 🚩 Custom Setup: Manual Rendering (Not Recommended)
|
|
55
|
+
|
|
56
|
+
> 💡 We recommend using one of our official framework SDKs, which are designed to handle UVE integration, routing, rendering, and more—out of the box.
|
|
57
|
+
|
|
58
|
+
You can use `@dotcms/uve` directly, but **it’s not recommended or supported** unless you’re building a highly custom integration. Here’s how the pieces fit together:
|
|
59
|
+
|
|
60
|
+
1. **You must use `@dotcms/client` to fetch content and page data.**
|
|
61
|
+
2. **You must render pages based on dotCMS’s layout schema.**
|
|
62
|
+
3. **You must apply the correct `data-dot-*` attributes to containers and contentlets.**
|
|
63
|
+
|
|
64
|
+
Here's a minimal setup using `@dotcms/client` and `@dotcms/uve`:
|
|
65
|
+
|
|
66
|
+
1. Initializa the Client and get the page response:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
// getPage.ts
|
|
70
|
+
import { createDotCMSClient } from '@dotcms/client/next';
|
|
71
|
+
import { initUVE, createUVESubscription } from '@dotcms/uve/next';
|
|
72
|
+
|
|
73
|
+
const dotCMSClient = createDotCMSClient({
|
|
74
|
+
dotcmsUrl: 'https://your-dotcms-instance.com',
|
|
75
|
+
authToken: 'your-api-key',
|
|
76
|
+
siteId: 'your-site-id'
|
|
77
|
+
});
|
|
22
78
|
|
|
23
|
-
|
|
79
|
+
const getPage = async () => {
|
|
80
|
+
const pageResponse = await dotCMSClient.page.get('/', {
|
|
81
|
+
languageId: '1'
|
|
82
|
+
});
|
|
24
83
|
|
|
25
|
-
|
|
84
|
+
return pageResponse;
|
|
85
|
+
};
|
|
86
|
+
```
|
|
26
87
|
|
|
27
|
-
|
|
28
|
-
# Using npm
|
|
29
|
-
npm install @dotcms/uve-sdk
|
|
88
|
+
2. Initialize the UVE and subscribe to changes:
|
|
30
89
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
```
|
|
90
|
+
> ⚠️ The `initUVE()` function only works with a `PageResponse` returned by `@dotcms/client`. If you try to pass in data from another source or build your own structure, it won't initialize properly.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import { initUVE, createUVESubscription } from '@dotcms/uve/next';
|
|
94
|
+
import { getPage } from './getPage';
|
|
34
95
|
|
|
35
|
-
|
|
96
|
+
const pageResponse = await getPage();
|
|
36
97
|
|
|
37
|
-
|
|
98
|
+
initUVE(pageResponse);
|
|
99
|
+
createUVESubscription('changes', (newPageResponse) => {
|
|
100
|
+
// Handle page updates (e.g. re-render)
|
|
101
|
+
});
|
|
102
|
+
```
|
|
38
103
|
|
|
39
|
-
|
|
104
|
+
> ⚠️ This only sets up the editor connection. You are responsible for rendering the page structure (rows, columns, containers, contentlets) using your own UI components.
|
|
40
105
|
|
|
41
|
-
|
|
106
|
+
3. Create a custom render for the page:
|
|
42
107
|
|
|
43
|
-
|
|
108
|
+
```tsx
|
|
109
|
+
// 🔧 Render the page layout (you must implement this component)
|
|
110
|
+
<MyDotCMSPage pageAsset={pageResponse.pageAsset} />
|
|
111
|
+
```
|
|
44
112
|
|
|
45
|
-
|
|
113
|
+
> ⚠️ Below is a simplified breakdown of how dotCMS layouts are structured and how you might render them manually.
|
|
114
|
+
|
|
115
|
+
#### 🔄 How to Render a dotCMS Page
|
|
116
|
+
|
|
117
|
+
> 📚 For a complete guide, here is a full tutorial:
|
|
118
|
+
> 👉 [dotCMS Page Rendering Architecture]( https://dev.dotcms.com/docs/dotcms-page-rendering-architecture)
|
|
119
|
+
|
|
120
|
+
dotCMS pages are structured as nested layout objects:
|
|
121
|
+
|
|
122
|
+
- A `PageAsset` contains a `layout` object
|
|
123
|
+
- The `layout` includes rows, columns, containers, and contentlets
|
|
124
|
+
|
|
125
|
+
Here’s a basic pseudocode outline:
|
|
126
|
+
|
|
127
|
+
```jsx
|
|
128
|
+
<Page>
|
|
129
|
+
{layout.body.rows.map(row => (
|
|
130
|
+
<Row>
|
|
131
|
+
{row.columns.map(column => (
|
|
132
|
+
<Column>
|
|
133
|
+
{column.containers.map(container => (
|
|
134
|
+
<Container data-dot-object="container" ...>
|
|
135
|
+
{container.contentlets.map(contentlet => (
|
|
136
|
+
<Contentlet data-dot-object="contentlet" ...>
|
|
137
|
+
{renderContentletByType(contentlet)}
|
|
138
|
+
</Contentlet>
|
|
139
|
+
))}
|
|
140
|
+
</Container>
|
|
141
|
+
))}
|
|
142
|
+
</Column>
|
|
143
|
+
))}
|
|
144
|
+
</Row>
|
|
145
|
+
))}
|
|
146
|
+
</Page>
|
|
147
|
+
```
|
|
46
148
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
|
|
58
|
-
console.log('Content updated:', changes);
|
|
59
|
-
// Update your UI with the new content
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// Later, when no longer needed
|
|
63
|
-
subscription.unsubscribe();
|
|
149
|
+
Each contentlet is rendered according to its content type:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
function renderContentletByType(contentlet) {
|
|
153
|
+
switch(contentlet.contentType) {
|
|
154
|
+
case 'text': return <TextBlock contentlet={contentlet} />;
|
|
155
|
+
case 'image': return <ImageBlock contentlet={contentlet} />;
|
|
156
|
+
case 'video': return <VideoBlock contentlet={contentlet} />;
|
|
157
|
+
default: return null;
|
|
158
|
+
}
|
|
64
159
|
}
|
|
65
160
|
```
|
|
66
161
|
|
|
67
|
-
|
|
162
|
+
To make the layout editable, be sure to apply all required `data-dot-*` attributes on containers and contentlets.
|
|
68
163
|
|
|
69
|
-
|
|
164
|
+
## Prerequisites & Setup
|
|
70
165
|
|
|
71
|
-
|
|
166
|
+
### Get a dotCMS Environment
|
|
72
167
|
|
|
73
|
-
|
|
168
|
+
#### Version Compatibility
|
|
74
169
|
|
|
75
|
-
**
|
|
76
|
-
-
|
|
170
|
+
- **Recommended**: dotCMS Evergreen
|
|
171
|
+
- **Minimum**: dotCMS v25.05
|
|
172
|
+
- **Best Experience**: Latest Evergreen release
|
|
77
173
|
|
|
78
|
-
|
|
79
|
-
- `mode`: The current editor mode (preview, edit, live).
|
|
80
|
-
- `languageId`: The language ID of the current page set in the UVE.
|
|
81
|
-
- `persona`: The persona of the current page set in the UVE.
|
|
82
|
-
- `variantName`: The name of the current variant.
|
|
83
|
-
- `experimentId`: The ID of the current experiment.
|
|
84
|
-
- `publishDate`: The publish date of the current page set in the UVE.
|
|
174
|
+
#### Environment Setup
|
|
85
175
|
|
|
86
|
-
|
|
176
|
+
**For Production Use:**
|
|
87
177
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const editorState = getUVEState();
|
|
91
|
-
if (editorState?.mode === 'edit') {
|
|
92
|
-
// Enable editing features
|
|
93
|
-
}
|
|
94
|
-
```
|
|
178
|
+
- ☁️ [Cloud hosting options](https://www.dotcms.com/pricing) - managed solutions with SLA
|
|
179
|
+
- 🛠️ [Self-hosted options](https://dev.dotcms.com/docs/current-releases) - deploy on your infrastructure
|
|
95
180
|
|
|
96
|
-
|
|
181
|
+
**For Testing & Development:**
|
|
97
182
|
|
|
98
|
-
|
|
183
|
+
- 🧑🏻💻 [dotCMS demo site](https://demo.dotcms.com/dotAdmin/#/public/login) - perfect for trying out the SDK
|
|
184
|
+
- 📘 [Learn how to use the demo site](https://dev.dotcms.com/docs/demo-site)
|
|
185
|
+
- 📝 Read-only access, ideal for building proof-of-concepts
|
|
99
186
|
|
|
100
|
-
|
|
187
|
+
**For Local Development:**
|
|
101
188
|
|
|
102
|
-
|
|
103
|
-
-
|
|
104
|
-
- `callback` - The callback function that will be called when the event occurs.
|
|
189
|
+
- 🐳 [Docker setup guide](https://github.com/dotCMS/core/tree/main/docker/docker-compose-examples/single-node-demo-site)
|
|
190
|
+
- 💻 [Local installation guide](https://dev.dotcms.com/docs/quick-start-guide)
|
|
105
191
|
|
|
106
|
-
|
|
107
|
-
- An event subscription that can be used to unsubscribe.
|
|
192
|
+
### Configure The Universal Visual Editor App
|
|
108
193
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
|
|
113
|
-
console.log('Content changes:', changes);
|
|
114
|
-
});
|
|
194
|
+
For a step-by-step guide on setting up the Universal Visual Editor, check out our [easy-to-follow instructions](https://dev.dotcms.com/docs/uve-headless-config) and get started in no time!
|
|
195
|
+
|
|
196
|
+
### Installation
|
|
115
197
|
|
|
116
|
-
|
|
117
|
-
|
|
198
|
+
```bash
|
|
199
|
+
npm install @dotcms/uve@next
|
|
118
200
|
```
|
|
119
201
|
|
|
120
|
-
###
|
|
202
|
+
### Using the SDK with TypeScript
|
|
121
203
|
|
|
122
|
-
|
|
204
|
+
All interfaces and types are available through the `@dotcms/types` package:
|
|
123
205
|
|
|
124
|
-
|
|
206
|
+
```bash
|
|
207
|
+
npm install @dotcms/types@next --save-dev
|
|
208
|
+
```
|
|
125
209
|
|
|
126
|
-
|
|
210
|
+
#### Common Types
|
|
127
211
|
|
|
128
|
-
|
|
129
|
-
- `contentlet<T>` - The contentlet to edit.
|
|
212
|
+
The SDK uses several key types from `@dotcms/types`:
|
|
130
213
|
|
|
131
|
-
**Example:**
|
|
132
214
|
```typescript
|
|
133
|
-
|
|
134
|
-
|
|
215
|
+
import {
|
|
216
|
+
DotCMSContentlet,
|
|
217
|
+
DotCMSPageResponse,
|
|
218
|
+
DotCMSUVEConfig,
|
|
219
|
+
DotCMSInlineEditingType,
|
|
220
|
+
UVEEventType,
|
|
221
|
+
UVEState
|
|
222
|
+
} from '@dotcms/types';
|
|
135
223
|
```
|
|
136
224
|
|
|
137
|
-
|
|
225
|
+
For a complete reference of all available types and interfaces, please refer to the [@dotcms/types documentation](https://www.npmjs.com/package/@dotcms/types).
|
|
138
226
|
|
|
139
|
-
|
|
227
|
+
## SDK Reference
|
|
140
228
|
|
|
141
|
-
|
|
142
|
-
- `type` - The type of inline editing ('BLOCK_EDITOR' or 'WYSIWYG').
|
|
143
|
-
- `data` - (Optional) Data for the inline editing session.
|
|
229
|
+
### `initUVE(config?: DotCMSUVEConfig)`
|
|
144
230
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
});
|
|
231
|
+
`initUVE` is a function that initializes the Universal Visual Editor (UVE). It sets up the necessary communication between your app and the editor, enabling seamless integration and interaction.
|
|
232
|
+
|
|
233
|
+
| Input | Type | Required | Description |
|
|
234
|
+
| -------- | -------------------- | -------- | ------------------------------------------- |
|
|
235
|
+
| `config` | `DotCMSPageResponse` | ✅ | The page Response from the `@dotcms/client` |
|
|
236
|
+
|
|
237
|
+
#### Usage
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
const { destroyUVESubscriptions } = initUVE(pageResponse);
|
|
155
241
|
```
|
|
156
242
|
|
|
157
|
-
|
|
243
|
+
> ⚠️ If you don't provide a `pageResponse`, we can't assure that the UVE will be initialized correctly.
|
|
158
244
|
|
|
159
|
-
|
|
245
|
+
### `getUVEState()`
|
|
160
246
|
|
|
161
|
-
|
|
247
|
+
`getUVEState` is a function that returns the [UVE state](#uve-state) if UVE is active.
|
|
162
248
|
|
|
163
|
-
|
|
164
|
-
- `config` (optional): Configuration for reordering the menu.
|
|
165
|
-
- `startLevel` (default: `1`): The starting level of the menu to reorder.
|
|
166
|
-
- `depth` (default: `2`): The depth of the menu to reorder.
|
|
249
|
+
#### Usage
|
|
167
250
|
|
|
168
|
-
|
|
251
|
+
```tsx
|
|
252
|
+
import { getUVEState } from '@dotcms/uve';
|
|
253
|
+
import { UVE_MODE } from '@dotcms/types';
|
|
169
254
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
255
|
+
const myEditButton = () => {
|
|
256
|
+
const uveState = getUVEState();
|
|
257
|
+
|
|
258
|
+
if (uveState?.mode === UVE_MODE.EDIT) {
|
|
259
|
+
return <button>Edit</button>;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return null;
|
|
263
|
+
};
|
|
174
264
|
```
|
|
175
265
|
|
|
176
|
-
|
|
266
|
+
#### UVE State
|
|
177
267
|
|
|
178
|
-
|
|
268
|
+
- `dotCMSHost`: The host URL of the DotCMS instance
|
|
269
|
+
- `experimentId`: The ID of the current experiment
|
|
270
|
+
- `languageId`: The language ID of the current page set on the UVE
|
|
271
|
+
- `mode`: The current editor mode (`'preview'`, `'edit'`, `'live'`)
|
|
272
|
+
- `persona`: The persona of the current page set on the UVE
|
|
273
|
+
- `publishDate`: The publish date of the current page set on the UVE
|
|
274
|
+
- `variantName`: The name of the current variant
|
|
179
275
|
|
|
180
|
-
|
|
276
|
+
### `createUVESubscription(eventType, callback)`
|
|
181
277
|
|
|
182
|
-
|
|
278
|
+
`createUVESubscription` is a function that allows your application to dynamically interact with UVE by subscribing to events such as content changes or navigation updates. This enables your app to respond in real-time to user actions and editor events, enhancing the interactive experience.
|
|
183
279
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
280
|
+
| Input | Type | Required | Description |
|
|
281
|
+
| ----------- | -------------- | -------- | ----------------------------------------- |
|
|
282
|
+
| `eventType` | `UVEEventType` | ✅ | [The event to subscribe to](#event-types) |
|
|
283
|
+
| `callback` | `Function` | ✅ | Called when the event is triggered |
|
|
284
|
+
|
|
285
|
+
#### Usage
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
import { createUVESubscription } from '@dotcms/uve';
|
|
289
|
+
import { UVEEventType } from '@dotcms/types';
|
|
290
|
+
|
|
291
|
+
const sub = createUVESubscription(UVEEventType.CONTENT_CHANGES, (newPageResponse) => {
|
|
292
|
+
// do something when the content changes
|
|
189
293
|
});
|
|
294
|
+
|
|
295
|
+
// Later, when you want to unsubscribe
|
|
296
|
+
sub.unsubscribe();
|
|
190
297
|
```
|
|
191
298
|
|
|
192
|
-
|
|
299
|
+
#### Event Types
|
|
193
300
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
| `IFRAME_SCROLL_END` | Notifies the editor that scrolling has stopped. |
|
|
201
|
-
| `PING_EDITOR` | Pings the editor to check if the page is inside the editor. |
|
|
202
|
-
| `INIT_INLINE_EDITING` | Initializes the inline editing mode in the editor. |
|
|
203
|
-
| `COPY_CONTENTLET_INLINE_EDITING` | Opens the "Copy Contentlet" dialog to duplicate and edit a contentlet inline. |
|
|
204
|
-
| `UPDATE_CONTENTLET_INLINE_EDITING` | Triggers the save action for inline-edited contentlets. |
|
|
205
|
-
| `REORDER_MENU` | Triggers the menu reorder action with a specified configuration. |
|
|
206
|
-
| `GET_PAGE_DATA` | Requests the current page information from the editor. |
|
|
207
|
-
| `CLIENT_READY` | Indicates that the client has completed initialization. |
|
|
208
|
-
| `EDIT_CONTENTLET` | Opens the contentlet editing dialog in the editor. |
|
|
301
|
+
- `UVEEventType.CONTENT_CHANGES`: Triggered when the content of the page changes.
|
|
302
|
+
- `UVEEventType.PAGE_RELOAD`: Triggered when the page is reloaded.
|
|
303
|
+
- `UVEEventType.REQUEST_BOUNDS`: Triggered when the editor requests the bounds of the page.
|
|
304
|
+
- `UVEEventType.IFRAME_SCROLL`: Triggered when the iframe is scrolled.
|
|
305
|
+
- `UVEEventType.IFRAME_SCROLL_END`: Triggered when the iframe has stopped scrolling.
|
|
306
|
+
- `UVEEventType.CONTENTLET_HOVERED`: Triggered when a contentlet is hovered.
|
|
209
307
|
|
|
210
|
-
|
|
308
|
+
### `editContentlet(contentlet)`
|
|
211
309
|
|
|
212
|
-
|
|
310
|
+
`editContentlet` is a function that opens the dotCMS modal editor for any contentlet in or out of page area.
|
|
213
311
|
|
|
214
|
-
|
|
312
|
+
| Input | Type | Required | Description |
|
|
313
|
+
| ------------ | ------------------ | -------- | -------------------------------- |
|
|
314
|
+
| `contentlet` | `Contentlet<T>` | ✅ | The contentlet you want to edit. |
|
|
215
315
|
|
|
216
|
-
|
|
217
|
-
// UVE State Interface
|
|
218
|
-
interface UVEState {
|
|
219
|
-
mode: UVE_MODE;
|
|
220
|
-
persona: string | null;
|
|
221
|
-
variantName: string | null;
|
|
222
|
-
experimentId: string | null;
|
|
223
|
-
publishDate: string | null;
|
|
224
|
-
languageId: string | null;
|
|
225
|
-
}
|
|
316
|
+
#### Usage
|
|
226
317
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
318
|
+
```tsx
|
|
319
|
+
import { editContentlet, getUVEState } from '@dotcms/uve';
|
|
320
|
+
import { UVE_MODE } from '@dotcms/types';
|
|
321
|
+
|
|
322
|
+
const myEditButton = ({ contentlet }) => {
|
|
323
|
+
const uveState = getUVEState();
|
|
324
|
+
|
|
325
|
+
if (uveState?.mode === UVE_MODE.EDIT) {
|
|
326
|
+
return <button onClick={() => editContentlet(contentlet)}>Edit</button>;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return null;
|
|
330
|
+
};
|
|
234
331
|
```
|
|
235
332
|
|
|
236
|
-
###
|
|
333
|
+
### `initInlineEditing(type, data)`
|
|
334
|
+
|
|
335
|
+
`initInlineEditing` is a function that triggers inline editing for supported field types (WYSIWYG or Block Editor).
|
|
336
|
+
|
|
337
|
+
| Input | Type | Required | Description |
|
|
338
|
+
| ----------- | ---------------------------- | -------- | ------------------------------------------------------------------------------ |
|
|
339
|
+
| `type` | `DotCMSInlineEditingType` | ✅ | `'BLOCK_EDITOR'` or `'WYSIWYG'` |
|
|
340
|
+
| `fieldData` | `DotCMSInlineEditingPayload` | ✅ | [Field content required to enable inline editing](#dotcmsinlineeditingpayload) |
|
|
341
|
+
|
|
342
|
+
#### Usage
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
import { initInlineEditing, getUVEState } from "@dotcms/uve";
|
|
346
|
+
import { UVE_MODE } from "@dotcms/types";
|
|
347
|
+
|
|
348
|
+
const MyBanner = ({ contentlet }) => {
|
|
349
|
+
const uveState = getUVEState();
|
|
350
|
+
|
|
351
|
+
const handleClick = () => {
|
|
352
|
+
if (uveState?.mode === UVE_MODE.EDIT) {
|
|
353
|
+
const { inode, contentType, title } = contentlet;
|
|
354
|
+
initInlineEditing("BLOCK_EDITOR", {
|
|
355
|
+
inode,
|
|
356
|
+
contentType,
|
|
357
|
+
content: title,
|
|
358
|
+
fieldName: "title",
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
return (
|
|
363
|
+
<div>
|
|
364
|
+
<h1 onClick={handleClick}>{contentlet.title}</h1>
|
|
365
|
+
<p>{contentlet.description}</p>
|
|
366
|
+
</div>
|
|
367
|
+
);
|
|
368
|
+
};
|
|
369
|
+
```
|
|
237
370
|
|
|
238
|
-
|
|
239
|
-
// Event Types Enum
|
|
240
|
-
enum UVEEventType {
|
|
241
|
-
CONTENT_CHANGES = 'changes',
|
|
242
|
-
PAGE_RELOAD = 'page-reload',
|
|
243
|
-
REQUEST_BOUNDS = 'request-bounds',
|
|
244
|
-
IFRAME_SCROLL = 'iframe-scroll',
|
|
245
|
-
CONTENTLET_HOVERED = 'contentlet-hovered'
|
|
246
|
-
}
|
|
371
|
+
#### DotCMSInlineEditingPayload
|
|
247
372
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
373
|
+
- `inode` (string): The inode of the contentlet to edit.
|
|
374
|
+
- `contentType` (string): The content type of the contentlet to edit.
|
|
375
|
+
- `fieldName` (string): The name of the field to edit.
|
|
376
|
+
- `content` (string): The content of the field to edit.
|
|
377
|
+
|
|
378
|
+
### `enableBlockEditorInline(contentlet, fieldName)`
|
|
379
|
+
|
|
380
|
+
`enableBlockEditorInline` is a shortcut to [enable inline block editing](https://dev.dotcms.com/docs/block-editor#BlockInlineEditor) for a field.
|
|
381
|
+
|
|
382
|
+
| Input | Type | Required | Description |
|
|
383
|
+
| ------------ | ----------------------- | -------- | -------------------------------------------------------------- |
|
|
384
|
+
| `contentlet` | `DotCMSBasicContentlet` | ✅ | The target contentlet |
|
|
385
|
+
| `fieldName` | `string` | ✅ | [Name of the block field to edit](#dotcmsinlineeditingpayload) |
|
|
386
|
+
|
|
387
|
+
#### Usage
|
|
388
|
+
|
|
389
|
+
```tsx
|
|
390
|
+
import { enableBlockEditorInline, getUVEState } from '@dotcms/uve';
|
|
391
|
+
import { UVE_MODE } from '@dotcms/types';
|
|
392
|
+
|
|
393
|
+
const MyBanner = ({ contentlet }) => {
|
|
394
|
+
const uveState = getUVEState();
|
|
395
|
+
|
|
396
|
+
const handleClick = () => {
|
|
397
|
+
if (uveState?.mode === UVE_MODE.EDIT) {
|
|
398
|
+
enableBlockEditorInline(contentlet, 'blockContent');
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
return <MyBlockEditorRender onClick={handleClick} />;
|
|
403
|
+
};
|
|
253
404
|
```
|
|
254
405
|
|
|
255
|
-
|
|
406
|
+
### `updateNavigation(pathname)`
|
|
256
407
|
|
|
257
|
-
|
|
408
|
+
`updateNavigation` is a function that notifies UVE that navigation has changed (e.g., in SPAs).
|
|
258
409
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
if (uveState.mode === UVE_MODE.EDIT) {
|
|
270
|
-
enableEditFeatures();
|
|
271
|
-
}
|
|
272
|
-
}
|
|
410
|
+
| Input | Type | Required | Description |
|
|
411
|
+
| ---------- | -------- | -------- | -------------------------- |
|
|
412
|
+
| `pathname` | `string` | ✅ | The new pathname to update |
|
|
413
|
+
|
|
414
|
+
#### Usage
|
|
415
|
+
|
|
416
|
+
```tsx
|
|
417
|
+
import { updateNavigation } from '@dotcms/uve';
|
|
418
|
+
|
|
419
|
+
updateNavigation('/navigate-to-this-new-page');
|
|
273
420
|
```
|
|
274
421
|
|
|
275
|
-
###
|
|
422
|
+
### `reorderMenu(config?)`
|
|
276
423
|
|
|
277
|
-
|
|
278
|
-
import { createUVESubscription } from '@dotcms/uve';
|
|
279
|
-
import { UVEEventType } from '@dotcms/uve/types';
|
|
424
|
+
`reorderMenu` is a function that opens the UVE menu editor to reorder navigation links.
|
|
280
425
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
updateUI(changes);
|
|
285
|
-
});
|
|
426
|
+
| Input | Type | Required | Description |
|
|
427
|
+
| --------- | ------------------------- | -------- | ---------------------------------------------------------- |
|
|
428
|
+
| `config?` | `DotCMSReorderMenuConfig` | ❌ | [Optional config for reordering](#dotcmsreordermenuconfig) |
|
|
286
429
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
430
|
+
#### Usage
|
|
431
|
+
|
|
432
|
+
```ts
|
|
433
|
+
import { reorderMenu } from '@dotcms/uve';
|
|
434
|
+
|
|
435
|
+
reorderMenu({ startLevel: 2, depth: 3 });
|
|
291
436
|
```
|
|
292
437
|
|
|
293
|
-
|
|
438
|
+
#### DotCMSReorderMenuConfig
|
|
294
439
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
440
|
+
- `startLevel` (number): The level to start reordering from
|
|
441
|
+
- `depth` (number): The depth of the menu to reorder
|
|
442
|
+
|
|
443
|
+
### `sendMessageToUVE(message)`
|
|
444
|
+
|
|
445
|
+
`sendMessageToUVE` is a low-level function to send custom messages to UVE.
|
|
446
|
+
|
|
447
|
+
| Input | Type | Required | Description |
|
|
448
|
+
| --------- | ------------------------------------------ | -------- | ---------------------------- |
|
|
449
|
+
| `message` | [`DotCMSUVEMessage<T>`](#dotcmsuvemessage) | ✅ | Object with action + payload |
|
|
450
|
+
|
|
451
|
+
#### Usage
|
|
452
|
+
|
|
453
|
+
```ts
|
|
454
|
+
sendMessageToUVE({
|
|
455
|
+
action: DotCMSUVEAction.CUSTOM_EVENT,
|
|
456
|
+
payload: { type: 'MyEvent', data: {...} }
|
|
457
|
+
});
|
|
310
458
|
```
|
|
311
459
|
|
|
312
|
-
|
|
460
|
+
#### DotCMSUVEMessage<T>
|
|
461
|
+
|
|
462
|
+
| Event (DotCMSUVEAction) | Payload (T) |
|
|
463
|
+
| ---------------------------------- | ------------------------------------------------------------- | ------- |
|
|
464
|
+
| `NAVIGATION_UPDATE` | `{ url: string }` |
|
|
465
|
+
| `SET_BOUNDS` | `DotCMSContainerBound[]` |
|
|
466
|
+
| `SET_CONTENTLET` | `DotCMSBasicContentlet` |
|
|
467
|
+
| `IFRAME_SCROLL` | `'up' | 'down'` |
|
|
468
|
+
| `IFRAME_SCROLL_END` | --- |
|
|
469
|
+
| `REORDER_MENU` | `DotCMSReorderMenuConfig` |
|
|
470
|
+
| `INIT_INLINE_EDITING` | `DotCMSInlineEditingPayload` |
|
|
471
|
+
| `COPY_CONTENTLET_INLINE_EDITING` | `{ dataset: { inode, language, fieldName: this.fieldName } }` |
|
|
472
|
+
| `UPDATE_CONTENTLET_INLINE_EDITING` | `{ content: string, dataset: { inode, langId, fieldName } }` |
|
|
473
|
+
| `GET_PAGE_DATA` | --- |
|
|
474
|
+
| `CLIENT_READY` | --- |
|
|
475
|
+
| `EDIT_CONTENTLET` | `DotCMSBasicContentlet` |
|
|
476
|
+
|
|
477
|
+
## Troubleshooting
|
|
478
|
+
|
|
479
|
+
### Common Issues & Solutions
|
|
313
480
|
|
|
314
|
-
|
|
481
|
+
#### Memory Management
|
|
315
482
|
|
|
316
|
-
1.
|
|
483
|
+
1. **Memory Leaks**: Application experiences memory leaks
|
|
484
|
+
- **Possible Causes**:
|
|
485
|
+
- Failing to call `destroyUVESubscriptions()` on unmount
|
|
486
|
+
- **Solutions**:
|
|
487
|
+
- Always call `destroyUVESubscriptions()` when your component unmounts to clean up subscriptions
|
|
488
|
+
|
|
489
|
+
#### Editor State
|
|
490
|
+
|
|
491
|
+
1. **Undefined State**: `getUVEState()` returns undefined
|
|
492
|
+
- **Possible Causes**:
|
|
493
|
+
- Application not running inside the dotCMS editor
|
|
494
|
+
- **Solutions**:
|
|
495
|
+
- Ensure your application is running within the dotCMS environment when calling `getUVEState()`
|
|
496
|
+
|
|
497
|
+
#### Event Handling
|
|
498
|
+
|
|
499
|
+
1. **Unsubscribed Events**: Events not unsubscribed leading to unexpected behavior
|
|
500
|
+
- **Possible Causes**:
|
|
501
|
+
- Not unsubscribing from events
|
|
502
|
+
- **Solutions**:
|
|
503
|
+
- Always unsubscribe from events using the `unsubscribe()` method to prevent memory leaks
|
|
504
|
+
|
|
505
|
+
#### Inline Editing
|
|
506
|
+
|
|
507
|
+
1. **Invalid Contentlet or Field**: `initInlineEditing()` requires valid contentlet and field name
|
|
508
|
+
- **Possible Causes**:
|
|
509
|
+
- Incorrect contentlet or field name
|
|
510
|
+
- **Solutions**:
|
|
511
|
+
- Verify that the contentlet and field name are correct and exist in the dotCMS instance
|
|
512
|
+
|
|
513
|
+
#### Non-existent Page Navigation
|
|
514
|
+
|
|
515
|
+
1. **Navigation to a non-existent page**: May break content sync in UVE and make the editor redirect to the home page
|
|
516
|
+
- **Possible Causes**:
|
|
517
|
+
- Navigation to a non-existent page
|
|
518
|
+
- **Solutions**:
|
|
519
|
+
- Ensure the page exists in the dotCMS instance
|
|
520
|
+
|
|
521
|
+
#### Menu Reordering
|
|
522
|
+
|
|
523
|
+
1. **UI Action Requirement**: `reorderMenu()` must be called from a UI action
|
|
524
|
+
- **Possible Causes**:
|
|
525
|
+
- Attempting to auto-trigger `reorderMenu()`
|
|
526
|
+
- **Solutions**:
|
|
527
|
+
- Ensure `reorderMenu()` is triggered by a user action within the UI
|
|
528
|
+
|
|
529
|
+
### Debugging Tips
|
|
530
|
+
|
|
531
|
+
1. **Ensure you are in the UVE Context**
|
|
532
|
+
- Check if you are in the UVE context by calling `getUVEState()`
|
|
533
|
+
- If you are not in the UVE context, you will not be able to use the UVE SDK correctly
|
|
534
|
+
2. **Check Browser Console**
|
|
535
|
+
- Check for errors in the browser console
|
|
536
|
+
- Check for errors in the browser network tab
|
|
537
|
+
3. **Network Monitoring**
|
|
538
|
+
- Use browser dev tools to monitor API calls
|
|
539
|
+
- Check for 401/403 errors (auth issues)
|
|
540
|
+
- Verify asset loading paths
|
|
541
|
+
|
|
542
|
+
### Still Having Issues?
|
|
543
|
+
|
|
544
|
+
If you're still experiencing problems after trying these solutions:
|
|
545
|
+
|
|
546
|
+
1. Search existing [GitHub issues](https://github.com/dotCMS/core/issues)
|
|
547
|
+
2. Check our [community forum](https://community.dotcms.com/)
|
|
548
|
+
3. Create a new issue with:
|
|
549
|
+
- Detailed reproduction steps
|
|
550
|
+
- Environment information
|
|
551
|
+
- Error messages
|
|
552
|
+
- Code samples
|
|
553
|
+
|
|
554
|
+
## dotCMS Support
|
|
555
|
+
|
|
556
|
+
We offer multiple channels to get help with the dotCMS UVE SDK:
|
|
557
|
+
|
|
558
|
+
- **GitHub Issues**: For bug reports and feature requests, please [open an issue](https://github.com/dotCMS/core/issues/new/choose) in the GitHub repository.
|
|
559
|
+
- **Community Forum**: Join our [community discussions](https://community.dotcms.com/) to ask questions and share solutions.
|
|
560
|
+
- **Stack Overflow**: Use the tag `dotcms-uve` when posting questions.
|
|
561
|
+
|
|
562
|
+
When reporting issues, please include:
|
|
563
|
+
|
|
564
|
+
- SDK version you're using
|
|
565
|
+
- dotCMS version
|
|
566
|
+
- Minimal reproduction steps
|
|
567
|
+
- Expected vs. actual behavior
|
|
568
|
+
|
|
569
|
+
Enterprise customers can access premium support through the [dotCMS Support Portal](https://dev.dotcms.com/docs/help).
|
|
570
|
+
|
|
571
|
+
## How To Contribute
|
|
572
|
+
|
|
573
|
+
GitHub pull requests are the preferred method to contribute code to dotCMS. We welcome contributions to the DotCMS UVE SDK! If you'd like to contribute, please follow these steps:
|
|
574
|
+
|
|
575
|
+
1. Fork the repository [dotCMS/core](https://github.com/dotCMS/core)
|
|
317
576
|
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
318
577
|
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
319
578
|
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
320
579
|
5. Open a Pull Request
|
|
321
580
|
|
|
322
|
-
|
|
581
|
+
Please ensure your code follows the existing style and includes appropriate tests.
|
|
582
|
+
|
|
583
|
+
## Licensing Information
|
|
584
|
+
|
|
585
|
+
dotCMS comes in multiple editions and as such is dual-licensed. The dotCMS Community Edition is licensed under the GPL 3.0 and is freely available for download, customization, and deployment for use within organizations of all stripes. dotCMS Enterprise Editions (EE) adds several enterprise features and is available via a supported, indemnified commercial license from dotCMS. For the differences between the editions, see [the feature page](http://www.dotcms.com/cms-platform/features).
|
|
586
|
+
|
|
587
|
+
This SDK is part of dotCMS's dual-licensed platform (GPL 3.0 for Community, commercial license for Enterprise).
|
|
323
588
|
|
|
324
|
-
|
|
589
|
+
[Learn more ](https://www.dotcms.com)at [dotcms.com](https://www.dotcms.com).
|
package/package.json
CHANGED
package/public.cjs.js
CHANGED
|
@@ -1042,7 +1042,7 @@ function enableBlockEditorInline(contentlet, fieldName) {
|
|
|
1042
1042
|
return;
|
|
1043
1043
|
}
|
|
1044
1044
|
const data = {
|
|
1045
|
-
fieldName,
|
|
1045
|
+
fieldName: fieldName,
|
|
1046
1046
|
inode: contentlet.inode,
|
|
1047
1047
|
language: contentlet.languageId,
|
|
1048
1048
|
contentType: contentlet.contentType,
|
package/public.esm.js
CHANGED
|
@@ -1040,7 +1040,7 @@ function enableBlockEditorInline(contentlet, fieldName) {
|
|
|
1040
1040
|
return;
|
|
1041
1041
|
}
|
|
1042
1042
|
const data = {
|
|
1043
|
-
fieldName,
|
|
1043
|
+
fieldName: fieldName,
|
|
1044
1044
|
inode: contentlet.inode,
|
|
1045
1045
|
language: contentlet.languageId,
|
|
1046
1046
|
contentType: contentlet.contentType,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Contentlet,
|
|
1
|
+
import { Contentlet, DotCMSInlineEditingPayload, DotCMSInlineEditingType, DotCMSBasicContentlet, DotCMSPageResponse } from '@dotcms/types';
|
|
2
2
|
import { DotCMSReorderMenuConfig, DotCMSUVEMessage } from '@dotcms/types/internal';
|
|
3
3
|
/**
|
|
4
4
|
* Updates the navigation in the editor.
|
|
@@ -59,7 +59,7 @@ export declare function initInlineEditing(type: DotCMSInlineEditingType, data?:
|
|
|
59
59
|
* @param {string} fieldName
|
|
60
60
|
* @return {*} {void}
|
|
61
61
|
*/
|
|
62
|
-
export declare function enableBlockEditorInline(contentlet: DotCMSBasicContentlet, fieldName:
|
|
62
|
+
export declare function enableBlockEditorInline<T extends DotCMSBasicContentlet>(contentlet: T extends DotCMSBasicContentlet ? T : never, fieldName: keyof T): void;
|
|
63
63
|
/**
|
|
64
64
|
* Initializes the Universal Visual Editor (UVE) with required handlers and event listeners.
|
|
65
65
|
*
|
|
@@ -81,6 +81,6 @@ export declare function enableBlockEditorInline(contentlet: DotCMSBasicContentle
|
|
|
81
81
|
* destroyUVESubscriptions();
|
|
82
82
|
* ```
|
|
83
83
|
*/
|
|
84
|
-
export declare function initUVE(config?:
|
|
84
|
+
export declare function initUVE(config?: DotCMSPageResponse): {
|
|
85
85
|
destroyUVESubscriptions: () => void;
|
|
86
86
|
};
|
package/src/script/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DotCMSPageResponse } from '@dotcms/types';
|
|
2
2
|
/**
|
|
3
3
|
* Sets up scroll event handlers for the window to notify the editor about scroll events.
|
|
4
4
|
* Adds listeners for both 'scroll' and 'scrollend' events, sending appropriate messages
|
|
@@ -44,7 +44,7 @@ export declare function registerUVEEvents(): {
|
|
|
44
44
|
* This is typically called after all UVE event handlers and DOM listeners
|
|
45
45
|
* have been set up successfully.
|
|
46
46
|
*/
|
|
47
|
-
export declare function setClientIsReady(config?:
|
|
47
|
+
export declare function setClientIsReady(config?: DotCMSPageResponse): void;
|
|
48
48
|
/**
|
|
49
49
|
* Listen for block editor inline event.
|
|
50
50
|
*/
|