@dotcms/angular 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/README.md +10 -10
- package/dotcms-angular.d.ts.map +1 -0
- package/esm2022/dotcms-angular.mjs +5 -0
- package/esm2022/index.mjs +5 -0
- package/esm2022/lib/components/dot-editable-text/dot-editable-text.component.mjs +225 -0
- package/esm2022/lib/components/dot-editable-text/utils.mjs +43 -0
- package/esm2022/lib/components/no-component/no-component.component.mjs +32 -0
- package/esm2022/lib/layout/column/column.component.mjs +45 -0
- package/esm2022/lib/layout/container/container.component.mjs +126 -0
- package/esm2022/lib/layout/contentlet/contentlet.component.mjs +120 -0
- package/esm2022/lib/layout/dotcms-layout/dotcms-layout.component.mjs +100 -0
- package/esm2022/lib/layout/row/row.component.mjs +29 -0
- package/esm2022/lib/models/dotcms.model.mjs +3 -0
- package/esm2022/lib/models/index.mjs +3 -0
- package/esm2022/lib/services/dotcms-context/page-context.service.mjs +75 -0
- package/esm2022/lib/utils/index.mjs +79 -0
- package/fesm2022/dotcms-angular.mjs +858 -0
- package/fesm2022/dotcms-angular.mjs.map +1 -0
- package/{src/index.ts → index.d.ts} +1 -0
- package/index.d.ts.map +1 -0
- package/lib/components/dot-editable-text/dot-editable-text.component.d.ts +129 -0
- package/lib/components/dot-editable-text/dot-editable-text.component.d.ts.map +1 -0
- package/lib/components/dot-editable-text/utils.d.ts +7 -0
- package/lib/components/dot-editable-text/utils.d.ts.map +1 -0
- package/lib/components/no-component/no-component.component.d.ts +22 -0
- package/lib/components/no-component/no-component.component.d.ts.map +1 -0
- package/lib/layout/column/column.component.d.ts +29 -0
- package/lib/layout/column/column.component.d.ts.map +1 -0
- package/lib/layout/container/container.component.d.ts +88 -0
- package/lib/layout/container/container.component.d.ts.map +1 -0
- package/{src/lib/layout/contentlet/contentlet.component.ts → lib/layout/contentlet/contentlet.component.d.ts} +17 -32
- package/lib/layout/contentlet/contentlet.component.d.ts.map +1 -0
- package/lib/layout/dotcms-layout/dotcms-layout.component.d.ts +67 -0
- package/lib/layout/dotcms-layout/dotcms-layout.component.d.ts.map +1 -0
- package/lib/layout/row/row.component.d.ts +20 -0
- package/lib/layout/row/row.component.d.ts.map +1 -0
- package/{src/lib/models/dotcms.model.ts → lib/models/dotcms.model.d.ts} +3 -21
- package/lib/models/dotcms.model.d.ts.map +1 -0
- package/{src/lib/models/index.ts → lib/models/index.d.ts} +1 -8
- package/lib/models/index.d.ts.map +1 -0
- package/{src/lib/services/dotcms-context/page-context.service.ts → lib/services/dotcms-context/page-context.service.d.ts} +12 -41
- package/lib/services/dotcms-context/page-context.service.d.ts.map +1 -0
- package/lib/utils/index.d.ts +63 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/package.json +22 -5
- package/.eslintrc.json +0 -18
- package/jest.config.ts +0 -22
- package/ng-package.json +0 -7
- package/project.json +0 -33
- package/src/lib/components/dot-editable-text/dot-editable-text.component.css +0 -4
- package/src/lib/components/dot-editable-text/dot-editable-text.component.html +0 -8
- package/src/lib/components/dot-editable-text/dot-editable-text.component.spec.ts +0 -424
- package/src/lib/components/dot-editable-text/dot-editable-text.component.ts +0 -269
- package/src/lib/components/dot-editable-text/utils.ts +0 -51
- package/src/lib/components/no-component/no-component.component.css +0 -3
- package/src/lib/components/no-component/no-component.component.spec.ts +0 -24
- package/src/lib/components/no-component/no-component.component.ts +0 -31
- package/src/lib/layout/column/column.component.css +0 -99
- package/src/lib/layout/column/column.component.spec.ts +0 -33
- package/src/lib/layout/column/column.component.ts +0 -49
- package/src/lib/layout/container/container.component.css +0 -9
- package/src/lib/layout/container/container.component.html +0 -26
- package/src/lib/layout/container/container.component.spec.ts +0 -205
- package/src/lib/layout/container/container.component.ts +0 -140
- package/src/lib/layout/contentlet/contentlet.component.spec.ts +0 -22
- package/src/lib/layout/dotcms-layout/dotcms-layout.component.css +0 -3
- package/src/lib/layout/dotcms-layout/dotcms-layout.component.spec.ts +0 -195
- package/src/lib/layout/dotcms-layout/dotcms-layout.component.ts +0 -150
- package/src/lib/layout/row/row.component.css +0 -6
- package/src/lib/layout/row/row.component.spec.ts +0 -28
- package/src/lib/layout/row/row.component.ts +0 -32
- package/src/lib/services/dotcms-context/page-context.spec.ts +0 -80
- package/src/lib/utils/index.ts +0 -92
- package/src/lib/utils/testing.utils.ts +0 -1019
- package/src/test-setup.ts +0 -8
- package/tsconfig.json +0 -29
- package/tsconfig.lib.json +0 -12
- package/tsconfig.lib.prod.json +0 -9
- package/tsconfig.spec.json +0 -11
|
@@ -0,0 +1,858 @@
|
|
|
1
|
+
import { TINYMCE_SCRIPT_SRC, EditorComponent } from '@tinymce/tinymce-angular';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { inject, Renderer2, ElementRef, SecurityContext, Component, ViewChild, Input, HostListener, Injectable, ChangeDetectionStrategy, HostBinding, signal, computed, DestroyRef } from '@angular/core';
|
|
4
|
+
import { DomSanitizer } from '@angular/platform-browser';
|
|
5
|
+
import { isInsideEditor, DotCmsClient, postMessageToEditor, CUSTOMER_ACTIONS, initEditor, updateNavigation } from '@dotcms/client';
|
|
6
|
+
import { AsyncPipe, NgComponentOutlet } from '@angular/common';
|
|
7
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
8
|
+
import { ActivatedRoute } from '@angular/router';
|
|
9
|
+
import { BehaviorSubject } from 'rxjs';
|
|
10
|
+
import { map } from 'rxjs/operators';
|
|
11
|
+
|
|
12
|
+
const DEFAULT_TINYMCE_CONFIG = {
|
|
13
|
+
menubar: false,
|
|
14
|
+
inline: true,
|
|
15
|
+
valid_styles: {
|
|
16
|
+
'*': 'font-size,font-family,color,text-decoration,text-align'
|
|
17
|
+
},
|
|
18
|
+
powerpaste_word_import: 'clean',
|
|
19
|
+
powerpaste_html_import: 'clean',
|
|
20
|
+
suffix: '.min', // Suffix to use when loading resources
|
|
21
|
+
license_key: 'gpl'
|
|
22
|
+
};
|
|
23
|
+
const TINYMCE_CONFIG = {
|
|
24
|
+
minimal: {
|
|
25
|
+
...DEFAULT_TINYMCE_CONFIG,
|
|
26
|
+
plugins: 'link autolink',
|
|
27
|
+
toolbar: 'bold italic underline | link',
|
|
28
|
+
valid_elements: 'strong,em,span[style],a[href]'
|
|
29
|
+
},
|
|
30
|
+
full: {
|
|
31
|
+
...DEFAULT_TINYMCE_CONFIG,
|
|
32
|
+
plugins: 'link lists autolink charmap',
|
|
33
|
+
style_formats: [
|
|
34
|
+
{ title: 'Paragraph', format: 'p' },
|
|
35
|
+
{ title: 'Header 1', format: 'h1' },
|
|
36
|
+
{ title: 'Header 2', format: 'h2' },
|
|
37
|
+
{ title: 'Header 3', format: 'h3' },
|
|
38
|
+
{ title: 'Header 4', format: 'h4' },
|
|
39
|
+
{ title: 'Header 5', format: 'h5' },
|
|
40
|
+
{ title: 'Header 6', format: 'h6' },
|
|
41
|
+
{ title: 'Pre', format: 'pre' },
|
|
42
|
+
{ title: 'Code', format: 'code' }
|
|
43
|
+
],
|
|
44
|
+
toolbar: [
|
|
45
|
+
'styleselect undo redo | bold italic underline | forecolor backcolor | alignleft aligncenter alignright alignfull | numlist bullist outdent indent | hr charmap removeformat | link'
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
plain: {
|
|
49
|
+
...DEFAULT_TINYMCE_CONFIG,
|
|
50
|
+
plugins: '',
|
|
51
|
+
toolbar: ''
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Dot editable text component.
|
|
57
|
+
* This component is responsible to render a text field that can be edited inline.
|
|
58
|
+
*
|
|
59
|
+
* @export
|
|
60
|
+
* @class DotEditableTextComponent
|
|
61
|
+
* @implements {OnInit}
|
|
62
|
+
* @implements {OnChanges}
|
|
63
|
+
*/
|
|
64
|
+
class DotEditableTextComponent {
|
|
65
|
+
constructor() {
|
|
66
|
+
/**
|
|
67
|
+
* Represents the mode of the editor which can be `plain`, `minimal`, or `full`
|
|
68
|
+
*
|
|
69
|
+
* @type {DOT_EDITABLE_TEXT_MODE}
|
|
70
|
+
* @memberof DotEditableTextComponent
|
|
71
|
+
*/
|
|
72
|
+
this.mode = 'plain';
|
|
73
|
+
/**
|
|
74
|
+
* Represents the format of the editor which can be `text` or `html`
|
|
75
|
+
*
|
|
76
|
+
* @type {DOT_EDITABLE_TEXT_FORMAT}
|
|
77
|
+
* @memberof DotEditableTextComponent
|
|
78
|
+
*/
|
|
79
|
+
this.format = 'text';
|
|
80
|
+
/**
|
|
81
|
+
* Represents the field name of the `contentlet` that can be edited
|
|
82
|
+
*
|
|
83
|
+
* @memberof DotEditableTextComponent
|
|
84
|
+
*/
|
|
85
|
+
this.fieldName = '';
|
|
86
|
+
/**
|
|
87
|
+
* Represents the content of the `contentlet` that can be edited
|
|
88
|
+
*
|
|
89
|
+
* @protected
|
|
90
|
+
* @memberof DotEditableTextComponent
|
|
91
|
+
*/
|
|
92
|
+
this.content = '';
|
|
93
|
+
this.#sanitizer = inject(DomSanitizer);
|
|
94
|
+
this.#renderer = inject(Renderer2);
|
|
95
|
+
this.#elementRef = inject(ElementRef);
|
|
96
|
+
}
|
|
97
|
+
#sanitizer;
|
|
98
|
+
#renderer;
|
|
99
|
+
#elementRef;
|
|
100
|
+
/**
|
|
101
|
+
* The TinyMCE editor
|
|
102
|
+
*
|
|
103
|
+
* @readonly
|
|
104
|
+
* @memberof DotEditableTextComponent
|
|
105
|
+
*/
|
|
106
|
+
get editor() {
|
|
107
|
+
return this.editorComponent?.editor;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Returns the number of pages the contentlet is on
|
|
111
|
+
*
|
|
112
|
+
* @readonly
|
|
113
|
+
* @memberof DotEditableTextComponent
|
|
114
|
+
*/
|
|
115
|
+
get onNumberOfPages() {
|
|
116
|
+
return this.contentlet['onNumberOfPages'] || 1;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Handle copy contentlet inline editing success event
|
|
120
|
+
*
|
|
121
|
+
* @param {MessageEvent} { data }
|
|
122
|
+
* @return {*}
|
|
123
|
+
* @memberof DotEditableTextComponent
|
|
124
|
+
*/
|
|
125
|
+
onMessage({ data }) {
|
|
126
|
+
const { name, payload } = data;
|
|
127
|
+
if (name !== 'COPY_CONTENTLET_INLINE_EDITING_SUCCESS') {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const { oldInode, inode } = payload;
|
|
131
|
+
const currentInode = this.contentlet.inode;
|
|
132
|
+
if (currentInode === oldInode || currentInode === inode) {
|
|
133
|
+
this.editorComponent.editor.focus();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
ngOnInit() {
|
|
138
|
+
this.isInsideEditor = isInsideEditor();
|
|
139
|
+
if (!this.isInsideEditor) {
|
|
140
|
+
this.innerHTMLToElement();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
this.init = {
|
|
144
|
+
...TINYMCE_CONFIG[this.mode],
|
|
145
|
+
base_url: `${DotCmsClient.dotcmsUrl}/ext/tinymcev7`
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
ngOnChanges() {
|
|
149
|
+
this.content = this.contentlet[this.fieldName] || '';
|
|
150
|
+
if (this.editor) {
|
|
151
|
+
this.editor.setContent(this.content, { format: this.format });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Handle mouse down event
|
|
156
|
+
*
|
|
157
|
+
* @param {EventObj<MouseEvent>} { event }
|
|
158
|
+
* @return {*}
|
|
159
|
+
* @memberof DotEditableTextComponent
|
|
160
|
+
*/
|
|
161
|
+
onMouseDown({ event }) {
|
|
162
|
+
if (this.onNumberOfPages <= 1 || this.editorComponent.editor.hasFocus()) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const { inode, languageId: language } = this.contentlet;
|
|
166
|
+
event.stopPropagation();
|
|
167
|
+
event.preventDefault();
|
|
168
|
+
try {
|
|
169
|
+
postMessageToEditor({
|
|
170
|
+
action: CUSTOMER_ACTIONS.COPY_CONTENTLET_INLINE_EDITING,
|
|
171
|
+
payload: {
|
|
172
|
+
dataset: {
|
|
173
|
+
inode,
|
|
174
|
+
language,
|
|
175
|
+
fieldName: this.fieldName
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
console.error('Failed to post message to editor:', error);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Handle focus out event
|
|
186
|
+
*
|
|
187
|
+
* @return {*}
|
|
188
|
+
* @memberof DotEditableTextComponent
|
|
189
|
+
*/
|
|
190
|
+
onFocusOut() {
|
|
191
|
+
const content = this.editor.getContent({ format: this.format });
|
|
192
|
+
if (!this.editor.isDirty() || !this.didContentChange(content)) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const { inode, languageId: langId } = this.contentlet;
|
|
196
|
+
try {
|
|
197
|
+
postMessageToEditor({
|
|
198
|
+
action: CUSTOMER_ACTIONS.UPDATE_CONTENTLET_INLINE_EDITING,
|
|
199
|
+
payload: {
|
|
200
|
+
content,
|
|
201
|
+
dataset: {
|
|
202
|
+
inode,
|
|
203
|
+
langId,
|
|
204
|
+
fieldName: this.fieldName
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
console.error('Failed to post message to editor:', error);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* inner HTML to element
|
|
215
|
+
*
|
|
216
|
+
* @private
|
|
217
|
+
* @param {string} editedContent
|
|
218
|
+
* @return {*}
|
|
219
|
+
* @memberof DotEditableTextComponent
|
|
220
|
+
*/
|
|
221
|
+
innerHTMLToElement() {
|
|
222
|
+
const element = this.#elementRef.nativeElement;
|
|
223
|
+
const safeHtml = this.#sanitizer.bypassSecurityTrustHtml(this.content);
|
|
224
|
+
const content = this.#sanitizer.sanitize(SecurityContext.HTML, safeHtml) || '';
|
|
225
|
+
this.#renderer.setProperty(element, 'innerHTML', content);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Check if the content has changed
|
|
229
|
+
*
|
|
230
|
+
* @private
|
|
231
|
+
* @param {string} editedContent
|
|
232
|
+
* @return {*}
|
|
233
|
+
* @memberof DotEditableTextComponent
|
|
234
|
+
*/
|
|
235
|
+
didContentChange(editedContent) {
|
|
236
|
+
return this.content !== editedContent;
|
|
237
|
+
}
|
|
238
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotEditableTextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
239
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: DotEditableTextComponent, isStandalone: true, selector: "dot-editable-text", inputs: { mode: "mode", format: "format", contentlet: "contentlet", fieldName: "fieldName" }, host: { listeners: { "window:message": "onMessage($event)" } }, providers: [
|
|
240
|
+
{
|
|
241
|
+
provide: TINYMCE_SCRIPT_SRC,
|
|
242
|
+
useFactory: () => {
|
|
243
|
+
return `${DotCmsClient.dotcmsUrl}/ext/tinymcev7/tinymce.min.js`;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
], viewQueries: [{ propertyName: "editorComponent", first: true, predicate: EditorComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (isInsideEditor) {\n <editor\n #tinyEditor\n [init]=\"init\"\n [initialValue]=\"content\"\n (onMouseDown)=\"onMouseDown($event)\"\n (onFocusOut)=\"onFocusOut()\" />\n}\n", styles: [":host ::ng-deep .mce-content-body:not(.mce-edit-focus):hover{outline:2px solid #006ce7;border-radius:4px}\n"], dependencies: [{ kind: "component", type: EditorComponent, selector: "editor", inputs: ["cloudChannel", "apiKey", "init", "id", "initialValue", "outputFormat", "inline", "tagName", "plugins", "toolbar", "modelEvents", "allowedEvents", "ignoreEvents", "disabled"] }] }); }
|
|
247
|
+
}
|
|
248
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotEditableTextComponent, decorators: [{
|
|
249
|
+
type: Component,
|
|
250
|
+
args: [{ selector: 'dot-editable-text', standalone: true, imports: [EditorComponent], providers: [
|
|
251
|
+
{
|
|
252
|
+
provide: TINYMCE_SCRIPT_SRC,
|
|
253
|
+
useFactory: () => {
|
|
254
|
+
return `${DotCmsClient.dotcmsUrl}/ext/tinymcev7/tinymce.min.js`;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
], template: "@if (isInsideEditor) {\n <editor\n #tinyEditor\n [init]=\"init\"\n [initialValue]=\"content\"\n (onMouseDown)=\"onMouseDown($event)\"\n (onFocusOut)=\"onFocusOut()\" />\n}\n", styles: [":host ::ng-deep .mce-content-body:not(.mce-edit-focus):hover{outline:2px solid #006ce7;border-radius:4px}\n"] }]
|
|
258
|
+
}], propDecorators: { editorComponent: [{
|
|
259
|
+
type: ViewChild,
|
|
260
|
+
args: [EditorComponent]
|
|
261
|
+
}], mode: [{
|
|
262
|
+
type: Input
|
|
263
|
+
}], format: [{
|
|
264
|
+
type: Input
|
|
265
|
+
}], contentlet: [{
|
|
266
|
+
type: Input
|
|
267
|
+
}], fieldName: [{
|
|
268
|
+
type: Input
|
|
269
|
+
}], onMessage: [{
|
|
270
|
+
type: HostListener,
|
|
271
|
+
args: ['window:message', ['$event']]
|
|
272
|
+
}] } });
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* @author dotCMS
|
|
276
|
+
* @description This service is responsible for managing the page context.
|
|
277
|
+
* @export
|
|
278
|
+
* @class PageContextService
|
|
279
|
+
*/
|
|
280
|
+
class PageContextService {
|
|
281
|
+
constructor() {
|
|
282
|
+
this.context$ = new BehaviorSubject(null);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* @description Get the context
|
|
286
|
+
* @readonly
|
|
287
|
+
* @type {DotCMSPageContext}
|
|
288
|
+
* @memberof PageContextService
|
|
289
|
+
*/
|
|
290
|
+
get context() {
|
|
291
|
+
return this.context$.getValue();
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* @description Get the context as an observable
|
|
295
|
+
* @readonly
|
|
296
|
+
* @memberof PageContextService
|
|
297
|
+
*/
|
|
298
|
+
get contextObs$() {
|
|
299
|
+
return this.context$.asObservable();
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* @description Get the current page asset
|
|
303
|
+
* @readonly
|
|
304
|
+
* @type {(Observable<DotCMSPageAsset | null>)}
|
|
305
|
+
* @memberof PageContextService
|
|
306
|
+
*/
|
|
307
|
+
get currentPage$() {
|
|
308
|
+
return this.contextObs$.pipe(map((context) => context?.pageAsset || null));
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
*
|
|
312
|
+
* @description Set the context
|
|
313
|
+
* @param {DotCMSPageAsset} value
|
|
314
|
+
* @memberof DotcmsContextService
|
|
315
|
+
*/
|
|
316
|
+
setContext(pageAsset, components) {
|
|
317
|
+
this.context$.next({
|
|
318
|
+
pageAsset,
|
|
319
|
+
components,
|
|
320
|
+
isInsideEditor: isInsideEditor()
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* @description Set the page asset in the context
|
|
325
|
+
* @param {DotCMSPageAsset} pageAsset
|
|
326
|
+
* @memberof PageContextService
|
|
327
|
+
*/
|
|
328
|
+
setPageAsset(pageAsset) {
|
|
329
|
+
this.context$.next({
|
|
330
|
+
...this.context,
|
|
331
|
+
pageAsset
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: PageContextService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
335
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: PageContextService, providedIn: 'root' }); }
|
|
336
|
+
}
|
|
337
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: PageContextService, decorators: [{
|
|
338
|
+
type: Injectable,
|
|
339
|
+
args: [{
|
|
340
|
+
providedIn: 'root'
|
|
341
|
+
}]
|
|
342
|
+
}] });
|
|
343
|
+
|
|
344
|
+
//Changed the type, to avoid SQ issue.
|
|
345
|
+
//This should be put inside a lib
|
|
346
|
+
/**
|
|
347
|
+
* Represents a mapping of numbers to corresponding CSS class names for column end values.
|
|
348
|
+
* @typedef {Record<number, string | null>} EndClassMap
|
|
349
|
+
*/
|
|
350
|
+
const endClassMap = {
|
|
351
|
+
1: 'col-end-1',
|
|
352
|
+
2: 'col-end-2',
|
|
353
|
+
3: 'col-end-3',
|
|
354
|
+
4: 'col-end-4',
|
|
355
|
+
5: 'col-end-5',
|
|
356
|
+
6: 'col-end-6',
|
|
357
|
+
7: 'col-end-7',
|
|
358
|
+
8: 'col-end-8',
|
|
359
|
+
9: 'col-end-9',
|
|
360
|
+
10: 'col-end-10',
|
|
361
|
+
11: 'col-end-11',
|
|
362
|
+
12: 'col-end-12',
|
|
363
|
+
13: 'col-end-13'
|
|
364
|
+
};
|
|
365
|
+
//Changed the type, to avoid SQ issue.
|
|
366
|
+
//This should be put inside a lib
|
|
367
|
+
/**
|
|
368
|
+
* Represents a mapping of numbers to CSS class names for starting columns.
|
|
369
|
+
* @typedef {Record<number, string | null>} StartClassMap
|
|
370
|
+
*/
|
|
371
|
+
const startClassMap = {
|
|
372
|
+
1: 'col-start-1',
|
|
373
|
+
2: 'col-start-2',
|
|
374
|
+
3: 'col-start-3',
|
|
375
|
+
4: 'col-start-4',
|
|
376
|
+
5: 'col-start-5',
|
|
377
|
+
6: 'col-start-6',
|
|
378
|
+
7: 'col-start-7',
|
|
379
|
+
8: 'col-start-8',
|
|
380
|
+
9: 'col-start-9',
|
|
381
|
+
10: 'col-start-10',
|
|
382
|
+
11: 'col-start-11',
|
|
383
|
+
12: 'col-start-12'
|
|
384
|
+
};
|
|
385
|
+
/**
|
|
386
|
+
* Retrieves the data for a set of containers.
|
|
387
|
+
*
|
|
388
|
+
* @param containers - The DotCMSPageAssetContainer object containing the containers.
|
|
389
|
+
* @param containerRef - The DotCMSContainer object representing the container reference.
|
|
390
|
+
* @returns An object containing the container data, accept types, contentlets, and variant ID.
|
|
391
|
+
*/
|
|
392
|
+
const getContainersData = (containers, containerRef) => {
|
|
393
|
+
const { identifier, uuid } = containerRef;
|
|
394
|
+
const { containerStructures, container } = containers[identifier];
|
|
395
|
+
const { variantId } = container?.parentPermissionable || {};
|
|
396
|
+
const acceptTypes = containerStructures
|
|
397
|
+
.map((structure) => structure.contentTypeVar)
|
|
398
|
+
.join(',');
|
|
399
|
+
const contentlets = containers[identifier].contentlets[`uuid-${uuid}`];
|
|
400
|
+
return {
|
|
401
|
+
...containers[identifier].container,
|
|
402
|
+
acceptTypes,
|
|
403
|
+
contentlets,
|
|
404
|
+
variantId
|
|
405
|
+
};
|
|
406
|
+
};
|
|
407
|
+
/**
|
|
408
|
+
* Returns the position style classes based on the start and end values.
|
|
409
|
+
* Used to set the grid column start and end values.
|
|
410
|
+
* @param start - The start value.
|
|
411
|
+
* @param end - The end value.
|
|
412
|
+
* @returns An object containing the startClass and endClass.
|
|
413
|
+
*/
|
|
414
|
+
const getPositionStyleClasses = (start, end) => {
|
|
415
|
+
const startClass = startClassMap[start];
|
|
416
|
+
const endClass = endClassMap[end];
|
|
417
|
+
return {
|
|
418
|
+
startClass,
|
|
419
|
+
endClass
|
|
420
|
+
};
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* This component is responsible to display a message when there is no component for a contentlet.
|
|
425
|
+
*
|
|
426
|
+
* @export
|
|
427
|
+
* @class NoComponent
|
|
428
|
+
*/
|
|
429
|
+
class NoComponent {
|
|
430
|
+
constructor() {
|
|
431
|
+
/**
|
|
432
|
+
* The data-testid attribute used for identifying the component during testing.
|
|
433
|
+
*/
|
|
434
|
+
this.testId = 'no-component';
|
|
435
|
+
}
|
|
436
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: NoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
437
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: NoComponent, isStandalone: true, selector: "dotcms-no-component", inputs: { contentlet: "contentlet" }, host: { properties: { "attr.data-testid": "this.testId" } }, ngImport: i0, template: `
|
|
438
|
+
No Component for {{ contentlet.contentType }}
|
|
439
|
+
`, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
440
|
+
}
|
|
441
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: NoComponent, decorators: [{
|
|
442
|
+
type: Component,
|
|
443
|
+
args: [{ selector: 'dotcms-no-component', standalone: true, template: `
|
|
444
|
+
No Component for {{ contentlet.contentType }}
|
|
445
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
|
|
446
|
+
}], propDecorators: { contentlet: [{
|
|
447
|
+
type: Input
|
|
448
|
+
}], testId: [{
|
|
449
|
+
type: HostBinding,
|
|
450
|
+
args: ['attr.data-testid']
|
|
451
|
+
}] } });
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* This component is responsible to display a contentlet.
|
|
455
|
+
*
|
|
456
|
+
* @export
|
|
457
|
+
* @class ContentletComponent
|
|
458
|
+
* @implements {OnChanges}
|
|
459
|
+
*/
|
|
460
|
+
class ContentletComponent {
|
|
461
|
+
constructor() {
|
|
462
|
+
/**
|
|
463
|
+
* The identifier of contentlet component.
|
|
464
|
+
*
|
|
465
|
+
* @type {(string | null)}
|
|
466
|
+
* @memberof ContentletComponent
|
|
467
|
+
*/
|
|
468
|
+
this.identifier = null;
|
|
469
|
+
/**
|
|
470
|
+
* The base type of contentlet component.
|
|
471
|
+
*
|
|
472
|
+
* @type {(string | null)}
|
|
473
|
+
* @memberof ContentletComponent
|
|
474
|
+
*/
|
|
475
|
+
this.baseType = null;
|
|
476
|
+
/**
|
|
477
|
+
* The title of contentlet component.
|
|
478
|
+
*
|
|
479
|
+
* @type {(string | null)}
|
|
480
|
+
* @memberof ContentletComponent
|
|
481
|
+
*/
|
|
482
|
+
this.title = null;
|
|
483
|
+
/**
|
|
484
|
+
* The inode of contentlet component.
|
|
485
|
+
*
|
|
486
|
+
* @type {(string | null)}
|
|
487
|
+
* @memberof ContentletComponent
|
|
488
|
+
*/
|
|
489
|
+
this.inode = null;
|
|
490
|
+
/**
|
|
491
|
+
* The type of contentlet component.
|
|
492
|
+
*
|
|
493
|
+
* @type {(string | null)}
|
|
494
|
+
* @memberof ContentletComponent
|
|
495
|
+
*/
|
|
496
|
+
this.dotType = null;
|
|
497
|
+
/**
|
|
498
|
+
* The container of contentlet component.
|
|
499
|
+
*
|
|
500
|
+
* @type {(string | null)}
|
|
501
|
+
* @memberof ContentletComponent
|
|
502
|
+
*/
|
|
503
|
+
this.dotContainer = null;
|
|
504
|
+
/**
|
|
505
|
+
* The number of pages where the contentlet appears
|
|
506
|
+
*
|
|
507
|
+
* @type {(string | null)}
|
|
508
|
+
* @memberof ContentletComponent
|
|
509
|
+
*/
|
|
510
|
+
this.numberOfPages = null;
|
|
511
|
+
/**
|
|
512
|
+
* The content of contentlet component.
|
|
513
|
+
*
|
|
514
|
+
* @type {(string | null)}
|
|
515
|
+
* @memberof ContentletComponent
|
|
516
|
+
*/
|
|
517
|
+
this.dotContent = null;
|
|
518
|
+
}
|
|
519
|
+
ngOnChanges() {
|
|
520
|
+
this.identifier = this.contentlet.identifier;
|
|
521
|
+
this.baseType = this.contentlet.baseType;
|
|
522
|
+
this.title = this.contentlet.title;
|
|
523
|
+
this.inode = this.contentlet.inode;
|
|
524
|
+
this.dotType = this.contentlet.contentType;
|
|
525
|
+
this.dotContainer = this.container;
|
|
526
|
+
this.numberOfPages = this.contentlet['onNumberOfPages'];
|
|
527
|
+
this.dotContent = 'contentlet';
|
|
528
|
+
}
|
|
529
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ContentletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
530
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: ContentletComponent, isStandalone: true, selector: "dotcms-contentlet-wrapper", inputs: { contentlet: "contentlet", container: "container" }, host: { properties: { "attr.data-dot-identifier": "this.identifier", "attr.data-dot-basetype": "this.baseType", "attr.data-dot-title": "this.title", "attr.data-dot-inode": "this.inode", "attr.data-dot-type": "this.dotType", "attr.data-dot-container": "this.dotContainer", "attr.data-dot-on-number-of-pages": "this.numberOfPages", "attr.data-dot-object": "this.dotContent" } }, usesOnChanges: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
531
|
+
}
|
|
532
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ContentletComponent, decorators: [{
|
|
533
|
+
type: Component,
|
|
534
|
+
args: [{
|
|
535
|
+
selector: 'dotcms-contentlet-wrapper',
|
|
536
|
+
standalone: true,
|
|
537
|
+
template: '<ng-content></ng-content>',
|
|
538
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
539
|
+
}]
|
|
540
|
+
}], propDecorators: { contentlet: [{
|
|
541
|
+
type: Input,
|
|
542
|
+
args: [{ required: true }]
|
|
543
|
+
}], container: [{
|
|
544
|
+
type: Input
|
|
545
|
+
}], identifier: [{
|
|
546
|
+
type: HostBinding,
|
|
547
|
+
args: ['attr.data-dot-identifier']
|
|
548
|
+
}], baseType: [{
|
|
549
|
+
type: HostBinding,
|
|
550
|
+
args: ['attr.data-dot-basetype']
|
|
551
|
+
}], title: [{
|
|
552
|
+
type: HostBinding,
|
|
553
|
+
args: ['attr.data-dot-title']
|
|
554
|
+
}], inode: [{
|
|
555
|
+
type: HostBinding,
|
|
556
|
+
args: ['attr.data-dot-inode']
|
|
557
|
+
}], dotType: [{
|
|
558
|
+
type: HostBinding,
|
|
559
|
+
args: ['attr.data-dot-type']
|
|
560
|
+
}], dotContainer: [{
|
|
561
|
+
type: HostBinding,
|
|
562
|
+
args: ['attr.data-dot-container']
|
|
563
|
+
}], numberOfPages: [{
|
|
564
|
+
type: HostBinding,
|
|
565
|
+
args: ['attr.data-dot-on-number-of-pages']
|
|
566
|
+
}], dotContent: [{
|
|
567
|
+
type: HostBinding,
|
|
568
|
+
args: ['attr.data-dot-object']
|
|
569
|
+
}] } });
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* This component is responsible to display a container with contentlets.
|
|
573
|
+
*
|
|
574
|
+
* @export
|
|
575
|
+
* @class ContainerComponent
|
|
576
|
+
* @implements {OnChanges}
|
|
577
|
+
*/
|
|
578
|
+
class ContainerComponent {
|
|
579
|
+
constructor() {
|
|
580
|
+
this.pageContextService = inject(PageContextService);
|
|
581
|
+
this.NoComponent = NoComponent;
|
|
582
|
+
this.$isInsideEditor = signal(false);
|
|
583
|
+
this.$contentlets = signal([]);
|
|
584
|
+
this.$dotContainer = signal(null);
|
|
585
|
+
this.$dotContainerAsString = computed(() => JSON.stringify(this.$dotContainer()));
|
|
586
|
+
/**
|
|
587
|
+
* The accept types for the container component.
|
|
588
|
+
*
|
|
589
|
+
* @type {(string | null)}
|
|
590
|
+
* @memberof ContainerComponent
|
|
591
|
+
*/
|
|
592
|
+
this.acceptTypes = null;
|
|
593
|
+
/**
|
|
594
|
+
* The identifier for the container component.
|
|
595
|
+
*
|
|
596
|
+
* @type {(string | null)}
|
|
597
|
+
* @memberof ContainerComponent
|
|
598
|
+
*/
|
|
599
|
+
this.identifier = null;
|
|
600
|
+
/**
|
|
601
|
+
* The max contentlets for the container component.
|
|
602
|
+
*
|
|
603
|
+
* @type {(number | null)}
|
|
604
|
+
* @memberof ContainerComponent
|
|
605
|
+
*/
|
|
606
|
+
this.maxContentlets = null;
|
|
607
|
+
/**
|
|
608
|
+
* The uuid for the container component.
|
|
609
|
+
*
|
|
610
|
+
* @type {(string | null)}
|
|
611
|
+
* @memberof ContainerComponent
|
|
612
|
+
*/
|
|
613
|
+
this.uuid = null;
|
|
614
|
+
/**
|
|
615
|
+
* The class for the container component.
|
|
616
|
+
*
|
|
617
|
+
* @type {(string | null)}
|
|
618
|
+
* @memberof ContainerComponent
|
|
619
|
+
*/
|
|
620
|
+
this.class = null;
|
|
621
|
+
/**
|
|
622
|
+
* The dot object for the container component.
|
|
623
|
+
*
|
|
624
|
+
* @type {(string | null)}
|
|
625
|
+
* @memberof ContainerComponent
|
|
626
|
+
*/
|
|
627
|
+
this.dotObject = null;
|
|
628
|
+
/**
|
|
629
|
+
* The data-testid attribute used for identifying the component during testing.
|
|
630
|
+
*
|
|
631
|
+
* @memberof ContainerComponent
|
|
632
|
+
*/
|
|
633
|
+
this.testId = 'dot-container';
|
|
634
|
+
}
|
|
635
|
+
ngOnChanges() {
|
|
636
|
+
const { pageAsset, components, isInsideEditor } = this.pageContextService.context;
|
|
637
|
+
const { acceptTypes, maxContentlets, variantId, path, contentlets } = getContainersData(pageAsset.containers, this.container);
|
|
638
|
+
const { identifier, uuid } = this.container;
|
|
639
|
+
this.componentsMap = components;
|
|
640
|
+
this.$isInsideEditor.set(isInsideEditor);
|
|
641
|
+
this.$contentlets.set(contentlets);
|
|
642
|
+
this.$dotContainer.set({
|
|
643
|
+
identifier: path ?? identifier,
|
|
644
|
+
acceptTypes,
|
|
645
|
+
maxContentlets,
|
|
646
|
+
variantId,
|
|
647
|
+
uuid
|
|
648
|
+
});
|
|
649
|
+
if (this.$isInsideEditor()) {
|
|
650
|
+
this.acceptTypes = acceptTypes;
|
|
651
|
+
this.identifier = identifier;
|
|
652
|
+
this.maxContentlets = maxContentlets;
|
|
653
|
+
this.uuid = uuid;
|
|
654
|
+
this.class = this.$contentlets().length ? null : 'empty-container';
|
|
655
|
+
this.dotObject = 'container';
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
659
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: ContainerComponent, isStandalone: true, selector: "dotcms-container", inputs: { container: "container" }, host: { properties: { "attr.data-dot-accept-types": "this.acceptTypes", "attr.data-dot-identifier": "this.identifier", "attr.data-max-contentlets": "this.maxContentlets", "attr.data-dot-uuid": "this.uuid", "class": "this.class", "attr.data-dot-object": "this.dotObject", "attr.data-testid": "this.testId" } }, usesOnChanges: true, ngImport: i0, template: "@if ($isInsideEditor()) {\n @if ($contentlets().length) {\n @for (contentlet of $contentlets(); track $index) {\n <dotcms-contentlet-wrapper\n [contentlet]=\"contentlet\"\n [container]=\"$dotContainerAsString()\">\n <ng-container\n *ngComponentOutlet=\"\n (componentsMap[contentlet.contentType] || componentsMap['CustomNoComponent']\n | async) || NoComponent;\n inputs: { contentlet }\n \" />\n </dotcms-contentlet-wrapper>\n }\n } @else {\n This container is empty.\n }\n} @else {\n @for (contentlet of $contentlets(); track $index) {\n <ng-container\n *ngComponentOutlet=\"\n componentsMap[contentlet.contentType] | async;\n inputs: { contentlet }\n \" />\n }\n}\n", styles: [":host.empty-container{width:100%;background-color:#ecf0fd;display:flex;justify-content:center;align-items:center;color:#030e32;height:10rem}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "component", type: ContentletComponent, selector: "dotcms-contentlet-wrapper", inputs: ["contentlet", "container"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
660
|
+
}
|
|
661
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ContainerComponent, decorators: [{
|
|
662
|
+
type: Component,
|
|
663
|
+
args: [{ selector: 'dotcms-container', standalone: true, imports: [AsyncPipe, NgComponentOutlet, NoComponent, ContentletComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if ($isInsideEditor()) {\n @if ($contentlets().length) {\n @for (contentlet of $contentlets(); track $index) {\n <dotcms-contentlet-wrapper\n [contentlet]=\"contentlet\"\n [container]=\"$dotContainerAsString()\">\n <ng-container\n *ngComponentOutlet=\"\n (componentsMap[contentlet.contentType] || componentsMap['CustomNoComponent']\n | async) || NoComponent;\n inputs: { contentlet }\n \" />\n </dotcms-contentlet-wrapper>\n }\n } @else {\n This container is empty.\n }\n} @else {\n @for (contentlet of $contentlets(); track $index) {\n <ng-container\n *ngComponentOutlet=\"\n componentsMap[contentlet.contentType] | async;\n inputs: { contentlet }\n \" />\n }\n}\n", styles: [":host.empty-container{width:100%;background-color:#ecf0fd;display:flex;justify-content:center;align-items:center;color:#030e32;height:10rem}\n"] }]
|
|
664
|
+
}], propDecorators: { container: [{
|
|
665
|
+
type: Input,
|
|
666
|
+
args: [{ required: true }]
|
|
667
|
+
}], acceptTypes: [{
|
|
668
|
+
type: HostBinding,
|
|
669
|
+
args: ['attr.data-dot-accept-types']
|
|
670
|
+
}], identifier: [{
|
|
671
|
+
type: HostBinding,
|
|
672
|
+
args: ['attr.data-dot-identifier']
|
|
673
|
+
}], maxContentlets: [{
|
|
674
|
+
type: HostBinding,
|
|
675
|
+
args: ['attr.data-max-contentlets']
|
|
676
|
+
}], uuid: [{
|
|
677
|
+
type: HostBinding,
|
|
678
|
+
args: ['attr.data-dot-uuid']
|
|
679
|
+
}], class: [{
|
|
680
|
+
type: HostBinding,
|
|
681
|
+
args: ['class']
|
|
682
|
+
}], dotObject: [{
|
|
683
|
+
type: HostBinding,
|
|
684
|
+
args: ['attr.data-dot-object']
|
|
685
|
+
}], testId: [{
|
|
686
|
+
type: HostBinding,
|
|
687
|
+
args: ['attr.data-testid']
|
|
688
|
+
}] } });
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* This component is responsible to display a column with containers.
|
|
692
|
+
*
|
|
693
|
+
* @export
|
|
694
|
+
* @class ColumnComponent
|
|
695
|
+
* @implements {OnInit}
|
|
696
|
+
*/
|
|
697
|
+
class ColumnComponent {
|
|
698
|
+
constructor() {
|
|
699
|
+
/**
|
|
700
|
+
* The data-testid attribute used for identifying the component during testing.
|
|
701
|
+
*
|
|
702
|
+
* @memberof ColumnComponent
|
|
703
|
+
*/
|
|
704
|
+
this.containerClasses = '';
|
|
705
|
+
}
|
|
706
|
+
ngOnInit() {
|
|
707
|
+
const { startClass, endClass } = getPositionStyleClasses(this.column.leftOffset, this.column.width + this.column.leftOffset);
|
|
708
|
+
this.containerClasses = `${startClass} ${endClass}`;
|
|
709
|
+
}
|
|
710
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
711
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: ColumnComponent, isStandalone: true, selector: "dotcms-column", inputs: { column: "column" }, host: { properties: { "class": "this.containerClasses" } }, ngImport: i0, template: `
|
|
712
|
+
@for (container of column.containers; track $index) {
|
|
713
|
+
<dotcms-container [container]="container" />
|
|
714
|
+
}
|
|
715
|
+
`, isInline: true, styles: [":host.col-start-1{grid-column-start:1}:host.col-start-2{grid-column-start:2}:host.col-start-3{grid-column-start:3}:host.col-start-4{grid-column-start:4}:host.col-start-5{grid-column-start:5}:host.col-start-6{grid-column-start:6}:host.col-start-7{grid-column-start:7}:host.col-start-8{grid-column-start:8}:host.col-start-9{grid-column-start:9}:host.col-start-10{grid-column-start:10}:host.col-start-11{grid-column-start:11}:host.col-start-12{grid-column-start:12}:host.col-end-1{grid-column-end:1}:host.col-end-2{grid-column-end:2}:host.col-end-3{grid-column-end:3}:host.col-end-4{grid-column-end:4}:host.col-end-5{grid-column-end:5}:host.col-end-6{grid-column-end:6}:host.col-end-7{grid-column-end:7}:host.col-end-8{grid-column-end:8}:host.col-end-9{grid-column-end:9}:host.col-end-10{grid-column-end:10}:host.col-end-11{grid-column-end:11}:host.col-end-12{grid-column-end:12}:host.col-end-13{grid-column-end:13}\n"], dependencies: [{ kind: "component", type: ContainerComponent, selector: "dotcms-container", inputs: ["container"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
716
|
+
}
|
|
717
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ColumnComponent, decorators: [{
|
|
718
|
+
type: Component,
|
|
719
|
+
args: [{ selector: 'dotcms-column', standalone: true, imports: [ContainerComponent], template: `
|
|
720
|
+
@for (container of column.containers; track $index) {
|
|
721
|
+
<dotcms-container [container]="container" />
|
|
722
|
+
}
|
|
723
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host.col-start-1{grid-column-start:1}:host.col-start-2{grid-column-start:2}:host.col-start-3{grid-column-start:3}:host.col-start-4{grid-column-start:4}:host.col-start-5{grid-column-start:5}:host.col-start-6{grid-column-start:6}:host.col-start-7{grid-column-start:7}:host.col-start-8{grid-column-start:8}:host.col-start-9{grid-column-start:9}:host.col-start-10{grid-column-start:10}:host.col-start-11{grid-column-start:11}:host.col-start-12{grid-column-start:12}:host.col-end-1{grid-column-end:1}:host.col-end-2{grid-column-end:2}:host.col-end-3{grid-column-end:3}:host.col-end-4{grid-column-end:4}:host.col-end-5{grid-column-end:5}:host.col-end-6{grid-column-end:6}:host.col-end-7{grid-column-end:7}:host.col-end-8{grid-column-end:8}:host.col-end-9{grid-column-end:9}:host.col-end-10{grid-column-end:10}:host.col-end-11{grid-column-end:11}:host.col-end-12{grid-column-end:12}:host.col-end-13{grid-column-end:13}\n"] }]
|
|
724
|
+
}], propDecorators: { column: [{
|
|
725
|
+
type: Input
|
|
726
|
+
}], containerClasses: [{
|
|
727
|
+
type: HostBinding,
|
|
728
|
+
args: ['class']
|
|
729
|
+
}] } });
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* This component is responsible to display a row with columns.
|
|
733
|
+
*
|
|
734
|
+
* @export
|
|
735
|
+
* @class RowComponent
|
|
736
|
+
*/
|
|
737
|
+
class RowComponent {
|
|
738
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: RowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
739
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: RowComponent, isStandalone: true, selector: "dotcms-row", inputs: { row: "row" }, ngImport: i0, template: `
|
|
740
|
+
@for (column of row.columns; track $index) {
|
|
741
|
+
<dotcms-column [column]="column" />
|
|
742
|
+
}
|
|
743
|
+
`, isInline: true, styles: [":host{display:grid;grid-template-columns:repeat(12,1fr);gap:1rem;row-gap:1rem}\n"], dependencies: [{ kind: "component", type: ColumnComponent, selector: "dotcms-column", inputs: ["column"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
744
|
+
}
|
|
745
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: RowComponent, decorators: [{
|
|
746
|
+
type: Component,
|
|
747
|
+
args: [{ selector: 'dotcms-row', standalone: true, imports: [ColumnComponent], template: `
|
|
748
|
+
@for (column of row.columns; track $index) {
|
|
749
|
+
<dotcms-column [column]="column" />
|
|
750
|
+
}
|
|
751
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:grid;grid-template-columns:repeat(12,1fr);gap:1rem;row-gap:1rem}\n"] }]
|
|
752
|
+
}], propDecorators: { row: [{
|
|
753
|
+
type: Input,
|
|
754
|
+
args: [{ required: true }]
|
|
755
|
+
}] } });
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* `DotcmsLayoutComponent` is a class that represents the layout for a DotCMS page.
|
|
759
|
+
* It includes a `pageAsset` property that represents the DotCMS page asset and a `components` property that represents the dynamic components for the page.
|
|
760
|
+
*
|
|
761
|
+
* @export
|
|
762
|
+
* @class DotcmsLayoutComponent
|
|
763
|
+
*/
|
|
764
|
+
class DotcmsLayoutComponent {
|
|
765
|
+
constructor() {
|
|
766
|
+
this.route = inject(ActivatedRoute);
|
|
767
|
+
this.pageContextService = inject(PageContextService);
|
|
768
|
+
this.destroyRef$ = inject(DestroyRef);
|
|
769
|
+
this.pageAsset$ = this.pageContextService.currentPage$;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Represents the DotCMS page asset.
|
|
773
|
+
*
|
|
774
|
+
* @type {DotCMSPageAsset}
|
|
775
|
+
* @memberof DotcmsLayoutComponent
|
|
776
|
+
*/
|
|
777
|
+
set pageAsset(value) {
|
|
778
|
+
this._pageAsset = value;
|
|
779
|
+
if (!value.layout) {
|
|
780
|
+
console.warn('Warning: pageAsset does not have a `layout` property. Might be using an advaced template or your dotCMS instance not have a enterprise license.');
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Returns the DotCMS page asset.
|
|
785
|
+
*
|
|
786
|
+
* @readonly
|
|
787
|
+
* @type {DotCMSPageAsset}
|
|
788
|
+
* @memberof DotcmsLayoutComponent
|
|
789
|
+
*/
|
|
790
|
+
get pageAsset() {
|
|
791
|
+
return this._pageAsset;
|
|
792
|
+
}
|
|
793
|
+
ngOnInit() {
|
|
794
|
+
this.pageContextService.setContext(this.pageAsset, this.components);
|
|
795
|
+
if (!isInsideEditor()) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
this.client = DotCmsClient.instance;
|
|
799
|
+
this.route.url.pipe(takeUntilDestroyed(this.destroyRef$)).subscribe((urlSegments) => {
|
|
800
|
+
const pathname = '/' + urlSegments.join('/');
|
|
801
|
+
initEditor({ pathname });
|
|
802
|
+
updateNavigation(pathname || '/');
|
|
803
|
+
});
|
|
804
|
+
this.client.editor.on('changes', (data) => {
|
|
805
|
+
if (this.onReload) {
|
|
806
|
+
this.onReload();
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
this.pageContextService.setPageAsset(data);
|
|
810
|
+
});
|
|
811
|
+
postMessageToEditor({ action: CUSTOMER_ACTIONS.CLIENT_READY, payload: this.editor });
|
|
812
|
+
}
|
|
813
|
+
ngOnDestroy() {
|
|
814
|
+
if (!isInsideEditor()) {
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
this.client.editor.off('changes');
|
|
818
|
+
}
|
|
819
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotcmsLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
820
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: DotcmsLayoutComponent, isStandalone: true, selector: "dotcms-layout", inputs: { pageAsset: "pageAsset", components: "components", onReload: "onReload", editor: "editor" }, ngImport: i0, template: `
|
|
821
|
+
@if (pageAsset$ | async; as page) {
|
|
822
|
+
@for (row of this.page?.layout?.body?.rows; track $index) {
|
|
823
|
+
<dotcms-row [row]="row" />
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: RowComponent, selector: "dotcms-row", inputs: ["row"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
827
|
+
}
|
|
828
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotcmsLayoutComponent, decorators: [{
|
|
829
|
+
type: Component,
|
|
830
|
+
args: [{ selector: 'dotcms-layout', standalone: true, imports: [RowComponent, AsyncPipe], template: `
|
|
831
|
+
@if (pageAsset$ | async; as page) {
|
|
832
|
+
@for (row of this.page?.layout?.body?.rows; track $index) {
|
|
833
|
+
<dotcms-row [row]="row" />
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
|
|
837
|
+
}], propDecorators: { pageAsset: [{
|
|
838
|
+
type: Input,
|
|
839
|
+
args: [{ required: true }]
|
|
840
|
+
}], components: [{
|
|
841
|
+
type: Input,
|
|
842
|
+
args: [{ required: true }]
|
|
843
|
+
}], onReload: [{
|
|
844
|
+
type: Input
|
|
845
|
+
}], editor: [{
|
|
846
|
+
type: Input
|
|
847
|
+
}] } });
|
|
848
|
+
|
|
849
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
850
|
+
|
|
851
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
852
|
+
|
|
853
|
+
/**
|
|
854
|
+
* Generated bundle index. Do not edit.
|
|
855
|
+
*/
|
|
856
|
+
|
|
857
|
+
export { DotEditableTextComponent, DotcmsLayoutComponent, PageContextService };
|
|
858
|
+
//# sourceMappingURL=dotcms-angular.mjs.map
|