@nascentdigital/funnel-editor 5.0.1 → 5.0.3
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/components.d.ts +3 -1
- package/dist/components.js +3 -1
- package/dist/core/client/EditorApiClient.js +1 -1
- package/dist/core/components/fields/OptInField.js +42 -2
- package/dist/core/components/fields/asset/AssetEditor.d.ts +1 -2
- package/dist/core/components/fields/asset/AssetEditor.js +18 -6
- package/dist/core/components/fields/asset/AssetUploader.d.ts +1 -2
- package/dist/core/components/fields/asset/AssetUploader.js +18 -6
- package/dist/core/components/fields/collection/CollectionEditor.d.ts +2 -1
- package/dist/core/components/fields/collection/CollectionEditor.js +17 -3
- package/dist/core/components/fields/embed/EmbeddedVideoEditor.d.ts +2 -2
- package/dist/core/components/fields/embed/EmbeddedVideoEditor.js +17 -5
- package/dist/core/components/fields/factories/AssetFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/AssetFactory.js +18 -13
- package/dist/core/components/fields/factories/CollectionFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/CollectionFactory.js +20 -13
- package/dist/core/components/fields/factories/EmbeddedVideoFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/EmbeddedVideoFactory.js +17 -8
- package/dist/core/components/fields/factories/FieldValueFactory.d.ts +7 -5
- package/dist/core/components/fields/factories/FieldValueFactory.js +49 -12
- package/dist/core/components/fields/factories/LinkFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/LinkFactory.js +17 -8
- package/dist/core/components/fields/factories/MediaFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/MediaFactory.js +105 -149
- package/dist/core/components/fields/factories/ObjectFactory.d.ts +3 -2
- package/dist/core/components/fields/factories/ObjectFactory.js +16 -2
- package/dist/core/components/fields/factories/TextFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/TextFactory.js +16 -10
- package/dist/core/components/fields/link/LinkEditor.d.ts +2 -2
- package/dist/core/components/fields/link/LinkEditor.js +18 -6
- package/dist/core/components/fields/media/MediaEditor.d.ts +2 -3
- package/dist/core/components/fields/media/MediaEditor.js +40 -11
- package/dist/core/components/fields/media/index.d.ts +0 -1
- package/dist/core/components/fields/media/index.js +0 -1
- package/dist/core/components/fields/object/ObjectEditor.d.ts +2 -1
- package/dist/core/components/fields/object/ObjectEditor.js +15 -1
- package/dist/core/components/fields/page/PagePicker.js +1 -1
- package/dist/core/components/interaction/Popup.d.ts +11 -7
- package/dist/core/components/interaction/Popup.js +8 -6
- package/dist/core/components/interaction/QuickInput.d.ts +2 -4
- package/dist/core/components/interaction/QuickInput.js +6 -2
- package/dist/core/components/interaction/menu/Menu.d.ts +8 -19
- package/dist/core/components/interaction/menu/Menu.js +26 -60
- package/dist/core/components/interaction/menu/useMenuController.d.ts +4 -2
- package/dist/core/components/interaction/menu/useMenuController.js +4 -1
- package/dist/core/domain/CollectionFieldProxy.js +1 -1
- package/dist/core/domain/Collections.js +0 -2
- package/dist/core/domain/ICollection.d.ts +1 -0
- package/dist/core/domain/IPage.d.ts +6 -1
- package/dist/core/domain/IPage.js +30 -0
- package/dist/core/domain/PageOverview.d.ts +6 -0
- package/dist/core/domain/PageOverview.js +17 -0
- package/dist/core/domain/PageSummary.d.ts +9 -7
- package/dist/core/domain/PageSummary.js +12 -16
- package/dist/core/domain/Pages.js +1 -2
- package/dist/core/domain/Site.js +0 -2
- package/dist/core/hooks/useCollectionRepository.d.ts +1 -1
- package/dist/core/hooks/useCollections.js +4 -0
- package/dist/core/hooks/usePageRepository.d.ts +1 -1
- package/dist/core/hooks/useSite.js +4 -0
- package/dist/core/repository/CollectionRepository.d.ts +2 -2
- package/dist/core/repository/ICollectionRepository.d.ts +2 -3
- package/dist/core/repository/IPageRepository.d.ts +0 -1
- package/dist/core/repository/PageRepository.js +1 -1
- package/dist/core/repository/SerializeCollectionUpdate.d.ts +5 -5
- package/dist/core/repository/SerializePageUpdate.d.ts +7 -8
- package/dist/core/splash/SplashContainer.d.ts +4 -2
- package/dist/core/splash/SplashContainer.js +3 -3
- package/dist/explore/screens/PageExplorer.js +2 -1
- package/dist/page/components/BlockEditor.d.ts +3 -1
- package/dist/page/components/BlockEditor.js +4 -3
- package/dist/page/components/config/BlockConfigurationProvider.d.ts +10 -2
- package/dist/page/components/config/BlockConfigurationProvider.js +11 -3
- package/dist/page/components/config/BlockPreview.d.ts +4 -2
- package/dist/page/components/config/BlockPreview.js +5 -11
- package/dist/page/components/config/index.d.ts +1 -0
- package/dist/page/components/config/index.js +1 -0
- package/dist/page/components/config/useBlockConfiguration$.d.ts +3 -0
- package/dist/page/components/config/useBlockConfiguration$.js +22 -0
- package/dist/page/components/panels/BlockConfigPanel.js +3 -3
- package/dist/page/hooks/PageController.js +2 -1
- package/dist/styles/index.css +34 -9
- package/dist/styles/tailwind.js +1 -0
- package/package.json +3 -3
- package/dist/core/components/fields/media/MediaPicker.d.ts +0 -15
- package/dist/core/components/fields/media/MediaPicker.js +0 -251
|
@@ -1,10 +1,30 @@
|
|
|
1
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
|
+
};
|
|
2
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
14
|
exports.IPage = void 0;
|
|
4
15
|
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
16
|
// extension
|
|
6
17
|
var IPage;
|
|
7
18
|
(function (IPage) {
|
|
19
|
+
let Ref;
|
|
20
|
+
(function (Ref) {
|
|
21
|
+
function fromData(_a) {
|
|
22
|
+
var { tags } = _a, data = __rest(_a, ["tags"]);
|
|
23
|
+
const template = funnel_core_1.Schema.Site.getPage(data.type, data.region);
|
|
24
|
+
return Object.assign({ template, tags: template.parseTags(tags !== null && tags !== void 0 ? tags : []) }, data);
|
|
25
|
+
}
|
|
26
|
+
Ref.fromData = fromData;
|
|
27
|
+
})(Ref = IPage.Ref || (IPage.Ref = {}));
|
|
8
28
|
let Event;
|
|
9
29
|
(function (Event) {
|
|
10
30
|
// methods
|
|
@@ -17,4 +37,14 @@ var IPage;
|
|
|
17
37
|
}
|
|
18
38
|
Event.create = create;
|
|
19
39
|
})(Event = IPage.Event || (IPage.Event = {}));
|
|
40
|
+
// helpers
|
|
41
|
+
function getPreviewUrl(path) {
|
|
42
|
+
// get base url
|
|
43
|
+
const url = new URL('/api/preview', window.location.href);
|
|
44
|
+
// apply args
|
|
45
|
+
url.searchParams.set('redirect', path);
|
|
46
|
+
// return url
|
|
47
|
+
return url;
|
|
48
|
+
}
|
|
49
|
+
IPage.getPreviewUrl = getPreviewUrl;
|
|
20
50
|
})(IPage || (exports.IPage = IPage = {}));
|
|
@@ -17,14 +17,20 @@ export declare class StaticPageOverview extends PageOverviewBase {
|
|
|
17
17
|
readonly refs: Readonly<Record<Language, Schema.Page.Data.AsLink>>;
|
|
18
18
|
readonly languages: ReadonlyArray<Language>;
|
|
19
19
|
constructor({ refs, ...args }: StaticPageOverview.ConstructorArgs);
|
|
20
|
+
get pages(): Schema.Page.Data.AsLink<Schema.Page<Schema.Page.Content, string>, string>[];
|
|
20
21
|
get isEmpty(): boolean;
|
|
21
22
|
hasLanguage(language: Language): boolean;
|
|
23
|
+
findPage({ region, language }: StaticPageOverview.FindPageArgs): Schema.Page.Data.AsLink | undefined;
|
|
22
24
|
getClosestPageRef(language: Language, fallback?: Language): IPage.Ref | undefined;
|
|
23
25
|
}
|
|
24
26
|
export declare namespace StaticPageOverview {
|
|
25
27
|
type ConstructorArgs = Omit<PageOverviewBase.ConstructorArgs, 'variant'> & {
|
|
26
28
|
refs: Record<Language, Schema.Page.Data.AsLink>;
|
|
27
29
|
};
|
|
30
|
+
type FindPageArgs = {
|
|
31
|
+
region: string;
|
|
32
|
+
language?: Language;
|
|
33
|
+
};
|
|
28
34
|
}
|
|
29
35
|
export declare class DynamicPageOverview extends PageOverviewBase {
|
|
30
36
|
readonly count: number;
|
|
@@ -32,12 +32,29 @@ class StaticPageOverview extends PageOverviewBase {
|
|
|
32
32
|
this.refs = refs;
|
|
33
33
|
this.languages = Object.keys(refs).map(funnel_core_1.Language.parse);
|
|
34
34
|
}
|
|
35
|
+
get pages() {
|
|
36
|
+
return Object.values(this.refs);
|
|
37
|
+
}
|
|
35
38
|
get isEmpty() {
|
|
36
39
|
return this.languages.length === 0;
|
|
37
40
|
}
|
|
38
41
|
hasLanguage(language) {
|
|
39
42
|
return this.languages.includes(language);
|
|
40
43
|
}
|
|
44
|
+
findPage({ region, language }) {
|
|
45
|
+
var _a;
|
|
46
|
+
// narrow down to region
|
|
47
|
+
const pages = this.pages.filter(page => page.region === region);
|
|
48
|
+
// return exact match (if any) if a language is provided
|
|
49
|
+
if (language) {
|
|
50
|
+
return pages.find(page => page.language === language);
|
|
51
|
+
}
|
|
52
|
+
// or pick the best match
|
|
53
|
+
else {
|
|
54
|
+
const { defaultLanguage } = funnel_core_1.AppConfig.brandConfig().regionalization.regions[region];
|
|
55
|
+
return (_a = pages.find(page => page.language === defaultLanguage)) !== null && _a !== void 0 ? _a : pages[0];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
41
58
|
getClosestPageRef(language, fallback) {
|
|
42
59
|
var _a, _b;
|
|
43
60
|
const { template, languages, refs } = this;
|
|
@@ -4,7 +4,6 @@ export declare class PageSummary {
|
|
|
4
4
|
readonly template: Schema.Page;
|
|
5
5
|
readonly brand: string;
|
|
6
6
|
readonly groupId: Schema.Page.GroupId;
|
|
7
|
-
readonly region: string;
|
|
8
7
|
readonly slug?: string;
|
|
9
8
|
readonly pages: ReadonlyArray<PageSummary.PageRef>;
|
|
10
9
|
readonly status: PageSummary.Status;
|
|
@@ -12,10 +11,10 @@ export declare class PageSummary {
|
|
|
12
11
|
get type(): Schema.Page.Type;
|
|
13
12
|
get variant(): Schema.Page.Variant;
|
|
14
13
|
get hasPages(): boolean;
|
|
15
|
-
hasLanguage(language: Language): boolean;
|
|
16
|
-
getPage(language: Language): PageSummary.PageRef | undefined;
|
|
17
|
-
getClosestPageRef(
|
|
18
|
-
isInGroup({ template
|
|
14
|
+
hasLanguage(region: string, language: Language): boolean;
|
|
15
|
+
getPage(region: string, language: Language): PageSummary.PageRef | undefined;
|
|
16
|
+
getClosestPageRef({ region, language, fallbackLanguage }: PageSummary.GetClosestPageRefArgs): IPage.Ref;
|
|
17
|
+
isInGroup({ template }: PageSummary.IsInGroupArgs): boolean;
|
|
19
18
|
}
|
|
20
19
|
export declare namespace PageSummary {
|
|
21
20
|
type Status = 'draft' | 'ready' | 'live' | 'unpublished' | 'changed' | 'empty';
|
|
@@ -23,13 +22,16 @@ export declare namespace PageSummary {
|
|
|
23
22
|
template: Schema.Page;
|
|
24
23
|
brand: string;
|
|
25
24
|
groupId: Schema.Page.GroupId;
|
|
26
|
-
region: string;
|
|
27
25
|
slug?: string;
|
|
28
26
|
pages: PageSummary.PageRef[];
|
|
29
27
|
};
|
|
30
28
|
type PageRef = Schema.Page.Data.AsGroup.Instance & Pick<Schema.Page.Data.AsLink, 'state' | 'errors' | 'createdOn' | 'updatedOn' | 'publishedOn'>;
|
|
29
|
+
type GetClosestPageRefArgs = {
|
|
30
|
+
region: string;
|
|
31
|
+
language: Language;
|
|
32
|
+
fallbackLanguage?: Language;
|
|
33
|
+
};
|
|
31
34
|
type IsInGroupArgs = {
|
|
32
35
|
template: Schema.Page;
|
|
33
|
-
region: string;
|
|
34
36
|
};
|
|
35
37
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PageSummary = void 0;
|
|
4
4
|
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
|
+
const IPage_1 = require("./IPage");
|
|
5
6
|
// class
|
|
6
7
|
class PageSummary {
|
|
7
8
|
constructor(args) {
|
|
@@ -9,7 +10,6 @@ class PageSummary {
|
|
|
9
10
|
this.template = args.template;
|
|
10
11
|
this.brand = args.brand;
|
|
11
12
|
this.groupId = args.groupId;
|
|
12
|
-
this.region = args.region;
|
|
13
13
|
this.slug = args.slug;
|
|
14
14
|
this.pages = args.pages;
|
|
15
15
|
this.status = getStatus(args.pages);
|
|
@@ -23,24 +23,20 @@ class PageSummary {
|
|
|
23
23
|
get hasPages() {
|
|
24
24
|
return this.groupId !== funnel_core_1.Schema.Page.GroupId.empty;
|
|
25
25
|
}
|
|
26
|
-
hasLanguage(language) {
|
|
27
|
-
return this.pages.some(page => page.language === language);
|
|
26
|
+
hasLanguage(region, language) {
|
|
27
|
+
return this.pages.some(page => page.region === region && page.language === language);
|
|
28
28
|
}
|
|
29
|
-
getPage(language) {
|
|
30
|
-
return this.pages.find(page => page.language === language);
|
|
29
|
+
getPage(region, language) {
|
|
30
|
+
return this.pages.find(page => page.region === region && page.language === language);
|
|
31
31
|
}
|
|
32
|
-
getClosestPageRef(language,
|
|
33
|
-
var _a, _b;
|
|
34
|
-
const { template, brand, groupId,
|
|
35
|
-
const ref = (_b = (_a = pages.find(page => page.language === language)) !== null && _a !== void 0 ? _a : (
|
|
36
|
-
return Object.assign(Object.assign({}, ref), { template,
|
|
37
|
-
brand,
|
|
38
|
-
groupId,
|
|
39
|
-
region, tags: template.tags.flatMap(tagGroup => tagGroup.parse(ref.tags)) });
|
|
32
|
+
getClosestPageRef({ region, language, fallbackLanguage }) {
|
|
33
|
+
var _a, _b, _c, _d;
|
|
34
|
+
const { template, brand, groupId, pages } = this;
|
|
35
|
+
const ref = (_d = (_c = (_b = (_a = pages.find(page => page.region === region && page.language === language)) !== null && _a !== void 0 ? _a : (fallbackLanguage && pages.find(page => page.region === region && page.language === fallbackLanguage))) !== null && _b !== void 0 ? _b : pages.find(page => page.language === language)) !== null && _c !== void 0 ? _c : (fallbackLanguage && pages.find(page => page.language === fallbackLanguage))) !== null && _d !== void 0 ? _d : pages[0];
|
|
36
|
+
return IPage_1.IPage.Ref.fromData(Object.assign(Object.assign({}, ref), { groupId, type: template.type, brand }));
|
|
40
37
|
}
|
|
41
|
-
isInGroup({ template
|
|
42
|
-
return this.template.type === template.type
|
|
43
|
-
&& this.region === region;
|
|
38
|
+
isInGroup({ template }) {
|
|
39
|
+
return this.template.type === template.type;
|
|
44
40
|
}
|
|
45
41
|
}
|
|
46
42
|
exports.PageSummary = PageSummary;
|
|
@@ -60,7 +60,6 @@ class Pages {
|
|
|
60
60
|
const { region } = site;
|
|
61
61
|
const { items: pages } = await site.repository.search({
|
|
62
62
|
template,
|
|
63
|
-
region: region.id,
|
|
64
63
|
tags: tags.map(tag => tag.data),
|
|
65
64
|
pagination: 'all'
|
|
66
65
|
});
|
|
@@ -77,7 +76,6 @@ class Pages {
|
|
|
77
76
|
template,
|
|
78
77
|
brand: page.brand,
|
|
79
78
|
groupId: page.groupId,
|
|
80
|
-
region: region.id,
|
|
81
79
|
slug: page.slug,
|
|
82
80
|
pages: []
|
|
83
81
|
};
|
|
@@ -88,6 +86,7 @@ class Pages {
|
|
|
88
86
|
// add page to args
|
|
89
87
|
args.pages.push({
|
|
90
88
|
id: page.id,
|
|
89
|
+
region: page.region,
|
|
91
90
|
language: page.language,
|
|
92
91
|
slug: page.slug,
|
|
93
92
|
name: page.name,
|
package/dist/core/domain/Site.js
CHANGED
|
@@ -21,8 +21,6 @@ class Site {
|
|
|
21
21
|
this._overviews = [];
|
|
22
22
|
this._pages = new Map();
|
|
23
23
|
this._pagesToSync = new Set();
|
|
24
|
-
// start initial loading of data
|
|
25
|
-
this.sync().catch(console.error);
|
|
26
24
|
// listen to app state for page changes
|
|
27
25
|
this._subscription = this.appState.pageEvents$.subscribe(e => this.onPageEvent(e));
|
|
28
26
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ICollectionRepository } from '../repository';
|
|
2
|
-
export declare function useCollectionRepository():
|
|
2
|
+
export declare function useCollectionRepository<TRepository extends ICollectionRepository = ICollectionRepository>(): TRepository;
|
|
3
3
|
export declare const CollectionRepositoryContext: import("react").Context<ICollectionRepository>;
|
|
@@ -17,6 +17,10 @@ function usePossibleCollections() {
|
|
|
17
17
|
if (!collections) {
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
+
// sync if it's not ready
|
|
21
|
+
else if (collections.state === 'uninitialized') {
|
|
22
|
+
collections.sync().catch(console.error);
|
|
23
|
+
}
|
|
20
24
|
// subscribe to changes
|
|
21
25
|
const subscription = collections.events$.subscribe(() => touch());
|
|
22
26
|
// unsubscribe on unmount
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { IPageRepository } from '../repository';
|
|
2
|
-
export declare function usePageRepository():
|
|
2
|
+
export declare function usePageRepository<TRepository extends IPageRepository = IPageRepository>(): TRepository;
|
|
3
3
|
export declare const PageRepositoryContext: import("react").Context<IPageRepository>;
|
|
@@ -17,6 +17,10 @@ function usePossibleSite() {
|
|
|
17
17
|
if (!site) {
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
+
// sync if it's not ready
|
|
21
|
+
else if (site.state === 'uninitialized') {
|
|
22
|
+
site.sync().catch(console.error);
|
|
23
|
+
}
|
|
20
24
|
// subscribe to changes
|
|
21
25
|
const subscription = site.events$.subscribe(() => touch());
|
|
22
26
|
// unsubscribe on unmount
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Schema } from '@nascentdigital/funnel-core';
|
|
2
2
|
import { UpdateCollectionCommand } from '../../api/collections';
|
|
3
3
|
import { EditorApiClient } from '../client';
|
|
4
|
-
import { Collection, CollectionFieldProxy } from '../domain';
|
|
4
|
+
import { Collection, CollectionFieldProxy, ICollection } from '../domain';
|
|
5
5
|
import { CollectionTarget } from './CollectionTarget';
|
|
6
6
|
import { ICollectionRepository } from './ICollectionRepository';
|
|
7
7
|
export declare class CollectionRepository implements ICollectionRepository {
|
|
@@ -26,5 +26,5 @@ export declare class CollectionRepository implements ICollectionRepository {
|
|
|
26
26
|
getItems(args: ICollectionRepository.GetItems.Args): Promise<ICollectionRepository.GetItems.Result>;
|
|
27
27
|
get(args: ICollectionRepository.Get.Args): Promise<ICollectionRepository.Get.Result>;
|
|
28
28
|
update(args: ICollectionRepository.Update.Args): Promise<ICollectionRepository.Update.Result>;
|
|
29
|
-
serializeUpdate(collection: Collection | CollectionFieldProxy, savables:
|
|
29
|
+
serializeUpdate(collection: Collection | CollectionFieldProxy, savables: ICollection.Savable[]): UpdateCollectionCommand.Data;
|
|
30
30
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CollectionClient } from '@nascentdigital/funnel-cms';
|
|
2
|
-
import { EventBus,
|
|
2
|
+
import { EventBus, Schema } from '@nascentdigital/funnel-core';
|
|
3
3
|
import { CollectionFieldProxy, ICollection } from '../domain';
|
|
4
4
|
export interface ICollectionRepository {
|
|
5
5
|
create(args: ICollectionRepository.Create.Args): Promise<ICollectionRepository.Create.Result>;
|
|
@@ -11,10 +11,9 @@ export interface ICollectionRepository {
|
|
|
11
11
|
getItems(args: ICollectionRepository.GetItems.Args): Promise<ICollectionRepository.GetItems.Result>;
|
|
12
12
|
get(args: ICollectionRepository.Get.Args): Promise<ICollectionRepository.Get.Result>;
|
|
13
13
|
update(args: ICollectionRepository.Update.Args): Promise<ICollectionRepository.Update.Result>;
|
|
14
|
-
serializeUpdate(collection: ICollection | CollectionFieldProxy, savables:
|
|
14
|
+
serializeUpdate(collection: ICollection | CollectionFieldProxy, savables: ICollection.Savable[]): ICollectionRepository.SerializeUpdates.Result;
|
|
15
15
|
}
|
|
16
16
|
export declare namespace ICollectionRepository {
|
|
17
|
-
type Savable = FieldModel;
|
|
18
17
|
namespace Create {
|
|
19
18
|
type Args = Omit<CollectionClient.Create.NewArgs, 'brand' | 'type' | 'version'> & {
|
|
20
19
|
template: Schema.Collection;
|
|
@@ -57,7 +57,7 @@ class PageRepository {
|
|
|
57
57
|
const { eventBus, template } = args, query = __rest(args, ["eventBus", "template"]);
|
|
58
58
|
const data = await this.editorApi.createPage(Object.assign(Object.assign({}, query), { type: template.type }));
|
|
59
59
|
// return page
|
|
60
|
-
return PageSerializer_1.PageSerializer.deserializePageWithSummary(Object.assign(Object.assign({
|
|
60
|
+
return PageSerializer_1.PageSerializer.deserializePageWithSummary(Object.assign(Object.assign({}, args), data));
|
|
61
61
|
}
|
|
62
62
|
async save(page) {
|
|
63
63
|
// get page update
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Field, FieldList, FieldModel, ObjectField, Schema } from '@nascentdigital/funnel-core';
|
|
2
|
-
import {
|
|
2
|
+
import { ICollection } from '../domain';
|
|
3
3
|
export declare namespace SerializeCollectionUpdate {
|
|
4
|
-
function serializeFieldsUpdate(updates: Schema.Collection.Update[], fields: ReadonlyArray<FieldModel>, parentPath: ReadonlyArray<string>, savables:
|
|
5
|
-
function serializeObjectFieldUpdate(updates: Schema.Collection.Update[], field: ObjectField, parentPath: ReadonlyArray<string>, savables:
|
|
6
|
-
function serializeFieldUpdate(updates: Schema.Collection.Update[], field: Field, parentPath: ReadonlyArray<string>, savables:
|
|
7
|
-
function serializeListUpdate(updates: Schema.Collection.Update[], list: FieldList, parentPath: ReadonlyArray<string>, savables:
|
|
4
|
+
function serializeFieldsUpdate(updates: Schema.Collection.Update[], fields: ReadonlyArray<FieldModel>, parentPath: ReadonlyArray<string>, savables: ICollection.Savable[]): Schema.Collection.Update[];
|
|
5
|
+
function serializeObjectFieldUpdate(updates: Schema.Collection.Update[], field: ObjectField, parentPath: ReadonlyArray<string>, savables: ICollection.Savable[]): void;
|
|
6
|
+
function serializeFieldUpdate(updates: Schema.Collection.Update[], field: Field, parentPath: ReadonlyArray<string>, savables: ICollection.Savable[]): void;
|
|
7
|
+
function serializeListUpdate(updates: Schema.Collection.Update[], list: FieldList, parentPath: ReadonlyArray<string>, savables: ICollection.Savable[]): void;
|
|
8
8
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { Field, FieldList, FieldModel, ObjectField, Schema } from '@nascentdigital/funnel-core';
|
|
2
|
-
import
|
|
2
|
+
import { Block, IPage, Section } from '../domain';
|
|
3
3
|
export declare namespace SerializePageUpdate {
|
|
4
|
-
|
|
5
|
-
function
|
|
6
|
-
function
|
|
7
|
-
function
|
|
8
|
-
function
|
|
9
|
-
function
|
|
10
|
-
function serializeListUpdate(updates: Schema.Page.Update[], list: FieldList, parentPath: ReadonlyArray<string>, savables: Savable[]): void;
|
|
4
|
+
function serializeSectionUpdate(updates: Schema.Page.Update[], section: Section, parentPath: string, savables: IPage.Savable[]): void;
|
|
5
|
+
function serializeBlockUpdate(updates: Schema.Page.Update[], block: Block, parentPath: string, savables: IPage.Savable[]): void;
|
|
6
|
+
function serializeFieldsUpdate(updates: Schema.Page.Update[], fields: ReadonlyArray<FieldModel>, parentPath: ReadonlyArray<string>, savables: IPage.Savable[]): Schema.Page.Update[];
|
|
7
|
+
function serializeObjectFieldUpdate(updates: Schema.Page.Update[], field: ObjectField, parentPath: ReadonlyArray<string>, savables: IPage.Savable[]): void;
|
|
8
|
+
function serializeFieldUpdate(updates: Schema.Page.Update[], field: Field, parentPath: ReadonlyArray<string>, savables: IPage.Savable[]): void;
|
|
9
|
+
function serializeListUpdate(updates: Schema.Page.Update[], list: FieldList, parentPath: ReadonlyArray<string>, savables: IPage.Savable[]): void;
|
|
11
10
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
|
-
export declare function SplashContainer({ children }: SplashContainer.Props): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function SplashContainer({ message, children }: SplashContainer.Props): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
export declare namespace SplashContainer {
|
|
4
|
-
type Props = PropsWithChildren
|
|
4
|
+
type Props = PropsWithChildren & {
|
|
5
|
+
message?: string;
|
|
6
|
+
};
|
|
5
7
|
}
|
|
@@ -8,16 +8,16 @@ const Splash_1 = require("./Splash");
|
|
|
8
8
|
const SplashContext_1 = require("./SplashContext");
|
|
9
9
|
const SplashService_1 = require("./SplashService");
|
|
10
10
|
// component
|
|
11
|
-
function SplashContainer({ children }) {
|
|
11
|
+
function SplashContainer({ message = 'Signing you in', children }) {
|
|
12
12
|
// bind hooks + memo
|
|
13
13
|
const service = (0, react_2.useMemo)(() => {
|
|
14
14
|
// create service
|
|
15
15
|
const service = new SplashService_1.SplashService();
|
|
16
16
|
// start in a loading state
|
|
17
|
-
service.showLoading(
|
|
17
|
+
service.showLoading(message);
|
|
18
18
|
// return service
|
|
19
19
|
return service;
|
|
20
|
-
}, []);
|
|
20
|
+
}, [message]);
|
|
21
21
|
const [context, setContext] = (0, react_2.useState)(() => ({ service }));
|
|
22
22
|
// update context on event changes
|
|
23
23
|
(0, react_2.useEffect)(() => {
|
|
@@ -72,9 +72,10 @@ function renderPages({ template, groupedPages, onCreatePage, onOpenPage }) {
|
|
|
72
72
|
}
|
|
73
73
|
function groupPages(site, summaries) {
|
|
74
74
|
// group pages
|
|
75
|
+
const { region: { id: region }, defaultLanguage: language } = site;
|
|
75
76
|
const groupedPages = summaries
|
|
76
77
|
// enrich summaries with links
|
|
77
|
-
.map(summary => ({ summary, link: summary.getClosestPageRef(
|
|
78
|
+
.map(summary => ({ summary, link: summary.getClosestPageRef({ region, language }) }))
|
|
78
79
|
// group summaries based on status
|
|
79
80
|
.reduce((groupedPages, linkedSummary) => {
|
|
80
81
|
// bind page to group (drop empty pages groups, which shouldn't occur)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Callback } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
import { Block, PageSettings, Section, SectionBlock } from '../../core';
|
|
3
|
-
export declare function BlockEditor({ className, block, onSelectItem }: BlockEditor.Props): import("react/jsx-runtime").JSX.Element | null;
|
|
4
|
+
export declare function BlockEditor({ className, block, headerActions, onSelectItem }: BlockEditor.Props): import("react/jsx-runtime").JSX.Element | null;
|
|
4
5
|
export declare namespace BlockEditor {
|
|
5
6
|
type Props = {
|
|
6
7
|
className?: string;
|
|
7
8
|
block: Block | SectionBlock;
|
|
9
|
+
headerActions?: ReactNode;
|
|
8
10
|
onSelectItem: Callback<Block | SectionBlock | Section | PageSettings>;
|
|
9
11
|
};
|
|
10
12
|
}
|
|
@@ -10,8 +10,9 @@ const react_1 = require("react");
|
|
|
10
10
|
const core_1 = require("../../core");
|
|
11
11
|
const config_1 = require("./config");
|
|
12
12
|
// component
|
|
13
|
-
function BlockEditor({ className, block, onSelectItem }) {
|
|
13
|
+
function BlockEditor({ className, block, headerActions, onSelectItem }) {
|
|
14
14
|
// bind props + hooks
|
|
15
|
+
const page = (0, core_1.usePage)();
|
|
15
16
|
const dialog = (0, core_1.useDialog)();
|
|
16
17
|
const menu = (0, core_1.useMenuController)(blockMenu);
|
|
17
18
|
const anchorId = (0, react_1.useId)();
|
|
@@ -58,8 +59,8 @@ function BlockEditor({ className, block, onSelectItem }) {
|
|
|
58
59
|
};
|
|
59
60
|
// render editor
|
|
60
61
|
const { messageFields, visualFields, listsFields, extendedFields } = block;
|
|
61
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(className, 'max-h-full h-full flex flex-col'), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center px-l6 pt-l10 pb-l4", children: [(0, jsx_runtime_1.jsx)("h2", { className: "heading-lg flex-1", children: block.name }), (0, jsx_runtime_1.
|
|
62
|
-
|
|
62
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(className, 'max-h-full h-full flex flex-col'), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center px-l6 pt-l10 pb-l4", children: [(0, jsx_runtime_1.jsx)("h2", { className: "heading-lg flex-1", children: (0, jsx_runtime_1.jsx)("a", { href: core_1.IPage.getPreviewUrl(page.url).href, target: `${page.brand}.preview`, children: block.name }) }), (0, jsx_runtime_1.jsxs)("div", { className: "shrink-0 flex items-center gap-l5", children: [headerActions, block.canDelete &&
|
|
63
|
+
(0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(core_1.IconButton, { anchorId: anchorId, className: "DeleteAction text-content-primary hover:text-destructive shrink-0", variant: "util", icon: "EllipsisVertical", onClick: e => menu.open(anchorId) }), (0, jsx_runtime_1.jsx)(core_1.Menu, { controller: menu, onItemClick: onMenuClick })] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 flex flex-col gap-l8 px-l6 pb-l10 overflow-y-scroll scrollbar-thin scroller-fade-top bg-background", tabIndex: -1, children: [messageFields.length > 0 &&
|
|
63
64
|
(0, jsx_runtime_1.jsx)(core_1.FieldsPanel, { title: "Messaging", actions: (0, jsx_runtime_1.jsx)(config_1.BlockConfigButton, { target: "message" }), fields: messageFields }), visualFields.length > 0 &&
|
|
64
65
|
(0, jsx_runtime_1.jsx)(core_1.FieldsPanel, { title: "Visual", actions: (0, jsx_runtime_1.jsx)(config_1.BlockConfigButton, { target: "visual" }), fields: visualFields }), listsFields.length > 0 &&
|
|
65
66
|
(0, jsx_runtime_1.jsx)(core_1.FieldsPanel, { title: "List", actions: (0, jsx_runtime_1.jsx)(config_1.BlockConfigButton, { target: "list" }), fields: listsFields }), extendedFields.length > 0 &&
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { Block, BlockConfiguration, PageSettings, Section, SectionBlock } from '../../../core';
|
|
4
|
+
export declare const BlockConfigurationProvider: import("react").ForwardRefExoticComponent<{
|
|
5
|
+
children?: import("react").ReactNode | undefined;
|
|
6
|
+
} & {
|
|
7
|
+
item?: Block | SectionBlock | Section | PageSettings;
|
|
8
|
+
} & import("react").RefAttributes<BlockConfigurationProvider.Ref>>;
|
|
4
9
|
export declare namespace BlockConfigurationProvider {
|
|
5
10
|
type Props = PropsWithChildren & {
|
|
6
11
|
item?: Block | SectionBlock | Section | PageSettings;
|
|
7
12
|
};
|
|
13
|
+
interface Ref {
|
|
14
|
+
readonly configuration$: Observable<BlockConfiguration | undefined>;
|
|
15
|
+
}
|
|
8
16
|
}
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BlockConfigurationProvider =
|
|
3
|
+
exports.BlockConfigurationProvider = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
|
+
const rxjs_1 = require("rxjs");
|
|
6
7
|
const core_1 = require("../../../core");
|
|
7
8
|
// provider
|
|
8
|
-
function BlockConfigurationProvider({ item, children }) {
|
|
9
|
+
exports.BlockConfigurationProvider = (0, react_1.forwardRef)(function BlockConfigurationProvider({ item, children }, ref) {
|
|
9
10
|
// bind context
|
|
10
11
|
const context = (0, react_1.useMemo)(() => ({
|
|
11
12
|
configuration: item instanceof core_1.Block || item instanceof core_1.SectionBlock
|
|
12
13
|
? item.getConfiguration()
|
|
13
14
|
: undefined
|
|
14
15
|
}), [item]);
|
|
16
|
+
const configuration$ = (0, react_1.useMemo)(() => new rxjs_1.BehaviorSubject(undefined), []);
|
|
17
|
+
// bind interface
|
|
18
|
+
(0, react_1.useImperativeHandle)(ref, () => ({ configuration$ }), [configuration$]);
|
|
19
|
+
// sync configuration when context updates
|
|
20
|
+
(0, react_1.useEffect)(() => {
|
|
21
|
+
configuration$.next(context.configuration);
|
|
22
|
+
}, [configuration$, context]);
|
|
15
23
|
// render
|
|
16
24
|
return ((0, jsx_runtime_1.jsx)(core_1.BlockConfigurationContext.Provider, { value: context, children: children }));
|
|
17
|
-
}
|
|
25
|
+
});
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { BlockLayout } from '@nascentdigital/funnel-core';
|
|
1
2
|
import { BlockConfiguration } from '../../../core';
|
|
2
|
-
export declare function BlockPreview({ className,
|
|
3
|
+
export declare function BlockPreview({ className, scope, layout }: BlockPreview.Props): import("react/jsx-runtime").JSX.Element;
|
|
3
4
|
export declare namespace BlockPreview {
|
|
4
5
|
type Props = {
|
|
5
6
|
className?: string;
|
|
6
|
-
|
|
7
|
+
scope: BlockConfiguration.Scope;
|
|
8
|
+
layout: BlockLayout;
|
|
7
9
|
};
|
|
8
10
|
}
|
|
@@ -10,12 +10,11 @@ const classnames_1 = __importDefault(require("classnames"));
|
|
|
10
10
|
const react_1 = require("motion/react");
|
|
11
11
|
const preview_1 = require("./preview");
|
|
12
12
|
// components
|
|
13
|
-
function BlockPreview({ className,
|
|
13
|
+
function BlockPreview({ className, scope, layout }) {
|
|
14
14
|
// bind props
|
|
15
|
-
const { scope = 'desktop', layout } = configuration !== null && configuration !== void 0 ? configuration : {};
|
|
16
15
|
const tight = scope === 'mobile'
|
|
17
|
-
? layout
|
|
18
|
-
: layout
|
|
16
|
+
? layout.tight.mobile
|
|
17
|
+
: layout.tight.desktop;
|
|
19
18
|
// render
|
|
20
19
|
return ((0, jsx_runtime_1.jsx)(react_1.motion.section, { className: (0, classnames_1.default)(className, 'bg-surface2 rounded-xs interpolate-all', {
|
|
21
20
|
'min-h-[100px]': !layout,
|
|
@@ -24,14 +23,9 @@ function BlockPreview({ className, configuration }) {
|
|
|
24
23
|
'pb-l4': tight === 'above',
|
|
25
24
|
'pt-l4': tight === 'below',
|
|
26
25
|
'py-l4': tight === 'none'
|
|
27
|
-
}), layoutRoot: true, layout: true, children:
|
|
26
|
+
}), layoutRoot: true, layout: true, children: renderLayout({ scope, layout }) }));
|
|
28
27
|
}
|
|
29
|
-
function renderLayout({
|
|
30
|
-
// skip if there's no layout
|
|
31
|
-
const { scope, layout } = configuration;
|
|
32
|
-
if (!layout) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
28
|
+
function renderLayout({ scope, layout }) {
|
|
35
29
|
// render layout based on root type
|
|
36
30
|
const mobile = scope === 'mobile';
|
|
37
31
|
const { root } = layout;
|
|
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./BlockConfigButton"), exports);
|
|
18
18
|
__exportStar(require("./BlockConfigurationProvider"), exports);
|
|
19
19
|
__exportStar(require("./BlockPreview"), exports);
|
|
20
|
+
__exportStar(require("./useBlockConfiguration$"), exports);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useBlockConfiguration$ = useBlockConfiguration$;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
function useBlockConfiguration$(configuration$) {
|
|
6
|
+
// bind hooks
|
|
7
|
+
const [configuration, setConfiguration] = (0, react_1.useState)();
|
|
8
|
+
// sync configuration
|
|
9
|
+
(0, react_1.useEffect)(() => {
|
|
10
|
+
// skip if there's no stream
|
|
11
|
+
if (!configuration$) {
|
|
12
|
+
setConfiguration(undefined);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
// watch stream and sync
|
|
16
|
+
const subscription = configuration$.subscribe(setConfiguration);
|
|
17
|
+
// stop on unmount
|
|
18
|
+
return () => subscription.unsubscribe();
|
|
19
|
+
}, [configuration$]);
|
|
20
|
+
// return configuration
|
|
21
|
+
return configuration;
|
|
22
|
+
}
|
|
@@ -11,12 +11,12 @@ function BlockConfigPanel() {
|
|
|
11
11
|
const id = (0, react_1.useId)();
|
|
12
12
|
const configuration = (0, core_1.useBlockConfiguration)();
|
|
13
13
|
// skip if there's no config (shouldn't happen)
|
|
14
|
-
|
|
14
|
+
const { scope = 'desktop', layout } = configuration !== null && configuration !== void 0 ? configuration : {};
|
|
15
|
+
if (!configuration || !configuration.hasPanels || !layout) {
|
|
15
16
|
return null;
|
|
16
17
|
}
|
|
17
18
|
// render
|
|
18
|
-
|
|
19
|
-
return ((0, jsx_runtime_1.jsx)(core_1.FadeIn, { children: (0, jsx_runtime_1.jsxs)(core_1.Popup.AnchorElement, { tag: "div", anchorId: id, className: "h-full flex flex-col gap-l6 py-l7 bg-surface1 rounded-xxl interpolate-all", children: [(0, jsx_runtime_1.jsx)(core_1.Tabs, { className: "mx-l7", variant: "highlighted", size: "sm", items: blockScopes, selectedItem: scope, onSelect: scope => configuration.scope = scope }), (0, jsx_runtime_1.jsx)(config_1.BlockPreview, { className: "self-center", configuration: configuration }), (0, jsx_runtime_1.jsx)("div", { className: "px-l7", children: (0, jsx_runtime_1.jsx)(config_1.BlockConfigButton, { anchorId: id, target: "block" }) })] }) }, "block.config"));
|
|
19
|
+
return ((0, jsx_runtime_1.jsx)(core_1.FadeIn, { children: (0, jsx_runtime_1.jsxs)(core_1.Popup.AnchorElement, { tag: "div", anchorId: id, className: "h-full flex flex-col gap-l6 py-l7 bg-surface1 rounded-xxl interpolate-all", children: [(0, jsx_runtime_1.jsx)(core_1.Tabs, { className: "mx-l7", variant: "highlighted", size: "sm", items: blockScopes, selectedItem: scope, onSelect: scope => configuration.scope = scope }), (0, jsx_runtime_1.jsx)(config_1.BlockPreview, { className: "self-center", scope: scope, layout: layout }), (0, jsx_runtime_1.jsx)("div", { className: "px-l7", children: (0, jsx_runtime_1.jsx)(config_1.BlockConfigButton, { anchorId: id, target: "block" }) })] }) }, "block.config"));
|
|
20
20
|
}
|
|
21
21
|
// helpers
|
|
22
22
|
const blockScopes = [
|
|
@@ -206,11 +206,12 @@ class PageController {
|
|
|
206
206
|
if (existingSummary
|
|
207
207
|
&& existingSummary.isInGroup(target)
|
|
208
208
|
&& existingSummary.groupId !== funnel_core_1.Schema.Page.GroupId.empty) {
|
|
209
|
-
const { template, slug, language } = target;
|
|
209
|
+
const { template, slug, region, language } = target;
|
|
210
210
|
result = await this.repository.createLanguage({
|
|
211
211
|
template,
|
|
212
212
|
groupId: existingSummary.groupId,
|
|
213
213
|
slug,
|
|
214
|
+
region,
|
|
214
215
|
language,
|
|
215
216
|
eventBus
|
|
216
217
|
});
|