@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,568 @@
1
+ import { Map, List, fromJS, OrderedMap, Set } from 'immutable';
2
+ import { dirname, join } from 'path';
3
+ import { isAbsolutePath, basename } from 'decap-cms-lib-util';
4
+ import trim from 'lodash/trim';
5
+ import once from 'lodash/once';
6
+ import sortBy from 'lodash/sortBy';
7
+ import set from 'lodash/set';
8
+ import orderBy from 'lodash/orderBy';
9
+ import groupBy from 'lodash/groupBy';
10
+ import { stringTemplate } from 'decap-cms-lib-widgets';
11
+ import { SortDirection } from '../types/redux';
12
+ import { folderFormatter } from '../lib/formatters';
13
+ import { selectSortDataPath } from './collections';
14
+ import { SEARCH_ENTRIES_SUCCESS } from '../actions/search';
15
+ import { ENTRY_REQUEST, ENTRY_SUCCESS, ENTRY_FAILURE, ENTRIES_REQUEST, ENTRIES_SUCCESS, ENTRIES_FAILURE, ENTRY_DELETE_SUCCESS, SORT_ENTRIES_REQUEST, SORT_ENTRIES_SUCCESS, SORT_ENTRIES_FAILURE, FILTER_ENTRIES_REQUEST, FILTER_ENTRIES_SUCCESS, FILTER_ENTRIES_FAILURE, GROUP_ENTRIES_REQUEST, GROUP_ENTRIES_SUCCESS, GROUP_ENTRIES_FAILURE, CHANGE_VIEW_STYLE } from '../actions/entries';
16
+ import { VIEW_STYLE_LIST } from '../constants/collectionViews';
17
+ import { joinUrlPath } from '../lib/urlHelper';
18
+ const {
19
+ keyToPathArray
20
+ } = stringTemplate;
21
+ let collection;
22
+ let loadedEntries;
23
+ let append;
24
+ let page;
25
+ let slug;
26
+ const storageSortKey = 'decap-cms.entries.sort';
27
+ const viewStyleKey = 'decap-cms.entries.viewStyle';
28
+ function normalizeDoubleSlashes(path) {
29
+ if (!path) {
30
+ return path;
31
+ }
32
+ return path.replace(/([^:]\/)\/+/g, '$1');
33
+ }
34
+ const loadSort = once(() => {
35
+ const sortString = localStorage.getItem(storageSortKey);
36
+ if (sortString) {
37
+ try {
38
+ const sort = JSON.parse(sortString);
39
+ let map = Map();
40
+ Object.entries(sort).forEach(([collection, sort]) => {
41
+ let orderedMap = OrderedMap();
42
+ sortBy(Object.values(sort), ['index']).forEach(value => {
43
+ const {
44
+ key,
45
+ direction
46
+ } = value;
47
+ orderedMap = orderedMap.set(key, fromJS({
48
+ key,
49
+ direction
50
+ }));
51
+ });
52
+ map = map.set(collection, orderedMap);
53
+ });
54
+ return map;
55
+ } catch (e) {
56
+ return Map();
57
+ }
58
+ }
59
+ return Map();
60
+ });
61
+ function clearSort() {
62
+ localStorage.removeItem(storageSortKey);
63
+ }
64
+ function persistSort(sort) {
65
+ if (sort) {
66
+ const storageSort = {};
67
+ sort.keySeq().forEach(key => {
68
+ const collection = key;
69
+ const sortObjects = sort.get(collection).valueSeq().toJS().map((value, index) => ({
70
+ ...value,
71
+ index
72
+ }));
73
+ sortObjects.forEach(value => {
74
+ set(storageSort, [collection, value.key], value);
75
+ });
76
+ });
77
+ localStorage.setItem(storageSortKey, JSON.stringify(storageSort));
78
+ } else {
79
+ clearSort();
80
+ }
81
+ }
82
+ const loadViewStyle = once(() => {
83
+ const viewStyle = localStorage.getItem(viewStyleKey);
84
+ if (viewStyle) {
85
+ return viewStyle;
86
+ }
87
+ localStorage.setItem(viewStyleKey, VIEW_STYLE_LIST);
88
+ return VIEW_STYLE_LIST;
89
+ });
90
+ function clearViewStyle() {
91
+ localStorage.removeItem(viewStyleKey);
92
+ }
93
+ function persistViewStyle(viewStyle) {
94
+ if (viewStyle) {
95
+ localStorage.setItem(viewStyleKey, viewStyle);
96
+ } else {
97
+ clearViewStyle();
98
+ }
99
+ }
100
+ function entries(state = Map({
101
+ entities: Map(),
102
+ pages: Map(),
103
+ sort: loadSort(),
104
+ viewStyle: loadViewStyle()
105
+ }), action) {
106
+ switch (action.type) {
107
+ case ENTRY_REQUEST:
108
+ {
109
+ const payload = action.payload;
110
+ return state.setIn(['entities', `${payload.collection}.${payload.slug}`, 'isFetching'], true);
111
+ }
112
+ case ENTRY_SUCCESS:
113
+ {
114
+ const payload = action.payload;
115
+ collection = payload.collection;
116
+ slug = payload.entry.slug;
117
+ return state.withMutations(map => {
118
+ map.setIn(['entities', `${collection}.${slug}`], fromJS(payload.entry));
119
+ const ids = map.getIn(['pages', collection, 'ids'], List());
120
+ if (!ids.includes(slug)) {
121
+ map.setIn(['pages', collection, 'ids'], ids.unshift(slug));
122
+ }
123
+ });
124
+ }
125
+ case ENTRIES_REQUEST:
126
+ {
127
+ const payload = action.payload;
128
+ const newState = state.withMutations(map => {
129
+ map.setIn(['pages', payload.collection, 'isFetching'], true);
130
+ });
131
+ return newState;
132
+ }
133
+ case ENTRIES_SUCCESS:
134
+ {
135
+ const payload = action.payload;
136
+ collection = payload.collection;
137
+ loadedEntries = payload.entries;
138
+ append = payload.append;
139
+ page = payload.page;
140
+ return state.withMutations(map => {
141
+ loadedEntries.forEach(entry => map.setIn(['entities', `${collection}.${entry.slug}`], fromJS(entry).set('isFetching', false)));
142
+ const ids = List(loadedEntries.map(entry => entry.slug));
143
+ map.setIn(['pages', collection], Map({
144
+ page,
145
+ ids: append ? map.getIn(['pages', collection, 'ids'], List()).concat(ids) : ids
146
+ }));
147
+ });
148
+ }
149
+ case ENTRIES_FAILURE:
150
+ return state.setIn(['pages', action.meta.collection, 'isFetching'], false);
151
+ case ENTRY_FAILURE:
152
+ {
153
+ const payload = action.payload;
154
+ return state.withMutations(map => {
155
+ map.setIn(['entities', `${payload.collection}.${payload.slug}`, 'isFetching'], false);
156
+ map.setIn(['entities', `${payload.collection}.${payload.slug}`, 'error'], payload.error.message);
157
+ });
158
+ }
159
+ case SEARCH_ENTRIES_SUCCESS:
160
+ {
161
+ const payload = action.payload;
162
+ loadedEntries = payload.entries;
163
+ return state.withMutations(map => {
164
+ loadedEntries.forEach(entry => map.setIn(['entities', `${entry.collection}.${entry.slug}`], fromJS(entry).set('isFetching', false)));
165
+ });
166
+ }
167
+ case ENTRY_DELETE_SUCCESS:
168
+ {
169
+ const payload = action.payload;
170
+ return state.withMutations(map => {
171
+ map.deleteIn(['entities', `${payload.collectionName}.${payload.entrySlug}`]);
172
+ map.updateIn(['pages', payload.collectionName, 'ids'], ids => ids.filter(id => id !== payload.entrySlug));
173
+ });
174
+ }
175
+ case SORT_ENTRIES_REQUEST:
176
+ {
177
+ const payload = action.payload;
178
+ const {
179
+ collection,
180
+ key,
181
+ direction
182
+ } = payload;
183
+ const newState = state.withMutations(map => {
184
+ const sort = OrderedMap({
185
+ [key]: Map({
186
+ key,
187
+ direction
188
+ })
189
+ });
190
+ map.setIn(['sort', collection], sort);
191
+ map.setIn(['pages', collection, 'isFetching'], true);
192
+ map.deleteIn(['pages', collection, 'page']);
193
+ });
194
+ persistSort(newState.get('sort'));
195
+ return newState;
196
+ }
197
+ case GROUP_ENTRIES_SUCCESS:
198
+ case FILTER_ENTRIES_SUCCESS:
199
+ case SORT_ENTRIES_SUCCESS:
200
+ {
201
+ const payload = action.payload;
202
+ const {
203
+ collection,
204
+ entries
205
+ } = payload;
206
+ loadedEntries = entries;
207
+ const newState = state.withMutations(map => {
208
+ loadedEntries.forEach(entry => map.setIn(['entities', `${entry.collection}.${entry.slug}`], fromJS(entry).set('isFetching', false)));
209
+ map.setIn(['pages', collection, 'isFetching'], false);
210
+ const ids = List(loadedEntries.map(entry => entry.slug));
211
+ map.setIn(['pages', collection], Map({
212
+ page: 1,
213
+ ids
214
+ }));
215
+ });
216
+ return newState;
217
+ }
218
+ case SORT_ENTRIES_FAILURE:
219
+ {
220
+ const payload = action.payload;
221
+ const {
222
+ collection,
223
+ key
224
+ } = payload;
225
+ const newState = state.withMutations(map => {
226
+ map.deleteIn(['sort', collection, key]);
227
+ map.setIn(['pages', collection, 'isFetching'], false);
228
+ });
229
+ persistSort(newState.get('sort'));
230
+ return newState;
231
+ }
232
+ case FILTER_ENTRIES_REQUEST:
233
+ {
234
+ const payload = action.payload;
235
+ const {
236
+ collection,
237
+ filter
238
+ } = payload;
239
+ const newState = state.withMutations(map => {
240
+ const current = map.getIn(['filter', collection, filter.id], fromJS(filter));
241
+ map.setIn(['filter', collection, current.get('id')], current.set('active', !current.get('active')));
242
+ });
243
+ return newState;
244
+ }
245
+ case FILTER_ENTRIES_FAILURE:
246
+ {
247
+ const payload = action.payload;
248
+ const {
249
+ collection,
250
+ filter
251
+ } = payload;
252
+ const newState = state.withMutations(map => {
253
+ map.deleteIn(['filter', collection, filter.id]);
254
+ map.setIn(['pages', collection, 'isFetching'], false);
255
+ });
256
+ return newState;
257
+ }
258
+ case GROUP_ENTRIES_REQUEST:
259
+ {
260
+ const payload = action.payload;
261
+ const {
262
+ collection,
263
+ group
264
+ } = payload;
265
+ const newState = state.withMutations(map => {
266
+ const current = map.getIn(['group', collection, group.id], fromJS(group));
267
+ map.deleteIn(['group', collection]);
268
+ map.setIn(['group', collection, current.get('id')], current.set('active', !current.get('active')));
269
+ });
270
+ return newState;
271
+ }
272
+ case GROUP_ENTRIES_FAILURE:
273
+ {
274
+ const payload = action.payload;
275
+ const {
276
+ collection,
277
+ group
278
+ } = payload;
279
+ const newState = state.withMutations(map => {
280
+ map.deleteIn(['group', collection, group.id]);
281
+ map.setIn(['pages', collection, 'isFetching'], false);
282
+ });
283
+ return newState;
284
+ }
285
+ case CHANGE_VIEW_STYLE:
286
+ {
287
+ const payload = action.payload;
288
+ const {
289
+ style
290
+ } = payload;
291
+ const newState = state.withMutations(map => {
292
+ map.setIn(['viewStyle'], style);
293
+ });
294
+ persistViewStyle(newState.get('viewStyle'));
295
+ return newState;
296
+ }
297
+ default:
298
+ return state;
299
+ }
300
+ }
301
+ export function selectEntriesSort(entries, collection) {
302
+ const sort = entries.get('sort');
303
+ return sort?.get(collection);
304
+ }
305
+ export function selectEntriesFilter(entries, collection) {
306
+ const filter = entries.get('filter');
307
+ return filter?.get(collection) || Map();
308
+ }
309
+ export function selectEntriesGroup(entries, collection) {
310
+ const group = entries.get('group');
311
+ return group?.get(collection) || Map();
312
+ }
313
+ export function selectEntriesGroupField(entries, collection) {
314
+ const groups = selectEntriesGroup(entries, collection);
315
+ const value = groups?.valueSeq().find(v => v?.get('active') === true);
316
+ return value;
317
+ }
318
+ export function selectEntriesSortFields(entries, collection) {
319
+ const sort = selectEntriesSort(entries, collection);
320
+ const values = sort?.valueSeq().filter(v => v?.get('direction') !== SortDirection.None).toArray() || [];
321
+ return values;
322
+ }
323
+ export function selectEntriesFilterFields(entries, collection) {
324
+ const filter = selectEntriesFilter(entries, collection);
325
+ const values = filter?.valueSeq().filter(v => v?.get('active') === true).toArray() || [];
326
+ return values;
327
+ }
328
+ export function selectViewStyle(entries) {
329
+ return entries.get('viewStyle');
330
+ }
331
+ export function selectEntry(state, collection, slug) {
332
+ return state.getIn(['entities', `${collection}.${slug}`]);
333
+ }
334
+ export function selectPublishedSlugs(state, collection) {
335
+ return state.getIn(['pages', collection, 'ids'], List());
336
+ }
337
+ function getPublishedEntries(state, collectionName) {
338
+ const slugs = selectPublishedSlugs(state, collectionName);
339
+ const entries = slugs && slugs.map(slug => selectEntry(state, collectionName, slug));
340
+ return entries;
341
+ }
342
+ export function selectEntries(state, collection) {
343
+ const collectionName = collection.get('name');
344
+ let entries = getPublishedEntries(state, collectionName);
345
+ const sortFields = selectEntriesSortFields(state, collectionName);
346
+ if (sortFields && sortFields.length > 0) {
347
+ const keys = sortFields.map(v => selectSortDataPath(collection, v.get('key')));
348
+ const orders = sortFields.map(v => v.get('direction') === SortDirection.Ascending ? 'asc' : 'desc');
349
+ entries = fromJS(orderBy(entries.toJS(), keys, orders));
350
+ }
351
+ const filters = selectEntriesFilterFields(state, collectionName);
352
+ if (filters && filters.length > 0) {
353
+ entries = entries.filter(e => {
354
+ const allMatched = filters.every(f => {
355
+ const pattern = f.get('pattern');
356
+ const field = f.get('field');
357
+ const data = e.get('data') || Map();
358
+ const toMatch = data.getIn(keyToPathArray(field));
359
+ const matched = toMatch !== undefined && new RegExp(String(pattern)).test(String(toMatch));
360
+ return matched;
361
+ });
362
+ return allMatched;
363
+ }).toList();
364
+ }
365
+ return entries;
366
+ }
367
+ function getGroup(entry, selectedGroup) {
368
+ const label = selectedGroup.get('label');
369
+ const field = selectedGroup.get('field');
370
+ const fieldData = entry.getIn(['data', ...keyToPathArray(field)]);
371
+ if (fieldData === undefined) {
372
+ return {
373
+ id: 'missing_value',
374
+ label,
375
+ value: fieldData
376
+ };
377
+ }
378
+ const dataAsString = String(fieldData);
379
+ if (selectedGroup.has('pattern')) {
380
+ const pattern = selectedGroup.get('pattern');
381
+ let value = '';
382
+ try {
383
+ const regex = new RegExp(pattern);
384
+ const matched = dataAsString.match(regex);
385
+ if (matched) {
386
+ value = matched[0];
387
+ }
388
+ } catch (e) {
389
+ console.warn(`Invalid view group pattern '${pattern}' for field '${field}'`, e);
390
+ }
391
+ return {
392
+ id: `${label}${value}`,
393
+ label,
394
+ value
395
+ };
396
+ }
397
+ return {
398
+ id: `${label}${fieldData}`,
399
+ label,
400
+ value: typeof fieldData === 'boolean' ? fieldData : dataAsString
401
+ };
402
+ }
403
+ export function selectGroups(state, collection) {
404
+ const collectionName = collection.get('name');
405
+ const entries = getPublishedEntries(state, collectionName);
406
+ const selectedGroup = selectEntriesGroupField(state, collectionName);
407
+ if (selectedGroup === undefined) {
408
+ return [];
409
+ }
410
+ let groups = {};
411
+ const groupedEntries = groupBy(entries.toArray(), entry => {
412
+ const group = getGroup(entry, selectedGroup);
413
+ groups = {
414
+ ...groups,
415
+ [group.id]: group
416
+ };
417
+ return group.id;
418
+ });
419
+ const groupsArray = Object.entries(groupedEntries).map(([id, entries]) => {
420
+ return {
421
+ ...groups[id],
422
+ paths: Set(entries.map(entry => entry.get('path')))
423
+ };
424
+ });
425
+ return groupsArray;
426
+ }
427
+ export function selectEntryByPath(state, collection, path) {
428
+ const slugs = selectPublishedSlugs(state, collection);
429
+ const entries = slugs && slugs.map(slug => selectEntry(state, collection, slug));
430
+ return entries && entries.find(e => e?.get('path') === path);
431
+ }
432
+ export function selectEntriesLoaded(state, collection) {
433
+ return !!state.getIn(['pages', collection]);
434
+ }
435
+ export function selectIsFetching(state, collection) {
436
+ return state.getIn(['pages', collection, 'isFetching'], false);
437
+ }
438
+ function getFileField(collectionFiles, slug) {
439
+ const file = collectionFiles.find(f => f?.get('name') === slug);
440
+ return file;
441
+ }
442
+ function hasCustomFolder(folderKey, collection, slug, field) {
443
+ if (!collection) {
444
+ return false;
445
+ }
446
+ if (field && field.has(folderKey)) {
447
+ return true;
448
+ }
449
+ if (collection.has('files')) {
450
+ const file = getFileField(collection.get('files'), slug);
451
+ if (file && file.has(folderKey)) {
452
+ return true;
453
+ }
454
+ }
455
+ if (collection.has(folderKey)) {
456
+ return true;
457
+ }
458
+ return false;
459
+ }
460
+ function traverseFields(folderKey, config, collection, entryMap, field, fields, currentFolder) {
461
+ const matchedField = fields.filter(f => f === field)[0];
462
+ if (matchedField) {
463
+ return folderFormatter(matchedField.has(folderKey) ? matchedField.get(folderKey) : `{{${folderKey}}}`, entryMap, collection, currentFolder, folderKey, config.slug);
464
+ }
465
+ for (let f of fields) {
466
+ if (!f.has(folderKey)) {
467
+ // add identity template if doesn't exist
468
+ f = f.set(folderKey, `{{${folderKey}}}`);
469
+ }
470
+ const folder = folderFormatter(f.get(folderKey), entryMap, collection, currentFolder, folderKey, config.slug);
471
+ let fieldFolder = null;
472
+ if (f.has('fields')) {
473
+ fieldFolder = traverseFields(folderKey, config, collection, entryMap, field, f.get('fields').toArray(), folder);
474
+ } else if (f.has('field')) {
475
+ fieldFolder = traverseFields(folderKey, config, collection, entryMap, field, [f.get('field')], folder);
476
+ } else if (f.has('types')) {
477
+ fieldFolder = traverseFields(folderKey, config, collection, entryMap, field, f.get('types').toArray(), folder);
478
+ }
479
+ if (fieldFolder != null) {
480
+ return fieldFolder;
481
+ }
482
+ }
483
+ return null;
484
+ }
485
+ function evaluateFolder(folderKey, config, collection, entryMap, field) {
486
+ let currentFolder = config[folderKey];
487
+
488
+ // add identity template if doesn't exist
489
+ if (!collection.has(folderKey)) {
490
+ collection = collection.set(folderKey, `{{${folderKey}}}`);
491
+ }
492
+ if (collection.has('files')) {
493
+ // files collection evaluate the collection template
494
+ // then move on to the specific file configuration denoted by the slug
495
+ currentFolder = folderFormatter(collection.get(folderKey), entryMap, collection, currentFolder, folderKey, config.slug);
496
+ let file = getFileField(collection.get('files'), entryMap?.get('slug'));
497
+ if (file) {
498
+ if (!file.has(folderKey)) {
499
+ // add identity template if doesn't exist
500
+ file = file.set(folderKey, `{{${folderKey}}}`);
501
+ }
502
+
503
+ // evaluate the file template and keep evaluating until we match our field
504
+ currentFolder = folderFormatter(file.get(folderKey), entryMap, collection, currentFolder, folderKey, config.slug);
505
+ if (field) {
506
+ const fieldFolder = traverseFields(folderKey, config, collection, entryMap, field, file.get('fields').toArray(), currentFolder);
507
+ if (fieldFolder !== null) {
508
+ currentFolder = fieldFolder;
509
+ }
510
+ }
511
+ }
512
+ } else {
513
+ // folder collection, evaluate the collection template
514
+ // and keep evaluating until we match our field
515
+ currentFolder = folderFormatter(collection.get(folderKey), entryMap, collection, currentFolder, folderKey, config.slug);
516
+ if (field) {
517
+ const fieldFolder = traverseFields(folderKey, config, collection, entryMap, field, collection.get('fields').toArray(), currentFolder);
518
+ if (fieldFolder !== null) {
519
+ currentFolder = fieldFolder;
520
+ }
521
+ }
522
+ }
523
+ return currentFolder;
524
+ }
525
+ export function selectMediaFolder(config, collection, entryMap, field) {
526
+ const name = 'media_folder';
527
+ let mediaFolder = config[name];
528
+ const customFolder = hasCustomFolder(name, collection, entryMap?.get('slug'), field);
529
+ if (customFolder) {
530
+ const folder = evaluateFolder(name, config, collection, entryMap, field);
531
+ if (folder.startsWith('/')) {
532
+ // return absolute paths as is
533
+ mediaFolder = join(folder);
534
+ } else {
535
+ const entryPath = entryMap?.get('path');
536
+ mediaFolder = entryPath ? join(dirname(entryPath), folder) : collection.get('folder');
537
+ }
538
+ }
539
+ return trim(mediaFolder, '/');
540
+ }
541
+ export function selectMediaFilePath(config, collection, entryMap, mediaPath, field) {
542
+ if (isAbsolutePath(mediaPath)) {
543
+ return mediaPath;
544
+ }
545
+ const mediaFolder = selectMediaFolder(config, collection, entryMap, field);
546
+ return join(mediaFolder, basename(mediaPath));
547
+ }
548
+ export function selectMediaFilePublicPath(config, collection, mediaPath, entryMap, field) {
549
+ if (isAbsolutePath(mediaPath)) {
550
+ return mediaPath;
551
+ }
552
+ const name = 'public_folder';
553
+ let publicFolder = normalizeDoubleSlashes(config[name]);
554
+ const customFolder = hasCustomFolder(name, collection, entryMap?.get('slug'), field);
555
+ if (customFolder) {
556
+ publicFolder = normalizeDoubleSlashes(evaluateFolder(name, config, collection, entryMap, field));
557
+ }
558
+ if (isAbsolutePath(publicFolder)) {
559
+ return joinUrlPath(publicFolder, basename(mediaPath));
560
+ }
561
+ return join(publicFolder, basename(mediaPath));
562
+ }
563
+ export function selectEditingDraft(state) {
564
+ const entry = state.get('entry');
565
+ const workflowDraft = entry && !entry.isEmpty();
566
+ return workflowDraft;
567
+ }
568
+ export default entries;