decap-cms-core 2.56.0-beta.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/LICENSE +22 -0
- package/README.md +9 -0
- package/dist/decap-cms-core.js +47 -0
- package/dist/decap-cms-core.js.LICENSE.txt +109 -0
- package/dist/decap-cms-core.js.map +1 -0
- package/dist/esm/actions/auth.js +118 -0
- package/dist/esm/actions/collections.js +23 -0
- package/dist/esm/actions/config.js +482 -0
- package/dist/esm/actions/deploys.js +89 -0
- package/dist/esm/actions/editorialWorkflow.js +511 -0
- package/dist/esm/actions/entries.js +940 -0
- package/dist/esm/actions/media.js +168 -0
- package/dist/esm/actions/mediaLibrary.js +606 -0
- package/dist/esm/actions/notifications.js +32 -0
- package/dist/esm/actions/search.js +156 -0
- package/dist/esm/actions/status.js +93 -0
- package/dist/esm/actions/waitUntil.js +39 -0
- package/dist/esm/backend.js +1073 -0
- package/dist/esm/bootstrap.js +107 -0
- package/dist/esm/components/App/App.js +301 -0
- package/dist/esm/components/App/Header.js +162 -0
- package/dist/esm/components/App/NotFoundPage.js +27 -0
- package/dist/esm/components/Collection/Collection.js +210 -0
- package/dist/esm/components/Collection/CollectionControls.js +54 -0
- package/dist/esm/components/Collection/CollectionSearch.js +235 -0
- package/dist/esm/components/Collection/CollectionTop.js +77 -0
- package/dist/esm/components/Collection/ControlButton.js +23 -0
- package/dist/esm/components/Collection/Entries/Entries.js +74 -0
- package/dist/esm/components/Collection/Entries/EntriesCollection.js +193 -0
- package/dist/esm/components/Collection/Entries/EntriesSearch.js +117 -0
- package/dist/esm/components/Collection/Entries/EntryCard.js +134 -0
- package/dist/esm/components/Collection/Entries/EntryListing.js +120 -0
- package/dist/esm/components/Collection/FilterControl.js +41 -0
- package/dist/esm/components/Collection/GroupControl.js +41 -0
- package/dist/esm/components/Collection/NestedCollection.js +311 -0
- package/dist/esm/components/Collection/Sidebar.js +102 -0
- package/dist/esm/components/Collection/SortControl.js +67 -0
- package/dist/esm/components/Collection/ViewStyleControl.js +47 -0
- package/dist/esm/components/Editor/Editor.js +479 -0
- package/dist/esm/components/Editor/EditorControlPane/EditorControl.js +393 -0
- package/dist/esm/components/Editor/EditorControlPane/EditorControlPane.js +259 -0
- package/dist/esm/components/Editor/EditorControlPane/Widget.js +355 -0
- package/dist/esm/components/Editor/EditorInterface.js +401 -0
- package/dist/esm/components/Editor/EditorPreviewPane/EditorPreview.js +56 -0
- package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewContent.js +34 -0
- package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewPane.js +252 -0
- package/dist/esm/components/Editor/EditorPreviewPane/PreviewHOC.js +39 -0
- package/dist/esm/components/Editor/EditorToolbar.js +551 -0
- package/dist/esm/components/Editor/withWorkflow.js +64 -0
- package/dist/esm/components/EditorWidgets/Unknown/UnknownControl.js +26 -0
- package/dist/esm/components/EditorWidgets/Unknown/UnknownPreview.js +28 -0
- package/dist/esm/components/EditorWidgets/index.js +7 -0
- package/dist/esm/components/MediaLibrary/EmptyMessage.js +30 -0
- package/dist/esm/components/MediaLibrary/MediaLibrary.js +444 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryButtons.js +110 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryCard.js +108 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryCardGrid.js +211 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryHeader.js +40 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryModal.js +163 -0
- package/dist/esm/components/MediaLibrary/MediaLibrarySearch.js +60 -0
- package/dist/esm/components/MediaLibrary/MediaLibraryTop.js +134 -0
- package/dist/esm/components/UI/DragDrop.js +84 -0
- package/dist/esm/components/UI/ErrorBoundary.js +184 -0
- package/dist/esm/components/UI/FileUploadButton.js +34 -0
- package/dist/esm/components/UI/Modal.js +113 -0
- package/dist/esm/components/UI/Notifications.js +74 -0
- package/dist/esm/components/UI/SettingsDropdown.js +118 -0
- package/dist/esm/components/UI/index.js +60 -0
- package/dist/esm/components/Workflow/Workflow.js +144 -0
- package/dist/esm/components/Workflow/WorkflowCard.js +137 -0
- package/dist/esm/components/Workflow/WorkflowList.js +219 -0
- package/dist/esm/constants/collectionTypes.js +10 -0
- package/dist/esm/constants/collectionViews.js +10 -0
- package/dist/esm/constants/commitProps.js +10 -0
- package/dist/esm/constants/configSchema.js +594 -0
- package/dist/esm/constants/fieldInference.js +67 -0
- package/dist/esm/constants/publishModes.js +28 -0
- package/dist/esm/constants/validationErrorTypes.js +13 -0
- package/dist/esm/formats/formats.js +82 -0
- package/dist/esm/formats/frontmatter.js +163 -0
- package/dist/esm/formats/helpers.js +18 -0
- package/dist/esm/formats/json.js +15 -0
- package/dist/esm/formats/toml.js +40 -0
- package/dist/esm/formats/yaml.js +63 -0
- package/dist/esm/index.js +20 -0
- package/dist/esm/integrations/index.js +37 -0
- package/dist/esm/integrations/providers/algolia/implementation.js +184 -0
- package/dist/esm/integrations/providers/assetStore/implementation.js +175 -0
- package/dist/esm/lib/consoleError.js +9 -0
- package/dist/esm/lib/formatters.js +204 -0
- package/dist/esm/lib/i18n.js +381 -0
- package/dist/esm/lib/phrases.js +13 -0
- package/dist/esm/lib/registry.js +322 -0
- package/dist/esm/lib/serializeEntryValues.js +74 -0
- package/dist/esm/lib/textHelper.js +15 -0
- package/dist/esm/lib/urlHelper.js +128 -0
- package/dist/esm/mediaLibrary.js +42 -0
- package/dist/esm/reducers/auth.js +35 -0
- package/dist/esm/reducers/collections.js +424 -0
- package/dist/esm/reducers/combinedReducer.js +19 -0
- package/dist/esm/reducers/config.js +42 -0
- package/dist/esm/reducers/cursors.js +38 -0
- package/dist/esm/reducers/deploys.js +53 -0
- package/dist/esm/reducers/editorialWorkflow.js +98 -0
- package/dist/esm/reducers/entries.js +591 -0
- package/dist/esm/reducers/entryDraft.js +184 -0
- package/dist/esm/reducers/globalUI.js +32 -0
- package/dist/esm/reducers/index.js +84 -0
- package/dist/esm/reducers/integrations.js +68 -0
- package/dist/esm/reducers/mediaLibrary.js +265 -0
- package/dist/esm/reducers/medias.js +76 -0
- package/dist/esm/reducers/notifications.js +36 -0
- package/dist/esm/reducers/search.js +89 -0
- package/dist/esm/reducers/status.js +37 -0
- package/dist/esm/redux/index.js +14 -0
- package/dist/esm/redux/middleware/waitUntilAction.js +56 -0
- package/dist/esm/routing/history.js +21 -0
- package/dist/esm/types/diacritics.d.js +1 -0
- package/dist/esm/types/global.d.js +5 -0
- package/dist/esm/types/immutable.js +5 -0
- package/dist/esm/types/redux.js +16 -0
- package/dist/esm/types/tomlify-j0.4.d.js +1 -0
- package/dist/esm/valueObjects/AssetProxy.js +60 -0
- package/dist/esm/valueObjects/EditorComponent.js +48 -0
- package/dist/esm/valueObjects/Entry.js +27 -0
- package/index.d.ts +587 -0
- package/package.json +102 -0
- package/src/__tests__/backend.spec.js +934 -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 +575 -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 +538 -0
- package/src/actions/deploys.ts +104 -0
- package/src/actions/editorialWorkflow.ts +567 -0
- package/src/actions/entries.ts +1041 -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 +194 -0
- package/src/actions/status.ts +99 -0
- package/src/actions/waitUntil.ts +49 -0
- package/src/backend.ts +1342 -0
- package/src/bootstrap.js +102 -0
- package/src/components/App/App.js +280 -0
- package/src/components/App/Header.js +236 -0
- package/src/components/App/NotFoundPage.js +23 -0
- package/src/components/Collection/Collection.js +205 -0
- package/src/components/Collection/CollectionControls.js +58 -0
- package/src/components/Collection/CollectionSearch.js +238 -0
- package/src/components/Collection/CollectionTop.js +81 -0
- package/src/components/Collection/ControlButton.js +27 -0
- package/src/components/Collection/Entries/Entries.js +73 -0
- package/src/components/Collection/Entries/EntriesCollection.js +165 -0
- package/src/components/Collection/Entries/EntriesSearch.js +91 -0
- package/src/components/Collection/Entries/EntryCard.js +167 -0
- package/src/components/Collection/Entries/EntryListing.js +86 -0
- package/src/components/Collection/Entries/__tests__/EntriesCollection.spec.js +155 -0
- package/src/components/Collection/Entries/__tests__/__snapshots__/EntriesCollection.spec.js.snap +49 -0
- package/src/components/Collection/FilterControl.js +39 -0
- package/src/components/Collection/GroupControl.js +39 -0
- package/src/components/Collection/NestedCollection.js +309 -0
- package/src/components/Collection/Sidebar.js +130 -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 +442 -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 +308 -0
- package/src/components/Editor/Editor.js +494 -0
- package/src/components/Editor/EditorControlPane/EditorControl.js +428 -0
- package/src/components/Editor/EditorControlPane/EditorControlPane.js +256 -0
- package/src/components/Editor/EditorControlPane/Widget.js +351 -0
- package/src/components/Editor/EditorInterface.js +434 -0
- package/src/components/Editor/EditorPreviewPane/EditorPreview.js +40 -0
- package/src/components/Editor/EditorPreviewPane/EditorPreviewContent.js +34 -0
- package/src/components/Editor/EditorPreviewPane/EditorPreviewPane.js +278 -0
- package/src/components/Editor/EditorPreviewPane/PreviewHOC.js +33 -0
- package/src/components/Editor/EditorToolbar.js +678 -0
- package/src/components/Editor/__tests__/Editor.spec.js +219 -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 +4020 -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 +407 -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 +216 -0
- package/src/components/UI/DragDrop.js +66 -0
- package/src/components/UI/ErrorBoundary.js +209 -0
- package/src/components/UI/FileUploadButton.js +24 -0
- package/src/components/UI/Modal.js +109 -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 +166 -0
- package/src/components/Workflow/WorkflowCard.js +177 -0
- package/src/components/Workflow/WorkflowList.js +269 -0
- package/src/constants/__tests__/configSchema.spec.js +511 -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 +399 -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__/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 +86 -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 +147 -0
- package/src/lib/__tests__/formatters.spec.js +723 -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 +246 -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 +267 -0
- package/src/lib/i18n.ts +427 -0
- package/src/lib/phrases.js +8 -0
- package/src/lib/registry.js +282 -0
- package/src/lib/serializeEntryValues.js +75 -0
- package/src/lib/textHelper.js +11 -0
- package/src/lib/urlHelper.ts +125 -0
- package/src/mediaLibrary.ts +51 -0
- package/src/reducers/__tests__/auth.spec.ts +38 -0
- package/src/reducers/__tests__/collections.spec.js +571 -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 +198 -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 +483 -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 +806 -0
- package/src/reducers/entryDraft.js +218 -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 +53 -0
- package/src/reducers/search.ts +89 -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 +39 -0
- package/src/types/redux.ts +810 -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,66 @@
|
|
|
1
|
+
import { produce } from 'immer';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ADD_ASSETS,
|
|
5
|
+
ADD_ASSET,
|
|
6
|
+
REMOVE_ASSET,
|
|
7
|
+
LOAD_ASSET_REQUEST,
|
|
8
|
+
LOAD_ASSET_SUCCESS,
|
|
9
|
+
LOAD_ASSET_FAILURE,
|
|
10
|
+
} from '../actions/media';
|
|
11
|
+
|
|
12
|
+
import type { MediasAction } from '../actions/media';
|
|
13
|
+
import type AssetProxy from '../valueObjects/AssetProxy';
|
|
14
|
+
|
|
15
|
+
export type Medias = {
|
|
16
|
+
[path: string]: { asset: AssetProxy | undefined; isLoading: boolean; error: Error | null };
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const defaultState: Medias = {};
|
|
20
|
+
|
|
21
|
+
const medias = produce((state: Medias, action: MediasAction) => {
|
|
22
|
+
switch (action.type) {
|
|
23
|
+
case ADD_ASSETS: {
|
|
24
|
+
const assets = action.payload;
|
|
25
|
+
assets.forEach(asset => {
|
|
26
|
+
state[asset.path] = { asset, isLoading: false, error: null };
|
|
27
|
+
});
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
case ADD_ASSET: {
|
|
31
|
+
const asset = action.payload;
|
|
32
|
+
state[asset.path] = { asset, isLoading: false, error: null };
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
case REMOVE_ASSET: {
|
|
36
|
+
const path = action.payload;
|
|
37
|
+
delete state[path];
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
case LOAD_ASSET_REQUEST: {
|
|
41
|
+
const { path } = action.payload;
|
|
42
|
+
state[path] = state[path] || {};
|
|
43
|
+
state[path].isLoading = true;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
case LOAD_ASSET_SUCCESS: {
|
|
47
|
+
const { path } = 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
|
+
const { path, error } = action.payload;
|
|
55
|
+
state[path] = state[path] || {};
|
|
56
|
+
state[path].isLoading = false;
|
|
57
|
+
state[path].error = error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}, defaultState);
|
|
61
|
+
|
|
62
|
+
export function selectIsLoadingAsset(state: Medias) {
|
|
63
|
+
return Object.values(state).some(state => state.isLoading);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default medias;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { produce } from 'immer';
|
|
2
|
+
import uuid from 'uuid';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
NOTIFICATION_SEND,
|
|
6
|
+
NOTIFICATION_DISMISS,
|
|
7
|
+
NOTIFICATIONS_CLEAR,
|
|
8
|
+
} from '../actions/notifications';
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
NotificationsAction,
|
|
12
|
+
NotificationMessage,
|
|
13
|
+
NotificationPayload,
|
|
14
|
+
} from '../actions/notifications';
|
|
15
|
+
import type { TypeOptions } from 'react-toastify';
|
|
16
|
+
|
|
17
|
+
export type Notification = {
|
|
18
|
+
id: string;
|
|
19
|
+
message: string | NotificationMessage;
|
|
20
|
+
dismissAfter?: number;
|
|
21
|
+
type: TypeOptions | undefined;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type NotificationsState = {
|
|
25
|
+
notifications: Notification[];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const defaultState: NotificationsState = {
|
|
29
|
+
notifications: [],
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const notifications = produce((state: NotificationsState, action: NotificationsAction) => {
|
|
33
|
+
switch (action.type) {
|
|
34
|
+
case NOTIFICATIONS_CLEAR:
|
|
35
|
+
state.notifications = [];
|
|
36
|
+
break;
|
|
37
|
+
case NOTIFICATION_DISMISS:
|
|
38
|
+
console.log('dismissed!');
|
|
39
|
+
state.notifications = state.notifications.filter(n => n.id !== action.id);
|
|
40
|
+
break;
|
|
41
|
+
case NOTIFICATION_SEND:
|
|
42
|
+
state.notifications = [
|
|
43
|
+
...state.notifications,
|
|
44
|
+
{
|
|
45
|
+
id: uuid(),
|
|
46
|
+
...(action.payload as NotificationPayload),
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}, defaultState);
|
|
52
|
+
|
|
53
|
+
export default notifications;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { produce } from 'immer';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
QUERY_FAILURE,
|
|
5
|
+
QUERY_REQUEST,
|
|
6
|
+
QUERY_SUCCESS,
|
|
7
|
+
SEARCH_CLEAR,
|
|
8
|
+
SEARCH_ENTRIES_FAILURE,
|
|
9
|
+
SEARCH_ENTRIES_REQUEST,
|
|
10
|
+
SEARCH_ENTRIES_SUCCESS,
|
|
11
|
+
} from '../actions/search';
|
|
12
|
+
|
|
13
|
+
import type { SearchAction } from '../actions/search';
|
|
14
|
+
import type { EntryValue } from '../valueObjects/Entry';
|
|
15
|
+
|
|
16
|
+
export type Search = {
|
|
17
|
+
isFetching: boolean;
|
|
18
|
+
term: string;
|
|
19
|
+
collections: string[];
|
|
20
|
+
page: number;
|
|
21
|
+
entryIds: { collection: string; slug: string }[];
|
|
22
|
+
queryHits: Record<string, EntryValue[]>;
|
|
23
|
+
error: Error | undefined;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const defaultState: Search = {
|
|
27
|
+
isFetching: false,
|
|
28
|
+
term: '',
|
|
29
|
+
collections: [],
|
|
30
|
+
page: 0,
|
|
31
|
+
entryIds: [],
|
|
32
|
+
queryHits: {},
|
|
33
|
+
error: undefined,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const search = produce((state: Search, action: SearchAction) => {
|
|
37
|
+
switch (action.type) {
|
|
38
|
+
case SEARCH_CLEAR:
|
|
39
|
+
return defaultState;
|
|
40
|
+
|
|
41
|
+
case SEARCH_ENTRIES_REQUEST: {
|
|
42
|
+
const { page, searchTerm, searchCollections } = action.payload;
|
|
43
|
+
state.isFetching = true;
|
|
44
|
+
state.term = searchTerm;
|
|
45
|
+
state.collections = searchCollections;
|
|
46
|
+
state.page = page;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
case SEARCH_ENTRIES_SUCCESS: {
|
|
51
|
+
const { entries, page } = action.payload;
|
|
52
|
+
const entryIds = entries.map(entry => ({ collection: entry.collection, slug: entry.slug }));
|
|
53
|
+
state.isFetching = false;
|
|
54
|
+
state.page = page;
|
|
55
|
+
state.entryIds =
|
|
56
|
+
!page || isNaN(page) || page === 0 ? entryIds : state.entryIds.concat(entryIds);
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
case SEARCH_ENTRIES_FAILURE: {
|
|
61
|
+
const { error } = action.payload;
|
|
62
|
+
state.isFetching = false;
|
|
63
|
+
state.error = error;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
case QUERY_REQUEST: {
|
|
68
|
+
const { searchTerm } = action.payload;
|
|
69
|
+
state.isFetching = true;
|
|
70
|
+
state.term = searchTerm;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
case QUERY_SUCCESS: {
|
|
75
|
+
const { namespace, hits } = action.payload;
|
|
76
|
+
state.isFetching = false;
|
|
77
|
+
state.queryHits[namespace] = hits;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
case QUERY_FAILURE: {
|
|
82
|
+
const { error } = action.payload;
|
|
83
|
+
state.isFetching = false;
|
|
84
|
+
state.error = error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}, defaultState);
|
|
88
|
+
|
|
89
|
+
export default search;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { produce } from 'immer';
|
|
2
|
+
|
|
3
|
+
import { STATUS_REQUEST, STATUS_SUCCESS, STATUS_FAILURE } from '../actions/status';
|
|
4
|
+
|
|
5
|
+
import type { StatusAction } from '../actions/status';
|
|
6
|
+
|
|
7
|
+
export type Status = {
|
|
8
|
+
isFetching: boolean;
|
|
9
|
+
status: {
|
|
10
|
+
auth: { status: boolean };
|
|
11
|
+
api: { status: boolean; statusPage: string };
|
|
12
|
+
};
|
|
13
|
+
error: Error | undefined;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const defaultState: Status = {
|
|
17
|
+
isFetching: false,
|
|
18
|
+
status: {
|
|
19
|
+
auth: { status: true },
|
|
20
|
+
api: { status: true, statusPage: '' },
|
|
21
|
+
},
|
|
22
|
+
error: undefined,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const status = produce((state: Status, action: StatusAction) => {
|
|
26
|
+
switch (action.type) {
|
|
27
|
+
case STATUS_REQUEST:
|
|
28
|
+
state.isFetching = true;
|
|
29
|
+
break;
|
|
30
|
+
case STATUS_SUCCESS:
|
|
31
|
+
state.isFetching = false;
|
|
32
|
+
state.status = action.payload.status;
|
|
33
|
+
break;
|
|
34
|
+
case STATUS_FAILURE:
|
|
35
|
+
state.isFetching = false;
|
|
36
|
+
state.error = action.payload.error;
|
|
37
|
+
}
|
|
38
|
+
}, defaultState);
|
|
39
|
+
|
|
40
|
+
export default status;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createStore, applyMiddleware } from 'redux';
|
|
2
|
+
import { composeWithDevTools } from 'redux-devtools-extension';
|
|
3
|
+
import thunkMiddleware from 'redux-thunk';
|
|
4
|
+
|
|
5
|
+
import { waitUntilAction } from './middleware/waitUntilAction';
|
|
6
|
+
import createRootReducer from '../reducers/combinedReducer';
|
|
7
|
+
|
|
8
|
+
import type { ThunkMiddleware } from 'redux-thunk';
|
|
9
|
+
import type { AnyAction } from 'redux';
|
|
10
|
+
import type { State } from '../types/redux';
|
|
11
|
+
import type { Reducer } from 'react';
|
|
12
|
+
|
|
13
|
+
const store = createStore<State | undefined, AnyAction, unknown, unknown>(
|
|
14
|
+
createRootReducer() as unknown as Reducer<State | undefined, AnyAction>,
|
|
15
|
+
composeWithDevTools(applyMiddleware(thunkMiddleware as ThunkMiddleware<State>, waitUntilAction)),
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
export { store };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Based on wait-service by Mozilla:
|
|
2
|
+
// https://github.com/mozilla/gecko-dev/blob/master/devtools/client/shared/redux/middleware/wait-service.js
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A middleware that provides the ability for actions to install a
|
|
6
|
+
* function to be run once when a specific condition is met by an
|
|
7
|
+
* action coming through the system. Think of it as a thunk that
|
|
8
|
+
* blocks until the condition is met.
|
|
9
|
+
*/
|
|
10
|
+
import type { Middleware, MiddlewareAPI, Dispatch, AnyAction } from 'redux';
|
|
11
|
+
import type { State } from '../../types/redux';
|
|
12
|
+
|
|
13
|
+
export const WAIT_UNTIL_ACTION = 'WAIT_UNTIL_ACTION';
|
|
14
|
+
|
|
15
|
+
export interface WaitActionArgs {
|
|
16
|
+
predicate: (action: AnyAction) => boolean;
|
|
17
|
+
run: (dispatch: Dispatch, getState: () => State, action: AnyAction) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface WaitAction extends WaitActionArgs {
|
|
21
|
+
type: typeof WAIT_UNTIL_ACTION;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// eslint-disable-next-line func-style
|
|
25
|
+
export const waitUntilAction: Middleware<{}, State, Dispatch> = ({
|
|
26
|
+
dispatch,
|
|
27
|
+
getState,
|
|
28
|
+
}: MiddlewareAPI<Dispatch, State>) => {
|
|
29
|
+
let pending: WaitAction[] = [];
|
|
30
|
+
|
|
31
|
+
function checkPending(action: AnyAction): void {
|
|
32
|
+
const readyRequests = [];
|
|
33
|
+
const stillPending = [];
|
|
34
|
+
|
|
35
|
+
// Find the pending requests whose predicates are satisfied with
|
|
36
|
+
// this action. Wait to run the requests until after we update the
|
|
37
|
+
// pending queue because the request handler may synchronously
|
|
38
|
+
// dispatch again and run this service (that use case is
|
|
39
|
+
// completely valid).
|
|
40
|
+
for (const request of pending) {
|
|
41
|
+
if (request.predicate(action)) {
|
|
42
|
+
readyRequests.push(request);
|
|
43
|
+
} else {
|
|
44
|
+
stillPending.push(request);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
pending = stillPending;
|
|
49
|
+
for (const request of readyRequests) {
|
|
50
|
+
request.run(dispatch, getState, action);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return (next: Dispatch<AnyAction>) =>
|
|
55
|
+
(action: AnyAction): null | AnyAction => {
|
|
56
|
+
if (action.type === WAIT_UNTIL_ACTION) {
|
|
57
|
+
pending.push(action as WaitAction);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const result = next(action);
|
|
61
|
+
checkPending(action);
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { createHashHistory } from 'history';
|
|
2
|
+
import { mocked } from 'ts-jest/utils';
|
|
3
|
+
|
|
4
|
+
import type { History } from 'history';
|
|
5
|
+
|
|
6
|
+
jest.mock('history');
|
|
7
|
+
|
|
8
|
+
const history = { push: jest.fn(), replace: jest.fn() } as unknown as History;
|
|
9
|
+
const mockedCreateHashHistory = mocked(createHashHistory);
|
|
10
|
+
mockedCreateHashHistory.mockReturnValue(history);
|
|
11
|
+
|
|
12
|
+
describe('history', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
jest.clearAllMocks();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('navigateToCollection', () => {
|
|
18
|
+
it('should push route', () => {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
20
|
+
const { navigateToCollection } = require('../history');
|
|
21
|
+
|
|
22
|
+
navigateToCollection('posts');
|
|
23
|
+
expect(history.push).toHaveBeenCalledTimes(1);
|
|
24
|
+
expect(history.push).toHaveBeenCalledWith('/collections/posts');
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('navigateToNewEntry', () => {
|
|
29
|
+
it('should replace route', () => {
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
31
|
+
const { navigateToNewEntry } = require('../history');
|
|
32
|
+
|
|
33
|
+
navigateToNewEntry('posts');
|
|
34
|
+
expect(history.replace).toHaveBeenCalledTimes(1);
|
|
35
|
+
expect(history.replace).toHaveBeenCalledWith('/collections/posts/new');
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('navigateToEntry', () => {
|
|
40
|
+
it('should replace route', () => {
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
42
|
+
const { navigateToEntry } = require('../history');
|
|
43
|
+
|
|
44
|
+
navigateToEntry('posts', 'index');
|
|
45
|
+
expect(history.replace).toHaveBeenCalledTimes(1);
|
|
46
|
+
expect(history.replace).toHaveBeenCalledWith('/collections/posts/entries/index');
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createHashHistory } from 'history';
|
|
2
|
+
|
|
3
|
+
const history = createHashHistory();
|
|
4
|
+
|
|
5
|
+
export function navigateToCollection(collectionName: string) {
|
|
6
|
+
return history.push(`/collections/${collectionName}`);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function navigateToNewEntry(collectionName: string) {
|
|
10
|
+
return history.replace(`/collections/${collectionName}/new`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function navigateToEntry(collectionName: string, slug: string) {
|
|
14
|
+
return history.replace(`/collections/${collectionName}/entries/${slug}`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { history };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module 'diacritics';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface StaticallyTypedRecord<T> {
|
|
2
|
+
get<K extends keyof T>(key: K, defaultValue?: T[K]): T[K];
|
|
3
|
+
set<K extends keyof T, V extends T[K]>(key: K, value: V): StaticallyTypedRecord<T> & T;
|
|
4
|
+
has<K extends keyof T>(key: K): boolean;
|
|
5
|
+
delete<K extends keyof T>(key: K): StaticallyTypedRecord<T>;
|
|
6
|
+
getIn<K1 extends keyof T, K2 extends keyof T[K1], V extends T[K1][K2]>(
|
|
7
|
+
keys: [K1, K2],
|
|
8
|
+
defaultValue?: V,
|
|
9
|
+
): T[K1][K2];
|
|
10
|
+
getIn<
|
|
11
|
+
K1 extends keyof T,
|
|
12
|
+
K2 extends keyof T[K1],
|
|
13
|
+
K3 extends keyof T[K1][K2],
|
|
14
|
+
V extends T[K1][K2][K3],
|
|
15
|
+
>(
|
|
16
|
+
keys: [K1, K2, K3],
|
|
17
|
+
defaultValue?: V,
|
|
18
|
+
): T[K1][K2][K3];
|
|
19
|
+
getIn(keys: string[]): unknown;
|
|
20
|
+
setIn<K1 extends keyof T, K2 extends keyof T[K1], V extends T[K1][K2]>(
|
|
21
|
+
keys: [K1, K2],
|
|
22
|
+
value: V,
|
|
23
|
+
): StaticallyTypedRecord<T>;
|
|
24
|
+
setIn(keys: string[], value: unknown): StaticallyTypedRecord<T> & T;
|
|
25
|
+
toJS(): T;
|
|
26
|
+
isEmpty(): boolean;
|
|
27
|
+
some<K extends keyof T>(predicate: (value: T[K], key: K, iter: this) => boolean): boolean;
|
|
28
|
+
mapKeys<K extends keyof T, V>(mapFunc: (key: K, value: StaticallyTypedRecord<T>) => V): V[];
|
|
29
|
+
find<K extends keyof T>(findFunc: (value: T[K]) => boolean): T[K];
|
|
30
|
+
filter<K extends keyof T>(
|
|
31
|
+
predicate: (value: T[K], key: K, iter: this) => boolean,
|
|
32
|
+
): StaticallyTypedRecord<T>;
|
|
33
|
+
valueSeq<K extends keyof T>(): T[K][] & { toArray: () => T[K][] };
|
|
34
|
+
map<K extends keyof T, V>(
|
|
35
|
+
mapFunc: (value: T[K]) => V,
|
|
36
|
+
): StaticallyTypedRecord<{ [key: string]: V }>;
|
|
37
|
+
keySeq<K extends keyof T>(): { toArray: () => K[] };
|
|
38
|
+
withMutations(mutator: (mutable: StaticallyTypedRecord<T>) => unknown): StaticallyTypedRecord<T>;
|
|
39
|
+
}
|