@dotcms/client 0.0.1-alpha.9 → 0.0.1-beta.2
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 +166 -19
- package/index.cjs.d.ts +1 -0
- package/index.cjs.default.js +1 -0
- package/index.cjs.js +2050 -0
- package/index.cjs.mjs +2 -0
- package/index.esm.d.ts +1 -0
- package/index.esm.js +2038 -0
- package/package.json +36 -25
- package/src/index.d.ts +8 -0
- package/src/lib/client/content/builders/collection/collection.d.ts +226 -0
- package/src/lib/client/content/content-api.d.ts +129 -0
- package/src/lib/client/content/shared/const.d.ts +13 -0
- package/src/lib/client/content/shared/types.d.ts +138 -0
- package/src/lib/client/content/shared/utils.d.ts +20 -0
- package/src/lib/client/models/index.d.ts +12 -0
- package/src/lib/client/models/types.d.ts +13 -0
- package/src/lib/client/sdk-js-client.d.ts +276 -0
- package/src/lib/editor/listeners/listeners.d.ts +45 -0
- package/src/lib/editor/models/client.model.d.ts +98 -0
- package/src/lib/editor/models/editor.model.d.ts +62 -0
- package/src/lib/editor/models/inline-event.model.d.ts +9 -0
- package/src/lib/editor/models/{listeners.model.ts → listeners.model.d.ts} +17 -8
- package/src/lib/editor/sdk-editor-vtl.d.ts +1 -0
- package/src/lib/editor/sdk-editor.d.ts +92 -0
- package/src/lib/editor/utils/editor.utils.d.ts +159 -0
- package/src/lib/editor/utils/traditional-vtl.utils.d.ts +4 -0
- package/src/lib/query-builder/lucene-syntax/Equals.d.ts +114 -0
- package/src/lib/query-builder/lucene-syntax/Field.d.ts +32 -0
- package/src/lib/query-builder/lucene-syntax/NotOperand.d.ts +26 -0
- package/src/lib/query-builder/lucene-syntax/Operand.d.ts +44 -0
- package/src/lib/query-builder/lucene-syntax/index.d.ts +4 -0
- package/src/lib/query-builder/sdk-query-builder.d.ts +76 -0
- package/src/lib/query-builder/utils/index.d.ts +142 -0
- package/src/lib/utils/graphql/transforms.d.ts +24 -0
- package/src/lib/utils/index.d.ts +2 -0
- package/src/lib/utils/page/common-utils.d.ts +33 -0
- package/.eslintrc.json +0 -18
- package/jest.config.ts +0 -15
- package/project.json +0 -63
- package/src/index.ts +0 -4
- package/src/lib/client/sdk-js-client.spec.ts +0 -258
- package/src/lib/client/sdk-js-client.ts +0 -297
- package/src/lib/editor/listeners/listeners.spec.ts +0 -55
- package/src/lib/editor/listeners/listeners.ts +0 -200
- package/src/lib/editor/models/client.model.ts +0 -55
- package/src/lib/editor/models/editor.model.ts +0 -17
- package/src/lib/editor/sdk-editor-vtl.ts +0 -24
- package/src/lib/editor/sdk-editor.spec.ts +0 -95
- package/src/lib/editor/sdk-editor.ts +0 -70
- package/src/lib/editor/utils/editor.utils.spec.ts +0 -164
- package/src/lib/editor/utils/editor.utils.ts +0 -151
- package/tsconfig.json +0 -22
- package/tsconfig.lib.json +0 -10
- package/tsconfig.spec.json +0 -9
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { CUSTOMER_ACTIONS, postMessageToEditor } from '../models/client.model';
|
|
2
|
-
import { DotCMSPageEditorConfig } from '../models/editor.model';
|
|
3
|
-
import { DotCMSPageEditorSubscription, NOTIFY_CUSTOMER } from '../models/listeners.model';
|
|
4
|
-
import {
|
|
5
|
-
findContentletElement,
|
|
6
|
-
getClosestContainerData,
|
|
7
|
-
getPageElementBound
|
|
8
|
-
} from '../utils/editor.utils';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Default reload function that reloads the current window.
|
|
12
|
-
*/
|
|
13
|
-
const defaultReloadFn = () => window.location.reload();
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Configuration object for the DotCMSPageEditor.
|
|
17
|
-
*/
|
|
18
|
-
let pageEditorConfig: DotCMSPageEditorConfig = {
|
|
19
|
-
onReload: defaultReloadFn
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export function setPageEditorConfig(config: DotCMSPageEditorConfig) {
|
|
23
|
-
pageEditorConfig = config;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Represents an array of DotCMSPageEditorSubscription objects.
|
|
28
|
-
* Used to store the subscriptions for the editor and unsubscribe later.
|
|
29
|
-
*/
|
|
30
|
-
export const subscriptions: DotCMSPageEditorSubscription[] = [];
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Sets the bounds of the containers in the editor.
|
|
34
|
-
* Retrieves the containers from the DOM and sends their position data to the editor.
|
|
35
|
-
* @private
|
|
36
|
-
* @memberof DotCMSPageEditor
|
|
37
|
-
*/
|
|
38
|
-
function setBounds() {
|
|
39
|
-
const containers = Array.from(
|
|
40
|
-
document.querySelectorAll('[data-dot-object="container"]')
|
|
41
|
-
) as HTMLDivElement[];
|
|
42
|
-
const positionData = getPageElementBound(containers);
|
|
43
|
-
|
|
44
|
-
postMessageToEditor({
|
|
45
|
-
action: CUSTOMER_ACTIONS.SET_BOUNDS,
|
|
46
|
-
payload: positionData
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Reloads the page and triggers the onReload callback if it exists in the config object.
|
|
52
|
-
*/
|
|
53
|
-
function reloadPage() {
|
|
54
|
-
pageEditorConfig?.onReload();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Listens for editor messages and performs corresponding actions based on the received message.
|
|
59
|
-
*
|
|
60
|
-
* @private
|
|
61
|
-
* @memberof DotCMSPageEditor
|
|
62
|
-
*/
|
|
63
|
-
export function listenEditorMessages() {
|
|
64
|
-
const messageCallback = (event: MessageEvent) => {
|
|
65
|
-
switch (event.data) {
|
|
66
|
-
case NOTIFY_CUSTOMER.EMA_REQUEST_BOUNDS: {
|
|
67
|
-
setBounds();
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
case NOTIFY_CUSTOMER.EMA_RELOAD_PAGE: {
|
|
72
|
-
reloadPage();
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
window.addEventListener('message', messageCallback);
|
|
79
|
-
|
|
80
|
-
subscriptions.push({
|
|
81
|
-
type: 'listener',
|
|
82
|
-
event: 'message',
|
|
83
|
-
callback: messageCallback
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Listens for pointer move events and extracts information about the hovered contentlet.
|
|
89
|
-
*
|
|
90
|
-
* @private
|
|
91
|
-
* @memberof DotCMSPageEditor
|
|
92
|
-
*/
|
|
93
|
-
export function listenHoveredContentlet() {
|
|
94
|
-
const pointerMoveCallback = (event: PointerEvent) => {
|
|
95
|
-
const target = findContentletElement(event.target as HTMLElement);
|
|
96
|
-
if (!target) return;
|
|
97
|
-
const { x, y, width, height } = target.getBoundingClientRect();
|
|
98
|
-
|
|
99
|
-
const contentletPayload = {
|
|
100
|
-
container:
|
|
101
|
-
// Here extract dot-container from contentlet if is Headless
|
|
102
|
-
// or search in parent container if is VTL
|
|
103
|
-
target.dataset?.['dotContainer']
|
|
104
|
-
? JSON.parse(target.dataset?.['dotContainer'])
|
|
105
|
-
: getClosestContainerData(target),
|
|
106
|
-
contentlet: {
|
|
107
|
-
identifier: target.dataset?.['dotIdentifier'],
|
|
108
|
-
title: target.dataset?.['dotTitle'],
|
|
109
|
-
inode: target.dataset?.['dotInode'],
|
|
110
|
-
contentType: target.dataset?.['dotType']
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
postMessageToEditor({
|
|
115
|
-
action: CUSTOMER_ACTIONS.SET_CONTENTLET,
|
|
116
|
-
payload: {
|
|
117
|
-
x,
|
|
118
|
-
y,
|
|
119
|
-
width,
|
|
120
|
-
height,
|
|
121
|
-
payload: contentletPayload
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
document.addEventListener('pointermove', pointerMoveCallback);
|
|
127
|
-
|
|
128
|
-
subscriptions.push({
|
|
129
|
-
type: 'listener',
|
|
130
|
-
event: 'pointermove',
|
|
131
|
-
callback: pointerMoveCallback
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Attaches a scroll event listener to the window
|
|
137
|
-
* and sends a message to the editor when the window is scrolled.
|
|
138
|
-
*
|
|
139
|
-
* @private
|
|
140
|
-
* @memberof DotCMSPageEditor
|
|
141
|
-
*/
|
|
142
|
-
export function scrollHandler() {
|
|
143
|
-
const scrollCallback = () => {
|
|
144
|
-
postMessageToEditor({
|
|
145
|
-
action: CUSTOMER_ACTIONS.IFRAME_SCROLL
|
|
146
|
-
});
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
window.addEventListener('scroll', scrollCallback);
|
|
150
|
-
|
|
151
|
-
subscriptions.push({
|
|
152
|
-
type: 'listener',
|
|
153
|
-
event: 'scroll',
|
|
154
|
-
callback: scrollCallback
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Listens for changes in the content and triggers a customer action when the content changes.
|
|
160
|
-
*
|
|
161
|
-
* @private
|
|
162
|
-
* @memberof DotCMSPageEditor
|
|
163
|
-
*/
|
|
164
|
-
export function listenContentChange() {
|
|
165
|
-
const observer = new MutationObserver((mutationsList) => {
|
|
166
|
-
for (const { addedNodes, removedNodes, type } of mutationsList) {
|
|
167
|
-
if (type === 'childList') {
|
|
168
|
-
const didNodesChanged = [
|
|
169
|
-
...Array.from(addedNodes),
|
|
170
|
-
...Array.from(removedNodes)
|
|
171
|
-
].filter(
|
|
172
|
-
(node) => (node as HTMLDivElement).dataset?.['dotObject'] === 'contentlet'
|
|
173
|
-
).length;
|
|
174
|
-
|
|
175
|
-
if (didNodesChanged) {
|
|
176
|
-
postMessageToEditor({
|
|
177
|
-
action: CUSTOMER_ACTIONS.CONTENT_CHANGE
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
observer.observe(document, { childList: true, subtree: true });
|
|
185
|
-
|
|
186
|
-
subscriptions.push({
|
|
187
|
-
type: 'observer',
|
|
188
|
-
observer
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Sends a ping message to the editor.
|
|
194
|
-
*
|
|
195
|
-
*/
|
|
196
|
-
export function pingEditor() {
|
|
197
|
-
postMessageToEditor({
|
|
198
|
-
action: CUSTOMER_ACTIONS.PING_EDITOR
|
|
199
|
-
});
|
|
200
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Actions send to the dotcms editor
|
|
3
|
-
*
|
|
4
|
-
* @export
|
|
5
|
-
* @enum {number}
|
|
6
|
-
*/
|
|
7
|
-
export enum CUSTOMER_ACTIONS {
|
|
8
|
-
/**
|
|
9
|
-
* Tell the dotcms editor that page change
|
|
10
|
-
*/
|
|
11
|
-
NAVIGATION_UPDATE = 'set-url',
|
|
12
|
-
/**
|
|
13
|
-
* Send the element position of the rows, columnsm containers and contentlets
|
|
14
|
-
*/
|
|
15
|
-
SET_BOUNDS = 'set-bounds',
|
|
16
|
-
/**
|
|
17
|
-
* Send the information of the hovered contentlet
|
|
18
|
-
*/
|
|
19
|
-
SET_CONTENTLET = 'set-contentlet',
|
|
20
|
-
/**
|
|
21
|
-
* Tell the editor that the page is being scrolled
|
|
22
|
-
*/
|
|
23
|
-
IFRAME_SCROLL = 'scroll',
|
|
24
|
-
/**
|
|
25
|
-
* Ping the editor to see if the page is inside the editor
|
|
26
|
-
*/
|
|
27
|
-
PING_EDITOR = 'ping-editor',
|
|
28
|
-
|
|
29
|
-
CONTENT_CHANGE = 'content-change',
|
|
30
|
-
|
|
31
|
-
NOOP = 'noop'
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Post message props
|
|
36
|
-
*
|
|
37
|
-
* @export
|
|
38
|
-
* @template T
|
|
39
|
-
* @interface PostMessageProps
|
|
40
|
-
*/
|
|
41
|
-
type PostMessageProps<T> = {
|
|
42
|
-
action: CUSTOMER_ACTIONS;
|
|
43
|
-
payload?: T;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Post message to dotcms page editor
|
|
48
|
-
*
|
|
49
|
-
* @export
|
|
50
|
-
* @template T
|
|
51
|
-
* @param {PostMessageProps<T>} message
|
|
52
|
-
*/
|
|
53
|
-
export function postMessageToEditor<T = unknown>(message: PostMessageProps<T>) {
|
|
54
|
-
window.parent.postMessage(message, '*');
|
|
55
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* Represents the configuration options for the DotCMS page editor.
|
|
4
|
-
* @export
|
|
5
|
-
* @interface DotCMSPageEditorConfig
|
|
6
|
-
*/
|
|
7
|
-
export interface DotCMSPageEditorConfig {
|
|
8
|
-
/**
|
|
9
|
-
* A callback function that will be called when the page editor needs to be reloaded.
|
|
10
|
-
*/
|
|
11
|
-
onReload: () => void;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The pathname of the page being edited. Optional.
|
|
15
|
-
*/
|
|
16
|
-
pathname?: string;
|
|
17
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
listenContentChange,
|
|
3
|
-
listenEditorMessages,
|
|
4
|
-
listenHoveredContentlet,
|
|
5
|
-
pingEditor
|
|
6
|
-
} from './listeners/listeners';
|
|
7
|
-
import { isInsideEditor } from './sdk-editor';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* This is the main entry point for the SDK VTL.
|
|
11
|
-
* This is added to VTL Script in the EditPage
|
|
12
|
-
*
|
|
13
|
-
* @remarks
|
|
14
|
-
* This module sets up the necessary listeners and functionality for the SDK VTL.
|
|
15
|
-
* It checks if the script is running inside the editor and then initializes the client by pinging the editor,
|
|
16
|
-
* listening for editor messages, hovered contentlet changes, and content changes.
|
|
17
|
-
*
|
|
18
|
-
*/
|
|
19
|
-
if (isInsideEditor()) {
|
|
20
|
-
pingEditor();
|
|
21
|
-
listenEditorMessages();
|
|
22
|
-
listenHoveredContentlet();
|
|
23
|
-
listenContentChange();
|
|
24
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
listenContentChange,
|
|
3
|
-
listenEditorMessages,
|
|
4
|
-
listenHoveredContentlet,
|
|
5
|
-
pingEditor,
|
|
6
|
-
scrollHandler
|
|
7
|
-
} from './listeners/listeners';
|
|
8
|
-
import { postMessageToEditor, CUSTOMER_ACTIONS } from './models/client.model';
|
|
9
|
-
import { initEditor, isInsideEditor, updateNavigation } from './sdk-editor';
|
|
10
|
-
|
|
11
|
-
jest.mock('./models/client.model', () => ({
|
|
12
|
-
postMessageToEditor: jest.fn(),
|
|
13
|
-
CUSTOMER_ACTIONS: {
|
|
14
|
-
NAVIGATION_UPDATE: 'set-url',
|
|
15
|
-
SET_BOUNDS: 'set-bounds',
|
|
16
|
-
SET_CONTENTLET: 'set-contentlet',
|
|
17
|
-
IFRAME_SCROLL: 'scroll',
|
|
18
|
-
PING_EDITOR: 'ping-editor',
|
|
19
|
-
CONTENT_CHANGE: 'content-change',
|
|
20
|
-
NOOP: 'noop'
|
|
21
|
-
}
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
jest.mock('./listeners/listeners', () => ({
|
|
25
|
-
pingEditor: jest.fn(),
|
|
26
|
-
listenEditorMessages: jest.fn(),
|
|
27
|
-
listenHoveredContentlet: jest.fn(),
|
|
28
|
-
scrollHandler: jest.fn(),
|
|
29
|
-
listenContentChange: jest.fn()
|
|
30
|
-
}));
|
|
31
|
-
|
|
32
|
-
describe('DotCMSPageEditor', () => {
|
|
33
|
-
describe('is NOT inside editor', () => {
|
|
34
|
-
beforeEach(() => {
|
|
35
|
-
const mockWindow = {
|
|
36
|
-
...window,
|
|
37
|
-
parent: window
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const spy = jest.spyOn(global, 'window', 'get');
|
|
41
|
-
spy.mockReturnValueOnce(mockWindow as unknown as Window & typeof globalThis);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
afterEach(() => {
|
|
45
|
-
jest.clearAllMocks();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('should initialize without any listener', () => {
|
|
49
|
-
const addEventListenerSpy = jest.spyOn(window, 'addEventListener');
|
|
50
|
-
|
|
51
|
-
expect(isInsideEditor()).toBe(false);
|
|
52
|
-
expect(addEventListenerSpy).not.toHaveBeenCalled();
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe('is inside editor', () => {
|
|
57
|
-
beforeEach(() => {
|
|
58
|
-
const mockWindow = {
|
|
59
|
-
...window,
|
|
60
|
-
parent: null
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const spy = jest.spyOn(global, 'window', 'get');
|
|
64
|
-
spy.mockReturnValue(mockWindow as unknown as Window & typeof globalThis);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
afterEach(() => {
|
|
68
|
-
jest.clearAllMocks();
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('should initialize properly', () => {
|
|
72
|
-
expect(isInsideEditor()).toBe(true);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('should update navigation', () => {
|
|
76
|
-
listenContentChange();
|
|
77
|
-
updateNavigation('/');
|
|
78
|
-
expect(postMessageToEditor).toHaveBeenCalledWith({
|
|
79
|
-
action: CUSTOMER_ACTIONS.NAVIGATION_UPDATE,
|
|
80
|
-
payload: {
|
|
81
|
-
url: 'index'
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should init editor calling listeners', () => {
|
|
87
|
-
initEditor();
|
|
88
|
-
expect(pingEditor).toHaveBeenCalled();
|
|
89
|
-
expect(listenEditorMessages).toHaveBeenCalled();
|
|
90
|
-
expect(listenHoveredContentlet).toHaveBeenCalled();
|
|
91
|
-
expect(scrollHandler).toHaveBeenCalled();
|
|
92
|
-
expect(listenContentChange).toHaveBeenCalled();
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
});
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
listenContentChange,
|
|
3
|
-
listenEditorMessages,
|
|
4
|
-
listenHoveredContentlet,
|
|
5
|
-
pingEditor,
|
|
6
|
-
scrollHandler,
|
|
7
|
-
subscriptions,
|
|
8
|
-
setPageEditorConfig
|
|
9
|
-
} from './listeners/listeners';
|
|
10
|
-
import { CUSTOMER_ACTIONS, postMessageToEditor } from './models/client.model';
|
|
11
|
-
import { DotCMSPageEditorConfig } from './models/editor.model';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
15
|
-
* Updates the navigation in the editor.
|
|
16
|
-
* @param {string} pathname - The pathname to update the navigation with.
|
|
17
|
-
* @memberof DotCMSPageEditor
|
|
18
|
-
*/
|
|
19
|
-
export function updateNavigation(pathname: string) {
|
|
20
|
-
postMessageToEditor({
|
|
21
|
-
action: CUSTOMER_ACTIONS.NAVIGATION_UPDATE,
|
|
22
|
-
payload: {
|
|
23
|
-
url: pathname === '/' ? 'index' : pathname?.replace('/', '')
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Checks if the code is running inside an editor.
|
|
30
|
-
* @returns {boolean} Returns true if the code is running inside an editor, otherwise false.
|
|
31
|
-
*/
|
|
32
|
-
export function isInsideEditor() {
|
|
33
|
-
if (window.parent === window) {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Initializes the DotCMS page editor.
|
|
42
|
-
*
|
|
43
|
-
* @param conf - Optional configuration for the editor.
|
|
44
|
-
*/
|
|
45
|
-
export function initEditor(config?: DotCMSPageEditorConfig) {
|
|
46
|
-
if (config) {
|
|
47
|
-
setPageEditorConfig(config);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
pingEditor();
|
|
51
|
-
listenEditorMessages();
|
|
52
|
-
listenHoveredContentlet();
|
|
53
|
-
scrollHandler();
|
|
54
|
-
listenContentChange();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Destroys the editor by removing event listeners and disconnecting observers.
|
|
59
|
-
*/
|
|
60
|
-
export function destroyEditor() {
|
|
61
|
-
subscriptions.forEach((subscription) => {
|
|
62
|
-
if (subscription.type === 'listener') {
|
|
63
|
-
window.removeEventListener(subscription.event, subscription.callback as EventListener);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (subscription.type === 'observer') {
|
|
67
|
-
subscription.observer.disconnect();
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
}
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { getContentletsBound } from './editor.utils';
|
|
2
|
-
|
|
3
|
-
describe('getContentletsBound', () => {
|
|
4
|
-
const createContentlet = ({
|
|
5
|
-
x,
|
|
6
|
-
y,
|
|
7
|
-
width,
|
|
8
|
-
height,
|
|
9
|
-
dataset
|
|
10
|
-
}: {
|
|
11
|
-
x: number;
|
|
12
|
-
y: number;
|
|
13
|
-
width: number;
|
|
14
|
-
height: number;
|
|
15
|
-
dataset: { [key: string]: string };
|
|
16
|
-
}): HTMLDivElement => {
|
|
17
|
-
const contentlet = document.createElement('div');
|
|
18
|
-
const mockGetBoundingClientRect = jest.fn(() => ({
|
|
19
|
-
x,
|
|
20
|
-
y,
|
|
21
|
-
width,
|
|
22
|
-
height
|
|
23
|
-
})) as unknown as () => DOMRect;
|
|
24
|
-
contentlet.getBoundingClientRect = mockGetBoundingClientRect;
|
|
25
|
-
Object.keys(dataset).forEach((key) => {
|
|
26
|
-
contentlet.setAttribute(`data-${key}`, dataset[key]);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
return contentlet;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const containerRect = {
|
|
33
|
-
x: 0,
|
|
34
|
-
y: 0,
|
|
35
|
-
width: 100,
|
|
36
|
-
height: 100,
|
|
37
|
-
top: 0,
|
|
38
|
-
right: 100,
|
|
39
|
-
bottom: 100,
|
|
40
|
-
left: 0
|
|
41
|
-
} as DOMRect;
|
|
42
|
-
|
|
43
|
-
const contentlets: HTMLDivElement[] = [
|
|
44
|
-
createContentlet({
|
|
45
|
-
x: 10,
|
|
46
|
-
y: 20,
|
|
47
|
-
width: 30,
|
|
48
|
-
height: 40,
|
|
49
|
-
dataset: {
|
|
50
|
-
'dot-container': JSON.stringify({ uuid: 'container1' }),
|
|
51
|
-
'dot-identifier': 'contentlet1',
|
|
52
|
-
'dot-title': 'Contentlet 1',
|
|
53
|
-
'dot-inode': 'inode1',
|
|
54
|
-
'dot-type': 'type1'
|
|
55
|
-
}
|
|
56
|
-
}),
|
|
57
|
-
createContentlet({
|
|
58
|
-
x: 50,
|
|
59
|
-
y: 60,
|
|
60
|
-
width: 70,
|
|
61
|
-
height: 80,
|
|
62
|
-
dataset: {
|
|
63
|
-
'dot-container': JSON.stringify({ uuid: 'container1' }),
|
|
64
|
-
'dot-identifier': 'contentlet2',
|
|
65
|
-
'dot-title': 'Contentlet 2',
|
|
66
|
-
'dot-inode': 'inode2',
|
|
67
|
-
'dot-type': 'type2'
|
|
68
|
-
}
|
|
69
|
-
})
|
|
70
|
-
];
|
|
71
|
-
|
|
72
|
-
it('should return an array of contentlets bound from contentlet with data atrribute dotContainer ', () => {
|
|
73
|
-
const result = getContentletsBound(containerRect, contentlets);
|
|
74
|
-
|
|
75
|
-
expect(result).toEqual([
|
|
76
|
-
{
|
|
77
|
-
x: 0,
|
|
78
|
-
y: 20,
|
|
79
|
-
width: 30,
|
|
80
|
-
height: 40,
|
|
81
|
-
payload: JSON.stringify({
|
|
82
|
-
container: { uuid: 'container1' },
|
|
83
|
-
contentlet: {
|
|
84
|
-
identifier: 'contentlet1',
|
|
85
|
-
title: 'Contentlet 1',
|
|
86
|
-
inode: 'inode1',
|
|
87
|
-
contentType: 'type1'
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
x: 0,
|
|
93
|
-
y: 60,
|
|
94
|
-
width: 70,
|
|
95
|
-
height: 80,
|
|
96
|
-
payload: JSON.stringify({
|
|
97
|
-
container: { uuid: 'container1' },
|
|
98
|
-
contentlet: {
|
|
99
|
-
identifier: 'contentlet2',
|
|
100
|
-
title: 'Contentlet 2',
|
|
101
|
-
inode: 'inode2',
|
|
102
|
-
contentType: 'type2'
|
|
103
|
-
}
|
|
104
|
-
})
|
|
105
|
-
}
|
|
106
|
-
]);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('should return an empty array if contentlets is empty', () => {
|
|
110
|
-
const result = getContentletsBound(containerRect, []);
|
|
111
|
-
|
|
112
|
-
expect(result).toEqual([]);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('should return an array of contentlets with correct properties when dotContainer is not present in dataset', () => {
|
|
116
|
-
const contentletsWithMissingContainer: HTMLDivElement[] = [
|
|
117
|
-
createContentlet({
|
|
118
|
-
x: 10,
|
|
119
|
-
y: 20,
|
|
120
|
-
width: 30,
|
|
121
|
-
height: 40,
|
|
122
|
-
dataset: {
|
|
123
|
-
'dot-identifier': 'contentlet1',
|
|
124
|
-
'dot-title': 'Contentlet 1',
|
|
125
|
-
'dot-inode': 'inode1',
|
|
126
|
-
'dot-type': 'type1'
|
|
127
|
-
}
|
|
128
|
-
})
|
|
129
|
-
];
|
|
130
|
-
|
|
131
|
-
const container = document.createElement('div');
|
|
132
|
-
|
|
133
|
-
container.appendChild(contentletsWithMissingContainer[0]);
|
|
134
|
-
container.setAttribute('data-dot-object', 'container');
|
|
135
|
-
container.setAttribute('data-dot-accept-types', '[Blogs]');
|
|
136
|
-
container.setAttribute('data-dot-identifier', '1');
|
|
137
|
-
container.setAttribute('data-max-contentlets', '1');
|
|
138
|
-
container.setAttribute('data-dot-uuid', '1');
|
|
139
|
-
const result = getContentletsBound(containerRect, contentletsWithMissingContainer);
|
|
140
|
-
|
|
141
|
-
expect(result).toEqual([
|
|
142
|
-
{
|
|
143
|
-
x: 0,
|
|
144
|
-
y: 20,
|
|
145
|
-
width: 30,
|
|
146
|
-
height: 40,
|
|
147
|
-
payload: JSON.stringify({
|
|
148
|
-
container: {
|
|
149
|
-
acceptTypes: '[Blogs]',
|
|
150
|
-
identifier: '1',
|
|
151
|
-
maxContentlets: '1',
|
|
152
|
-
uuid: '1'
|
|
153
|
-
},
|
|
154
|
-
contentlet: {
|
|
155
|
-
identifier: 'contentlet1',
|
|
156
|
-
title: 'Contentlet 1',
|
|
157
|
-
inode: 'inode1',
|
|
158
|
-
contentType: 'type1'
|
|
159
|
-
}
|
|
160
|
-
})
|
|
161
|
-
}
|
|
162
|
-
]);
|
|
163
|
-
});
|
|
164
|
-
});
|