@pranaysahith/decap-cms-core 3.9.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 (299) hide show
  1. package/README.md +9 -0
  2. package/dist/@pranaysahith/decap-cms-core.js +52 -0
  3. package/dist/@pranaysahith/decap-cms-core.js.LICENSE.txt +141 -0
  4. package/dist/@pranaysahith/decap-cms-core.js.map +1 -0
  5. package/dist/decap-cms-core.js +47 -0
  6. package/dist/decap-cms-core.js.LICENSE.txt +116 -0
  7. package/dist/decap-cms-core.js.map +1 -0
  8. package/dist/esm/actions/auth.js +97 -0
  9. package/dist/esm/actions/collections.js +15 -0
  10. package/dist/esm/actions/config.js +493 -0
  11. package/dist/esm/actions/deploys.js +79 -0
  12. package/dist/esm/actions/editorialWorkflow.js +480 -0
  13. package/dist/esm/actions/entries.js +865 -0
  14. package/dist/esm/actions/media.js +147 -0
  15. package/dist/esm/actions/mediaLibrary.js +552 -0
  16. package/dist/esm/actions/notifications.js +21 -0
  17. package/dist/esm/actions/search.js +149 -0
  18. package/dist/esm/actions/status.js +74 -0
  19. package/dist/esm/actions/waitUntil.js +32 -0
  20. package/dist/esm/backend.js +1082 -0
  21. package/dist/esm/bootstrap.js +101 -0
  22. package/dist/esm/components/App/App.js +289 -0
  23. package/dist/esm/components/App/Header.js +172 -0
  24. package/dist/esm/components/App/NotFoundPage.js +19 -0
  25. package/dist/esm/components/Collection/Collection.js +198 -0
  26. package/dist/esm/components/Collection/CollectionControls.js +46 -0
  27. package/dist/esm/components/Collection/CollectionSearch.js +222 -0
  28. package/dist/esm/components/Collection/CollectionTop.js +68 -0
  29. package/dist/esm/components/Collection/ControlButton.js +17 -0
  30. package/dist/esm/components/Collection/Entries/Entries.js +73 -0
  31. package/dist/esm/components/Collection/Entries/EntriesCollection.js +241 -0
  32. package/dist/esm/components/Collection/Entries/EntriesSearch.js +113 -0
  33. package/dist/esm/components/Collection/Entries/EntryCard.js +177 -0
  34. package/dist/esm/components/Collection/Entries/EntryListing.js +143 -0
  35. package/dist/esm/components/Collection/FilterControl.js +33 -0
  36. package/dist/esm/components/Collection/FolderRenameControl.js +403 -0
  37. package/dist/esm/components/Collection/GroupControl.js +33 -0
  38. package/dist/esm/components/Collection/NestedCollection.js +308 -0
  39. package/dist/esm/components/Collection/Sidebar.js +91 -0
  40. package/dist/esm/components/Collection/SortControl.js +59 -0
  41. package/dist/esm/components/Collection/ViewStyleControl.js +38 -0
  42. package/dist/esm/components/Editor/Editor.js +466 -0
  43. package/dist/esm/components/Editor/EditorControlPane/EditorControl.js +395 -0
  44. package/dist/esm/components/Editor/EditorControlPane/EditorControlPane.js +254 -0
  45. package/dist/esm/components/Editor/EditorControlPane/Widget.js +374 -0
  46. package/dist/esm/components/Editor/EditorInterface.js +386 -0
  47. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreview.js +47 -0
  48. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewContent.js +66 -0
  49. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewPane.js +288 -0
  50. package/dist/esm/components/Editor/EditorPreviewPane/PreviewHOC.js +27 -0
  51. package/dist/esm/components/Editor/EditorToolbar.js +536 -0
  52. package/dist/esm/components/Editor/EntryPathEditor.js +272 -0
  53. package/dist/esm/components/Editor/withWorkflow.js +56 -0
  54. package/dist/esm/components/EditorWidgets/Unknown/UnknownControl.js +18 -0
  55. package/dist/esm/components/EditorWidgets/Unknown/UnknownPreview.js +20 -0
  56. package/dist/esm/components/EditorWidgets/index.js +4 -0
  57. package/dist/esm/components/MediaLibrary/EmptyMessage.js +22 -0
  58. package/dist/esm/components/MediaLibrary/MediaLibrary.js +446 -0
  59. package/dist/esm/components/MediaLibrary/MediaLibraryButtons.js +93 -0
  60. package/dist/esm/components/MediaLibrary/MediaLibraryCard.js +99 -0
  61. package/dist/esm/components/MediaLibrary/MediaLibraryCardGrid.js +198 -0
  62. package/dist/esm/components/MediaLibrary/MediaLibraryHeader.js +32 -0
  63. package/dist/esm/components/MediaLibrary/MediaLibraryModal.js +156 -0
  64. package/dist/esm/components/MediaLibrary/MediaLibrarySearch.js +51 -0
  65. package/dist/esm/components/MediaLibrary/MediaLibraryTop.js +123 -0
  66. package/dist/esm/components/UI/DragDrop.js +67 -0
  67. package/dist/esm/components/UI/ErrorBoundary.js +173 -0
  68. package/dist/esm/components/UI/FileUploadButton.js +27 -0
  69. package/dist/esm/components/UI/Modal.js +104 -0
  70. package/dist/esm/components/UI/Notifications.js +62 -0
  71. package/dist/esm/components/UI/SettingsDropdown.js +107 -0
  72. package/dist/esm/components/UI/index.js +6 -0
  73. package/dist/esm/components/Workflow/Workflow.js +133 -0
  74. package/dist/esm/components/Workflow/WorkflowCard.js +128 -0
  75. package/dist/esm/components/Workflow/WorkflowList.js +204 -0
  76. package/dist/esm/constants/collectionTypes.js +2 -0
  77. package/dist/esm/constants/collectionViews.js +2 -0
  78. package/dist/esm/constants/commitProps.js +2 -0
  79. package/dist/esm/constants/configSchema.js +644 -0
  80. package/dist/esm/constants/fieldInference.js +57 -0
  81. package/dist/esm/constants/publishModes.js +18 -0
  82. package/dist/esm/constants/validationErrorTypes.js +6 -0
  83. package/dist/esm/formats/formats.js +83 -0
  84. package/dist/esm/formats/frontmatter.js +146 -0
  85. package/dist/esm/formats/helpers.js +12 -0
  86. package/dist/esm/formats/json.js +8 -0
  87. package/dist/esm/formats/toml.js +32 -0
  88. package/dist/esm/formats/yaml.js +51 -0
  89. package/dist/esm/index.js +7 -0
  90. package/dist/esm/integrations/index.js +28 -0
  91. package/dist/esm/integrations/providers/algolia/implementation.js +174 -0
  92. package/dist/esm/integrations/providers/assetStore/implementation.js +165 -0
  93. package/dist/esm/lib/consoleError.js +3 -0
  94. package/dist/esm/lib/formatters.js +191 -0
  95. package/dist/esm/lib/i18n.js +367 -0
  96. package/dist/esm/lib/phrases.js +6 -0
  97. package/dist/esm/lib/polyfill.js +8 -0
  98. package/dist/esm/lib/registry.js +329 -0
  99. package/dist/esm/lib/serializeEntryValues.js +67 -0
  100. package/dist/esm/lib/stega.js +142 -0
  101. package/dist/esm/lib/textHelper.js +9 -0
  102. package/dist/esm/lib/urlHelper.js +111 -0
  103. package/dist/esm/mediaLibrary.js +37 -0
  104. package/dist/esm/reducers/auth.js +27 -0
  105. package/dist/esm/reducers/collections.js +428 -0
  106. package/dist/esm/reducers/combinedReducer.js +8 -0
  107. package/dist/esm/reducers/config.js +29 -0
  108. package/dist/esm/reducers/cursors.js +31 -0
  109. package/dist/esm/reducers/deploys.js +45 -0
  110. package/dist/esm/reducers/editorialWorkflow.js +83 -0
  111. package/dist/esm/reducers/entries.js +568 -0
  112. package/dist/esm/reducers/entryDraft.js +212 -0
  113. package/dist/esm/reducers/globalUI.js +25 -0
  114. package/dist/esm/reducers/index.js +66 -0
  115. package/dist/esm/reducers/integrations.js +53 -0
  116. package/dist/esm/reducers/mediaLibrary.js +252 -0
  117. package/dist/esm/reducers/medias.js +68 -0
  118. package/dist/esm/reducers/notifications.js +23 -0
  119. package/dist/esm/reducers/search.js +92 -0
  120. package/dist/esm/reducers/status.js +30 -0
  121. package/dist/esm/redux/index.js +7 -0
  122. package/dist/esm/redux/middleware/waitUntilAction.js +48 -0
  123. package/dist/esm/routing/history.js +12 -0
  124. package/dist/esm/types/diacritics.d.js +0 -0
  125. package/dist/esm/types/global.d.js +1 -0
  126. package/dist/esm/types/immutable.js +7 -0
  127. package/dist/esm/types/redux.js +14 -0
  128. package/dist/esm/types/tomlify-j0.4.d.js +0 -0
  129. package/dist/esm/valueObjects/AssetProxy.js +44 -0
  130. package/dist/esm/valueObjects/EditorComponent.js +34 -0
  131. package/dist/esm/valueObjects/Entry.js +20 -0
  132. package/index.d.ts +618 -0
  133. package/package.json +106 -0
  134. package/src/__tests__/backend.spec.js +1161 -0
  135. package/src/actions/__tests__/config.spec.js +1009 -0
  136. package/src/actions/__tests__/editorialWorkflow.spec.js +216 -0
  137. package/src/actions/__tests__/entries.spec.js +596 -0
  138. package/src/actions/__tests__/media.spec.ts +171 -0
  139. package/src/actions/__tests__/mediaLibrary.spec.js +327 -0
  140. package/src/actions/__tests__/search.spec.js +209 -0
  141. package/src/actions/auth.ts +127 -0
  142. package/src/actions/collections.ts +18 -0
  143. package/src/actions/config.ts +565 -0
  144. package/src/actions/deploys.ts +104 -0
  145. package/src/actions/editorialWorkflow.ts +567 -0
  146. package/src/actions/entries.ts +1055 -0
  147. package/src/actions/media.ts +139 -0
  148. package/src/actions/mediaLibrary.ts +574 -0
  149. package/src/actions/notifications.ts +36 -0
  150. package/src/actions/search.ts +221 -0
  151. package/src/actions/status.ts +99 -0
  152. package/src/actions/waitUntil.ts +49 -0
  153. package/src/backend.ts +1400 -0
  154. package/src/bootstrap.js +104 -0
  155. package/src/components/App/App.js +286 -0
  156. package/src/components/App/Header.js +266 -0
  157. package/src/components/App/NotFoundPage.js +23 -0
  158. package/src/components/Collection/Collection.js +210 -0
  159. package/src/components/Collection/CollectionControls.js +58 -0
  160. package/src/components/Collection/CollectionSearch.js +243 -0
  161. package/src/components/Collection/CollectionTop.js +81 -0
  162. package/src/components/Collection/ControlButton.js +27 -0
  163. package/src/components/Collection/Entries/Entries.js +82 -0
  164. package/src/components/Collection/Entries/EntriesCollection.js +277 -0
  165. package/src/components/Collection/Entries/EntriesSearch.js +102 -0
  166. package/src/components/Collection/Entries/EntryCard.js +246 -0
  167. package/src/components/Collection/Entries/EntryListing.js +151 -0
  168. package/src/components/Collection/Entries/__tests__/EntriesCollection.spec.js +163 -0
  169. package/src/components/Collection/Entries/__tests__/__snapshots__/EntriesCollection.spec.js.snap +46 -0
  170. package/src/components/Collection/FilterControl.js +39 -0
  171. package/src/components/Collection/GroupControl.js +39 -0
  172. package/src/components/Collection/NestedCollection.js +330 -0
  173. package/src/components/Collection/Sidebar.js +136 -0
  174. package/src/components/Collection/SortControl.js +68 -0
  175. package/src/components/Collection/ViewStyleControl.js +50 -0
  176. package/src/components/Collection/__tests__/Collection.spec.js +75 -0
  177. package/src/components/Collection/__tests__/NestedCollection.spec.js +445 -0
  178. package/src/components/Collection/__tests__/Sidebar.spec.js +87 -0
  179. package/src/components/Collection/__tests__/__snapshots__/Collection.spec.js.snap +144 -0
  180. package/src/components/Collection/__tests__/__snapshots__/NestedCollection.spec.js.snap +550 -0
  181. package/src/components/Collection/__tests__/__snapshots__/Sidebar.spec.js.snap +312 -0
  182. package/src/components/Editor/Editor.js +497 -0
  183. package/src/components/Editor/EditorControlPane/EditorControl.js +452 -0
  184. package/src/components/Editor/EditorControlPane/EditorControlPane.js +269 -0
  185. package/src/components/Editor/EditorControlPane/Widget.js +384 -0
  186. package/src/components/Editor/EditorInterface.js +444 -0
  187. package/src/components/Editor/EditorPreviewPane/EditorPreview.js +40 -0
  188. package/src/components/Editor/EditorPreviewPane/EditorPreviewContent.js +74 -0
  189. package/src/components/Editor/EditorPreviewPane/EditorPreviewPane.js +333 -0
  190. package/src/components/Editor/EditorPreviewPane/PreviewHOC.js +33 -0
  191. package/src/components/Editor/EditorToolbar.js +691 -0
  192. package/src/components/Editor/__tests__/Editor.spec.js +221 -0
  193. package/src/components/Editor/__tests__/EditorToolbar.spec.js +120 -0
  194. package/src/components/Editor/__tests__/__snapshots__/Editor.spec.js.snap +45 -0
  195. package/src/components/Editor/__tests__/__snapshots__/EditorToolbar.spec.js.snap +4233 -0
  196. package/src/components/Editor/withWorkflow.js +61 -0
  197. package/src/components/EditorWidgets/Unknown/UnknownControl.js +17 -0
  198. package/src/components/EditorWidgets/Unknown/UnknownPreview.js +19 -0
  199. package/src/components/EditorWidgets/index.js +5 -0
  200. package/src/components/MediaLibrary/EmptyMessage.js +28 -0
  201. package/src/components/MediaLibrary/MediaLibrary.js +411 -0
  202. package/src/components/MediaLibrary/MediaLibraryButtons.js +136 -0
  203. package/src/components/MediaLibrary/MediaLibraryCard.js +128 -0
  204. package/src/components/MediaLibrary/MediaLibraryCardGrid.js +199 -0
  205. package/src/components/MediaLibrary/MediaLibraryHeader.js +48 -0
  206. package/src/components/MediaLibrary/MediaLibraryModal.js +200 -0
  207. package/src/components/MediaLibrary/MediaLibrarySearch.js +61 -0
  208. package/src/components/MediaLibrary/MediaLibraryTop.js +143 -0
  209. package/src/components/MediaLibrary/__tests__/MediaLibraryButtons.spec.js +45 -0
  210. package/src/components/MediaLibrary/__tests__/MediaLibraryCard.spec.js +49 -0
  211. package/src/components/MediaLibrary/__tests__/__snapshots__/MediaLibraryCard.spec.js.snap +264 -0
  212. package/src/components/UI/DragDrop.js +66 -0
  213. package/src/components/UI/ErrorBoundary.js +214 -0
  214. package/src/components/UI/FileUploadButton.js +24 -0
  215. package/src/components/UI/Modal.js +112 -0
  216. package/src/components/UI/Notifications.tsx +83 -0
  217. package/src/components/UI/SettingsDropdown.js +103 -0
  218. package/src/components/UI/__tests__/ErrorBoundary.spec.js +57 -0
  219. package/src/components/UI/index.js +6 -0
  220. package/src/components/Workflow/Workflow.js +169 -0
  221. package/src/components/Workflow/WorkflowCard.js +177 -0
  222. package/src/components/Workflow/WorkflowList.js +272 -0
  223. package/src/constants/__tests__/configSchema.spec.js +611 -0
  224. package/src/constants/collectionTypes.ts +2 -0
  225. package/src/constants/collectionViews.js +2 -0
  226. package/src/constants/commitProps.ts +2 -0
  227. package/src/constants/configSchema.js +441 -0
  228. package/src/constants/fieldInference.tsx +78 -0
  229. package/src/constants/publishModes.ts +22 -0
  230. package/src/constants/validationErrorTypes.js +6 -0
  231. package/src/formats/__tests__/formats.spec.js +87 -0
  232. package/src/formats/__tests__/frontmatter.spec.js +429 -0
  233. package/src/formats/__tests__/toml.spec.js +9 -0
  234. package/src/formats/__tests__/yaml.spec.js +162 -0
  235. package/src/formats/formats.ts +97 -0
  236. package/src/formats/frontmatter.ts +150 -0
  237. package/src/formats/helpers.ts +14 -0
  238. package/src/formats/json.ts +9 -0
  239. package/src/formats/toml.ts +33 -0
  240. package/src/formats/yaml.ts +58 -0
  241. package/src/index.js +8 -0
  242. package/src/integrations/index.js +35 -0
  243. package/src/integrations/providers/algolia/implementation.js +176 -0
  244. package/src/integrations/providers/assetStore/implementation.js +148 -0
  245. package/src/lib/__tests__/formatters.spec.js +751 -0
  246. package/src/lib/__tests__/i18n.spec.js +792 -0
  247. package/src/lib/__tests__/phrases.spec.js +119 -0
  248. package/src/lib/__tests__/registry.spec.js +261 -0
  249. package/src/lib/__tests__/serializeEntryValues.spec.js +22 -0
  250. package/src/lib/__tests__/urlHelper.spec.js +138 -0
  251. package/src/lib/consoleError.js +7 -0
  252. package/src/lib/formatters.ts +286 -0
  253. package/src/lib/i18n.ts +454 -0
  254. package/src/lib/phrases.js +8 -0
  255. package/src/lib/polyfill.js +9 -0
  256. package/src/lib/registry.js +312 -0
  257. package/src/lib/serializeEntryValues.js +75 -0
  258. package/src/lib/stega.ts +145 -0
  259. package/src/lib/textHelper.js +11 -0
  260. package/src/lib/urlHelper.ts +128 -0
  261. package/src/mediaLibrary.ts +51 -0
  262. package/src/reducers/__tests__/auth.spec.ts +38 -0
  263. package/src/reducers/__tests__/collections.spec.js +610 -0
  264. package/src/reducers/__tests__/config.spec.js +38 -0
  265. package/src/reducers/__tests__/entries.spec.js +694 -0
  266. package/src/reducers/__tests__/entryDraft.spec.js +297 -0
  267. package/src/reducers/__tests__/globalUI.js +43 -0
  268. package/src/reducers/__tests__/integrations.spec.ts +76 -0
  269. package/src/reducers/__tests__/mediaLibrary.spec.js +154 -0
  270. package/src/reducers/__tests__/medias.spec.ts +49 -0
  271. package/src/reducers/auth.ts +46 -0
  272. package/src/reducers/collections.ts +535 -0
  273. package/src/reducers/combinedReducer.ts +11 -0
  274. package/src/reducers/config.ts +38 -0
  275. package/src/reducers/cursors.js +36 -0
  276. package/src/reducers/deploys.ts +52 -0
  277. package/src/reducers/editorialWorkflow.ts +163 -0
  278. package/src/reducers/entries.ts +819 -0
  279. package/src/reducers/entryDraft.js +260 -0
  280. package/src/reducers/globalUI.ts +45 -0
  281. package/src/reducers/index.ts +82 -0
  282. package/src/reducers/integrations.ts +59 -0
  283. package/src/reducers/mediaLibrary.ts +296 -0
  284. package/src/reducers/medias.ts +66 -0
  285. package/src/reducers/notifications.ts +52 -0
  286. package/src/reducers/search.ts +111 -0
  287. package/src/reducers/status.ts +40 -0
  288. package/src/redux/index.ts +18 -0
  289. package/src/redux/middleware/waitUntilAction.ts +64 -0
  290. package/src/routing/__tests__/history.spec.ts +49 -0
  291. package/src/routing/history.ts +17 -0
  292. package/src/types/diacritics.d.ts +1 -0
  293. package/src/types/global.d.ts +8 -0
  294. package/src/types/immutable.ts +49 -0
  295. package/src/types/redux.ts +827 -0
  296. package/src/types/tomlify-j0.4.d.ts +13 -0
  297. package/src/valueObjects/AssetProxy.ts +48 -0
  298. package/src/valueObjects/EditorComponent.js +38 -0
  299. package/src/valueObjects/Entry.ts +63 -0
@@ -0,0 +1,104 @@
1
+ import { currentBackend } from '../backend';
2
+ import { selectDeployPreview } from '../reducers';
3
+ import { addNotification } from './notifications';
4
+
5
+ import type { ThunkDispatch } from 'redux-thunk';
6
+ import type { AnyAction } from 'redux';
7
+ import type { Collection, Entry, State } from '../types/redux';
8
+
9
+ export const DEPLOY_PREVIEW_REQUEST = 'DEPLOY_PREVIEW_REQUEST';
10
+ export const DEPLOY_PREVIEW_SUCCESS = 'DEPLOY_PREVIEW_SUCCESS';
11
+ export const DEPLOY_PREVIEW_FAILURE = 'DEPLOY_PREVIEW_FAILURE';
12
+
13
+ function deployPreviewLoading(collection: string, slug: string) {
14
+ return {
15
+ type: DEPLOY_PREVIEW_REQUEST,
16
+ payload: {
17
+ collection,
18
+ slug,
19
+ },
20
+ } as const;
21
+ }
22
+
23
+ function deployPreviewLoaded(
24
+ collection: string,
25
+ slug: string,
26
+ deploy: { url: string | undefined; status: string },
27
+ ) {
28
+ const { url, status } = deploy;
29
+ return {
30
+ type: DEPLOY_PREVIEW_SUCCESS,
31
+ payload: {
32
+ collection,
33
+ slug,
34
+ url,
35
+ status,
36
+ },
37
+ } as const;
38
+ }
39
+
40
+ function deployPreviewError(collection: string, slug: string) {
41
+ return {
42
+ type: DEPLOY_PREVIEW_FAILURE,
43
+ payload: {
44
+ collection,
45
+ slug,
46
+ },
47
+ } as const;
48
+ }
49
+
50
+ /**
51
+ * Requests a deploy preview object from the registered backend.
52
+ */
53
+ export function loadDeployPreview(
54
+ collection: Collection,
55
+ slug: string,
56
+ entry: Entry,
57
+ published: boolean,
58
+ opts?: { maxAttempts?: number; interval?: number },
59
+ ) {
60
+ return async (dispatch: ThunkDispatch<State, undefined, AnyAction>, getState: () => State) => {
61
+ const state = getState();
62
+ const backend = currentBackend(state.config);
63
+ const collectionName = collection.get('name');
64
+
65
+ // Exit if currently fetching
66
+ const deployState = selectDeployPreview(state, collectionName, slug);
67
+ if (deployState && deployState.isFetching) {
68
+ return;
69
+ }
70
+
71
+ dispatch(deployPreviewLoading(collectionName, slug));
72
+
73
+ try {
74
+ /**
75
+ * `getDeploy` is for published entries, while `getDeployPreview` is for
76
+ * unpublished entries.
77
+ */
78
+ const deploy = published
79
+ ? backend.getDeploy(collection, slug, entry)
80
+ : await backend.getDeployPreview(collection, slug, entry, opts);
81
+ if (deploy) {
82
+ return dispatch(deployPreviewLoaded(collectionName, slug, deploy));
83
+ }
84
+ return dispatch(deployPreviewError(collectionName, slug));
85
+ } catch (error) {
86
+ console.error(error);
87
+ dispatch(
88
+ addNotification({
89
+ message: {
90
+ details: error.message,
91
+ key: 'ui.toast.onFailToLoadDeployPreview',
92
+ },
93
+ type: 'error',
94
+ dismissAfter: 8000,
95
+ }),
96
+ );
97
+ dispatch(deployPreviewError(collectionName, slug));
98
+ }
99
+ };
100
+ }
101
+
102
+ export type DeploysAction = ReturnType<
103
+ typeof deployPreviewLoading | typeof deployPreviewLoaded | typeof deployPreviewError
104
+ >;
@@ -0,0 +1,567 @@
1
+ import get from 'lodash/get';
2
+ import { Map, List } from 'immutable';
3
+ import { EDITORIAL_WORKFLOW_ERROR } from 'decap-cms-lib-util';
4
+
5
+ import { currentBackend, slugFromCustomPath } from '../backend';
6
+ import {
7
+ selectPublishedSlugs,
8
+ selectUnpublishedSlugs,
9
+ selectEntry,
10
+ selectUnpublishedEntry,
11
+ } from '../reducers';
12
+ import { selectEditingDraft } from '../reducers/entries';
13
+ import { EDITORIAL_WORKFLOW, status } from '../constants/publishModes';
14
+ import {
15
+ loadEntry,
16
+ entryDeleted,
17
+ getMediaAssets,
18
+ createDraftFromEntry,
19
+ loadEntries,
20
+ getSerializedEntry,
21
+ } from './entries';
22
+ import { createAssetProxy } from '../valueObjects/AssetProxy';
23
+ import { addAssets } from './media';
24
+ import { loadMedia } from './mediaLibrary';
25
+ import ValidationErrorTypes from '../constants/validationErrorTypes';
26
+ import { navigateToEntry } from '../routing/history';
27
+ import { addNotification } from './notifications';
28
+
29
+ import type {
30
+ Collection,
31
+ EntryMap,
32
+ State,
33
+ Collections,
34
+ EntryDraft,
35
+ MediaFile,
36
+ } from '../types/redux';
37
+ import type { AnyAction } from 'redux';
38
+ import type { EntryValue } from '../valueObjects/Entry';
39
+ import type { Status } from '../constants/publishModes';
40
+ import type { ThunkDispatch } from 'redux-thunk';
41
+
42
+ /*
43
+ * Constant Declarations
44
+ */
45
+ export const UNPUBLISHED_ENTRY_REQUEST = 'UNPUBLISHED_ENTRY_REQUEST';
46
+ export const UNPUBLISHED_ENTRY_SUCCESS = 'UNPUBLISHED_ENTRY_SUCCESS';
47
+ export const UNPUBLISHED_ENTRY_REDIRECT = 'UNPUBLISHED_ENTRY_REDIRECT';
48
+
49
+ export const UNPUBLISHED_ENTRIES_REQUEST = 'UNPUBLISHED_ENTRIES_REQUEST';
50
+ export const UNPUBLISHED_ENTRIES_SUCCESS = 'UNPUBLISHED_ENTRIES_SUCCESS';
51
+ export const UNPUBLISHED_ENTRIES_FAILURE = 'UNPUBLISHED_ENTRIES_FAILURE';
52
+
53
+ export const UNPUBLISHED_ENTRY_PERSIST_REQUEST = 'UNPUBLISHED_ENTRY_PERSIST_REQUEST';
54
+ export const UNPUBLISHED_ENTRY_PERSIST_SUCCESS = 'UNPUBLISHED_ENTRY_PERSIST_SUCCESS';
55
+ export const UNPUBLISHED_ENTRY_PERSIST_FAILURE = 'UNPUBLISHED_ENTRY_PERSIST_FAILURE';
56
+
57
+ export const UNPUBLISHED_ENTRY_STATUS_CHANGE_REQUEST = 'UNPUBLISHED_ENTRY_STATUS_CHANGE_REQUEST';
58
+ export const UNPUBLISHED_ENTRY_STATUS_CHANGE_SUCCESS = 'UNPUBLISHED_ENTRY_STATUS_CHANGE_SUCCESS';
59
+ export const UNPUBLISHED_ENTRY_STATUS_CHANGE_FAILURE = 'UNPUBLISHED_ENTRY_STATUS_CHANGE_FAILURE';
60
+
61
+ export const UNPUBLISHED_ENTRY_PUBLISH_REQUEST = 'UNPUBLISHED_ENTRY_PUBLISH_REQUEST';
62
+ export const UNPUBLISHED_ENTRY_PUBLISH_SUCCESS = 'UNPUBLISHED_ENTRY_PUBLISH_SUCCESS';
63
+ export const UNPUBLISHED_ENTRY_PUBLISH_FAILURE = 'UNPUBLISHED_ENTRY_PUBLISH_FAILURE';
64
+
65
+ export const UNPUBLISHED_ENTRY_DELETE_REQUEST = 'UNPUBLISHED_ENTRY_DELETE_REQUEST';
66
+ export const UNPUBLISHED_ENTRY_DELETE_SUCCESS = 'UNPUBLISHED_ENTRY_DELETE_SUCCESS';
67
+ export const UNPUBLISHED_ENTRY_DELETE_FAILURE = 'UNPUBLISHED_ENTRY_DELETE_FAILURE';
68
+
69
+ /*
70
+ * Simple Action Creators (Internal)
71
+ */
72
+
73
+ function unpublishedEntryLoading(collection: Collection, slug: string) {
74
+ return {
75
+ type: UNPUBLISHED_ENTRY_REQUEST,
76
+ payload: {
77
+ collection: collection.get('name'),
78
+ slug,
79
+ },
80
+ };
81
+ }
82
+
83
+ function unpublishedEntryLoaded(
84
+ collection: Collection,
85
+ entry: EntryValue & { mediaFiles: MediaFile[] },
86
+ ) {
87
+ return {
88
+ type: UNPUBLISHED_ENTRY_SUCCESS,
89
+ payload: {
90
+ collection: collection.get('name'),
91
+ entry,
92
+ },
93
+ };
94
+ }
95
+
96
+ function unpublishedEntryRedirected(collection: Collection, slug: string) {
97
+ return {
98
+ type: UNPUBLISHED_ENTRY_REDIRECT,
99
+ payload: {
100
+ collection: collection.get('name'),
101
+ slug,
102
+ },
103
+ };
104
+ }
105
+
106
+ function unpublishedEntriesLoading() {
107
+ return {
108
+ type: UNPUBLISHED_ENTRIES_REQUEST,
109
+ };
110
+ }
111
+
112
+ function unpublishedEntriesLoaded(entries: EntryValue[], pagination: number) {
113
+ return {
114
+ type: UNPUBLISHED_ENTRIES_SUCCESS,
115
+ payload: {
116
+ entries,
117
+ pages: pagination,
118
+ },
119
+ };
120
+ }
121
+
122
+ function unpublishedEntriesFailed(error: Error) {
123
+ return {
124
+ type: UNPUBLISHED_ENTRIES_FAILURE,
125
+ error: 'Failed to load entries',
126
+ payload: error,
127
+ };
128
+ }
129
+
130
+ function unpublishedEntryPersisting(collection: Collection, slug: string) {
131
+ return {
132
+ type: UNPUBLISHED_ENTRY_PERSIST_REQUEST,
133
+ payload: {
134
+ collection: collection.get('name'),
135
+ slug,
136
+ },
137
+ };
138
+ }
139
+
140
+ function unpublishedEntryPersisted(collection: Collection, entry: EntryMap) {
141
+ return {
142
+ type: UNPUBLISHED_ENTRY_PERSIST_SUCCESS,
143
+ payload: {
144
+ collection: collection.get('name'),
145
+ entry,
146
+ },
147
+ };
148
+ }
149
+
150
+ function unpublishedEntryPersistedFail(error: Error, collection: Collection, slug: string) {
151
+ return {
152
+ type: UNPUBLISHED_ENTRY_PERSIST_FAILURE,
153
+ payload: {
154
+ error,
155
+ collection: collection.get('name'),
156
+ slug,
157
+ },
158
+ error,
159
+ };
160
+ }
161
+
162
+ function unpublishedEntryStatusChangeRequest(collection: string, slug: string) {
163
+ return {
164
+ type: UNPUBLISHED_ENTRY_STATUS_CHANGE_REQUEST,
165
+ payload: {
166
+ collection,
167
+ slug,
168
+ },
169
+ };
170
+ }
171
+
172
+ function unpublishedEntryStatusChangePersisted(
173
+ collection: string,
174
+ slug: string,
175
+ newStatus: Status,
176
+ ) {
177
+ return {
178
+ type: UNPUBLISHED_ENTRY_STATUS_CHANGE_SUCCESS,
179
+ payload: {
180
+ collection,
181
+ slug,
182
+ newStatus,
183
+ },
184
+ };
185
+ }
186
+
187
+ function unpublishedEntryStatusChangeError(collection: string, slug: string) {
188
+ return {
189
+ type: UNPUBLISHED_ENTRY_STATUS_CHANGE_FAILURE,
190
+ payload: { collection, slug },
191
+ };
192
+ }
193
+
194
+ function unpublishedEntryPublishRequest(collection: string, slug: string) {
195
+ return {
196
+ type: UNPUBLISHED_ENTRY_PUBLISH_REQUEST,
197
+ payload: { collection, slug },
198
+ };
199
+ }
200
+
201
+ function unpublishedEntryPublished(collection: string, slug: string) {
202
+ return {
203
+ type: UNPUBLISHED_ENTRY_PUBLISH_SUCCESS,
204
+ payload: { collection, slug },
205
+ };
206
+ }
207
+
208
+ function unpublishedEntryPublishError(collection: string, slug: string) {
209
+ return {
210
+ type: UNPUBLISHED_ENTRY_PUBLISH_FAILURE,
211
+ payload: { collection, slug },
212
+ };
213
+ }
214
+
215
+ function unpublishedEntryDeleteRequest(collection: string, slug: string) {
216
+ return {
217
+ type: UNPUBLISHED_ENTRY_DELETE_REQUEST,
218
+ payload: { collection, slug },
219
+ };
220
+ }
221
+
222
+ function unpublishedEntryDeleted(collection: string, slug: string) {
223
+ return {
224
+ type: UNPUBLISHED_ENTRY_DELETE_SUCCESS,
225
+ payload: { collection, slug },
226
+ };
227
+ }
228
+
229
+ function unpublishedEntryDeleteError(collection: string, slug: string) {
230
+ return {
231
+ type: UNPUBLISHED_ENTRY_DELETE_FAILURE,
232
+ payload: { collection, slug },
233
+ };
234
+ }
235
+
236
+ /*
237
+ * Exported Thunk Action Creators
238
+ */
239
+
240
+ export function loadUnpublishedEntry(collection: Collection, slug: string) {
241
+ return async (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
242
+ const state = getState();
243
+ const backend = currentBackend(state.config);
244
+ const entriesLoaded = get(state.editorialWorkflow.toJS(), 'pages.ids', false);
245
+ //run possible unpublishedEntries migration
246
+ if (!entriesLoaded) {
247
+ try {
248
+ const { entries, pagination } = await backend.unpublishedEntries(state.collections);
249
+ dispatch(unpublishedEntriesLoaded(entries, pagination));
250
+ // eslint-disable-next-line no-empty
251
+ } catch (e) {}
252
+ }
253
+
254
+ dispatch(unpublishedEntryLoading(collection, slug));
255
+
256
+ try {
257
+ const entry = (await backend.unpublishedEntry(state, collection, slug)) as EntryValue;
258
+ const assetProxies = await Promise.all(
259
+ entry.mediaFiles
260
+ .filter(file => file.draft)
261
+ .map(({ url, file, path }) =>
262
+ createAssetProxy({
263
+ path,
264
+ url,
265
+ file,
266
+ }),
267
+ ),
268
+ );
269
+ dispatch(addAssets(assetProxies));
270
+ dispatch(unpublishedEntryLoaded(collection, entry));
271
+ dispatch(createDraftFromEntry(entry));
272
+ } catch (error) {
273
+ if (error.name === EDITORIAL_WORKFLOW_ERROR && error.notUnderEditorialWorkflow) {
274
+ dispatch(unpublishedEntryRedirected(collection, slug));
275
+ dispatch(loadEntry(collection, slug));
276
+ } else {
277
+ dispatch(
278
+ addNotification({
279
+ message: {
280
+ key: 'ui.toast.onFailToLoadEntries',
281
+ details: error,
282
+ },
283
+ type: 'error',
284
+ dismissAfter: 8000,
285
+ }),
286
+ );
287
+ }
288
+ }
289
+ };
290
+ }
291
+
292
+ export function loadUnpublishedEntries(collections: Collections) {
293
+ return (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
294
+ const state = getState();
295
+ const backend = currentBackend(state.config);
296
+ const entriesLoaded = get(state.editorialWorkflow.toJS(), 'pages.ids', false);
297
+
298
+ if (state.config.publish_mode !== EDITORIAL_WORKFLOW || entriesLoaded) {
299
+ return;
300
+ }
301
+
302
+ dispatch(unpublishedEntriesLoading());
303
+ backend
304
+ .unpublishedEntries(collections)
305
+ .then(response => dispatch(unpublishedEntriesLoaded(response.entries, response.pagination)))
306
+ .catch((error: Error) => {
307
+ dispatch(
308
+ addNotification({
309
+ message: {
310
+ key: 'ui.toast.onFailToLoadEntries',
311
+ details: error,
312
+ },
313
+ type: 'error',
314
+ dismissAfter: 8000,
315
+ }),
316
+ );
317
+ dispatch(unpublishedEntriesFailed(error));
318
+ Promise.reject(error);
319
+ });
320
+ };
321
+ }
322
+
323
+ export function persistUnpublishedEntry(collection: Collection, existingUnpublishedEntry: boolean) {
324
+ return async (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
325
+ const state = getState();
326
+ const entryDraft = state.entryDraft;
327
+ const fieldsErrors = entryDraft.get('fieldsErrors');
328
+ const unpublishedSlugs = selectUnpublishedSlugs(state, collection.get('name'));
329
+ const publishedSlugs = selectPublishedSlugs(state, collection.get('name'));
330
+ const usedSlugs = publishedSlugs.concat(unpublishedSlugs) as List<string>;
331
+ const entriesLoaded = get(state.editorialWorkflow.toJS(), 'pages.ids', false);
332
+
333
+ //load unpublishedEntries
334
+ !entriesLoaded && dispatch(loadUnpublishedEntries(state.collections));
335
+
336
+ // Early return if draft contains validation errors
337
+ if (!fieldsErrors.isEmpty()) {
338
+ const hasPresenceErrors = fieldsErrors.some(errors =>
339
+ errors.some(error => error.type && error.type === ValidationErrorTypes.PRESENCE),
340
+ );
341
+
342
+ if (hasPresenceErrors) {
343
+ dispatch(
344
+ addNotification({
345
+ message: {
346
+ key: 'ui.toast.missingRequiredField',
347
+ },
348
+ type: 'error',
349
+ dismissAfter: 8000,
350
+ }),
351
+ );
352
+ }
353
+ return Promise.reject();
354
+ }
355
+
356
+ const backend = currentBackend(state.config);
357
+ const entry = entryDraft.get('entry');
358
+ const assetProxies = getMediaAssets({
359
+ entry,
360
+ });
361
+
362
+ const serializedEntry = getSerializedEntry(collection, entry);
363
+ const serializedEntryDraft = entryDraft.set('entry', serializedEntry);
364
+
365
+ dispatch(unpublishedEntryPersisting(collection, entry.get('slug')));
366
+ const persistAction = existingUnpublishedEntry
367
+ ? backend.persistUnpublishedEntry
368
+ : backend.persistEntry;
369
+
370
+ try {
371
+ const newSlug = await persistAction.call(backend, {
372
+ config: state.config,
373
+ collection,
374
+ entryDraft: serializedEntryDraft,
375
+ assetProxies,
376
+ usedSlugs,
377
+ });
378
+ dispatch(
379
+ addNotification({
380
+ message: {
381
+ key: 'ui.toast.entrySaved',
382
+ },
383
+ type: 'success',
384
+ dismissAfter: 4000,
385
+ }),
386
+ );
387
+ dispatch(unpublishedEntryPersisted(collection, serializedEntry));
388
+
389
+ if (entry.get('slug') !== newSlug) {
390
+ await dispatch(loadUnpublishedEntry(collection, newSlug));
391
+ navigateToEntry(collection.get('name'), newSlug);
392
+ }
393
+ } catch (error) {
394
+ dispatch(
395
+ addNotification({
396
+ message: {
397
+ key: 'ui.toast.onFailToPersist',
398
+ details: error,
399
+ },
400
+ type: 'error',
401
+ dismissAfter: 8000,
402
+ }),
403
+ );
404
+ return Promise.reject(
405
+ dispatch(unpublishedEntryPersistedFail(error, collection, entry.get('slug'))),
406
+ );
407
+ }
408
+ };
409
+ }
410
+
411
+ export function updateUnpublishedEntryStatus(
412
+ collection: string,
413
+ slug: string,
414
+ oldStatus: Status,
415
+ newStatus: Status,
416
+ ) {
417
+ return (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
418
+ if (oldStatus === newStatus) return;
419
+ const state = getState();
420
+ const backend = currentBackend(state.config);
421
+ dispatch(unpublishedEntryStatusChangeRequest(collection, slug));
422
+ backend
423
+ .updateUnpublishedEntryStatus(collection, slug, newStatus)
424
+ .then(() => {
425
+ dispatch(
426
+ addNotification({
427
+ message: {
428
+ key: 'ui.toast.entryUpdated',
429
+ },
430
+ type: 'success',
431
+ dismissAfter: 4000,
432
+ }),
433
+ );
434
+ dispatch(unpublishedEntryStatusChangePersisted(collection, slug, newStatus));
435
+ })
436
+ .catch((error: Error) => {
437
+ dispatch(
438
+ addNotification({
439
+ message: {
440
+ key: 'ui.toast.onFailToUpdateStatus',
441
+ details: error,
442
+ },
443
+ type: 'error',
444
+ dismissAfter: 8000,
445
+ }),
446
+ );
447
+ dispatch(unpublishedEntryStatusChangeError(collection, slug));
448
+ });
449
+ };
450
+ }
451
+
452
+ export function deleteUnpublishedEntry(collection: string, slug: string) {
453
+ return (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
454
+ const state = getState();
455
+ const backend = currentBackend(state.config);
456
+ dispatch(unpublishedEntryDeleteRequest(collection, slug));
457
+ return backend
458
+ .deleteUnpublishedEntry(collection, slug)
459
+ .then(() => {
460
+ dispatch(
461
+ addNotification({
462
+ message: { key: 'ui.toast.onDeleteUnpublishedChanges' },
463
+ type: 'success',
464
+ dismissAfter: 4000,
465
+ }),
466
+ );
467
+ dispatch(unpublishedEntryDeleted(collection, slug));
468
+ })
469
+ .catch((error: Error) => {
470
+ dispatch(
471
+ addNotification({
472
+ message: { key: 'ui.toast.onDeleteUnpublishedChanges', details: error },
473
+ type: 'error',
474
+ dismissAfter: 8000,
475
+ }),
476
+ );
477
+ dispatch(unpublishedEntryDeleteError(collection, slug));
478
+ });
479
+ };
480
+ }
481
+
482
+ export function publishUnpublishedEntry(collectionName: string, slug: string) {
483
+ return async (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
484
+ const state = getState();
485
+ const collections = state.collections;
486
+ const backend = currentBackend(state.config);
487
+ const entry = selectUnpublishedEntry(state, collectionName, slug);
488
+ dispatch(unpublishedEntryPublishRequest(collectionName, slug));
489
+ try {
490
+ await backend.publishUnpublishedEntry(entry);
491
+ // re-load media after entry was published
492
+ dispatch(loadMedia());
493
+ dispatch(
494
+ addNotification({
495
+ message: { key: 'ui.toast.entryPublished' },
496
+ type: 'success',
497
+ dismissAfter: 4000,
498
+ }),
499
+ );
500
+ dispatch(unpublishedEntryPublished(collectionName, slug));
501
+ const collection = collections.get(collectionName);
502
+ if (collection.has('nested')) {
503
+ dispatch(loadEntries(collection));
504
+ const newSlug = slugFromCustomPath(collection, entry.get('path'));
505
+ loadEntry(collection, newSlug);
506
+ if (slug !== newSlug && selectEditingDraft(state.entryDraft)) {
507
+ navigateToEntry(collection.get('name'), newSlug);
508
+ }
509
+ } else {
510
+ return dispatch(loadEntry(collection, slug));
511
+ }
512
+ } catch (error) {
513
+ dispatch(
514
+ addNotification({
515
+ message: { key: 'ui.toast.onFailToPublishEntry', details: error },
516
+ type: 'error',
517
+ dismissAfter: 8000,
518
+ }),
519
+ );
520
+ dispatch(unpublishedEntryPublishError(collectionName, slug));
521
+ }
522
+ };
523
+ }
524
+
525
+ export function unpublishPublishedEntry(collection: Collection, slug: string) {
526
+ return (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
527
+ const state = getState();
528
+ const backend = currentBackend(state.config);
529
+ const entry = selectEntry(state, collection.get('name'), slug);
530
+ const entryDraft = Map().set('entry', entry) as unknown as EntryDraft;
531
+ dispatch(unpublishedEntryPersisting(collection, slug));
532
+ return backend
533
+ .deleteEntry(state, collection, slug)
534
+ .then(() =>
535
+ backend.persistEntry({
536
+ config: state.config,
537
+ collection,
538
+ entryDraft,
539
+ assetProxies: [],
540
+ usedSlugs: List(),
541
+ status: status.get('PENDING_PUBLISH'),
542
+ }),
543
+ )
544
+ .then(() => {
545
+ dispatch(unpublishedEntryPersisted(collection, entry));
546
+ dispatch(entryDeleted(collection, slug));
547
+ dispatch(loadUnpublishedEntry(collection, slug));
548
+ dispatch(
549
+ addNotification({
550
+ message: { key: 'ui.toast.entryUnpublished' },
551
+ type: 'success',
552
+ dismissAfter: 4000,
553
+ }),
554
+ );
555
+ })
556
+ .catch((error: Error) => {
557
+ dispatch(
558
+ addNotification({
559
+ message: { key: 'ui.toast.onFailToUnpublishEntry', details: error },
560
+ type: 'error',
561
+ dismissAfter: 8000,
562
+ }),
563
+ );
564
+ dispatch(unpublishedEntryPersistedFail(error, collection, entry.get('slug')));
565
+ });
566
+ };
567
+ }