UNPKG

sanity

Version:

Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches

191 lines (172 loc) • 5.77 kB
import {useCallback, useEffect, useMemo} from 'react' import useSWR from 'swr' import {useClient} from '../../hooks/useClient' import {useScheduledPublishingEnabled} from '../tool/contexts/ScheduledPublishingEnabledProvider' import {type Schedule, type ScheduleState} from '../types' import {sortByExecuteDate} from '../utils/sortByExecuteDate' import { type ScheduleDeleteEvent, type ScheduleDeleteMultipleEvent, ScheduleEvents, type SchedulePublishEvent, type ScheduleUpdateEvent, } from './useScheduleOperation' type QueryKey = { params?: { documentIds?: string state?: ScheduleState } url: string } function useScheduleBaseUrl() { const client = useClient({apiVersion: '2022-09-01'}) const {dataset, projectId} = client.config() return `/schedules/${projectId}/${dataset}` } function useFetcher(queryKey: QueryKey) { const client = useClient({apiVersion: '2022-09-01'}) return useCallback( () => client.request<{schedules: Schedule[] | undefined}>({ query: queryKey.params, method: 'GET', uri: queryKey.url, }), [client, queryKey], ) } const NO_SCHEDULES: Schedule[] = [] /** * Poll for all schedules */ function usePollSchedules({documentId, state}: {documentId?: string; state?: ScheduleState} = {}): { error: Error isInitialLoading: boolean schedules: Schedule[] } { const {mode, enabled} = useScheduledPublishingEnabled() const swrOptions = useMemo(() => { const SWR_OPTIONS = { refreshWhenHidden: false, refreshWhenOffline: false, revalidateOnFocus: false, shouldRetryOnError: false, // Revalidate data only on default mode, upsell mode should not poll given the data won't change. refreshInterval: mode === 'default' ? 10000 : undefined, // 10s revalidateIfStale: mode === 'default', revalidateOnReconnect: mode === 'default', } return SWR_OPTIONS }, [mode]) const url = useScheduleBaseUrl() const queryKey: QueryKey = useMemo( () => ({params: {documentIds: documentId, state}, url}), [url, documentId, state], ) const fetcher = useFetcher(queryKey) // Disables SWR if scheduled publishing is not enabled by not providing a key const {data, error, mutate} = useSWR(enabled ? queryKey : null, fetcher, swrOptions) // Immediately remove schedule from SWR cache and revalidate const handleDelete = useCallback( (event: CustomEvent<ScheduleDeleteEvent>) => { mutate( (currentData) => ({ schedules: currentData?.schedules?.filter( (schedule) => schedule.id !== event.detail.scheduleId, ), }), true, // revalidate SWR ) }, [mutate], ) // Immediately remove schedules from SWR cache and revalidate const handleDeleteMultiple = useCallback( (event: CustomEvent<ScheduleDeleteMultipleEvent>) => { mutate( (currentData) => ({ schedules: currentData?.schedules?.filter( (schedule) => !event.detail.scheduleIds.includes(schedule.id), ), }), true, // revalidate SWR ) }, [mutate], ) // Immediately publish schedule in SWR cache and revalidate const handlePublish = useCallback( (event: CustomEvent<SchedulePublishEvent>) => { mutate( (currentData) => { const currentSchedules = currentData?.schedules || [] const index = currentSchedules.findIndex( (schedule) => schedule.id === event.detail.scheduleId, ) return { schedules: [ ...currentSchedules.slice(0, index), { ...currentSchedules[index], executeAt: new Date().toISOString(), state: 'succeeded', }, ...currentSchedules.slice(index + 1), ], } }, true, // revalidate SWR ) }, [mutate], ) // Immediately update schedule in SWR cache and revalidate const handleUpdate = useCallback( (event: CustomEvent<ScheduleUpdateEvent>) => { mutate( (currentData) => { const currentSchedules = currentData?.schedules || [] const index = currentSchedules.findIndex( (schedule) => schedule.id === event.detail.scheduleId, ) return { schedules: [ ...currentSchedules.slice(0, index), { ...currentSchedules[index], executeAt: event.detail.date, }, ...currentSchedules.slice(index + 1), ], } }, true, // revalidate SWR ) }, [mutate], ) // Listen to schedule events useEffect(() => { window.addEventListener(ScheduleEvents.delete, handleDelete) window.addEventListener(ScheduleEvents.deleteMultiple, handleDeleteMultiple) window.addEventListener(ScheduleEvents.publish, handlePublish) window.addEventListener(ScheduleEvents.update, handleUpdate) return () => { window.removeEventListener(ScheduleEvents.delete, handleDelete) window.removeEventListener(ScheduleEvents.deleteMultiple, handleDeleteMultiple) window.removeEventListener(ScheduleEvents.publish, handlePublish) window.removeEventListener(ScheduleEvents.update, handleUpdate) } }, [handleDelete, handleDeleteMultiple, handlePublish, handleUpdate]) // By default: sort schedules by last execute date (executedAt || executeAt) const sortedSchedules = useMemo( () => data?.schedules?.sort(sortByExecuteDate()), [data?.schedules], ) return { error, isInitialLoading: !error && !data, schedules: sortedSchedules || NO_SCHEDULES, } } export default usePollSchedules