@nascentdigital/funnel-editor-contentful 4.6.7 → 5.0.1
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/dist/Editor.d.ts +6 -1
- package/dist/Editor.js +17 -1
- package/dist/EditorApp.js +1 -1
- package/dist/EntryEditor.js +42 -1
- package/dist/EntrySidebar.js +18 -1
- package/dist/collection/controller/LocalCollectionController.d.ts +35 -0
- package/dist/collection/controller/LocalCollectionController.js +200 -0
- package/dist/collection/controller/LocalCollectionControllerContainer.d.ts +8 -0
- package/dist/collection/controller/LocalCollectionControllerContainer.js +36 -0
- package/dist/collection/controller/LocalCollectionControllerContext.d.ts +7 -0
- package/dist/collection/controller/LocalCollectionControllerContext.js +6 -0
- package/dist/collection/controller/index.d.ts +4 -0
- package/dist/collection/controller/index.js +20 -0
- package/dist/collection/controller/useLocalCollectionController.d.ts +2 -0
- package/dist/collection/controller/useLocalCollectionController.js +10 -0
- package/dist/collection/index.d.ts +2 -0
- package/dist/collection/index.js +18 -0
- package/dist/collection/screens/CollectionEditor.d.ts +1 -0
- package/dist/collection/screens/CollectionEditor.js +42 -0
- package/dist/collection/screens/index.d.ts +1 -0
- package/dist/{page/hooks → collection/screens}/index.js +1 -1
- package/dist/core/bridge/AppBridgeContainer.d.ts +9 -0
- package/dist/core/bridge/AppBridgeContainer.js +55 -0
- package/dist/core/bridge/AppBridgeContext.d.ts +8 -0
- package/dist/core/bridge/AppBridgeContext.js +11 -0
- package/dist/core/bridge/AppMessage.d.ts +19 -0
- package/dist/core/bridge/AppMessage.js +19 -0
- package/dist/core/bridge/index.d.ts +4 -0
- package/dist/core/bridge/index.js +20 -0
- package/dist/core/bridge/useAppBridge.d.ts +8 -0
- package/dist/core/bridge/useAppBridge.js +24 -0
- package/dist/core/contentful/Contentful.d.ts +33 -0
- package/dist/core/contentful/Contentful.js +67 -0
- package/dist/core/contentful/ContentfulAsset.d.ts +23 -0
- package/dist/core/contentful/ContentfulAsset.js +88 -0
- package/dist/core/contentful/ContentfulCollection.d.ts +29 -0
- package/dist/core/contentful/ContentfulCollection.js +97 -0
- package/dist/core/contentful/ContentfulPage.d.ts +31 -0
- package/dist/core/contentful/ContentfulPage.js +84 -0
- package/dist/core/contentful/ContentfulRefs.d.ts +16 -0
- package/dist/core/contentful/ContentfulRefs.js +152 -0
- package/dist/core/contentful/index.d.ts +5 -0
- package/dist/core/contentful/index.js +21 -0
- package/dist/core/domain/Collection.d.ts +99 -0
- package/dist/core/domain/Collection.js +311 -0
- package/dist/core/domain/Page.d.ts +58 -8
- package/dist/core/domain/Page.js +329 -16
- package/dist/core/domain/index.d.ts +1 -0
- package/dist/core/domain/index.js +1 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +2 -0
- package/dist/core/repository/AssetRepository.d.ts +10 -0
- package/dist/core/repository/AssetRepository.js +33 -0
- package/dist/core/repository/CollectionSerializer.d.ts +9 -0
- package/dist/core/repository/CollectionSerializer.js +41 -0
- package/dist/core/repository/LocalCollectionRepository.d.ts +27 -0
- package/dist/core/repository/LocalCollectionRepository.js +143 -0
- package/dist/core/repository/LocalPageRepository.d.ts +16 -0
- package/dist/core/repository/LocalPageRepository.js +153 -0
- package/dist/core/repository/PageSerializer.d.ts +2 -2
- package/dist/core/repository/PageSerializer.js +16 -13
- package/dist/core/repository/RemoteCollectionRepository.d.ts +19 -0
- package/dist/core/repository/RemoteCollectionRepository.js +236 -0
- package/dist/core/repository/RemotePageRepository.d.ts +14 -0
- package/dist/core/repository/RemotePageRepository.js +113 -0
- package/dist/core/repository/index.d.ts +5 -1
- package/dist/core/repository/index.js +5 -1
- package/dist/page/{hooks/PageController.d.ts → controller/LocalPageController.d.ts} +11 -6
- package/dist/page/controller/LocalPageController.js +190 -0
- package/dist/page/controller/LocalPageControllerContainer.d.ts +8 -0
- package/dist/page/controller/LocalPageControllerContainer.js +36 -0
- package/dist/page/controller/LocalPageControllerContext.d.ts +7 -0
- package/dist/page/controller/LocalPageControllerContext.js +6 -0
- package/dist/page/controller/index.d.ts +3 -0
- package/dist/page/controller/index.js +19 -0
- package/dist/page/controller/useLocalPageController.d.ts +2 -0
- package/dist/page/controller/useLocalPageController.js +10 -0
- package/dist/page/index.d.ts +1 -0
- package/dist/page/index.js +1 -0
- package/dist/page/screens/PageEditor.js +9 -11
- package/package.json +5 -3
- package/dist/core/repository/PageRepository.d.ts +0 -12
- package/dist/core/repository/PageRepository.js +0 -23
- package/dist/page/hooks/PageController.js +0 -107
- package/dist/page/hooks/index.d.ts +0 -1
|
@@ -1,42 +1,75 @@
|
|
|
1
1
|
import { AssetClient } from '@nascentdigital/funnel-cms';
|
|
2
|
-
import { EventBus, Language, Schema } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { EventBus, FieldModel, Language, Schema } from '@nascentdigital/funnel-core';
|
|
3
3
|
import { Asset, Block, IPage, PageSettings, Section, SectionBlock } from '@nascentdigital/funnel-editor/components';
|
|
4
4
|
import { Observable } from 'rxjs';
|
|
5
5
|
export declare class Page implements IPage {
|
|
6
6
|
readonly id: Schema.Page.Id;
|
|
7
7
|
readonly template: Schema.Page;
|
|
8
8
|
readonly eventBus: EventBus;
|
|
9
|
+
readonly settings: PageSettings;
|
|
9
10
|
readonly groupId: Schema.Page.GroupId;
|
|
10
11
|
readonly brand: string;
|
|
11
12
|
readonly language: Language;
|
|
12
13
|
readonly region: string;
|
|
13
|
-
readonly url: string;
|
|
14
14
|
readonly publishedOn?: number;
|
|
15
15
|
readonly createdOn: number;
|
|
16
|
-
|
|
16
|
+
private _state;
|
|
17
|
+
private _initialErrors;
|
|
18
|
+
private readonly _discover;
|
|
17
19
|
private readonly _content;
|
|
18
20
|
private readonly _assets;
|
|
19
21
|
private readonly _pages;
|
|
20
22
|
private readonly _collections;
|
|
21
|
-
private readonly _tags;
|
|
22
23
|
private _initialTags;
|
|
24
|
+
private readonly _tags;
|
|
25
|
+
private _initialName;
|
|
26
|
+
private _name;
|
|
23
27
|
private _initialSlug;
|
|
28
|
+
private _url;
|
|
24
29
|
private _slug;
|
|
25
|
-
private
|
|
30
|
+
private _initialPublication?;
|
|
31
|
+
private _publication?;
|
|
32
|
+
private _updatedOn;
|
|
26
33
|
private _modifiedOn?;
|
|
34
|
+
private _deletedBlocks;
|
|
35
|
+
private _syncing;
|
|
36
|
+
private readonly _subscription;
|
|
37
|
+
private _savingOn?;
|
|
27
38
|
constructor(args: Page.ConstructorArgs);
|
|
28
|
-
settings: PageSettings;
|
|
29
|
-
publication: number | undefined;
|
|
30
39
|
get events$(): Observable<IPage.Events>;
|
|
31
40
|
get stable$(): Observable<boolean>;
|
|
41
|
+
get state(): Schema.Page.State;
|
|
42
|
+
private set state(value);
|
|
32
43
|
get modified(): boolean;
|
|
44
|
+
get updatedOn(): number;
|
|
45
|
+
get changes(): Page.Changes;
|
|
33
46
|
get published(): boolean;
|
|
47
|
+
get type(): Schema.Page.Type;
|
|
34
48
|
get syncing(): boolean;
|
|
49
|
+
set syncing(syncing: boolean);
|
|
50
|
+
repair(): void;
|
|
51
|
+
get url(): string;
|
|
52
|
+
get initialSlug(): string | undefined;
|
|
35
53
|
get hasSlug(): boolean;
|
|
54
|
+
set slug(slug: string | undefined);
|
|
36
55
|
get slug(): string | undefined;
|
|
56
|
+
get initialName(): string;
|
|
57
|
+
get name(): string;
|
|
58
|
+
set name(name: string);
|
|
59
|
+
get initialPublication(): number | undefined;
|
|
60
|
+
get publication(): number | undefined;
|
|
61
|
+
set publication(publication: number | undefined);
|
|
62
|
+
get initialErrors(): boolean;
|
|
63
|
+
get errors(): Page.Errors;
|
|
64
|
+
get valid(): boolean;
|
|
65
|
+
get hasErrors(): boolean;
|
|
66
|
+
get asRef(): IPage.Ref;
|
|
37
67
|
get discover(): ReadonlyArray<Block>;
|
|
68
|
+
get seo(): Block<Schema.Block<string, any, any>>;
|
|
69
|
+
getPreviewBlock(): Block | undefined;
|
|
38
70
|
get content(): ReadonlyArray<Section | Block>;
|
|
39
71
|
get blocks(): (Block<Schema.Block<string, any, any>> | SectionBlock<Schema.Block<string, any, any>>)[];
|
|
72
|
+
get deleteBlocks(): ReadonlyArray<Block>;
|
|
40
73
|
get firstBlock(): Block<Schema.Block<string, any, any>> | SectionBlock<Schema.Block<string, any, any>> | undefined;
|
|
41
74
|
get firstItem(): Block<Schema.Block<string, any, any>> | Section;
|
|
42
75
|
get items(): Array<Block | Section>;
|
|
@@ -45,9 +78,10 @@ export declare class Page implements IPage {
|
|
|
45
78
|
get initialTags(): ReadonlySet<Schema.Tag<string, string>>;
|
|
46
79
|
get tagGroups(): ReadonlyArray<Schema.TagGroup>;
|
|
47
80
|
get tags(): ReadonlySet<Schema.Tag>;
|
|
81
|
+
hydrateStores(references: IPage.References): void;
|
|
48
82
|
getItem(identifier: string | undefined): Block | SectionBlock | Section | PageSettings | undefined;
|
|
49
83
|
coerceItem(identifier: string | undefined): Block | SectionBlock | Section | PageSettings;
|
|
50
|
-
deleteBlock(area: IPage.Area, key: string):
|
|
84
|
+
deleteBlock(area: IPage.Area, key: string): boolean;
|
|
51
85
|
getAsset(assetId: Asset.Id): Asset | undefined;
|
|
52
86
|
getAssetScope(range: Schema.AssetScope.Range): Schema.AssetScope;
|
|
53
87
|
getSearchScope(): AssetClient.GetAssets.Scope;
|
|
@@ -61,6 +95,10 @@ export declare class Page implements IPage {
|
|
|
61
95
|
removePageRef(pageId: Schema.Page.Id): boolean;
|
|
62
96
|
addTag(tag: Schema.Tag): void;
|
|
63
97
|
removeTag(tag: Schema.Tag): void;
|
|
98
|
+
onSaveStart(): void;
|
|
99
|
+
onSaveComplete(updatedOn: number): void;
|
|
100
|
+
private getBlock;
|
|
101
|
+
private raiseEvent;
|
|
64
102
|
}
|
|
65
103
|
export declare namespace Page {
|
|
66
104
|
type ConstructorArgs = {
|
|
@@ -75,15 +113,27 @@ export declare namespace Page {
|
|
|
75
113
|
slug?: string;
|
|
76
114
|
name: string;
|
|
77
115
|
tags: Schema.Tag[];
|
|
116
|
+
discover: Blocks;
|
|
78
117
|
content: Content;
|
|
79
118
|
files?: Asset[];
|
|
80
119
|
pages?: IPage.Ref[];
|
|
81
120
|
collections?: Schema.Collection.Data.AsLink[];
|
|
82
121
|
state: Schema.Page.State;
|
|
122
|
+
errors: boolean;
|
|
83
123
|
createdOn: number;
|
|
84
124
|
updatedOn: number;
|
|
85
125
|
publishedOn?: number;
|
|
86
126
|
publication?: number;
|
|
87
127
|
};
|
|
128
|
+
type Blocks = Block[];
|
|
88
129
|
type Content = Array<Block | Section>;
|
|
130
|
+
type Errors = {
|
|
131
|
+
page: Page;
|
|
132
|
+
items: Array<Block | Section>;
|
|
133
|
+
};
|
|
134
|
+
type Changes = {
|
|
135
|
+
page: Page;
|
|
136
|
+
items: Array<Block | Section>;
|
|
137
|
+
};
|
|
138
|
+
type Target = Block | SectionBlock | Section | FieldModel;
|
|
89
139
|
}
|
package/dist/core/domain/Page.js
CHANGED
|
@@ -16,21 +16,35 @@ class Page {
|
|
|
16
16
|
this.brand = args.brand;
|
|
17
17
|
this.language = args.language;
|
|
18
18
|
this.region = args.region;
|
|
19
|
-
this.url = args.url;
|
|
20
19
|
this.publishedOn = args.publishedOn;
|
|
21
20
|
this.createdOn = args.createdOn;
|
|
22
|
-
this.updatedOn = args.updatedOn;
|
|
23
21
|
this.settings = new components_1.PageSettings(this);
|
|
22
|
+
this._state = args.state;
|
|
23
|
+
this._initialErrors = args.errors;
|
|
24
|
+
this._initialName = this._name = args.name;
|
|
25
|
+
this._updatedOn = args.updatedOn;
|
|
26
|
+
this._discover = args.discover;
|
|
24
27
|
this._content = args.content;
|
|
28
|
+
this._url = args.url;
|
|
25
29
|
this._initialSlug = this._slug = args.slug;
|
|
30
|
+
this._initialPublication = this._publication = args.publication;
|
|
26
31
|
this._assets = (_a = args.files) !== null && _a !== void 0 ? _a : [];
|
|
27
32
|
this._pages = (_b = args.pages) !== null && _b !== void 0 ? _b : [];
|
|
28
33
|
this._collections = (_c = args.collections) !== null && _c !== void 0 ? _c : [];
|
|
29
34
|
this._initialTags = new Set(args.tags);
|
|
30
35
|
this._tags = new Set(args.tags);
|
|
36
|
+
this._deletedBlocks = [];
|
|
31
37
|
this._syncing = false;
|
|
32
38
|
// bind content
|
|
39
|
+
this._discover.forEach(item => item.bind({ parent: this, area: 'discover' }));
|
|
33
40
|
this._content.forEach((item) => item.bind({ parent: this, area: 'content' }));
|
|
41
|
+
// listen to block/field changes
|
|
42
|
+
this._subscription = this.eventBus.events$
|
|
43
|
+
.pipe((0, rxjs_1.filter)(e => (funnel_core_1.Field.Event.filter(e) && e.type === 'changed' && !e.field.sandboxed)
|
|
44
|
+
|| (funnel_core_1.FieldList.Event.filter(e) && e.type === 'changed')
|
|
45
|
+
|| (funnel_core_1.ObjectField.Event.filter(e) && e.type === 'changed')
|
|
46
|
+
|| (components_1.Item.Event.filter(e) && e.type === 'changed')))
|
|
47
|
+
.subscribe(() => this.raiseEvent('changed'));
|
|
34
48
|
}
|
|
35
49
|
get events$() {
|
|
36
50
|
return this.eventBus.events$;
|
|
@@ -38,23 +52,166 @@ class Page {
|
|
|
38
52
|
get stable$() {
|
|
39
53
|
return this.eventBus.events$.pipe((0, rxjs_1.map)(() => !this._syncing && !this.modified), (0, rxjs_1.distinctUntilChanged)());
|
|
40
54
|
}
|
|
55
|
+
get state() {
|
|
56
|
+
return this._state;
|
|
57
|
+
}
|
|
58
|
+
set state(state) {
|
|
59
|
+
// skip if unchanged
|
|
60
|
+
if (this._state === state) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// update state
|
|
64
|
+
this._state = state;
|
|
65
|
+
this._modifiedOn = Date.now();
|
|
66
|
+
// raise change
|
|
67
|
+
this.raiseEvent('changed');
|
|
68
|
+
}
|
|
41
69
|
get modified() {
|
|
42
|
-
|
|
70
|
+
const { _deletedBlocks, initialSlug, _slug, initialPublication, _publication, initialTags, _tags, items } = this;
|
|
71
|
+
return _deletedBlocks.length > 0
|
|
72
|
+
|| initialSlug !== _slug
|
|
73
|
+
|| initialPublication !== _publication
|
|
74
|
+
|| initialTags.symmetricDifference(_tags).size > 0
|
|
75
|
+
|| items.some(item => item.modified);
|
|
76
|
+
}
|
|
77
|
+
get updatedOn() {
|
|
78
|
+
return this._updatedOn;
|
|
79
|
+
}
|
|
80
|
+
get changes() {
|
|
81
|
+
return {
|
|
82
|
+
page: this,
|
|
83
|
+
items: this.items.filter(item => item instanceof components_1.Section
|
|
84
|
+
? item.changes.blocks.length > 0
|
|
85
|
+
: item.changes.fields.length > 0)
|
|
86
|
+
};
|
|
43
87
|
}
|
|
44
88
|
get published() {
|
|
45
89
|
return this.publishedOn !== undefined;
|
|
46
90
|
}
|
|
91
|
+
get type() {
|
|
92
|
+
return this.template.type;
|
|
93
|
+
}
|
|
47
94
|
get syncing() {
|
|
48
95
|
return this._syncing;
|
|
49
96
|
}
|
|
97
|
+
set syncing(syncing) {
|
|
98
|
+
this._syncing = syncing;
|
|
99
|
+
this.raiseEvent('changed');
|
|
100
|
+
}
|
|
101
|
+
repair() {
|
|
102
|
+
// repair all content blocks
|
|
103
|
+
this.blocks.forEach(block => block.repair());
|
|
104
|
+
}
|
|
105
|
+
get url() {
|
|
106
|
+
return this._url;
|
|
107
|
+
}
|
|
108
|
+
get initialSlug() {
|
|
109
|
+
return this._initialSlug;
|
|
110
|
+
}
|
|
50
111
|
get hasSlug() {
|
|
51
112
|
return this.template.variant === 'dynamic';
|
|
52
113
|
}
|
|
114
|
+
set slug(slug) {
|
|
115
|
+
// stop static pages from setting slugs
|
|
116
|
+
if (!this.hasSlug) {
|
|
117
|
+
throw new funnel_core_1.InvalidOperationError('Cannot set slug on static page');
|
|
118
|
+
}
|
|
119
|
+
// or from being unset
|
|
120
|
+
else if (!slug) {
|
|
121
|
+
throw new funnel_core_1.ArgumentError('Slug cannot be unset');
|
|
122
|
+
}
|
|
123
|
+
// ignore if unchanged
|
|
124
|
+
else if (this._slug === slug) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// update slug
|
|
128
|
+
this._slug = slug;
|
|
129
|
+
this._modifiedOn = Date.now();
|
|
130
|
+
// raise change
|
|
131
|
+
this.raiseEvent('modified');
|
|
132
|
+
}
|
|
53
133
|
get slug() {
|
|
54
134
|
return this._slug;
|
|
55
135
|
}
|
|
136
|
+
get initialName() {
|
|
137
|
+
return this._initialName;
|
|
138
|
+
}
|
|
139
|
+
get name() {
|
|
140
|
+
return this._name;
|
|
141
|
+
}
|
|
142
|
+
set name(name) {
|
|
143
|
+
// ignore if unchanged
|
|
144
|
+
if (this._name === name) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// update name
|
|
148
|
+
this._name = name;
|
|
149
|
+
this._modifiedOn = Date.now();
|
|
150
|
+
// raise change
|
|
151
|
+
this.raiseEvent('modified');
|
|
152
|
+
}
|
|
153
|
+
get initialPublication() {
|
|
154
|
+
return this._initialPublication;
|
|
155
|
+
}
|
|
156
|
+
get publication() {
|
|
157
|
+
return this._publication;
|
|
158
|
+
}
|
|
159
|
+
set publication(publication) {
|
|
160
|
+
// ignore if unchanged
|
|
161
|
+
if (this._publication === publication) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
// update name
|
|
165
|
+
this._publication = publication;
|
|
166
|
+
this._modifiedOn = Date.now();
|
|
167
|
+
// raise change
|
|
168
|
+
this.raiseEvent('modified');
|
|
169
|
+
}
|
|
170
|
+
get initialErrors() {
|
|
171
|
+
return this._initialErrors;
|
|
172
|
+
}
|
|
173
|
+
get errors() {
|
|
174
|
+
return {
|
|
175
|
+
page: this,
|
|
176
|
+
items: this.items.filter(item => (!item.activated && item.required)
|
|
177
|
+
|| (item.activated && !item.valid))
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
get valid() {
|
|
181
|
+
return this.errors.items.length === 0;
|
|
182
|
+
}
|
|
183
|
+
get hasErrors() {
|
|
184
|
+
return this.errors.items.length > 0;
|
|
185
|
+
}
|
|
186
|
+
get asRef() {
|
|
187
|
+
const { id, groupId, template, brand, region, language, slug, url, name, tags, state, hasErrors, createdOn, updatedOn, publishedOn } = this;
|
|
188
|
+
return {
|
|
189
|
+
id, groupId, template,
|
|
190
|
+
brand, region, language, slug, url, name, tags: Array.from(tags),
|
|
191
|
+
state, errors: hasErrors, createdOn, updatedOn, publishedOn
|
|
192
|
+
};
|
|
193
|
+
}
|
|
56
194
|
get discover() {
|
|
57
|
-
return
|
|
195
|
+
return this._discover;
|
|
196
|
+
}
|
|
197
|
+
get seo() {
|
|
198
|
+
// get seo (or blow up)
|
|
199
|
+
const seo = this.discover.find(block => block.key === 'seo');
|
|
200
|
+
if (!seo) {
|
|
201
|
+
throw new funnel_core_1.IllegalStateError('Failed to resolve SEO block - should always exist');
|
|
202
|
+
}
|
|
203
|
+
// return seo
|
|
204
|
+
return seo;
|
|
205
|
+
}
|
|
206
|
+
getPreviewBlock() {
|
|
207
|
+
// get preview block identifier
|
|
208
|
+
const previewBlockIdentifier = this.template.preview;
|
|
209
|
+
// bail if no identifier specified
|
|
210
|
+
if (!previewBlockIdentifier) {
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
// otherwise try to get the preview block
|
|
214
|
+
return this.getBlock(previewBlockIdentifier);
|
|
58
215
|
}
|
|
59
216
|
get content() {
|
|
60
217
|
return this._content;
|
|
@@ -63,6 +220,9 @@ class Page {
|
|
|
63
220
|
return this.content
|
|
64
221
|
.flatMap((item) => item instanceof components_1.Section ? item.blocks : item);
|
|
65
222
|
}
|
|
223
|
+
get deleteBlocks() {
|
|
224
|
+
return this._deletedBlocks;
|
|
225
|
+
}
|
|
66
226
|
get firstBlock() {
|
|
67
227
|
// find first block
|
|
68
228
|
for (const item of this.content) {
|
|
@@ -85,7 +245,7 @@ class Page {
|
|
|
85
245
|
return this.content[0];
|
|
86
246
|
}
|
|
87
247
|
get items() {
|
|
88
|
-
return [...this._content];
|
|
248
|
+
return [...this._discover, ...this._content];
|
|
89
249
|
}
|
|
90
250
|
get assets() {
|
|
91
251
|
return this._assets;
|
|
@@ -102,6 +262,11 @@ class Page {
|
|
|
102
262
|
get tags() {
|
|
103
263
|
return this._tags;
|
|
104
264
|
}
|
|
265
|
+
hydrateStores(references) {
|
|
266
|
+
this._assets.push(...references.assets);
|
|
267
|
+
this._pages.push(...references.pages);
|
|
268
|
+
this._collections.push(...references.collections);
|
|
269
|
+
}
|
|
105
270
|
getItem(identifier) {
|
|
106
271
|
// skip if there's no identifier
|
|
107
272
|
if (!identifier) {
|
|
@@ -135,40 +300,152 @@ class Page {
|
|
|
135
300
|
return (_b = (_a = this.getItem(identifier)) !== null && _a !== void 0 ? _a : this.firstBlock) !== null && _b !== void 0 ? _b : this.firstItem;
|
|
136
301
|
}
|
|
137
302
|
deleteBlock(area, key) {
|
|
138
|
-
|
|
303
|
+
// get parent
|
|
304
|
+
let parent;
|
|
305
|
+
switch (area) {
|
|
306
|
+
case 'discover':
|
|
307
|
+
parent = this._discover;
|
|
308
|
+
break;
|
|
309
|
+
case 'content':
|
|
310
|
+
parent = this._content;
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
// skip if item isn't in parent
|
|
314
|
+
const blockIndex = parent.findIndex(item => item.key === key);
|
|
315
|
+
if (!blockIndex) {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
// remove item
|
|
319
|
+
const [deletedBlock] = parent.splice(blockIndex, 1);
|
|
320
|
+
this._modifiedOn = Date.now();
|
|
321
|
+
// track deletion of top-level blocks
|
|
322
|
+
if (deletedBlock instanceof components_1.Block) {
|
|
323
|
+
console.debug('Removing deleted block', deletedBlock);
|
|
324
|
+
this._deletedBlocks.push(deletedBlock);
|
|
325
|
+
}
|
|
326
|
+
// raise change
|
|
327
|
+
this.raiseEvent('modified');
|
|
328
|
+
// indicate success
|
|
329
|
+
return true;
|
|
139
330
|
}
|
|
140
331
|
getAsset(assetId) {
|
|
141
332
|
return this._assets.find((asset) => asset.value.id === assetId);
|
|
142
333
|
}
|
|
143
334
|
getAssetScope(range) {
|
|
144
|
-
|
|
335
|
+
switch (range) {
|
|
336
|
+
case 'global':
|
|
337
|
+
return funnel_core_1.Schema.AssetScope.global;
|
|
338
|
+
case 'type':
|
|
339
|
+
return new funnel_core_1.Schema.PageTypeAssetScope(this.type);
|
|
340
|
+
case 'instance':
|
|
341
|
+
return new funnel_core_1.Schema.PageInstanceAssetScope(this.groupId);
|
|
342
|
+
}
|
|
145
343
|
}
|
|
146
344
|
getSearchScope() {
|
|
147
|
-
|
|
345
|
+
return {
|
|
346
|
+
target: 'page',
|
|
347
|
+
type: this.type,
|
|
348
|
+
groupId: this.groupId
|
|
349
|
+
};
|
|
148
350
|
}
|
|
149
351
|
addAsset(asset) {
|
|
150
|
-
|
|
352
|
+
// replace asset if it exists
|
|
353
|
+
const { _assets } = this;
|
|
354
|
+
const { id } = asset.value;
|
|
355
|
+
const assetIndex = _assets.findIndex(asset => asset.value.id === id);
|
|
356
|
+
if (assetIndex >= 0) {
|
|
357
|
+
_assets[assetIndex] = asset;
|
|
358
|
+
}
|
|
359
|
+
// or add asset
|
|
360
|
+
else {
|
|
361
|
+
_assets.push(asset);
|
|
362
|
+
}
|
|
363
|
+
// raise event
|
|
364
|
+
this.raiseEvent('changed');
|
|
151
365
|
}
|
|
152
366
|
removeAsset(assetId) {
|
|
153
|
-
|
|
367
|
+
// skip if asset isn't there
|
|
368
|
+
const { _assets } = this;
|
|
369
|
+
const assetIndex = _assets.findIndex(asset => asset.value.id === assetId);
|
|
370
|
+
if (assetIndex < 0) {
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
// remove asset
|
|
374
|
+
_assets.splice(assetIndex, 1);
|
|
375
|
+
// raise event
|
|
376
|
+
this.raiseEvent('changed');
|
|
377
|
+
// indicate success
|
|
378
|
+
return true;
|
|
154
379
|
}
|
|
155
380
|
getCollection(collectionId) {
|
|
156
|
-
|
|
381
|
+
return this._collections.find(collection => collection.id === collectionId);
|
|
157
382
|
}
|
|
158
383
|
addCollection(collection) {
|
|
159
|
-
|
|
384
|
+
// replace collection if it exists
|
|
385
|
+
const { _collections } = this;
|
|
386
|
+
const collectionId = collection.id;
|
|
387
|
+
const collectionIndex = _collections.findIndex(collection => collection.id === collectionId);
|
|
388
|
+
if (collectionIndex >= 0) {
|
|
389
|
+
_collections[collectionIndex] = collection;
|
|
390
|
+
}
|
|
391
|
+
// or add collection
|
|
392
|
+
else {
|
|
393
|
+
_collections.push(collection);
|
|
394
|
+
}
|
|
395
|
+
// raise event
|
|
396
|
+
this.raiseEvent('changed');
|
|
160
397
|
}
|
|
161
398
|
removeCollection(collectionId) {
|
|
162
|
-
|
|
399
|
+
// skip if collection isn't there
|
|
400
|
+
const { _collections } = this;
|
|
401
|
+
const collectionIndex = _collections.findIndex(collection => collection.id === collectionId);
|
|
402
|
+
if (collectionIndex < 0) {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
// remove collection
|
|
406
|
+
const [collection] = _collections.splice(collectionIndex, 1);
|
|
407
|
+
// raise event
|
|
408
|
+
this.raiseEvent('changed');
|
|
409
|
+
// indicate success
|
|
410
|
+
return true;
|
|
163
411
|
}
|
|
164
412
|
getPageRef(pageId) {
|
|
165
|
-
return pageId && pageId !== funnel_core_1.Schema.Page.Id.draft
|
|
413
|
+
return pageId && pageId !== funnel_core_1.Schema.Page.Id.draft
|
|
414
|
+
? this._pages.find((ref) => ref.id === pageId)
|
|
415
|
+
: undefined;
|
|
166
416
|
}
|
|
167
417
|
addPageRef(ref) {
|
|
168
|
-
throw
|
|
418
|
+
// throw if page is a draft
|
|
419
|
+
if (ref.id === funnel_core_1.Schema.Page.Id.draft) {
|
|
420
|
+
throw new funnel_core_1.InvalidOperationError('Cannot add draft Page as reference');
|
|
421
|
+
}
|
|
422
|
+
// replace ref if it exists
|
|
423
|
+
const { _pages } = this;
|
|
424
|
+
const pageId = ref.id;
|
|
425
|
+
const refIndex = _pages.findIndex(ref => ref.id === pageId);
|
|
426
|
+
if (refIndex >= 0) {
|
|
427
|
+
_pages[refIndex] = ref;
|
|
428
|
+
}
|
|
429
|
+
// or add ref
|
|
430
|
+
else {
|
|
431
|
+
_pages.push(ref);
|
|
432
|
+
}
|
|
433
|
+
// raise event
|
|
434
|
+
this.raiseEvent('changed');
|
|
169
435
|
}
|
|
170
436
|
removePageRef(pageId) {
|
|
171
|
-
|
|
437
|
+
// skip if file isn't there
|
|
438
|
+
const { _pages } = this;
|
|
439
|
+
const refIndex = _pages.findIndex(ref => ref.id === pageId);
|
|
440
|
+
if (refIndex < 0) {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
// remove file
|
|
444
|
+
_pages.splice(refIndex, 1);
|
|
445
|
+
// raise event
|
|
446
|
+
this.raiseEvent('changed');
|
|
447
|
+
// indicate success
|
|
448
|
+
return true;
|
|
172
449
|
}
|
|
173
450
|
addTag(tag) {
|
|
174
451
|
throw new Error('Method not implemented.');
|
|
@@ -176,5 +453,41 @@ class Page {
|
|
|
176
453
|
removeTag(tag) {
|
|
177
454
|
throw new Error('Method not implemented.');
|
|
178
455
|
}
|
|
456
|
+
onSaveStart() {
|
|
457
|
+
this._savingOn = Date.now();
|
|
458
|
+
}
|
|
459
|
+
onSaveComplete(updatedOn) {
|
|
460
|
+
// update fundamentals
|
|
461
|
+
this._updatedOn = updatedOn;
|
|
462
|
+
this._state = 'draft';
|
|
463
|
+
// reset to values to match save
|
|
464
|
+
const { _modifiedOn, _savingOn } = this;
|
|
465
|
+
if (_savingOn && (!_modifiedOn || _savingOn >= _modifiedOn)) {
|
|
466
|
+
// sync data
|
|
467
|
+
this._initialErrors = !this.valid;
|
|
468
|
+
this._initialSlug = this._slug;
|
|
469
|
+
this._initialName = this._name;
|
|
470
|
+
this._initialTags = new Set(this._tags);
|
|
471
|
+
this._initialPublication = this._publication;
|
|
472
|
+
this._deletedBlocks = [];
|
|
473
|
+
}
|
|
474
|
+
// clear saving flag
|
|
475
|
+
delete this._savingOn;
|
|
476
|
+
}
|
|
477
|
+
getBlock(identifier) {
|
|
478
|
+
// try to find item
|
|
479
|
+
const item = this.getItem(identifier);
|
|
480
|
+
// make sure it is a block
|
|
481
|
+
if (item instanceof components_1.Block) {
|
|
482
|
+
return item;
|
|
483
|
+
}
|
|
484
|
+
// otherwise undefined
|
|
485
|
+
else {
|
|
486
|
+
return undefined;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
raiseEvent(type) {
|
|
490
|
+
this.eventBus.publish(components_1.IPage.Event.create({ type, page: this }));
|
|
491
|
+
}
|
|
179
492
|
}
|
|
180
493
|
exports.Page = Page;
|
|
@@ -14,4 +14,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Collection"), exports);
|
|
17
18
|
__exportStar(require("./Page"), exports);
|
package/dist/core/index.d.ts
CHANGED
package/dist/core/index.js
CHANGED
|
@@ -15,5 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./api"), exports);
|
|
18
|
+
__exportStar(require("./bridge"), exports);
|
|
19
|
+
__exportStar(require("./contentful"), exports);
|
|
18
20
|
__exportStar(require("./domain"), exports);
|
|
19
21
|
__exportStar(require("./repository"), exports);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EditorAppSDK } from '@contentful/app-sdk';
|
|
2
|
+
import { IAssetRepository } from '@nascentdigital/funnel-editor/components';
|
|
3
|
+
export declare class AssetRepository implements IAssetRepository {
|
|
4
|
+
readonly sdk: EditorAppSDK;
|
|
5
|
+
constructor(sdk: EditorAppSDK);
|
|
6
|
+
search(args: IAssetRepository.Search.Args): Promise<IAssetRepository.Search.Result>;
|
|
7
|
+
get(args: IAssetRepository.Get.Args): Promise<IAssetRepository.Get.Result>;
|
|
8
|
+
update(args: IAssetRepository.Update.Args): Promise<IAssetRepository.Update.Result>;
|
|
9
|
+
uploadFile(args: IAssetRepository.UploadFile.Args): Promise<IAssetRepository.UploadFile.Result>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AssetRepository = void 0;
|
|
4
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
|
+
const contentful_1 = require("../contentful");
|
|
6
|
+
// class
|
|
7
|
+
class AssetRepository {
|
|
8
|
+
constructor(sdk) {
|
|
9
|
+
this.sdk = sdk;
|
|
10
|
+
}
|
|
11
|
+
async search(args) {
|
|
12
|
+
// TODO: implement fetching assets
|
|
13
|
+
return {
|
|
14
|
+
items: [],
|
|
15
|
+
page: 1,
|
|
16
|
+
pageCount: 0,
|
|
17
|
+
totalItemCount: 0
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async get(args) {
|
|
21
|
+
throw new funnel_core_1.NotImplementedError();
|
|
22
|
+
}
|
|
23
|
+
async update(args) {
|
|
24
|
+
throw new funnel_core_1.NotImplementedError();
|
|
25
|
+
}
|
|
26
|
+
async uploadFile(args) {
|
|
27
|
+
// upload asset
|
|
28
|
+
const asset = await contentful_1.ContentfulAsset.upload(args, this.sdk);
|
|
29
|
+
// return result
|
|
30
|
+
return contentful_1.ContentfulAsset.serialize(asset, this.sdk.locales.default);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.AssetRepository = AssetRepository;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EventBus, Schema } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { Collection } from '../domain';
|
|
3
|
+
export declare namespace CollectionSerializer {
|
|
4
|
+
type DeserializeCollectionArgs = {
|
|
5
|
+
flattenedCollection: Schema.Collection.FlattenedData;
|
|
6
|
+
eventBus: EventBus;
|
|
7
|
+
};
|
|
8
|
+
function deserializeCollection({ flattenedCollection, eventBus }: DeserializeCollectionArgs): Collection;
|
|
9
|
+
}
|