@pranaysahith/decap-cms-core 3.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/README.md +9 -0
  2. package/dist/@pranaysahith/decap-cms-core.js +52 -0
  3. package/dist/@pranaysahith/decap-cms-core.js.LICENSE.txt +141 -0
  4. package/dist/@pranaysahith/decap-cms-core.js.map +1 -0
  5. package/dist/decap-cms-core.js +47 -0
  6. package/dist/decap-cms-core.js.LICENSE.txt +116 -0
  7. package/dist/decap-cms-core.js.map +1 -0
  8. package/dist/esm/actions/auth.js +97 -0
  9. package/dist/esm/actions/collections.js +15 -0
  10. package/dist/esm/actions/config.js +493 -0
  11. package/dist/esm/actions/deploys.js +79 -0
  12. package/dist/esm/actions/editorialWorkflow.js +480 -0
  13. package/dist/esm/actions/entries.js +865 -0
  14. package/dist/esm/actions/media.js +147 -0
  15. package/dist/esm/actions/mediaLibrary.js +552 -0
  16. package/dist/esm/actions/notifications.js +21 -0
  17. package/dist/esm/actions/search.js +149 -0
  18. package/dist/esm/actions/status.js +74 -0
  19. package/dist/esm/actions/waitUntil.js +32 -0
  20. package/dist/esm/backend.js +1082 -0
  21. package/dist/esm/bootstrap.js +101 -0
  22. package/dist/esm/components/App/App.js +289 -0
  23. package/dist/esm/components/App/Header.js +172 -0
  24. package/dist/esm/components/App/NotFoundPage.js +19 -0
  25. package/dist/esm/components/Collection/Collection.js +198 -0
  26. package/dist/esm/components/Collection/CollectionControls.js +46 -0
  27. package/dist/esm/components/Collection/CollectionSearch.js +222 -0
  28. package/dist/esm/components/Collection/CollectionTop.js +68 -0
  29. package/dist/esm/components/Collection/ControlButton.js +17 -0
  30. package/dist/esm/components/Collection/Entries/Entries.js +73 -0
  31. package/dist/esm/components/Collection/Entries/EntriesCollection.js +241 -0
  32. package/dist/esm/components/Collection/Entries/EntriesSearch.js +113 -0
  33. package/dist/esm/components/Collection/Entries/EntryCard.js +177 -0
  34. package/dist/esm/components/Collection/Entries/EntryListing.js +143 -0
  35. package/dist/esm/components/Collection/FilterControl.js +33 -0
  36. package/dist/esm/components/Collection/FolderRenameControl.js +403 -0
  37. package/dist/esm/components/Collection/GroupControl.js +33 -0
  38. package/dist/esm/components/Collection/NestedCollection.js +308 -0
  39. package/dist/esm/components/Collection/Sidebar.js +91 -0
  40. package/dist/esm/components/Collection/SortControl.js +59 -0
  41. package/dist/esm/components/Collection/ViewStyleControl.js +38 -0
  42. package/dist/esm/components/Editor/Editor.js +466 -0
  43. package/dist/esm/components/Editor/EditorControlPane/EditorControl.js +395 -0
  44. package/dist/esm/components/Editor/EditorControlPane/EditorControlPane.js +254 -0
  45. package/dist/esm/components/Editor/EditorControlPane/Widget.js +374 -0
  46. package/dist/esm/components/Editor/EditorInterface.js +386 -0
  47. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreview.js +47 -0
  48. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewContent.js +66 -0
  49. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewPane.js +288 -0
  50. package/dist/esm/components/Editor/EditorPreviewPane/PreviewHOC.js +27 -0
  51. package/dist/esm/components/Editor/EditorToolbar.js +536 -0
  52. package/dist/esm/components/Editor/EntryPathEditor.js +272 -0
  53. package/dist/esm/components/Editor/withWorkflow.js +56 -0
  54. package/dist/esm/components/EditorWidgets/Unknown/UnknownControl.js +18 -0
  55. package/dist/esm/components/EditorWidgets/Unknown/UnknownPreview.js +20 -0
  56. package/dist/esm/components/EditorWidgets/index.js +4 -0
  57. package/dist/esm/components/MediaLibrary/EmptyMessage.js +22 -0
  58. package/dist/esm/components/MediaLibrary/MediaLibrary.js +446 -0
  59. package/dist/esm/components/MediaLibrary/MediaLibraryButtons.js +93 -0
  60. package/dist/esm/components/MediaLibrary/MediaLibraryCard.js +99 -0
  61. package/dist/esm/components/MediaLibrary/MediaLibraryCardGrid.js +198 -0
  62. package/dist/esm/components/MediaLibrary/MediaLibraryHeader.js +32 -0
  63. package/dist/esm/components/MediaLibrary/MediaLibraryModal.js +156 -0
  64. package/dist/esm/components/MediaLibrary/MediaLibrarySearch.js +51 -0
  65. package/dist/esm/components/MediaLibrary/MediaLibraryTop.js +123 -0
  66. package/dist/esm/components/UI/DragDrop.js +67 -0
  67. package/dist/esm/components/UI/ErrorBoundary.js +173 -0
  68. package/dist/esm/components/UI/FileUploadButton.js +27 -0
  69. package/dist/esm/components/UI/Modal.js +104 -0
  70. package/dist/esm/components/UI/Notifications.js +62 -0
  71. package/dist/esm/components/UI/SettingsDropdown.js +107 -0
  72. package/dist/esm/components/UI/index.js +6 -0
  73. package/dist/esm/components/Workflow/Workflow.js +133 -0
  74. package/dist/esm/components/Workflow/WorkflowCard.js +128 -0
  75. package/dist/esm/components/Workflow/WorkflowList.js +204 -0
  76. package/dist/esm/constants/collectionTypes.js +2 -0
  77. package/dist/esm/constants/collectionViews.js +2 -0
  78. package/dist/esm/constants/commitProps.js +2 -0
  79. package/dist/esm/constants/configSchema.js +644 -0
  80. package/dist/esm/constants/fieldInference.js +57 -0
  81. package/dist/esm/constants/publishModes.js +18 -0
  82. package/dist/esm/constants/validationErrorTypes.js +6 -0
  83. package/dist/esm/formats/formats.js +83 -0
  84. package/dist/esm/formats/frontmatter.js +146 -0
  85. package/dist/esm/formats/helpers.js +12 -0
  86. package/dist/esm/formats/json.js +8 -0
  87. package/dist/esm/formats/toml.js +32 -0
  88. package/dist/esm/formats/yaml.js +51 -0
  89. package/dist/esm/index.js +7 -0
  90. package/dist/esm/integrations/index.js +28 -0
  91. package/dist/esm/integrations/providers/algolia/implementation.js +174 -0
  92. package/dist/esm/integrations/providers/assetStore/implementation.js +165 -0
  93. package/dist/esm/lib/consoleError.js +3 -0
  94. package/dist/esm/lib/formatters.js +191 -0
  95. package/dist/esm/lib/i18n.js +367 -0
  96. package/dist/esm/lib/phrases.js +6 -0
  97. package/dist/esm/lib/polyfill.js +8 -0
  98. package/dist/esm/lib/registry.js +329 -0
  99. package/dist/esm/lib/serializeEntryValues.js +67 -0
  100. package/dist/esm/lib/stega.js +142 -0
  101. package/dist/esm/lib/textHelper.js +9 -0
  102. package/dist/esm/lib/urlHelper.js +111 -0
  103. package/dist/esm/mediaLibrary.js +37 -0
  104. package/dist/esm/reducers/auth.js +27 -0
  105. package/dist/esm/reducers/collections.js +428 -0
  106. package/dist/esm/reducers/combinedReducer.js +8 -0
  107. package/dist/esm/reducers/config.js +29 -0
  108. package/dist/esm/reducers/cursors.js +31 -0
  109. package/dist/esm/reducers/deploys.js +45 -0
  110. package/dist/esm/reducers/editorialWorkflow.js +83 -0
  111. package/dist/esm/reducers/entries.js +568 -0
  112. package/dist/esm/reducers/entryDraft.js +212 -0
  113. package/dist/esm/reducers/globalUI.js +25 -0
  114. package/dist/esm/reducers/index.js +66 -0
  115. package/dist/esm/reducers/integrations.js +53 -0
  116. package/dist/esm/reducers/mediaLibrary.js +252 -0
  117. package/dist/esm/reducers/medias.js +68 -0
  118. package/dist/esm/reducers/notifications.js +23 -0
  119. package/dist/esm/reducers/search.js +92 -0
  120. package/dist/esm/reducers/status.js +30 -0
  121. package/dist/esm/redux/index.js +7 -0
  122. package/dist/esm/redux/middleware/waitUntilAction.js +48 -0
  123. package/dist/esm/routing/history.js +12 -0
  124. package/dist/esm/types/diacritics.d.js +0 -0
  125. package/dist/esm/types/global.d.js +1 -0
  126. package/dist/esm/types/immutable.js +7 -0
  127. package/dist/esm/types/redux.js +14 -0
  128. package/dist/esm/types/tomlify-j0.4.d.js +0 -0
  129. package/dist/esm/valueObjects/AssetProxy.js +44 -0
  130. package/dist/esm/valueObjects/EditorComponent.js +34 -0
  131. package/dist/esm/valueObjects/Entry.js +20 -0
  132. package/index.d.ts +618 -0
  133. package/package.json +106 -0
  134. package/src/__tests__/backend.spec.js +1161 -0
  135. package/src/actions/__tests__/config.spec.js +1009 -0
  136. package/src/actions/__tests__/editorialWorkflow.spec.js +216 -0
  137. package/src/actions/__tests__/entries.spec.js +596 -0
  138. package/src/actions/__tests__/media.spec.ts +171 -0
  139. package/src/actions/__tests__/mediaLibrary.spec.js +327 -0
  140. package/src/actions/__tests__/search.spec.js +209 -0
  141. package/src/actions/auth.ts +127 -0
  142. package/src/actions/collections.ts +18 -0
  143. package/src/actions/config.ts +565 -0
  144. package/src/actions/deploys.ts +104 -0
  145. package/src/actions/editorialWorkflow.ts +567 -0
  146. package/src/actions/entries.ts +1055 -0
  147. package/src/actions/media.ts +139 -0
  148. package/src/actions/mediaLibrary.ts +574 -0
  149. package/src/actions/notifications.ts +36 -0
  150. package/src/actions/search.ts +221 -0
  151. package/src/actions/status.ts +99 -0
  152. package/src/actions/waitUntil.ts +49 -0
  153. package/src/backend.ts +1400 -0
  154. package/src/bootstrap.js +104 -0
  155. package/src/components/App/App.js +286 -0
  156. package/src/components/App/Header.js +266 -0
  157. package/src/components/App/NotFoundPage.js +23 -0
  158. package/src/components/Collection/Collection.js +210 -0
  159. package/src/components/Collection/CollectionControls.js +58 -0
  160. package/src/components/Collection/CollectionSearch.js +243 -0
  161. package/src/components/Collection/CollectionTop.js +81 -0
  162. package/src/components/Collection/ControlButton.js +27 -0
  163. package/src/components/Collection/Entries/Entries.js +82 -0
  164. package/src/components/Collection/Entries/EntriesCollection.js +277 -0
  165. package/src/components/Collection/Entries/EntriesSearch.js +102 -0
  166. package/src/components/Collection/Entries/EntryCard.js +246 -0
  167. package/src/components/Collection/Entries/EntryListing.js +151 -0
  168. package/src/components/Collection/Entries/__tests__/EntriesCollection.spec.js +163 -0
  169. package/src/components/Collection/Entries/__tests__/__snapshots__/EntriesCollection.spec.js.snap +46 -0
  170. package/src/components/Collection/FilterControl.js +39 -0
  171. package/src/components/Collection/GroupControl.js +39 -0
  172. package/src/components/Collection/NestedCollection.js +330 -0
  173. package/src/components/Collection/Sidebar.js +136 -0
  174. package/src/components/Collection/SortControl.js +68 -0
  175. package/src/components/Collection/ViewStyleControl.js +50 -0
  176. package/src/components/Collection/__tests__/Collection.spec.js +75 -0
  177. package/src/components/Collection/__tests__/NestedCollection.spec.js +445 -0
  178. package/src/components/Collection/__tests__/Sidebar.spec.js +87 -0
  179. package/src/components/Collection/__tests__/__snapshots__/Collection.spec.js.snap +144 -0
  180. package/src/components/Collection/__tests__/__snapshots__/NestedCollection.spec.js.snap +550 -0
  181. package/src/components/Collection/__tests__/__snapshots__/Sidebar.spec.js.snap +312 -0
  182. package/src/components/Editor/Editor.js +497 -0
  183. package/src/components/Editor/EditorControlPane/EditorControl.js +452 -0
  184. package/src/components/Editor/EditorControlPane/EditorControlPane.js +269 -0
  185. package/src/components/Editor/EditorControlPane/Widget.js +384 -0
  186. package/src/components/Editor/EditorInterface.js +444 -0
  187. package/src/components/Editor/EditorPreviewPane/EditorPreview.js +40 -0
  188. package/src/components/Editor/EditorPreviewPane/EditorPreviewContent.js +74 -0
  189. package/src/components/Editor/EditorPreviewPane/EditorPreviewPane.js +333 -0
  190. package/src/components/Editor/EditorPreviewPane/PreviewHOC.js +33 -0
  191. package/src/components/Editor/EditorToolbar.js +691 -0
  192. package/src/components/Editor/__tests__/Editor.spec.js +221 -0
  193. package/src/components/Editor/__tests__/EditorToolbar.spec.js +120 -0
  194. package/src/components/Editor/__tests__/__snapshots__/Editor.spec.js.snap +45 -0
  195. package/src/components/Editor/__tests__/__snapshots__/EditorToolbar.spec.js.snap +4233 -0
  196. package/src/components/Editor/withWorkflow.js +61 -0
  197. package/src/components/EditorWidgets/Unknown/UnknownControl.js +17 -0
  198. package/src/components/EditorWidgets/Unknown/UnknownPreview.js +19 -0
  199. package/src/components/EditorWidgets/index.js +5 -0
  200. package/src/components/MediaLibrary/EmptyMessage.js +28 -0
  201. package/src/components/MediaLibrary/MediaLibrary.js +411 -0
  202. package/src/components/MediaLibrary/MediaLibraryButtons.js +136 -0
  203. package/src/components/MediaLibrary/MediaLibraryCard.js +128 -0
  204. package/src/components/MediaLibrary/MediaLibraryCardGrid.js +199 -0
  205. package/src/components/MediaLibrary/MediaLibraryHeader.js +48 -0
  206. package/src/components/MediaLibrary/MediaLibraryModal.js +200 -0
  207. package/src/components/MediaLibrary/MediaLibrarySearch.js +61 -0
  208. package/src/components/MediaLibrary/MediaLibraryTop.js +143 -0
  209. package/src/components/MediaLibrary/__tests__/MediaLibraryButtons.spec.js +45 -0
  210. package/src/components/MediaLibrary/__tests__/MediaLibraryCard.spec.js +49 -0
  211. package/src/components/MediaLibrary/__tests__/__snapshots__/MediaLibraryCard.spec.js.snap +264 -0
  212. package/src/components/UI/DragDrop.js +66 -0
  213. package/src/components/UI/ErrorBoundary.js +214 -0
  214. package/src/components/UI/FileUploadButton.js +24 -0
  215. package/src/components/UI/Modal.js +112 -0
  216. package/src/components/UI/Notifications.tsx +83 -0
  217. package/src/components/UI/SettingsDropdown.js +103 -0
  218. package/src/components/UI/__tests__/ErrorBoundary.spec.js +57 -0
  219. package/src/components/UI/index.js +6 -0
  220. package/src/components/Workflow/Workflow.js +169 -0
  221. package/src/components/Workflow/WorkflowCard.js +177 -0
  222. package/src/components/Workflow/WorkflowList.js +272 -0
  223. package/src/constants/__tests__/configSchema.spec.js +611 -0
  224. package/src/constants/collectionTypes.ts +2 -0
  225. package/src/constants/collectionViews.js +2 -0
  226. package/src/constants/commitProps.ts +2 -0
  227. package/src/constants/configSchema.js +441 -0
  228. package/src/constants/fieldInference.tsx +78 -0
  229. package/src/constants/publishModes.ts +22 -0
  230. package/src/constants/validationErrorTypes.js +6 -0
  231. package/src/formats/__tests__/formats.spec.js +87 -0
  232. package/src/formats/__tests__/frontmatter.spec.js +429 -0
  233. package/src/formats/__tests__/toml.spec.js +9 -0
  234. package/src/formats/__tests__/yaml.spec.js +162 -0
  235. package/src/formats/formats.ts +97 -0
  236. package/src/formats/frontmatter.ts +150 -0
  237. package/src/formats/helpers.ts +14 -0
  238. package/src/formats/json.ts +9 -0
  239. package/src/formats/toml.ts +33 -0
  240. package/src/formats/yaml.ts +58 -0
  241. package/src/index.js +8 -0
  242. package/src/integrations/index.js +35 -0
  243. package/src/integrations/providers/algolia/implementation.js +176 -0
  244. package/src/integrations/providers/assetStore/implementation.js +148 -0
  245. package/src/lib/__tests__/formatters.spec.js +751 -0
  246. package/src/lib/__tests__/i18n.spec.js +792 -0
  247. package/src/lib/__tests__/phrases.spec.js +119 -0
  248. package/src/lib/__tests__/registry.spec.js +261 -0
  249. package/src/lib/__tests__/serializeEntryValues.spec.js +22 -0
  250. package/src/lib/__tests__/urlHelper.spec.js +138 -0
  251. package/src/lib/consoleError.js +7 -0
  252. package/src/lib/formatters.ts +286 -0
  253. package/src/lib/i18n.ts +454 -0
  254. package/src/lib/phrases.js +8 -0
  255. package/src/lib/polyfill.js +9 -0
  256. package/src/lib/registry.js +312 -0
  257. package/src/lib/serializeEntryValues.js +75 -0
  258. package/src/lib/stega.ts +145 -0
  259. package/src/lib/textHelper.js +11 -0
  260. package/src/lib/urlHelper.ts +128 -0
  261. package/src/mediaLibrary.ts +51 -0
  262. package/src/reducers/__tests__/auth.spec.ts +38 -0
  263. package/src/reducers/__tests__/collections.spec.js +610 -0
  264. package/src/reducers/__tests__/config.spec.js +38 -0
  265. package/src/reducers/__tests__/entries.spec.js +694 -0
  266. package/src/reducers/__tests__/entryDraft.spec.js +297 -0
  267. package/src/reducers/__tests__/globalUI.js +43 -0
  268. package/src/reducers/__tests__/integrations.spec.ts +76 -0
  269. package/src/reducers/__tests__/mediaLibrary.spec.js +154 -0
  270. package/src/reducers/__tests__/medias.spec.ts +49 -0
  271. package/src/reducers/auth.ts +46 -0
  272. package/src/reducers/collections.ts +535 -0
  273. package/src/reducers/combinedReducer.ts +11 -0
  274. package/src/reducers/config.ts +38 -0
  275. package/src/reducers/cursors.js +36 -0
  276. package/src/reducers/deploys.ts +52 -0
  277. package/src/reducers/editorialWorkflow.ts +163 -0
  278. package/src/reducers/entries.ts +819 -0
  279. package/src/reducers/entryDraft.js +260 -0
  280. package/src/reducers/globalUI.ts +45 -0
  281. package/src/reducers/index.ts +82 -0
  282. package/src/reducers/integrations.ts +59 -0
  283. package/src/reducers/mediaLibrary.ts +296 -0
  284. package/src/reducers/medias.ts +66 -0
  285. package/src/reducers/notifications.ts +52 -0
  286. package/src/reducers/search.ts +111 -0
  287. package/src/reducers/status.ts +40 -0
  288. package/src/redux/index.ts +18 -0
  289. package/src/redux/middleware/waitUntilAction.ts +64 -0
  290. package/src/routing/__tests__/history.spec.ts +49 -0
  291. package/src/routing/history.ts +17 -0
  292. package/src/types/diacritics.d.ts +1 -0
  293. package/src/types/global.d.ts +8 -0
  294. package/src/types/immutable.ts +49 -0
  295. package/src/types/redux.ts +827 -0
  296. package/src/types/tomlify-j0.4.d.ts +13 -0
  297. package/src/valueObjects/AssetProxy.ts +48 -0
  298. package/src/valueObjects/EditorComponent.js +38 -0
  299. package/src/valueObjects/Entry.ts +63 -0
@@ -0,0 +1,139 @@
1
+ import { isAbsolutePath } from 'decap-cms-lib-util';
2
+
3
+ import { createAssetProxy } from '../valueObjects/AssetProxy';
4
+ import { selectMediaFilePath } from '../reducers/entries';
5
+ import { selectMediaFileByPath } from '../reducers/mediaLibrary';
6
+ import { getMediaFile, waitForMediaLibraryToLoad, getMediaDisplayURL } from './mediaLibrary';
7
+
8
+ import type AssetProxy from '../valueObjects/AssetProxy';
9
+ import type { Collection, State, EntryMap, EntryField } from '../types/redux';
10
+ import type { ThunkDispatch } from 'redux-thunk';
11
+ import type { AnyAction } from 'redux';
12
+
13
+ export const ADD_ASSETS = 'ADD_ASSETS';
14
+ export const ADD_ASSET = 'ADD_ASSET';
15
+ export const REMOVE_ASSET = 'REMOVE_ASSET';
16
+
17
+ export const LOAD_ASSET_REQUEST = 'LOAD_ASSET_REQUEST';
18
+ export const LOAD_ASSET_SUCCESS = 'LOAD_ASSET_SUCCESS';
19
+ export const LOAD_ASSET_FAILURE = 'LOAD_ASSET_FAILURE';
20
+
21
+ export function addAssets(assets: AssetProxy[]) {
22
+ return { type: ADD_ASSETS, payload: assets } as const;
23
+ }
24
+
25
+ export function addAsset(assetProxy: AssetProxy) {
26
+ return { type: ADD_ASSET, payload: assetProxy } as const;
27
+ }
28
+
29
+ export function removeAsset(path: string) {
30
+ return { type: REMOVE_ASSET, payload: path } as const;
31
+ }
32
+
33
+ export function loadAssetRequest(path: string) {
34
+ return { type: LOAD_ASSET_REQUEST, payload: { path } } as const;
35
+ }
36
+
37
+ export function loadAssetSuccess(path: string) {
38
+ return { type: LOAD_ASSET_SUCCESS, payload: { path } } as const;
39
+ }
40
+
41
+ export function loadAssetFailure(path: string, error: Error) {
42
+ return { type: LOAD_ASSET_FAILURE, payload: { path, error } } as const;
43
+ }
44
+
45
+ export function loadAsset(resolvedPath: string) {
46
+ return async (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
47
+ try {
48
+ dispatch(loadAssetRequest(resolvedPath));
49
+ // load asset url from backend
50
+ await waitForMediaLibraryToLoad(dispatch, getState());
51
+ const file = selectMediaFileByPath(getState(), resolvedPath);
52
+
53
+ if (file) {
54
+ const url = await getMediaDisplayURL(dispatch, getState(), file);
55
+ const asset = createAssetProxy({ path: resolvedPath, url: url || resolvedPath });
56
+ dispatch(addAsset(asset));
57
+ } else {
58
+ const { url } = await getMediaFile(getState(), resolvedPath);
59
+ const asset = createAssetProxy({ path: resolvedPath, url });
60
+ dispatch(addAsset(asset));
61
+ }
62
+ dispatch(loadAssetSuccess(resolvedPath));
63
+ } catch (e) {
64
+ dispatch(loadAssetFailure(resolvedPath, e));
65
+ }
66
+ };
67
+ }
68
+
69
+ interface GetAssetArgs {
70
+ collection: Collection;
71
+ entry: EntryMap;
72
+ path: string;
73
+ field?: EntryField;
74
+ }
75
+
76
+ const emptyAsset = createAssetProxy({
77
+ path: 'empty.svg',
78
+ file: new File([`<svg xmlns="http://www.w3.org/2000/svg"></svg>`], 'empty.svg', {
79
+ type: 'image/svg+xml',
80
+ }),
81
+ });
82
+
83
+ export function boundGetAsset(
84
+ dispatch: ThunkDispatch<State, {}, AnyAction>,
85
+ collection: Collection,
86
+ entry: EntryMap,
87
+ ) {
88
+ function bound(path: string, field: EntryField) {
89
+ const asset = dispatch(getAsset({ collection, entry, path, field }));
90
+ return asset;
91
+ }
92
+
93
+ return bound;
94
+ }
95
+
96
+ export function getAsset({ collection, entry, path, field }: GetAssetArgs) {
97
+ return (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
98
+ if (!path) return emptyAsset;
99
+
100
+ const state = getState();
101
+ const resolvedPath = selectMediaFilePath(state.config, collection, entry, path, field);
102
+
103
+ let { asset, isLoading, error } = state.medias[resolvedPath] || {};
104
+ if (isLoading) {
105
+ return emptyAsset;
106
+ }
107
+
108
+ if (asset) {
109
+ // There is already an AssetProxy in memory for this path. Use it.
110
+ return asset;
111
+ }
112
+
113
+ if (isAbsolutePath(resolvedPath)) {
114
+ // asset path is a public url so we can just use it as is
115
+ asset = createAssetProxy({ path: resolvedPath, url: path });
116
+ dispatch(addAsset(asset));
117
+ } else {
118
+ if (error) {
119
+ // on load error default back to original path
120
+ asset = createAssetProxy({ path: resolvedPath, url: path });
121
+ dispatch(addAsset(asset));
122
+ } else {
123
+ dispatch(loadAsset(resolvedPath));
124
+ asset = emptyAsset;
125
+ }
126
+ }
127
+
128
+ return asset;
129
+ };
130
+ }
131
+
132
+ export type MediasAction = ReturnType<
133
+ | typeof addAssets
134
+ | typeof addAsset
135
+ | typeof removeAsset
136
+ | typeof loadAssetRequest
137
+ | typeof loadAssetSuccess
138
+ | typeof loadAssetFailure
139
+ >;
@@ -0,0 +1,574 @@
1
+ import { Map } from 'immutable';
2
+ import { basename, getBlobSHA } from 'decap-cms-lib-util';
3
+
4
+ import { currentBackend } from '../backend';
5
+ import { createAssetProxy } from '../valueObjects/AssetProxy';
6
+ import { selectIntegration } from '../reducers';
7
+ import {
8
+ selectMediaFilePath,
9
+ selectMediaFilePublicPath,
10
+ selectEditingDraft,
11
+ } from '../reducers/entries';
12
+ import { selectMediaDisplayURL, selectMediaFiles } from '../reducers/mediaLibrary';
13
+ import { getIntegrationProvider } from '../integrations';
14
+ import { addAsset, removeAsset } from './media';
15
+ import { addDraftEntryMediaFile, removeDraftEntryMediaFile } from './entries';
16
+ import { sanitizeSlug } from '../lib/urlHelper';
17
+ import { waitUntilWithTimeout } from './waitUntil';
18
+ import { addNotification } from './notifications';
19
+
20
+ import type {
21
+ State,
22
+ MediaFile,
23
+ DisplayURLState,
24
+ MediaLibraryInstance,
25
+ EntryField,
26
+ } from '../types/redux';
27
+ import type { AnyAction } from 'redux';
28
+ import type { ThunkDispatch } from 'redux-thunk';
29
+ import type AssetProxy from '../valueObjects/AssetProxy';
30
+ import type { ImplementationMediaFile } from 'decap-cms-lib-util';
31
+
32
+ export const MEDIA_LIBRARY_OPEN = 'MEDIA_LIBRARY_OPEN';
33
+ export const MEDIA_LIBRARY_CLOSE = 'MEDIA_LIBRARY_CLOSE';
34
+ export const MEDIA_LIBRARY_CREATE = 'MEDIA_LIBRARY_CREATE';
35
+ export const MEDIA_INSERT = 'MEDIA_INSERT';
36
+ export const MEDIA_REMOVE_INSERTED = 'MEDIA_REMOVE_INSERTED';
37
+ export const MEDIA_LOAD_REQUEST = 'MEDIA_LOAD_REQUEST';
38
+ export const MEDIA_LOAD_SUCCESS = 'MEDIA_LOAD_SUCCESS';
39
+ export const MEDIA_LOAD_FAILURE = 'MEDIA_LOAD_FAILURE';
40
+ export const MEDIA_PERSIST_REQUEST = 'MEDIA_PERSIST_REQUEST';
41
+ export const MEDIA_PERSIST_SUCCESS = 'MEDIA_PERSIST_SUCCESS';
42
+ export const MEDIA_PERSIST_FAILURE = 'MEDIA_PERSIST_FAILURE';
43
+ export const MEDIA_DELETE_REQUEST = 'MEDIA_DELETE_REQUEST';
44
+ export const MEDIA_DELETE_SUCCESS = 'MEDIA_DELETE_SUCCESS';
45
+ export const MEDIA_DELETE_FAILURE = 'MEDIA_DELETE_FAILURE';
46
+ export const MEDIA_DISPLAY_URL_REQUEST = 'MEDIA_DISPLAY_URL_REQUEST';
47
+ export const MEDIA_DISPLAY_URL_SUCCESS = 'MEDIA_DISPLAY_URL_SUCCESS';
48
+ export const MEDIA_DISPLAY_URL_FAILURE = 'MEDIA_DISPLAY_URL_FAILURE';
49
+
50
+ export function createMediaLibrary(instance: MediaLibraryInstance) {
51
+ const api = {
52
+ show: instance.show || (() => undefined),
53
+ hide: instance.hide || (() => undefined),
54
+ onClearControl: instance.onClearControl || (() => undefined),
55
+ onRemoveControl: instance.onRemoveControl || (() => undefined),
56
+ enableStandalone: instance.enableStandalone || (() => undefined),
57
+ };
58
+ return { type: MEDIA_LIBRARY_CREATE, payload: api } as const;
59
+ }
60
+
61
+ export function clearMediaControl(id: string) {
62
+ return (_dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
63
+ const state = getState();
64
+ const mediaLibrary = state.mediaLibrary.get('externalLibrary');
65
+ if (mediaLibrary) {
66
+ mediaLibrary.onClearControl({ id });
67
+ }
68
+ };
69
+ }
70
+
71
+ export function removeMediaControl(id: string) {
72
+ return (_dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
73
+ const state = getState();
74
+ const mediaLibrary = state.mediaLibrary.get('externalLibrary');
75
+ if (mediaLibrary) {
76
+ mediaLibrary.onRemoveControl({ id });
77
+ }
78
+ };
79
+ }
80
+
81
+ export function openMediaLibrary(
82
+ payload: {
83
+ controlID?: string;
84
+ forImage?: boolean;
85
+ privateUpload?: boolean;
86
+ value?: string;
87
+ allowMultiple?: boolean;
88
+ config?: Map<string, unknown>;
89
+ field?: EntryField;
90
+ } = {},
91
+ ) {
92
+ return (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
93
+ const state = getState();
94
+ const mediaLibrary = state.mediaLibrary.get('externalLibrary');
95
+ if (mediaLibrary) {
96
+ const { controlID: id, value, config = Map(), allowMultiple, forImage } = payload;
97
+ mediaLibrary.show({ id, value, config: config.toJS(), allowMultiple, imagesOnly: forImage });
98
+ }
99
+ dispatch(mediaLibraryOpened(payload));
100
+ };
101
+ }
102
+
103
+ export function closeMediaLibrary() {
104
+ return (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
105
+ const state = getState();
106
+ const mediaLibrary = state.mediaLibrary.get('externalLibrary');
107
+ if (mediaLibrary) {
108
+ mediaLibrary.hide();
109
+ }
110
+ dispatch(mediaLibraryClosed());
111
+ };
112
+ }
113
+
114
+ export function insertMedia(mediaPath: string | string[], field: EntryField | undefined) {
115
+ return (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
116
+ const state = getState();
117
+ const config = state.config;
118
+ const entry = state.entryDraft.get('entry');
119
+ const collectionName = state.entryDraft.getIn(['entry', 'collection']);
120
+ const collection = state.collections.get(collectionName);
121
+ if (Array.isArray(mediaPath)) {
122
+ mediaPath = mediaPath.map(path =>
123
+ selectMediaFilePublicPath(config, collection, path, entry, field),
124
+ );
125
+ } else {
126
+ mediaPath = selectMediaFilePublicPath(config, collection, mediaPath as string, entry, field);
127
+ }
128
+ dispatch(mediaInserted(mediaPath));
129
+ };
130
+ }
131
+
132
+ export function removeInsertedMedia(controlID: string) {
133
+ return { type: MEDIA_REMOVE_INSERTED, payload: { controlID } } as const;
134
+ }
135
+
136
+ export function loadMedia(
137
+ opts: { delay?: number; query?: string; page?: number; privateUpload?: boolean } = {},
138
+ ) {
139
+ const { delay = 0, query = '', page = 1, privateUpload } = opts;
140
+ return async (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
141
+ const state = getState();
142
+ const backend = currentBackend(state.config);
143
+ const integration = selectIntegration(state, null, 'assetStore');
144
+ if (integration) {
145
+ const provider = getIntegrationProvider(state.integrations, backend.getToken, integration);
146
+ dispatch(mediaLoading(page));
147
+ try {
148
+ const files = await provider.retrieve(query, page, privateUpload);
149
+ const mediaLoadedOpts = {
150
+ page,
151
+ canPaginate: true,
152
+ dynamicSearch: true,
153
+ dynamicSearchQuery: query,
154
+ privateUpload,
155
+ };
156
+ return dispatch(mediaLoaded(files, mediaLoadedOpts));
157
+ } catch (error) {
158
+ return dispatch(mediaLoadFailed({ privateUpload }));
159
+ }
160
+ }
161
+ dispatch(mediaLoading(page));
162
+
163
+ function loadFunction() {
164
+ return backend
165
+ .getMedia()
166
+ .then(files => dispatch(mediaLoaded(files)))
167
+ .catch((error: { status?: number }) => {
168
+ console.error(error);
169
+ if (error.status === 404) {
170
+ console.log('This 404 was expected and handled appropriately.');
171
+ dispatch(mediaLoaded([]));
172
+ } else {
173
+ dispatch(mediaLoadFailed());
174
+ }
175
+ });
176
+ }
177
+
178
+ if (delay > 0) {
179
+ return new Promise(resolve => {
180
+ setTimeout(() => resolve(loadFunction()), delay);
181
+ });
182
+ } else {
183
+ return loadFunction();
184
+ }
185
+ };
186
+ }
187
+
188
+ function createMediaFileFromAsset({
189
+ id,
190
+ file,
191
+ assetProxy,
192
+ draft,
193
+ }: {
194
+ id: string;
195
+ file: File;
196
+ assetProxy: AssetProxy;
197
+ draft: boolean;
198
+ }): ImplementationMediaFile {
199
+ const mediaFile = {
200
+ id,
201
+ name: basename(assetProxy.path),
202
+ displayURL: assetProxy.url,
203
+ draft,
204
+ file,
205
+ size: file.size,
206
+ url: assetProxy.url,
207
+ path: assetProxy.path,
208
+ field: assetProxy.field,
209
+ };
210
+ return mediaFile;
211
+ }
212
+
213
+ export function persistMedia(file: File, opts: MediaOptions = {}) {
214
+ const { privateUpload, field } = opts;
215
+ return async (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
216
+ const state = getState();
217
+ const backend = currentBackend(state.config);
218
+ const integration = selectIntegration(state, null, 'assetStore');
219
+ const files: MediaFile[] = selectMediaFiles(state, field);
220
+ const fileName = sanitizeSlug(file.name.toLowerCase(), state.config.slug);
221
+ const existingFile = files.find(existingFile => existingFile.name.toLowerCase() === fileName);
222
+
223
+ const editingDraft = selectEditingDraft(state.entryDraft);
224
+
225
+ /**
226
+ * Check for existing files of the same name before persisting. If no asset
227
+ * store integration is used, files are being stored in Git, so we can
228
+ * expect file names to be unique. If an asset store is in use, file names
229
+ * may not be unique, so we forego this check.
230
+ */
231
+ if (!integration && existingFile) {
232
+ if (!window.confirm(`${existingFile.name} already exists. Do you want to replace it?`)) {
233
+ return;
234
+ } else {
235
+ await dispatch(deleteMedia(existingFile, { privateUpload }));
236
+ }
237
+ }
238
+
239
+ if (integration || !editingDraft) {
240
+ dispatch(mediaPersisting());
241
+ }
242
+
243
+ try {
244
+ let assetProxy: AssetProxy;
245
+ if (integration) {
246
+ try {
247
+ const provider = getIntegrationProvider(
248
+ state.integrations,
249
+ backend.getToken,
250
+ integration,
251
+ );
252
+ const response = await provider.upload(file, privateUpload);
253
+ assetProxy = createAssetProxy({
254
+ url: response.asset.url,
255
+ path: response.asset.url,
256
+ });
257
+ } catch (error) {
258
+ assetProxy = createAssetProxy({
259
+ file,
260
+ path: fileName,
261
+ });
262
+ }
263
+ } else if (privateUpload) {
264
+ throw new Error('The Private Upload option is only available for Asset Store Integration');
265
+ } else {
266
+ const entry = state.entryDraft.get('entry');
267
+ const collection = state.collections.get(entry?.get('collection'));
268
+ const path = selectMediaFilePath(state.config, collection, entry, fileName, field);
269
+ assetProxy = createAssetProxy({
270
+ file,
271
+ path,
272
+ field,
273
+ });
274
+ }
275
+
276
+ dispatch(addAsset(assetProxy));
277
+
278
+ let mediaFile: ImplementationMediaFile;
279
+ if (integration) {
280
+ const id = await getBlobSHA(file);
281
+ // integration assets are persisted immediately, thus draft is false
282
+ mediaFile = createMediaFileFromAsset({ id, file, assetProxy, draft: false });
283
+ } else if (editingDraft) {
284
+ const id = await getBlobSHA(file);
285
+ mediaFile = createMediaFileFromAsset({
286
+ id,
287
+ file,
288
+ assetProxy,
289
+ draft: editingDraft,
290
+ });
291
+ return dispatch(addDraftEntryMediaFile(mediaFile));
292
+ } else {
293
+ mediaFile = await backend.persistMedia(state.config, assetProxy);
294
+ }
295
+
296
+ return dispatch(mediaPersisted(mediaFile, { privateUpload }));
297
+ } catch (error) {
298
+ console.error(error);
299
+ dispatch(
300
+ addNotification({
301
+ message: `Failed to persist media: ${error}`,
302
+ type: 'error',
303
+ dismissAfter: 8000,
304
+ }),
305
+ );
306
+ return dispatch(mediaPersistFailed({ privateUpload }));
307
+ }
308
+ };
309
+ }
310
+
311
+ export function deleteMedia(file: MediaFile, opts: MediaOptions = {}) {
312
+ const { privateUpload } = opts;
313
+ return async (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
314
+ const state = getState();
315
+ const backend = currentBackend(state.config);
316
+ const integration = selectIntegration(state, null, 'assetStore');
317
+ if (integration) {
318
+ const provider = getIntegrationProvider(state.integrations, backend.getToken, integration);
319
+ dispatch(mediaDeleting());
320
+
321
+ try {
322
+ await provider.delete(file.id);
323
+ return dispatch(mediaDeleted(file, { privateUpload }));
324
+ } catch (error) {
325
+ console.error(error);
326
+ dispatch(
327
+ addNotification({
328
+ message: `Failed to delete media: ${error.message}`,
329
+ type: 'error',
330
+ dismissAfter: 8000,
331
+ }),
332
+ );
333
+ return dispatch(mediaDeleteFailed({ privateUpload }));
334
+ }
335
+ }
336
+
337
+ try {
338
+ if (file.draft) {
339
+ dispatch(removeAsset(file.path));
340
+ dispatch(removeDraftEntryMediaFile({ id: file.id }));
341
+ } else {
342
+ const editingDraft = selectEditingDraft(state.entryDraft);
343
+
344
+ dispatch(mediaDeleting());
345
+ dispatch(removeAsset(file.path));
346
+
347
+ await backend.deleteMedia(state.config, file.path);
348
+
349
+ dispatch(mediaDeleted(file));
350
+ if (editingDraft) {
351
+ dispatch(removeDraftEntryMediaFile({ id: file.id }));
352
+ }
353
+ }
354
+ } catch (error) {
355
+ console.error(error);
356
+ dispatch(
357
+ addNotification({
358
+ message: `Failed to delete media: ${error.message}`,
359
+ type: 'error',
360
+ dismissAfter: 8000,
361
+ }),
362
+ );
363
+ return dispatch(mediaDeleteFailed());
364
+ }
365
+ };
366
+ }
367
+
368
+ export async function getMediaFile(state: State, path: string) {
369
+ const backend = currentBackend(state.config);
370
+ const { url } = await backend.getMediaFile(path);
371
+ return { url };
372
+ }
373
+
374
+ export function loadMediaDisplayURL(file: MediaFile) {
375
+ return async (dispatch: ThunkDispatch<State, {}, AnyAction>, getState: () => State) => {
376
+ const { displayURL, id } = file;
377
+ const state = getState();
378
+ const displayURLState: DisplayURLState = selectMediaDisplayURL(state, id);
379
+ if (
380
+ !id ||
381
+ !displayURL ||
382
+ displayURLState.get('url') ||
383
+ displayURLState.get('isFetching') ||
384
+ displayURLState.get('err')
385
+ ) {
386
+ return Promise.resolve();
387
+ }
388
+ if (typeof displayURL === 'string') {
389
+ dispatch(mediaDisplayURLRequest(id));
390
+ dispatch(mediaDisplayURLSuccess(id, displayURL));
391
+ return;
392
+ }
393
+ try {
394
+ const backend = currentBackend(state.config);
395
+ dispatch(mediaDisplayURLRequest(id));
396
+ const newURL = await backend.getMediaDisplayURL(displayURL);
397
+ if (newURL) {
398
+ dispatch(mediaDisplayURLSuccess(id, newURL));
399
+ } else {
400
+ throw new Error('No display URL was returned!');
401
+ }
402
+ } catch (err) {
403
+ console.error(err);
404
+ dispatch(mediaDisplayURLFailure(id, err));
405
+ }
406
+ };
407
+ }
408
+
409
+ function mediaLibraryOpened(payload: {
410
+ controlID?: string;
411
+ forImage?: boolean;
412
+ privateUpload?: boolean;
413
+ value?: string;
414
+ replaceIndex?: number;
415
+ allowMultiple?: boolean;
416
+ config?: Map<string, unknown>;
417
+ field?: EntryField;
418
+ }) {
419
+ return { type: MEDIA_LIBRARY_OPEN, payload } as const;
420
+ }
421
+
422
+ function mediaLibraryClosed() {
423
+ return { type: MEDIA_LIBRARY_CLOSE } as const;
424
+ }
425
+
426
+ function mediaInserted(mediaPath: string | string[]) {
427
+ return { type: MEDIA_INSERT, payload: { mediaPath } } as const;
428
+ }
429
+
430
+ export function mediaLoading(page: number) {
431
+ return {
432
+ type: MEDIA_LOAD_REQUEST,
433
+ payload: { page },
434
+ } as const;
435
+ }
436
+
437
+ interface MediaOptions {
438
+ privateUpload?: boolean;
439
+ field?: EntryField;
440
+ page?: number;
441
+ canPaginate?: boolean;
442
+ dynamicSearch?: boolean;
443
+ dynamicSearchQuery?: string;
444
+ }
445
+
446
+ export function mediaLoaded(files: ImplementationMediaFile[], opts: MediaOptions = {}) {
447
+ return {
448
+ type: MEDIA_LOAD_SUCCESS,
449
+ payload: { files, ...opts },
450
+ } as const;
451
+ }
452
+
453
+ export function mediaLoadFailed(opts: MediaOptions = {}) {
454
+ const { privateUpload } = opts;
455
+ return { type: MEDIA_LOAD_FAILURE, payload: { privateUpload } } as const;
456
+ }
457
+
458
+ export function mediaPersisting() {
459
+ return { type: MEDIA_PERSIST_REQUEST } as const;
460
+ }
461
+
462
+ export function mediaPersisted(file: ImplementationMediaFile, opts: MediaOptions = {}) {
463
+ const { privateUpload } = opts;
464
+ return {
465
+ type: MEDIA_PERSIST_SUCCESS,
466
+ payload: { file, privateUpload },
467
+ } as const;
468
+ }
469
+
470
+ export function mediaPersistFailed(opts: MediaOptions = {}) {
471
+ const { privateUpload } = opts;
472
+ return { type: MEDIA_PERSIST_FAILURE, payload: { privateUpload } } as const;
473
+ }
474
+
475
+ export function mediaDeleting() {
476
+ return { type: MEDIA_DELETE_REQUEST } as const;
477
+ }
478
+
479
+ export function mediaDeleted(file: MediaFile, opts: MediaOptions = {}) {
480
+ const { privateUpload } = opts;
481
+ return {
482
+ type: MEDIA_DELETE_SUCCESS,
483
+ payload: { file, privateUpload },
484
+ } as const;
485
+ }
486
+
487
+ export function mediaDeleteFailed(opts: MediaOptions = {}) {
488
+ const { privateUpload } = opts;
489
+ return { type: MEDIA_DELETE_FAILURE, payload: { privateUpload } } as const;
490
+ }
491
+
492
+ export function mediaDisplayURLRequest(key: string) {
493
+ return { type: MEDIA_DISPLAY_URL_REQUEST, payload: { key } } as const;
494
+ }
495
+
496
+ export function mediaDisplayURLSuccess(key: string, url: string) {
497
+ return {
498
+ type: MEDIA_DISPLAY_URL_SUCCESS,
499
+ payload: { key, url },
500
+ } as const;
501
+ }
502
+
503
+ export function mediaDisplayURLFailure(key: string, err: Error) {
504
+ return {
505
+ type: MEDIA_DISPLAY_URL_FAILURE,
506
+ payload: { key, err },
507
+ } as const;
508
+ }
509
+
510
+ export async function waitForMediaLibraryToLoad(
511
+ dispatch: ThunkDispatch<State, {}, AnyAction>,
512
+ state: State,
513
+ ) {
514
+ if (state.mediaLibrary.get('isLoading') !== false && !state.mediaLibrary.get('externalLibrary')) {
515
+ await waitUntilWithTimeout(dispatch, resolve => ({
516
+ predicate: ({ type }) => type === MEDIA_LOAD_SUCCESS || type === MEDIA_LOAD_FAILURE,
517
+ run: () => resolve(),
518
+ }));
519
+ }
520
+ }
521
+
522
+ export async function getMediaDisplayURL(
523
+ dispatch: ThunkDispatch<State, {}, AnyAction>,
524
+ state: State,
525
+ file: MediaFile,
526
+ ) {
527
+ const displayURLState: DisplayURLState = selectMediaDisplayURL(state, file.id);
528
+
529
+ let url: string | null | undefined;
530
+ if (displayURLState.get('url')) {
531
+ // url was already loaded
532
+ url = displayURLState.get('url');
533
+ } else if (displayURLState.get('err')) {
534
+ // url loading had an error
535
+ url = null;
536
+ } else {
537
+ const key = file.id;
538
+ const promise = waitUntilWithTimeout<string>(dispatch, resolve => ({
539
+ predicate: ({ type, payload }) =>
540
+ (type === MEDIA_DISPLAY_URL_SUCCESS || type === MEDIA_DISPLAY_URL_FAILURE) &&
541
+ payload.key === key,
542
+ run: (_dispatch, _getState, action) => resolve(action.payload.url),
543
+ }));
544
+
545
+ if (!displayURLState.get('isFetching')) {
546
+ // load display url
547
+ dispatch(loadMediaDisplayURL(file));
548
+ }
549
+
550
+ url = (await promise) ?? null;
551
+ }
552
+
553
+ return url;
554
+ }
555
+
556
+ export type MediaLibraryAction = ReturnType<
557
+ | typeof createMediaLibrary
558
+ | typeof mediaLibraryOpened
559
+ | typeof mediaLibraryClosed
560
+ | typeof mediaInserted
561
+ | typeof removeInsertedMedia
562
+ | typeof mediaLoading
563
+ | typeof mediaLoaded
564
+ | typeof mediaLoadFailed
565
+ | typeof mediaPersisting
566
+ | typeof mediaPersisted
567
+ | typeof mediaPersistFailed
568
+ | typeof mediaDeleting
569
+ | typeof mediaDeleted
570
+ | typeof mediaDeleteFailed
571
+ | typeof mediaDisplayURLRequest
572
+ | typeof mediaDisplayURLSuccess
573
+ | typeof mediaDisplayURLFailure
574
+ >;