sanity-plugin-media
Version:
This version of `sanity-plugin-media` is for Sanity Studio V3.
179 lines (160 loc) • 5.08 kB
text/typescript
import {type PayloadAction, createSlice} from '@reduxjs/toolkit'
import type {ImageAsset, MyEpic} from '../../types'
import pluralize from 'pluralize'
import {ofType} from 'redux-observable'
import {of} from 'rxjs'
import {bufferTime, filter, mergeMap} from 'rxjs/operators'
import {assetsActions} from '../assets'
import {ASSETS_ACTIONS} from '../assets/actions'
import {tagsActions} from '../tags'
import {uploadsActions} from '../uploads'
type Notification = {
asset?: ImageAsset
status?: 'error' | 'warning' | 'success' | 'info'
title?: string
}
type NotificationsReducerState = {
items: Notification[]
}
const initialState = {
items: []
} as NotificationsReducerState
const notificationsSlice = createSlice({
name: 'notifications',
initialState,
reducers: {
add(state, action: PayloadAction<Notification>) {
const {asset, status, title} = action.payload
state.items.push({
asset,
status,
title
})
}
}
})
// Epics
export const notificationsAssetsDeleteCompleteEpic: MyEpic = action$ =>
action$.pipe(
filter(assetsActions.deleteComplete.match),
mergeMap(action => {
const {assetIds} = action.payload
const deletedCount = assetIds.length
return of(
notificationsSlice.actions.add({
status: 'info',
title: `${deletedCount} ${pluralize('asset', deletedCount)} deleted`
})
)
})
)
export const notificationsAssetsDeleteErrorEpic: MyEpic = action$ =>
action$.pipe(
filter(assetsActions.deleteError.match),
mergeMap(action => {
const {assetIds} = action.payload
const count = assetIds.length
return of(
notificationsSlice.actions.add({
status: 'error',
title: `Unable to delete ${count} ${pluralize(
'asset',
count
)}. Please review any asset errors and try again.`
})
)
})
)
export const notificationsAssetsUploadCompleteEpic: MyEpic = action$ =>
action$.pipe(
filter(uploadsActions.checkComplete.match),
mergeMap(action => {
const {results} = action.payload
const count = Object.keys(results).length
return of(
notificationsSlice.actions.add({
status: 'info',
title: `Uploaded ${count} ${pluralize('asset', count)}`
})
)
})
)
export const notificationsAssetsTagsAddCompleteEpic: MyEpic = action$ =>
action$.pipe(
filter(ASSETS_ACTIONS.tagsAddComplete.match),
mergeMap(action => {
const count = action?.payload?.assets?.length
return of(
notificationsSlice.actions.add({
status: 'info',
title: `Tag added to ${count} ${pluralize('asset', count)}`
})
)
})
)
export const notificationsAssetsTagsRemoveCompleteEpic: MyEpic = action$ =>
action$.pipe(
filter(ASSETS_ACTIONS.tagsRemoveComplete.match),
mergeMap(action => {
const count = action?.payload?.assets?.length
return of(
notificationsSlice.actions.add({
status: 'info',
title: `Tag removed from ${count} ${pluralize('asset', count)}`
})
)
})
)
export const notificationsAssetsUpdateCompleteEpic: MyEpic = action$ =>
action$.pipe(
filter(assetsActions.updateComplete.match),
bufferTime(2000),
filter(actions => actions.length > 0),
mergeMap(actions => {
const updatedCount = actions.length
return of(
notificationsSlice.actions.add({
status: 'info',
title: `${updatedCount} ${pluralize('asset', updatedCount)} updated`
})
)
})
)
export const notificationsGenericErrorEpic: MyEpic = action$ =>
action$.pipe(
ofType(
assetsActions.fetchError.type,
assetsActions.updateError.type,
tagsActions.createError.type,
tagsActions.deleteError.type,
tagsActions.fetchError.type,
tagsActions.updateError.type,
uploadsActions.uploadError.type
),
mergeMap((action: {payload: {error: {message: string}}}) => {
const error = action.payload?.error
return of(
notificationsSlice.actions.add({
status: 'error',
title: `An error occured: ${error.message}`
})
)
})
)
export const notificationsTagCreateCompleteEpic: MyEpic = action$ =>
action$.pipe(
filter(tagsActions.createComplete.match),
mergeMap(() => of(notificationsSlice.actions.add({status: 'info', title: `Tag created`})))
)
export const notificationsTagDeleteCompleteEpic: MyEpic = action$ =>
action$.pipe(
filter(tagsActions.deleteComplete.match),
mergeMap(() => of(notificationsSlice.actions.add({status: 'info', title: `Tag deleted`})))
)
export const notificationsTagUpdateCompleteEpic: MyEpic = action$ =>
action$.pipe(
filter(tagsActions.updateComplete.match),
mergeMap(() => of(notificationsSlice.actions.add({status: 'info', title: `Tag updated`})))
)
export const notificationsActions = {...notificationsSlice.actions}
export default notificationsSlice.reducer