@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,212 @@
1
+ import { Map, List, fromJS } from 'immutable';
2
+ import { v4 as uuid } from 'uuid';
3
+ import get from 'lodash/get';
4
+ import { join } from 'path';
5
+ import { DRAFT_CREATE_FROM_ENTRY, DRAFT_CREATE_EMPTY, DRAFT_DISCARD, DRAFT_CHANGE_FIELD, DRAFT_VALIDATION_ERRORS, DRAFT_CLEAR_ERRORS, DRAFT_LOCAL_BACKUP_RETRIEVED, DRAFT_CREATE_FROM_LOCAL_BACKUP, DRAFT_CREATE_DUPLICATE_FROM_ENTRY, ENTRY_PERSIST_REQUEST, ENTRY_PERSIST_SUCCESS, ENTRY_PERSIST_FAILURE, ENTRY_DELETE_SUCCESS, ADD_DRAFT_ENTRY_MEDIA_FILE, REMOVE_DRAFT_ENTRY_MEDIA_FILE } from '../actions/entries';
6
+ import { UNPUBLISHED_ENTRY_PERSIST_REQUEST, UNPUBLISHED_ENTRY_PERSIST_SUCCESS, UNPUBLISHED_ENTRY_PERSIST_FAILURE, UNPUBLISHED_ENTRY_STATUS_CHANGE_REQUEST, UNPUBLISHED_ENTRY_STATUS_CHANGE_SUCCESS, UNPUBLISHED_ENTRY_STATUS_CHANGE_FAILURE, UNPUBLISHED_ENTRY_PUBLISH_REQUEST, UNPUBLISHED_ENTRY_PUBLISH_SUCCESS, UNPUBLISHED_ENTRY_PUBLISH_FAILURE } from '../actions/editorialWorkflow';
7
+ import { selectFolderEntryExtension, selectHasMetaPath } from './collections';
8
+ import { getDataPath, duplicateI18nFields } from '../lib/i18n';
9
+ const initialState = Map({
10
+ entry: Map(),
11
+ fieldsMetaData: Map(),
12
+ fieldsErrors: Map(),
13
+ hasChanged: false,
14
+ key: ''
15
+ });
16
+ function entryDraftReducer(state = Map(), action) {
17
+ switch (action.type) {
18
+ case DRAFT_CREATE_FROM_ENTRY:
19
+ // Existing Entry
20
+ return state.withMutations(state => {
21
+ state.set('entry', fromJS(action.payload.entry));
22
+ state.setIn(['entry', 'newRecord'], false);
23
+ state.set('fieldsMetaData', Map());
24
+ state.set('fieldsErrors', Map());
25
+ state.set('hasChanged', false);
26
+ state.set('key', uuid());
27
+ });
28
+ case DRAFT_CREATE_EMPTY:
29
+ // New Entry
30
+ return state.withMutations(state => {
31
+ state.set('entry', fromJS(action.payload));
32
+ state.setIn(['entry', 'newRecord'], true);
33
+ state.set('fieldsMetaData', Map());
34
+ state.set('fieldsErrors', Map());
35
+ state.set('hasChanged', false);
36
+ state.set('key', uuid());
37
+ });
38
+ case DRAFT_CREATE_FROM_LOCAL_BACKUP:
39
+ // Local Backup
40
+ return state.withMutations(state => {
41
+ const backupDraftEntry = state.get('localBackup');
42
+ const backupEntry = backupDraftEntry.get('entry');
43
+ state.delete('localBackup');
44
+ state.set('entry', backupEntry);
45
+ state.setIn(['entry', 'newRecord'], !backupEntry.get('path'));
46
+ state.set('fieldsMetaData', Map());
47
+ state.set('fieldsErrors', Map());
48
+ state.set('hasChanged', true);
49
+ state.set('key', uuid());
50
+ });
51
+ case DRAFT_CREATE_DUPLICATE_FROM_ENTRY:
52
+ // Duplicate Entry
53
+ return state.withMutations(state => {
54
+ state.set('entry', fromJS(action.payload));
55
+ state.setIn(['entry', 'newRecord'], true);
56
+ state.set('mediaFiles', List());
57
+ state.set('fieldsMetaData', Map());
58
+ state.set('fieldsErrors', Map());
59
+ state.set('hasChanged', true);
60
+ });
61
+ case DRAFT_DISCARD:
62
+ return initialState;
63
+ case DRAFT_LOCAL_BACKUP_RETRIEVED:
64
+ {
65
+ const {
66
+ entry
67
+ } = action.payload;
68
+ const newState = new Map({
69
+ entry: fromJS(entry)
70
+ });
71
+ return state.set('localBackup', newState);
72
+ }
73
+ case DRAFT_CHANGE_FIELD:
74
+ {
75
+ return state.withMutations(state => {
76
+ const {
77
+ field,
78
+ value,
79
+ metadata,
80
+ entries,
81
+ i18n
82
+ } = action.payload;
83
+ const name = field.get('name');
84
+ const meta = field.get('meta');
85
+ const dataPath = i18n && getDataPath(i18n.currentLocale, i18n.defaultLocale) || ['data'];
86
+ if (meta) {
87
+ state.setIn(['entry', 'meta', name], value);
88
+ } else {
89
+ state.setIn(['entry', ...dataPath, name], value);
90
+ if (i18n) {
91
+ state = duplicateI18nFields(state, field, i18n.locales, i18n.defaultLocale);
92
+ }
93
+ }
94
+ state.mergeDeepIn(['fieldsMetaData'], fromJS(metadata));
95
+ const newData = state.getIn(['entry', ...dataPath]);
96
+ const newMeta = state.getIn(['entry', 'meta']);
97
+ state.set('hasChanged', !entries.some(e => newData.equals(e.get(...dataPath))) || !entries.some(e => newMeta.equals(e.get('meta'))));
98
+ });
99
+ }
100
+ case DRAFT_VALIDATION_ERRORS:
101
+ if (action.payload.errors.length === 0) {
102
+ return state.deleteIn(['fieldsErrors', action.payload.uniquefieldId]);
103
+ } else {
104
+ return state.setIn(['fieldsErrors', action.payload.uniquefieldId], action.payload.errors);
105
+ }
106
+ case DRAFT_CLEAR_ERRORS:
107
+ {
108
+ const {
109
+ uniqueFieldId
110
+ } = action.payload;
111
+ return state.deleteIn(['fieldsErrors', uniqueFieldId]);
112
+ }
113
+ case ENTRY_PERSIST_REQUEST:
114
+ case UNPUBLISHED_ENTRY_PERSIST_REQUEST:
115
+ {
116
+ return state.setIn(['entry', 'isPersisting'], true);
117
+ }
118
+ case ENTRY_PERSIST_FAILURE:
119
+ case UNPUBLISHED_ENTRY_PERSIST_FAILURE:
120
+ {
121
+ return state.deleteIn(['entry', 'isPersisting']);
122
+ }
123
+ case UNPUBLISHED_ENTRY_STATUS_CHANGE_REQUEST:
124
+ return state.setIn(['entry', 'isUpdatingStatus'], true);
125
+ case UNPUBLISHED_ENTRY_STATUS_CHANGE_FAILURE:
126
+ case UNPUBLISHED_ENTRY_STATUS_CHANGE_SUCCESS:
127
+ return state.deleteIn(['entry', 'isUpdatingStatus']);
128
+ case UNPUBLISHED_ENTRY_PUBLISH_REQUEST:
129
+ return state.setIn(['entry', 'isPublishing'], true);
130
+ case UNPUBLISHED_ENTRY_PUBLISH_SUCCESS:
131
+ case UNPUBLISHED_ENTRY_PUBLISH_FAILURE:
132
+ return state.deleteIn(['entry', 'isPublishing']);
133
+ case ENTRY_PERSIST_SUCCESS:
134
+ case UNPUBLISHED_ENTRY_PERSIST_SUCCESS:
135
+ return state.withMutations(state => {
136
+ state.deleteIn(['entry', 'isPersisting']);
137
+ state.set('hasChanged', false);
138
+ if (!state.getIn(['entry', 'slug'])) {
139
+ state.setIn(['entry', 'slug'], action.payload.slug);
140
+ }
141
+ });
142
+ case ENTRY_DELETE_SUCCESS:
143
+ return state.withMutations(state => {
144
+ state.deleteIn(['entry', 'isPersisting']);
145
+ state.set('hasChanged', false);
146
+ });
147
+ case ADD_DRAFT_ENTRY_MEDIA_FILE:
148
+ {
149
+ return state.withMutations(state => {
150
+ const mediaFiles = state.getIn(['entry', 'mediaFiles']);
151
+ state.setIn(['entry', 'mediaFiles'], mediaFiles.filterNot(file => file.get('id') === action.payload.id).insert(0, fromJS(action.payload)));
152
+ state.set('hasChanged', true);
153
+ });
154
+ }
155
+ case REMOVE_DRAFT_ENTRY_MEDIA_FILE:
156
+ {
157
+ return state.withMutations(state => {
158
+ const mediaFiles = state.getIn(['entry', 'mediaFiles']);
159
+ state.setIn(['entry', 'mediaFiles'], mediaFiles.filterNot(file => file.get('id') === action.payload.id));
160
+ state.set('hasChanged', true);
161
+ });
162
+ }
163
+ default:
164
+ return state;
165
+ }
166
+ }
167
+ function cleanTitleForFilename(title) {
168
+ if (!title) return 'untitled';
169
+ // Convert to lowercase, replace spaces and special chars with hyphens
170
+ return title.toString().toLowerCase().trim().replace(/[^\w\s-]/g, '') // Remove special characters
171
+ .replace(/[\s_]+/g, '-') // Replace spaces and underscores with hyphens
172
+ .replace(/^-+|-+$/g, ''); // Remove leading/trailing hyphens
173
+ }
174
+ export function selectCustomPath(collection, entryDraft) {
175
+ if (!selectHasMetaPath(collection)) {
176
+ return;
177
+ }
178
+ const meta = entryDraft.getIn(['entry', 'meta']);
179
+ const path = meta && meta.get('path');
180
+ if (!path) {
181
+ return;
182
+ }
183
+ const extension = selectFolderEntryExtension(collection);
184
+ const indexFile = get(collection.toJS(), ['meta', 'path', 'index_file']);
185
+
186
+ // If index_file is specified, use the old behavior for backward compatibility
187
+ if (indexFile) {
188
+ const customPath = join(collection.get('folder'), path, `${indexFile}.${extension}`);
189
+ return customPath;
190
+ }
191
+
192
+ // New behavior: generate filename from entry title
193
+ const isNewEntry = entryDraft.getIn(['entry', 'newRecord']);
194
+ const currentPath = entryDraft.getIn(['entry', 'path']);
195
+ let filename;
196
+ if (isNewEntry || !currentPath) {
197
+ // For new entries, generate filename from title
198
+ const entryData = entryDraft.getIn(['entry', 'data']);
199
+ const title = entryData && entryData.get('title');
200
+ filename = cleanTitleForFilename(title);
201
+ } else {
202
+ // For existing entries, preserve the current filename
203
+ const {
204
+ basename: basenameFunc
205
+ } = require('path');
206
+ const currentFilename = basenameFunc(currentPath, `.${extension}`);
207
+ filename = currentFilename;
208
+ }
209
+ const customPath = join(collection.get('folder'), path, `${filename}.${extension}`);
210
+ return customPath;
211
+ }
212
+ export default entryDraftReducer;
@@ -0,0 +1,25 @@
1
+ import { produce } from 'immer';
2
+ import { USE_OPEN_AUTHORING } from '../actions/auth';
3
+ const LOADING_IGNORE_LIST = ['DEPLOY_PREVIEW', 'STATUS_REQUEST', 'STATUS_SUCCESS', 'STATUS_FAILURE'];
4
+ function ignoreWhenLoading(action) {
5
+ return LOADING_IGNORE_LIST.some(type => action.type.includes(type));
6
+ }
7
+ const defaultState = {
8
+ isFetching: false,
9
+ useOpenAuthoring: false
10
+ };
11
+
12
+ /**
13
+ * Reducer for some global UI state that we want to share between components
14
+ */
15
+ const globalUI = produce((state, action) => {
16
+ // Generic, global loading indicator
17
+ if (!ignoreWhenLoading(action) && action.type.includes('REQUEST')) {
18
+ state.isFetching = true;
19
+ } else if (!ignoreWhenLoading(action) && (action.type.includes('SUCCESS') || action.type.includes('FAILURE'))) {
20
+ state.isFetching = false;
21
+ } else if (action.type === USE_OPEN_AUTHORING) {
22
+ state.useOpenAuthoring = true;
23
+ }
24
+ }, defaultState);
25
+ export default globalUI;
@@ -0,0 +1,66 @@
1
+ import { List } from 'immutable';
2
+ import auth from './auth';
3
+ import config from './config';
4
+ import integrations, * as fromIntegrations from './integrations';
5
+ import entries, * as fromEntries from './entries';
6
+ import cursors from './cursors';
7
+ import editorialWorkflow, * as fromEditorialWorkflow from './editorialWorkflow';
8
+ import entryDraft from './entryDraft';
9
+ import collections from './collections';
10
+ import search from './search';
11
+ import medias from './medias';
12
+ import mediaLibrary from './mediaLibrary';
13
+ import deploys, * as fromDeploys from './deploys';
14
+ import globalUI from './globalUI';
15
+ import status from './status';
16
+ import notifications from './notifications';
17
+ const reducers = {
18
+ auth,
19
+ config,
20
+ collections,
21
+ search,
22
+ integrations,
23
+ entries,
24
+ cursors,
25
+ editorialWorkflow,
26
+ entryDraft,
27
+ medias,
28
+ mediaLibrary,
29
+ deploys,
30
+ globalUI,
31
+ status,
32
+ notifications
33
+ };
34
+ export default reducers;
35
+
36
+ /*
37
+ * Selectors
38
+ */
39
+ export function selectEntry(state, collection, slug) {
40
+ return fromEntries.selectEntry(state.entries, collection, slug);
41
+ }
42
+ export function selectEntries(state, collection) {
43
+ return fromEntries.selectEntries(state.entries, collection);
44
+ }
45
+ export function selectPublishedSlugs(state, collection) {
46
+ return fromEntries.selectPublishedSlugs(state.entries, collection);
47
+ }
48
+ export function selectSearchedEntries(state, availableCollections) {
49
+ // only return search results for actually available collections
50
+ return List(state.search.entryIds).filter(entryId => availableCollections.indexOf(entryId.collection) !== -1).map(entryId => fromEntries.selectEntry(state.entries, entryId.collection, entryId.slug));
51
+ }
52
+ export function selectDeployPreview(state, collection, slug) {
53
+ return fromDeploys.selectDeployPreview(state.deploys, collection, slug);
54
+ }
55
+ export function selectUnpublishedEntry(state, collection, slug) {
56
+ return fromEditorialWorkflow.selectUnpublishedEntry(state.editorialWorkflow, collection, slug);
57
+ }
58
+ export function selectUnpublishedEntriesByStatus(state, status) {
59
+ return fromEditorialWorkflow.selectUnpublishedEntriesByStatus(state.editorialWorkflow, status);
60
+ }
61
+ export function selectUnpublishedSlugs(state, collection) {
62
+ return fromEditorialWorkflow.selectUnpublishedSlugs(state.editorialWorkflow, collection);
63
+ }
64
+ export function selectIntegration(state, collection, hook) {
65
+ return fromIntegrations.selectIntegration(state.integrations, collection, hook);
66
+ }
@@ -0,0 +1,53 @@
1
+ import { fromJS } from 'immutable';
2
+ import { CONFIG_SUCCESS } from '../actions/config';
3
+ export function getIntegrations(config) {
4
+ const integrations = config.integrations || [];
5
+ const newState = integrations.reduce((acc, integration) => {
6
+ const {
7
+ hooks,
8
+ collections,
9
+ provider,
10
+ ...providerData
11
+ } = integration;
12
+ acc.providers[provider] = {
13
+ ...providerData
14
+ };
15
+ if (!collections) {
16
+ hooks.forEach(hook => {
17
+ acc.hooks[hook] = provider;
18
+ });
19
+ return acc;
20
+ }
21
+ const integrationCollections = collections === '*' ? config.collections.map(collection => collection.name) : collections;
22
+ integrationCollections.forEach(collection => {
23
+ hooks.forEach(hook => {
24
+ acc.hooks[collection] ? acc.hooks[collection][hook] = provider : acc.hooks[collection] = {
25
+ [hook]: provider
26
+ };
27
+ });
28
+ });
29
+ return acc;
30
+ }, {
31
+ providers: {},
32
+ hooks: {}
33
+ });
34
+ return fromJS(newState);
35
+ }
36
+ const defaultState = fromJS({
37
+ providers: {},
38
+ hooks: {}
39
+ });
40
+ function integrations(state = defaultState, action) {
41
+ switch (action.type) {
42
+ case CONFIG_SUCCESS:
43
+ {
44
+ return getIntegrations(action.payload);
45
+ }
46
+ default:
47
+ return state;
48
+ }
49
+ }
50
+ export function selectIntegration(state, collection, hook) {
51
+ return collection ? state.getIn(['hooks', collection, hook], false) : state.getIn(['hooks', hook], false);
52
+ }
53
+ export default integrations;
@@ -0,0 +1,252 @@
1
+ import { Map, List } from 'immutable';
2
+ import { v4 as uuid } from 'uuid';
3
+ import { dirname } from 'path';
4
+ import { MEDIA_LIBRARY_OPEN, MEDIA_LIBRARY_CLOSE, MEDIA_LIBRARY_CREATE, MEDIA_INSERT, MEDIA_REMOVE_INSERTED, MEDIA_LOAD_REQUEST, MEDIA_LOAD_SUCCESS, MEDIA_LOAD_FAILURE, MEDIA_PERSIST_REQUEST, MEDIA_PERSIST_SUCCESS, MEDIA_PERSIST_FAILURE, MEDIA_DELETE_REQUEST, MEDIA_DELETE_SUCCESS, MEDIA_DELETE_FAILURE, MEDIA_DISPLAY_URL_REQUEST, MEDIA_DISPLAY_URL_SUCCESS, MEDIA_DISPLAY_URL_FAILURE } from '../actions/mediaLibrary';
5
+ import { selectEditingDraft, selectMediaFolder } from './entries';
6
+ import { selectIntegration } from './';
7
+ const defaultState = {
8
+ isVisible: false,
9
+ showMediaButton: true,
10
+ controlMedia: Map(),
11
+ displayURLs: Map(),
12
+ config: Map()
13
+ };
14
+ function mediaLibrary(state = Map(defaultState), action) {
15
+ switch (action.type) {
16
+ case MEDIA_LIBRARY_CREATE:
17
+ return state.withMutations(map => {
18
+ map.set('externalLibrary', action.payload);
19
+ map.set('showMediaButton', action.payload.enableStandalone());
20
+ });
21
+ case MEDIA_LIBRARY_OPEN:
22
+ {
23
+ const {
24
+ controlID,
25
+ forImage,
26
+ privateUpload,
27
+ config,
28
+ field,
29
+ value,
30
+ replaceIndex
31
+ } = action.payload;
32
+ const libConfig = config || Map();
33
+ const privateUploadChanged = state.get('privateUpload') !== privateUpload;
34
+ if (privateUploadChanged) {
35
+ return Map({
36
+ isVisible: true,
37
+ forImage,
38
+ controlID,
39
+ canInsert: !!controlID,
40
+ privateUpload,
41
+ config: libConfig,
42
+ controlMedia: Map(),
43
+ displayURLs: Map(),
44
+ field,
45
+ value,
46
+ replaceIndex
47
+ });
48
+ }
49
+ return state.withMutations(map => {
50
+ map.set('isVisible', true);
51
+ map.set('forImage', forImage ?? false);
52
+ map.set('controlID', controlID ?? '');
53
+ map.set('canInsert', !!controlID);
54
+ map.set('privateUpload', privateUpload);
55
+ map.set('config', libConfig);
56
+ map.set('field', field ?? '');
57
+ map.set('value', value == '' && libConfig.get('multiple') ? [] : value ?? '');
58
+ map.set('replaceIndex', replaceIndex ?? false);
59
+ });
60
+ }
61
+ case MEDIA_LIBRARY_CLOSE:
62
+ return state.set('isVisible', false);
63
+ case MEDIA_INSERT:
64
+ {
65
+ const {
66
+ mediaPath
67
+ } = action.payload;
68
+ const controlID = state.get('controlID');
69
+ const value = state.get('value');
70
+ if (!Array.isArray(value)) {
71
+ return state.withMutations(map => {
72
+ map.setIn(['controlMedia', controlID], mediaPath);
73
+ });
74
+ }
75
+ const replaceIndex = state.get('replaceIndex');
76
+ const mediaArray = Array.isArray(mediaPath) ? mediaPath : [mediaPath];
77
+ const valueArray = value;
78
+ if (typeof replaceIndex == 'number') {
79
+ valueArray[replaceIndex] = mediaArray[0];
80
+ } else {
81
+ valueArray.push(...mediaArray);
82
+ }
83
+ return state.withMutations(map => {
84
+ map.setIn(['controlMedia', controlID], valueArray);
85
+ });
86
+ }
87
+ case MEDIA_REMOVE_INSERTED:
88
+ {
89
+ const controlID = action.payload.controlID;
90
+ return state.setIn(['controlMedia', controlID], '');
91
+ }
92
+ case MEDIA_LOAD_REQUEST:
93
+ return state.withMutations(map => {
94
+ map.set('isLoading', true);
95
+ map.set('isPaginating', action.payload.page > 1);
96
+ });
97
+ case MEDIA_LOAD_SUCCESS:
98
+ {
99
+ const {
100
+ files = [],
101
+ page,
102
+ canPaginate,
103
+ dynamicSearch,
104
+ dynamicSearchQuery,
105
+ privateUpload
106
+ } = action.payload;
107
+ const privateUploadChanged = state.get('privateUpload') !== privateUpload;
108
+ if (privateUploadChanged) {
109
+ return state;
110
+ }
111
+ const filesWithKeys = files.map(file => ({
112
+ ...file,
113
+ key: uuid()
114
+ }));
115
+ return state.withMutations(map => {
116
+ map.set('isLoading', false);
117
+ map.set('isPaginating', false);
118
+ map.set('page', page ?? 1);
119
+ map.set('hasNextPage', !!(canPaginate && files.length > 0));
120
+ map.set('dynamicSearch', dynamicSearch ?? false);
121
+ map.set('dynamicSearchQuery', dynamicSearchQuery ?? '');
122
+ map.set('dynamicSearchActive', !!dynamicSearchQuery);
123
+ if (page && page > 1) {
124
+ const updatedFiles = map.get('files').concat(filesWithKeys);
125
+ map.set('files', updatedFiles);
126
+ } else {
127
+ map.set('files', filesWithKeys);
128
+ }
129
+ });
130
+ }
131
+ case MEDIA_LOAD_FAILURE:
132
+ {
133
+ const privateUploadChanged = state.get('privateUpload') !== action.payload.privateUpload;
134
+ if (privateUploadChanged) {
135
+ return state;
136
+ }
137
+ return state.set('isLoading', false);
138
+ }
139
+ case MEDIA_PERSIST_REQUEST:
140
+ return state.set('isPersisting', true);
141
+ case MEDIA_PERSIST_SUCCESS:
142
+ {
143
+ const {
144
+ file,
145
+ privateUpload
146
+ } = action.payload;
147
+ const privateUploadChanged = state.get('privateUpload') !== privateUpload;
148
+ if (privateUploadChanged) {
149
+ return state;
150
+ }
151
+ return state.withMutations(map => {
152
+ const fileWithKey = {
153
+ ...file,
154
+ key: uuid()
155
+ };
156
+ const files = map.get('files');
157
+ const updatedFiles = [fileWithKey, ...files];
158
+ map.set('files', updatedFiles);
159
+ map.set('isPersisting', false);
160
+ });
161
+ }
162
+ case MEDIA_PERSIST_FAILURE:
163
+ {
164
+ const privateUploadChanged = state.get('privateUpload') !== action.payload.privateUpload;
165
+ if (privateUploadChanged) {
166
+ return state;
167
+ }
168
+ return state.set('isPersisting', false);
169
+ }
170
+ case MEDIA_DELETE_REQUEST:
171
+ return state.set('isDeleting', true);
172
+ case MEDIA_DELETE_SUCCESS:
173
+ {
174
+ const {
175
+ file,
176
+ privateUpload
177
+ } = action.payload;
178
+ const {
179
+ key,
180
+ id
181
+ } = file;
182
+ const privateUploadChanged = state.get('privateUpload') !== privateUpload;
183
+ if (privateUploadChanged) {
184
+ return state;
185
+ }
186
+ return state.withMutations(map => {
187
+ const files = map.get('files');
188
+ const updatedFiles = files.filter(file => key ? file.key !== key : file.id !== id);
189
+ map.set('files', updatedFiles);
190
+ map.deleteIn(['displayURLs', id]);
191
+ map.set('isDeleting', false);
192
+ });
193
+ }
194
+ case MEDIA_DELETE_FAILURE:
195
+ {
196
+ const privateUploadChanged = state.get('privateUpload') !== action.payload.privateUpload;
197
+ if (privateUploadChanged) {
198
+ return state;
199
+ }
200
+ return state.set('isDeleting', false);
201
+ }
202
+ case MEDIA_DISPLAY_URL_REQUEST:
203
+ return state.setIn(['displayURLs', action.payload.key, 'isFetching'], true);
204
+ case MEDIA_DISPLAY_URL_SUCCESS:
205
+ {
206
+ const displayURLPath = ['displayURLs', action.payload.key];
207
+ return state.setIn([...displayURLPath, 'isFetching'], false).setIn([...displayURLPath, 'url'], action.payload.url);
208
+ }
209
+ case MEDIA_DISPLAY_URL_FAILURE:
210
+ {
211
+ const displayURLPath = ['displayURLs', action.payload.key];
212
+ return state.setIn([...displayURLPath, 'isFetching'], false)
213
+ // make sure that err is set so the CMS won't attempt to load
214
+ // the image again
215
+ .setIn([...displayURLPath, 'err'], action.payload.err || true).deleteIn([...displayURLPath, 'url']);
216
+ }
217
+ default:
218
+ return state;
219
+ }
220
+ }
221
+ export function selectMediaFiles(state, field) {
222
+ const {
223
+ mediaLibrary,
224
+ entryDraft
225
+ } = state;
226
+ const editingDraft = selectEditingDraft(state.entryDraft);
227
+ const integration = selectIntegration(state, null, 'assetStore');
228
+ let files;
229
+ if (editingDraft && !integration) {
230
+ const entryFiles = entryDraft.getIn(['entry', 'mediaFiles'], List()).toJS();
231
+ const entry = entryDraft.get('entry');
232
+ const collection = state.collections.get(entry?.get('collection'));
233
+ const mediaFolder = selectMediaFolder(state.config, collection, entry, field);
234
+ files = entryFiles.filter(f => dirname(f.path) === mediaFolder).map(file => ({
235
+ key: file.id,
236
+ ...file
237
+ }));
238
+ } else {
239
+ files = mediaLibrary.get('files') || [];
240
+ }
241
+ return files;
242
+ }
243
+ export function selectMediaFileByPath(state, path) {
244
+ const files = selectMediaFiles(state);
245
+ const file = files.find(file => file.path === path);
246
+ return file;
247
+ }
248
+ export function selectMediaDisplayURL(state, id) {
249
+ const displayUrlState = state.mediaLibrary.getIn(['displayURLs', id], Map());
250
+ return displayUrlState;
251
+ }
252
+ export default mediaLibrary;
@@ -0,0 +1,68 @@
1
+ import { produce } from 'immer';
2
+ import { ADD_ASSETS, ADD_ASSET, REMOVE_ASSET, LOAD_ASSET_REQUEST, LOAD_ASSET_SUCCESS, LOAD_ASSET_FAILURE } from '../actions/media';
3
+ const defaultState = {};
4
+ const medias = produce((state, action) => {
5
+ switch (action.type) {
6
+ case ADD_ASSETS:
7
+ {
8
+ const assets = action.payload;
9
+ assets.forEach(asset => {
10
+ state[asset.path] = {
11
+ asset,
12
+ isLoading: false,
13
+ error: null
14
+ };
15
+ });
16
+ break;
17
+ }
18
+ case ADD_ASSET:
19
+ {
20
+ const asset = action.payload;
21
+ state[asset.path] = {
22
+ asset,
23
+ isLoading: false,
24
+ error: null
25
+ };
26
+ break;
27
+ }
28
+ case REMOVE_ASSET:
29
+ {
30
+ const path = action.payload;
31
+ delete state[path];
32
+ break;
33
+ }
34
+ case LOAD_ASSET_REQUEST:
35
+ {
36
+ const {
37
+ path
38
+ } = action.payload;
39
+ state[path] = state[path] || {};
40
+ state[path].isLoading = true;
41
+ break;
42
+ }
43
+ case LOAD_ASSET_SUCCESS:
44
+ {
45
+ const {
46
+ path
47
+ } = action.payload;
48
+ state[path] = state[path] || {};
49
+ state[path].isLoading = false;
50
+ state[path].error = null;
51
+ break;
52
+ }
53
+ case LOAD_ASSET_FAILURE:
54
+ {
55
+ const {
56
+ path,
57
+ error
58
+ } = action.payload;
59
+ state[path] = state[path] || {};
60
+ state[path].isLoading = false;
61
+ state[path].error = error;
62
+ }
63
+ }
64
+ }, defaultState);
65
+ export function selectIsLoadingAsset(state) {
66
+ return Object.values(state).some(state => state.isLoading);
67
+ }
68
+ export default medias;