@webiny/app-headless-cms 6.6.0-alpha.0 → 6.6.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/ContentEntriesModule.js +3 -3
  2. package/ContentEntriesModule.js.map +1 -1
  3. package/HeadlessCMS.js +7 -2
  4. package/HeadlessCMS.js.map +1 -1
  5. package/admin/RoutesConfig.js +14 -1
  6. package/admin/RoutesConfig.js.map +1 -1
  7. package/admin/components/ContentEntries/BulkActions/ActionDelete.d.ts +2 -2
  8. package/admin/components/ContentEntries/BulkActions/ActionDelete.js.map +1 -1
  9. package/admin/components/ContentEntries/BulkActions/ActionMove.d.ts +2 -2
  10. package/admin/components/ContentEntries/BulkActions/ActionMove.js.map +1 -1
  11. package/admin/components/ContentEntries/BulkActions/ActionPublish.d.ts +2 -2
  12. package/admin/components/ContentEntries/BulkActions/ActionPublish.js.map +1 -1
  13. package/admin/components/ContentEntries/BulkActions/ActionUnpublish.d.ts +2 -2
  14. package/admin/components/ContentEntries/BulkActions/ActionUnpublish.js.map +1 -1
  15. package/admin/components/ContentModelEditor/ContentModelEditorProvider.js +1 -0
  16. package/admin/components/ContentModelEditor/ContentModelEditorProvider.js.map +1 -1
  17. package/admin/components/ContentModelEditor/FieldsSidebar.js +12 -2
  18. package/admin/components/ContentModelEditor/FieldsSidebar.js.map +1 -1
  19. package/admin/components/ContentModelEditor/evaluateExpression.js +4 -0
  20. package/admin/components/ContentModelEditor/evaluateExpression.js.map +1 -1
  21. package/admin/components/Dialogs/PublishEntryConfirmDialog.d.ts +26 -1
  22. package/admin/components/Dialogs/PublishEntryConfirmDialog.js +4 -3
  23. package/admin/components/Dialogs/PublishEntryConfirmDialog.js.map +1 -1
  24. package/admin/components/Dialogs/UnpublishEntryConfirmDialog.d.ts +26 -1
  25. package/admin/components/Dialogs/UnpublishEntryConfirmDialog.js +4 -3
  26. package/admin/components/Dialogs/UnpublishEntryConfirmDialog.js.map +1 -1
  27. package/admin/components/FieldEditor/EditFieldDialog/PermissionsEditor/PermissionsEditor.js +3 -3
  28. package/admin/components/FieldEditor/EditFieldDialog/PermissionsEditor/PermissionsEditor.js.map +1 -1
  29. package/admin/components/FieldEditor/EditFieldDialog.d.ts +2 -2
  30. package/admin/components/FieldEditor/EditFieldDialog.js +5 -2
  31. package/admin/components/FieldEditor/EditFieldDialog.js.map +1 -1
  32. package/admin/components/FieldEditor/Field.js +1 -1
  33. package/admin/components/FieldEditor/Field.js.map +1 -1
  34. package/admin/components/FieldEditor/FieldEditor.js +2 -2
  35. package/admin/components/FieldEditor/FieldEditor.js.map +1 -1
  36. package/admin/components/FieldEditor/FieldEditorContext.d.ts +1 -1
  37. package/admin/components/FieldEditor/FieldEditorContext.js +6 -1
  38. package/admin/components/FieldEditor/FieldEditorContext.js.map +1 -1
  39. package/admin/components/LexicalCmsEditor/LexicalEditor.js +10 -6
  40. package/admin/components/LexicalCmsEditor/LexicalEditor.js.map +1 -1
  41. package/admin/components/LexicalCmsEditor/TypographyDropDown.js +3 -2
  42. package/admin/components/LexicalCmsEditor/TypographyDropDown.js.map +1 -1
  43. package/admin/config/contentEntries/editor/ContentEntryEditorConfig.d.ts +60 -2
  44. package/admin/config/contentEntries/editor/ContentEntryEditorConfig.js +18 -5
  45. package/admin/config/contentEntries/editor/ContentEntryEditorConfig.js.map +1 -1
  46. package/admin/config/contentEntries/editor/NewEntryWizard.d.ts +8 -1
  47. package/admin/config/contentEntries/editor/NewEntryWizard.js +20 -5
  48. package/admin/config/contentEntries/editor/NewEntryWizard.js.map +1 -1
  49. package/admin/config/contentEntries/list/Browser/BreadcrumbRoot.d.ts +38 -0
  50. package/admin/config/contentEntries/list/Browser/BreadcrumbRoot.js +23 -0
  51. package/admin/config/contentEntries/list/Browser/BreadcrumbRoot.js.map +1 -0
  52. package/admin/config/contentEntries/list/Browser/index.d.ts +21 -0
  53. package/admin/config/contentEntries/list/Browser/index.js +2 -0
  54. package/admin/config/contentEntries/list/Browser/index.js.map +1 -1
  55. package/admin/config/contentEntries/list/ContentEntryListConfig.d.ts +39 -0
  56. package/admin/config/contentEntries/list/ContentEntryListConfig.js +2 -1
  57. package/admin/config/contentEntries/list/ContentEntryListConfig.js.map +1 -1
  58. package/admin/graphql/contentModels.d.ts +1 -1
  59. package/admin/graphql/contentModels.js +2 -1
  60. package/admin/graphql/contentModels.js.map +1 -1
  61. package/admin/plugins/editor/formSettings/components/GeneralSettings.js +24 -1
  62. package/admin/plugins/editor/formSettings/components/GeneralSettings.js.map +1 -1
  63. package/exports/admin/cms/entry/editor.d.ts +1 -0
  64. package/exports/admin/cms/entry/editor.js +1 -0
  65. package/exports/admin/cms/entry/list.d.ts +2 -0
  66. package/exports/admin/cms/entry/list.js +2 -0
  67. package/exports/admin/cms.d.ts +2 -0
  68. package/exports/admin/cms.js +2 -0
  69. package/features/contentEntry/EntryGraphQLFields.js +1 -1
  70. package/features/contentEntry/EntryGraphQLFields.js.map +1 -1
  71. package/features/contentEntry/createEntry/CreateEntryRepository.d.ts +3 -1
  72. package/features/contentEntry/createEntry/CreateEntryRepository.js +10 -2
  73. package/features/contentEntry/createEntry/CreateEntryRepository.js.map +1 -1
  74. package/features/contentEntry/deleteEntry/DeleteEntryRepository.d.ts +3 -1
  75. package/features/contentEntry/deleteEntry/DeleteEntryRepository.js +12 -2
  76. package/features/contentEntry/deleteEntry/DeleteEntryRepository.js.map +1 -1
  77. package/features/contentEntry/refTypes.d.ts +7 -0
  78. package/features/contentEntry/refTypes.js.map +1 -1
  79. package/features/contentEntry/updateEntry/UpdateEntryRepository.d.ts +3 -1
  80. package/features/contentEntry/updateEntry/UpdateEntryRepository.js +10 -2
  81. package/features/contentEntry/updateEntry/UpdateEntryRepository.js.map +1 -1
  82. package/features/formModel/mappers/AssetFieldMapper.d.ts +12 -0
  83. package/features/formModel/mappers/AssetFieldMapper.js +13 -0
  84. package/features/formModel/mappers/AssetFieldMapper.js.map +1 -0
  85. package/features/formModel/mappers/index.js +2 -0
  86. package/features/formModel/mappers/index.js.map +1 -1
  87. package/features/model/updateModel/UpdateModelGateway.js +1 -0
  88. package/features/model/updateModel/UpdateModelGateway.js.map +1 -1
  89. package/index.d.ts +1 -1
  90. package/index.js +1 -1
  91. package/package.json +24 -24
  92. package/presentation/contentEntries/list/ContentEntriesPresenter.test.js +4 -0
  93. package/presentation/contentEntries/list/ContentEntriesPresenter.test.js.map +1 -1
  94. package/presentation/contentEntries/preview/ComponentDiscoveryIframe.d.ts +6 -0
  95. package/presentation/contentEntries/preview/ComponentDiscoveryIframe.js +47 -0
  96. package/presentation/contentEntries/preview/ComponentDiscoveryIframe.js.map +1 -0
  97. package/presentation/contentEntries/preview/LivePreviewPresenter.d.ts +14 -0
  98. package/presentation/contentEntries/preview/LivePreviewPresenter.js +33 -0
  99. package/presentation/contentEntries/preview/LivePreviewPresenter.js.map +1 -0
  100. package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.d.ts +2 -0
  101. package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.js +27 -0
  102. package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.js.map +1 -0
  103. package/presentation/contentEntries/preview/PreviewComponentsContext.d.ts +15 -0
  104. package/presentation/contentEntries/preview/PreviewComponentsContext.js +43 -0
  105. package/presentation/contentEntries/preview/PreviewComponentsContext.js.map +1 -0
  106. package/presentation/contentEntries/preview/PreviewDecorator.d.ts +2 -0
  107. package/presentation/contentEntries/preview/PreviewDecorator.js +48 -0
  108. package/presentation/contentEntries/preview/PreviewDecorator.js.map +1 -0
  109. package/presentation/contentEntries/preview/PreviewPane.d.ts +9 -0
  110. package/presentation/contentEntries/preview/PreviewPane.js +181 -0
  111. package/presentation/contentEntries/preview/PreviewPane.js.map +1 -0
  112. package/presentation/contentEntries/preview/abstractions.d.ts +16 -0
  113. package/presentation/contentEntries/preview/abstractions.js +5 -0
  114. package/presentation/contentEntries/preview/abstractions.js.map +1 -0
  115. package/presentation/contentEntries/preview/feature.d.ts +3 -0
  116. package/presentation/contentEntries/preview/feature.js +17 -0
  117. package/presentation/contentEntries/preview/feature.js.map +1 -0
  118. package/presentation/contentEntries/preview/resolvePreviewUrl.d.ts +5 -0
  119. package/presentation/contentEntries/preview/resolvePreviewUrl.js +29 -0
  120. package/presentation/contentEntries/preview/resolvePreviewUrl.js.map +1 -0
  121. package/presentation/contentEntries/preview/useLivePreviewPresenter.d.ts +1 -0
  122. package/presentation/contentEntries/preview/useLivePreviewPresenter.js +8 -0
  123. package/presentation/contentEntries/preview/useLivePreviewPresenter.js.map +1 -0
  124. package/presentation/contentEntries/trashBin/CmsTrashBin.d.ts +2 -2
  125. package/presentation/contentEntries/views/CmsAdvancedSearch.d.ts +2 -2
  126. package/presentation/contentEntries/views/ContentEntriesBreadcrumbs.d.ts +13 -0
  127. package/presentation/contentEntries/views/ContentEntriesBreadcrumbs.js +54 -0
  128. package/presentation/contentEntries/views/ContentEntriesBreadcrumbs.js.map +1 -0
  129. package/presentation/contentEntries/views/ContentEntriesListLayout.d.ts +2 -2
  130. package/presentation/contentEntries/views/ContentEntriesListLayout.js +3 -2
  131. package/presentation/contentEntries/views/ContentEntriesListLayout.js.map +1 -1
  132. package/presentation/contentEntries/views/ContentEntryFormView.d.ts +2 -2
  133. package/presentation/contentEntries/views/ContentEntryFormView.js +5 -6
  134. package/presentation/contentEntries/views/ContentEntryFormView.js.map +1 -1
  135. package/presentation/contentEntries/views/RevisionDrawer.d.ts +2 -2
  136. package/presentation/contentEntries/views/RevisionsList.d.ts +2 -2
  137. package/presentation/contentEntries/views/SingleEntryLayout.d.ts +2 -2
  138. package/presentation/contentEntries/views/Table/Table.d.ts +2 -2
  139. package/presentation/contentEntries/views/actions/CreateNewRevisionButton.d.ts +2 -2
  140. package/presentation/contentEntries/views/actions/DeleteEntryMenuItem.d.ts +2 -2
  141. package/presentation/contentEntries/views/actions/PublishOnlyButton.d.ts +2 -2
  142. package/presentation/contentEntries/views/actions/RevisionSelector.d.ts +2 -2
  143. package/presentation/contentEntries/views/actions/SaveAndPublishButton.d.ts +2 -2
  144. package/presentation/contentEntries/views/actions/SaveContentButton.d.ts +2 -2
  145. package/presentation/contentEntries/views/actions/ShowRevisionListMenuItem.d.ts +2 -2
  146. package/presentation/contentEntries/views/layout/ContentEntryForm.d.ts +12 -12
  147. package/presentation/contentEntries/views/layout/ContentEntryFormContent.d.ts +10 -6
  148. package/presentation/contentEntries/views/layout/ContentEntryFormContent.js +7 -2
  149. package/presentation/contentEntries/views/layout/ContentEntryFormContent.js.map +1 -1
  150. package/presentation/contentModels/components/CloneContentModelDialog.d.ts +2 -2
  151. package/presentation/contentModels/components/ContentModels.d.ts +2 -2
  152. package/presentation/contentModels/components/ContentModelsDataList.d.ts +2 -2
  153. package/presentation/contentModels/components/NewContentModelDialog.d.ts +2 -2
  154. package/presentation/contentModels/components/fullDelete/types.js.map +1 -1
  155. package/presentation/fieldEditor/FieldEditorPresenter.js +1 -1
  156. package/presentation/fieldEditor/FieldEditorPresenter.js.map +1 -1
  157. package/presentation/fieldEditor/groups/ValidationsGroup.js +1 -1
  158. package/presentation/fieldEditor/groups/ValidationsGroup.js.map +1 -1
  159. package/presentation/fieldEditor/renderers/CmsAccessControlRulesRenderer.js +3 -3
  160. package/presentation/fieldEditor/renderers/CmsAccessControlRulesRenderer.js.map +1 -1
  161. package/presentation/fieldRenderers/ref/CmsRefDetailedMultipleRenderer.js +8 -0
  162. package/presentation/fieldRenderers/ref/CmsRefDetailedMultipleRenderer.js.map +1 -1
  163. package/presentation/fieldRenderers/ref/CmsRefDetailedSingleRenderer.js +8 -0
  164. package/presentation/fieldRenderers/ref/CmsRefDetailedSingleRenderer.js.map +1 -1
  165. package/presentation/fieldRenderers/ref/components/EditEntryDrawer.d.ts +10 -0
  166. package/presentation/fieldRenderers/ref/components/EditEntryDrawer.js +94 -0
  167. package/presentation/fieldRenderers/ref/components/EditEntryDrawer.js.map +1 -0
  168. package/presentation/fieldRenderers/ref/components/EntryCard.d.ts +2 -0
  169. package/presentation/fieldRenderers/ref/components/EntryCard.js +13 -3
  170. package/presentation/fieldRenderers/ref/components/EntryCard.js.map +1 -1
  171. package/presentation/fieldRenderers/ref/components/RefFieldOptions.d.ts +2 -2
  172. package/presentation/fieldRenderers/ref/detailed/RefDetailedPresenter.d.ts +2 -1
  173. package/presentation/fieldRenderers/ref/detailed/RefDetailedPresenter.js +6 -0
  174. package/presentation/fieldRenderers/ref/detailed/RefDetailedPresenter.js.map +1 -1
  175. package/presentation/fieldRenderers/ref/detailed/abstractions.d.ts +2 -1
  176. package/presentation/fieldRenderers/ref/detailed/abstractions.js.map +1 -1
  177. package/presentation/fieldRenderers/ref/editEntry/EditEntryPresenter.d.ts +13 -0
  178. package/presentation/fieldRenderers/ref/editEntry/EditEntryPresenter.js +25 -0
  179. package/presentation/fieldRenderers/ref/editEntry/EditEntryPresenter.js.map +1 -0
  180. package/presentation/fieldRenderers/ref/editEntry/abstractions.d.ts +10 -0
  181. package/presentation/fieldRenderers/ref/editEntry/abstractions.js +5 -0
  182. package/presentation/fieldRenderers/ref/editEntry/abstractions.js.map +1 -0
  183. package/presentation/fieldRenderers/ref/editEntry/feature.d.ts +3 -0
  184. package/presentation/fieldRenderers/ref/editEntry/feature.js +17 -0
  185. package/presentation/fieldRenderers/ref/editEntry/feature.js.map +1 -0
  186. package/presentation/fieldTypes/abstractions.d.ts +12 -0
  187. package/presentation/fieldTypes/abstractions.js.map +1 -1
  188. package/presentation/fieldTypes/renderers/common/SelectBoxRenderer.js +1 -1
  189. package/presentation/fieldTypes/renderers/common/SelectBoxRenderer.js.map +1 -1
  190. package/presentation/fieldTypes/renderers/dynamicZone/DynamicZoneRenderer.js +6 -2
  191. package/presentation/fieldTypes/renderers/dynamicZone/DynamicZoneRenderer.js.map +1 -1
  192. package/presentation/fieldTypes/renderers/object/ObjectAccordionRenderer.js +2 -0
  193. package/presentation/fieldTypes/renderers/object/ObjectAccordionRenderer.js.map +1 -1
  194. package/presentation/fieldTypes/renderers/object/ObjectsAccordionRenderer.js +6 -0
  195. package/presentation/fieldTypes/renderers/object/ObjectsAccordionRenderer.js.map +1 -1
  196. package/presentation/fieldTypes/types/DynamicZoneFieldType.d.ts +3 -6
  197. package/presentation/fieldTypes/types/DynamicZoneFieldType.js +2 -12
  198. package/presentation/fieldTypes/types/DynamicZoneFieldType.js.map +1 -1
  199. package/presentation/fieldTypes/types/dynamicZone/TemplateDialog.js +25 -3
  200. package/presentation/fieldTypes/types/dynamicZone/TemplateDialog.js.map +1 -1
  201. package/presentation/importContentModels/ImportContentModelsDialog.d.ts +2 -2
  202. package/presentation/importContentModels/components/DataList.d.ts +2 -2
  203. package/presentation/importContentModels/components/FileUpload.d.ts +2 -2
  204. package/presentation/importContentModels/components/Model/DataListModels.d.ts +2 -2
  205. package/presentation/menus/ContentGroupsMenuItems.d.ts +2 -2
  206. package/presentation/modelGroup/ModelGroupPresenter.d.ts +3 -1
  207. package/presentation/modelGroup/ModelGroupPresenter.js +7 -9
  208. package/presentation/modelGroup/ModelGroupPresenter.js.map +1 -1
  209. package/presentation/modelGroup/components/ContentModelGroups.d.ts +2 -2
  210. package/presentation/modelGroup/components/ContentModelGroupsDataList.d.ts +6 -2
  211. package/presentation/modelGroup/components/ContentModelGroupsForm.d.ts +8 -2
@@ -0,0 +1,181 @@
1
+ import react, { useCallback, useEffect, useRef, useState } from "react";
2
+ import { MessageOrigin, Messenger } from "@webiny/cms-sdk/messenger";
3
+ import { jsonPatch } from "@webiny/cms-sdk";
4
+ import { IconButton, Input, OverlayLoader, SegmentedControl } from "@webiny/admin-ui";
5
+ import { ReactComponent } from "@webiny/icons/refresh.svg";
6
+ import { ReactComponent as content_copy_svg_ReactComponent } from "@webiny/icons/content_copy.svg";
7
+ import { ReactComponent as laptop_svg_ReactComponent } from "@webiny/icons/laptop.svg";
8
+ import { ReactComponent as smartphone_svg_ReactComponent } from "@webiny/icons/smartphone.svg";
9
+ import { ReactComponent as open_in_new_svg_ReactComponent } from "@webiny/icons/open_in_new.svg";
10
+ import { useLivePreviewPresenter } from "./useLivePreviewPresenter.js";
11
+ import { buildDisplayUrl, buildEditorUrl } from "./resolvePreviewUrl.js";
12
+ const PreviewPane = ({ previewPrefix, previewSlug, entryId, entryData })=>{
13
+ const iframeRef = useRef(null);
14
+ const messengerRef = useRef(null);
15
+ const entryDataRef = useRef(entryData);
16
+ const lastSentDataRef = useRef(null);
17
+ const [ready, setReady] = useState(false);
18
+ const [loading, setLoading] = useState(true);
19
+ const [iframeKey, setIframeKey] = useState(0);
20
+ const [viewport, setViewport] = useState("desktop");
21
+ const presenter = useLivePreviewPresenter();
22
+ entryDataRef.current = entryData;
23
+ const displayUrl = buildDisplayUrl(previewPrefix, previewSlug, entryData || {});
24
+ const [address, setAddress] = useState(displayUrl);
25
+ useEffect(()=>{
26
+ setAddress(displayUrl);
27
+ }, [
28
+ displayUrl
29
+ ]);
30
+ const iframeSrc = (()=>{
31
+ const editorPath = buildEditorUrl(previewPrefix);
32
+ const url = new URL(editorPath);
33
+ url.searchParams.set("wb.editing", "true");
34
+ url.searchParams.set("wb.type", "entry");
35
+ url.searchParams.set("wb.id", entryId);
36
+ url.searchParams.set("wb.path", url.pathname);
37
+ url.searchParams.set("wb.referrer", window.location.origin);
38
+ return url.toString();
39
+ })();
40
+ const sendEntryData = useCallback(()=>{
41
+ const data = entryDataRef.current;
42
+ if (!data || !messengerRef.current) return;
43
+ const serialized = JSON.parse(JSON.stringify(data));
44
+ messengerRef.current.send("document.set", serialized);
45
+ lastSentDataRef.current = serialized;
46
+ }, []);
47
+ useEffect(()=>{
48
+ const iframe = iframeRef.current;
49
+ if (!iframe || !iframe.contentWindow) return;
50
+ const targetOrigin = new URL(iframe.src).origin;
51
+ const editorOrigin = new MessageOrigin(()=>window, window.location.origin);
52
+ const previewTarget = new MessageOrigin(()=>iframe.contentWindow, targetOrigin);
53
+ const messenger = new Messenger(editorOrigin, previewTarget, "wb.editor.*");
54
+ messengerRef.current = messenger;
55
+ messenger.on("preview.ready", ()=>{
56
+ setReady(true);
57
+ setLoading(false);
58
+ sendEntryData();
59
+ });
60
+ messenger.on("preview.component.register", (manifest)=>{
61
+ presenter.addComponent(manifest);
62
+ });
63
+ return ()=>{
64
+ messenger.dispose();
65
+ messengerRef.current = null;
66
+ lastSentDataRef.current = null;
67
+ setReady(false);
68
+ };
69
+ }, [
70
+ iframeSrc,
71
+ presenter,
72
+ iframeKey,
73
+ sendEntryData
74
+ ]);
75
+ useEffect(()=>{
76
+ if (!ready || !entryData || !messengerRef.current) return;
77
+ const current = JSON.parse(JSON.stringify(entryData));
78
+ const previous = lastSentDataRef.current;
79
+ if (previous) {
80
+ const patch = jsonPatch.compare(previous, current);
81
+ if (patch.length > 0) messengerRef.current.send("document.patch", patch);
82
+ } else messengerRef.current.send("document.set", current);
83
+ lastSentDataRef.current = current;
84
+ }, [
85
+ ready,
86
+ entryData
87
+ ]);
88
+ const reload = useCallback(()=>{
89
+ setLoading(true);
90
+ setReady(false);
91
+ lastSentDataRef.current = null;
92
+ setIframeKey((prev)=>prev + 1);
93
+ }, []);
94
+ const getDraftUrl = useCallback(()=>{
95
+ const url = new URL(displayUrl);
96
+ url.searchParams.set("wb.type", "entry");
97
+ url.searchParams.set("wb.path", url.pathname);
98
+ url.searchParams.set("wb.preview", "true");
99
+ url.searchParams.set("wb.id", entryId);
100
+ return url.toString();
101
+ }, [
102
+ displayUrl,
103
+ entryId
104
+ ]);
105
+ const copyUrl = useCallback(()=>{
106
+ navigator.clipboard.writeText(getDraftUrl());
107
+ }, [
108
+ getDraftUrl
109
+ ]);
110
+ const openInNewTab = useCallback(()=>{
111
+ window.open(getDraftUrl(), "_blank");
112
+ }, [
113
+ getDraftUrl
114
+ ]);
115
+ return /*#__PURE__*/ react.createElement("div", {
116
+ className: "relative border border-neutral-dimmed rounded-t-lg flex flex-col flex-1 h-full overflow-hidden"
117
+ }, /*#__PURE__*/ react.createElement("div", {
118
+ className: "flex p-md items-center bg-white border-b border-neutral-dimmed"
119
+ }, /*#__PURE__*/ react.createElement("div", {
120
+ className: "w-full"
121
+ }, /*#__PURE__*/ react.createElement(Input, {
122
+ value: address,
123
+ onChange: setAddress,
124
+ readOnly: true,
125
+ size: "md",
126
+ variant: "secondary",
127
+ className: "bg-gray-100"
128
+ })), /*#__PURE__*/ react.createElement("div", {
129
+ className: "flex items-center gap-xxs ml-sm"
130
+ }, /*#__PURE__*/ react.createElement(IconButton, {
131
+ onClick: openInNewTab,
132
+ icon: /*#__PURE__*/ react.createElement(open_in_new_svg_ReactComponent, null),
133
+ variant: "ghost",
134
+ size: "md"
135
+ }), /*#__PURE__*/ react.createElement(IconButton, {
136
+ onClick: copyUrl,
137
+ icon: /*#__PURE__*/ react.createElement(content_copy_svg_ReactComponent, null),
138
+ variant: "ghost",
139
+ size: "sm"
140
+ }), /*#__PURE__*/ react.createElement(IconButton, {
141
+ onClick: reload,
142
+ icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
143
+ variant: "ghost",
144
+ size: "sm"
145
+ }), /*#__PURE__*/ react.createElement(SegmentedControl, {
146
+ value: viewport,
147
+ onChange: (value)=>setViewport(value),
148
+ items: [
149
+ {
150
+ value: "desktop",
151
+ label: "",
152
+ icon: /*#__PURE__*/ react.createElement(laptop_svg_ReactComponent, null)
153
+ },
154
+ {
155
+ value: "mobile",
156
+ label: "",
157
+ icon: /*#__PURE__*/ react.createElement(smartphone_svg_ReactComponent, null)
158
+ }
159
+ ]
160
+ }))), /*#__PURE__*/ react.createElement("div", {
161
+ className: "block box-border h-full w-full overflow-auto fill-grid"
162
+ }, loading ? /*#__PURE__*/ react.createElement(OverlayLoader, {
163
+ text: "Connecting to Live Preview..."
164
+ }) : null, /*#__PURE__*/ react.createElement("div", {
165
+ className: `mx-auto h-full transition-all duration-300 ${"mobile" === viewport ? "p-md" : ""}`,
166
+ style: {
167
+ width: "mobile" === viewport ? "375px" : "100%"
168
+ }
169
+ }, /*#__PURE__*/ react.createElement("iframe", {
170
+ key: iframeKey,
171
+ ref: iframeRef,
172
+ src: iframeSrc,
173
+ width: "100%",
174
+ height: "100%",
175
+ className: "h-full",
176
+ sandbox: "allow-same-origin allow-scripts allow-forms"
177
+ }))));
178
+ };
179
+ export { PreviewPane };
180
+
181
+ //# sourceMappingURL=PreviewPane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/contentEntries/preview/PreviewPane.js","sources":["../../../../src/presentation/contentEntries/preview/PreviewPane.tsx"],"sourcesContent":["import React, { useRef, useEffect, useCallback, useState } from \"react\";\nimport { Messenger, MessageOrigin } from \"@webiny/cms-sdk/messenger\";\nimport { jsonPatch } from \"@webiny/cms-sdk\";\nimport { IconButton, Input, OverlayLoader, SegmentedControl } from \"@webiny/admin-ui\";\nimport { ReactComponent as RefreshIcon } from \"@webiny/icons/refresh.svg\";\nimport { ReactComponent as ContentCopyIcon } from \"@webiny/icons/content_copy.svg\";\nimport { ReactComponent as LaptopIcon } from \"@webiny/icons/laptop.svg\";\nimport { ReactComponent as SmartphoneIcon } from \"@webiny/icons/smartphone.svg\";\nimport { ReactComponent as OpenInNewIcon } from \"@webiny/icons/open_in_new.svg\";\nimport { useLivePreviewPresenter } from \"./useLivePreviewPresenter.js\";\nimport { buildEditorUrl, buildDisplayUrl } from \"./resolvePreviewUrl.js\";\n\ninterface PreviewPaneProps {\n previewPrefix: string;\n previewSlug: string;\n entryId: string;\n entryData: Record<string, unknown> | null;\n}\n\ntype ViewportMode = \"desktop\" | \"mobile\";\n\nexport const PreviewPane = ({\n previewPrefix,\n previewSlug,\n entryId,\n entryData\n}: PreviewPaneProps) => {\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const messengerRef = useRef<Messenger | null>(null);\n const entryDataRef = useRef(entryData);\n const lastSentDataRef = useRef<Record<string, unknown> | null>(null);\n const [ready, setReady] = useState(false);\n const [loading, setLoading] = useState(true);\n const [iframeKey, setIframeKey] = useState(0);\n const [viewport, setViewport] = useState<ViewportMode>(\"desktop\");\n const presenter = useLivePreviewPresenter();\n\n entryDataRef.current = entryData;\n\n const displayUrl = buildDisplayUrl(\n previewPrefix,\n previewSlug,\n (entryData as Record<string, unknown>) || {}\n );\n\n const [address, setAddress] = useState(displayUrl);\n\n useEffect(() => {\n setAddress(displayUrl);\n }, [displayUrl]);\n\n const iframeSrc = (() => {\n const editorPath = buildEditorUrl(previewPrefix);\n const url = new URL(editorPath);\n url.searchParams.set(\"wb.editing\", \"true\");\n url.searchParams.set(\"wb.type\", \"entry\");\n url.searchParams.set(\"wb.id\", entryId);\n url.searchParams.set(\"wb.path\", url.pathname);\n url.searchParams.set(\"wb.referrer\", window.location.origin);\n return url.toString();\n })();\n\n const sendEntryData = useCallback(() => {\n const data = entryDataRef.current;\n if (!data || !messengerRef.current) {\n return;\n }\n\n const serialized = JSON.parse(JSON.stringify(data));\n messengerRef.current.send(\"document.set\", serialized);\n lastSentDataRef.current = serialized;\n }, []);\n\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe || !iframe.contentWindow) {\n return;\n }\n\n const targetOrigin = new URL(iframe.src).origin;\n const editorOrigin = new MessageOrigin(() => window, window.location.origin);\n const previewTarget = new MessageOrigin(() => iframe.contentWindow!, targetOrigin);\n\n const messenger = new Messenger(editorOrigin, previewTarget, \"wb.editor.*\");\n messengerRef.current = messenger;\n\n messenger.on(\"preview.ready\", () => {\n setReady(true);\n setLoading(false);\n sendEntryData();\n });\n\n messenger.on(\n \"preview.component.register\",\n (manifest: { name: string; label: string; description: string }) => {\n presenter.addComponent(manifest);\n }\n );\n\n return () => {\n messenger.dispose();\n messengerRef.current = null;\n lastSentDataRef.current = null;\n setReady(false);\n };\n }, [iframeSrc, presenter, iframeKey, sendEntryData]);\n\n useEffect(() => {\n if (!ready || !entryData || !messengerRef.current) {\n return;\n }\n\n const current = JSON.parse(JSON.stringify(entryData));\n const previous = lastSentDataRef.current;\n\n if (previous) {\n const patch = jsonPatch.compare(previous, current);\n if (patch.length > 0) {\n messengerRef.current.send(\"document.patch\", patch);\n }\n } else {\n messengerRef.current.send(\"document.set\", current);\n }\n\n lastSentDataRef.current = current;\n }, [ready, entryData]);\n\n const reload = useCallback(() => {\n setLoading(true);\n setReady(false);\n lastSentDataRef.current = null;\n setIframeKey(prev => prev + 1);\n }, []);\n\n const getDraftUrl = useCallback(() => {\n const url = new URL(displayUrl);\n url.searchParams.set(\"wb.type\", \"entry\");\n url.searchParams.set(\"wb.path\", url.pathname);\n url.searchParams.set(\"wb.preview\", \"true\");\n url.searchParams.set(\"wb.id\", entryId);\n return url.toString();\n }, [displayUrl, entryId]);\n\n const copyUrl = useCallback(() => {\n navigator.clipboard.writeText(getDraftUrl());\n }, [getDraftUrl]);\n\n const openInNewTab = useCallback(() => {\n window.open(getDraftUrl(), \"_blank\");\n }, [getDraftUrl]);\n\n return (\n <div className=\"relative border border-neutral-dimmed rounded-t-lg flex flex-col flex-1 h-full overflow-hidden\">\n <div className=\"flex p-md items-center bg-white border-b border-neutral-dimmed\">\n <div className=\"w-full\">\n <Input\n value={address}\n onChange={setAddress}\n readOnly\n size=\"md\"\n variant={\"secondary\"}\n className=\"bg-gray-100\"\n />\n </div>\n\n <div className=\"flex items-center gap-xxs ml-sm\">\n <IconButton\n onClick={openInNewTab}\n icon={<OpenInNewIcon />}\n variant=\"ghost\"\n size=\"md\"\n />\n <IconButton\n onClick={copyUrl}\n icon={<ContentCopyIcon />}\n variant=\"ghost\"\n size=\"sm\"\n />\n <IconButton onClick={reload} icon={<RefreshIcon />} variant=\"ghost\" size=\"sm\" />\n <SegmentedControl\n value={viewport}\n onChange={(value: string) => setViewport(value as ViewportMode)}\n items={[\n { value: \"desktop\", label: \"\", icon: <LaptopIcon /> },\n { value: \"mobile\", label: \"\", icon: <SmartphoneIcon /> }\n ]}\n />\n </div>\n </div>\n\n <div className=\"block box-border h-full w-full overflow-auto fill-grid\">\n {loading ? <OverlayLoader text=\"Connecting to Live Preview...\" /> : null}\n <div\n className={`mx-auto h-full transition-all duration-300 ${viewport === \"mobile\" ? \"p-md\" : \"\"}`}\n style={{ width: viewport === \"mobile\" ? \"375px\" : \"100%\" }}\n >\n <iframe\n key={iframeKey}\n ref={iframeRef}\n src={iframeSrc}\n width=\"100%\"\n height=\"100%\"\n className=\"h-full\"\n sandbox=\"allow-same-origin allow-scripts allow-forms\"\n />\n </div>\n </div>\n </div>\n );\n};\n"],"names":["PreviewPane","previewPrefix","previewSlug","entryId","entryData","iframeRef","useRef","messengerRef","entryDataRef","lastSentDataRef","ready","setReady","useState","loading","setLoading","iframeKey","setIframeKey","viewport","setViewport","presenter","useLivePreviewPresenter","displayUrl","buildDisplayUrl","address","setAddress","useEffect","iframeSrc","editorPath","buildEditorUrl","url","URL","window","sendEntryData","useCallback","data","serialized","JSON","iframe","targetOrigin","editorOrigin","MessageOrigin","previewTarget","messenger","Messenger","manifest","current","previous","patch","jsonPatch","reload","prev","getDraftUrl","copyUrl","navigator","openInNewTab","Input","IconButton","OpenInNewIcon","ContentCopyIcon","RefreshIcon","SegmentedControl","value","LaptopIcon","SmartphoneIcon","OverlayLoader"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface PreviewComponent {
2
+ name: string;
3
+ label: string;
4
+ description: string;
5
+ }
6
+ export interface ILivePreviewPresenter {
7
+ vm: {
8
+ components: PreviewComponent[];
9
+ };
10
+ addComponent(component: PreviewComponent): void;
11
+ clearComponents(): void;
12
+ }
13
+ export declare const LivePreviewPresenter: import("@webiny/di").Abstraction<ILivePreviewPresenter>;
14
+ export declare namespace LivePreviewPresenter {
15
+ type Interface = ILivePreviewPresenter;
16
+ }
@@ -0,0 +1,5 @@
1
+ import { createAbstraction } from "@webiny/feature/admin";
2
+ const LivePreviewPresenter = createAbstraction("CmsContentEntries/LivePreviewPresenter");
3
+ export { LivePreviewPresenter };
4
+
5
+ //# sourceMappingURL=abstractions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/contentEntries/preview/abstractions.js","sources":["../../../../src/presentation/contentEntries/preview/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\n\nexport interface PreviewComponent {\n name: string;\n label: string;\n description: string;\n}\n\nexport interface ILivePreviewPresenter {\n vm: {\n components: PreviewComponent[];\n };\n addComponent(component: PreviewComponent): void;\n clearComponents(): void;\n}\n\nexport const LivePreviewPresenter = createAbstraction<ILivePreviewPresenter>(\n \"CmsContentEntries/LivePreviewPresenter\"\n);\n\nexport namespace LivePreviewPresenter {\n export type Interface = ILivePreviewPresenter;\n}\n"],"names":["LivePreviewPresenter","createAbstraction"],"mappings":";AAgBO,MAAMA,uBAAuBC,kBAChC"}
@@ -0,0 +1,3 @@
1
+ export declare const LivePreviewFeature: import("@webiny/feature/admin").FeatureDefinition<{
2
+ presenter: import("./abstractions.js").ILivePreviewPresenter;
3
+ }, []>;
@@ -0,0 +1,17 @@
1
+ import { createFeature } from "@webiny/feature/admin";
2
+ import { LivePreviewPresenter } from "./abstractions.js";
3
+ import { LivePreviewPresenter as external_LivePreviewPresenter_js_LivePreviewPresenter } from "./LivePreviewPresenter.js";
4
+ const LivePreviewFeature = createFeature({
5
+ name: "CmsContentEntries/LivePreview",
6
+ register (container) {
7
+ container.register(external_LivePreviewPresenter_js_LivePreviewPresenter).inSingletonScope();
8
+ },
9
+ resolve (container) {
10
+ return {
11
+ presenter: container.resolve(LivePreviewPresenter)
12
+ };
13
+ }
14
+ });
15
+ export { LivePreviewFeature };
16
+
17
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/contentEntries/preview/feature.js","sources":["../../../../src/presentation/contentEntries/preview/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/admin\";\nimport { LivePreviewPresenter as Abstraction } from \"./abstractions.js\";\nimport { LivePreviewPresenter } from \"./LivePreviewPresenter.js\";\n\nexport const LivePreviewFeature = createFeature({\n name: \"CmsContentEntries/LivePreview\",\n register(container) {\n container.register(LivePreviewPresenter).inSingletonScope();\n },\n resolve(container) {\n return {\n presenter: container.resolve(Abstraction)\n };\n }\n});\n"],"names":["LivePreviewFeature","createFeature","container","LivePreviewPresenter","Abstraction"],"mappings":";;;AAIO,MAAMA,qBAAqBC,cAAc;IAC5C,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC,uDAAsB,gBAAgB;IAC7D;IACA,SAAQD,SAAS;QACb,OAAO;YACH,WAAWA,UAAU,OAAO,CAACE;QACjC;IACJ;AACJ"}
@@ -0,0 +1,5 @@
1
+ type EntryData = Record<string, unknown>;
2
+ export declare function resolveSlugPattern(pattern: string, entry: EntryData): string;
3
+ export declare function buildEditorUrl(prefix: string): string;
4
+ export declare function buildDisplayUrl(prefix: string, slugPattern: string, entry: EntryData): string;
5
+ export {};
@@ -0,0 +1,29 @@
1
+ function getNestedValue(obj, path) {
2
+ const parts = path.split(".");
3
+ let current = obj;
4
+ for (const part of parts){
5
+ if (null == current || "object" != typeof current) return;
6
+ current = current[part];
7
+ }
8
+ return current;
9
+ }
10
+ function resolveSlugPattern(pattern, entry) {
11
+ return pattern.replace(/\{([^}]+)\}/g, (_match, path)=>{
12
+ const value = getNestedValue(entry, path);
13
+ if (null != value && "" !== value) return String(value);
14
+ return "";
15
+ });
16
+ }
17
+ function buildEditorUrl(prefix) {
18
+ const base = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
19
+ return `${base}/preview`;
20
+ }
21
+ function buildDisplayUrl(prefix, slugPattern, entry) {
22
+ const base = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
23
+ const slug = resolveSlugPattern(slugPattern, entry);
24
+ if (!slug) return base;
25
+ return `${base}/${slug}`;
26
+ }
27
+ export { buildDisplayUrl, buildEditorUrl, resolveSlugPattern };
28
+
29
+ //# sourceMappingURL=resolvePreviewUrl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/contentEntries/preview/resolvePreviewUrl.js","sources":["../../../../src/presentation/contentEntries/preview/resolvePreviewUrl.ts"],"sourcesContent":["type EntryData = Record<string, unknown>;\n\nfunction getNestedValue(obj: EntryData, path: string): unknown {\n const parts = path.split(\".\");\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== \"object\") {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\nexport function resolveSlugPattern(pattern: string, entry: EntryData): string {\n return pattern.replace(/\\{([^}]+)\\}/g, (_match, path: string) => {\n const value = getNestedValue(entry, path);\n if (value !== null && value !== undefined && value !== \"\") {\n return String(value);\n }\n return \"\";\n });\n}\n\nexport function buildEditorUrl(prefix: string): string {\n const base = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n return `${base}/preview`;\n}\n\nexport function buildDisplayUrl(prefix: string, slugPattern: string, entry: EntryData): string {\n const base = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const slug = resolveSlugPattern(slugPattern, entry);\n if (!slug) {\n return base;\n }\n return `${base}/${slug}`;\n}\n"],"names":["getNestedValue","obj","path","parts","current","part","resolveSlugPattern","pattern","entry","_match","value","String","buildEditorUrl","prefix","base","buildDisplayUrl","slugPattern","slug"],"mappings":"AAEA,SAASA,eAAeC,GAAc,EAAEC,IAAY;IAChD,MAAMC,QAAQD,KAAK,KAAK,CAAC;IACzB,IAAIE,UAAmBH;IACvB,KAAK,MAAMI,QAAQF,MAAO;QACtB,IAAIC,QAAAA,WAA6C,AAAmB,YAAnB,OAAOA,SACpD;QAEJA,UAAWA,OAAmC,CAACC,KAAK;IACxD;IACA,OAAOD;AACX;AAEO,SAASE,mBAAmBC,OAAe,EAAEC,KAAgB;IAChE,OAAOD,QAAQ,OAAO,CAAC,gBAAgB,CAACE,QAAQP;QAC5C,MAAMQ,QAAQV,eAAeQ,OAAON;QACpC,IAAIQ,QAAAA,SAAyCA,AAAU,OAAVA,OACzC,OAAOC,OAAOD;QAElB,OAAO;IACX;AACJ;AAEO,SAASE,eAAeC,MAAc;IACzC,MAAMC,OAAOD,OAAO,QAAQ,CAAC,OAAOA,OAAO,KAAK,CAAC,GAAG,MAAMA;IAC1D,OAAO,GAAGC,KAAK,QAAQ,CAAC;AAC5B;AAEO,SAASC,gBAAgBF,MAAc,EAAEG,WAAmB,EAAER,KAAgB;IACjF,MAAMM,OAAOD,OAAO,QAAQ,CAAC,OAAOA,OAAO,KAAK,CAAC,GAAG,MAAMA;IAC1D,MAAMI,OAAOX,mBAAmBU,aAAaR;IAC7C,IAAI,CAACS,MACD,OAAOH;IAEX,OAAO,GAAGA,KAAK,CAAC,EAAEG,MAAM;AAC5B"}
@@ -0,0 +1 @@
1
+ export declare function useLivePreviewPresenter(): import("./abstractions.js").ILivePreviewPresenter;
@@ -0,0 +1,8 @@
1
+ import { useFeature } from "@webiny/app";
2
+ import { LivePreviewFeature } from "./feature.js";
3
+ function useLivePreviewPresenter() {
4
+ return useFeature(LivePreviewFeature).presenter;
5
+ }
6
+ export { useLivePreviewPresenter };
7
+
8
+ //# sourceMappingURL=useLivePreviewPresenter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/contentEntries/preview/useLivePreviewPresenter.js","sources":["../../../../src/presentation/contentEntries/preview/useLivePreviewPresenter.ts"],"sourcesContent":["import { useFeature } from \"@webiny/app\";\nimport { LivePreviewFeature } from \"./feature.js\";\n\nexport function useLivePreviewPresenter() {\n return useFeature(LivePreviewFeature).presenter;\n}\n"],"names":["useLivePreviewPresenter","useFeature","LivePreviewFeature"],"mappings":";;AAGO,SAASA;IACZ,OAAOC,WAAWC,oBAAoB,SAAS;AACnD"}
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const CmsTrashBin: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const CmsTrashBin: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const CmsAdvancedSearch: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const CmsAdvancedSearch: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ /**
3
+ * Emits the content-entries trail (`<root> › <Model> › <folder path>`) through the React
4
+ * Config API. Model and folder path come from the scoped presenter, so this is a plain
5
+ * observer that renders `<Breadcrumb>` entries; the header marks the last as current.
6
+ *
7
+ * The leading root defaults to "Headless CMS" but can be overridden per app via the entries
8
+ * list config (`Browser.BreadcrumbRoot`) — e.g. Tenant Manager, which reuses this view for the
9
+ * tenant model, shows "Tenant Manager" instead.
10
+ */
11
+ export declare const ContentEntriesBreadcrumbs: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
12
+ readonly type: () => React.JSX.Element;
13
+ };
@@ -0,0 +1,54 @@
1
+ import react from "react";
2
+ import { observer } from "mobx-react-lite";
3
+ import { Breadcrumb } from "@webiny/app-admin";
4
+ import { useContentEntriesPresenter } from "../list/useContentEntriesPresenter.js";
5
+ import { useContentEntryListConfig } from "../../../admin/config/contentEntries/list/ContentEntryListConfig.js";
6
+ import { Routes } from "../../../routes.js";
7
+ const ContentEntriesBreadcrumbs_ContentEntriesBreadcrumbs = observer(function() {
8
+ const presenter = useContentEntriesPresenter();
9
+ const { browser } = useContentEntryListConfig();
10
+ const model = presenter.vm.model;
11
+ const foldersPresenter = presenter.folders;
12
+ const folders = foldersPresenter.vm;
13
+ const root = browser.breadcrumbRoot ?? {
14
+ label: "Headless CMS",
15
+ to: {
16
+ route: Routes.ContentModels.List
17
+ }
18
+ };
19
+ const ancestorIds = folders.currentFolderId ? [
20
+ ...foldersPresenter.getAncestorIds(folders.currentFolderId)
21
+ ].reverse() : [];
22
+ const titleById = new Map(folders.folders.map((folder)=>[
23
+ folder.id,
24
+ folder.title
25
+ ]));
26
+ return /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(Breadcrumb, {
27
+ name: "cms",
28
+ label: root.label,
29
+ to: root.to
30
+ }), /*#__PURE__*/ react.createElement(Breadcrumb, {
31
+ name: "cms.model",
32
+ label: model.name,
33
+ to: {
34
+ route: Routes.ContentEntries.List,
35
+ params: {
36
+ modelId: model.modelId
37
+ }
38
+ }
39
+ }), ancestorIds.map((id)=>/*#__PURE__*/ react.createElement(Breadcrumb, {
40
+ key: id,
41
+ name: id,
42
+ label: titleById.get(id) ?? "…",
43
+ to: {
44
+ route: Routes.ContentEntries.List,
45
+ params: {
46
+ modelId: model.modelId,
47
+ folderId: id
48
+ }
49
+ }
50
+ })));
51
+ });
52
+ export { ContentEntriesBreadcrumbs_ContentEntriesBreadcrumbs as ContentEntriesBreadcrumbs };
53
+
54
+ //# sourceMappingURL=ContentEntriesBreadcrumbs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/contentEntries/views/ContentEntriesBreadcrumbs.js","sources":["../../../../src/presentation/contentEntries/views/ContentEntriesBreadcrumbs.tsx"],"sourcesContent":["import React from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { Breadcrumb } from \"@webiny/app-admin\";\nimport { useContentEntriesPresenter } from \"~/presentation/contentEntries/list/useContentEntriesPresenter.js\";\nimport { useContentEntryListConfig } from \"~/admin/config/contentEntries/list/ContentEntryListConfig.js\";\nimport { Routes } from \"~/routes.js\";\n\n/**\n * Emits the content-entries trail (`<root> › <Model> › <folder path>`) through the React\n * Config API. Model and folder path come from the scoped presenter, so this is a plain\n * observer that renders `<Breadcrumb>` entries; the header marks the last as current.\n *\n * The leading root defaults to \"Headless CMS\" but can be overridden per app via the entries\n * list config (`Browser.BreadcrumbRoot`) — e.g. Tenant Manager, which reuses this view for the\n * tenant model, shows \"Tenant Manager\" instead.\n */\nexport const ContentEntriesBreadcrumbs = observer(function ContentEntriesBreadcrumbs() {\n const presenter = useContentEntriesPresenter();\n const { browser } = useContentEntryListConfig();\n const model = presenter.vm.model;\n const foldersPresenter = presenter.folders;\n const folders = foldersPresenter.vm;\n\n const root = browser.breadcrumbRoot ?? {\n label: \"Headless CMS\",\n to: { route: Routes.ContentModels.List }\n };\n\n // `getAncestorIds` walks self → root; reverse it to render root → current.\n const ancestorIds = folders.currentFolderId\n ? [...foldersPresenter.getAncestorIds(folders.currentFolderId)].reverse()\n : [];\n const titleById = new Map(folders.folders.map(folder => [folder.id, folder.title]));\n\n return (\n <>\n <Breadcrumb name={\"cms\"} label={root.label} to={root.to} />\n <Breadcrumb\n name={\"cms.model\"}\n label={model.name}\n to={{ route: Routes.ContentEntries.List, params: { modelId: model.modelId } }}\n />\n {ancestorIds.map(id => (\n <Breadcrumb\n key={id}\n name={id}\n label={titleById.get(id) ?? \"…\"}\n to={{\n route: Routes.ContentEntries.List,\n params: { modelId: model.modelId, folderId: id }\n }}\n />\n ))}\n </>\n );\n});\n"],"names":["ContentEntriesBreadcrumbs","observer","presenter","useContentEntriesPresenter","browser","useContentEntryListConfig","model","foldersPresenter","folders","root","Routes","ancestorIds","titleById","Map","folder","Breadcrumb","id"],"mappings":";;;;;;AAgBO,MAAMA,sDAA4BC,SAAS;IAC9C,MAAMC,YAAYC;IAClB,MAAM,EAAEC,OAAO,EAAE,GAAGC;IACpB,MAAMC,QAAQJ,UAAU,EAAE,CAAC,KAAK;IAChC,MAAMK,mBAAmBL,UAAU,OAAO;IAC1C,MAAMM,UAAUD,iBAAiB,EAAE;IAEnC,MAAME,OAAOL,QAAQ,cAAc,IAAI;QACnC,OAAO;QACP,IAAI;YAAE,OAAOM,OAAO,aAAa,CAAC,IAAI;QAAC;IAC3C;IAGA,MAAMC,cAAcH,QAAQ,eAAe,GACrC;WAAID,iBAAiB,cAAc,CAACC,QAAQ,eAAe;KAAE,CAAC,OAAO,KACrE,EAAE;IACR,MAAMI,YAAY,IAAIC,IAAIL,QAAQ,OAAO,CAAC,GAAG,CAACM,CAAAA,SAAU;YAACA,OAAO,EAAE;YAAEA,OAAO,KAAK;SAAC;IAEjF,OAAO,WAAP,GACI,wDACI,oBAACC,YAAUA;QAAC,MAAM;QAAO,OAAON,KAAK,KAAK;QAAE,IAAIA,KAAK,EAAE;sBACvD,oBAACM,YAAUA;QACP,MAAM;QACN,OAAOT,MAAM,IAAI;QACjB,IAAI;YAAE,OAAOI,OAAO,cAAc,CAAC,IAAI;YAAE,QAAQ;gBAAE,SAASJ,MAAM,OAAO;YAAC;QAAE;QAE/EK,YAAY,GAAG,CAACK,CAAAA,KAAAA,WAAAA,GACb,oBAACD,YAAUA;YACP,KAAKC;YACL,MAAMA;YACN,OAAOJ,UAAU,GAAG,CAACI,OAAO;YAC5B,IAAI;gBACA,OAAON,OAAO,cAAc,CAAC,IAAI;gBACjC,QAAQ;oBAAE,SAASJ,MAAM,OAAO;oBAAE,UAAUU;gBAAG;YACnD;;AAKpB"}
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const ContentEntriesListLayout: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const ContentEntriesListLayout: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -8,14 +8,14 @@ import { ReactComponent as folder_svg_ReactComponent } from "@webiny/icons/folde
8
8
  import { FolderTree } from "@webiny/app-aco/presentation/folderTree/FolderTree.js";
9
9
  import { useContentEntryListConfig } from "../../../admin/config/contentEntries/list/ContentEntryListConfig.js";
10
10
  import { useContentEntriesPresenter } from "../list/useContentEntriesPresenter.js";
11
+ import { ContentEntriesBreadcrumbs } from "./ContentEntriesBreadcrumbs.js";
11
12
  import { ContentEntryFormView } from "./ContentEntryFormView.js";
12
13
  import { Table } from "./Table/Table.js";
13
14
  import { CmsAdvancedSearch } from "./CmsAdvancedSearch.js";
14
15
  import { SidebarFooter } from "./SidebarFooter.js";
15
16
  const ContentEntriesListLayout = observer(()=>{
16
17
  const presenter = useContentEntriesPresenter();
17
- if (presenter.vm.showingEntry) return /*#__PURE__*/ react.createElement(ContentEntryFormView, null);
18
- return /*#__PURE__*/ react.createElement(DocumentList, null);
18
+ return /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(ContentEntriesBreadcrumbs, null), presenter.vm.showingEntry ? /*#__PURE__*/ react.createElement(ContentEntryFormView, null) : /*#__PURE__*/ react.createElement(DocumentList, null));
19
19
  });
20
20
  const DocumentList = observer(()=>{
21
21
  const presenter = useContentEntriesPresenter();
@@ -76,6 +76,7 @@ const DocumentList = observer(()=>{
76
76
  }),
77
77
  bulkActions: /*#__PURE__*/ react.createElement(ListView.BulkActions, {
78
78
  itemLabel: "entry",
79
+ itemLabelPlural: "entries",
79
80
  actions: browser.bulkActions
80
81
  }),
81
82
  filters: /*#__PURE__*/ react.createElement(ListView.Filters, {
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/contentEntries/views/ContentEntriesListLayout.js","sources":["../../../../src/presentation/contentEntries/views/ContentEntriesListLayout.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { useCreateDialog } from \"@webiny/app-aco\";\nimport { ListView, EmptyView } from \"@webiny/app-admin\";\nimport { Button } from \"@webiny/admin-ui\";\nimport { ReactComponent as HomeIcon } from \"@webiny/icons/home.svg\";\nimport { ReactComponent as FolderIcon } from \"@webiny/icons/folder.svg\";\nimport { FolderTree } from \"@webiny/app-aco/presentation/folderTree/FolderTree.js\";\nimport { useContentEntryListConfig } from \"~/admin/config/contentEntries/list/ContentEntryListConfig.js\";\nimport { useContentEntriesPresenter } from \"~/presentation/contentEntries/list/useContentEntriesPresenter.js\";\nimport { ContentEntryFormView } from \"./ContentEntryFormView.js\";\nimport { Table } from \"./Table/Table.js\";\nimport { CmsAdvancedSearch } from \"./CmsAdvancedSearch.js\";\nimport { SidebarFooter } from \"./SidebarFooter.js\";\n\nexport const ContentEntriesListLayout = observer(() => {\n const presenter = useContentEntriesPresenter();\n\n if (presenter.vm.showingEntry) {\n return <ContentEntryFormView />;\n }\n\n return <DocumentList />;\n});\n\nconst DocumentList = observer(() => {\n const presenter = useContentEntriesPresenter();\n const { browser } = useContentEntryListConfig();\n const { showDialog: showCreateFolderDialog } = useCreateDialog();\n\n const folderId = presenter.folders.vm.currentFolderId ?? \"root\";\n const isRoot = folderId === \"root\";\n const hasFolders = presenter.vm.showFolders && presenter.vm.childFolders.length > 0;\n\n const onCreateFolder = useCallback(() => {\n showCreateFolderDialog({ currentParentId: folderId });\n }, [folderId]);\n\n const onCreateEntry = useCallback(() => {\n presenter.createEntry();\n }, [presenter]);\n\n return (\n <ListView\n list={presenter.list.vm}\n actions={presenter.list.actions}\n namespace={`cms/${presenter.vm.model.modelId}/list`}\n showingFilters={presenter.list.vm.showingFilters}\n onToggleFilters={() => {\n presenter.list.vm.showingFilters\n ? presenter.list.actions.filter.hide()\n : presenter.list.actions.filter.show();\n }}\n sidebar={\n <ListView.Sidebar title={presenter.vm.model.name}>\n <ListView.Sidebar.Section grow>\n <FolderTree\n vm={presenter.folders.vm}\n actions={presenter.folders}\n folderActions={browser.folder.actions}\n enableActions={true}\n enableCreate={true}\n />\n </ListView.Sidebar.Section>\n <ListView.Sidebar.Section scrollable={false}>\n <SidebarFooter />\n </ListView.Sidebar.Section>\n </ListView.Sidebar>\n }\n header={\n <ListView.Header\n title={{\n icon: isRoot ? <HomeIcon /> : <FolderIcon />,\n text: isRoot ? \"Home\" : presenter.folders.vm.currentFolderTitle\n }}\n search\n filtersToggle\n actions={\n <>\n <Button\n variant={\"secondary\"}\n onClick={onCreateFolder}\n text={\"New Folder\"}\n />\n <Button\n variant={\"primary\"}\n onClick={onCreateEntry}\n text={\"New Entry\"}\n />\n </>\n }\n />\n }\n bulkActions={<ListView.BulkActions itemLabel=\"entry\" actions={browser.bulkActions} />}\n filters={\n <ListView.Filters filters={browser.filters} filtersToWhere={browser.filtersToWhere}>\n <CmsAdvancedSearch />\n </ListView.Filters>\n }\n content={\n <ListView.Content\n empty={\n hasFolders ? undefined : (\n <EmptyView\n title={\"No entries yet. Create your first entry.\"}\n action={\n <>\n <Button\n variant={\"secondary\"}\n onClick={onCreateFolder}\n text={\"New Folder\"}\n />\n <Button\n variant={\"primary\"}\n onClick={onCreateEntry}\n text={\"New Entry\"}\n />\n </>\n }\n />\n )\n }\n searchEmpty={<EmptyView title={\"No results found.\"} action={null} />}\n >\n <Table />\n </ListView.Content>\n }\n bottomBar={\n <ListView.BottomBar\n meta={{ itemLabel: { singular: \"entry\", plural: \"entries\" } }}\n status\n />\n }\n />\n );\n});\n"],"names":["ContentEntriesListLayout","observer","presenter","useContentEntriesPresenter","ContentEntryFormView","DocumentList","browser","useContentEntryListConfig","showCreateFolderDialog","useCreateDialog","folderId","isRoot","hasFolders","onCreateFolder","useCallback","onCreateEntry","ListView","FolderTree","SidebarFooter","HomeIcon","FolderIcon","Button","CmsAdvancedSearch","undefined","EmptyView","Table"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/contentEntries/views/ContentEntriesListLayout.js","sources":["../../../../src/presentation/contentEntries/views/ContentEntriesListLayout.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { useCreateDialog } from \"@webiny/app-aco\";\nimport { ListView, EmptyView } from \"@webiny/app-admin\";\nimport { Button } from \"@webiny/admin-ui\";\nimport { ReactComponent as HomeIcon } from \"@webiny/icons/home.svg\";\nimport { ReactComponent as FolderIcon } from \"@webiny/icons/folder.svg\";\nimport { FolderTree } from \"@webiny/app-aco/presentation/folderTree/FolderTree.js\";\nimport { useContentEntryListConfig } from \"~/admin/config/contentEntries/list/ContentEntryListConfig.js\";\nimport { useContentEntriesPresenter } from \"~/presentation/contentEntries/list/useContentEntriesPresenter.js\";\nimport { ContentEntriesBreadcrumbs } from \"./ContentEntriesBreadcrumbs.js\";\nimport { ContentEntryFormView } from \"./ContentEntryFormView.js\";\nimport { Table } from \"./Table/Table.js\";\nimport { CmsAdvancedSearch } from \"./CmsAdvancedSearch.js\";\nimport { SidebarFooter } from \"./SidebarFooter.js\";\n\nexport const ContentEntriesListLayout = observer(() => {\n const presenter = useContentEntriesPresenter();\n\n return (\n <>\n <ContentEntriesBreadcrumbs />\n {presenter.vm.showingEntry ? <ContentEntryFormView /> : <DocumentList />}\n </>\n );\n});\n\nconst DocumentList = observer(() => {\n const presenter = useContentEntriesPresenter();\n const { browser } = useContentEntryListConfig();\n const { showDialog: showCreateFolderDialog } = useCreateDialog();\n\n const folderId = presenter.folders.vm.currentFolderId ?? \"root\";\n const isRoot = folderId === \"root\";\n const hasFolders = presenter.vm.showFolders && presenter.vm.childFolders.length > 0;\n\n const onCreateFolder = useCallback(() => {\n showCreateFolderDialog({ currentParentId: folderId });\n }, [folderId]);\n\n const onCreateEntry = useCallback(() => {\n presenter.createEntry();\n }, [presenter]);\n\n return (\n <ListView\n list={presenter.list.vm}\n actions={presenter.list.actions}\n namespace={`cms/${presenter.vm.model.modelId}/list`}\n showingFilters={presenter.list.vm.showingFilters}\n onToggleFilters={() => {\n presenter.list.vm.showingFilters\n ? presenter.list.actions.filter.hide()\n : presenter.list.actions.filter.show();\n }}\n sidebar={\n <ListView.Sidebar title={presenter.vm.model.name}>\n <ListView.Sidebar.Section grow>\n <FolderTree\n vm={presenter.folders.vm}\n actions={presenter.folders}\n folderActions={browser.folder.actions}\n enableActions={true}\n enableCreate={true}\n />\n </ListView.Sidebar.Section>\n <ListView.Sidebar.Section scrollable={false}>\n <SidebarFooter />\n </ListView.Sidebar.Section>\n </ListView.Sidebar>\n }\n header={\n <ListView.Header\n title={{\n icon: isRoot ? <HomeIcon /> : <FolderIcon />,\n text: isRoot ? \"Home\" : presenter.folders.vm.currentFolderTitle\n }}\n search\n filtersToggle\n actions={\n <>\n <Button\n variant={\"secondary\"}\n onClick={onCreateFolder}\n text={\"New Folder\"}\n />\n <Button\n variant={\"primary\"}\n onClick={onCreateEntry}\n text={\"New Entry\"}\n />\n </>\n }\n />\n }\n bulkActions={\n <ListView.BulkActions\n itemLabel=\"entry\"\n itemLabelPlural=\"entries\"\n actions={browser.bulkActions}\n />\n }\n filters={\n <ListView.Filters filters={browser.filters} filtersToWhere={browser.filtersToWhere}>\n <CmsAdvancedSearch />\n </ListView.Filters>\n }\n content={\n <ListView.Content\n empty={\n hasFolders ? undefined : (\n <EmptyView\n title={\"No entries yet. Create your first entry.\"}\n action={\n <>\n <Button\n variant={\"secondary\"}\n onClick={onCreateFolder}\n text={\"New Folder\"}\n />\n <Button\n variant={\"primary\"}\n onClick={onCreateEntry}\n text={\"New Entry\"}\n />\n </>\n }\n />\n )\n }\n searchEmpty={<EmptyView title={\"No results found.\"} action={null} />}\n >\n <Table />\n </ListView.Content>\n }\n bottomBar={\n <ListView.BottomBar\n meta={{ itemLabel: { singular: \"entry\", plural: \"entries\" } }}\n status\n />\n }\n />\n );\n});\n"],"names":["ContentEntriesListLayout","observer","presenter","useContentEntriesPresenter","ContentEntriesBreadcrumbs","ContentEntryFormView","DocumentList","browser","useContentEntryListConfig","showCreateFolderDialog","useCreateDialog","folderId","isRoot","hasFolders","onCreateFolder","useCallback","onCreateEntry","ListView","FolderTree","SidebarFooter","HomeIcon","FolderIcon","Button","CmsAdvancedSearch","undefined","EmptyView","Table"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const ContentEntryFormView: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const ContentEntryFormView: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -17,7 +17,7 @@ const ContentEntryFormView = observer(()=>{
17
17
  const listPresenter = useContentEntriesPresenter();
18
18
  const formPresenter = useContentEntryFormPresenter();
19
19
  const { presenter: revisionsPresenter } = useFeature(RevisionsListFeature);
20
- const { width, newEntryWizard } = useContentEntryEditorConfig();
20
+ const { newEntryWizard, width } = useContentEntryEditorConfig();
21
21
  const router = useRouter();
22
22
  const dialogs = useDialogs();
23
23
  const { route } = useRoute(Routes.ContentEntries.List);
@@ -75,11 +75,10 @@ const ContentEntryFormView = observer(()=>{
75
75
  end: /*#__PURE__*/ react.createElement(EntryFormHeaderRight, null)
76
76
  }), /*#__PURE__*/ react.createElement(ScrollArea, null, vm.loading ? /*#__PURE__*/ react.createElement(OverlayLoader, {
77
77
  text: vm.loading
78
- }) : null, showWizard ? newEntryWizard : /*#__PURE__*/ react.createElement(ContentEntryFormContent, null, /*#__PURE__*/ react.createElement("div", {
79
- className: "bg-neutral-base rounded-lg p-lg",
80
- style: {
81
- width
82
- }
78
+ }) : null, showWizard ? newEntryWizard : /*#__PURE__*/ react.createElement(ContentEntryFormContent, {
79
+ width: width
80
+ }, /*#__PURE__*/ react.createElement("div", {
81
+ className: "bg-neutral-base rounded-lg p-lg"
83
82
  }, /*#__PURE__*/ react.createElement(ContentEntryForm, null)))), /*#__PURE__*/ react.createElement(RevisionDrawer, null));
84
83
  });
85
84
  const EntryFormHeaderLeft = ({ onBack, title, isNewEntry, modelName, status })=>/*#__PURE__*/ react.createElement("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/contentEntries/views/ContentEntryFormView.js","sources":["../../../../src/presentation/contentEntries/views/ContentEntryFormView.tsx"],"sourcesContent":["import React, { useEffect } from \"react\";\nimport { Helmet } from \"react-helmet\";\nimport { observer } from \"mobx-react-lite\";\nimport { useFeature, useRouter } from \"@webiny/app\";\nimport { Buttons, useDialogs, useRoute } from \"@webiny/app-admin\";\nimport { HeaderBar, Heading, Icon, IconButton, OverlayLoader, Tooltip } from \"@webiny/admin-ui\";\nimport { ReactComponent as BackIcon } from \"@webiny/icons/arrow_back.svg\";\nimport { ReactComponent as InfoIcon } from \"@webiny/icons/info.svg\";\nimport { useContentEntryEditorConfig } from \"~/admin/config/contentEntries/index.js\";\nimport { Routes } from \"~/routes.js\";\nimport {\n Container,\n ScrollArea,\n ContentEntryFormContent,\n ContentEntryForm\n} from \"./layout/index.js\";\nimport { RevisionsListFeature } from \"../revisionsList/feature.js\";\nimport { useContentEntriesPresenter } from \"~/presentation/contentEntries/list/useContentEntriesPresenter.js\";\nimport { useContentEntryFormPresenter } from \"~/presentation/contentEntries/form/useContentEntryFormPresenter.js\";\nimport { RevisionDrawer } from \"./RevisionDrawer.js\";\n\nexport const ContentEntryFormView = observer(() => {\n const listPresenter = useContentEntriesPresenter();\n const formPresenter = useContentEntryFormPresenter();\n const { presenter: revisionsPresenter } = useFeature(RevisionsListFeature);\n const { width, newEntryWizard } = useContentEntryEditorConfig();\n const router = useRouter();\n const dialogs = useDialogs();\n const { route } = useRoute(Routes.ContentEntries.List);\n\n const entryId = listPresenter.vm.selectedEntryId;\n const { vm } = formPresenter;\n\n const hasWizard = entryId === \"new\" && newEntryWizard !== null;\n const showWizard = hasWizard && vm.form === null;\n\n useEffect(() => {\n if (entryId === \"new\") {\n if (!newEntryWizard) {\n formPresenter.newEntry();\n }\n } else if (entryId) {\n formPresenter.loadRevision(entryId);\n revisionsPresenter.init(entryId);\n }\n\n return () => {\n formPresenter.reset();\n revisionsPresenter.dispose();\n };\n }, [entryId]);\n\n useEffect(() => {\n return router.addTransitionGuard({\n guard: () => formPresenter.vm.isDirty,\n onBlocked: () => {\n dialogs.showDialog({\n title: \"Confirm Navigation\",\n content:\n \"There are some unsaved changes! Are you sure you want to navigate away and discard all changes?\",\n acceptLabel: \"Yes!\",\n cancelLabel: \"No, stay here.\",\n onAccept: () => {\n // We must reset the form to prevent the guard from kicking in again.\n formPresenter.reset();\n router.confirmTransition();\n },\n onClose: () => router.cancelTransition()\n });\n }\n });\n }, []);\n\n const handleBack = () => {\n const { modelId, folderId } = route.params;\n router.goToRoute(Routes.ContentEntries.List, { modelId, folderId });\n };\n\n return (\n <Container>\n <Helmet title={vm.entry?.meta?.title || listPresenter.vm.model.name} />\n <HeaderBar\n start={\n <EntryFormHeaderLeft\n onBack={handleBack}\n title={vm.entry?.meta?.title || `New ${listPresenter.vm.model.name}`}\n isNewEntry={vm.isNewEntry}\n modelName={listPresenter.vm.model.name}\n status={vm.entry?.meta?.status ?? null}\n />\n }\n end={<EntryFormHeaderRight />}\n />\n <ScrollArea>\n {vm.loading ? <OverlayLoader text={vm.loading} /> : null}\n {showWizard ? (\n newEntryWizard\n ) : (\n <ContentEntryFormContent>\n <div className={\"bg-neutral-base rounded-lg p-lg\"} style={{ width }}>\n <ContentEntryForm />\n </div>\n </ContentEntryFormContent>\n )}\n </ScrollArea>\n <RevisionDrawer />\n </Container>\n );\n});\n\ninterface EntryFormHeaderLeftProps {\n onBack: () => void;\n title: string;\n isNewEntry: boolean;\n modelName: string;\n status: string | null;\n}\n\nconst EntryFormHeaderLeft = ({\n onBack,\n title,\n isNewEntry,\n modelName,\n status\n}: EntryFormHeaderLeftProps) => {\n return (\n <div className={\"flex items-center gap-sm\"}>\n <IconButton variant={\"ghost\"} onClick={onBack} icon={<BackIcon />} />\n <Heading level={5} className={`text-neutral-primary${isNewEntry ? \" opacity-50\" : \"\"}`}>\n {title}\n </Heading>\n <Tooltip\n content={`Model: ${modelName}${status ? ` - Status: ${status}` : \"\"}`}\n trigger={\n <Icon icon={<InfoIcon />} label={\"Info\"} size={\"sm\"} color={\"neutral-light\"} />\n }\n />\n </div>\n );\n};\n\nconst EntryFormHeaderRight = observer(() => {\n const presenter = useContentEntryFormPresenter();\n const { buttonActions } = useContentEntryEditorConfig();\n\n const { canSave, canPublish, canUnpublish, canDelete } = presenter.vm;\n\n if (!canSave && !canPublish && !canUnpublish && !canDelete) {\n return <div />;\n }\n\n return (\n <div className={\"flex items-center gap-sm\"}>\n <Buttons actions={buttonActions} />\n </div>\n );\n});\n"],"names":["ContentEntryFormView","observer","listPresenter","useContentEntriesPresenter","formPresenter","useContentEntryFormPresenter","revisionsPresenter","useFeature","RevisionsListFeature","width","newEntryWizard","useContentEntryEditorConfig","router","useRouter","dialogs","useDialogs","route","useRoute","Routes","entryId","vm","hasWizard","showWizard","useEffect","handleBack","modelId","folderId","Container","Helmet","HeaderBar","EntryFormHeaderLeft","EntryFormHeaderRight","ScrollArea","OverlayLoader","ContentEntryFormContent","ContentEntryForm","RevisionDrawer","onBack","title","isNewEntry","modelName","status","IconButton","BackIcon","Heading","Tooltip","Icon","InfoIcon","presenter","buttonActions","canSave","canPublish","canUnpublish","canDelete","Buttons"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/contentEntries/views/ContentEntryFormView.js","sources":["../../../../src/presentation/contentEntries/views/ContentEntryFormView.tsx"],"sourcesContent":["import React, { useEffect } from \"react\";\nimport { Helmet } from \"react-helmet\";\nimport { observer } from \"mobx-react-lite\";\nimport { useFeature, useRouter } from \"@webiny/app\";\nimport { Buttons, useDialogs, useRoute } from \"@webiny/app-admin\";\nimport { HeaderBar, Heading, Icon, IconButton, OverlayLoader, Tooltip } from \"@webiny/admin-ui\";\nimport { ReactComponent as BackIcon } from \"@webiny/icons/arrow_back.svg\";\nimport { ReactComponent as InfoIcon } from \"@webiny/icons/info.svg\";\nimport { useContentEntryEditorConfig } from \"~/admin/config/contentEntries/index.js\";\nimport { Routes } from \"~/routes.js\";\nimport {\n Container,\n ScrollArea,\n ContentEntryFormContent,\n ContentEntryForm\n} from \"./layout/index.js\";\nimport { RevisionsListFeature } from \"../revisionsList/feature.js\";\nimport { useContentEntriesPresenter } from \"~/presentation/contentEntries/list/useContentEntriesPresenter.js\";\nimport { useContentEntryFormPresenter } from \"~/presentation/contentEntries/form/useContentEntryFormPresenter.js\";\nimport { RevisionDrawer } from \"./RevisionDrawer.js\";\n\nexport const ContentEntryFormView = observer(() => {\n const listPresenter = useContentEntriesPresenter();\n const formPresenter = useContentEntryFormPresenter();\n const { presenter: revisionsPresenter } = useFeature(RevisionsListFeature);\n const { newEntryWizard, width } = useContentEntryEditorConfig();\n const router = useRouter();\n const dialogs = useDialogs();\n const { route } = useRoute(Routes.ContentEntries.List);\n\n const entryId = listPresenter.vm.selectedEntryId;\n const { vm } = formPresenter;\n\n const hasWizard = entryId === \"new\" && newEntryWizard !== null;\n const showWizard = hasWizard && vm.form === null;\n\n useEffect(() => {\n if (entryId === \"new\") {\n if (!newEntryWizard) {\n formPresenter.newEntry();\n }\n } else if (entryId) {\n formPresenter.loadRevision(entryId);\n revisionsPresenter.init(entryId);\n }\n\n return () => {\n formPresenter.reset();\n revisionsPresenter.dispose();\n };\n }, [entryId]);\n\n useEffect(() => {\n return router.addTransitionGuard({\n guard: () => formPresenter.vm.isDirty,\n onBlocked: () => {\n dialogs.showDialog({\n title: \"Confirm Navigation\",\n content:\n \"There are some unsaved changes! Are you sure you want to navigate away and discard all changes?\",\n acceptLabel: \"Yes!\",\n cancelLabel: \"No, stay here.\",\n onAccept: () => {\n // We must reset the form to prevent the guard from kicking in again.\n formPresenter.reset();\n router.confirmTransition();\n },\n onClose: () => router.cancelTransition()\n });\n }\n });\n }, []);\n\n const handleBack = () => {\n const { modelId, folderId } = route.params;\n router.goToRoute(Routes.ContentEntries.List, { modelId, folderId });\n };\n\n return (\n <Container>\n <Helmet title={vm.entry?.meta?.title || listPresenter.vm.model.name} />\n <HeaderBar\n start={\n <EntryFormHeaderLeft\n onBack={handleBack}\n title={vm.entry?.meta?.title || `New ${listPresenter.vm.model.name}`}\n isNewEntry={vm.isNewEntry}\n modelName={listPresenter.vm.model.name}\n status={vm.entry?.meta?.status ?? null}\n />\n }\n end={<EntryFormHeaderRight />}\n />\n <ScrollArea>\n {vm.loading ? <OverlayLoader text={vm.loading} /> : null}\n {showWizard ? (\n newEntryWizard\n ) : (\n <ContentEntryFormContent width={width}>\n <div className={\"bg-neutral-base rounded-lg p-lg\"}>\n <ContentEntryForm />\n </div>\n </ContentEntryFormContent>\n )}\n </ScrollArea>\n <RevisionDrawer />\n </Container>\n );\n});\n\ninterface EntryFormHeaderLeftProps {\n onBack: () => void;\n title: string;\n isNewEntry: boolean;\n modelName: string;\n status: string | null;\n}\n\nconst EntryFormHeaderLeft = ({\n onBack,\n title,\n isNewEntry,\n modelName,\n status\n}: EntryFormHeaderLeftProps) => {\n return (\n <div className={\"flex items-center gap-sm\"}>\n <IconButton variant={\"ghost\"} onClick={onBack} icon={<BackIcon />} />\n <Heading level={5} className={`text-neutral-primary${isNewEntry ? \" opacity-50\" : \"\"}`}>\n {title}\n </Heading>\n <Tooltip\n content={`Model: ${modelName}${status ? ` - Status: ${status}` : \"\"}`}\n trigger={\n <Icon icon={<InfoIcon />} label={\"Info\"} size={\"sm\"} color={\"neutral-light\"} />\n }\n />\n </div>\n );\n};\n\nconst EntryFormHeaderRight = observer(() => {\n const presenter = useContentEntryFormPresenter();\n const { buttonActions } = useContentEntryEditorConfig();\n\n const { canSave, canPublish, canUnpublish, canDelete } = presenter.vm;\n\n if (!canSave && !canPublish && !canUnpublish && !canDelete) {\n return <div />;\n }\n\n return (\n <div className={\"flex items-center gap-sm\"}>\n <Buttons actions={buttonActions} />\n </div>\n );\n});\n"],"names":["ContentEntryFormView","observer","listPresenter","useContentEntriesPresenter","formPresenter","useContentEntryFormPresenter","revisionsPresenter","useFeature","RevisionsListFeature","newEntryWizard","width","useContentEntryEditorConfig","router","useRouter","dialogs","useDialogs","route","useRoute","Routes","entryId","vm","hasWizard","showWizard","useEffect","handleBack","modelId","folderId","Container","Helmet","HeaderBar","EntryFormHeaderLeft","EntryFormHeaderRight","ScrollArea","OverlayLoader","ContentEntryFormContent","ContentEntryForm","RevisionDrawer","onBack","title","isNewEntry","modelName","status","IconButton","BackIcon","Heading","Tooltip","Icon","InfoIcon","presenter","buttonActions","canSave","canPublish","canUnpublish","canDelete","Buttons"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const RevisionDrawer: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const RevisionDrawer: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const RevisionsList: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const RevisionsList: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };