@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.
Files changed (104) hide show
  1. package/dist/EditorApp.js +2 -2
  2. package/dist/EditorPageRouter.js +3 -9
  3. package/dist/EditorPageRoutes.d.ts +1 -0
  4. package/dist/EditorPageRoutes.js +16 -0
  5. package/dist/EntryEditor.js +1 -1
  6. package/dist/EntrySidebar.js +26 -5
  7. package/dist/NotFound.d.ts +1 -0
  8. package/dist/NotFound.js +18 -0
  9. package/dist/asset/repository/AssetRepository.d.ts +11 -3
  10. package/dist/asset/repository/AssetRepository.js +6 -5
  11. package/dist/collection/domain/Collection.js +2 -1
  12. package/dist/collection/repository/CollectionRepository.d.ts +3 -3
  13. package/dist/collection/repository/CollectionRepository.js +19 -6
  14. package/dist/core/bridge/AppBridge.d.ts +31 -0
  15. package/dist/core/bridge/AppBridge.js +160 -0
  16. package/dist/core/bridge/AppBridgeContainer.d.ts +3 -3
  17. package/dist/core/bridge/AppBridgeContainer.js +8 -44
  18. package/dist/core/bridge/AppBridgeContext.d.ts +7 -8
  19. package/dist/core/bridge/AppBridgeContext.js +1 -6
  20. package/dist/core/bridge/BridgeLifecycleMessage.d.ts +7 -0
  21. package/dist/core/bridge/BridgeLifecycleMessage.js +12 -0
  22. package/dist/core/bridge/IAppBridgeMessage.d.ts +16 -0
  23. package/dist/core/bridge/IAppBridgeMessage.js +12 -0
  24. package/dist/core/bridge/index.d.ts +2 -1
  25. package/dist/core/bridge/index.js +2 -1
  26. package/dist/core/bridge/useAppBridge.d.ts +2 -8
  27. package/dist/core/bridge/useAppBridge.js +24 -15
  28. package/dist/core/index.d.ts +0 -2
  29. package/dist/core/index.js +0 -2
  30. package/dist/explore/components/header/Header.d.ts +14 -0
  31. package/dist/explore/components/{Header.js → header/Header.js} +10 -8
  32. package/dist/explore/components/header/HeaderActions.d.ts +8 -0
  33. package/dist/explore/components/header/HeaderActions.js +37 -0
  34. package/dist/explore/components/header/HeaderContainer.d.ts +2 -0
  35. package/dist/explore/components/header/HeaderContainer.js +15 -0
  36. package/dist/explore/components/header/HeaderContext.d.ts +7 -0
  37. package/dist/explore/components/header/HeaderContext.js +6 -0
  38. package/dist/explore/components/header/HeaderController.d.ts +39 -0
  39. package/dist/explore/components/header/HeaderController.js +100 -0
  40. package/dist/explore/components/header/HeaderOptions.d.ts +10 -0
  41. package/dist/explore/components/header/HeaderOptions.js +26 -0
  42. package/dist/explore/components/header/index.d.ts +5 -0
  43. package/dist/{core/contentful → explore/components/header}/index.js +5 -5
  44. package/dist/explore/components/header/useHeader.d.ts +2 -0
  45. package/dist/explore/components/header/useHeader.js +30 -0
  46. package/dist/explore/components/index.d.ts +2 -1
  47. package/dist/explore/components/index.js +2 -1
  48. package/dist/explore/components/pages/PagesExplorerLayout.d.ts +4 -0
  49. package/dist/explore/components/pages/PagesExplorerLayout.js +28 -0
  50. package/dist/explore/components/pages/index.d.ts +1 -0
  51. package/dist/{core/repository → explore/components/pages}/index.js +1 -4
  52. package/dist/explore/index.d.ts +1 -0
  53. package/dist/explore/index.js +1 -0
  54. package/dist/explore/screens/Dashboard.d.ts +3 -0
  55. package/dist/explore/screens/Dashboard.js +34 -1
  56. package/dist/explore/screens/PageExplorer.d.ts +10 -0
  57. package/dist/explore/screens/PageExplorer.js +121 -1
  58. package/dist/explore/screens/PagesExplorer.d.ts +7 -0
  59. package/dist/explore/screens/PagesExplorer.js +98 -0
  60. package/dist/explore/screens/index.d.ts +1 -1
  61. package/dist/explore/screens/index.js +1 -1
  62. package/dist/page/bridge/BlockChangedMessage.d.ts +25 -0
  63. package/dist/page/bridge/BlockChangedMessage.js +18 -0
  64. package/dist/page/bridge/PageBridgeHub.d.ts +8 -0
  65. package/dist/page/bridge/PageBridgeHub.js +51 -0
  66. package/dist/page/bridge/index.d.ts +2 -0
  67. package/dist/page/bridge/index.js +18 -0
  68. package/dist/page/domain/Page.d.ts +2 -2
  69. package/dist/page/domain/Page.js +2 -1
  70. package/dist/page/index.d.ts +1 -0
  71. package/dist/page/index.js +1 -0
  72. package/dist/page/repository/PageRepository.d.ts +3 -3
  73. package/dist/page/repository/PageRepository.js +25 -8
  74. package/dist/page/screens/PageEditor.js +14 -6
  75. package/package.json +5 -5
  76. package/dist/core/bridge/AppMessage.d.ts +0 -19
  77. package/dist/core/bridge/AppMessage.js +0 -19
  78. package/dist/core/contentful/Contentful.d.ts +0 -33
  79. package/dist/core/contentful/Contentful.js +0 -67
  80. package/dist/core/contentful/ContentfulAsset.d.ts +0 -23
  81. package/dist/core/contentful/ContentfulAsset.js +0 -89
  82. package/dist/core/contentful/ContentfulCollection.d.ts +0 -29
  83. package/dist/core/contentful/ContentfulCollection.js +0 -97
  84. package/dist/core/contentful/ContentfulPage.d.ts +0 -31
  85. package/dist/core/contentful/ContentfulPage.js +0 -84
  86. package/dist/core/contentful/ContentfulRefs.d.ts +0 -16
  87. package/dist/core/contentful/ContentfulRefs.js +0 -152
  88. package/dist/core/contentful/index.d.ts +0 -5
  89. package/dist/core/repository/CollectionSerializer.d.ts +0 -9
  90. package/dist/core/repository/CollectionSerializer.js +0 -41
  91. package/dist/core/repository/LocalCollectionRepository.d.ts +0 -27
  92. package/dist/core/repository/LocalCollectionRepository.js +0 -143
  93. package/dist/core/repository/LocalPageRepository.d.ts +0 -16
  94. package/dist/core/repository/LocalPageRepository.js +0 -153
  95. package/dist/core/repository/PageSerializer.d.ts +0 -9
  96. package/dist/core/repository/PageSerializer.js +0 -48
  97. package/dist/core/repository/RemoteCollectionRepository.d.ts +0 -19
  98. package/dist/core/repository/RemoteCollectionRepository.js +0 -236
  99. package/dist/core/repository/RemotePageRepository.d.ts +0 -14
  100. package/dist/core/repository/RemotePageRepository.js +0 -113
  101. package/dist/core/repository/index.d.ts +0 -4
  102. package/dist/explore/components/Header.d.ts +0 -26
  103. package/dist/explore/screens/SiteExplorer.d.ts +0 -1
  104. 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.Header, { breadcrumbs: ['Dashboard'], back: "none" }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(react_router_1.Link, { to: "/contentful/pages", children: "Site Explorer" }) })] }));
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: "Page" }));
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,7 @@
1
+ export declare function PagesExplorer(): import("react/jsx-runtime").JSX.Element;
2
+ export declare namespace PagesExplorer {
3
+ type GetUrlArgs = {
4
+ region: string;
5
+ };
6
+ function getUrl({ region }: GetUrlArgs): string;
7
+ }
@@ -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 = {}));
@@ -1,3 +1,3 @@
1
1
  export * from './Dashboard';
2
2
  export * from './PageExplorer';
3
- export * from './SiteExplorer';
3
+ export * from './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("./SiteExplorer"), exports);
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,2 @@
1
+ export * from './BlockChangedMessage';
2
+ export * from './PageBridgeHub';
@@ -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>> | Section;
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?: Schema.Page.References;
145
+ references: Schema.Page.References;
146
146
  eventBus?: EventBus;
147
147
  };
148
148
  function fromSchemaData({ data, references, eventBus }: FromSchemaData): Page;
@@ -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) {
@@ -1,3 +1,4 @@
1
+ export * from './bridge';
1
2
  export * from './domain';
2
3
  export * from './repository';
3
4
  export * from './screens';
@@ -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
- throw new funnel_core_1.NotImplementedError();
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
- // throw if entry isn't a page (it should be in this case)
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(Object.assign({ data }, references));
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
- page = domain_1.Page.fromSchemaData(result.page);
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
- // skip if entity version and updated sys are same
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(Object.assign({ data }, references)),
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.preview, pageData.content]);
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([