sanity-plugin-media 4.3.0 → 4.3.2
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 +4 -4
- package/README.md +12 -12
- package/dist/index.d.mts +263 -195
- package/dist/index.d.ts +263 -195
- package/dist/index.js +83 -203
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +84 -203
- package/dist/index.mjs.map +1 -1
- package/package.json +42 -64
- package/src/__tests__/fixtures/createEpicTestStore.ts +5 -4
- package/src/__tests__/fixtures/mockSanityClient.ts +8 -8
- package/src/__tests__/fixtures/renderWithProviders.tsx +8 -7
- package/src/__tests__/fixtures/rootState.ts +4 -4
- package/src/components/AssetGridVirtualized/index.tsx +8 -7
- package/src/components/AssetMetadata/index.tsx +6 -5
- package/src/components/AssetTableVirtualized/index.tsx +7 -6
- package/src/components/AutoTagInputWrapper/index.tsx +9 -4
- package/src/components/Browser/Browser.test.tsx +9 -8
- package/src/components/Browser/index.tsx +2 -1
- package/src/components/Browser/useBrowserInit.ts +9 -9
- package/src/components/ButtonAssetCopy/index.tsx +1 -0
- package/src/components/ButtonViewGroup/index.tsx +4 -3
- package/src/components/CardAsset/CardAsset.test.tsx +53 -52
- package/src/components/CardAsset/index.tsx +52 -49
- package/src/components/CardUpload/index.tsx +7 -6
- package/src/components/Controls/index.tsx +7 -6
- package/src/components/DebugControls/index.tsx +5 -4
- package/src/components/DialogAssetEdit/Details.tsx +3 -2
- package/src/components/DialogAssetEdit/DialogAssetEdit.test.tsx +28 -27
- package/src/components/DialogAssetEdit/index.tsx +37 -37
- package/src/components/DialogConfirm/index.tsx +2 -1
- package/src/components/DialogSearchFacets/index.tsx +3 -2
- package/src/components/DialogTagCreate/DialogTagCreate.test.tsx +16 -15
- package/src/components/DialogTagCreate/index.tsx +11 -10
- package/src/components/DialogTagEdit/DialogTagEdit.test.tsx +28 -27
- package/src/components/DialogTagEdit/index.tsx +17 -16
- package/src/components/DialogTags/index.tsx +4 -3
- package/src/components/Dialogs/index.tsx +2 -3
- package/src/components/DocumentList/index.tsx +2 -3
- package/src/components/FileAssetPreview/index.tsx +2 -2
- package/src/components/FormBuilderTool/FormBuilderTool.test.tsx +12 -11
- package/src/components/FormBuilderTool/index.tsx +2 -1
- package/src/components/FormFieldInputLabel/index.tsx +1 -2
- package/src/components/FormFieldInputTags/index.tsx +4 -3
- package/src/components/FormSubmitButton/index.tsx +1 -1
- package/src/components/Header/index.tsx +3 -3
- package/src/components/Image/index.tsx +10 -4
- package/src/components/Items/index.tsx +5 -4
- package/src/components/Notifications/index.tsx +3 -2
- package/src/components/OrderSelect/index.tsx +4 -3
- package/src/components/PickedBar/index.tsx +2 -1
- package/src/components/Progress/index.tsx +3 -3
- package/src/components/ReduxProvider/index.tsx +15 -12
- package/src/components/SearchFacet/index.tsx +3 -2
- package/src/components/SearchFacetNumber/index.tsx +8 -8
- package/src/components/SearchFacetSelect/index.tsx +7 -8
- package/src/components/SearchFacetString/index.tsx +1 -1
- package/src/components/SearchFacetTags/index.tsx +13 -12
- package/src/components/SearchFacets/index.tsx +2 -3
- package/src/components/SearchFacetsControl/index.tsx +13 -12
- package/src/components/TableHeader/index.tsx +18 -17
- package/src/components/TableHeaderItem/index.tsx +4 -4
- package/src/components/TableRowAsset/index.tsx +37 -36
- package/src/components/TableRowUpload/index.tsx +7 -6
- package/src/components/Tag/index.tsx +8 -7
- package/src/components/TagView/index.tsx +2 -2
- package/src/components/TagViewHeader/index.tsx +5 -4
- package/src/components/TagsPanel/index.tsx +3 -3
- package/src/components/TagsVirtualized/index.tsx +25 -24
- package/src/components/TextInputSearch/index.tsx +3 -2
- package/src/components/UploadDropzone/UploadDropzone.test.tsx +8 -7
- package/src/components/UploadDropzone/index.tsx +14 -13
- package/src/config/orders.ts +6 -6
- package/src/config/searchFacets.ts +56 -55
- package/src/constants.ts +15 -14
- package/src/contexts/AssetSourceDispatchContext.tsx +1 -1
- package/src/contexts/ToolOptionsContext.tsx +6 -5
- package/src/formSchema/index.test.ts +6 -5
- package/src/formSchema/index.ts +5 -5
- package/src/hooks/useBreakpointIndex.ts +6 -6
- package/src/hooks/useKeyPress.ts +2 -2
- package/src/hooks/usePortalPopoverProps.ts +1 -1
- package/src/modules/assets/actions.ts +8 -7
- package/src/modules/assets/deleteAndUpdateEpics.test.ts +18 -17
- package/src/modules/assets/fetchEpic.test.ts +12 -11
- package/src/modules/assets/index.ts +134 -133
- package/src/modules/assets/reducer.test.ts +9 -8
- package/src/modules/assets/tagsAndListenerEpics.test.ts +36 -35
- package/src/modules/debug/index.ts +3 -3
- package/src/modules/dialog/actions.ts +2 -2
- package/src/modules/dialog/epics.test.ts +29 -28
- package/src/modules/dialog/index.ts +36 -35
- package/src/modules/dialog/reducer.test.ts +31 -30
- package/src/modules/index.ts +9 -9
- package/src/modules/notifications/epics.test.ts +71 -70
- package/src/modules/notifications/index.ts +50 -49
- package/src/modules/notifications/reducer.test.ts +8 -7
- package/src/modules/search/index.test.ts +2 -1
- package/src/modules/search/index.ts +22 -22
- package/src/modules/selected/index.ts +2 -2
- package/src/modules/selectors.test.ts +4 -3
- package/src/modules/selectors.ts +5 -5
- package/src/modules/tags/epics.test.ts +16 -15
- package/src/modules/tags/index.test.ts +2 -1
- package/src/modules/tags/index.ts +82 -81
- package/src/modules/uploads/actions.ts +3 -3
- package/src/modules/uploads/epics.test.ts +13 -12
- package/src/modules/uploads/index.test.ts +8 -7
- package/src/modules/uploads/index.ts +48 -47
- package/src/operators/checkTagName.test.ts +7 -6
- package/src/operators/checkTagName.ts +6 -5
- package/src/operators/debugThrottle.ts +4 -4
- package/src/plugin.tsx +18 -18
- package/src/schemas/tag.ts +7 -7
- package/src/styled/react-select/creatable.tsx +40 -39
- package/src/styled/react-select/single.tsx +39 -38
- package/src/types/index.ts +4 -3
- package/src/utils/applyMediaTags.ts +11 -10
- package/src/utils/blocksToText.test.ts +5 -4
- package/src/utils/blocksToText.ts +2 -2
- package/src/utils/constructFilter.test.ts +15 -14
- package/src/utils/constructFilter.ts +7 -7
- package/src/utils/generatePreviewBlobUrl.test.ts +6 -5
- package/src/utils/generatePreviewBlobUrl.ts +2 -2
- package/src/utils/getAssetResolution.test.ts +3 -2
- package/src/utils/getDocumentAssetIds.test.ts +7 -6
- package/src/utils/getDocumentAssetIds.ts +2 -2
- package/src/utils/getSchemeColor.test.ts +1 -0
- package/src/utils/getSchemeColor.ts +9 -9
- package/src/utils/getTagSelectOptions.test.ts +6 -5
- package/src/utils/getTagSelectOptions.ts +1 -1
- package/src/utils/getUniqueDocuments.test.ts +4 -3
- package/src/utils/getUniqueDocuments.ts +2 -2
- package/src/utils/imageDprUrl.test.ts +4 -3
- package/src/utils/imageDprUrl.ts +1 -1
- package/src/utils/isSupportedAssetType.test.ts +1 -0
- package/src/utils/mediaField.ts +4 -3
- package/src/utils/sanitizeFormData.test.ts +14 -13
- package/src/utils/typeGuards.test.ts +2 -1
- package/src/utils/uploadSanityAsset.test.ts +5 -4
- package/src/utils/uploadSanityAsset.ts +17 -16
- package/src/utils/withMaxConcurrency.test.ts +5 -4
- package/src/utils/withMaxConcurrency.ts +4 -4
- package/src/utils/zodFormResolver.ts +17 -0
- package/v2-incompatible.js +2 -2
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {createSelector, createSlice, isAnyOf, type PayloadAction} from '@reduxjs/toolkit'
|
|
2
2
|
import type {ClientError, Transaction} from '@sanity/client'
|
|
3
|
-
import type {Asset, HttpError, MyEpic, TagSelectOption, Tag, TagItem} from '../../types'
|
|
4
3
|
import groq from 'groq'
|
|
5
4
|
import type {Selector} from 'react-redux'
|
|
6
5
|
import {ofType} from 'redux-observable'
|
|
7
6
|
import {from, Observable, of} from 'rxjs'
|
|
8
7
|
import {bufferTime, catchError, filter, mergeMap, switchMap, withLatestFrom} from 'rxjs/operators'
|
|
8
|
+
|
|
9
9
|
import {TAG_DOCUMENT_NAME} from '../../constants'
|
|
10
10
|
import checkTagName from '../../operators/checkTagName'
|
|
11
11
|
import debugThrottle from '../../operators/debugThrottle'
|
|
12
|
+
import type {Asset, HttpError, MyEpic, TagSelectOption, Tag, TagItem} from '../../types'
|
|
12
13
|
import getTagSelectOptions from '../../utils/getTagSelectOptions'
|
|
13
14
|
import {ASSETS_ACTIONS} from '../assets/actions'
|
|
14
15
|
import {DIALOG_ACTIONS} from '../dialog/actions'
|
|
@@ -34,15 +35,15 @@ const initialState = {
|
|
|
34
35
|
fetchCount: -1,
|
|
35
36
|
fetching: false,
|
|
36
37
|
fetchingError: undefined,
|
|
37
|
-
panelVisible: true
|
|
38
|
+
panelVisible: true,
|
|
38
39
|
} as TagsReducerState
|
|
39
40
|
|
|
40
41
|
const tagsSlice = createSlice({
|
|
41
42
|
name: 'tags',
|
|
42
43
|
initialState,
|
|
43
|
-
extraReducers: builder => {
|
|
44
|
+
extraReducers: (builder) => {
|
|
44
45
|
builder
|
|
45
|
-
.addCase(DIALOG_ACTIONS.showTagCreate, state => {
|
|
46
|
+
.addCase(DIALOG_ACTIONS.showTagCreate, (state) => {
|
|
46
47
|
delete state.creatingError
|
|
47
48
|
})
|
|
48
49
|
.addCase(DIALOG_ACTIONS.showTagEdit, (state, action) => {
|
|
@@ -54,19 +55,19 @@ const tagsSlice = createSlice({
|
|
|
54
55
|
ASSETS_ACTIONS.tagsAddComplete,
|
|
55
56
|
ASSETS_ACTIONS.tagsAddError,
|
|
56
57
|
ASSETS_ACTIONS.tagsRemoveComplete,
|
|
57
|
-
ASSETS_ACTIONS.tagsRemoveError
|
|
58
|
+
ASSETS_ACTIONS.tagsRemoveError,
|
|
58
59
|
),
|
|
59
60
|
(state, action) => {
|
|
60
61
|
const {tag} = action.payload
|
|
61
62
|
state.byIds[tag._id].updating = false
|
|
62
|
-
}
|
|
63
|
+
},
|
|
63
64
|
)
|
|
64
65
|
.addMatcher(
|
|
65
66
|
isAnyOf(ASSETS_ACTIONS.tagsAddRequest, ASSETS_ACTIONS.tagsRemoveRequest),
|
|
66
67
|
(state, action) => {
|
|
67
68
|
const {tag} = action.payload
|
|
68
69
|
state.byIds[tag._id].updating = true
|
|
69
|
-
}
|
|
70
|
+
},
|
|
70
71
|
)
|
|
71
72
|
},
|
|
72
73
|
reducers: {
|
|
@@ -80,7 +81,7 @@ const tagsSlice = createSlice({
|
|
|
80
81
|
_type: 'tag',
|
|
81
82
|
picked: false,
|
|
82
83
|
tag,
|
|
83
|
-
updating: false
|
|
84
|
+
updating: false,
|
|
84
85
|
}
|
|
85
86
|
},
|
|
86
87
|
createError(state, action: PayloadAction<{error: HttpError; name: string}>) {
|
|
@@ -111,20 +112,20 @@ const tagsSlice = createSlice({
|
|
|
111
112
|
state.byIds[tagId].picked = false
|
|
112
113
|
state.byIds[tagId].updating = true
|
|
113
114
|
|
|
114
|
-
Object.keys(state.byIds).forEach(key => {
|
|
115
|
+
Object.keys(state.byIds).forEach((key) => {
|
|
115
116
|
delete state.byIds[key].error
|
|
116
117
|
})
|
|
117
118
|
},
|
|
118
119
|
fetchComplete(state, action: PayloadAction<{tags: Tag[]}>) {
|
|
119
120
|
const {tags} = action.payload
|
|
120
121
|
|
|
121
|
-
tags?.forEach(tag => {
|
|
122
|
+
tags?.forEach((tag) => {
|
|
122
123
|
state.allIds.push(tag._id)
|
|
123
124
|
state.byIds[tag._id] = {
|
|
124
125
|
_type: 'tag',
|
|
125
126
|
picked: false,
|
|
126
127
|
tag,
|
|
127
|
-
updating: false
|
|
128
|
+
updating: false,
|
|
128
129
|
}
|
|
129
130
|
})
|
|
130
131
|
|
|
@@ -160,7 +161,7 @@ const tagsSlice = createSlice({
|
|
|
160
161
|
}
|
|
161
162
|
`
|
|
162
163
|
return {payload: {query}}
|
|
163
|
-
}
|
|
164
|
+
},
|
|
164
165
|
},
|
|
165
166
|
// Queue batch tag creation
|
|
166
167
|
listenerCreateQueue(_state, _action: PayloadAction<{tag: Tag}>) {
|
|
@@ -170,12 +171,12 @@ const tagsSlice = createSlice({
|
|
|
170
171
|
listenerCreateQueueComplete(state, action: PayloadAction<{tags: Tag[]}>) {
|
|
171
172
|
const {tags} = action.payload
|
|
172
173
|
|
|
173
|
-
tags?.forEach(tag => {
|
|
174
|
+
tags?.forEach((tag) => {
|
|
174
175
|
state.byIds[tag._id] = {
|
|
175
176
|
_type: 'tag',
|
|
176
177
|
picked: false,
|
|
177
178
|
tag,
|
|
178
|
-
updating: false
|
|
179
|
+
updating: false,
|
|
179
180
|
}
|
|
180
181
|
if (!state.allIds.includes(tag._id)) {
|
|
181
182
|
state.allIds.push(tag._id)
|
|
@@ -190,7 +191,7 @@ const tagsSlice = createSlice({
|
|
|
190
191
|
listenerDeleteQueueComplete(state, action: PayloadAction<{tagIds: string[]}>) {
|
|
191
192
|
const {tagIds} = action.payload
|
|
192
193
|
|
|
193
|
-
tagIds?.forEach(tagId => {
|
|
194
|
+
tagIds?.forEach((tagId) => {
|
|
194
195
|
const deleteIndex = state.allIds.indexOf(tagId)
|
|
195
196
|
if (deleteIndex >= 0) {
|
|
196
197
|
state.allIds.splice(deleteIndex, 1)
|
|
@@ -206,7 +207,7 @@ const tagsSlice = createSlice({
|
|
|
206
207
|
listenerUpdateQueueComplete(state, action: PayloadAction<{tags: Tag[]}>) {
|
|
207
208
|
const {tags} = action.payload
|
|
208
209
|
|
|
209
|
-
tags?.forEach(tag => {
|
|
210
|
+
tags?.forEach((tag) => {
|
|
210
211
|
if (state.byIds[tag._id]) {
|
|
211
212
|
state.byIds[tag._id].tag = tag
|
|
212
213
|
}
|
|
@@ -248,12 +249,12 @@ const tagsSlice = createSlice({
|
|
|
248
249
|
closeDialogId?: string
|
|
249
250
|
formData: Record<string, any>
|
|
250
251
|
tag: Tag
|
|
251
|
-
}
|
|
252
|
+
}>,
|
|
252
253
|
) {
|
|
253
254
|
const {tag} = action.payload
|
|
254
255
|
state.byIds[tag?._id].updating = true
|
|
255
|
-
}
|
|
256
|
-
}
|
|
256
|
+
},
|
|
257
|
+
},
|
|
257
258
|
})
|
|
258
259
|
|
|
259
260
|
// Epics
|
|
@@ -277,24 +278,24 @@ export const tagsCreateEpic: MyEpic = (action$, state$, {client}) =>
|
|
|
277
278
|
_type: TAG_DOCUMENT_NAME,
|
|
278
279
|
name: {
|
|
279
280
|
_type: 'slug',
|
|
280
|
-
current: name
|
|
281
|
-
}
|
|
282
|
-
})
|
|
281
|
+
current: name,
|
|
282
|
+
},
|
|
283
|
+
}),
|
|
283
284
|
),
|
|
284
|
-
mergeMap(result => of(tagsSlice.actions.createComplete({assetId, tag: result as Tag}))),
|
|
285
|
+
mergeMap((result) => of(tagsSlice.actions.createComplete({assetId, tag: result as Tag}))),
|
|
285
286
|
catchError((error: ClientError) =>
|
|
286
287
|
of(
|
|
287
288
|
tagsSlice.actions.createError({
|
|
288
289
|
error: {
|
|
289
290
|
message: error?.message || 'Internal error',
|
|
290
|
-
statusCode: error?.statusCode || 500
|
|
291
|
+
statusCode: error?.statusCode || 500,
|
|
291
292
|
},
|
|
292
|
-
name
|
|
293
|
-
})
|
|
294
|
-
)
|
|
295
|
-
)
|
|
293
|
+
name,
|
|
294
|
+
}),
|
|
295
|
+
),
|
|
296
|
+
),
|
|
296
297
|
)
|
|
297
|
-
})
|
|
298
|
+
}),
|
|
298
299
|
)
|
|
299
300
|
|
|
300
301
|
// On tag delete request
|
|
@@ -320,23 +321,23 @@ export const tagsDeleteEpic: MyEpic = (action$, state$, {client}) =>
|
|
|
320
321
|
_rev,
|
|
321
322
|
opt
|
|
322
323
|
}`,
|
|
323
|
-
{tagName: tag.name.current}
|
|
324
|
-
)
|
|
324
|
+
{tagName: tag.name.current},
|
|
325
|
+
),
|
|
325
326
|
),
|
|
326
327
|
// Create transaction which remove tag references from all matched assets and delete tag
|
|
327
|
-
mergeMap(assets => {
|
|
328
|
-
const patches = assets.map(asset => ({
|
|
328
|
+
mergeMap((assets) => {
|
|
329
|
+
const patches = assets.map((asset) => ({
|
|
329
330
|
id: asset._id,
|
|
330
331
|
patch: {
|
|
331
332
|
// this will cause the transaction to fail if the document has been modified since it was fetched.
|
|
332
333
|
ifRevisionID: asset._rev,
|
|
333
|
-
unset: [`opt.media.tags[_ref == "${tag._id}"]`]
|
|
334
|
-
}
|
|
334
|
+
unset: [`opt.media.tags[_ref == "${tag._id}"]`],
|
|
335
|
+
},
|
|
335
336
|
}))
|
|
336
337
|
|
|
337
338
|
const transaction: Transaction = patches.reduce(
|
|
338
339
|
(tx, patch) => tx.patch(patch.id, patch.patch),
|
|
339
|
-
client.transaction()
|
|
340
|
+
client.transaction(),
|
|
340
341
|
)
|
|
341
342
|
|
|
342
343
|
transaction.delete(tag._id)
|
|
@@ -350,14 +351,14 @@ export const tagsDeleteEpic: MyEpic = (action$, state$, {client}) =>
|
|
|
350
351
|
tagsSlice.actions.deleteError({
|
|
351
352
|
error: {
|
|
352
353
|
message: error?.message || 'Internal error',
|
|
353
|
-
statusCode: error?.statusCode || 500
|
|
354
|
+
statusCode: error?.statusCode || 500,
|
|
354
355
|
},
|
|
355
|
-
tag
|
|
356
|
-
})
|
|
357
|
-
)
|
|
358
|
-
)
|
|
356
|
+
tag,
|
|
357
|
+
}),
|
|
358
|
+
),
|
|
359
|
+
),
|
|
359
360
|
)
|
|
360
|
-
})
|
|
361
|
+
}),
|
|
361
362
|
)
|
|
362
363
|
|
|
363
364
|
// Async fetch tags
|
|
@@ -375,10 +376,10 @@ export const tagsFetchEpic: MyEpic = (action$, state$, {client}) =>
|
|
|
375
376
|
mergeMap(() =>
|
|
376
377
|
client.observable.fetch<{
|
|
377
378
|
items: Tag[]
|
|
378
|
-
}>(query)
|
|
379
|
+
}>(query),
|
|
379
380
|
),
|
|
380
381
|
// Dispatch complete action
|
|
381
|
-
mergeMap(result => {
|
|
382
|
+
mergeMap((result) => {
|
|
382
383
|
const {items} = result
|
|
383
384
|
return of(tagsSlice.actions.fetchComplete({tags: items}))
|
|
384
385
|
}),
|
|
@@ -387,65 +388,65 @@ export const tagsFetchEpic: MyEpic = (action$, state$, {client}) =>
|
|
|
387
388
|
tagsSlice.actions.fetchError({
|
|
388
389
|
error: {
|
|
389
390
|
message: error?.message || 'Internal error',
|
|
390
|
-
statusCode: error?.statusCode || 500
|
|
391
|
-
}
|
|
392
|
-
})
|
|
393
|
-
)
|
|
394
|
-
)
|
|
391
|
+
statusCode: error?.statusCode || 500,
|
|
392
|
+
},
|
|
393
|
+
}),
|
|
394
|
+
),
|
|
395
|
+
),
|
|
395
396
|
)
|
|
396
|
-
})
|
|
397
|
+
}),
|
|
397
398
|
)
|
|
398
399
|
|
|
399
400
|
// TODO: merge all buffer epics
|
|
400
401
|
// Buffer tag creation via sanity subscriber
|
|
401
|
-
export const tagsListenerCreateQueueEpic: MyEpic = action$ =>
|
|
402
|
+
export const tagsListenerCreateQueueEpic: MyEpic = (action$) =>
|
|
402
403
|
action$.pipe(
|
|
403
404
|
filter(tagsSlice.actions.listenerCreateQueue.match),
|
|
404
405
|
bufferTime(2000),
|
|
405
|
-
filter(actions => actions.length > 0),
|
|
406
|
-
mergeMap(actions => {
|
|
407
|
-
const tags = actions?.map(action => action.payload.tag)
|
|
406
|
+
filter((actions) => actions.length > 0),
|
|
407
|
+
mergeMap((actions) => {
|
|
408
|
+
const tags = actions?.map((action) => action.payload.tag)
|
|
408
409
|
return of(tagsSlice.actions.listenerCreateQueueComplete({tags}))
|
|
409
|
-
})
|
|
410
|
+
}),
|
|
410
411
|
)
|
|
411
412
|
|
|
412
413
|
// TODO: merge all buffer epics
|
|
413
414
|
// Buffer tag deletion via sanity subscriber
|
|
414
|
-
export const tagsListenerDeleteQueueEpic: MyEpic = action$ =>
|
|
415
|
+
export const tagsListenerDeleteQueueEpic: MyEpic = (action$) =>
|
|
415
416
|
action$.pipe(
|
|
416
417
|
filter(tagsSlice.actions.listenerDeleteQueue.match),
|
|
417
418
|
bufferTime(2000),
|
|
418
|
-
filter(actions => actions.length > 0),
|
|
419
|
-
mergeMap(actions => {
|
|
420
|
-
const tagIds = actions?.map(action => action.payload.tagId)
|
|
419
|
+
filter((actions) => actions.length > 0),
|
|
420
|
+
mergeMap((actions) => {
|
|
421
|
+
const tagIds = actions?.map((action) => action.payload.tagId)
|
|
421
422
|
return of(tagsSlice.actions.listenerDeleteQueueComplete({tagIds}))
|
|
422
|
-
})
|
|
423
|
+
}),
|
|
423
424
|
)
|
|
424
425
|
|
|
425
426
|
// TODO: merge all buffer epics
|
|
426
427
|
// Buffer tag update via sanity subscriber
|
|
427
|
-
export const tagsListenerUpdateQueueEpic: MyEpic = action$ =>
|
|
428
|
+
export const tagsListenerUpdateQueueEpic: MyEpic = (action$) =>
|
|
428
429
|
action$.pipe(
|
|
429
430
|
filter(tagsSlice.actions.listenerUpdateQueue.match),
|
|
430
431
|
bufferTime(2000),
|
|
431
|
-
filter(actions => actions.length > 0),
|
|
432
|
-
mergeMap(actions => {
|
|
433
|
-
const tags = actions?.map(action => action.payload.tag)
|
|
432
|
+
filter((actions) => actions.length > 0),
|
|
433
|
+
mergeMap((actions) => {
|
|
434
|
+
const tags = actions?.map((action) => action.payload.tag)
|
|
434
435
|
return of(tagsSlice.actions.listenerUpdateQueueComplete({tags}))
|
|
435
|
-
})
|
|
436
|
+
}),
|
|
436
437
|
)
|
|
437
438
|
|
|
438
439
|
// On successful tag creation or updates:
|
|
439
440
|
// - Re-sort all tags
|
|
440
|
-
export const tagsSortEpic: MyEpic = action$ =>
|
|
441
|
+
export const tagsSortEpic: MyEpic = (action$) =>
|
|
441
442
|
action$.pipe(
|
|
442
443
|
ofType(
|
|
443
444
|
tagsSlice.actions.listenerCreateQueueComplete.type,
|
|
444
|
-
tagsSlice.actions.listenerUpdateQueueComplete.type
|
|
445
|
+
tagsSlice.actions.listenerUpdateQueueComplete.type,
|
|
445
446
|
),
|
|
446
447
|
bufferTime(1000),
|
|
447
|
-
filter(actions => actions.length > 0),
|
|
448
|
-
mergeMap(() => of(tagsSlice.actions.sort()))
|
|
448
|
+
filter((actions) => actions.length > 0),
|
|
449
|
+
mergeMap(() => of(tagsSlice.actions.sort())),
|
|
449
450
|
)
|
|
450
451
|
|
|
451
452
|
// On tag update request
|
|
@@ -471,16 +472,16 @@ export const tagsUpdateEpic: MyEpic = (action$, state$, {client}) =>
|
|
|
471
472
|
client
|
|
472
473
|
.patch(tag._id)
|
|
473
474
|
.set({name: {_type: 'slug', current: formData?.name.current}})
|
|
474
|
-
.commit()
|
|
475
|
-
) as Observable<Tag
|
|
475
|
+
.commit(),
|
|
476
|
+
) as Observable<Tag>,
|
|
476
477
|
),
|
|
477
478
|
// Dispatch complete action
|
|
478
479
|
mergeMap((updatedTag: Tag) => {
|
|
479
480
|
return of(
|
|
480
481
|
tagsSlice.actions.updateComplete({
|
|
481
482
|
closeDialogId,
|
|
482
|
-
tag: updatedTag
|
|
483
|
-
})
|
|
483
|
+
tag: updatedTag,
|
|
484
|
+
}),
|
|
484
485
|
)
|
|
485
486
|
}),
|
|
486
487
|
catchError((error: ClientError) =>
|
|
@@ -488,14 +489,14 @@ export const tagsUpdateEpic: MyEpic = (action$, state$, {client}) =>
|
|
|
488
489
|
tagsSlice.actions.updateError({
|
|
489
490
|
error: {
|
|
490
491
|
message: error?.message || 'Internal error',
|
|
491
|
-
statusCode: error?.statusCode || 500
|
|
492
|
+
statusCode: error?.statusCode || 500,
|
|
492
493
|
},
|
|
493
|
-
tag
|
|
494
|
-
})
|
|
495
|
-
)
|
|
496
|
-
)
|
|
494
|
+
tag,
|
|
495
|
+
}),
|
|
496
|
+
),
|
|
497
|
+
),
|
|
497
498
|
)
|
|
498
|
-
})
|
|
499
|
+
}),
|
|
499
500
|
)
|
|
500
501
|
|
|
501
502
|
// Selectors
|
|
@@ -506,12 +507,12 @@ const selectTagsAllIds = (state: RootReducerState) => state.tags.allIds
|
|
|
506
507
|
|
|
507
508
|
export const selectTags: Selector<RootReducerState, TagItem[]> = createSelector(
|
|
508
509
|
[selectTagsByIds, selectTagsAllIds],
|
|
509
|
-
(byIds, allIds) => allIds.map(id => byIds[id])
|
|
510
|
+
(byIds, allIds) => allIds.map((id) => byIds[id]),
|
|
510
511
|
)
|
|
511
512
|
|
|
512
513
|
export const selectTagById = createSelector(
|
|
513
514
|
[selectTagsByIds, (_state: RootReducerState, tagId: string) => tagId],
|
|
514
|
-
(byIds, tagId) => byIds[tagId]
|
|
515
|
+
(byIds, tagId) => byIds[tagId],
|
|
515
516
|
)
|
|
516
517
|
|
|
517
518
|
// TODO: use createSelector
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import type {SanityImageAssetDocument} from '@sanity/client'
|
|
4
4
|
import {of} from 'rxjs'
|
|
5
|
-
import {
|
|
5
|
+
import {describe, expect, it, vi, beforeEach, afterEach} from 'vitest'
|
|
6
|
+
|
|
6
7
|
import {createEpicTestStore} from '../../__tests__/fixtures/createEpicTestStore'
|
|
7
8
|
import {createMockSanityClient} from '../../__tests__/fixtures/mockSanityClient'
|
|
8
9
|
import {initialState as assetsInitialState} from '../assets'
|
|
9
|
-
import
|
|
10
|
+
import {uploadsAssetStartEpic, uploadsCheckRequestEpic, uploadsActions} from './index'
|
|
10
11
|
|
|
11
12
|
vi.mock('../../utils/generatePreviewBlobUrl', () => ({
|
|
12
|
-
generatePreviewBlobUrl$: () => of('blob:http://preview')
|
|
13
|
+
generatePreviewBlobUrl$: () => of('blob:http://preview'),
|
|
13
14
|
}))
|
|
14
15
|
|
|
15
16
|
const uploadedAsset = {
|
|
@@ -22,17 +23,17 @@ const uploadedAsset = {
|
|
|
22
23
|
originalFilename: 'f.png',
|
|
23
24
|
mimeType: 'image/png',
|
|
24
25
|
size: 10,
|
|
25
|
-
url: ''
|
|
26
|
+
url: '',
|
|
26
27
|
} as SanityImageAssetDocument
|
|
27
28
|
|
|
28
29
|
vi.mock('../../utils/uploadSanityAsset', () => ({
|
|
29
30
|
uploadAsset$: () =>
|
|
30
31
|
of({
|
|
31
32
|
type: 'complete' as const,
|
|
32
|
-
asset: uploadedAsset
|
|
33
|
+
asset: uploadedAsset,
|
|
33
34
|
}),
|
|
34
35
|
hashFile$: () => of('deadbeef'),
|
|
35
|
-
withMaxConcurrency: (fn: unknown) => fn
|
|
36
|
+
withMaxConcurrency: (fn: unknown) => fn,
|
|
36
37
|
}))
|
|
37
38
|
|
|
38
39
|
describe('uploadsAssetStartEpic', () => {
|
|
@@ -48,7 +49,7 @@ describe('uploadsAssetStartEpic', () => {
|
|
|
48
49
|
hash: 'deadbeef',
|
|
49
50
|
name: 'f.png',
|
|
50
51
|
size: file.size,
|
|
51
|
-
status: 'queued' as const
|
|
52
|
+
status: 'queued' as const,
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
store.dispatch(uploadsActions.uploadStart({file, uploadItem}))
|
|
@@ -75,12 +76,12 @@ describe('uploadsCheckRequestEpic', () => {
|
|
|
75
76
|
it('after delay, fetches sha hashes and dispatches checkComplete + insertUploads', async () => {
|
|
76
77
|
const client = createMockSanityClient({
|
|
77
78
|
observable: {
|
|
78
|
-
fetch: vi.fn(() => of(['hh']))
|
|
79
|
-
}
|
|
79
|
+
fetch: vi.fn(() => of(['hh'])),
|
|
80
|
+
},
|
|
80
81
|
})
|
|
81
82
|
|
|
82
83
|
const store = createEpicTestStore(uploadsCheckRequestEpic, client, {
|
|
83
|
-
assets: {...assetsInitialState, assetTypes: ['image']}
|
|
84
|
+
assets: {...assetsInitialState, assetTypes: ['image']},
|
|
84
85
|
})
|
|
85
86
|
|
|
86
87
|
const asset = {
|
|
@@ -93,7 +94,7 @@ describe('uploadsCheckRequestEpic', () => {
|
|
|
93
94
|
originalFilename: 'f.png',
|
|
94
95
|
mimeType: 'image/png',
|
|
95
96
|
size: 1,
|
|
96
|
-
url: ''
|
|
97
|
+
url: '',
|
|
97
98
|
} as SanityImageAssetDocument
|
|
98
99
|
|
|
99
100
|
store.dispatch(uploadsActions.checkRequest({assets: [asset]}))
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @vitest-environment node
|
|
2
2
|
|
|
3
3
|
import {describe, expect, it} from 'vitest'
|
|
4
|
+
|
|
4
5
|
import type {UploadItem} from '../../types'
|
|
5
6
|
import uploadsReducer, {uploadsActions} from './index'
|
|
6
7
|
|
|
@@ -13,15 +14,15 @@ describe('uploads slice', () => {
|
|
|
13
14
|
hash: 'abc',
|
|
14
15
|
name: 'x.png',
|
|
15
16
|
size: 1,
|
|
16
|
-
status: 'queued'
|
|
17
|
+
status: 'queued',
|
|
17
18
|
} as UploadItem
|
|
18
19
|
|
|
19
20
|
state = uploadsReducer(
|
|
20
21
|
state,
|
|
21
22
|
uploadsActions.uploadStart({
|
|
22
23
|
file: new File([], 'x.png'),
|
|
23
|
-
uploadItem
|
|
24
|
-
})
|
|
24
|
+
uploadItem,
|
|
25
|
+
}),
|
|
25
26
|
)
|
|
26
27
|
|
|
27
28
|
expect(state.allIds).toEqual(['abc'])
|
|
@@ -37,19 +38,19 @@ describe('uploads slice', () => {
|
|
|
37
38
|
name: 'x.png',
|
|
38
39
|
size: 1,
|
|
39
40
|
status: 'queued',
|
|
40
|
-
percent: 0
|
|
41
|
+
percent: 0,
|
|
41
42
|
} as UploadItem
|
|
42
43
|
|
|
43
44
|
state = uploadsReducer(
|
|
44
45
|
state,
|
|
45
|
-
uploadsActions.uploadStart({file: new File([], 'x.png'), uploadItem})
|
|
46
|
+
uploadsActions.uploadStart({file: new File([], 'x.png'), uploadItem}),
|
|
46
47
|
)
|
|
47
48
|
state = uploadsReducer(
|
|
48
49
|
state,
|
|
49
50
|
uploadsActions.uploadProgress({
|
|
50
51
|
uploadHash: 'h1',
|
|
51
|
-
event: {percent: 42, stage: 'upload'} as any
|
|
52
|
-
})
|
|
52
|
+
event: {percent: 42, stage: 'upload'} as any,
|
|
53
|
+
}),
|
|
53
54
|
)
|
|
54
55
|
|
|
55
56
|
expect(state.byIds.h1.percent).toBe(42)
|