UNPKG

sanity-plugin-media

Version:

This version of `sanity-plugin-media` is for Sanity Studio V3.

199 lines (179 loc) 5.64 kB
import {type PayloadAction, createSlice} from '@reduxjs/toolkit' import type {AnyAction} from 'redux' import type {HttpError, 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[] } function messageFromGenericErrorPayload(payload: unknown): string { if (!payload || typeof payload !== 'object') { return 'Unknown error' } if ( 'error' in payload && payload.error && typeof payload.error === 'object' && payload.error !== null && 'message' in payload.error ) { return String((payload.error as HttpError).message) } if ('message' in payload && typeof (payload as HttpError).message === 'string') { return String((payload as HttpError).message) } return 'Unknown error' } 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: AnyAction) => { const title = `An error occurred: ${messageFromGenericErrorPayload(action.payload)}` return of( notificationsSlice.actions.add({ status: 'error', title }) ) }) ) 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