@nascentdigital/funnel-editor-contentful 5.0.2 → 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/EditorApp.js +2 -2
- package/dist/EditorPageRouter.js +3 -9
- package/dist/EditorPageRoutes.d.ts +1 -0
- package/dist/EditorPageRoutes.js +16 -0
- package/dist/EntryEditor.js +1 -1
- package/dist/EntrySidebar.js +26 -5
- package/dist/NotFound.d.ts +1 -0
- package/dist/NotFound.js +18 -0
- package/dist/asset/repository/AssetRepository.d.ts +11 -3
- package/dist/asset/repository/AssetRepository.js +6 -5
- package/dist/collection/domain/Collection.js +2 -1
- package/dist/collection/repository/CollectionRepository.d.ts +3 -3
- package/dist/collection/repository/CollectionRepository.js +19 -6
- package/dist/core/bridge/AppBridge.d.ts +31 -0
- package/dist/core/bridge/AppBridge.js +160 -0
- package/dist/core/bridge/AppBridgeContainer.d.ts +3 -3
- package/dist/core/bridge/AppBridgeContainer.js +8 -44
- package/dist/core/bridge/AppBridgeContext.d.ts +7 -8
- package/dist/core/bridge/AppBridgeContext.js +1 -6
- package/dist/core/bridge/BridgeLifecycleMessage.d.ts +7 -0
- package/dist/core/bridge/BridgeLifecycleMessage.js +12 -0
- package/dist/core/bridge/IAppBridgeMessage.d.ts +16 -0
- package/dist/core/bridge/IAppBridgeMessage.js +12 -0
- package/dist/core/bridge/index.d.ts +2 -1
- package/dist/core/bridge/index.js +2 -1
- package/dist/core/bridge/useAppBridge.d.ts +2 -8
- package/dist/core/bridge/useAppBridge.js +24 -15
- package/dist/core/index.d.ts +0 -2
- package/dist/core/index.js +0 -2
- package/dist/explore/components/header/Header.d.ts +14 -0
- package/dist/explore/components/{Header.js → header/Header.js} +10 -8
- package/dist/explore/components/header/HeaderActions.d.ts +8 -0
- package/dist/explore/components/header/HeaderActions.js +37 -0
- package/dist/explore/components/header/HeaderContainer.d.ts +2 -0
- package/dist/explore/components/header/HeaderContainer.js +15 -0
- package/dist/explore/components/header/HeaderContext.d.ts +7 -0
- package/dist/explore/components/header/HeaderContext.js +6 -0
- package/dist/explore/components/header/HeaderController.d.ts +39 -0
- package/dist/explore/components/header/HeaderController.js +100 -0
- package/dist/explore/components/header/HeaderOptions.d.ts +10 -0
- package/dist/explore/components/header/HeaderOptions.js +26 -0
- package/dist/explore/components/header/index.d.ts +5 -0
- package/dist/{core/contentful → explore/components/header}/index.js +5 -5
- package/dist/explore/components/header/useHeader.d.ts +2 -0
- package/dist/explore/components/header/useHeader.js +30 -0
- package/dist/explore/components/index.d.ts +2 -1
- package/dist/explore/components/index.js +2 -1
- package/dist/explore/components/pages/PagesExplorerLayout.d.ts +4 -0
- package/dist/explore/components/pages/PagesExplorerLayout.js +28 -0
- package/dist/explore/components/pages/index.d.ts +1 -0
- package/dist/{core/repository → explore/components/pages}/index.js +1 -4
- package/dist/explore/index.d.ts +1 -0
- package/dist/explore/index.js +1 -0
- package/dist/explore/screens/Dashboard.d.ts +3 -0
- package/dist/explore/screens/Dashboard.js +34 -1
- package/dist/explore/screens/PageExplorer.d.ts +10 -0
- package/dist/explore/screens/PageExplorer.js +121 -1
- package/dist/explore/screens/PagesExplorer.d.ts +7 -0
- package/dist/explore/screens/PagesExplorer.js +98 -0
- package/dist/explore/screens/index.d.ts +1 -1
- package/dist/explore/screens/index.js +1 -1
- package/dist/page/bridge/BlockChangedMessage.d.ts +25 -0
- package/dist/page/bridge/BlockChangedMessage.js +18 -0
- package/dist/page/bridge/PageBridgeHub.d.ts +8 -0
- package/dist/page/bridge/PageBridgeHub.js +51 -0
- package/dist/page/bridge/index.d.ts +2 -0
- package/dist/page/bridge/index.js +18 -0
- package/dist/page/domain/Page.d.ts +2 -2
- package/dist/page/domain/Page.js +2 -1
- package/dist/page/index.d.ts +1 -0
- package/dist/page/index.js +1 -0
- package/dist/page/repository/PageRepository.d.ts +3 -3
- package/dist/page/repository/PageRepository.js +25 -8
- package/dist/page/screens/PageEditor.js +14 -6
- package/package.json +5 -5
- package/dist/core/bridge/AppMessage.d.ts +0 -19
- package/dist/core/bridge/AppMessage.js +0 -19
- package/dist/core/contentful/Contentful.d.ts +0 -33
- package/dist/core/contentful/Contentful.js +0 -67
- package/dist/core/contentful/ContentfulAsset.d.ts +0 -23
- package/dist/core/contentful/ContentfulAsset.js +0 -89
- package/dist/core/contentful/ContentfulCollection.d.ts +0 -29
- package/dist/core/contentful/ContentfulCollection.js +0 -97
- package/dist/core/contentful/ContentfulPage.d.ts +0 -31
- package/dist/core/contentful/ContentfulPage.js +0 -84
- package/dist/core/contentful/ContentfulRefs.d.ts +0 -16
- package/dist/core/contentful/ContentfulRefs.js +0 -152
- package/dist/core/contentful/index.d.ts +0 -5
- package/dist/core/repository/CollectionSerializer.d.ts +0 -9
- package/dist/core/repository/CollectionSerializer.js +0 -41
- package/dist/core/repository/LocalCollectionRepository.d.ts +0 -27
- package/dist/core/repository/LocalCollectionRepository.js +0 -143
- package/dist/core/repository/LocalPageRepository.d.ts +0 -16
- package/dist/core/repository/LocalPageRepository.js +0 -153
- package/dist/core/repository/PageSerializer.d.ts +0 -9
- package/dist/core/repository/PageSerializer.js +0 -48
- package/dist/core/repository/RemoteCollectionRepository.d.ts +0 -19
- package/dist/core/repository/RemoteCollectionRepository.js +0 -236
- package/dist/core/repository/RemotePageRepository.d.ts +0 -14
- package/dist/core/repository/RemotePageRepository.js +0 -113
- package/dist/core/repository/index.d.ts +0 -4
- package/dist/explore/components/Header.d.ts +0 -26
- package/dist/explore/screens/SiteExplorer.d.ts +0 -1
- package/dist/explore/screens/SiteExplorer.js +0 -24
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.Dashboard = Dashboard;
|
|
4
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
8
|
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
6
9
|
const components_1 = require("@nascentdigital/funnel-editor/components");
|
|
10
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
7
11
|
const react_1 = require("react");
|
|
8
12
|
const react_router_1 = require("react-router");
|
|
9
13
|
const components_2 = require("../components");
|
|
@@ -13,10 +17,39 @@ function Dashboard() {
|
|
|
13
17
|
const brand = funnel_core_1.AppConfig.brandConfig();
|
|
14
18
|
const splash = (0, components_1.useSplash)();
|
|
15
19
|
const { collections } = funnel_core_1.Schema.Site.current();
|
|
20
|
+
const navigate = (0, react_router_1.useNavigate)();
|
|
16
21
|
// dismiss splash
|
|
17
22
|
(0, react_1.useEffect)(() => {
|
|
18
23
|
splash.dismiss();
|
|
19
24
|
}, [splash]);
|
|
20
25
|
// render
|
|
21
|
-
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(components_2.
|
|
26
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "w-dvw h-dvh flex flex-col", children: [(0, jsx_runtime_1.jsx)(components_2.HeaderOptions, { breadcrumbs: ['CMS Dashboard'], backButton: "none", highlightBreadcrumb: true }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('w-full sm:w-4/5 md:w-3/5 max-h-full overflow-y-scroll p-l6', 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 grid-auto-rows auto-cols-fr auto-rows-fr gap-l6'), tabIndex: -1, children: [renderNavCard({
|
|
27
|
+
title: 'My Site\'s Pages',
|
|
28
|
+
caption: 'Your main website.',
|
|
29
|
+
action: 'Explore pages',
|
|
30
|
+
onClick: () => navigate('/pages')
|
|
31
|
+
}), collections.length > 0 && renderNavCard({
|
|
32
|
+
title: 'Collections',
|
|
33
|
+
caption: 'Shared data used by site pages.',
|
|
34
|
+
action: 'Manage collections',
|
|
35
|
+
onClick: () => navigate('/collections')
|
|
36
|
+
}), renderNavCard({
|
|
37
|
+
title: 'Media',
|
|
38
|
+
caption: 'Images, videos and other files.',
|
|
39
|
+
action: 'Manage media',
|
|
40
|
+
onClick: () => navigate('/pages'),
|
|
41
|
+
disabled: true
|
|
42
|
+
})] })] }));
|
|
43
|
+
}
|
|
44
|
+
// extension
|
|
45
|
+
(function (Dashboard) {
|
|
46
|
+
// helper
|
|
47
|
+
function getUrl() {
|
|
48
|
+
return '/';
|
|
49
|
+
}
|
|
50
|
+
Dashboard.getUrl = getUrl;
|
|
51
|
+
})(Dashboard || (exports.Dashboard = Dashboard = {}));
|
|
52
|
+
function renderNavCard({ title, caption, action, disabled = false, onClick = funnel_core_1.Fn.NoOp }) {
|
|
53
|
+
// render
|
|
54
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex flex-col items-center gap-l6 bg-background p-l8', 'border border-solid border-border-l1 rounded-sm'), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex-1 w-full", children: [(0, jsx_runtime_1.jsx)("h2", { className: "heading-md text-content-primary", children: title }), (0, jsx_runtime_1.jsx)("p", { className: "body-sm texts-content-secondary", children: caption })] }), (0, jsx_runtime_1.jsx)(components_1.Button, { variant: "primary", disabled: disabled, onClick: onClick, children: action })] }));
|
|
22
55
|
}
|
|
@@ -1 +1,11 @@
|
|
|
1
|
+
import { Schema } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { PagesExplorerLayout } from '../components';
|
|
3
|
+
import { PagesExplorer } from './PagesExplorer';
|
|
1
4
|
export declare function PageExplorer(): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare namespace PageExplorer {
|
|
6
|
+
type Params = PagesExplorerLayout.Params | 'pageType';
|
|
7
|
+
type GetUrlArgs = PagesExplorer.GetUrlArgs & {
|
|
8
|
+
pageType: Schema.Page.Type;
|
|
9
|
+
};
|
|
10
|
+
function getUrl({ pageType, ...pagesArgs }: GetUrlArgs): string;
|
|
11
|
+
}
|
|
@@ -1,9 +1,129 @@
|
|
|
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.PageExplorer = PageExplorer;
|
|
4
15
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
16
|
+
const components_1 = require("@nascentdigital/funnel-editor/components");
|
|
17
|
+
const react_1 = require("react");
|
|
18
|
+
const react_router_1 = require("react-router");
|
|
19
|
+
const components_2 = require("../components");
|
|
20
|
+
const PagesExplorer_1 = require("./PagesExplorer");
|
|
5
21
|
// screen
|
|
6
22
|
function PageExplorer() {
|
|
23
|
+
// bind hooks
|
|
24
|
+
const params = (0, react_router_1.useParams)();
|
|
25
|
+
const pageType = params.pageType;
|
|
26
|
+
const navigate = (0, react_router_1.useNavigate)();
|
|
27
|
+
const splash = (0, components_1.useSplash)();
|
|
28
|
+
const site = (0, components_1.useSite)();
|
|
29
|
+
const template = site.getPageSchema(pageType);
|
|
30
|
+
const collection = (0, components_1.usePageCollection)(pageType);
|
|
31
|
+
const { ready = false, items } = collection !== null && collection !== void 0 ? collection : {};
|
|
32
|
+
const groupedPages = (0, react_1.useMemo)(() => (!ready || !items)
|
|
33
|
+
? undefined
|
|
34
|
+
: groupPages(site, items), [site, items, ready]);
|
|
35
|
+
// dismiss splash
|
|
36
|
+
(0, react_1.useEffect)(() => {
|
|
37
|
+
if (ready) {
|
|
38
|
+
splash.dismiss();
|
|
39
|
+
}
|
|
40
|
+
}, [splash, ready]);
|
|
41
|
+
// helpers
|
|
42
|
+
const onCreatePage = async (e, anchorId) => {
|
|
43
|
+
};
|
|
44
|
+
const onOpenPage = async ({ template, language, slug }) => {
|
|
45
|
+
};
|
|
7
46
|
// render
|
|
8
|
-
return ((0, jsx_runtime_1.jsx)("div", { children: "
|
|
47
|
+
return ((0, jsx_runtime_1.jsxs)(components_1.FadeIn, { className: "w-full flex-1", variant: "blur", children: [(0, jsx_runtime_1.jsx)(components_2.HeaderOptions, { breadcrumbs: [{ label: 'Site Map', url: PagesExplorer_1.PagesExplorer.getUrl({ region: site.region.id }) }, template.name], highlightBreadcrumb: true, backButton: "back", onBack: () => navigate('/pages') }), (0, jsx_runtime_1.jsx)("div", { className: "relative flex-1 overflow-y-scroll shrink-0", tabIndex: -1, children: (0, jsx_runtime_1.jsx)("div", { className: "container-sm container-p", children: (0, jsx_runtime_1.jsx)(components_1.LoadingUntilReady, { className: "flex flex-col gap-l10 py-l14", ready: ready, children: renderPages({ template, groupedPages, onCreatePage, onOpenPage }) }) }) })] }, `page.${pageType}`));
|
|
48
|
+
}
|
|
49
|
+
// extension
|
|
50
|
+
(function (PageExplorer) {
|
|
51
|
+
function getUrl(_a) {
|
|
52
|
+
var { pageType } = _a, pagesArgs = __rest(_a, ["pageType"]);
|
|
53
|
+
return `${PagesExplorer_1.PagesExplorer.getUrl(pagesArgs)}/page/${pageType}`;
|
|
54
|
+
}
|
|
55
|
+
PageExplorer.getUrl = getUrl;
|
|
56
|
+
})(PageExplorer || (exports.PageExplorer = PageExplorer = {}));
|
|
57
|
+
function renderPages({ template, groupedPages, onCreatePage, onOpenPage }) {
|
|
58
|
+
// show loader if not ready
|
|
59
|
+
if (!groupedPages) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
// or show empty state if there are no pages
|
|
63
|
+
const { inProgress, live, unpublished } = groupedPages;
|
|
64
|
+
if (inProgress.length === 0 && live.length === 0 && unpublished.length === 0) {
|
|
65
|
+
return ((0, jsx_runtime_1.jsxs)(components_1.EmptyState, { variant: "missing", children: [(0, jsx_runtime_1.jsxs)("h3", { className: "heading-md text-content-primary", children: ["There are no ", template.name, " pages created yet!"] }), (0, jsx_runtime_1.jsxs)(components_1.Button, { anchorId: "page-create", variant: "primary", iconLeft: "Plus", onClick: e => onCreatePage(e, 'page-create'), children: ["Create a ", template.name] })] }, "empty"));
|
|
66
|
+
}
|
|
67
|
+
// render pages
|
|
68
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap gap-l8 justify-between items-center", children: [(0, jsx_runtime_1.jsxs)("h2", { className: "heading-lg text-content-primary", children: [template.name, " pages"] }), (0, jsx_runtime_1.jsxs)(components_1.Button, { anchorId: "page-create", variant: "primary", iconLeft: "Plus", onClick: e => onCreatePage(e, 'page-create'), children: ["Create a new ", template.name] })] }), inProgress.length > 0 &&
|
|
69
|
+
(0, jsx_runtime_1.jsx)(components_1.Table, { className: "flex-1", title: "Work in progress", children: inProgress.map(({ summary: { status }, link }) => (0, jsx_runtime_1.jsx)(components_1.TableItem, { details: status === 'ready'
|
|
70
|
+
? (0, jsx_runtime_1.jsx)(components_1.StatusBadge, { variant: "success", label: "Ready to publish" })
|
|
71
|
+
: status === 'changed'
|
|
72
|
+
? (0, jsx_runtime_1.jsx)(components_1.StatusBadge, { variant: "warn", label: "Changed" })
|
|
73
|
+
: undefined, iconRight: "ChevronRight", onClick: () => onOpenPage(link), children: link.name }, link.id)) }), unpublished.length > 0 &&
|
|
74
|
+
(0, jsx_runtime_1.jsx)(components_1.Table, { className: "flex-1", title: "Pending Unpublish", children: unpublished.map(({ summary: { status }, link }) => (0, jsx_runtime_1.jsx)(components_1.TableItem, { children: link.name }, link.id)) }), live.length > 0 &&
|
|
75
|
+
(0, jsx_runtime_1.jsx)(components_1.Table, { className: "flex-1", title: "Live", children: live.map(({ summary, link }) => (0, jsx_runtime_1.jsx)(components_1.TableItem, { iconRight: "ChevronRight", onClick: () => onOpenPage(link), children: link.name }, link.id)) })] }, "pages"));
|
|
76
|
+
}
|
|
77
|
+
function groupPages(site, summaries) {
|
|
78
|
+
// group pages
|
|
79
|
+
const { region: { id: region }, defaultLanguage: language } = site;
|
|
80
|
+
const groupedPages = summaries
|
|
81
|
+
// enrich summaries with links
|
|
82
|
+
.map(summary => ({ summary, link: summary.getClosestPageRef({ region, language }) }))
|
|
83
|
+
// group summaries based on status
|
|
84
|
+
.reduce((groupedPages, linkedSummary) => {
|
|
85
|
+
// bind page to group (drop empty pages groups, which shouldn't occur)
|
|
86
|
+
switch (linkedSummary.summary.status) {
|
|
87
|
+
case 'draft':
|
|
88
|
+
case 'changed':
|
|
89
|
+
case 'ready':
|
|
90
|
+
groupedPages.inProgress.push(linkedSummary);
|
|
91
|
+
break;
|
|
92
|
+
case 'unpublished':
|
|
93
|
+
groupedPages.unpublished.push(linkedSummary);
|
|
94
|
+
break;
|
|
95
|
+
case 'live':
|
|
96
|
+
groupedPages.live.push(linkedSummary);
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
// keep reducing
|
|
100
|
+
return groupedPages;
|
|
101
|
+
}, { inProgress: [], live: [], unpublished: [] });
|
|
102
|
+
// sort pages
|
|
103
|
+
groupedPages.inProgress.sort((lhs, rhs) => {
|
|
104
|
+
// sort by status first
|
|
105
|
+
const lhsStatus = lhs.summary.status;
|
|
106
|
+
const rhsStatus = rhs.summary.status;
|
|
107
|
+
if (lhsStatus !== rhsStatus) {
|
|
108
|
+
if (lhsStatus === 'ready') {
|
|
109
|
+
return -1;
|
|
110
|
+
}
|
|
111
|
+
else if (rhsStatus === 'ready') {
|
|
112
|
+
return 1;
|
|
113
|
+
}
|
|
114
|
+
else if (lhsStatus === 'changed') {
|
|
115
|
+
return -1;
|
|
116
|
+
}
|
|
117
|
+
else if (rhsStatus === 'changed') {
|
|
118
|
+
return 1;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// otherwise sort by name
|
|
122
|
+
return lhs.link.name.localeCompare(rhs.link.name);
|
|
123
|
+
});
|
|
124
|
+
groupedPages.unpublished.sort((lhs, rhs) => lhs.link.name.localeCompare(rhs.link.name));
|
|
125
|
+
groupedPages.live.sort((lhs, rhs) => lhs.link.name.localeCompare(rhs.link.name));
|
|
126
|
+
console.debug('[PageExplorer] grouped pages', groupedPages);
|
|
127
|
+
// return groups
|
|
128
|
+
return groupedPages;
|
|
9
129
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PagesExplorer = PagesExplorer;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_apps_toolkit_1 = require("@contentful/react-apps-toolkit");
|
|
6
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
7
|
+
const components_1 = require("@nascentdigital/funnel-editor/components");
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const react_router_1 = require("react-router");
|
|
10
|
+
const core_1 = require("../../core");
|
|
11
|
+
const components_2 = require("../components");
|
|
12
|
+
const PageExplorer_1 = require("./PageExplorer");
|
|
13
|
+
// screen
|
|
14
|
+
function PagesExplorer() {
|
|
15
|
+
// bind hooks
|
|
16
|
+
const sdk = (0, react_apps_toolkit_1.useSDK)();
|
|
17
|
+
const navigate = (0, react_router_1.useNavigate)();
|
|
18
|
+
const site = (0, components_1.useSite)();
|
|
19
|
+
const contentClient = (0, core_1.useContentfulClient)();
|
|
20
|
+
const splash = (0, components_1.useSplash)();
|
|
21
|
+
const dialog = (0, components_1.useDialog)();
|
|
22
|
+
const { ready, region: { id: region } } = site;
|
|
23
|
+
// dismiss splash
|
|
24
|
+
(0, react_1.useEffect)(() => {
|
|
25
|
+
if (ready) {
|
|
26
|
+
splash.dismiss();
|
|
27
|
+
}
|
|
28
|
+
}, [splash, ready]);
|
|
29
|
+
// helpers
|
|
30
|
+
const onPageClick = async (overview) => {
|
|
31
|
+
var _a;
|
|
32
|
+
// open static page
|
|
33
|
+
if (overview instanceof components_1.StaticPageOverview) {
|
|
34
|
+
// get closest page that matches our current region (or create it if there are no pages at all - new group)
|
|
35
|
+
let page = (_a = overview.findPage({ region })) !== null && _a !== void 0 ? _a : overview.pages[0];
|
|
36
|
+
if (!page) {
|
|
37
|
+
try {
|
|
38
|
+
// pick the best language
|
|
39
|
+
const language = site.getClosestLanguage(overview.languages);
|
|
40
|
+
console.debug('[PagesExplorer] page is not here - creating for language:', language);
|
|
41
|
+
// create new page for region
|
|
42
|
+
const { template } = overview;
|
|
43
|
+
const result = await contentClient.pages.create({
|
|
44
|
+
type: template.type,
|
|
45
|
+
brand: funnel_core_1.AppConfig.brand(),
|
|
46
|
+
region,
|
|
47
|
+
language,
|
|
48
|
+
name: template.name,
|
|
49
|
+
tags: []
|
|
50
|
+
});
|
|
51
|
+
// fail if page wasn't created
|
|
52
|
+
if (!result.page) {
|
|
53
|
+
await dialog.notify({
|
|
54
|
+
title: 'Failed to create page',
|
|
55
|
+
message: 'Something went wrong and while trying to create the page.'
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
// or capture ir
|
|
59
|
+
else {
|
|
60
|
+
page = result.page.data;
|
|
61
|
+
console.debug('[PagesExplorer] created page:', page);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// or show error dialog
|
|
65
|
+
catch (e) {
|
|
66
|
+
console.warn('[PagesExplorer] failed to create page', e);
|
|
67
|
+
await dialog.notify(Object.assign({ title: 'Failed to create page' }, components_1.ErrorMessage.coerce(funnel_core_1.IsometricErrorUtils.coerceError(e))));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.debug('[PagesExplorer] opening page for:', page.language);
|
|
72
|
+
}
|
|
73
|
+
// navigate to page using sdk
|
|
74
|
+
await sdk.navigator.openEntry(page.id, {
|
|
75
|
+
slideIn: false
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// or browse page group
|
|
79
|
+
else {
|
|
80
|
+
navigate(PageExplorer_1.PageExplorer.getUrl({ region, pageType: overview.type }));
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
// render
|
|
84
|
+
return ((0, jsx_runtime_1.jsxs)(components_1.FadeIn, { className: "w-full flex-1", variant: "blur", children: [(0, jsx_runtime_1.jsx)(components_2.HeaderOptions, { breadcrumbs: ['Site Map'], highlightBreadcrumb: true, backButton: "back", onBack: () => navigate('/') }), (0, jsx_runtime_1.jsx)("div", { className: "container-sm container-p", children: (0, jsx_runtime_1.jsxs)(components_1.LoadingUntilReady, { className: "flex flex-col gap-l10 py-l14", ready: ready, children: [(0, jsx_runtime_1.jsx)("h2", { className: "heading-lg text-content-primary", children: "Site explorer" }), (0, jsx_runtime_1.jsx)(components_1.Table, { className: "flex-1", children: site.overviews.map(overview => overview instanceof components_1.DynamicPageOverview
|
|
85
|
+
// nested item for dynamic pages
|
|
86
|
+
?
|
|
87
|
+
(0, jsx_runtime_1.jsx)(components_1.Table, { nested: true, children: (0, jsx_runtime_1.jsx)(components_1.TableItem, { nested: true, iconLeft: "CornerDownRight", iconRight: "ChevronRight", details: (0, jsx_runtime_1.jsx)(components_1.CountBadge, { count: overview.count }), onClick: () => onPageClick(overview), children: overview.template.name }) }, overview.type)
|
|
88
|
+
// or direct entry for static pages
|
|
89
|
+
:
|
|
90
|
+
(0, jsx_runtime_1.jsx)(components_1.TableItem, { iconRight: "ChevronRight", onClick: () => onPageClick(overview), children: overview.template.name }, overview.type)) })] }) })] }, "pages"));
|
|
91
|
+
}
|
|
92
|
+
// extension
|
|
93
|
+
(function (PagesExplorer) {
|
|
94
|
+
function getUrl({ region }) {
|
|
95
|
+
return `/pages/${region}`;
|
|
96
|
+
}
|
|
97
|
+
PagesExplorer.getUrl = getUrl;
|
|
98
|
+
})(PagesExplorer || (exports.PagesExplorer = PagesExplorer = {}));
|
|
@@ -16,4 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./Dashboard"), exports);
|
|
18
18
|
__exportStar(require("./PageExplorer"), exports);
|
|
19
|
-
__exportStar(require("./
|
|
19
|
+
__exportStar(require("./PagesExplorer"), exports);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BlockLayout } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { BlockConfiguration } from '@nascentdigital/funnel-editor/components';
|
|
3
|
+
import type { IAppBridgeMessage } from '../../core';
|
|
4
|
+
export interface BlockChangedMessage extends IAppBridgeMessage<BlockChangedMessage.Domain, BlockChangedMessage.Type> {
|
|
5
|
+
block?: BlockChangedMessage.BlockInfo;
|
|
6
|
+
}
|
|
7
|
+
export declare namespace BlockChangedMessage {
|
|
8
|
+
const domain: "nav.block";
|
|
9
|
+
type Domain = typeof domain;
|
|
10
|
+
type Type = 'changed';
|
|
11
|
+
type BlockInfo = {
|
|
12
|
+
schema: string;
|
|
13
|
+
identifier: string;
|
|
14
|
+
name: string;
|
|
15
|
+
errors: BlockErrors;
|
|
16
|
+
scope?: BlockConfiguration.Scope;
|
|
17
|
+
layout?: BlockLayout;
|
|
18
|
+
};
|
|
19
|
+
type BlockErrors = {
|
|
20
|
+
config: string[];
|
|
21
|
+
fields: string[];
|
|
22
|
+
};
|
|
23
|
+
function create(args: Omit<IAppBridgeMessage.Create.Args<BlockChangedMessage>, 'type'>): IAppBridgeMessage.Create.Result<BlockChangedMessage>;
|
|
24
|
+
function filter(message: IAppBridgeMessage): message is BlockChangedMessage;
|
|
25
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BlockChangedMessage = void 0;
|
|
4
|
+
// extensions
|
|
5
|
+
var BlockChangedMessage;
|
|
6
|
+
(function (BlockChangedMessage) {
|
|
7
|
+
// types
|
|
8
|
+
BlockChangedMessage.domain = 'nav.block';
|
|
9
|
+
// helpers
|
|
10
|
+
function create(args) {
|
|
11
|
+
return Object.assign(Object.assign({}, args), { domain: BlockChangedMessage.domain, type: 'changed' });
|
|
12
|
+
}
|
|
13
|
+
BlockChangedMessage.create = create;
|
|
14
|
+
function filter(message) {
|
|
15
|
+
return message.domain === BlockChangedMessage.domain;
|
|
16
|
+
}
|
|
17
|
+
BlockChangedMessage.filter = filter;
|
|
18
|
+
})(BlockChangedMessage || (exports.BlockChangedMessage = BlockChangedMessage = {}));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Block, PageSettings, Section, SectionBlock } from '@nascentdigital/funnel-editor/components';
|
|
2
|
+
import { PropsWithChildren } from 'react';
|
|
3
|
+
export declare function PageBridgeHub({ selectedItem, children }: PageBridgeHub.Props): import("react").ReactNode;
|
|
4
|
+
export declare namespace PageBridgeHub {
|
|
5
|
+
type Props = PropsWithChildren & {
|
|
6
|
+
selectedItem?: Block | SectionBlock | Section | PageSettings;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PageBridgeHub = PageBridgeHub;
|
|
4
|
+
const components_1 = require("@nascentdigital/funnel-editor/components");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const core_1 = require("../../core");
|
|
7
|
+
const BlockChangedMessage_1 = require("./BlockChangedMessage");
|
|
8
|
+
function PageBridgeHub({ selectedItem, children }) {
|
|
9
|
+
// bind bridge
|
|
10
|
+
const configuration = (0, components_1.useBlockConfiguration)();
|
|
11
|
+
const { block, scope, layout } = configuration !== null && configuration !== void 0 ? configuration : {};
|
|
12
|
+
const bridge = (0, core_1.useAppBridge)();
|
|
13
|
+
const ready = bridge.state === 'ready';
|
|
14
|
+
const bridges = bridge.bridges;
|
|
15
|
+
// sync selected item
|
|
16
|
+
(0, react_1.useEffect)(() => {
|
|
17
|
+
// skip if bridge isn't ready
|
|
18
|
+
if (!ready || bridges.size === 1) {
|
|
19
|
+
console.debug('[PageBridgeHub] not ready');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
console.debug('[PageBridgeHub] processing block change', { block, scope, layout });
|
|
23
|
+
// update
|
|
24
|
+
sendBlockChange({ bridge, block, scope, layout });
|
|
25
|
+
}, [bridge, ready, block, scope, layout, bridges]);
|
|
26
|
+
// render
|
|
27
|
+
return children;
|
|
28
|
+
}
|
|
29
|
+
function sendBlockChange({ bridge, block, scope, layout }) {
|
|
30
|
+
// send update
|
|
31
|
+
if (block) {
|
|
32
|
+
const { schema, identifier, name, errors } = block;
|
|
33
|
+
bridge.send(BlockChangedMessage_1.BlockChangedMessage.create({
|
|
34
|
+
block: {
|
|
35
|
+
schema: schema.id,
|
|
36
|
+
identifier,
|
|
37
|
+
name,
|
|
38
|
+
errors: {
|
|
39
|
+
config: errors.config.map(field => field.id),
|
|
40
|
+
fields: errors.fields.map(field => field.id)
|
|
41
|
+
},
|
|
42
|
+
scope,
|
|
43
|
+
layout
|
|
44
|
+
}
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
// or clear block
|
|
48
|
+
else {
|
|
49
|
+
bridge.send(BlockChangedMessage_1.BlockChangedMessage.create({}));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
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("./BlockChangedMessage"), exports);
|
|
18
|
+
__exportStar(require("./PageBridgeHub"), exports);
|
|
@@ -73,7 +73,7 @@ export declare class Page implements IPage {
|
|
|
73
73
|
get blocks(): (Block<Schema.Block<string, any, any>> | SectionBlock<Schema.Block<string, any, any>>)[];
|
|
74
74
|
get deleteBlocks(): ReadonlyArray<Block>;
|
|
75
75
|
get firstBlock(): Block<Schema.Block<string, any, any>> | SectionBlock<Schema.Block<string, any, any>> | undefined;
|
|
76
|
-
get firstItem(): Block<Schema.Block<string, any, any
|
|
76
|
+
get firstItem(): Section | Block<Schema.Block<string, any, any>>;
|
|
77
77
|
get items(): Array<Block | Section>;
|
|
78
78
|
get assets(): Asset[];
|
|
79
79
|
get collections(): ReadonlyArray<Schema.Collection.Data.AsLink>;
|
|
@@ -142,7 +142,7 @@ export declare namespace Page {
|
|
|
142
142
|
};
|
|
143
143
|
type FromSchemaData = {
|
|
144
144
|
data: ContentfulPageData.ForSchema;
|
|
145
|
-
references
|
|
145
|
+
references: Schema.Page.References;
|
|
146
146
|
eventBus?: EventBus;
|
|
147
147
|
};
|
|
148
148
|
function fromSchemaData({ data, references, eventBus }: FromSchemaData): Page;
|
package/dist/page/domain/Page.js
CHANGED
|
@@ -12,6 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.Page = void 0;
|
|
15
|
+
const contentful_1 = require("@nascentdigital/funnel-cms/contentful");
|
|
15
16
|
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
16
17
|
const components_1 = require("@nascentdigital/funnel-editor/components");
|
|
17
18
|
const rxjs_1 = require("rxjs");
|
|
@@ -534,7 +535,7 @@ exports.Page = Page;
|
|
|
534
535
|
eventBus,
|
|
535
536
|
content: content[key],
|
|
536
537
|
snapshot: contentSnapshot[key],
|
|
537
|
-
})), files: Object.values(files), collections: Object.values(collections), pages: Object.values(pages) }));
|
|
538
|
+
})), files: Object.values(files), collections: Object.values(collections), pages: Object.values(pages).map(components_1.IPage.Ref.fromData), references: contentful_1.ContentfulData.findReferences([discover, content]) }));
|
|
538
539
|
}
|
|
539
540
|
Page.fromSchemaData = fromSchemaData;
|
|
540
541
|
function toUpdates(page, savables) {
|
package/dist/page/index.d.ts
CHANGED
package/dist/page/index.js
CHANGED
|
@@ -14,6 +14,7 @@ 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("./bridge"), exports);
|
|
17
18
|
__exportStar(require("./domain"), exports);
|
|
18
19
|
__exportStar(require("./repository"), exports);
|
|
19
20
|
__exportStar(require("./screens"), exports);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { EditorAppSDK, EntrySys } from '@contentful/app-sdk';
|
|
1
|
+
import { EditorAppSDK, EntrySys, PageAppSDK } from '@contentful/app-sdk';
|
|
2
2
|
import { ContentfulContentClient } from '@nascentdigital/funnel-cms/contentful';
|
|
3
3
|
import { Schema } from '@nascentdigital/funnel-core';
|
|
4
4
|
import { IPage, IPageRepository, PageSummary } from '@nascentdigital/funnel-editor/components';
|
|
5
5
|
import { Page } from '../domain';
|
|
6
6
|
export declare class PageRepository implements IPageRepository {
|
|
7
|
-
readonly sdk: EditorAppSDK;
|
|
7
|
+
readonly sdk: EditorAppSDK | PageAppSDK;
|
|
8
8
|
readonly contentfulClient: ContentfulContentClient;
|
|
9
9
|
constructor(args: PageRepository.ConstructorArgs);
|
|
10
10
|
search(args: IPageRepository.Search.Args): Promise<IPageRepository.Search.Result>;
|
|
@@ -18,7 +18,7 @@ export declare class PageRepository implements IPageRepository {
|
|
|
18
18
|
}
|
|
19
19
|
export declare namespace PageRepository {
|
|
20
20
|
type ConstructorArgs = {
|
|
21
|
-
sdk: EditorAppSDK;
|
|
21
|
+
sdk: EditorAppSDK | PageAppSDK;
|
|
22
22
|
contentfulClient: ContentfulContentClient;
|
|
23
23
|
};
|
|
24
24
|
namespace Load {
|
|
@@ -24,7 +24,11 @@ class PageRepository {
|
|
|
24
24
|
this.contentfulClient = args.contentfulClient;
|
|
25
25
|
}
|
|
26
26
|
async search(args) {
|
|
27
|
-
|
|
27
|
+
// execute search
|
|
28
|
+
const { template } = args, query = __rest(args, ["template"]);
|
|
29
|
+
const _a = await this.contentfulClient.pages.search(Object.assign(Object.assign({}, query), { version: 'draft', brand: funnel_core_1.AppConfig.brand(), type: template.type })), { items } = _a, result = __rest(_a, ["items"]);
|
|
30
|
+
// return items
|
|
31
|
+
return Object.assign(Object.assign({}, result), { items: items.map(item => components_1.IPage.Ref.fromData(item)) });
|
|
28
32
|
}
|
|
29
33
|
async getOverview({ region }) {
|
|
30
34
|
// get overviews
|
|
@@ -57,8 +61,12 @@ class PageRepository {
|
|
|
57
61
|
throw new funnel_core_1.NotImplementedError();
|
|
58
62
|
}
|
|
59
63
|
async load(sys) {
|
|
60
|
-
//
|
|
64
|
+
// guard method
|
|
61
65
|
const { sdk, contentfulClient } = this;
|
|
66
|
+
if (!('entry' in sdk)) {
|
|
67
|
+
throw new funnel_core_1.InvalidOperationError('Attempt to call load() outside of EntryEditor');
|
|
68
|
+
}
|
|
69
|
+
// throw if entry isn't a page (it should be in this case)
|
|
62
70
|
const { entry } = sdk;
|
|
63
71
|
sys = sys !== null && sys !== void 0 ? sys : entry.getSys();
|
|
64
72
|
const { id: entryId, contentType: { sys: { id: entryType } } } = sys;
|
|
@@ -85,7 +93,7 @@ class PageRepository {
|
|
|
85
93
|
const { data: _remote } = pageResult, references = __rest(pageResult, ["data"]);
|
|
86
94
|
const data = entryToPageData(entry);
|
|
87
95
|
// return page model from data
|
|
88
|
-
const page = domain_1.Page.fromSchemaData(
|
|
96
|
+
const page = domain_1.Page.fromSchemaData({ data, references });
|
|
89
97
|
return {
|
|
90
98
|
pageSummary: new components_1.PageSummary(Object.assign(Object.assign({ template: page.template }, group), { pages })),
|
|
91
99
|
page,
|
|
@@ -93,6 +101,11 @@ class PageRepository {
|
|
|
93
101
|
};
|
|
94
102
|
}
|
|
95
103
|
async save(page) {
|
|
104
|
+
// guard method
|
|
105
|
+
const { sdk } = this;
|
|
106
|
+
if (!('entry' in sdk)) {
|
|
107
|
+
throw new funnel_core_1.InvalidOperationError('Attempt to call save() outside of EntryEditor');
|
|
108
|
+
}
|
|
96
109
|
// serialize page updates (or skip if there are no changes)
|
|
97
110
|
const savables = [];
|
|
98
111
|
const updateArgs = domain_1.Page.toUpdates(page, savables);
|
|
@@ -104,7 +117,6 @@ class PageRepository {
|
|
|
104
117
|
savables.forEach(savable => savable.onSaveStart());
|
|
105
118
|
// update entry if page is local
|
|
106
119
|
let updatedOn;
|
|
107
|
-
const { sdk } = this;
|
|
108
120
|
const { entry } = sdk;
|
|
109
121
|
const { id: entryId, contentType: { sys: { id: entryType } } } = entry.getSys();
|
|
110
122
|
if (entryType === contentful_1.ContentfulPageData.contentType && page.id === entryId) {
|
|
@@ -124,7 +136,8 @@ class PageRepository {
|
|
|
124
136
|
// swap to new page (if update returned new data)
|
|
125
137
|
if (result.page) {
|
|
126
138
|
console.debug('[PageRepository/save] switching to new page data', result.page);
|
|
127
|
-
|
|
139
|
+
const _a = result.page, { data } = _a, references = __rest(_a, ["data"]);
|
|
140
|
+
page = domain_1.Page.fromSchemaData({ data, references });
|
|
128
141
|
}
|
|
129
142
|
}
|
|
130
143
|
console.debug('[PageRepository/save] finalizing save');
|
|
@@ -136,8 +149,12 @@ class PageRepository {
|
|
|
136
149
|
return page;
|
|
137
150
|
}
|
|
138
151
|
async sync({ page, sys }) {
|
|
139
|
-
//
|
|
152
|
+
// guard method
|
|
140
153
|
const { sdk } = this;
|
|
154
|
+
if (!('entry' in sdk)) {
|
|
155
|
+
throw new funnel_core_1.InvalidOperationError('Attempt to call sync() outside of EntryEditor');
|
|
156
|
+
}
|
|
157
|
+
// skip if entity version and updated sys are same
|
|
141
158
|
const { entry } = sdk;
|
|
142
159
|
const entrySys = entry.getSys();
|
|
143
160
|
if (sys.version === entrySys.version) {
|
|
@@ -172,7 +189,7 @@ class PageRepository {
|
|
|
172
189
|
};
|
|
173
190
|
// create new page (use existing sys)
|
|
174
191
|
return {
|
|
175
|
-
page: domain_1.Page.fromSchemaData(
|
|
192
|
+
page: domain_1.Page.fromSchemaData({ data, references }),
|
|
176
193
|
sys
|
|
177
194
|
};
|
|
178
195
|
}
|
|
@@ -201,7 +218,7 @@ async function saveEntryUpdates({ entry, updates }) {
|
|
|
201
218
|
pageModel.update(updates);
|
|
202
219
|
pageModel.sync();
|
|
203
220
|
// resolve references
|
|
204
|
-
const references = contentful_1.ContentfulData.findReferences([pageData.discover, pageData.
|
|
221
|
+
const references = contentful_1.ContentfulData.findReferences([pageData.discover, pageData.content]);
|
|
205
222
|
// update fields
|
|
206
223
|
const { fields } = entry;
|
|
207
224
|
await Promise.all([
|