@dotcms/client 0.0.1-alpha.40 → 0.0.1-alpha.41
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/index.cjs.d.ts +1 -0
- package/index.cjs.default.js +1 -0
- package/index.cjs.js +1953 -0
- package/index.cjs.mjs +2 -0
- package/index.esm.d.ts +1 -0
- package/index.esm.js +1944 -0
- package/package.json +16 -4
- package/src/index.d.ts +6 -0
- package/src/lib/client/content/builders/collection/{collection.ts → collection.d.ts} +19 -209
- package/src/lib/client/content/{content-api.ts → content-api.d.ts} +4 -14
- package/src/lib/client/content/shared/{const.ts → const.d.ts} +3 -5
- package/src/lib/client/content/shared/{types.ts → types.d.ts} +2 -19
- package/src/lib/client/content/shared/{utils.ts → utils.d.ts} +1 -9
- package/src/lib/client/models/{index.ts → index.d.ts} +1 -8
- package/src/lib/client/models/{types.ts → types.d.ts} +0 -1
- package/src/lib/client/{sdk-js-client.ts → sdk-js-client.d.ts} +15 -181
- package/src/lib/editor/listeners/listeners.d.ts +50 -0
- package/src/lib/editor/models/{client.model.ts → client.model.d.ts} +16 -19
- package/src/lib/editor/models/{editor.model.ts → editor.model.d.ts} +5 -9
- package/src/lib/editor/models/{listeners.model.ts → listeners.model.d.ts} +6 -9
- package/src/lib/editor/sdk-editor-vtl.d.ts +6 -0
- package/src/lib/editor/sdk-editor.d.ts +54 -0
- package/src/lib/editor/utils/{editor.utils.ts → editor.utils.d.ts} +22 -121
- package/src/lib/query-builder/lucene-syntax/{Equals.ts → Equals.d.ts} +11 -45
- package/src/lib/query-builder/lucene-syntax/{Field.ts → Field.d.ts} +5 -13
- package/src/lib/query-builder/lucene-syntax/{NotOperand.ts → NotOperand.d.ts} +5 -13
- package/src/lib/query-builder/lucene-syntax/{Operand.ts → Operand.d.ts} +7 -21
- package/src/lib/query-builder/{sdk-query-builder.ts → sdk-query-builder.d.ts} +5 -16
- package/src/lib/query-builder/utils/{index.ts → index.d.ts} +12 -49
- package/src/lib/utils/graphql/transforms.d.ts +24 -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 -72
- package/src/index.ts +0 -30
- package/src/lib/client/content/builders/collection/collection.spec.ts +0 -515
- package/src/lib/client/sdk-js-client.spec.ts +0 -483
- package/src/lib/editor/listeners/listeners.spec.ts +0 -119
- package/src/lib/editor/listeners/listeners.ts +0 -223
- package/src/lib/editor/sdk-editor-vtl.ts +0 -31
- package/src/lib/editor/sdk-editor.spec.ts +0 -116
- package/src/lib/editor/sdk-editor.ts +0 -105
- package/src/lib/editor/utils/editor.utils.spec.ts +0 -206
- package/src/lib/query-builder/sdk-query-builder.spec.ts +0 -159
- package/src/lib/utils/graphql/transforms.spec.ts +0 -150
- package/src/lib/utils/graphql/transforms.ts +0 -99
- package/src/lib/utils/page/common-utils.spec.ts +0 -37
- package/src/lib/utils/page/common-utils.ts +0 -64
- package/tsconfig.json +0 -22
- package/tsconfig.lib.json +0 -13
- package/tsconfig.spec.json +0 -9
- /package/src/lib/query-builder/lucene-syntax/{index.ts → index.d.ts} +0 -0
- /package/src/lib/utils/{index.ts → index.d.ts} +0 -0
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { CUSTOMER_ACTIONS, postMessageToEditor } from '../models/client.model';
|
|
2
|
-
import { DotCMSPageEditorSubscription, NOTIFY_CUSTOMER } from '../models/listeners.model';
|
|
3
|
-
import {
|
|
4
|
-
findVTLData,
|
|
5
|
-
findDotElement,
|
|
6
|
-
getClosestContainerData,
|
|
7
|
-
getPageElementBound,
|
|
8
|
-
scrollIsInBottom
|
|
9
|
-
} from '../utils/editor.utils';
|
|
10
|
-
|
|
11
|
-
declare global {
|
|
12
|
-
interface Window {
|
|
13
|
-
lastScrollYPosition: number;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Represents an array of DotCMSPageEditorSubscription objects.
|
|
19
|
-
* Used to store the subscriptions for the editor and unsubscribe later.
|
|
20
|
-
*/
|
|
21
|
-
export const subscriptions: DotCMSPageEditorSubscription[] = [];
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Sets the bounds of the containers in the editor.
|
|
25
|
-
* Retrieves the containers from the DOM and sends their position data to the editor.
|
|
26
|
-
* @private
|
|
27
|
-
* @memberof DotCMSPageEditor
|
|
28
|
-
*/
|
|
29
|
-
function setBounds(): void {
|
|
30
|
-
const containers = Array.from(
|
|
31
|
-
document.querySelectorAll('[data-dot-object="container"]')
|
|
32
|
-
) as HTMLDivElement[];
|
|
33
|
-
const positionData = getPageElementBound(containers);
|
|
34
|
-
|
|
35
|
-
postMessageToEditor({
|
|
36
|
-
action: CUSTOMER_ACTIONS.SET_BOUNDS,
|
|
37
|
-
payload: positionData
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Listens for editor messages and performs corresponding actions based on the received message.
|
|
43
|
-
*
|
|
44
|
-
* @private
|
|
45
|
-
* @memberof DotCMSPageEditor
|
|
46
|
-
*/
|
|
47
|
-
export function listenEditorMessages(): void {
|
|
48
|
-
const messageCallback = (event: MessageEvent) => {
|
|
49
|
-
switch (event.data) {
|
|
50
|
-
case NOTIFY_CUSTOMER.EMA_REQUEST_BOUNDS: {
|
|
51
|
-
setBounds();
|
|
52
|
-
break;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (event.data.name === NOTIFY_CUSTOMER.EMA_SCROLL_INSIDE_IFRAME) {
|
|
57
|
-
const direction = event.data.direction;
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
(window.scrollY === 0 && direction === 'up') ||
|
|
61
|
-
(scrollIsInBottom() && direction === 'down')
|
|
62
|
-
) {
|
|
63
|
-
// If the iframe scroll is at the top or bottom, do not send anything.
|
|
64
|
-
// This avoids losing the scrollend event.
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const scrollY = direction === 'up' ? -120 : 120;
|
|
69
|
-
window.scrollBy({ left: 0, top: scrollY, behavior: 'smooth' });
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
window.addEventListener('message', messageCallback);
|
|
74
|
-
|
|
75
|
-
subscriptions.push({
|
|
76
|
-
type: 'listener',
|
|
77
|
-
event: 'message',
|
|
78
|
-
callback: messageCallback
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Listens for pointer move events and extracts information about the hovered contentlet.
|
|
84
|
-
*
|
|
85
|
-
* @private
|
|
86
|
-
* @memberof DotCMSPageEditor
|
|
87
|
-
*/
|
|
88
|
-
export function listenHoveredContentlet(): void {
|
|
89
|
-
const pointerMoveCallback = (event: PointerEvent) => {
|
|
90
|
-
const foundElement = findDotElement(event.target as HTMLElement);
|
|
91
|
-
|
|
92
|
-
if (!foundElement) return;
|
|
93
|
-
|
|
94
|
-
const { x, y, width, height } = foundElement.getBoundingClientRect();
|
|
95
|
-
|
|
96
|
-
const isContainer = foundElement.dataset?.['dotObject'] === 'container';
|
|
97
|
-
|
|
98
|
-
const contentletForEmptyContainer = {
|
|
99
|
-
identifier: 'TEMP_EMPTY_CONTENTLET',
|
|
100
|
-
title: 'TEMP_EMPTY_CONTENTLET',
|
|
101
|
-
contentType: 'TEMP_EMPTY_CONTENTLET_TYPE',
|
|
102
|
-
inode: 'TEMPY_EMPTY_CONTENTLET_INODE',
|
|
103
|
-
widgetTitle: 'TEMP_EMPTY_CONTENTLET',
|
|
104
|
-
baseType: 'TEMP_EMPTY_CONTENTLET',
|
|
105
|
-
onNumberOfPages: 1
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const contentlet = {
|
|
109
|
-
identifier: foundElement.dataset?.['dotIdentifier'],
|
|
110
|
-
title: foundElement.dataset?.['dotTitle'],
|
|
111
|
-
inode: foundElement.dataset?.['dotInode'],
|
|
112
|
-
contentType: foundElement.dataset?.['dotType'],
|
|
113
|
-
baseType: foundElement.dataset?.['dotBasetype'],
|
|
114
|
-
widgetTitle: foundElement.dataset?.['dotWidgetTitle'],
|
|
115
|
-
onNumberOfPages: foundElement.dataset?.['dotOnNumberOfPages']
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const vtlFiles = findVTLData(foundElement);
|
|
119
|
-
const contentletPayload = {
|
|
120
|
-
container:
|
|
121
|
-
// Here extract dot-container from contentlet if it is Headless
|
|
122
|
-
// or search in parent container if it is VTL
|
|
123
|
-
foundElement.dataset?.['dotContainer']
|
|
124
|
-
? JSON.parse(foundElement.dataset?.['dotContainer'])
|
|
125
|
-
: getClosestContainerData(foundElement),
|
|
126
|
-
contentlet: isContainer ? contentletForEmptyContainer : contentlet,
|
|
127
|
-
vtlFiles
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
postMessageToEditor({
|
|
131
|
-
action: CUSTOMER_ACTIONS.SET_CONTENTLET,
|
|
132
|
-
payload: {
|
|
133
|
-
x,
|
|
134
|
-
y,
|
|
135
|
-
width,
|
|
136
|
-
height,
|
|
137
|
-
payload: contentletPayload
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
document.addEventListener('pointermove', pointerMoveCallback);
|
|
143
|
-
|
|
144
|
-
subscriptions.push({
|
|
145
|
-
type: 'listener',
|
|
146
|
-
event: 'pointermove',
|
|
147
|
-
callback: pointerMoveCallback
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Attaches a scroll event listener to the window
|
|
153
|
-
* and sends a message to the editor when the window is scrolled.
|
|
154
|
-
*
|
|
155
|
-
* @private
|
|
156
|
-
* @memberof DotCMSPageEditor
|
|
157
|
-
*/
|
|
158
|
-
export function scrollHandler(): void {
|
|
159
|
-
const scrollCallback = () => {
|
|
160
|
-
postMessageToEditor({
|
|
161
|
-
action: CUSTOMER_ACTIONS.IFRAME_SCROLL
|
|
162
|
-
});
|
|
163
|
-
window.lastScrollYPosition = window.scrollY;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const scrollEndCallback = () => {
|
|
167
|
-
postMessageToEditor({
|
|
168
|
-
action: CUSTOMER_ACTIONS.IFRAME_SCROLL_END
|
|
169
|
-
});
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
window.addEventListener('scroll', scrollCallback);
|
|
173
|
-
window.addEventListener('scrollend', scrollEndCallback);
|
|
174
|
-
|
|
175
|
-
subscriptions.push({
|
|
176
|
-
type: 'listener',
|
|
177
|
-
event: 'scroll',
|
|
178
|
-
callback: scrollEndCallback
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
subscriptions.push({
|
|
182
|
-
type: 'listener',
|
|
183
|
-
event: 'scroll',
|
|
184
|
-
callback: scrollCallback
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Restores the scroll position of the window when an iframe is loaded.
|
|
190
|
-
* Only used in VTL Pages.
|
|
191
|
-
* @export
|
|
192
|
-
* @example
|
|
193
|
-
* ```ts
|
|
194
|
-
* preserveScrollOnIframe();
|
|
195
|
-
* ```
|
|
196
|
-
*/
|
|
197
|
-
export function preserveScrollOnIframe(): void {
|
|
198
|
-
const preserveScrollCallback = () => {
|
|
199
|
-
window.scrollTo(0, window.lastScrollYPosition);
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
window.addEventListener('load', preserveScrollCallback);
|
|
203
|
-
subscriptions.push({
|
|
204
|
-
type: 'listener',
|
|
205
|
-
event: 'scroll',
|
|
206
|
-
callback: preserveScrollCallback
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Sends a message to the editor to get the page data.
|
|
212
|
-
* @param {string} pathname - The pathname of the page.
|
|
213
|
-
* @private
|
|
214
|
-
* @memberof DotCMSPageEditor
|
|
215
|
-
*/
|
|
216
|
-
export function fetchPageDataFromInsideUVE(pathname: string) {
|
|
217
|
-
postMessageToEditor({
|
|
218
|
-
action: CUSTOMER_ACTIONS.GET_PAGE_DATA,
|
|
219
|
-
payload: {
|
|
220
|
-
pathname
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
listenEditorMessages,
|
|
3
|
-
listenHoveredContentlet,
|
|
4
|
-
preserveScrollOnIframe,
|
|
5
|
-
scrollHandler
|
|
6
|
-
} from './listeners/listeners';
|
|
7
|
-
import { isInsideEditor, addClassToEmptyContentlets } from './sdk-editor';
|
|
8
|
-
|
|
9
|
-
declare global {
|
|
10
|
-
interface Window {
|
|
11
|
-
lastScrollYPosition: number;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* This is the main entry point for the SDK VTL.
|
|
17
|
-
* This is added to VTL Script in the EditPage
|
|
18
|
-
*
|
|
19
|
-
* @remarks
|
|
20
|
-
* This module sets up the necessary listeners and functionality for the SDK VTL.
|
|
21
|
-
* It checks if the script is running inside the editor and then initializes the client by pinging the editor,
|
|
22
|
-
* listening for editor messages, hovered contentlet changes, and content changes.
|
|
23
|
-
*
|
|
24
|
-
*/
|
|
25
|
-
if (isInsideEditor()) {
|
|
26
|
-
listenEditorMessages();
|
|
27
|
-
scrollHandler();
|
|
28
|
-
preserveScrollOnIframe();
|
|
29
|
-
listenHoveredContentlet();
|
|
30
|
-
addClassToEmptyContentlets();
|
|
31
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
listenEditorMessages,
|
|
3
|
-
listenHoveredContentlet,
|
|
4
|
-
fetchPageDataFromInsideUVE,
|
|
5
|
-
scrollHandler
|
|
6
|
-
} from './listeners/listeners';
|
|
7
|
-
import { postMessageToEditor, CUSTOMER_ACTIONS } from './models/client.model';
|
|
8
|
-
import {
|
|
9
|
-
addClassToEmptyContentlets,
|
|
10
|
-
initEditor,
|
|
11
|
-
isInsideEditor,
|
|
12
|
-
updateNavigation
|
|
13
|
-
} from './sdk-editor';
|
|
14
|
-
|
|
15
|
-
jest.mock('./models/client.model', () => ({
|
|
16
|
-
postMessageToEditor: jest.fn(),
|
|
17
|
-
CUSTOMER_ACTIONS: {
|
|
18
|
-
NAVIGATION_UPDATE: 'set-url',
|
|
19
|
-
SET_BOUNDS: 'set-bounds',
|
|
20
|
-
SET_CONTENTLET: 'set-contentlet',
|
|
21
|
-
IFRAME_SCROLL: 'scroll',
|
|
22
|
-
PING_EDITOR: 'ping-editor',
|
|
23
|
-
CONTENT_CHANGE: 'content-change',
|
|
24
|
-
NOOP: 'noop'
|
|
25
|
-
}
|
|
26
|
-
}));
|
|
27
|
-
|
|
28
|
-
jest.mock('./listeners/listeners', () => ({
|
|
29
|
-
pingEditor: jest.fn(),
|
|
30
|
-
listenEditorMessages: jest.fn(),
|
|
31
|
-
listenHoveredContentlet: jest.fn(),
|
|
32
|
-
scrollHandler: jest.fn(),
|
|
33
|
-
listenContentChange: jest.fn(),
|
|
34
|
-
fetchPageDataFromInsideUVE: jest.fn()
|
|
35
|
-
}));
|
|
36
|
-
|
|
37
|
-
describe('DotCMSPageEditor', () => {
|
|
38
|
-
describe('is NOT inside editor', () => {
|
|
39
|
-
beforeEach(() => {
|
|
40
|
-
const mockWindow = {
|
|
41
|
-
...window,
|
|
42
|
-
parent: window
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const spy = jest.spyOn(global, 'window', 'get');
|
|
46
|
-
spy.mockReturnValueOnce(mockWindow as unknown as Window & typeof globalThis);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
afterEach(() => {
|
|
50
|
-
jest.clearAllMocks();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should initialize without any listener', () => {
|
|
54
|
-
const addEventListenerSpy = jest.spyOn(window, 'addEventListener');
|
|
55
|
-
|
|
56
|
-
expect(isInsideEditor()).toBe(false);
|
|
57
|
-
expect(addEventListenerSpy).not.toHaveBeenCalled();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('is inside editor', () => {
|
|
62
|
-
beforeEach(() => {
|
|
63
|
-
const mockWindow = {
|
|
64
|
-
...window,
|
|
65
|
-
parent: null
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const spy = jest.spyOn(global, 'window', 'get');
|
|
69
|
-
spy.mockReturnValue(mockWindow as unknown as Window & typeof globalThis);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
afterEach(() => {
|
|
73
|
-
jest.clearAllMocks();
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('should initialize properly', () => {
|
|
77
|
-
expect(isInsideEditor()).toBe(true);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should update navigation', () => {
|
|
81
|
-
updateNavigation('/');
|
|
82
|
-
expect(postMessageToEditor).toHaveBeenCalledWith({
|
|
83
|
-
action: CUSTOMER_ACTIONS.NAVIGATION_UPDATE,
|
|
84
|
-
payload: {
|
|
85
|
-
url: 'index'
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('should init editor calling listeners', () => {
|
|
91
|
-
initEditor({ pathname: 'some-url' });
|
|
92
|
-
expect(fetchPageDataFromInsideUVE).toHaveBeenCalledWith('some-url');
|
|
93
|
-
expect(listenEditorMessages).toHaveBeenCalled();
|
|
94
|
-
expect(listenHoveredContentlet).toHaveBeenCalled();
|
|
95
|
-
expect(scrollHandler).toHaveBeenCalled();
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
describe('Add Class to Empty Contentets', () => {
|
|
100
|
-
it('should add class to empty contentlets', () => {
|
|
101
|
-
const contentlet = document.createElement('div');
|
|
102
|
-
contentlet.setAttribute('data-dot-object', 'contentlet');
|
|
103
|
-
Object.defineProperty(contentlet, 'clientHeight', { value: 100 }); // Emulate a contentlet with height in the DOM
|
|
104
|
-
document.body.appendChild(contentlet);
|
|
105
|
-
|
|
106
|
-
const emptyContentlet = document.createElement('div');
|
|
107
|
-
emptyContentlet.setAttribute('data-dot-object', 'contentlet');
|
|
108
|
-
document.body.appendChild(emptyContentlet);
|
|
109
|
-
|
|
110
|
-
addClassToEmptyContentlets();
|
|
111
|
-
|
|
112
|
-
expect(emptyContentlet.classList.contains('empty-contentlet')).toBe(true);
|
|
113
|
-
expect(contentlet.classList.contains('empty-contentlet')).toBe(false);
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
});
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
fetchPageDataFromInsideUVE,
|
|
3
|
-
listenEditorMessages,
|
|
4
|
-
listenHoveredContentlet,
|
|
5
|
-
scrollHandler,
|
|
6
|
-
subscriptions
|
|
7
|
-
} from './listeners/listeners';
|
|
8
|
-
import { CUSTOMER_ACTIONS, postMessageToEditor } from './models/client.model';
|
|
9
|
-
import { DotCMSPageEditorConfig } from './models/editor.model';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Updates the navigation in the editor.
|
|
13
|
-
*
|
|
14
|
-
* @param {string} pathname - The pathname to update the navigation with.
|
|
15
|
-
* @memberof DotCMSPageEditor
|
|
16
|
-
* @example
|
|
17
|
-
* updateNavigation('/home'); // Sends a message to the editor to update the navigation to '/home'
|
|
18
|
-
*/
|
|
19
|
-
export function updateNavigation(pathname: string): void {
|
|
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
|
-
*
|
|
31
|
-
* @returns {boolean} Returns true if the code is running inside an editor, otherwise false.
|
|
32
|
-
* @example
|
|
33
|
-
* ```ts
|
|
34
|
-
* if (isInsideEditor()) {
|
|
35
|
-
* console.log('Running inside the editor');
|
|
36
|
-
* } else {
|
|
37
|
-
* console.log('Running outside the editor');
|
|
38
|
-
* }
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
export function isInsideEditor(): boolean {
|
|
42
|
-
if (typeof window === 'undefined') {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return window.parent !== window;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Initializes the DotCMS page editor.
|
|
51
|
-
*
|
|
52
|
-
* @param {DotCMSPageEditorConfig} config - Optional configuration for the editor.
|
|
53
|
-
* @example
|
|
54
|
-
* ```ts
|
|
55
|
-
* const config = { pathname: '/home' };
|
|
56
|
-
* initEditor(config); // Initializes the editor with the provided configuration
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
59
|
-
export function initEditor(config: DotCMSPageEditorConfig): void {
|
|
60
|
-
fetchPageDataFromInsideUVE(config.pathname);
|
|
61
|
-
listenEditorMessages();
|
|
62
|
-
listenHoveredContentlet();
|
|
63
|
-
scrollHandler();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Destroys the editor by removing event listeners and disconnecting observers.
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* ```ts
|
|
71
|
-
* destroyEditor(); // Cleans up the editor by removing all event listeners and disconnecting observers
|
|
72
|
-
* ```
|
|
73
|
-
*/
|
|
74
|
-
export function destroyEditor(): void {
|
|
75
|
-
subscriptions.forEach((subscription) => {
|
|
76
|
-
if (subscription.type === 'listener') {
|
|
77
|
-
window.removeEventListener(subscription.event, subscription.callback as EventListener);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (subscription.type === 'observer') {
|
|
81
|
-
subscription.observer.disconnect();
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Adds a style class to empty contentlets.
|
|
88
|
-
*
|
|
89
|
-
* @export
|
|
90
|
-
* @example
|
|
91
|
-
* ```ts
|
|
92
|
-
* addClassToEmptyContentlets(); // Adds the 'empty-contentlet' class to all contentlets that have no height
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
export function addClassToEmptyContentlets(): void {
|
|
96
|
-
const contentlets = document.querySelectorAll('[data-dot-object="contentlet"]');
|
|
97
|
-
|
|
98
|
-
contentlets.forEach((contentlet) => {
|
|
99
|
-
if (contentlet.clientHeight) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
contentlet.classList.add('empty-contentlet');
|
|
104
|
-
});
|
|
105
|
-
}
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
import { getContentletsBound, scrollIsInBottom } 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
|
-
});
|
|
165
|
-
|
|
166
|
-
describe('scrollIsInBottom', () => {
|
|
167
|
-
it('should return true when scroll position + viewport height equals document height', () => {
|
|
168
|
-
Object.defineProperty(window, 'innerHeight', {
|
|
169
|
-
writable: true,
|
|
170
|
-
configurable: true,
|
|
171
|
-
value: 500
|
|
172
|
-
});
|
|
173
|
-
Object.defineProperty(window, 'scrollY', {
|
|
174
|
-
writable: true,
|
|
175
|
-
configurable: true,
|
|
176
|
-
value: 500
|
|
177
|
-
});
|
|
178
|
-
Object.defineProperty(document.documentElement, 'scrollHeight', {
|
|
179
|
-
writable: true,
|
|
180
|
-
configurable: true,
|
|
181
|
-
value: 1000
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
expect(scrollIsInBottom()).toBe(true);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it('should return false when scroll position + viewport height is less than document height', () => {
|
|
188
|
-
Object.defineProperty(window, 'innerHeight', {
|
|
189
|
-
writable: true,
|
|
190
|
-
configurable: true,
|
|
191
|
-
value: 500
|
|
192
|
-
});
|
|
193
|
-
Object.defineProperty(window, 'scrollY', {
|
|
194
|
-
writable: true,
|
|
195
|
-
configurable: true,
|
|
196
|
-
value: 400
|
|
197
|
-
});
|
|
198
|
-
Object.defineProperty(document.documentElement, 'scrollHeight', {
|
|
199
|
-
writable: true,
|
|
200
|
-
configurable: true,
|
|
201
|
-
value: 1000
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
expect(scrollIsInBottom()).toBe(false);
|
|
205
|
-
});
|
|
206
|
-
});
|