@dotcms/angular 0.0.1-alpha.38 → 0.0.1-alpha.39
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/.eslintrc.json +18 -0
- package/jest.config.ts +22 -0
- package/ng-package.json +7 -0
- package/package.json +4 -21
- package/project.json +33 -0
- package/{index.d.ts → src/index.ts} +0 -1
- package/src/lib/components/dot-editable-text/dot-editable-text.component.css +4 -0
- package/src/lib/components/dot-editable-text/dot-editable-text.component.html +8 -0
- package/src/lib/components/dot-editable-text/dot-editable-text.component.spec.ts +424 -0
- package/src/lib/components/dot-editable-text/dot-editable-text.component.ts +269 -0
- package/src/lib/components/dot-editable-text/utils.ts +51 -0
- package/src/lib/components/no-component/no-component.component.css +3 -0
- package/src/lib/components/no-component/no-component.component.spec.ts +24 -0
- package/src/lib/components/no-component/no-component.component.ts +31 -0
- package/src/lib/layout/column/column.component.css +99 -0
- package/src/lib/layout/column/column.component.spec.ts +33 -0
- package/src/lib/layout/column/column.component.ts +49 -0
- package/src/lib/layout/container/container.component.css +9 -0
- package/src/lib/layout/container/container.component.html +26 -0
- package/src/lib/layout/container/container.component.spec.ts +205 -0
- package/src/lib/layout/container/container.component.ts +140 -0
- package/src/lib/layout/contentlet/contentlet.component.spec.ts +22 -0
- package/{lib/layout/contentlet/contentlet.component.d.ts → src/lib/layout/contentlet/contentlet.component.ts} +32 -17
- package/src/lib/layout/dotcms-layout/dotcms-layout.component.css +3 -0
- package/src/lib/layout/dotcms-layout/dotcms-layout.component.spec.ts +195 -0
- package/src/lib/layout/dotcms-layout/dotcms-layout.component.ts +150 -0
- package/src/lib/layout/row/row.component.css +6 -0
- package/src/lib/layout/row/row.component.spec.ts +28 -0
- package/src/lib/layout/row/row.component.ts +32 -0
- package/{lib/models/dotcms.model.d.ts → src/lib/models/dotcms.model.ts} +21 -3
- package/{lib/models/index.d.ts → src/lib/models/index.ts} +8 -1
- package/{lib/services/dotcms-context/page-context.service.d.ts → src/lib/services/dotcms-context/page-context.service.ts} +41 -12
- package/src/lib/services/dotcms-context/page-context.spec.ts +80 -0
- package/src/lib/utils/index.ts +92 -0
- package/src/lib/utils/testing.utils.ts +1019 -0
- package/src/test-setup.ts +8 -0
- package/tsconfig.json +29 -0
- package/tsconfig.lib.json +12 -0
- package/tsconfig.lib.prod.json +9 -0
- package/tsconfig.spec.json +11 -0
- package/dotcms-angular.d.ts.map +0 -1
- package/esm2022/dotcms-angular.mjs +0 -5
- package/esm2022/index.mjs +0 -5
- package/esm2022/lib/components/dot-editable-text/dot-editable-text.component.mjs +0 -225
- package/esm2022/lib/components/dot-editable-text/utils.mjs +0 -43
- package/esm2022/lib/components/no-component/no-component.component.mjs +0 -32
- package/esm2022/lib/layout/column/column.component.mjs +0 -45
- package/esm2022/lib/layout/container/container.component.mjs +0 -126
- package/esm2022/lib/layout/contentlet/contentlet.component.mjs +0 -120
- package/esm2022/lib/layout/dotcms-layout/dotcms-layout.component.mjs +0 -100
- package/esm2022/lib/layout/row/row.component.mjs +0 -29
- package/esm2022/lib/models/dotcms.model.mjs +0 -3
- package/esm2022/lib/models/index.mjs +0 -3
- package/esm2022/lib/services/dotcms-context/page-context.service.mjs +0 -75
- package/esm2022/lib/utils/index.mjs +0 -79
- package/fesm2022/dotcms-angular.mjs +0 -858
- package/fesm2022/dotcms-angular.mjs.map +0 -1
- package/index.d.ts.map +0 -1
- package/lib/components/dot-editable-text/dot-editable-text.component.d.ts +0 -129
- package/lib/components/dot-editable-text/dot-editable-text.component.d.ts.map +0 -1
- package/lib/components/dot-editable-text/utils.d.ts +0 -7
- package/lib/components/dot-editable-text/utils.d.ts.map +0 -1
- package/lib/components/no-component/no-component.component.d.ts +0 -22
- package/lib/components/no-component/no-component.component.d.ts.map +0 -1
- package/lib/layout/column/column.component.d.ts +0 -29
- package/lib/layout/column/column.component.d.ts.map +0 -1
- package/lib/layout/container/container.component.d.ts +0 -88
- package/lib/layout/container/container.component.d.ts.map +0 -1
- package/lib/layout/contentlet/contentlet.component.d.ts.map +0 -1
- package/lib/layout/dotcms-layout/dotcms-layout.component.d.ts +0 -67
- package/lib/layout/dotcms-layout/dotcms-layout.component.d.ts.map +0 -1
- package/lib/layout/row/row.component.d.ts +0 -20
- package/lib/layout/row/row.component.d.ts.map +0 -1
- package/lib/models/dotcms.model.d.ts.map +0 -1
- package/lib/models/index.d.ts.map +0 -1
- package/lib/services/dotcms-context/page-context.service.d.ts.map +0 -1
- package/lib/utils/index.d.ts +0 -63
- package/lib/utils/index.d.ts.map +0 -1
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { AsyncPipe } from '@angular/common';
|
|
2
|
+
import {
|
|
3
|
+
ChangeDetectionStrategy,
|
|
4
|
+
Component,
|
|
5
|
+
DestroyRef,
|
|
6
|
+
Input,
|
|
7
|
+
OnInit,
|
|
8
|
+
inject
|
|
9
|
+
} from '@angular/core';
|
|
10
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
11
|
+
import { ActivatedRoute } from '@angular/router';
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
CUSTOMER_ACTIONS,
|
|
15
|
+
DotCmsClient,
|
|
16
|
+
EditorConfig,
|
|
17
|
+
initEditor,
|
|
18
|
+
isInsideEditor,
|
|
19
|
+
postMessageToEditor,
|
|
20
|
+
updateNavigation
|
|
21
|
+
} from '@dotcms/client';
|
|
22
|
+
|
|
23
|
+
import { DotCMSPageComponent } from '../../models';
|
|
24
|
+
import { DotCMSPageAsset } from '../../models/dotcms.model';
|
|
25
|
+
import { PageContextService } from '../../services/dotcms-context/page-context.service';
|
|
26
|
+
import { RowComponent } from '../row/row.component';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* `DotcmsLayoutComponent` is a class that represents the layout for a DotCMS page.
|
|
30
|
+
* It includes a `pageAsset` property that represents the DotCMS page asset and a `components` property that represents the dynamic components for the page.
|
|
31
|
+
*
|
|
32
|
+
* @export
|
|
33
|
+
* @class DotcmsLayoutComponent
|
|
34
|
+
*/
|
|
35
|
+
@Component({
|
|
36
|
+
selector: 'dotcms-layout',
|
|
37
|
+
standalone: true,
|
|
38
|
+
imports: [RowComponent, AsyncPipe],
|
|
39
|
+
template: `
|
|
40
|
+
@if (pageAsset$ | async; as page) {
|
|
41
|
+
@for (row of this.page?.layout?.body?.rows; track $index) {
|
|
42
|
+
<dotcms-row [row]="row" />
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
`,
|
|
46
|
+
styleUrl: './dotcms-layout.component.css',
|
|
47
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
48
|
+
})
|
|
49
|
+
export class DotcmsLayoutComponent implements OnInit {
|
|
50
|
+
private _pageAsset!: DotCMSPageAsset;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Represents the DotCMS page asset.
|
|
54
|
+
*
|
|
55
|
+
* @type {DotCMSPageAsset}
|
|
56
|
+
* @memberof DotcmsLayoutComponent
|
|
57
|
+
*/
|
|
58
|
+
@Input({ required: true })
|
|
59
|
+
set pageAsset(value: DotCMSPageAsset) {
|
|
60
|
+
this._pageAsset = value;
|
|
61
|
+
if (!value.layout) {
|
|
62
|
+
console.warn(
|
|
63
|
+
'Warning: pageAsset does not have a `layout` property. Might be using an advaced template or your dotCMS instance not have a enterprise license.'
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Returns the DotCMS page asset.
|
|
70
|
+
*
|
|
71
|
+
* @readonly
|
|
72
|
+
* @type {DotCMSPageAsset}
|
|
73
|
+
* @memberof DotcmsLayoutComponent
|
|
74
|
+
*/
|
|
75
|
+
get pageAsset(): DotCMSPageAsset {
|
|
76
|
+
return this._pageAsset;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The `components` property is a record of dynamic components for each Contentlet on the page.
|
|
81
|
+
*
|
|
82
|
+
* @type {DotCMSPageComponent}
|
|
83
|
+
* @memberof DotcmsLayoutComponent
|
|
84
|
+
* @required
|
|
85
|
+
*/
|
|
86
|
+
@Input({ required: true }) components!: DotCMSPageComponent;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The `onReload` property is a function that reloads the page after changes are made.
|
|
90
|
+
*
|
|
91
|
+
* @memberof DotcmsLayoutComponent
|
|
92
|
+
* @deprecated In future implementation we will be listening for the changes from the editor to update the page state so reload will not be needed.
|
|
93
|
+
*/
|
|
94
|
+
@Input() onReload!: () => void;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
*
|
|
98
|
+
* @type {DotCMSFetchConfig}
|
|
99
|
+
* @memberof DotCMSPageEditorConfig
|
|
100
|
+
* @description The configuration custom params for data fetching on Edit Mode.
|
|
101
|
+
* @example <caption>Example with Custom GraphQL query</caption>
|
|
102
|
+
* <dotcms-layout [editor]="{ query: 'query { ... }' }"/>
|
|
103
|
+
*
|
|
104
|
+
* @example <caption>Example usage with Custom Page API parameters</caption>
|
|
105
|
+
* <dotcms-layout [editor]="{ params: { depth: '2' } }"/>;
|
|
106
|
+
*/
|
|
107
|
+
@Input() editor!: EditorConfig;
|
|
108
|
+
|
|
109
|
+
private readonly route = inject(ActivatedRoute);
|
|
110
|
+
private readonly pageContextService = inject(PageContextService);
|
|
111
|
+
private readonly destroyRef$ = inject(DestroyRef);
|
|
112
|
+
private client!: DotCmsClient;
|
|
113
|
+
protected readonly pageAsset$ = this.pageContextService.currentPage$;
|
|
114
|
+
|
|
115
|
+
ngOnInit() {
|
|
116
|
+
this.pageContextService.setContext(this.pageAsset, this.components);
|
|
117
|
+
|
|
118
|
+
if (!isInsideEditor()) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.client = DotCmsClient.instance;
|
|
123
|
+
this.route.url.pipe(takeUntilDestroyed(this.destroyRef$)).subscribe((urlSegments) => {
|
|
124
|
+
const pathname = '/' + urlSegments.join('/');
|
|
125
|
+
|
|
126
|
+
initEditor({ pathname });
|
|
127
|
+
updateNavigation(pathname || '/');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
this.client.editor.on('changes', (data) => {
|
|
131
|
+
if (this.onReload) {
|
|
132
|
+
this.onReload();
|
|
133
|
+
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this.pageContextService.setPageAsset(data as DotCMSPageAsset);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
postMessageToEditor({ action: CUSTOMER_ACTIONS.CLIENT_READY, payload: this.editor });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
ngOnDestroy() {
|
|
144
|
+
if (!isInsideEditor()) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
this.client.editor.off('changes');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Spectator, createComponentFactory } from '@ngneat/spectator/jest';
|
|
2
|
+
import { MockComponent } from 'ng-mocks';
|
|
3
|
+
|
|
4
|
+
import { RowComponent } from './row.component';
|
|
5
|
+
|
|
6
|
+
import { DotPageAssetLayoutRow } from '../../models';
|
|
7
|
+
import { PageResponseMock } from '../../utils/testing.utils';
|
|
8
|
+
import { ColumnComponent } from '../column/column.component';
|
|
9
|
+
|
|
10
|
+
describe('RowComponent', () => {
|
|
11
|
+
let spectator: Spectator<RowComponent>;
|
|
12
|
+
const createComponent = createComponentFactory({
|
|
13
|
+
component: RowComponent,
|
|
14
|
+
imports: [MockComponent(ColumnComponent)]
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
spectator = createComponent({
|
|
19
|
+
props: {
|
|
20
|
+
row: PageResponseMock.layout.body.rows[1] as DotPageAssetLayoutRow
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should render two columns', () => {
|
|
26
|
+
expect(spectator.queryAll(ColumnComponent)?.length).toBe(4);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
import { DotPageAssetLayoutRow } from '../../models';
|
|
4
|
+
import { ColumnComponent } from '../column/column.component';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This component is responsible to display a row with columns.
|
|
8
|
+
*
|
|
9
|
+
* @export
|
|
10
|
+
* @class RowComponent
|
|
11
|
+
*/
|
|
12
|
+
@Component({
|
|
13
|
+
selector: 'dotcms-row',
|
|
14
|
+
standalone: true,
|
|
15
|
+
imports: [ColumnComponent],
|
|
16
|
+
template: `
|
|
17
|
+
@for (column of row.columns; track $index) {
|
|
18
|
+
<dotcms-column [column]="column" />
|
|
19
|
+
}
|
|
20
|
+
`,
|
|
21
|
+
styleUrl: './row.component.css',
|
|
22
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
23
|
+
})
|
|
24
|
+
export class RowComponent {
|
|
25
|
+
/**
|
|
26
|
+
* The row object containing the columns.
|
|
27
|
+
*
|
|
28
|
+
* @type {DotPageAssetLayoutRow}
|
|
29
|
+
* @memberof RowComponent
|
|
30
|
+
*/
|
|
31
|
+
@Input({ required: true }) row!: DotPageAssetLayoutRow;
|
|
32
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
|
|
1
3
|
export interface DotCMSPageAsset {
|
|
2
4
|
canCreateTemplate: boolean;
|
|
3
5
|
containers: DotCMSPageAssetContainer;
|
|
@@ -20,6 +22,7 @@ export interface DotCMSPageAsset {
|
|
|
20
22
|
forward: boolean;
|
|
21
23
|
};
|
|
22
24
|
}
|
|
25
|
+
|
|
23
26
|
export interface DotPageAssetLayoutRow {
|
|
24
27
|
identifier: number;
|
|
25
28
|
value?: string;
|
|
@@ -27,6 +30,7 @@ export interface DotPageAssetLayoutRow {
|
|
|
27
30
|
columns: DotPageAssetLayoutColumn[];
|
|
28
31
|
styleClass?: string;
|
|
29
32
|
}
|
|
33
|
+
|
|
30
34
|
export interface DotPageAssetLayoutColumn {
|
|
31
35
|
preview: boolean;
|
|
32
36
|
containers: DotCMSContainer[];
|
|
@@ -36,6 +40,7 @@ export interface DotPageAssetLayoutColumn {
|
|
|
36
40
|
left: number;
|
|
37
41
|
styleClass?: string;
|
|
38
42
|
}
|
|
43
|
+
|
|
39
44
|
export interface DotCMSPageAssetContainer {
|
|
40
45
|
[key: string]: {
|
|
41
46
|
container: DotCMSContainer;
|
|
@@ -45,6 +50,7 @@ export interface DotCMSPageAssetContainer {
|
|
|
45
50
|
};
|
|
46
51
|
};
|
|
47
52
|
}
|
|
53
|
+
|
|
48
54
|
export interface DotCMSContainer {
|
|
49
55
|
identifier: string;
|
|
50
56
|
uuid: string;
|
|
@@ -87,6 +93,7 @@ export interface DotCMSContainer {
|
|
|
87
93
|
contentlets: DotCMSContentlet[];
|
|
88
94
|
parentPermissionable: DotCMSSiteParentPermissionable;
|
|
89
95
|
}
|
|
96
|
+
|
|
90
97
|
export interface DotCMSContentlet {
|
|
91
98
|
archived: boolean;
|
|
92
99
|
baseType: string;
|
|
@@ -124,8 +131,9 @@ export interface DotCMSContentlet {
|
|
|
124
131
|
contentTypeIcon?: string;
|
|
125
132
|
variant?: string;
|
|
126
133
|
__icon__?: string;
|
|
127
|
-
[key: string]: any;
|
|
134
|
+
[key: string]: any; // This is a catch-all for any other custom properties that might be on the contentlet.
|
|
128
135
|
}
|
|
136
|
+
|
|
129
137
|
export interface DotcmsNavigationItem {
|
|
130
138
|
code?: any;
|
|
131
139
|
folder: string;
|
|
@@ -139,6 +147,7 @@ export interface DotcmsNavigationItem {
|
|
|
139
147
|
target: string;
|
|
140
148
|
order: number;
|
|
141
149
|
}
|
|
150
|
+
|
|
142
151
|
interface DotCMSTemplate {
|
|
143
152
|
iDate: number;
|
|
144
153
|
type: string;
|
|
@@ -173,6 +182,7 @@ interface DotCMSTemplate {
|
|
|
173
182
|
new: boolean;
|
|
174
183
|
canEdit: boolean;
|
|
175
184
|
}
|
|
185
|
+
|
|
176
186
|
interface DotCMSPage {
|
|
177
187
|
template: string;
|
|
178
188
|
modDate: number;
|
|
@@ -218,6 +228,7 @@ interface DotCMSPage {
|
|
|
218
228
|
liveInode: string;
|
|
219
229
|
shortyLive: string;
|
|
220
230
|
}
|
|
231
|
+
|
|
221
232
|
interface DotCMSViewAs {
|
|
222
233
|
language: {
|
|
223
234
|
id: number;
|
|
@@ -228,6 +239,7 @@ interface DotCMSViewAs {
|
|
|
228
239
|
};
|
|
229
240
|
mode: string;
|
|
230
241
|
}
|
|
242
|
+
|
|
231
243
|
interface DotCMSLayout {
|
|
232
244
|
pageWidth: string;
|
|
233
245
|
width: string;
|
|
@@ -238,6 +250,7 @@ interface DotCMSLayout {
|
|
|
238
250
|
body: DotPageAssetLayoutBody;
|
|
239
251
|
sidebar: DotPageAssetLayoutSidebar;
|
|
240
252
|
}
|
|
253
|
+
|
|
241
254
|
interface DotCMSContainerStructure {
|
|
242
255
|
id: string;
|
|
243
256
|
structureId: string;
|
|
@@ -246,6 +259,7 @@ interface DotCMSContainerStructure {
|
|
|
246
259
|
code: string;
|
|
247
260
|
contentTypeVar: string;
|
|
248
261
|
}
|
|
262
|
+
|
|
249
263
|
interface DotPageAssetLayoutSidebar {
|
|
250
264
|
preview: boolean;
|
|
251
265
|
containers: DotCMSContainer[];
|
|
@@ -253,9 +267,11 @@ interface DotPageAssetLayoutSidebar {
|
|
|
253
267
|
widthPercent: number;
|
|
254
268
|
width: string;
|
|
255
269
|
}
|
|
270
|
+
|
|
256
271
|
interface DotPageAssetLayoutBody {
|
|
257
272
|
rows: DotPageAssetLayoutRow[];
|
|
258
273
|
}
|
|
274
|
+
|
|
259
275
|
interface DotCMSSite {
|
|
260
276
|
lowIndexPriority: boolean;
|
|
261
277
|
name: string;
|
|
@@ -306,12 +322,14 @@ interface DotCMSSite {
|
|
|
306
322
|
sortOrder: number;
|
|
307
323
|
contentType: DotCMSSiteContentType;
|
|
308
324
|
}
|
|
325
|
+
|
|
309
326
|
interface DotCMSSiteContentType {
|
|
310
327
|
owner?: any;
|
|
311
328
|
parentPermissionable: DotCMSSiteParentPermissionable;
|
|
312
329
|
permissionId: string;
|
|
313
330
|
permissionType: string;
|
|
314
331
|
}
|
|
332
|
+
|
|
315
333
|
export interface DotCMSSiteParentPermissionable {
|
|
316
334
|
Inode: string;
|
|
317
335
|
Identifier: string;
|
|
@@ -326,6 +344,7 @@ export interface DotCMSSiteParentPermissionable {
|
|
|
326
344
|
childrenPermissionable?: any;
|
|
327
345
|
variantId?: string;
|
|
328
346
|
}
|
|
347
|
+
|
|
329
348
|
interface DotCMSSiteStructure {
|
|
330
349
|
iDate: number;
|
|
331
350
|
type: string;
|
|
@@ -371,6 +390,7 @@ interface DotCMSSiteStructure {
|
|
|
371
390
|
versionId: string;
|
|
372
391
|
versionType: string;
|
|
373
392
|
}
|
|
393
|
+
|
|
374
394
|
interface DotCMSSiteField {
|
|
375
395
|
iDate: number;
|
|
376
396
|
type: string;
|
|
@@ -412,5 +432,3 @@ interface DotCMSSiteField {
|
|
|
412
432
|
versionId: string;
|
|
413
433
|
versionType: string;
|
|
414
434
|
}
|
|
415
|
-
export {};
|
|
416
|
-
//# sourceMappingURL=dotcms.model.d.ts.map
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
export * from './dotcms.model';
|
|
3
|
+
|
|
2
4
|
import { Type } from '@angular/core';
|
|
5
|
+
|
|
3
6
|
import { DotCMSPageAsset } from './dotcms.model';
|
|
7
|
+
|
|
4
8
|
/**
|
|
5
9
|
* Represents a dynamic component entity.
|
|
6
10
|
* @typedef {Promise<Type<any>>} DynamicComponentEntity
|
|
7
11
|
* @memberof @dotcms/angular
|
|
8
12
|
*/
|
|
9
13
|
export type DynamicComponentEntity = Promise<Type<any>>;
|
|
14
|
+
|
|
10
15
|
/**
|
|
11
16
|
* Represents the context of a DotCMS page.
|
|
12
17
|
*/
|
|
@@ -17,12 +22,14 @@ export interface DotCMSPageContext {
|
|
|
17
22
|
* @memberof DotCMSPageContext
|
|
18
23
|
*/
|
|
19
24
|
pageAsset: DotCMSPageAsset;
|
|
25
|
+
|
|
20
26
|
/**
|
|
21
27
|
* Represents the dynamic components of the page for each Content Type.
|
|
22
28
|
* @type {DotCMSPageComponent}
|
|
23
29
|
* @memberof DotCMSPageContext
|
|
24
30
|
*/
|
|
25
31
|
components: DotCMSPageComponent;
|
|
32
|
+
|
|
26
33
|
/**
|
|
27
34
|
* Indicates whether the page is being viewed inside the editor.
|
|
28
35
|
* @type {boolean}
|
|
@@ -30,6 +37,7 @@ export interface DotCMSPageContext {
|
|
|
30
37
|
*/
|
|
31
38
|
isInsideEditor: boolean;
|
|
32
39
|
}
|
|
40
|
+
|
|
33
41
|
/**
|
|
34
42
|
* Represents a DotCMS page component.
|
|
35
43
|
* Used to store the dynamic components of a DotCMS page.
|
|
@@ -37,4 +45,3 @@ export interface DotCMSPageContext {
|
|
|
37
45
|
* @memberof @dotcms/angular
|
|
38
46
|
*/
|
|
39
47
|
export type DotCMSPageComponent = Record<string, DynamicComponentEntity>;
|
|
40
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,49 +1,78 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
1
|
+
import { BehaviorSubject, Observable } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
import { Injectable } from '@angular/core';
|
|
4
|
+
|
|
5
|
+
import { map } from 'rxjs/operators';
|
|
6
|
+
|
|
7
|
+
import { isInsideEditor } from '@dotcms/client';
|
|
8
|
+
|
|
2
9
|
import { DotCMSPageComponent, DotCMSPageContext } from '../../models';
|
|
3
10
|
import { DotCMSPageAsset } from '../../models/dotcms.model';
|
|
4
|
-
|
|
11
|
+
|
|
5
12
|
/**
|
|
6
13
|
* @author dotCMS
|
|
7
14
|
* @description This service is responsible for managing the page context.
|
|
8
15
|
* @export
|
|
9
16
|
* @class PageContextService
|
|
10
17
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
@Injectable({
|
|
19
|
+
providedIn: 'root'
|
|
20
|
+
})
|
|
21
|
+
export class PageContextService {
|
|
22
|
+
private context$ = new BehaviorSubject<DotCMSPageContext | null>(null);
|
|
23
|
+
|
|
13
24
|
/**
|
|
14
25
|
* @description Get the context
|
|
15
26
|
* @readonly
|
|
16
27
|
* @type {DotCMSPageContext}
|
|
17
28
|
* @memberof PageContextService
|
|
18
29
|
*/
|
|
19
|
-
get context(): DotCMSPageContext
|
|
30
|
+
get context(): DotCMSPageContext {
|
|
31
|
+
return this.context$.getValue() as DotCMSPageContext;
|
|
32
|
+
}
|
|
33
|
+
|
|
20
34
|
/**
|
|
21
35
|
* @description Get the context as an observable
|
|
22
36
|
* @readonly
|
|
23
37
|
* @memberof PageContextService
|
|
24
38
|
*/
|
|
25
|
-
get contextObs$()
|
|
39
|
+
get contextObs$() {
|
|
40
|
+
return this.context$.asObservable();
|
|
41
|
+
}
|
|
42
|
+
|
|
26
43
|
/**
|
|
27
44
|
* @description Get the current page asset
|
|
28
45
|
* @readonly
|
|
29
46
|
* @type {(Observable<DotCMSPageAsset | null>)}
|
|
30
47
|
* @memberof PageContextService
|
|
31
48
|
*/
|
|
32
|
-
get currentPage$(): Observable<DotCMSPageAsset | null
|
|
49
|
+
get currentPage$(): Observable<DotCMSPageAsset | null> {
|
|
50
|
+
return this.contextObs$.pipe(map((context) => context?.pageAsset || null));
|
|
51
|
+
}
|
|
52
|
+
|
|
33
53
|
/**
|
|
34
54
|
*
|
|
35
55
|
* @description Set the context
|
|
36
56
|
* @param {DotCMSPageAsset} value
|
|
37
57
|
* @memberof DotcmsContextService
|
|
38
58
|
*/
|
|
39
|
-
setContext(pageAsset: DotCMSPageAsset, components: DotCMSPageComponent)
|
|
59
|
+
setContext(pageAsset: DotCMSPageAsset, components: DotCMSPageComponent) {
|
|
60
|
+
this.context$.next({
|
|
61
|
+
pageAsset,
|
|
62
|
+
components,
|
|
63
|
+
isInsideEditor: isInsideEditor()
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
40
67
|
/**
|
|
41
68
|
* @description Set the page asset in the context
|
|
42
69
|
* @param {DotCMSPageAsset} pageAsset
|
|
43
70
|
* @memberof PageContextService
|
|
44
71
|
*/
|
|
45
|
-
setPageAsset(pageAsset: DotCMSPageAsset)
|
|
46
|
-
|
|
47
|
-
|
|
72
|
+
setPageAsset(pageAsset: DotCMSPageAsset) {
|
|
73
|
+
this.context$.next({
|
|
74
|
+
...this.context,
|
|
75
|
+
pageAsset
|
|
76
|
+
});
|
|
77
|
+
}
|
|
48
78
|
}
|
|
49
|
-
//# sourceMappingURL=page-context.service.d.ts.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { SpectatorService, createServiceFactory } from '@ngneat/spectator';
|
|
2
|
+
|
|
3
|
+
import { TestBed } from '@angular/core/testing';
|
|
4
|
+
|
|
5
|
+
import { PageContextService } from './page-context.service';
|
|
6
|
+
|
|
7
|
+
import { DotCMSPageAsset, DotCMSPageComponent } from '../../models';
|
|
8
|
+
import { PageResponseMock } from '../../utils/testing.utils';
|
|
9
|
+
|
|
10
|
+
const initialPageAssetMock = {} as DotCMSPageAsset;
|
|
11
|
+
const initialComponentsMock = {} as DotCMSPageComponent;
|
|
12
|
+
|
|
13
|
+
describe('PageContextService', () => {
|
|
14
|
+
let spectator: SpectatorService<PageContextService>;
|
|
15
|
+
let service: PageContextService;
|
|
16
|
+
|
|
17
|
+
const createService = createServiceFactory(PageContextService);
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
TestBed.configureTestingModule({});
|
|
21
|
+
spectator = createService();
|
|
22
|
+
service = spectator.service;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should set the context', () => {
|
|
26
|
+
service.setContext(initialPageAssetMock, initialComponentsMock);
|
|
27
|
+
|
|
28
|
+
expect(service.context).toEqual({
|
|
29
|
+
components: initialComponentsMock,
|
|
30
|
+
pageAsset: initialPageAssetMock,
|
|
31
|
+
isInsideEditor: false
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should set the page asset in the context', () => {
|
|
36
|
+
service.setContext(initialPageAssetMock, initialComponentsMock);
|
|
37
|
+
|
|
38
|
+
const newPageAssetMock = PageResponseMock as unknown as DotCMSPageAsset;
|
|
39
|
+
|
|
40
|
+
service.setPageAsset(newPageAssetMock);
|
|
41
|
+
|
|
42
|
+
expect(service.context).toEqual({
|
|
43
|
+
components: initialComponentsMock,
|
|
44
|
+
pageAsset: newPageAssetMock,
|
|
45
|
+
isInsideEditor: false
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should return the context', () => {
|
|
50
|
+
service.setContext(initialPageAssetMock, initialComponentsMock);
|
|
51
|
+
|
|
52
|
+
expect(service.context).toEqual({
|
|
53
|
+
components: initialComponentsMock,
|
|
54
|
+
pageAsset: initialPageAssetMock,
|
|
55
|
+
isInsideEditor: false
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should return the context as an observable', (done) => {
|
|
60
|
+
service.setContext(initialPageAssetMock, initialComponentsMock);
|
|
61
|
+
|
|
62
|
+
service.contextObs$.subscribe((context) => {
|
|
63
|
+
expect(context).toEqual({
|
|
64
|
+
components: initialComponentsMock,
|
|
65
|
+
pageAsset: initialPageAssetMock,
|
|
66
|
+
isInsideEditor: false
|
|
67
|
+
});
|
|
68
|
+
done();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should return the page asset as an observable', (done) => {
|
|
73
|
+
service.setContext(initialPageAssetMock, initialComponentsMock);
|
|
74
|
+
|
|
75
|
+
service.currentPage$.subscribe((pageAsset) => {
|
|
76
|
+
expect(pageAsset).toEqual(initialPageAssetMock);
|
|
77
|
+
done();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { DotCMSContainer, DotCMSPageAssetContainer } from '../models/dotcms.model';
|
|
2
|
+
|
|
3
|
+
//Changed the type, to avoid SQ issue.
|
|
4
|
+
//This should be put inside a lib
|
|
5
|
+
/**
|
|
6
|
+
* Represents a mapping of numbers to corresponding CSS class names for column end values.
|
|
7
|
+
* @typedef {Record<number, string | null>} EndClassMap
|
|
8
|
+
*/
|
|
9
|
+
const endClassMap: Record<number, string | null> = {
|
|
10
|
+
1: 'col-end-1',
|
|
11
|
+
2: 'col-end-2',
|
|
12
|
+
3: 'col-end-3',
|
|
13
|
+
4: 'col-end-4',
|
|
14
|
+
5: 'col-end-5',
|
|
15
|
+
6: 'col-end-6',
|
|
16
|
+
7: 'col-end-7',
|
|
17
|
+
8: 'col-end-8',
|
|
18
|
+
9: 'col-end-9',
|
|
19
|
+
10: 'col-end-10',
|
|
20
|
+
11: 'col-end-11',
|
|
21
|
+
12: 'col-end-12',
|
|
22
|
+
13: 'col-end-13'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
//Changed the type, to avoid SQ issue.
|
|
26
|
+
//This should be put inside a lib
|
|
27
|
+
/**
|
|
28
|
+
* Represents a mapping of numbers to CSS class names for starting columns.
|
|
29
|
+
* @typedef {Record<number, string | null>} StartClassMap
|
|
30
|
+
*/
|
|
31
|
+
const startClassMap: Record<number, string | null> = {
|
|
32
|
+
1: 'col-start-1',
|
|
33
|
+
2: 'col-start-2',
|
|
34
|
+
3: 'col-start-3',
|
|
35
|
+
4: 'col-start-4',
|
|
36
|
+
5: 'col-start-5',
|
|
37
|
+
6: 'col-start-6',
|
|
38
|
+
7: 'col-start-7',
|
|
39
|
+
8: 'col-start-8',
|
|
40
|
+
9: 'col-start-9',
|
|
41
|
+
10: 'col-start-10',
|
|
42
|
+
11: 'col-start-11',
|
|
43
|
+
12: 'col-start-12'
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Retrieves the data for a set of containers.
|
|
48
|
+
*
|
|
49
|
+
* @param containers - The DotCMSPageAssetContainer object containing the containers.
|
|
50
|
+
* @param containerRef - The DotCMSContainer object representing the container reference.
|
|
51
|
+
* @returns An object containing the container data, accept types, contentlets, and variant ID.
|
|
52
|
+
*/
|
|
53
|
+
export const getContainersData = (
|
|
54
|
+
containers: DotCMSPageAssetContainer,
|
|
55
|
+
containerRef: DotCMSContainer
|
|
56
|
+
) => {
|
|
57
|
+
const { identifier, uuid } = containerRef;
|
|
58
|
+
|
|
59
|
+
const { containerStructures, container } = containers[identifier];
|
|
60
|
+
|
|
61
|
+
const { variantId } = container?.parentPermissionable || {};
|
|
62
|
+
|
|
63
|
+
const acceptTypes: string = containerStructures
|
|
64
|
+
.map((structure) => structure.contentTypeVar)
|
|
65
|
+
.join(',');
|
|
66
|
+
|
|
67
|
+
const contentlets = containers[identifier].contentlets[`uuid-${uuid}`];
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
...containers[identifier].container,
|
|
71
|
+
acceptTypes,
|
|
72
|
+
contentlets,
|
|
73
|
+
variantId
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Returns the position style classes based on the start and end values.
|
|
79
|
+
* Used to set the grid column start and end values.
|
|
80
|
+
* @param start - The start value.
|
|
81
|
+
* @param end - The end value.
|
|
82
|
+
* @returns An object containing the startClass and endClass.
|
|
83
|
+
*/
|
|
84
|
+
export const getPositionStyleClasses = (start: number, end: number) => {
|
|
85
|
+
const startClass = startClassMap[start];
|
|
86
|
+
const endClass = endClassMap[end];
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
startClass,
|
|
90
|
+
endClass
|
|
91
|
+
};
|
|
92
|
+
};
|