@nascentdigital/funnel-editor-contentful 4.6.7 → 5.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Editor.d.ts +6 -1
- package/dist/Editor.js +17 -1
- package/dist/EditorApp.js +11 -9
- package/dist/EditorPageRouter.d.ts +1 -0
- package/dist/EditorPageRouter.js +40 -0
- package/dist/EntryEditor.js +43 -1
- package/dist/EntrySidebar.js +18 -1
- package/dist/asset/index.d.ts +1 -0
- package/dist/{page/hooks → asset}/index.js +1 -1
- package/dist/asset/repository/AssetRepository.d.ts +10 -0
- package/dist/asset/repository/AssetRepository.js +33 -0
- package/dist/asset/repository/index.d.ts +1 -0
- package/dist/{core/api → asset/repository}/index.js +1 -3
- package/dist/collection/controller/ContentfulCollectionController.d.ts +41 -0
- package/dist/collection/controller/ContentfulCollectionController.js +278 -0
- package/dist/collection/controller/ContentfulCollectionControllerContainer.d.ts +5 -0
- package/dist/collection/controller/ContentfulCollectionControllerContainer.js +28 -0
- package/dist/collection/controller/index.d.ts +3 -0
- package/dist/collection/controller/index.js +19 -0
- package/dist/collection/controller/useContentfulCollectionController.d.ts +2 -0
- package/dist/collection/controller/useContentfulCollectionController.js +8 -0
- package/dist/collection/domain/Collection.d.ts +108 -0
- package/dist/collection/domain/Collection.js +386 -0
- package/dist/collection/domain/index.d.ts +1 -0
- package/dist/collection/domain/index.js +17 -0
- package/dist/collection/index.d.ts +3 -0
- package/dist/collection/index.js +19 -0
- package/dist/collection/repository/CollectionRepository.d.ts +49 -0
- package/dist/collection/repository/CollectionRepository.js +210 -0
- package/dist/collection/repository/index.d.ts +1 -0
- package/dist/collection/repository/index.js +17 -0
- package/dist/collection/screens/CollectionEditor.d.ts +1 -0
- package/dist/collection/screens/CollectionEditor.js +59 -0
- package/dist/collection/screens/index.d.ts +1 -0
- package/dist/collection/screens/index.js +17 -0
- 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/client/ContentfulClientContainer.d.ts +8 -0
- package/dist/core/client/ContentfulClientContainer.js +43 -0
- package/dist/core/client/ContentfulClientContext.d.ts +8 -0
- package/dist/core/client/ContentfulClientContext.js +8 -0
- package/dist/core/client/index.d.ts +3 -0
- package/dist/core/client/index.js +19 -0
- package/dist/core/client/useContentfulClient.d.ts +4 -0
- package/dist/core/client/useContentfulClient.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 +89 -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/index.d.ts +3 -2
- package/dist/core/index.js +3 -2
- 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 +3 -3
- package/dist/core/repository/PageSerializer.js +18 -14
- 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 +4 -1
- package/dist/core/repository/index.js +4 -1
- package/dist/explore/components/Header.d.ts +26 -0
- package/dist/explore/components/Header.js +31 -0
- package/dist/explore/components/index.d.ts +1 -0
- package/dist/explore/components/index.js +17 -0
- package/dist/explore/index.d.ts +1 -0
- package/dist/explore/index.js +17 -0
- package/dist/explore/screens/Dashboard.d.ts +1 -0
- package/dist/explore/screens/Dashboard.js +22 -0
- package/dist/explore/screens/PageExplorer.d.ts +1 -0
- package/dist/explore/screens/PageExplorer.js +9 -0
- package/dist/explore/screens/SiteExplorer.d.ts +1 -0
- package/dist/explore/screens/SiteExplorer.js +24 -0
- package/dist/explore/screens/index.d.ts +3 -0
- package/dist/explore/screens/index.js +19 -0
- package/dist/page/{hooks/PageController.d.ts → controller/ContentfulPageController.d.ts} +17 -6
- package/dist/page/controller/ContentfulPageController.js +277 -0
- package/dist/page/controller/ContentfulPageControllerContainer.d.ts +5 -0
- package/dist/page/controller/ContentfulPageControllerContainer.js +28 -0
- package/dist/page/controller/index.d.ts +3 -0
- package/dist/page/controller/index.js +19 -0
- package/dist/page/controller/useContentfulPageController.d.ts +2 -0
- package/dist/page/controller/useContentfulPageController.js +8 -0
- package/dist/{core → page}/domain/Page.d.ts +71 -10
- package/dist/page/domain/Page.js +631 -0
- package/dist/page/index.d.ts +3 -0
- package/dist/page/index.js +3 -0
- package/dist/page/repository/PageRepository.d.ts +45 -0
- package/dist/page/repository/PageRepository.js +224 -0
- package/dist/page/repository/index.d.ts +1 -0
- package/dist/page/repository/index.js +17 -0
- package/dist/page/screens/PageEditor.js +29 -15
- package/package.json +10 -4
- package/dist/core/api/EditorApiClient.d.ts +0 -7
- package/dist/core/api/EditorApiClient.js +0 -29
- package/dist/core/api/EditorApiContainer.d.ts +0 -5
- package/dist/core/api/EditorApiContainer.js +0 -16
- package/dist/core/api/EditorApiContext.d.ts +0 -7
- package/dist/core/api/EditorApiContext.js +0 -6
- package/dist/core/api/index.d.ts +0 -3
- package/dist/core/api/useEditorApi.d.ts +0 -2
- package/dist/core/api/useEditorApi.js +0 -12
- package/dist/core/domain/Page.js +0 -180
- 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
- /package/dist/{core → page}/domain/index.d.ts +0 -0
- /package/dist/{core → page}/domain/index.js +0 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.PageRepository = void 0;
|
|
15
|
+
const contentful_1 = require("@nascentdigital/funnel-cms/contentful");
|
|
16
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
17
|
+
const components_1 = require("@nascentdigital/funnel-editor/components");
|
|
18
|
+
const domain_1 = require("../domain");
|
|
19
|
+
// repository
|
|
20
|
+
class PageRepository {
|
|
21
|
+
constructor(args) {
|
|
22
|
+
// initialize instance
|
|
23
|
+
this.sdk = args.sdk;
|
|
24
|
+
this.contentfulClient = args.contentfulClient;
|
|
25
|
+
}
|
|
26
|
+
async search(args) {
|
|
27
|
+
throw new funnel_core_1.NotImplementedError();
|
|
28
|
+
}
|
|
29
|
+
async getOverview({ region }) {
|
|
30
|
+
// get overviews
|
|
31
|
+
const overview = await this.contentfulClient.pages.getOverview({
|
|
32
|
+
brand: funnel_core_1.AppConfig.brand(),
|
|
33
|
+
region,
|
|
34
|
+
version: 'draft'
|
|
35
|
+
});
|
|
36
|
+
// enrich with templates and flip to array
|
|
37
|
+
const templates = Object.values(funnel_core_1.Schema.Site.current().regions[region]);
|
|
38
|
+
return templates.map(template => {
|
|
39
|
+
var _a, _b;
|
|
40
|
+
// extract static page overview
|
|
41
|
+
const { type } = template;
|
|
42
|
+
if (template.variant === 'static') {
|
|
43
|
+
return new components_1.StaticPageOverview(Object.assign({ template,
|
|
44
|
+
type, refs: {} }, ((_a = overview.static.find(page => page.type === type)) !== null && _a !== void 0 ? _a : {})));
|
|
45
|
+
}
|
|
46
|
+
// or dynamic one
|
|
47
|
+
else {
|
|
48
|
+
return new components_1.DynamicPageOverview(Object.assign({ template,
|
|
49
|
+
type, count: 0 }, ((_b = overview.dynamic.find(page => page.type === type)) !== null && _b !== void 0 ? _b : {})));
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async create(args) {
|
|
54
|
+
throw new funnel_core_1.NotImplementedError();
|
|
55
|
+
}
|
|
56
|
+
async createLanguage(args) {
|
|
57
|
+
throw new funnel_core_1.NotImplementedError();
|
|
58
|
+
}
|
|
59
|
+
async load(sys) {
|
|
60
|
+
// throw if entry isn't a page (it should be in this case)
|
|
61
|
+
const { sdk, contentfulClient } = this;
|
|
62
|
+
const { entry } = sdk;
|
|
63
|
+
sys = sys !== null && sys !== void 0 ? sys : entry.getSys();
|
|
64
|
+
const { id: entryId, contentType: { sys: { id: entryType } } } = sys;
|
|
65
|
+
if (entryType !== contentful_1.ContentfulPageData.contentType) {
|
|
66
|
+
throw new funnel_core_1.ArgumentError(`Cannot load Page from entry that isn't of "${contentful_1.ContentfulPageData.contentType}" type`);
|
|
67
|
+
}
|
|
68
|
+
// throw if page doesn't have a group id
|
|
69
|
+
const pageId = entryId;
|
|
70
|
+
const type = entry.fields.type.getValue();
|
|
71
|
+
const groupId = entry.fields.groupId.getValue();
|
|
72
|
+
const brand = entry.fields.brand.getValue();
|
|
73
|
+
const region = entry.fields.region.getValue();
|
|
74
|
+
const language = funnel_core_1.Language.tryParse(entry.fields.language.getValue());
|
|
75
|
+
if (!groupId || !type || !brand || !region || !language) {
|
|
76
|
+
throw new funnel_core_1.ArgumentError(`Page "${pageId}" is not configured (missing required fields)`);
|
|
77
|
+
}
|
|
78
|
+
// fetch remote data (throw if not found)
|
|
79
|
+
const _a = await contentfulClient.pages.getGroup({ groupId, type, brand, region, language, version: 'draft' }), _b = _a.group, { instances: pages } = _b, group = __rest(_b, ["instances"]), { page: pageResult } = _a;
|
|
80
|
+
if (!pageResult) {
|
|
81
|
+
throw new funnel_core_1.NotFoundError(`Unable to resolve Page with id "${pageId}"`);
|
|
82
|
+
}
|
|
83
|
+
console.debug('[PageRepository/load] loaded page data:', { group, pages, pageResult });
|
|
84
|
+
// get entry data + remote references
|
|
85
|
+
const { data: _remote } = pageResult, references = __rest(pageResult, ["data"]);
|
|
86
|
+
const data = entryToPageData(entry);
|
|
87
|
+
// return page model from data
|
|
88
|
+
const page = domain_1.Page.fromSchemaData(Object.assign({ data }, references));
|
|
89
|
+
return {
|
|
90
|
+
pageSummary: new components_1.PageSummary(Object.assign(Object.assign({ template: page.template }, group), { pages })),
|
|
91
|
+
page,
|
|
92
|
+
sys
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async save(page) {
|
|
96
|
+
// serialize page updates (or skip if there are no changes)
|
|
97
|
+
const savables = [];
|
|
98
|
+
const updateArgs = domain_1.Page.toUpdates(page, savables);
|
|
99
|
+
if (updateArgs.updates.length === 0) {
|
|
100
|
+
return page;
|
|
101
|
+
}
|
|
102
|
+
// start all updates
|
|
103
|
+
page.onSaveStart();
|
|
104
|
+
savables.forEach(savable => savable.onSaveStart());
|
|
105
|
+
// update entry if page is local
|
|
106
|
+
let updatedOn;
|
|
107
|
+
const { sdk } = this;
|
|
108
|
+
const { entry } = sdk;
|
|
109
|
+
const { id: entryId, contentType: { sys: { id: entryType } } } = entry.getSys();
|
|
110
|
+
if (entryType === contentful_1.ContentfulPageData.contentType && page.id === entryId) {
|
|
111
|
+
console.debug('[PageRepository/save] saving local entry', { entry, page });
|
|
112
|
+
// save updates to entry
|
|
113
|
+
await saveEntryUpdates({ entry, updates: updateArgs.updates });
|
|
114
|
+
// capture updated timestamp
|
|
115
|
+
updatedOn = new Date(entry.getSys().updatedAt).getTime();
|
|
116
|
+
}
|
|
117
|
+
// or update remotely
|
|
118
|
+
else {
|
|
119
|
+
console.debug('[PageRepository/save] saving remote entry', page);
|
|
120
|
+
// push updates remotely
|
|
121
|
+
const result = await this.contentfulClient.pages.update(updateArgs);
|
|
122
|
+
// capture update timestamp
|
|
123
|
+
updatedOn = result.updatedOn;
|
|
124
|
+
// swap to new page (if update returned new data)
|
|
125
|
+
if (result.page) {
|
|
126
|
+
console.debug('[PageRepository/save] switching to new page data', result.page);
|
|
127
|
+
page = domain_1.Page.fromSchemaData(result.page);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
console.debug('[PageRepository/save] finalizing save');
|
|
131
|
+
// complete updates
|
|
132
|
+
savables.forEach(savable => savable.onSaveComplete());
|
|
133
|
+
page.onSaveComplete(updatedOn);
|
|
134
|
+
console.debug('[PageRepository/save] save complete', page);
|
|
135
|
+
// return page
|
|
136
|
+
return page;
|
|
137
|
+
}
|
|
138
|
+
async sync({ page, sys }) {
|
|
139
|
+
// skip if entity version and updated sys are same
|
|
140
|
+
const { sdk } = this;
|
|
141
|
+
const { entry } = sdk;
|
|
142
|
+
const entrySys = entry.getSys();
|
|
143
|
+
if (sys.version === entrySys.version) {
|
|
144
|
+
console.debug('[ContentfulPageRepository/sync] ignoring unchanged entity');
|
|
145
|
+
return { page, sys };
|
|
146
|
+
}
|
|
147
|
+
// force reload if entry references changed
|
|
148
|
+
const entryReferences = entry.fields.references.getValue();
|
|
149
|
+
const entryRefs = new Set(entryReferences.map(link => `${link.sys.linkType}.${link.sys.id}`));
|
|
150
|
+
const { references: pageReferences } = page;
|
|
151
|
+
const pageRefs = new Set(pageReferences.map(link => `${link.sys.linkType}.${link.sys.id}`));
|
|
152
|
+
if (!pageRefs.isSupersetOf(entryRefs)) {
|
|
153
|
+
console.debug('[ContentfulPageRepository/sync] references changed - triggering reload');
|
|
154
|
+
return this.load(sys);
|
|
155
|
+
}
|
|
156
|
+
console.debug('[ContentfulPageRepository/sync] reusing stable references - merging entity');
|
|
157
|
+
// or load page data, but use old references in store
|
|
158
|
+
const data = entryToPageData(entry);
|
|
159
|
+
const references = {
|
|
160
|
+
files: page.assets.reduce((files, file) => {
|
|
161
|
+
files[file.value.id] = file;
|
|
162
|
+
return files;
|
|
163
|
+
}, {}),
|
|
164
|
+
collections: page.collections.reduce((collections, collection) => {
|
|
165
|
+
collections[collection.id] = collection;
|
|
166
|
+
return collections;
|
|
167
|
+
}, {}),
|
|
168
|
+
pages: page.pages.reduce((pages, page) => {
|
|
169
|
+
pages[page.id] = page;
|
|
170
|
+
return pages;
|
|
171
|
+
}, {})
|
|
172
|
+
};
|
|
173
|
+
// create new page (use existing sys)
|
|
174
|
+
return {
|
|
175
|
+
page: domain_1.Page.fromSchemaData(Object.assign({ data }, references)),
|
|
176
|
+
sys
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
async unpublish(page) {
|
|
180
|
+
throw new funnel_core_1.NotImplementedError();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.PageRepository = PageRepository;
|
|
184
|
+
// helpers
|
|
185
|
+
function entryToPageData(entry) {
|
|
186
|
+
// throw if it's not a page
|
|
187
|
+
const entryType = entry.getSys().contentType.sys.id;
|
|
188
|
+
if (entryType !== contentful_1.ContentfulPageData.contentType) {
|
|
189
|
+
throw new funnel_core_1.ArgumentError(`Expected entry to be "${contentful_1.ContentfulPageData.contentType}", but found "${entryType}"`);
|
|
190
|
+
}
|
|
191
|
+
// serialize entry (this is the latest data)
|
|
192
|
+
const entryData = contentful_1.ContentfulData.fromEntryData(entry);
|
|
193
|
+
return contentful_1.ContentfulPageData.deserialize(entryData);
|
|
194
|
+
}
|
|
195
|
+
async function saveEntryUpdates({ entry, updates }) {
|
|
196
|
+
var _a;
|
|
197
|
+
// serialize entry (this is the latest data)
|
|
198
|
+
const pageData = entryToPageData(entry);
|
|
199
|
+
// create model and apply updates
|
|
200
|
+
const pageModel = new funnel_core_1.Schema.PageModel(pageData);
|
|
201
|
+
pageModel.update(updates);
|
|
202
|
+
pageModel.sync();
|
|
203
|
+
// resolve references
|
|
204
|
+
const references = contentful_1.ContentfulData.findReferences([pageData.discover, pageData.preview, pageData.content]);
|
|
205
|
+
// update fields
|
|
206
|
+
const { fields } = entry;
|
|
207
|
+
await Promise.all([
|
|
208
|
+
// required updates
|
|
209
|
+
fields.name.setValue(pageData.name),
|
|
210
|
+
fields.slug.setValue(pageData.slug),
|
|
211
|
+
fields.url.setValue(pageData.url),
|
|
212
|
+
fields.state.setValue(pageData.state),
|
|
213
|
+
fields.errors.setValue(pageData.errors),
|
|
214
|
+
fields.references.setValue(references),
|
|
215
|
+
// TODO: save only fields that changed
|
|
216
|
+
// conditional updates
|
|
217
|
+
fields.tags.setValue((_a = pageData.tags) !== null && _a !== void 0 ? _a : []),
|
|
218
|
+
fields.preview.setValue(pageData.preview),
|
|
219
|
+
fields.discover.setValue(pageData.discover),
|
|
220
|
+
fields.content.setValue(pageData.content)
|
|
221
|
+
]);
|
|
222
|
+
// save entry
|
|
223
|
+
await entry.save();
|
|
224
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './PageRepository';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./PageRepository"), exports);
|
|
@@ -2,34 +2,48 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PageEditor = PageEditor;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
6
|
const components_1 = require("@nascentdigital/funnel-editor/components");
|
|
6
7
|
const react_1 = require("react");
|
|
7
8
|
const core_1 = require("../../core");
|
|
8
|
-
const
|
|
9
|
+
const controller_1 = require("../controller");
|
|
9
10
|
// component
|
|
10
11
|
function PageEditor() {
|
|
11
12
|
// hooks
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
return {
|
|
16
|
-
controller,
|
|
17
|
-
controllerContext: { controller }
|
|
18
|
-
};
|
|
19
|
-
}, [editorApi]);
|
|
13
|
+
const splash = (0, components_1.useSplash)();
|
|
14
|
+
const bridge = (0, core_1.useAppBridge)();
|
|
15
|
+
const controller = (0, controller_1.useContentfulPageController)();
|
|
20
16
|
const { page } = controller;
|
|
21
17
|
const pageContext = (0, react_1.useMemo)(() => ({ page }), [page]);
|
|
22
18
|
const [itemId, setItemId] = (0, react_1.useState)();
|
|
23
19
|
const selectedItem = (0, react_1.useMemo)(() => page === null || page === void 0 ? void 0 : page.coerceItem(itemId), [page, itemId]);
|
|
24
|
-
|
|
25
|
-
(0, components_1.usePageController)(controller);
|
|
20
|
+
const { ready } = controller;
|
|
26
21
|
// load
|
|
27
22
|
(0, react_1.useEffect)(() => {
|
|
28
|
-
controller.load().catch(
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
controller.load().catch(e => {
|
|
24
|
+
// transform error
|
|
25
|
+
const error = funnel_core_1.IsometricErrorUtils.coerceError(e);
|
|
26
|
+
// TODO: come up with an appropriate message
|
|
27
|
+
const message = error.message;
|
|
28
|
+
// show error via splash
|
|
29
|
+
splash.showError({ message, onRetry: () => controller.reload() });
|
|
30
|
+
});
|
|
31
|
+
}, [splash, controller]);
|
|
32
|
+
// dismiss splash when ready
|
|
33
|
+
(0, react_1.useEffect)(() => {
|
|
34
|
+
if (ready) {
|
|
35
|
+
splash.dismiss();
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
splash.showLoading('Fetching content');
|
|
39
|
+
}
|
|
40
|
+
}, [splash, ready]);
|
|
41
|
+
const onSelectItem = (item) => {
|
|
42
|
+
setItemId(item.identifier);
|
|
43
|
+
bridge.sendMessage(core_1.AppBlockNavMessage.create(item.identifier));
|
|
44
|
+
};
|
|
31
45
|
// render
|
|
32
|
-
return ((0, jsx_runtime_1.jsx)(components_1.
|
|
46
|
+
return ((0, jsx_runtime_1.jsx)(components_1.PageContext.Provider, { value: pageContext, children: (0, jsx_runtime_1.jsx)(components_1.AssetStoreContext.Provider, { value: page, children: (0, jsx_runtime_1.jsx)(components_1.CollectionStoreContext.Provider, { value: page, children: (0, jsx_runtime_1.jsx)(components_1.PageRefStoreContext.Provider, { value: page, children: (0, jsx_runtime_1.jsx)("div", { className: "bg-background flex h-dvh w-dvw flex-col", children: (0, jsx_runtime_1.jsx)("div", { className: "relative flex-1", children: (0, jsx_runtime_1.jsxs)("div", { className: "absolute inset-0 flex", children: [(0, jsx_runtime_1.jsx)("section", { className: "scrollbar-thin w-[220px] shrink-0 overflow-y-scroll lg:w-[240px] xl:w-[280px]", tabIndex: -1, children: (0, jsx_runtime_1.jsx)(components_1.PageNav, { selectedItem: selectedItem, onSelectItem: onSelectItem }) }), (0, jsx_runtime_1.jsx)("section", { className: "mx-auto h-full max-h-full max-w-[1000px] flex-1", children: renderContent({ controller, page, selectedItem, onSelectItem }) })] }) }) }) }) }) }) }));
|
|
33
47
|
}
|
|
34
48
|
function renderContent({ controller, page, selectedItem, onSelectItem }) {
|
|
35
49
|
// show loader if not ready
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nascentdigital/funnel-editor-contentful",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "restricted"
|
|
@@ -37,9 +37,15 @@
|
|
|
37
37
|
"react-dom": "^19"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@contentful/app-sdk": "^4
|
|
40
|
+
"@contentful/app-sdk": "^4",
|
|
41
41
|
"@contentful/react-apps-toolkit": "^2.0.1",
|
|
42
|
-
"@nascentdigital/funnel-
|
|
42
|
+
"@nascentdigital/funnel-cms": "^5.0.2",
|
|
43
|
+
"@nascentdigital/funnel-editor": "^5.0.2",
|
|
44
|
+
"react-dom": "^19",
|
|
45
|
+
"react-router": "^8",
|
|
46
|
+
"react-router-dom": "^7",
|
|
47
|
+
"rxjs": "^7",
|
|
48
|
+
"uuid": "^11"
|
|
43
49
|
},
|
|
44
50
|
"devDependencies": {
|
|
45
51
|
"@types/node": "^22",
|
|
@@ -53,5 +59,5 @@
|
|
|
53
59
|
"ts-jest": "^29",
|
|
54
60
|
"type-fest": "^4"
|
|
55
61
|
},
|
|
56
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "24d9690cf813052f6561c3ccef11c7cf69ad7f7c"
|
|
57
63
|
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { EditorAppSDK } from '@contentful/app-sdk';
|
|
2
|
-
import { PageClient } from '@nascentdigital/funnel-cms';
|
|
3
|
-
export declare class EditorApiClient {
|
|
4
|
-
readonly sdk: EditorAppSDK;
|
|
5
|
-
constructor(sdk: EditorAppSDK);
|
|
6
|
-
currentPageGroup(): Promise<PageClient.GetGroup.Result>;
|
|
7
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EditorApiClient = void 0;
|
|
4
|
-
// class
|
|
5
|
-
class EditorApiClient {
|
|
6
|
-
constructor(sdk) {
|
|
7
|
-
this.sdk = sdk;
|
|
8
|
-
}
|
|
9
|
-
async currentPageGroup() {
|
|
10
|
-
const entry = this.sdk.entry;
|
|
11
|
-
const { type, content } = entry.fields;
|
|
12
|
-
return {
|
|
13
|
-
group: {},
|
|
14
|
-
page: {
|
|
15
|
-
data: {
|
|
16
|
-
id: entry.getSys().id,
|
|
17
|
-
type: 'home', // type.getValue(),
|
|
18
|
-
region: 'ca',
|
|
19
|
-
language: 'en',
|
|
20
|
-
content: content.getValue(),
|
|
21
|
-
},
|
|
22
|
-
files: {},
|
|
23
|
-
pages: {},
|
|
24
|
-
collections: {},
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
exports.EditorApiClient = EditorApiClient;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EditorApiContainer = EditorApiContainer;
|
|
4
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const react_apps_toolkit_1 = require("@contentful/react-apps-toolkit");
|
|
6
|
-
const react_1 = require("react");
|
|
7
|
-
const EditorApiClient_1 = require("./EditorApiClient");
|
|
8
|
-
const EditorApiContext_1 = require("./EditorApiContext");
|
|
9
|
-
// container
|
|
10
|
-
function EditorApiContainer({ children }) {
|
|
11
|
-
// bind context
|
|
12
|
-
const sdk = (0, react_apps_toolkit_1.useSDK)();
|
|
13
|
-
const context = (0, react_1.useMemo)(() => ({ client: new EditorApiClient_1.EditorApiClient(sdk) }), [sdk]);
|
|
14
|
-
// render
|
|
15
|
-
return ((0, jsx_runtime_1.jsx)(EditorApiContext_1.EditorApiContext.Provider, { value: context, children: children }));
|
|
16
|
-
}
|
package/dist/core/api/index.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useEditorApi = useEditorApi;
|
|
4
|
-
const react_1 = require("react");
|
|
5
|
-
const EditorApiContext_1 = require("./EditorApiContext");
|
|
6
|
-
// hook
|
|
7
|
-
function useEditorApi() {
|
|
8
|
-
// bind context
|
|
9
|
-
const { client } = (0, react_1.useContext)(EditorApiContext_1.EditorApiContext);
|
|
10
|
-
// return client
|
|
11
|
-
return client;
|
|
12
|
-
}
|
package/dist/core/domain/Page.js
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Page = void 0;
|
|
4
|
-
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
|
-
const components_1 = require("@nascentdigital/funnel-editor/components");
|
|
6
|
-
const rxjs_1 = require("rxjs");
|
|
7
|
-
// class
|
|
8
|
-
class Page {
|
|
9
|
-
constructor(args) {
|
|
10
|
-
var _a, _b, _c;
|
|
11
|
-
// initialize instance variables
|
|
12
|
-
this.id = args.id;
|
|
13
|
-
this.template = args.template;
|
|
14
|
-
this.eventBus = args.eventBus;
|
|
15
|
-
this.groupId = args.groupId;
|
|
16
|
-
this.brand = args.brand;
|
|
17
|
-
this.language = args.language;
|
|
18
|
-
this.region = args.region;
|
|
19
|
-
this.url = args.url;
|
|
20
|
-
this.publishedOn = args.publishedOn;
|
|
21
|
-
this.createdOn = args.createdOn;
|
|
22
|
-
this.updatedOn = args.updatedOn;
|
|
23
|
-
this.settings = new components_1.PageSettings(this);
|
|
24
|
-
this._content = args.content;
|
|
25
|
-
this._initialSlug = this._slug = args.slug;
|
|
26
|
-
this._assets = (_a = args.files) !== null && _a !== void 0 ? _a : [];
|
|
27
|
-
this._pages = (_b = args.pages) !== null && _b !== void 0 ? _b : [];
|
|
28
|
-
this._collections = (_c = args.collections) !== null && _c !== void 0 ? _c : [];
|
|
29
|
-
this._initialTags = new Set(args.tags);
|
|
30
|
-
this._tags = new Set(args.tags);
|
|
31
|
-
this._syncing = false;
|
|
32
|
-
// bind content
|
|
33
|
-
this._content.forEach((item) => item.bind({ parent: this, area: 'content' }));
|
|
34
|
-
}
|
|
35
|
-
get events$() {
|
|
36
|
-
return this.eventBus.events$;
|
|
37
|
-
}
|
|
38
|
-
get stable$() {
|
|
39
|
-
return this.eventBus.events$.pipe((0, rxjs_1.map)(() => !this._syncing && !this.modified), (0, rxjs_1.distinctUntilChanged)());
|
|
40
|
-
}
|
|
41
|
-
get modified() {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
get published() {
|
|
45
|
-
return this.publishedOn !== undefined;
|
|
46
|
-
}
|
|
47
|
-
get syncing() {
|
|
48
|
-
return this._syncing;
|
|
49
|
-
}
|
|
50
|
-
get hasSlug() {
|
|
51
|
-
return this.template.variant === 'dynamic';
|
|
52
|
-
}
|
|
53
|
-
get slug() {
|
|
54
|
-
return this._slug;
|
|
55
|
-
}
|
|
56
|
-
get discover() {
|
|
57
|
-
return [];
|
|
58
|
-
}
|
|
59
|
-
get content() {
|
|
60
|
-
return this._content;
|
|
61
|
-
}
|
|
62
|
-
get blocks() {
|
|
63
|
-
return this.content
|
|
64
|
-
.flatMap((item) => item instanceof components_1.Section ? item.blocks : item);
|
|
65
|
-
}
|
|
66
|
-
get firstBlock() {
|
|
67
|
-
// find first block
|
|
68
|
-
for (const item of this.content) {
|
|
69
|
-
// return item if it matches
|
|
70
|
-
if (item instanceof components_1.Block) {
|
|
71
|
-
return item;
|
|
72
|
-
}
|
|
73
|
-
// search deeply into sections
|
|
74
|
-
else {
|
|
75
|
-
const { blocks } = item;
|
|
76
|
-
if (blocks.length > 0) {
|
|
77
|
-
return blocks[0];
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
// or return undefined
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
get firstItem() {
|
|
85
|
-
return this.content[0];
|
|
86
|
-
}
|
|
87
|
-
get items() {
|
|
88
|
-
return [...this._content];
|
|
89
|
-
}
|
|
90
|
-
get assets() {
|
|
91
|
-
return this._assets;
|
|
92
|
-
}
|
|
93
|
-
get collections() {
|
|
94
|
-
return this._collections;
|
|
95
|
-
}
|
|
96
|
-
get initialTags() {
|
|
97
|
-
return this._initialTags;
|
|
98
|
-
}
|
|
99
|
-
get tagGroups() {
|
|
100
|
-
return this.template.tags;
|
|
101
|
-
}
|
|
102
|
-
get tags() {
|
|
103
|
-
return this._tags;
|
|
104
|
-
}
|
|
105
|
-
getItem(identifier) {
|
|
106
|
-
// skip if there's no identifier
|
|
107
|
-
if (!identifier) {
|
|
108
|
-
return undefined;
|
|
109
|
-
}
|
|
110
|
-
// or return settings
|
|
111
|
-
else if (identifier === components_1.PageSettings.id) {
|
|
112
|
-
return this.settings;
|
|
113
|
-
}
|
|
114
|
-
// search content for item
|
|
115
|
-
for (const item of this.items) {
|
|
116
|
-
// return item if it matches
|
|
117
|
-
if (item.identifier === identifier) {
|
|
118
|
-
return item;
|
|
119
|
-
}
|
|
120
|
-
// search deeply into sections
|
|
121
|
-
if (item instanceof components_1.Section) {
|
|
122
|
-
for (const block of item.blocks) {
|
|
123
|
-
// return block if it matches
|
|
124
|
-
if (block.identifier === identifier) {
|
|
125
|
-
return block;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
// or return undefined
|
|
131
|
-
return undefined;
|
|
132
|
-
}
|
|
133
|
-
coerceItem(identifier) {
|
|
134
|
-
var _a, _b;
|
|
135
|
-
return (_b = (_a = this.getItem(identifier)) !== null && _a !== void 0 ? _a : this.firstBlock) !== null && _b !== void 0 ? _b : this.firstItem;
|
|
136
|
-
}
|
|
137
|
-
deleteBlock(area, key) {
|
|
138
|
-
throw new Error('Method not implemented.');
|
|
139
|
-
}
|
|
140
|
-
getAsset(assetId) {
|
|
141
|
-
return this._assets.find((asset) => asset.value.id === assetId);
|
|
142
|
-
}
|
|
143
|
-
getAssetScope(range) {
|
|
144
|
-
throw new Error('Method not implemented.');
|
|
145
|
-
}
|
|
146
|
-
getSearchScope() {
|
|
147
|
-
throw new Error('Method not implemented.');
|
|
148
|
-
}
|
|
149
|
-
addAsset(asset) {
|
|
150
|
-
throw new Error('Method not implemented.');
|
|
151
|
-
}
|
|
152
|
-
removeAsset(assetId) {
|
|
153
|
-
throw new Error('Method not implemented.');
|
|
154
|
-
}
|
|
155
|
-
getCollection(collectionId) {
|
|
156
|
-
throw new Error('Method not implemented.');
|
|
157
|
-
}
|
|
158
|
-
addCollection(collection) {
|
|
159
|
-
throw new Error('Method not implemented.');
|
|
160
|
-
}
|
|
161
|
-
removeCollection(collectionId) {
|
|
162
|
-
throw new Error('Method not implemented.');
|
|
163
|
-
}
|
|
164
|
-
getPageRef(pageId) {
|
|
165
|
-
return pageId && pageId !== funnel_core_1.Schema.Page.Id.draft ? this._pages.find((ref) => ref.id === pageId) : undefined;
|
|
166
|
-
}
|
|
167
|
-
addPageRef(ref) {
|
|
168
|
-
throw new Error('Method not implemented.');
|
|
169
|
-
}
|
|
170
|
-
removePageRef(pageId) {
|
|
171
|
-
throw new Error('Method not implemented.');
|
|
172
|
-
}
|
|
173
|
-
addTag(tag) {
|
|
174
|
-
throw new Error('Method not implemented.');
|
|
175
|
-
}
|
|
176
|
-
removeTag(tag) {
|
|
177
|
-
throw new Error('Method not implemented.');
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
exports.Page = Page;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { EventBus } from '@nascentdigital/funnel-core';
|
|
2
|
-
import { EditorApiClient } from '../api';
|
|
3
|
-
export declare class PageRepository {
|
|
4
|
-
readonly editorApi: EditorApiClient;
|
|
5
|
-
constructor(editorApi: EditorApiClient);
|
|
6
|
-
load({ eventBus }: PageRepository.LoadArgs): Promise<import("..").Page | undefined>;
|
|
7
|
-
}
|
|
8
|
-
export declare namespace PageRepository {
|
|
9
|
-
type LoadArgs = {
|
|
10
|
-
eventBus: EventBus;
|
|
11
|
-
};
|
|
12
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PageRepository = void 0;
|
|
4
|
-
const PageSerializer_1 = require("./PageSerializer");
|
|
5
|
-
// class
|
|
6
|
-
class PageRepository {
|
|
7
|
-
constructor(editorApi) {
|
|
8
|
-
this.editorApi = editorApi;
|
|
9
|
-
}
|
|
10
|
-
async load({ eventBus }) {
|
|
11
|
-
// fetch current page
|
|
12
|
-
const { page: flattenedPage } = await this.editorApi.currentPageGroup();
|
|
13
|
-
if (!flattenedPage) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
// deserialize page
|
|
17
|
-
return PageSerializer_1.PageSerializer.deserializePage({
|
|
18
|
-
eventBus,
|
|
19
|
-
flattenedPage
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
exports.PageRepository = PageRepository;
|