@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,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;
|