@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.
- package/README.md +9 -0
- package/dist/@pranaysahith/decap-cms-core.js +52 -0
- package/dist/@pranaysahith/decap-cms-core.js.LICENSE.txt +141 -0
- package/dist/@pranaysahith/decap-cms-core.js.map +1 -0
- package/dist/decap-cms-core.js +47 -0
- package/dist/decap-cms-core.js.LICENSE.txt +116 -0
- package/dist/decap-cms-core.js.map +1 -0
- package/dist/esm/actions/auth.js +97 -0
- package/dist/esm/actions/collections.js +15 -0
- package/dist/esm/actions/config.js +493 -0
- package/dist/esm/actions/deploys.js +79 -0
- package/dist/esm/actions/editorialWorkflow.js +480 -0
- package/dist/esm/actions/entries.js +865 -0
- package/dist/esm/actions/media.js +147 -0
- package/dist/esm/actions/mediaLibrary.js +552 -0
- package/dist/esm/actions/notifications.js +21 -0
- package/dist/esm/actions/search.js +149 -0
- package/dist/esm/actions/status.js +74 -0
- package/dist/esm/actions/waitUntil.js +32 -0
- package/dist/esm/backend.js +1082 -0
- package/dist/esm/bootstrap.js +101 -0
- package/dist/esm/components/App/App.js +289 -0
- package/dist/esm/components/App/Header.js +172 -0
- package/dist/esm/components/App/NotFoundPage.js +19 -0
- package/dist/esm/components/Collection/Collection.js +198 -0
- package/dist/esm/components/Collection/CollectionControls.js +46 -0
- package/dist/esm/components/Collection/CollectionSearch.js +222 -0
- package/dist/esm/components/Collection/CollectionTop.js +68 -0
- package/dist/esm/components/Collection/ControlButton.js +17 -0
- package/dist/esm/components/Collection/Entries/Entries.js +73 -0
- package/dist/esm/components/Collection/Entries/EntriesCollection.js +241 -0
- package/dist/esm/components/Collection/Entries/EntriesSearch.js +113 -0
- package/dist/esm/components/Collection/Entries/EntryCard.js +177 -0
- package/dist/esm/components/Collection/Entries/EntryListing.js +143 -0
- package/dist/esm/components/Collection/FilterControl.js +33 -0
- package/dist/esm/components/Collection/FolderRenameControl.js +403 -0
- package/dist/esm/components/Collection/GroupControl.js +33 -0
- package/dist/esm/components/Collection/NestedCollection.js +308 -0
- package/dist/esm/components/Collection/Sidebar.js +91 -0
- package/dist/esm/components/Collection/SortControl.js +59 -0
- package/dist/esm/components/Collection/ViewStyleControl.js +38 -0
- package/dist/esm/components/Editor/Editor.js +466 -0
- package/dist/esm/components/Editor/EditorControlPane/EditorControl.js +395 -0
- package/dist/esm/components/Editor/EditorControlPane/EditorControlPane.js +254 -0
- package/dist/esm/components/Editor/EditorControlPane/Widget.js +374 -0
- package/dist/esm/components/Editor/EditorInterface.js +386 -0
- package/dist/esm/components/Editor/EditorPreviewPane/EditorPreview.js +47 -0
- package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewContent.js +66 -0
- package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewPane.js +288 -0
- package/dist/esm/components/Editor/EditorPreviewPane/PreviewHOC.js +27 -0
- package/dist/esm/components/Editor/EditorToolbar.js +536 -0
- package/dist/esm/components/Editor/EntryPathEditor.js +272 -0
- package/dist/esm/components/Editor/withWorkflow.js +56 -0
- package/dist/esm/components/EditorWidgets/Unknown/UnknownControl.js +18 -0
- package/dist/esm/components/EditorWidgets/Unknown/UnknownPreview.js +20 -0
- package/dist/esm/components/EditorWidgets/index.js +4 -0
- package/dist/esm/components/MediaLibrary/EmptyMessage.js +22 -0
- package/dist/esm/components/MediaLibrary/MediaLibrary.js +446 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryButtons.js +93 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryCard.js +99 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryCardGrid.js +198 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryHeader.js +32 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryModal.js +156 -0
- package/dist/esm/components/MediaLibrary/MediaLibrarySearch.js +51 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryTop.js +123 -0
- package/dist/esm/components/UI/DragDrop.js +67 -0
- package/dist/esm/components/UI/ErrorBoundary.js +173 -0
- package/dist/esm/components/UI/FileUploadButton.js +27 -0
- package/dist/esm/components/UI/Modal.js +104 -0
- package/dist/esm/components/UI/Notifications.js +62 -0
- package/dist/esm/components/UI/SettingsDropdown.js +107 -0
- package/dist/esm/components/UI/index.js +6 -0
- package/dist/esm/components/Workflow/Workflow.js +133 -0
- package/dist/esm/components/Workflow/WorkflowCard.js +128 -0
- package/dist/esm/components/Workflow/WorkflowList.js +204 -0
- package/dist/esm/constants/collectionTypes.js +2 -0
- package/dist/esm/constants/collectionViews.js +2 -0
- package/dist/esm/constants/commitProps.js +2 -0
- package/dist/esm/constants/configSchema.js +644 -0
- package/dist/esm/constants/fieldInference.js +57 -0
- package/dist/esm/constants/publishModes.js +18 -0
- package/dist/esm/constants/validationErrorTypes.js +6 -0
- package/dist/esm/formats/formats.js +83 -0
- package/dist/esm/formats/frontmatter.js +146 -0
- package/dist/esm/formats/helpers.js +12 -0
- package/dist/esm/formats/json.js +8 -0
- package/dist/esm/formats/toml.js +32 -0
- package/dist/esm/formats/yaml.js +51 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/integrations/index.js +28 -0
- package/dist/esm/integrations/providers/algolia/implementation.js +174 -0
- package/dist/esm/integrations/providers/assetStore/implementation.js +165 -0
- package/dist/esm/lib/consoleError.js +3 -0
- package/dist/esm/lib/formatters.js +191 -0
- package/dist/esm/lib/i18n.js +367 -0
- package/dist/esm/lib/phrases.js +6 -0
- package/dist/esm/lib/polyfill.js +8 -0
- package/dist/esm/lib/registry.js +329 -0
- package/dist/esm/lib/serializeEntryValues.js +67 -0
- package/dist/esm/lib/stega.js +142 -0
- package/dist/esm/lib/textHelper.js +9 -0
- package/dist/esm/lib/urlHelper.js +111 -0
- package/dist/esm/mediaLibrary.js +37 -0
- package/dist/esm/reducers/auth.js +27 -0
- package/dist/esm/reducers/collections.js +428 -0
- package/dist/esm/reducers/combinedReducer.js +8 -0
- package/dist/esm/reducers/config.js +29 -0
- package/dist/esm/reducers/cursors.js +31 -0
- package/dist/esm/reducers/deploys.js +45 -0
- package/dist/esm/reducers/editorialWorkflow.js +83 -0
- package/dist/esm/reducers/entries.js +568 -0
- package/dist/esm/reducers/entryDraft.js +212 -0
- package/dist/esm/reducers/globalUI.js +25 -0
- package/dist/esm/reducers/index.js +66 -0
- package/dist/esm/reducers/integrations.js +53 -0
- package/dist/esm/reducers/mediaLibrary.js +252 -0
- package/dist/esm/reducers/medias.js +68 -0
- package/dist/esm/reducers/notifications.js +23 -0
- package/dist/esm/reducers/search.js +92 -0
- package/dist/esm/reducers/status.js +30 -0
- package/dist/esm/redux/index.js +7 -0
- package/dist/esm/redux/middleware/waitUntilAction.js +48 -0
- package/dist/esm/routing/history.js +12 -0
- package/dist/esm/types/diacritics.d.js +0 -0
- package/dist/esm/types/global.d.js +1 -0
- package/dist/esm/types/immutable.js +7 -0
- package/dist/esm/types/redux.js +14 -0
- package/dist/esm/types/tomlify-j0.4.d.js +0 -0
- package/dist/esm/valueObjects/AssetProxy.js +44 -0
- package/dist/esm/valueObjects/EditorComponent.js +34 -0
- package/dist/esm/valueObjects/Entry.js +20 -0
- package/index.d.ts +618 -0
- package/package.json +106 -0
- package/src/__tests__/backend.spec.js +1161 -0
- package/src/actions/__tests__/config.spec.js +1009 -0
- package/src/actions/__tests__/editorialWorkflow.spec.js +216 -0
- package/src/actions/__tests__/entries.spec.js +596 -0
- package/src/actions/__tests__/media.spec.ts +171 -0
- package/src/actions/__tests__/mediaLibrary.spec.js +327 -0
- package/src/actions/__tests__/search.spec.js +209 -0
- package/src/actions/auth.ts +127 -0
- package/src/actions/collections.ts +18 -0
- package/src/actions/config.ts +565 -0
- package/src/actions/deploys.ts +104 -0
- package/src/actions/editorialWorkflow.ts +567 -0
- package/src/actions/entries.ts +1055 -0
- package/src/actions/media.ts +139 -0
- package/src/actions/mediaLibrary.ts +574 -0
- package/src/actions/notifications.ts +36 -0
- package/src/actions/search.ts +221 -0
- package/src/actions/status.ts +99 -0
- package/src/actions/waitUntil.ts +49 -0
- package/src/backend.ts +1400 -0
- package/src/bootstrap.js +104 -0
- package/src/components/App/App.js +286 -0
- package/src/components/App/Header.js +266 -0
- package/src/components/App/NotFoundPage.js +23 -0
- package/src/components/Collection/Collection.js +210 -0
- package/src/components/Collection/CollectionControls.js +58 -0
- package/src/components/Collection/CollectionSearch.js +243 -0
- package/src/components/Collection/CollectionTop.js +81 -0
- package/src/components/Collection/ControlButton.js +27 -0
- package/src/components/Collection/Entries/Entries.js +82 -0
- package/src/components/Collection/Entries/EntriesCollection.js +277 -0
- package/src/components/Collection/Entries/EntriesSearch.js +102 -0
- package/src/components/Collection/Entries/EntryCard.js +246 -0
- package/src/components/Collection/Entries/EntryListing.js +151 -0
- package/src/components/Collection/Entries/__tests__/EntriesCollection.spec.js +163 -0
- package/src/components/Collection/Entries/__tests__/__snapshots__/EntriesCollection.spec.js.snap +46 -0
- package/src/components/Collection/FilterControl.js +39 -0
- package/src/components/Collection/GroupControl.js +39 -0
- package/src/components/Collection/NestedCollection.js +330 -0
- package/src/components/Collection/Sidebar.js +136 -0
- package/src/components/Collection/SortControl.js +68 -0
- package/src/components/Collection/ViewStyleControl.js +50 -0
- package/src/components/Collection/__tests__/Collection.spec.js +75 -0
- package/src/components/Collection/__tests__/NestedCollection.spec.js +445 -0
- package/src/components/Collection/__tests__/Sidebar.spec.js +87 -0
- package/src/components/Collection/__tests__/__snapshots__/Collection.spec.js.snap +144 -0
- package/src/components/Collection/__tests__/__snapshots__/NestedCollection.spec.js.snap +550 -0
- package/src/components/Collection/__tests__/__snapshots__/Sidebar.spec.js.snap +312 -0
- package/src/components/Editor/Editor.js +497 -0
- package/src/components/Editor/EditorControlPane/EditorControl.js +452 -0
- package/src/components/Editor/EditorControlPane/EditorControlPane.js +269 -0
- package/src/components/Editor/EditorControlPane/Widget.js +384 -0
- package/src/components/Editor/EditorInterface.js +444 -0
- package/src/components/Editor/EditorPreviewPane/EditorPreview.js +40 -0
- package/src/components/Editor/EditorPreviewPane/EditorPreviewContent.js +74 -0
- package/src/components/Editor/EditorPreviewPane/EditorPreviewPane.js +333 -0
- package/src/components/Editor/EditorPreviewPane/PreviewHOC.js +33 -0
- package/src/components/Editor/EditorToolbar.js +691 -0
- package/src/components/Editor/__tests__/Editor.spec.js +221 -0
- package/src/components/Editor/__tests__/EditorToolbar.spec.js +120 -0
- package/src/components/Editor/__tests__/__snapshots__/Editor.spec.js.snap +45 -0
- package/src/components/Editor/__tests__/__snapshots__/EditorToolbar.spec.js.snap +4233 -0
- package/src/components/Editor/withWorkflow.js +61 -0
- package/src/components/EditorWidgets/Unknown/UnknownControl.js +17 -0
- package/src/components/EditorWidgets/Unknown/UnknownPreview.js +19 -0
- package/src/components/EditorWidgets/index.js +5 -0
- package/src/components/MediaLibrary/EmptyMessage.js +28 -0
- package/src/components/MediaLibrary/MediaLibrary.js +411 -0
- package/src/components/MediaLibrary/MediaLibraryButtons.js +136 -0
- package/src/components/MediaLibrary/MediaLibraryCard.js +128 -0
- package/src/components/MediaLibrary/MediaLibraryCardGrid.js +199 -0
- package/src/components/MediaLibrary/MediaLibraryHeader.js +48 -0
- package/src/components/MediaLibrary/MediaLibraryModal.js +200 -0
- package/src/components/MediaLibrary/MediaLibrarySearch.js +61 -0
- package/src/components/MediaLibrary/MediaLibraryTop.js +143 -0
- package/src/components/MediaLibrary/__tests__/MediaLibraryButtons.spec.js +45 -0
- package/src/components/MediaLibrary/__tests__/MediaLibraryCard.spec.js +49 -0
- package/src/components/MediaLibrary/__tests__/__snapshots__/MediaLibraryCard.spec.js.snap +264 -0
- package/src/components/UI/DragDrop.js +66 -0
- package/src/components/UI/ErrorBoundary.js +214 -0
- package/src/components/UI/FileUploadButton.js +24 -0
- package/src/components/UI/Modal.js +112 -0
- package/src/components/UI/Notifications.tsx +83 -0
- package/src/components/UI/SettingsDropdown.js +103 -0
- package/src/components/UI/__tests__/ErrorBoundary.spec.js +57 -0
- package/src/components/UI/index.js +6 -0
- package/src/components/Workflow/Workflow.js +169 -0
- package/src/components/Workflow/WorkflowCard.js +177 -0
- package/src/components/Workflow/WorkflowList.js +272 -0
- package/src/constants/__tests__/configSchema.spec.js +611 -0
- package/src/constants/collectionTypes.ts +2 -0
- package/src/constants/collectionViews.js +2 -0
- package/src/constants/commitProps.ts +2 -0
- package/src/constants/configSchema.js +441 -0
- package/src/constants/fieldInference.tsx +78 -0
- package/src/constants/publishModes.ts +22 -0
- package/src/constants/validationErrorTypes.js +6 -0
- package/src/formats/__tests__/formats.spec.js +87 -0
- package/src/formats/__tests__/frontmatter.spec.js +429 -0
- package/src/formats/__tests__/toml.spec.js +9 -0
- package/src/formats/__tests__/yaml.spec.js +162 -0
- package/src/formats/formats.ts +97 -0
- package/src/formats/frontmatter.ts +150 -0
- package/src/formats/helpers.ts +14 -0
- package/src/formats/json.ts +9 -0
- package/src/formats/toml.ts +33 -0
- package/src/formats/yaml.ts +58 -0
- package/src/index.js +8 -0
- package/src/integrations/index.js +35 -0
- package/src/integrations/providers/algolia/implementation.js +176 -0
- package/src/integrations/providers/assetStore/implementation.js +148 -0
- package/src/lib/__tests__/formatters.spec.js +751 -0
- package/src/lib/__tests__/i18n.spec.js +792 -0
- package/src/lib/__tests__/phrases.spec.js +119 -0
- package/src/lib/__tests__/registry.spec.js +261 -0
- package/src/lib/__tests__/serializeEntryValues.spec.js +22 -0
- package/src/lib/__tests__/urlHelper.spec.js +138 -0
- package/src/lib/consoleError.js +7 -0
- package/src/lib/formatters.ts +286 -0
- package/src/lib/i18n.ts +454 -0
- package/src/lib/phrases.js +8 -0
- package/src/lib/polyfill.js +9 -0
- package/src/lib/registry.js +312 -0
- package/src/lib/serializeEntryValues.js +75 -0
- package/src/lib/stega.ts +145 -0
- package/src/lib/textHelper.js +11 -0
- package/src/lib/urlHelper.ts +128 -0
- package/src/mediaLibrary.ts +51 -0
- package/src/reducers/__tests__/auth.spec.ts +38 -0
- package/src/reducers/__tests__/collections.spec.js +610 -0
- package/src/reducers/__tests__/config.spec.js +38 -0
- package/src/reducers/__tests__/entries.spec.js +694 -0
- package/src/reducers/__tests__/entryDraft.spec.js +297 -0
- package/src/reducers/__tests__/globalUI.js +43 -0
- package/src/reducers/__tests__/integrations.spec.ts +76 -0
- package/src/reducers/__tests__/mediaLibrary.spec.js +154 -0
- package/src/reducers/__tests__/medias.spec.ts +49 -0
- package/src/reducers/auth.ts +46 -0
- package/src/reducers/collections.ts +535 -0
- package/src/reducers/combinedReducer.ts +11 -0
- package/src/reducers/config.ts +38 -0
- package/src/reducers/cursors.js +36 -0
- package/src/reducers/deploys.ts +52 -0
- package/src/reducers/editorialWorkflow.ts +163 -0
- package/src/reducers/entries.ts +819 -0
- package/src/reducers/entryDraft.js +260 -0
- package/src/reducers/globalUI.ts +45 -0
- package/src/reducers/index.ts +82 -0
- package/src/reducers/integrations.ts +59 -0
- package/src/reducers/mediaLibrary.ts +296 -0
- package/src/reducers/medias.ts +66 -0
- package/src/reducers/notifications.ts +52 -0
- package/src/reducers/search.ts +111 -0
- package/src/reducers/status.ts +40 -0
- package/src/redux/index.ts +18 -0
- package/src/redux/middleware/waitUntilAction.ts +64 -0
- package/src/routing/__tests__/history.spec.ts +49 -0
- package/src/routing/history.ts +17 -0
- package/src/types/diacritics.d.ts +1 -0
- package/src/types/global.d.ts +8 -0
- package/src/types/immutable.ts +49 -0
- package/src/types/redux.ts +827 -0
- package/src/types/tomlify-j0.4.d.ts +13 -0
- package/src/valueObjects/AssetProxy.ts +48 -0
- package/src/valueObjects/EditorComponent.js +38 -0
- package/src/valueObjects/Entry.ts +63 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import { List, Set, fromJS, OrderedMap } from 'immutable';
|
|
2
|
+
import get from 'lodash/get';
|
|
3
|
+
import escapeRegExp from 'lodash/escapeRegExp';
|
|
4
|
+
import { stringTemplate } from 'decap-cms-lib-widgets';
|
|
5
|
+
import consoleError from '../lib/consoleError';
|
|
6
|
+
import { CONFIG_SUCCESS } from '../actions/config';
|
|
7
|
+
import { FILES, FOLDER } from '../constants/collectionTypes';
|
|
8
|
+
import { COMMIT_DATE, COMMIT_AUTHOR } from '../constants/commitProps';
|
|
9
|
+
import { INFERABLE_FIELDS, IDENTIFIER_FIELDS, SORTABLE_FIELDS } from '../constants/fieldInference';
|
|
10
|
+
import { getFormatExtensions } from '../formats/formats';
|
|
11
|
+
import { selectMediaFolder } from './entries';
|
|
12
|
+
import { summaryFormatter } from '../lib/formatters';
|
|
13
|
+
const {
|
|
14
|
+
keyToPathArray
|
|
15
|
+
} = stringTemplate;
|
|
16
|
+
const defaultState = fromJS({});
|
|
17
|
+
function collections(state = defaultState, action) {
|
|
18
|
+
switch (action.type) {
|
|
19
|
+
case CONFIG_SUCCESS:
|
|
20
|
+
{
|
|
21
|
+
const collections = action.payload.collections;
|
|
22
|
+
let newState = OrderedMap({});
|
|
23
|
+
collections.forEach(collection => {
|
|
24
|
+
newState = newState.set(collection.name, fromJS(collection));
|
|
25
|
+
});
|
|
26
|
+
return newState;
|
|
27
|
+
}
|
|
28
|
+
default:
|
|
29
|
+
return state;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const selectors = {
|
|
33
|
+
[FOLDER]: {
|
|
34
|
+
entryExtension(collection) {
|
|
35
|
+
const ext = collection.get('extension') || get(getFormatExtensions(), collection.get('format') || 'frontmatter');
|
|
36
|
+
if (!ext) {
|
|
37
|
+
throw new Error(`No extension found for format ${collection.get('format')}`);
|
|
38
|
+
}
|
|
39
|
+
return ext.replace(/^\./, '');
|
|
40
|
+
},
|
|
41
|
+
fields(collection) {
|
|
42
|
+
return collection.get('fields');
|
|
43
|
+
},
|
|
44
|
+
entryPath(collection, slug) {
|
|
45
|
+
const folder = collection.get('folder').replace(/\/$/, '');
|
|
46
|
+
return `${folder}/${slug}.${this.entryExtension(collection)}`;
|
|
47
|
+
},
|
|
48
|
+
entrySlug(collection, path) {
|
|
49
|
+
const folder = collection.get('folder').replace(/\/$/, '');
|
|
50
|
+
const slug = path.split(folder + '/').pop()?.replace(new RegExp(`\\.${escapeRegExp(this.entryExtension(collection))}$`), '');
|
|
51
|
+
return slug;
|
|
52
|
+
},
|
|
53
|
+
allowNewEntries(collection) {
|
|
54
|
+
return collection.get('create');
|
|
55
|
+
},
|
|
56
|
+
allowDeletion(collection) {
|
|
57
|
+
return collection.get('delete', true);
|
|
58
|
+
},
|
|
59
|
+
templateName(collection) {
|
|
60
|
+
return collection.get('name');
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
[FILES]: {
|
|
64
|
+
fileForEntry(collection, slug) {
|
|
65
|
+
const files = collection.get('files');
|
|
66
|
+
return files && files.filter(f => f?.get('name') === slug).get(0);
|
|
67
|
+
},
|
|
68
|
+
fields(collection, slug) {
|
|
69
|
+
const file = this.fileForEntry(collection, slug);
|
|
70
|
+
return file && file.get('fields');
|
|
71
|
+
},
|
|
72
|
+
entryPath(collection, slug) {
|
|
73
|
+
const file = this.fileForEntry(collection, slug);
|
|
74
|
+
return file && file.get('file');
|
|
75
|
+
},
|
|
76
|
+
entrySlug(collection, path) {
|
|
77
|
+
const file = collection.get('files').filter(f => f?.get('file') === path).get(0);
|
|
78
|
+
return file && file.get('name');
|
|
79
|
+
},
|
|
80
|
+
entryLabel(collection, slug) {
|
|
81
|
+
const file = this.fileForEntry(collection, slug);
|
|
82
|
+
return file && file.get('label');
|
|
83
|
+
},
|
|
84
|
+
allowNewEntries() {
|
|
85
|
+
return false;
|
|
86
|
+
},
|
|
87
|
+
allowDeletion(collection) {
|
|
88
|
+
return collection.get('delete', false);
|
|
89
|
+
},
|
|
90
|
+
templateName(_collection, slug) {
|
|
91
|
+
return slug;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
function getFieldsWithMediaFolders(fields) {
|
|
96
|
+
const fieldsWithMediaFolders = fields.reduce((acc, f) => {
|
|
97
|
+
if (f.has('media_folder')) {
|
|
98
|
+
acc = [...acc, f];
|
|
99
|
+
}
|
|
100
|
+
if (f.has('fields')) {
|
|
101
|
+
const fields = f.get('fields')?.toArray();
|
|
102
|
+
acc = [...acc, ...getFieldsWithMediaFolders(fields)];
|
|
103
|
+
} else if (f.has('field')) {
|
|
104
|
+
const field = f.get('field');
|
|
105
|
+
acc = [...acc, ...getFieldsWithMediaFolders([field])];
|
|
106
|
+
} else if (f.has('types')) {
|
|
107
|
+
const types = f.get('types')?.toArray();
|
|
108
|
+
acc = [...acc, ...getFieldsWithMediaFolders(types)];
|
|
109
|
+
}
|
|
110
|
+
return acc;
|
|
111
|
+
}, []);
|
|
112
|
+
return fieldsWithMediaFolders;
|
|
113
|
+
}
|
|
114
|
+
export function getFileFromSlug(collection, slug) {
|
|
115
|
+
return collection.get('files')?.toArray().find(f => f.get('name') === slug);
|
|
116
|
+
}
|
|
117
|
+
export function selectFieldsWithMediaFolders(collection, slug) {
|
|
118
|
+
if (collection.has('folder')) {
|
|
119
|
+
const fields = collection.get('fields').toArray();
|
|
120
|
+
return getFieldsWithMediaFolders(fields);
|
|
121
|
+
} else if (collection.has('files')) {
|
|
122
|
+
const fields = getFileFromSlug(collection, slug)?.get('fields').toArray() || [];
|
|
123
|
+
return getFieldsWithMediaFolders(fields);
|
|
124
|
+
}
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
export function selectMediaFolders(config, collection, entry) {
|
|
128
|
+
const fields = selectFieldsWithMediaFolders(collection, entry.get('slug'));
|
|
129
|
+
const folders = fields.map(f => selectMediaFolder(config, collection, entry, f));
|
|
130
|
+
if (collection.has('files')) {
|
|
131
|
+
const file = getFileFromSlug(collection, entry.get('slug'));
|
|
132
|
+
if (file) {
|
|
133
|
+
folders.unshift(selectMediaFolder(config, collection, entry, undefined));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (collection.has('media_folder')) {
|
|
137
|
+
// stop evaluating media folders at collection level
|
|
138
|
+
collection = collection.delete('files');
|
|
139
|
+
folders.unshift(selectMediaFolder(config, collection, entry, undefined));
|
|
140
|
+
}
|
|
141
|
+
return Set(folders).toArray();
|
|
142
|
+
}
|
|
143
|
+
export function selectFields(collection, slug) {
|
|
144
|
+
return selectors[collection.get('type')].fields(collection, slug);
|
|
145
|
+
}
|
|
146
|
+
export function selectFolderEntryExtension(collection) {
|
|
147
|
+
return selectors[FOLDER].entryExtension(collection);
|
|
148
|
+
}
|
|
149
|
+
export function selectFileEntryLabel(collection, slug) {
|
|
150
|
+
return selectors[FILES].entryLabel(collection, slug);
|
|
151
|
+
}
|
|
152
|
+
export function selectEntryPath(collection, slug) {
|
|
153
|
+
return selectors[collection.get('type')].entryPath(collection, slug);
|
|
154
|
+
}
|
|
155
|
+
export function selectEntrySlug(collection, path) {
|
|
156
|
+
return selectors[collection.get('type')].entrySlug(collection, path);
|
|
157
|
+
}
|
|
158
|
+
export function selectAllowNewEntries(collection) {
|
|
159
|
+
return selectors[collection.get('type')].allowNewEntries(collection);
|
|
160
|
+
}
|
|
161
|
+
export function selectAllowDeletion(collection) {
|
|
162
|
+
return selectors[collection.get('type')].allowDeletion(collection);
|
|
163
|
+
}
|
|
164
|
+
export function selectTemplateName(collection, slug) {
|
|
165
|
+
return selectors[collection.get('type')].templateName(collection, slug);
|
|
166
|
+
}
|
|
167
|
+
export function getFieldsNames(fields, prefix = '') {
|
|
168
|
+
let names = fields.map(f => `${prefix}${f.get('name')}`);
|
|
169
|
+
fields.forEach((f, index) => {
|
|
170
|
+
if (f.has('fields')) {
|
|
171
|
+
const fields = f.get('fields')?.toArray();
|
|
172
|
+
names = [...names, ...getFieldsNames(fields, `${names[index]}.`)];
|
|
173
|
+
} else if (f.has('field')) {
|
|
174
|
+
const field = f.get('field');
|
|
175
|
+
names = [...names, ...getFieldsNames([field], `${names[index]}.`)];
|
|
176
|
+
} else if (f.has('types')) {
|
|
177
|
+
const types = f.get('types')?.toArray();
|
|
178
|
+
names = [...names, ...getFieldsNames(types, `${names[index]}.`)];
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
return names;
|
|
182
|
+
}
|
|
183
|
+
export function selectField(collection, key) {
|
|
184
|
+
const array = keyToPathArray(key);
|
|
185
|
+
let name;
|
|
186
|
+
let field;
|
|
187
|
+
let fields = collection.get('fields', List()).toArray();
|
|
188
|
+
while ((name = array.shift()) && fields) {
|
|
189
|
+
field = fields.find(f => f.get('name') === name);
|
|
190
|
+
if (field?.has('fields')) {
|
|
191
|
+
fields = field?.get('fields')?.toArray();
|
|
192
|
+
} else if (field?.has('field')) {
|
|
193
|
+
fields = [field?.get('field')];
|
|
194
|
+
} else if (field?.has('types')) {
|
|
195
|
+
fields = field?.get('types')?.toArray();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return field;
|
|
199
|
+
}
|
|
200
|
+
export function traverseFields(fields, updater, done = () => false) {
|
|
201
|
+
if (done()) {
|
|
202
|
+
return fields;
|
|
203
|
+
}
|
|
204
|
+
fields = fields.map(f => {
|
|
205
|
+
const field = updater(f);
|
|
206
|
+
if (done()) {
|
|
207
|
+
return field;
|
|
208
|
+
} else if (field.has('fields')) {
|
|
209
|
+
return field.set('fields', traverseFields(field.get('fields'), updater, done));
|
|
210
|
+
} else if (field.has('field')) {
|
|
211
|
+
return field.set('field', traverseFields(List([field.get('field')]), updater, done).get(0));
|
|
212
|
+
} else if (field.has('types')) {
|
|
213
|
+
return field.set('types', traverseFields(field.get('types'), updater, done));
|
|
214
|
+
} else {
|
|
215
|
+
return field;
|
|
216
|
+
}
|
|
217
|
+
}).toList();
|
|
218
|
+
return fields;
|
|
219
|
+
}
|
|
220
|
+
export function updateFieldByKey(collection, key, updater) {
|
|
221
|
+
const selected = selectField(collection, key);
|
|
222
|
+
if (!selected) {
|
|
223
|
+
return collection;
|
|
224
|
+
}
|
|
225
|
+
let updated = false;
|
|
226
|
+
function updateAndBreak(f) {
|
|
227
|
+
const field = f;
|
|
228
|
+
if (field === selected) {
|
|
229
|
+
updated = true;
|
|
230
|
+
return updater(field);
|
|
231
|
+
} else {
|
|
232
|
+
return field;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
collection = collection.set('fields', traverseFields(collection.get('fields', List()), updateAndBreak, () => updated));
|
|
236
|
+
return collection;
|
|
237
|
+
}
|
|
238
|
+
export function selectIdentifier(collection) {
|
|
239
|
+
const identifier = collection.get('identifier_field');
|
|
240
|
+
const identifierFields = identifier ? [identifier, ...IDENTIFIER_FIELDS] : [...IDENTIFIER_FIELDS];
|
|
241
|
+
const fieldNames = getFieldsNames(collection.get('fields', List()).toArray());
|
|
242
|
+
return identifierFields.find(id => fieldNames.find(name => name.toLowerCase().trim() === id.toLowerCase().trim()));
|
|
243
|
+
}
|
|
244
|
+
export function selectInferredField(collection, fieldName) {
|
|
245
|
+
if (fieldName === 'title' && collection.get('identifier_field')) {
|
|
246
|
+
return selectIdentifier(collection);
|
|
247
|
+
}
|
|
248
|
+
const inferableField = INFERABLE_FIELDS[fieldName];
|
|
249
|
+
const fields = collection.get('fields');
|
|
250
|
+
let field;
|
|
251
|
+
|
|
252
|
+
// If collection has no fields or fieldName is not defined within inferables list, return null
|
|
253
|
+
if (!fields || !inferableField) return null;
|
|
254
|
+
// Try to return a field of the specified type with one of the synonyms
|
|
255
|
+
const mainTypeFields = fields.filter(f => f?.get('widget', 'string') === inferableField.type).map(f => f?.get('name'));
|
|
256
|
+
field = mainTypeFields.filter(f => inferableField.synonyms.indexOf(f) !== -1);
|
|
257
|
+
if (field && field.size > 0) return field.first();
|
|
258
|
+
|
|
259
|
+
// Try to return a field for each of the specified secondary types
|
|
260
|
+
const secondaryTypeFields = fields.filter(f => inferableField.secondaryTypes.indexOf(f?.get('widget', 'string')) !== -1).map(f => f?.get('name'));
|
|
261
|
+
field = secondaryTypeFields.filter(f => inferableField.synonyms.indexOf(f) !== -1);
|
|
262
|
+
if (field && field.size > 0) return field.first();
|
|
263
|
+
|
|
264
|
+
// Try to return the first field of the specified type
|
|
265
|
+
if (inferableField.fallbackToFirstField && mainTypeFields.size > 0) return mainTypeFields.first();
|
|
266
|
+
|
|
267
|
+
// Coundn't infer the field. Show error and return null.
|
|
268
|
+
if (inferableField.showError) {
|
|
269
|
+
consoleError(`The Field ${fieldName} is missing for the collection “${collection.get('name')}”`, `Decap CMS tries to infer the entry ${fieldName} automatically, but one couldn't be found for entries of the collection “${collection.get('name')}”. Please check your site configuration.`);
|
|
270
|
+
}
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
export function selectEntryCollectionTitle(collection, entry) {
|
|
274
|
+
// prefer formatted summary over everything else
|
|
275
|
+
const summaryTemplate = collection.get('summary');
|
|
276
|
+
if (summaryTemplate) return summaryFormatter(summaryTemplate, entry, collection);
|
|
277
|
+
|
|
278
|
+
// if the collection is a file collection return the label of the entry
|
|
279
|
+
if (collection.get('type') == FILES) {
|
|
280
|
+
const label = selectFileEntryLabel(collection, entry.get('slug'));
|
|
281
|
+
if (label) return label;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// try to infer a title field from the entry data
|
|
285
|
+
const entryData = entry.get('data');
|
|
286
|
+
const titleField = selectInferredField(collection, 'title');
|
|
287
|
+
const result = titleField && entryData.getIn(keyToPathArray(titleField));
|
|
288
|
+
|
|
289
|
+
// if the custom field does not yield a result, fallback to 'title'
|
|
290
|
+
if (!result && titleField !== 'title') {
|
|
291
|
+
return entryData.getIn(keyToPathArray('title'));
|
|
292
|
+
}
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
export function selectDefaultSortableFields(collection, backend, hasIntegration) {
|
|
296
|
+
let defaultSortable = SORTABLE_FIELDS.map(type => {
|
|
297
|
+
const field = selectInferredField(collection, type);
|
|
298
|
+
if (backend.isGitBackend() && type === 'author' && !field && !hasIntegration) {
|
|
299
|
+
// default to commit author if not author field is found
|
|
300
|
+
return COMMIT_AUTHOR;
|
|
301
|
+
}
|
|
302
|
+
return field;
|
|
303
|
+
}).filter(Boolean);
|
|
304
|
+
if (backend.isGitBackend() && !hasIntegration) {
|
|
305
|
+
// always have commit date by default
|
|
306
|
+
defaultSortable = [COMMIT_DATE, ...defaultSortable];
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Return as objects with field property
|
|
310
|
+
return defaultSortable.map(field => ({
|
|
311
|
+
field
|
|
312
|
+
}));
|
|
313
|
+
}
|
|
314
|
+
export function selectSortableFields(collection, t) {
|
|
315
|
+
const fields = collection.get('sortable_fields').toArray().map(sortableField => {
|
|
316
|
+
// Extract the field name and custom label from the sortable field object
|
|
317
|
+
const key = sortableField.get('field');
|
|
318
|
+
const customLabel = sortableField.get('label');
|
|
319
|
+
if (key === COMMIT_DATE) {
|
|
320
|
+
const label = customLabel || t('collection.defaultFields.updatedOn.label');
|
|
321
|
+
return {
|
|
322
|
+
key,
|
|
323
|
+
field: {
|
|
324
|
+
name: key,
|
|
325
|
+
label
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
const field = selectField(collection, key);
|
|
330
|
+
if (key === COMMIT_AUTHOR && !field) {
|
|
331
|
+
const label = customLabel || t('collection.defaultFields.author.label');
|
|
332
|
+
return {
|
|
333
|
+
key,
|
|
334
|
+
field: {
|
|
335
|
+
name: key,
|
|
336
|
+
label
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
let fieldObj = field?.toJS();
|
|
341
|
+
|
|
342
|
+
// If custom label is provided, override the field's label
|
|
343
|
+
if (fieldObj && customLabel) {
|
|
344
|
+
fieldObj = {
|
|
345
|
+
...fieldObj,
|
|
346
|
+
label: customLabel
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// If no label exists at all, use the field name
|
|
351
|
+
if (fieldObj && !fieldObj.label) {
|
|
352
|
+
fieldObj = {
|
|
353
|
+
...fieldObj,
|
|
354
|
+
label: fieldObj.name || key
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
key,
|
|
359
|
+
field: fieldObj
|
|
360
|
+
};
|
|
361
|
+
}).filter(item => !!item.field).map(item => ({
|
|
362
|
+
...item.field,
|
|
363
|
+
key: item.key
|
|
364
|
+
}));
|
|
365
|
+
return fields;
|
|
366
|
+
}
|
|
367
|
+
export function selectDefaultSortField(collection) {
|
|
368
|
+
const sortableFields = collection.get('sortable_fields').toArray();
|
|
369
|
+
const defaultField = sortableFields.find(field => field.get('default_sort') !== undefined);
|
|
370
|
+
if (!defaultField) {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
const fieldName = defaultField.get('field');
|
|
374
|
+
const defaultSortValue = defaultField.get('default_sort');
|
|
375
|
+
|
|
376
|
+
// Determine direction based on default_sort value
|
|
377
|
+
let direction;
|
|
378
|
+
if (defaultSortValue === true || defaultSortValue === 'asc') {
|
|
379
|
+
direction = 'asc';
|
|
380
|
+
} else if (defaultSortValue === 'desc') {
|
|
381
|
+
direction = 'desc';
|
|
382
|
+
} else {
|
|
383
|
+
direction = 'asc'; // fallback
|
|
384
|
+
}
|
|
385
|
+
return {
|
|
386
|
+
field: fieldName,
|
|
387
|
+
direction
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
export function selectSortDataPath(collection, key) {
|
|
391
|
+
if (key === COMMIT_DATE) {
|
|
392
|
+
return 'updatedOn';
|
|
393
|
+
} else if (key === COMMIT_AUTHOR && !selectField(collection, key)) {
|
|
394
|
+
return 'author';
|
|
395
|
+
} else {
|
|
396
|
+
return `data.${key}`;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
export function selectViewFilters(collection) {
|
|
400
|
+
const viewFilters = collection.get('view_filters').toJS();
|
|
401
|
+
return viewFilters;
|
|
402
|
+
}
|
|
403
|
+
export function selectViewGroups(collection) {
|
|
404
|
+
const viewGroups = collection.get('view_groups').toJS();
|
|
405
|
+
return viewGroups;
|
|
406
|
+
}
|
|
407
|
+
export function selectFieldsComments(collection, entryMap) {
|
|
408
|
+
let fields = [];
|
|
409
|
+
if (collection.has('folder')) {
|
|
410
|
+
fields = collection.get('fields').toArray();
|
|
411
|
+
} else if (collection.has('files')) {
|
|
412
|
+
const file = collection.get('files').find(f => f?.get('name') === entryMap.get('slug'));
|
|
413
|
+
fields = file.get('fields').toArray();
|
|
414
|
+
}
|
|
415
|
+
const comments = {};
|
|
416
|
+
const names = getFieldsNames(fields);
|
|
417
|
+
names.forEach(name => {
|
|
418
|
+
const field = selectField(collection, name);
|
|
419
|
+
if (field?.has('comment')) {
|
|
420
|
+
comments[name] = field.get('comment');
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
return comments;
|
|
424
|
+
}
|
|
425
|
+
export function selectHasMetaPath(collection) {
|
|
426
|
+
return collection.has('folder') && collection.get('type') === FOLDER && collection.has('meta') && collection.get('meta')?.has('path');
|
|
427
|
+
}
|
|
428
|
+
export default collections;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { produce } from 'immer';
|
|
2
|
+
import { CONFIG_REQUEST, CONFIG_SUCCESS, CONFIG_FAILURE } from '../actions/config';
|
|
3
|
+
import { EDITORIAL_WORKFLOW } from '../constants/publishModes';
|
|
4
|
+
const defaultState = {
|
|
5
|
+
isFetching: true
|
|
6
|
+
};
|
|
7
|
+
const config = produce((state, action) => {
|
|
8
|
+
switch (action.type) {
|
|
9
|
+
case CONFIG_REQUEST:
|
|
10
|
+
state.isFetching = true;
|
|
11
|
+
break;
|
|
12
|
+
case CONFIG_SUCCESS:
|
|
13
|
+
return {
|
|
14
|
+
...action.payload,
|
|
15
|
+
isFetching: false,
|
|
16
|
+
error: undefined
|
|
17
|
+
};
|
|
18
|
+
case CONFIG_FAILURE:
|
|
19
|
+
state.isFetching = false;
|
|
20
|
+
state.error = action.payload.toString();
|
|
21
|
+
}
|
|
22
|
+
}, defaultState);
|
|
23
|
+
export function selectLocale(state) {
|
|
24
|
+
return state.locale || 'en';
|
|
25
|
+
}
|
|
26
|
+
export function selectUseWorkflow(state) {
|
|
27
|
+
return state.publish_mode === EDITORIAL_WORKFLOW;
|
|
28
|
+
}
|
|
29
|
+
export default config;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { fromJS } from 'immutable';
|
|
2
|
+
import { Cursor } from 'decap-cms-lib-util';
|
|
3
|
+
import { ENTRIES_SUCCESS, SORT_ENTRIES_SUCCESS, FILTER_ENTRIES_SUCCESS, GROUP_ENTRIES_SUCCESS } from '../actions/entries';
|
|
4
|
+
|
|
5
|
+
// Since pagination can be used for a variety of views (collections
|
|
6
|
+
// and searches are the most common examples), we namespace cursors by
|
|
7
|
+
// their type before storing them in the state.
|
|
8
|
+
export function selectCollectionEntriesCursor(state, collectionName) {
|
|
9
|
+
return new Cursor(state.getIn(['cursorsByType', 'collectionEntries', collectionName]));
|
|
10
|
+
}
|
|
11
|
+
function cursors(state = fromJS({
|
|
12
|
+
cursorsByType: {
|
|
13
|
+
collectionEntries: {}
|
|
14
|
+
}
|
|
15
|
+
}), action) {
|
|
16
|
+
switch (action.type) {
|
|
17
|
+
case ENTRIES_SUCCESS:
|
|
18
|
+
{
|
|
19
|
+
return state.setIn(['cursorsByType', 'collectionEntries', action.payload.collection], Cursor.create(action.payload.cursor).store);
|
|
20
|
+
}
|
|
21
|
+
case FILTER_ENTRIES_SUCCESS:
|
|
22
|
+
case GROUP_ENTRIES_SUCCESS:
|
|
23
|
+
case SORT_ENTRIES_SUCCESS:
|
|
24
|
+
{
|
|
25
|
+
return state.deleteIn(['cursorsByType', 'collectionEntries', action.payload.collection]);
|
|
26
|
+
}
|
|
27
|
+
default:
|
|
28
|
+
return state;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export default cursors;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { produce } from 'immer';
|
|
2
|
+
import { DEPLOY_PREVIEW_REQUEST, DEPLOY_PREVIEW_SUCCESS, DEPLOY_PREVIEW_FAILURE } from '../actions/deploys';
|
|
3
|
+
const defaultState = {};
|
|
4
|
+
const deploys = produce((state, action) => {
|
|
5
|
+
switch (action.type) {
|
|
6
|
+
case DEPLOY_PREVIEW_REQUEST:
|
|
7
|
+
{
|
|
8
|
+
const {
|
|
9
|
+
collection,
|
|
10
|
+
slug
|
|
11
|
+
} = action.payload;
|
|
12
|
+
const key = `${collection}.${slug}`;
|
|
13
|
+
state[key] = state[key] || {};
|
|
14
|
+
state[key].isFetching = true;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
case DEPLOY_PREVIEW_SUCCESS:
|
|
18
|
+
{
|
|
19
|
+
const {
|
|
20
|
+
collection,
|
|
21
|
+
slug,
|
|
22
|
+
url,
|
|
23
|
+
status
|
|
24
|
+
} = action.payload;
|
|
25
|
+
const key = `${collection}.${slug}`;
|
|
26
|
+
state[key].isFetching = false;
|
|
27
|
+
state[key].url = url;
|
|
28
|
+
state[key].status = status;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
case DEPLOY_PREVIEW_FAILURE:
|
|
32
|
+
{
|
|
33
|
+
const {
|
|
34
|
+
collection,
|
|
35
|
+
slug
|
|
36
|
+
} = action.payload;
|
|
37
|
+
state[`${collection}.${slug}`].isFetching = false;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}, defaultState);
|
|
42
|
+
export function selectDeployPreview(state, collection, slug) {
|
|
43
|
+
return state[`${collection}.${slug}`];
|
|
44
|
+
}
|
|
45
|
+
export default deploys;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Map, List, fromJS } from 'immutable';
|
|
2
|
+
import startsWith from 'lodash/startsWith';
|
|
3
|
+
import { EDITORIAL_WORKFLOW } from '../constants/publishModes';
|
|
4
|
+
import { UNPUBLISHED_ENTRY_REQUEST, UNPUBLISHED_ENTRY_REDIRECT, UNPUBLISHED_ENTRY_SUCCESS, UNPUBLISHED_ENTRIES_REQUEST, UNPUBLISHED_ENTRIES_SUCCESS, 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, UNPUBLISHED_ENTRY_DELETE_SUCCESS } from '../actions/editorialWorkflow';
|
|
5
|
+
import { CONFIG_SUCCESS } from '../actions/config';
|
|
6
|
+
function unpublishedEntries(state = Map(), action) {
|
|
7
|
+
switch (action.type) {
|
|
8
|
+
case CONFIG_SUCCESS:
|
|
9
|
+
{
|
|
10
|
+
const publishMode = action.payload && action.payload.publish_mode;
|
|
11
|
+
if (publishMode === EDITORIAL_WORKFLOW) {
|
|
12
|
+
// Editorial workflow state is explicitly initiated after the config.
|
|
13
|
+
return Map({
|
|
14
|
+
entities: Map(),
|
|
15
|
+
pages: Map()
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return state;
|
|
19
|
+
}
|
|
20
|
+
case UNPUBLISHED_ENTRY_REQUEST:
|
|
21
|
+
return state.setIn(['entities', `${action.payload.collection}.${action.payload.slug}`, 'isFetching'], true);
|
|
22
|
+
case UNPUBLISHED_ENTRY_REDIRECT:
|
|
23
|
+
return state.deleteIn(['entities', `${action.payload.collection}.${action.payload.slug}`]);
|
|
24
|
+
case UNPUBLISHED_ENTRY_SUCCESS:
|
|
25
|
+
return state.setIn(['entities', `${action.payload.collection}.${action.payload.entry.slug}`], fromJS(action.payload.entry));
|
|
26
|
+
case UNPUBLISHED_ENTRIES_REQUEST:
|
|
27
|
+
return state.setIn(['pages', 'isFetching'], true);
|
|
28
|
+
case UNPUBLISHED_ENTRIES_SUCCESS:
|
|
29
|
+
return state.withMutations(map => {
|
|
30
|
+
action.payload.entries.forEach(entry => map.setIn(['entities', `${entry.collection}.${entry.slug}`], fromJS(entry).set('isFetching', false)));
|
|
31
|
+
map.set('pages', Map({
|
|
32
|
+
...action.payload.pages,
|
|
33
|
+
ids: List(action.payload.entries.map(entry => entry.slug))
|
|
34
|
+
}));
|
|
35
|
+
});
|
|
36
|
+
case UNPUBLISHED_ENTRY_PERSIST_REQUEST:
|
|
37
|
+
{
|
|
38
|
+
return state.setIn(['entities', `${action.payload.collection}.${action.payload.slug}`, 'isPersisting'], true);
|
|
39
|
+
}
|
|
40
|
+
case UNPUBLISHED_ENTRY_PERSIST_SUCCESS:
|
|
41
|
+
// Update Optimistically
|
|
42
|
+
return state.withMutations(map => {
|
|
43
|
+
map.setIn(['entities', `${action.payload.collection}.${action.payload.entry.get('slug')}`], fromJS(action.payload.entry));
|
|
44
|
+
map.deleteIn(['entities', `${action.payload.collection}.${action.payload.entry.get('slug')}`, 'isPersisting']);
|
|
45
|
+
map.updateIn(['pages', 'ids'], List(), list => list.push(action.payload.entry.get('slug')));
|
|
46
|
+
});
|
|
47
|
+
case UNPUBLISHED_ENTRY_PERSIST_FAILURE:
|
|
48
|
+
return state.setIn(['entities', `${action.payload.collection}.${action.payload.slug}`, 'isPersisting'], false);
|
|
49
|
+
case UNPUBLISHED_ENTRY_STATUS_CHANGE_REQUEST:
|
|
50
|
+
// Update Optimistically
|
|
51
|
+
return state.setIn(['entities', `${action.payload.collection}.${action.payload.slug}`, 'isUpdatingStatus'], true);
|
|
52
|
+
case UNPUBLISHED_ENTRY_STATUS_CHANGE_SUCCESS:
|
|
53
|
+
return state.withMutations(map => {
|
|
54
|
+
map.setIn(['entities', `${action.payload.collection}.${action.payload.slug}`, 'status'], action.payload.newStatus);
|
|
55
|
+
map.setIn(['entities', `${action.payload.collection}.${action.payload.slug}`, 'isUpdatingStatus'], false);
|
|
56
|
+
});
|
|
57
|
+
case UNPUBLISHED_ENTRY_STATUS_CHANGE_FAILURE:
|
|
58
|
+
return state.setIn(['entities', `${action.payload.collection}.${action.payload.slug}`, 'isUpdatingStatus'], false);
|
|
59
|
+
case UNPUBLISHED_ENTRY_PUBLISH_REQUEST:
|
|
60
|
+
return state.setIn(['entities', `${action.payload.collection}.${action.payload.slug}`, 'isPublishing'], true);
|
|
61
|
+
case UNPUBLISHED_ENTRY_PUBLISH_SUCCESS:
|
|
62
|
+
return state.deleteIn(['entities', `${action.payload.collection}.${action.payload.slug}`]);
|
|
63
|
+
case UNPUBLISHED_ENTRY_DELETE_SUCCESS:
|
|
64
|
+
return state.deleteIn(['entities', `${action.payload.collection}.${action.payload.slug}`]);
|
|
65
|
+
case UNPUBLISHED_ENTRY_PUBLISH_FAILURE:
|
|
66
|
+
default:
|
|
67
|
+
return state;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function selectUnpublishedEntry(state, collection, slug) {
|
|
71
|
+
return state && state.getIn(['entities', `${collection}.${slug}`]);
|
|
72
|
+
}
|
|
73
|
+
export function selectUnpublishedEntriesByStatus(state, status) {
|
|
74
|
+
if (!state) return null;
|
|
75
|
+
const entities = state.get('entities');
|
|
76
|
+
return entities.filter(entry => entry.get('status') === status).valueSeq();
|
|
77
|
+
}
|
|
78
|
+
export function selectUnpublishedSlugs(state, collection) {
|
|
79
|
+
if (!state.get('entities')) return null;
|
|
80
|
+
const entities = state.get('entities');
|
|
81
|
+
return entities.filter((_v, k) => startsWith(k, `${collection}.`)).map(entry => entry.get('slug')).valueSeq();
|
|
82
|
+
}
|
|
83
|
+
export default unpublishedEntries;
|