mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-10 00:29:41 +00:00
refactor: rundown (#597)
* refactor: add revision number to rundown * chore: migrate query
This commit is contained in:
@@ -12,8 +12,8 @@
|
|||||||
"@react-icons/all-files": "^4.1.0",
|
"@react-icons/all-files": "^4.1.0",
|
||||||
"@sentry/react": "^7.46.0",
|
"@sentry/react": "^7.46.0",
|
||||||
"@sentry/tracing": "^7.46.0",
|
"@sentry/tracing": "^7.46.0",
|
||||||
"@tanstack/react-query": "^4.28.0",
|
"@tanstack/react-query": "^5.8.4",
|
||||||
"@tanstack/react-query-devtools": "^4.29.0",
|
"@tanstack/react-query-devtools": "^5.8.4",
|
||||||
"@tanstack/react-table": "^8.9.2",
|
"@tanstack/react-table": "^8.9.2",
|
||||||
"autosize": "^6.0.1",
|
"autosize": "^6.0.1",
|
||||||
"axios": "^1.2.0",
|
"axios": "^1.2.0",
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sentry/vite-plugin": "^0.4.0",
|
"@sentry/vite-plugin": "^0.4.0",
|
||||||
"@tanstack/eslint-plugin-query": "^4.26.2",
|
"@tanstack/eslint-plugin-query": "^5.8.4",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.1.1",
|
"@testing-library/react": "^13.1.1",
|
||||||
"@testing-library/user-event": "^14.1.1",
|
"@testing-library/user-event": "^14.1.1",
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
export const PROJECT_DATA = ['project'];
|
export const PROJECT_DATA = ['project'];
|
||||||
export const ALIASES = ['aliases'];
|
export const ALIASES = ['aliases'];
|
||||||
export const USERFIELDS = ['userFields'];
|
export const USERFIELDS = ['userFields'];
|
||||||
export const RUNDOWN_TABLE_KEY = 'rundown';
|
export const RUNDOWN = ['rundown'];
|
||||||
export const RUNDOWN_TABLE = [RUNDOWN_TABLE_KEY];
|
|
||||||
export const APP_INFO = ['appinfo'];
|
export const APP_INFO = ['appinfo'];
|
||||||
export const OSC_SETTINGS = ['oscSettings'];
|
export const OSC_SETTINGS = ['oscSettings'];
|
||||||
export const APP_SETTINGS = ['appSettings'];
|
export const APP_SETTINGS = ['appSettings'];
|
||||||
|
|||||||
@@ -42,12 +42,12 @@ export function logAxiosError(prepend: string, error: unknown) {
|
|||||||
* Utility function invalidates react-query caches
|
* Utility function invalidates react-query caches
|
||||||
*/
|
*/
|
||||||
export async function invalidateAllCaches() {
|
export async function invalidateAllCaches() {
|
||||||
await ontimeQueryClient.invalidateQueries(['project']);
|
await ontimeQueryClient.invalidateQueries({ queryKey: ['project'] });
|
||||||
await ontimeQueryClient.invalidateQueries(['aliases']);
|
await ontimeQueryClient.invalidateQueries({ queryKey: ['aliases'] });
|
||||||
await ontimeQueryClient.invalidateQueries(['userFields']);
|
await ontimeQueryClient.invalidateQueries({ queryKey: ['userFields'] });
|
||||||
await ontimeQueryClient.invalidateQueries(['rundown']);
|
await ontimeQueryClient.invalidateQueries({ queryKey: ['rundown'] });
|
||||||
await ontimeQueryClient.invalidateQueries(['appinfo']);
|
await ontimeQueryClient.invalidateQueries({ queryKey: ['appinfo'] });
|
||||||
await ontimeQueryClient.invalidateQueries(['oscSettings']);
|
await ontimeQueryClient.invalidateQueries({ queryKey: ['oscSettings'] });
|
||||||
await ontimeQueryClient.invalidateQueries(['appSettings']);
|
await ontimeQueryClient.invalidateQueries({ queryKey: ['appSettings'] });
|
||||||
await ontimeQueryClient.invalidateQueries(['viewSettings']);
|
await ontimeQueryClient.invalidateQueries({ queryKey: ['viewSettings'] });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { OntimeRundown, OntimeRundownEntry } from 'ontime-types';
|
import { GetRundownCached, OntimeRundown, OntimeRundownEntry } from 'ontime-types';
|
||||||
|
|
||||||
import { rundownURL } from './apiConstants';
|
import { rundownURL } from './apiConstants';
|
||||||
|
|
||||||
@@ -7,6 +7,16 @@ import { rundownURL } from './apiConstants';
|
|||||||
* @description HTTP request to fetch all events
|
* @description HTTP request to fetch all events
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
|
export async function fetchCachedRundown(): Promise<GetRundownCached> {
|
||||||
|
const res = await axios.get(`${rundownURL}/cached`);
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use fetchCachedRundown instead
|
||||||
|
* @description HTTP request to fetch all events
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
export async function fetchRundown(): Promise<OntimeRundown> {
|
export async function fetchRundown(): Promise<OntimeRundown> {
|
||||||
const res = await axios.get(rundownURL);
|
const res = await axios.get(rundownURL);
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => {
|
|||||||
const [operatorAuth, setOperatorAuth] = useState(true);
|
const [operatorAuth, setOperatorAuth] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status === 'loading') return;
|
if (status === 'pending') return;
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
const previousEditor = sessionStorage.getItem(storageKeys.editor);
|
const previousEditor = sessionStorage.getItem(storageKeys.editor);
|
||||||
|
|
||||||
|
|||||||
@@ -24,20 +24,20 @@ export default function useOscSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useOscSettingsMutation() {
|
export function useOscSettingsMutation() {
|
||||||
const { isLoading, mutateAsync } = useMutation({
|
const { isPending, mutateAsync } = useMutation({
|
||||||
mutationFn: postOSC,
|
mutationFn: postOSC,
|
||||||
onError: (error) => logAxiosError('Error saving OSC settings', error),
|
onError: (error) => logAxiosError('Error saving OSC settings', error),
|
||||||
onSuccess: (res) => ontimeQueryClient.setQueryData(OSC_SETTINGS, res.data),
|
onSuccess: (res) => ontimeQueryClient.setQueryData(OSC_SETTINGS, res.data),
|
||||||
onSettled: () => ontimeQueryClient.invalidateQueries({ queryKey: OSC_SETTINGS }),
|
onSettled: () => ontimeQueryClient.invalidateQueries({ queryKey: OSC_SETTINGS }),
|
||||||
});
|
});
|
||||||
return { isLoading, mutateAsync };
|
return { isPending, mutateAsync };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function usePostOscSubscriptions() {
|
export function usePostOscSubscriptions() {
|
||||||
const { isLoading, mutateAsync } = useMutation({
|
const { isPending, mutateAsync } = useMutation({
|
||||||
mutationFn: postOscSubscriptions,
|
mutationFn: postOscSubscriptions,
|
||||||
onError: (error) => logAxiosError('Error saving OSC settings', error),
|
onError: (error) => logAxiosError('Error saving OSC settings', error),
|
||||||
onSettled: () => ontimeQueryClient.invalidateQueries({ queryKey: OSC_SETTINGS }),
|
onSettled: () => ontimeQueryClient.invalidateQueries({ queryKey: OSC_SETTINGS }),
|
||||||
});
|
});
|
||||||
return { isLoading, mutateAsync };
|
return { isPending, mutateAsync };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,29 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { GetRundownCached } from 'ontime-types';
|
||||||
|
|
||||||
import { queryRefetchInterval } from '../../ontimeConfig';
|
import { queryRefetchInterval } from '../../ontimeConfig';
|
||||||
import { RUNDOWN_TABLE } from '../api/apiConstants';
|
import { RUNDOWN } from '../api/apiConstants';
|
||||||
import { fetchRundown } from '../api/eventsApi';
|
import { fetchCachedRundown } from '../api/eventsApi';
|
||||||
|
|
||||||
|
const cachedRundownPlaceholder = { rundown: [], revision: -1 };
|
||||||
|
|
||||||
|
// TODO: can we leverage structural sharing to see if data has changed?
|
||||||
export default function useRundown() {
|
export default function useRundown() {
|
||||||
const { data, status, isError, refetch } = useQuery({
|
return useQuery<GetRundownCached>({
|
||||||
queryKey: RUNDOWN_TABLE,
|
queryKey: RUNDOWN,
|
||||||
queryFn: fetchRundown,
|
queryFn: fetchCachedRundown,
|
||||||
placeholderData: [],
|
placeholderData: cachedRundownPlaceholder,
|
||||||
retry: 5,
|
retry: 5,
|
||||||
|
select: (data) => data.rundown,
|
||||||
retryDelay: (attempt) => attempt * 2500,
|
retryDelay: (attempt) => attempt * 2500,
|
||||||
refetchInterval: queryRefetchInterval,
|
refetchInterval: queryRefetchInterval,
|
||||||
networkMode: 'always',
|
networkMode: 'always',
|
||||||
|
// structuralSharing: (oldData: GetRundownCached | undefined, newData: GetRundownCached) => {
|
||||||
|
// if (oldData === undefined) {
|
||||||
|
// cachedRundownPlaceholder;
|
||||||
|
// }
|
||||||
|
// const hasDataChanged = oldData?.revision === newData.revision;
|
||||||
|
// return hasDataChanged ? oldData : newData;
|
||||||
|
// },
|
||||||
});
|
});
|
||||||
|
|
||||||
return { data, status, isError, refetch };
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { isOntimeEvent, OntimeRundown, OntimeRundownEntry } from 'ontime-types';
|
import { GetRundownCached, isOntimeEvent, OntimeRundownEntry } from 'ontime-types';
|
||||||
import { getCueCandidate, swapOntimeEvents } from 'ontime-utils';
|
import { getCueCandidate, swapOntimeEvents } from 'ontime-utils';
|
||||||
|
|
||||||
import { RUNDOWN_TABLE, RUNDOWN_TABLE_KEY } from '../api/apiConstants';
|
import { RUNDOWN } from '../api/apiConstants';
|
||||||
import { logAxiosError } from '../api/apiUtils';
|
import { logAxiosError } from '../api/apiUtils';
|
||||||
import {
|
import {
|
||||||
ReorderEntry,
|
ReorderEntry,
|
||||||
@@ -36,7 +36,7 @@ export const useEventAction = () => {
|
|||||||
// Fetch anyway, just to be sure
|
// Fetch anyway, just to be sure
|
||||||
mutationFn: requestPostEvent,
|
mutationFn: requestPostEvent,
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
queryClient.invalidateQueries({ queryKey: RUNDOWN });
|
||||||
},
|
},
|
||||||
networkMode: 'always',
|
networkMode: 'always',
|
||||||
});
|
});
|
||||||
@@ -67,8 +67,10 @@ export const useEventAction = () => {
|
|||||||
after: options?.after,
|
after: options?.after,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const rundown = queryClient.getQueryData<GetRundownCached>(RUNDOWN)?.rundown ?? [];
|
||||||
|
|
||||||
if (newEvent?.cue === undefined) {
|
if (newEvent?.cue === undefined) {
|
||||||
newEvent.cue = getCueCandidate(queryClient.getQueryData(RUNDOWN_TABLE) || [], options?.after);
|
newEvent.cue = getCueCandidate(rundown, options?.after);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hard coding duration value to be as expected for now
|
// hard coding duration value to be as expected for now
|
||||||
@@ -78,7 +80,6 @@ export const useEventAction = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (applicationOptions.startTimeIsLastEnd && applicationOptions?.lastEventId) {
|
if (applicationOptions.startTimeIsLastEnd && applicationOptions?.lastEventId) {
|
||||||
const rundown = queryClient.getQueryData(RUNDOWN_TABLE) as OntimeRundown;
|
|
||||||
const previousEvent = rundown.find((event) => event.id === applicationOptions.lastEventId);
|
const previousEvent = rundown.find((event) => event.id === applicationOptions.lastEventId);
|
||||||
if (previousEvent !== undefined && previousEvent.type === 'event') {
|
if (previousEvent !== undefined && previousEvent.type === 'event') {
|
||||||
newEvent.timeStart = previousEvent.timeEnd;
|
newEvent.timeStart = previousEvent.timeEnd;
|
||||||
@@ -115,25 +116,35 @@ export const useEventAction = () => {
|
|||||||
// we optimistically update here
|
// we optimistically update here
|
||||||
onMutate: async (newEvent) => {
|
onMutate: async (newEvent) => {
|
||||||
// cancel ongoing queries
|
// cancel ongoing queries
|
||||||
await queryClient.cancelQueries([RUNDOWN_TABLE_KEY, newEvent.id]);
|
await queryClient.cancelQueries({ queryKey: RUNDOWN });
|
||||||
|
|
||||||
// Snapshot the previous value
|
// Snapshot the previous value
|
||||||
const previousEvent = queryClient.getQueryData([RUNDOWN_TABLE_KEY, newEvent.id]);
|
|
||||||
|
|
||||||
// optimistically update object
|
const previousData = queryClient.getQueryData<GetRundownCached>(RUNDOWN);
|
||||||
queryClient.setQueryData([RUNDOWN_TABLE_KEY, newEvent.id], newEvent);
|
|
||||||
|
if (previousData) {
|
||||||
|
// optimistically update object
|
||||||
|
const optimisticRundown = [...previousData.rundown];
|
||||||
|
const index = optimisticRundown.findIndex((event) => event.id === newEvent.id);
|
||||||
|
if (index > -1) {
|
||||||
|
// @ts-expect-error -- we expect the event types to match
|
||||||
|
optimisticRundown[index] = { ...optimisticRundown[index], ...newEvent };
|
||||||
|
|
||||||
|
queryClient.setQueryData(RUNDOWN, { rundown: optimisticRundown, revision: -1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return a context with the previous and new events
|
// Return a context with the previous and new events
|
||||||
return { previousEvent, newEvent };
|
return { previousData, newEvent };
|
||||||
},
|
},
|
||||||
// Mutation fails, rollback undoes optimist update
|
// Mutation fails, rollback undoes optimist update
|
||||||
onError: (_error, _newEvent, context) => {
|
onError: (_error, _newEvent, context) => {
|
||||||
queryClient.setQueryData([RUNDOWN_TABLE_KEY, context?.newEvent.id], context?.previousEvent);
|
queryClient.setQueryData(RUNDOWN, context?.previousData);
|
||||||
},
|
},
|
||||||
// Mutation finished, failed or successful
|
// Mutation finished, failed or successful
|
||||||
// Fetch anyway, just to be sure
|
// Fetch anyway, just to be sure
|
||||||
onSettled: async () => {
|
onSettled: async () => {
|
||||||
await queryClient.invalidateQueries([RUNDOWN_TABLE_KEY]);
|
await queryClient.invalidateQueries({ queryKey: RUNDOWN });
|
||||||
},
|
},
|
||||||
networkMode: 'always',
|
networkMode: 'always',
|
||||||
});
|
});
|
||||||
@@ -161,28 +172,37 @@ export const useEventAction = () => {
|
|||||||
// we optimistically update here
|
// we optimistically update here
|
||||||
onMutate: async (eventId) => {
|
onMutate: async (eventId) => {
|
||||||
// cancel ongoing queries
|
// cancel ongoing queries
|
||||||
await queryClient.cancelQueries([RUNDOWN_TABLE_KEY, eventId]);
|
await queryClient.cancelQueries({ queryKey: RUNDOWN });
|
||||||
|
|
||||||
// Snapshot the previous value
|
// Snapshot the previous value
|
||||||
const previousEvents = queryClient.getQueryData(RUNDOWN_TABLE);
|
const previousData = queryClient.getQueryData<GetRundownCached>(RUNDOWN);
|
||||||
|
|
||||||
const filtered = [...(previousEvents as OntimeRundown)].filter((e) => e.id !== eventId);
|
if (previousData) {
|
||||||
|
// optimistically update object
|
||||||
|
const optimisticRundown = [...previousData.rundown];
|
||||||
|
const index = optimisticRundown.findIndex((event) => event.id === eventId);
|
||||||
|
if (index > -1) {
|
||||||
|
optimisticRundown.splice(index, 1);
|
||||||
|
|
||||||
// optimistically update object
|
queryClient.setQueryData(RUNDOWN, {
|
||||||
queryClient.setQueryData(RUNDOWN_TABLE, filtered);
|
rundown: optimisticRundown,
|
||||||
|
revision: -1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return a context with the previous and new events
|
// Return a context with the previous and new events
|
||||||
return { previousEvents };
|
return { previousData };
|
||||||
},
|
},
|
||||||
|
|
||||||
// Mutation fails, rollback undoes optimist update
|
// Mutation fails, rollback undoes optimist update
|
||||||
onError: (_error, _eventId, context) => {
|
onError: (_error, _eventId, context) => {
|
||||||
queryClient.setQueryData(RUNDOWN_TABLE, context?.previousEvents);
|
queryClient.setQueryData(RUNDOWN, context?.previousData);
|
||||||
},
|
},
|
||||||
// Mutation finished, failed or successful
|
// Mutation finished, failed or successful
|
||||||
// Fetch anyway, just to be sure
|
// Fetch anyway, just to be sure
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
queryClient.invalidateQueries({ queryKey: RUNDOWN });
|
||||||
},
|
},
|
||||||
networkMode: 'always',
|
networkMode: 'always',
|
||||||
});
|
});
|
||||||
@@ -210,26 +230,26 @@ export const useEventAction = () => {
|
|||||||
// we optimistically update here
|
// we optimistically update here
|
||||||
onMutate: async () => {
|
onMutate: async () => {
|
||||||
// cancel ongoing queries
|
// cancel ongoing queries
|
||||||
await queryClient.cancelQueries(RUNDOWN_TABLE, { exact: true });
|
await queryClient.cancelQueries({ queryKey: RUNDOWN });
|
||||||
|
|
||||||
// Snapshot the previous value
|
// Snapshot the previous value
|
||||||
const previousEvents = queryClient.getQueryData(RUNDOWN_TABLE);
|
const previousData = queryClient.getQueryData<GetRundownCached>(RUNDOWN);
|
||||||
|
|
||||||
// optimistically update object
|
// optimistically update object
|
||||||
queryClient.setQueryData(RUNDOWN_TABLE, []);
|
queryClient.setQueryData(RUNDOWN, { rundown: [], revision: -1 });
|
||||||
|
|
||||||
// Return a context with the previous and new events
|
// Return a context with the previous and new events
|
||||||
return { previousEvents };
|
return { previousData };
|
||||||
},
|
},
|
||||||
|
|
||||||
// Mutation fails, rollback undos optimist update
|
// Mutation fails, rollback undos optimist update
|
||||||
onError: (_error, _eventId, context) => {
|
onError: (_error, _eventId, context) => {
|
||||||
queryClient.setQueryData(RUNDOWN_TABLE, context?.previousEvents);
|
queryClient.setQueryData(RUNDOWN, context?.previousData);
|
||||||
},
|
},
|
||||||
// Mutation finished, failed or successful
|
// Mutation finished, failed or successful
|
||||||
// Fetch anyway, just to be sure
|
// Fetch anyway, just to be sure
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
queryClient.invalidateQueries({ queryKey: RUNDOWN });
|
||||||
},
|
},
|
||||||
networkMode: 'always',
|
networkMode: 'always',
|
||||||
});
|
});
|
||||||
@@ -253,7 +273,7 @@ export const useEventAction = () => {
|
|||||||
mutationFn: requestApplyDelay,
|
mutationFn: requestApplyDelay,
|
||||||
// Mutation finished, failed or successful
|
// Mutation finished, failed or successful
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
queryClient.invalidateQueries({ queryKey: RUNDOWN });
|
||||||
},
|
},
|
||||||
networkMode: 'always',
|
networkMode: 'always',
|
||||||
});
|
});
|
||||||
@@ -281,30 +301,32 @@ export const useEventAction = () => {
|
|||||||
// we optimistically update here
|
// we optimistically update here
|
||||||
onMutate: async (data) => {
|
onMutate: async (data) => {
|
||||||
// cancel ongoing queries
|
// cancel ongoing queries
|
||||||
await queryClient.cancelQueries(RUNDOWN_TABLE, { exact: true });
|
await queryClient.cancelQueries({ queryKey: RUNDOWN });
|
||||||
|
|
||||||
// Snapshot the previous value
|
// Snapshot the previous value
|
||||||
const previousEvents = queryClient.getQueryData(RUNDOWN_TABLE);
|
const previousData = queryClient.getQueryData<GetRundownCached>(RUNDOWN);
|
||||||
|
|
||||||
const e = [...(previousEvents as OntimeRundown)];
|
if (previousData) {
|
||||||
const [reorderedItem] = e.splice(data.from, 1);
|
// optimistically update object
|
||||||
e.splice(data.to, 0, reorderedItem);
|
const optimisticRundown = [...previousData.rundown];
|
||||||
|
const [reorderedItem] = optimisticRundown.splice(data.from, 1);
|
||||||
|
optimisticRundown.splice(data.to, 0, reorderedItem);
|
||||||
|
|
||||||
// optimistically update object
|
queryClient.setQueryData(RUNDOWN, { rundown: optimisticRundown, revision: -1 });
|
||||||
queryClient.setQueryData(RUNDOWN_TABLE, e);
|
}
|
||||||
|
|
||||||
// Return a context with the previous and new events
|
// Return a context with the previous and new events
|
||||||
return { previousEvents };
|
return { previousData };
|
||||||
},
|
},
|
||||||
|
|
||||||
// Mutation fails, rollback undoes optimist update
|
// Mutation fails, rollback undoes optimist update
|
||||||
onError: (_error, _eventId, context) => {
|
onError: (_error, _eventId, context) => {
|
||||||
queryClient.setQueryData(RUNDOWN_TABLE, context?.previousEvents);
|
queryClient.setQueryData(RUNDOWN, context?.previousData);
|
||||||
},
|
},
|
||||||
// Mutation finished, failed or successful
|
// Mutation finished, failed or successful
|
||||||
// Fetch anyway, just to be sure
|
// Fetch anyway, just to be sure
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
queryClient.invalidateQueries({ queryKey: RUNDOWN });
|
||||||
},
|
},
|
||||||
networkMode: 'always',
|
networkMode: 'always',
|
||||||
});
|
});
|
||||||
@@ -337,31 +359,32 @@ export const useEventAction = () => {
|
|||||||
// we optimistically update here
|
// we optimistically update here
|
||||||
onMutate: async ({ from, to }) => {
|
onMutate: async ({ from, to }) => {
|
||||||
// cancel ongoing queries
|
// cancel ongoing queries
|
||||||
await queryClient.cancelQueries(RUNDOWN_TABLE, { exact: true });
|
await queryClient.cancelQueries({ queryKey: RUNDOWN });
|
||||||
|
|
||||||
// Snapshot the previous value
|
// Snapshot the previous value
|
||||||
const rundown = queryClient.getQueryData(RUNDOWN_TABLE) as OntimeRundown;
|
const previousData = queryClient.getQueryData<GetRundownCached>(RUNDOWN);
|
||||||
|
if (previousData) {
|
||||||
|
// optimistically update object
|
||||||
|
const fromEventIndex = previousData.rundown.findIndex((event) => event.id === from);
|
||||||
|
const toEventIndex = previousData.rundown.findIndex((event) => event.id === to);
|
||||||
|
|
||||||
const fromEventIndex = rundown.findIndex((event) => event.id === from);
|
const optimisticRundown = swapOntimeEvents(previousData.rundown, fromEventIndex, toEventIndex);
|
||||||
const toEventIndex = rundown.findIndex((event) => event.id === to);
|
|
||||||
|
|
||||||
const previousEvents = swapOntimeEvents(rundown, fromEventIndex, toEventIndex);
|
queryClient.setQueryData(RUNDOWN, { rundown: optimisticRundown, revision: -1 });
|
||||||
|
}
|
||||||
// optimistically update object
|
|
||||||
queryClient.setQueryData(RUNDOWN_TABLE, previousEvents);
|
|
||||||
|
|
||||||
// Return a context with the previous events
|
// Return a context with the previous events
|
||||||
return { previousEvents };
|
return { previousData };
|
||||||
},
|
},
|
||||||
|
|
||||||
// Mutation fails, rollback undoes optimist update
|
// Mutation fails, rollback undoes optimist update
|
||||||
onError: (_error, _eventId, context) => {
|
onError: (_error, _eventId, context) => {
|
||||||
queryClient.setQueryData(RUNDOWN_TABLE, context?.previousEvents);
|
queryClient.setQueryData(RUNDOWN, context?.previousData);
|
||||||
},
|
},
|
||||||
// Mutation finished, failed or successful
|
// Mutation finished, failed or successful
|
||||||
// Fetch anyway, just to be sure
|
// Fetch anyway, just to be sure
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
queryClient.invalidateQueries(RUNDOWN_TABLE);
|
queryClient.invalidateQueries({ queryKey: RUNDOWN });
|
||||||
},
|
},
|
||||||
networkMode: 'always',
|
networkMode: 'always',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { QueryClient } from '@tanstack/react-query';
|
|||||||
export const ontimeQueryClient = new QueryClient({
|
export const ontimeQueryClient = new QueryClient({
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
cacheTime: 1000 * 60 * 10, // 10 min
|
gcTime: 1000 * 60 * 10, // 10 min
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import type { ProjectData } from 'ontime-types';
|
import type { ProjectData } from 'ontime-types';
|
||||||
|
|
||||||
import { PROJECT_DATA, RUNDOWN_TABLE } from '../../../common/api/apiConstants';
|
import { PROJECT_DATA, RUNDOWN } from '../../../common/api/apiConstants';
|
||||||
import { postNew } from '../../../common/api/ontimeApi';
|
import { postNew } from '../../../common/api/ontimeApi';
|
||||||
import useProjectData from '../../../common/hooks-query/useProjectData';
|
import useProjectData from '../../../common/hooks-query/useProjectData';
|
||||||
import { projectDataPlaceholder } from '../../../common/models/ProjectData';
|
import { projectDataPlaceholder } from '../../../common/models/ProjectData';
|
||||||
@@ -52,8 +52,8 @@ export default function QuickStart({ onClose, isOpen }: QuickStartProps) {
|
|||||||
const onSubmit = async (data: Partial<ProjectData>) => {
|
const onSubmit = async (data: Partial<ProjectData>) => {
|
||||||
try {
|
try {
|
||||||
await postNew(data);
|
await postNew(data);
|
||||||
await ontimeQueryClient.invalidateQueries(PROJECT_DATA);
|
await ontimeQueryClient.invalidateQueries({ queryKey: PROJECT_DATA });
|
||||||
await ontimeQueryClient.invalidateQueries(RUNDOWN_TABLE);
|
await ontimeQueryClient.invalidateQueries({ queryKey: RUNDOWN });
|
||||||
|
|
||||||
onClose();
|
onClose();
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export default function AliasesForm() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const disableInputs = status === 'loading';
|
const disableInputs = status === 'pending';
|
||||||
const hasTooManyOptions = fields.length >= 20;
|
const hasTooManyOptions = fields.length >= 20;
|
||||||
|
|
||||||
if (isFetching) {
|
if (isFetching) {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export default function CuesheetSettingsForm() {
|
|||||||
reset(data);
|
reset(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const disableInputs = status === 'loading';
|
const disableInputs = status === 'pending';
|
||||||
|
|
||||||
if (isFetching) {
|
if (isFetching) {
|
||||||
return <ModalLoader />;
|
return <ModalLoader />;
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export default function ViewSettingsForm() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const disableInputs = status === 'loading';
|
const disableInputs = status === 'pending';
|
||||||
|
|
||||||
if (isFetching || isFetchingInfo) {
|
if (isFetching || isFetchingInfo) {
|
||||||
return <ModalLoader />;
|
return <ModalLoader />;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { useQueryClient } from '@tanstack/react-query';
|
|||||||
import { OntimeRundown, ProjectData, UserFields } from 'ontime-types';
|
import { OntimeRundown, ProjectData, UserFields } from 'ontime-types';
|
||||||
import { defaultExcelImportMap, ExcelImportMap } from 'ontime-utils';
|
import { defaultExcelImportMap, ExcelImportMap } from 'ontime-utils';
|
||||||
|
|
||||||
import { PROJECT_DATA, RUNDOWN_TABLE, USERFIELDS } from '../../../common/api/apiConstants';
|
import { PROJECT_DATA, RUNDOWN, USERFIELDS } from '../../../common/api/apiConstants';
|
||||||
import { invalidateAllCaches, maybeAxiosError } from '../../../common/api/apiUtils';
|
import { invalidateAllCaches, maybeAxiosError } from '../../../common/api/apiUtils';
|
||||||
import {
|
import {
|
||||||
patchData,
|
patchData,
|
||||||
@@ -155,11 +155,11 @@ export default function UploadModal({ onClose, isOpen }: UploadModalProps) {
|
|||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
try {
|
try {
|
||||||
await patchData({ rundown, userFields, project });
|
await patchData({ rundown, userFields, project });
|
||||||
queryClient.setQueryData(RUNDOWN_TABLE, rundown);
|
queryClient.setQueryData(RUNDOWN, { rundown, revision: -1 });
|
||||||
queryClient.setQueryData(USERFIELDS, userFields);
|
queryClient.setQueryData(USERFIELDS, userFields);
|
||||||
queryClient.setQueryData(PROJECT_DATA, project);
|
queryClient.setQueryData(PROJECT_DATA, project);
|
||||||
await queryClient.invalidateQueries({
|
await queryClient.invalidateQueries({
|
||||||
queryKey: [...RUNDOWN_TABLE, ...USERFIELDS, ...PROJECT_DATA],
|
queryKey: [...RUNDOWN, ...USERFIELDS, ...PROJECT_DATA],
|
||||||
});
|
});
|
||||||
doClose = true;
|
doClose = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export default function Operator() {
|
|||||||
const debouncedHandleScroll = debounce(handleUserScroll, 1000);
|
const debouncedHandleScroll = debounce(handleUserScroll, 1000);
|
||||||
|
|
||||||
const missingData = !data || !userFields || !projectData;
|
const missingData = !data || !userFields || !projectData;
|
||||||
const isLoading = status === 'loading' || userFieldsStatus === 'loading' || projectDataStatus === 'loading';
|
const isLoading = status === 'pending' || userFieldsStatus === 'pending' || projectDataStatus === 'pending';
|
||||||
|
|
||||||
if (missingData || isLoading) {
|
if (missingData || isLoading) {
|
||||||
return <Empty text='Loading...' />;
|
return <Empty text='Loading...' />;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { OntimeEvent, OntimeRundownEntry, Playback, SupportedEvent } from 'ontime-types';
|
import { GetRundownCached, OntimeEvent, OntimeRundownEntry, Playback, SupportedEvent } from 'ontime-types';
|
||||||
import { calculateDuration, getCueCandidate } from 'ontime-utils';
|
import { calculateDuration, getCueCandidate } from 'ontime-utils';
|
||||||
|
|
||||||
import { RUNDOWN_TABLE } from '../../common/api/apiConstants';
|
import { RUNDOWN } from '../../common/api/apiConstants';
|
||||||
import { useEventAction } from '../../common/hooks/useEventAction';
|
import { useEventAction } from '../../common/hooks/useEventAction';
|
||||||
import { ontimeQueryClient } from '../../common/queryClient';
|
import { ontimeQueryClient } from '../../common/queryClient';
|
||||||
import { useAppMode } from '../../common/stores/appModeStore';
|
import { useAppMode } from '../../common/stores/appModeStore';
|
||||||
@@ -100,7 +100,8 @@ export default function RundownEntry(props: RundownEntryProps) {
|
|||||||
}
|
}
|
||||||
case 'clone': {
|
case 'clone': {
|
||||||
const newEvent = cloneEvent(data as OntimeEvent, data.id);
|
const newEvent = cloneEvent(data as OntimeEvent, data.id);
|
||||||
newEvent.cue = getCueCandidate(ontimeQueryClient.getQueryData(RUNDOWN_TABLE) || [], data.id);
|
const rundown = ontimeQueryClient.getQueryData<GetRundownCached>(RUNDOWN)?.rundown ?? []
|
||||||
|
newEvent.cue = getCueCandidate(rundown, data.id);
|
||||||
addEvent(newEvent);
|
addEvent(newEvent);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
import { GetRundownCached } from 'ontime-types';
|
||||||
|
|
||||||
|
import { Request, Response, RequestHandler } from 'express';
|
||||||
|
|
||||||
import { failEmptyObjects } from '../utils/routerUtils.js';
|
import { failEmptyObjects } from '../utils/routerUtils.js';
|
||||||
import {
|
import {
|
||||||
addEvent,
|
addEvent,
|
||||||
@@ -8,8 +12,7 @@ import {
|
|||||||
reorderEvent,
|
reorderEvent,
|
||||||
swapEvents,
|
swapEvents,
|
||||||
} from '../services/rundown-service/RundownService.js';
|
} from '../services/rundown-service/RundownService.js';
|
||||||
import { getDelayedRundown } from '../services/rundown-service/delayedRundown.utils.js';
|
import { getDelayedRundown, getRundownCache } from '../services/rundown-service/delayedRundown.utils.js';
|
||||||
import { RequestHandler } from 'express';
|
|
||||||
|
|
||||||
// Create controller for GET request to '/events'
|
// Create controller for GET request to '/events'
|
||||||
// Returns -
|
// Returns -
|
||||||
@@ -18,6 +21,13 @@ export const rundownGetAll: RequestHandler = async (_req, res) => {
|
|||||||
res.json(delayedRundown);
|
res.json(delayedRundown);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Create controller for GET request to '/events/cached'
|
||||||
|
// Returns -
|
||||||
|
export const rundownGetCached: RequestHandler = async (_req: Request, res: Response<GetRundownCached>) => {
|
||||||
|
const cachedRundown = getRundownCache();
|
||||||
|
res.json(cachedRundown);
|
||||||
|
};
|
||||||
|
|
||||||
// Create controller for POST request to '/events/'
|
// Create controller for POST request to '/events/'
|
||||||
// Returns -
|
// Returns -
|
||||||
export const rundownPost: RequestHandler = async (req, res) => {
|
export const rundownPost: RequestHandler = async (req, res) => {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
rundownApplyDelay,
|
rundownApplyDelay,
|
||||||
rundownDelete,
|
rundownDelete,
|
||||||
rundownGetAll,
|
rundownGetAll,
|
||||||
|
rundownGetCached,
|
||||||
rundownPost,
|
rundownPost,
|
||||||
rundownPut,
|
rundownPut,
|
||||||
rundownReorder,
|
rundownReorder,
|
||||||
@@ -19,6 +20,9 @@ import {
|
|||||||
|
|
||||||
export const router = express.Router();
|
export const router = express.Router();
|
||||||
|
|
||||||
|
// create route between controller and '/events/cached' endpoint
|
||||||
|
router.get('/cached', rundownGetCached);
|
||||||
|
|
||||||
// create route between controller and '/events/' endpoint
|
// create route between controller and '/events/' endpoint
|
||||||
router.get('/', rundownGetAll);
|
router.get('/', rundownGetAll);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
GetRundownCached,
|
||||||
isOntimeBlock,
|
isOntimeBlock,
|
||||||
isOntimeDelay,
|
isOntimeDelay,
|
||||||
isOntimeEvent,
|
isOntimeEvent,
|
||||||
@@ -16,6 +17,11 @@ import { isProduction } from '../../setup.js';
|
|||||||
import { deleteAtIndex, insertAtIndex, reorderArray } from '../../utils/arrayUtils.js';
|
import { deleteAtIndex, insertAtIndex, reorderArray } from '../../utils/arrayUtils.js';
|
||||||
import { _applyDelay } from '../delayUtils.js';
|
import { _applyDelay } from '../delayUtils.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep incremental revision number of rundown for runtime
|
||||||
|
*/
|
||||||
|
let rundownRevision = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key of rundown in cache
|
* Key of rundown in cache
|
||||||
*/
|
*/
|
||||||
@@ -38,7 +44,25 @@ export function invalidateFromError(errorMessage = 'Found mismatch between store
|
|||||||
* Returns rundown with calculated delays
|
* Returns rundown with calculated delays
|
||||||
* Ensures request goes through the caching layer
|
* Ensures request goes through the caching layer
|
||||||
*/
|
*/
|
||||||
export function getDelayedRundown(): OntimeRundown {
|
export function getRundownCache(): GetRundownCached {
|
||||||
|
function calculateRundown() {
|
||||||
|
const rundown = DataProvider.getRundown();
|
||||||
|
return calculateRuntimeDelays(rundown);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cached = getCached(delayedRundownCacheKey, calculateRundown);
|
||||||
|
|
||||||
|
return {
|
||||||
|
rundown: cached,
|
||||||
|
revision: rundownRevision,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns rundown with calculated delays
|
||||||
|
* Ensures request goes through the caching layer
|
||||||
|
*/
|
||||||
|
export function getDelayedRundown() {
|
||||||
function calculateRundown() {
|
function calculateRundown() {
|
||||||
const rundown = DataProvider.getRundown();
|
const rundown = DataProvider.getRundown();
|
||||||
return calculateRuntimeDelays(rundown);
|
return calculateRuntimeDelays(rundown);
|
||||||
@@ -72,6 +96,8 @@ export async function cachedAdd(eventIndex: number, event: OntimeEvent | OntimeD
|
|||||||
runtimeCacheStore.setCached(delayedRundownCacheKey, newDelayedRundown);
|
runtimeCacheStore.setCached(delayedRundownCacheKey, newDelayedRundown);
|
||||||
// we need to delay updating this to ensure add operation happens on same dataset
|
// we need to delay updating this to ensure add operation happens on same dataset
|
||||||
await DataProvider.setRundown(newRundown);
|
await DataProvider.setRundown(newRundown);
|
||||||
|
|
||||||
|
rundownRevision++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,6 +139,8 @@ export async function cachedEdit(
|
|||||||
// we need to delay updating this to ensure edit operation happens on same dataset
|
// we need to delay updating this to ensure edit operation happens on same dataset
|
||||||
await DataProvider.setRundown(updatedRundown);
|
await DataProvider.setRundown(updatedRundown);
|
||||||
|
|
||||||
|
rundownRevision++;
|
||||||
|
|
||||||
return newEvent;
|
return newEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,6 +175,8 @@ export async function cachedDelete(eventId: string) {
|
|||||||
}
|
}
|
||||||
// we need to delay updating this to ensure edit operation happens on same dataset
|
// we need to delay updating this to ensure edit operation happens on same dataset
|
||||||
await DataProvider.setRundown(updatedRundown);
|
await DataProvider.setRundown(updatedRundown);
|
||||||
|
|
||||||
|
rundownRevision++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,12 +208,15 @@ export async function cachedReorder(eventId: string, from: number, to: number) {
|
|||||||
// we need to delay updating this to ensure edit operation happens on same dataset
|
// we need to delay updating this to ensure edit operation happens on same dataset
|
||||||
await DataProvider.setRundown(updatedRundown);
|
await DataProvider.setRundown(updatedRundown);
|
||||||
|
|
||||||
|
rundownRevision++;
|
||||||
|
|
||||||
return reorderedEvent;
|
return reorderedEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cachedClear() {
|
export async function cachedClear() {
|
||||||
await DataProvider.clearRundown();
|
await DataProvider.clearRundown();
|
||||||
runtimeCacheStore.setCached(delayedRundownCacheKey, []);
|
runtimeCacheStore.setCached(delayedRundownCacheKey, []);
|
||||||
|
rundownRevision++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -211,6 +244,8 @@ export async function cachedSwap(fromEventId: string, toEventId: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await DataProvider.setRundown(rundownToUpdate);
|
await DataProvider.setRundown(rundownToUpdate);
|
||||||
|
|
||||||
|
rundownRevision++;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cachedApplyDelay(eventId: string) {
|
export async function cachedApplyDelay(eventId: string) {
|
||||||
@@ -224,6 +259,8 @@ export async function cachedApplyDelay(eventId: string) {
|
|||||||
// update
|
// update
|
||||||
runtimeCacheStore.setCached(delayedRundownCacheKey, cachedRundown);
|
runtimeCacheStore.setCached(delayedRundownCacheKey, cachedRundown);
|
||||||
await DataProvider.setRundown(persistedRundown);
|
await DataProvider.setRundown(persistedRundown);
|
||||||
|
|
||||||
|
rundownRevision++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { OntimeRundown } from '../../definitions/core/Rundown.type.js';
|
||||||
|
|
||||||
|
export interface GetRundownCached {
|
||||||
|
rundown: OntimeRundown;
|
||||||
|
revision: number;
|
||||||
|
}
|
||||||
@@ -35,6 +35,7 @@ export type { OSCSettings, OscSubscription, OscSubscriptionOptions } from './def
|
|||||||
|
|
||||||
// SERVER RESPONSES
|
// SERVER RESPONSES
|
||||||
export type { NetworkInterface, GetInfo } from './api/ontime-controller/BackendResponse.type.js';
|
export type { NetworkInterface, GetInfo } from './api/ontime-controller/BackendResponse.type.js';
|
||||||
|
export type { GetRundownCached } from './api/rundown-controller/BackendResponse.type.js';
|
||||||
|
|
||||||
// SERVER RUNTIME
|
// SERVER RUNTIME
|
||||||
export { type Log, LogLevel, type LogMessage, LogOrigin } from './definitions/runtime/Logger.type.js';
|
export { type Log, LogLevel, type LogMessage, LogOrigin } from './definitions/runtime/Logger.type.js';
|
||||||
|
|||||||
Generated
+32
-53
@@ -78,11 +78,11 @@ importers:
|
|||||||
specifier: ^7.46.0
|
specifier: ^7.46.0
|
||||||
version: 7.46.0
|
version: 7.46.0
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^4.28.0
|
specifier: ^5.8.4
|
||||||
version: 4.28.0(react-dom@18.2.0)(react@18.2.0)
|
version: 5.8.4(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@tanstack/react-query-devtools':
|
'@tanstack/react-query-devtools':
|
||||||
specifier: ^4.29.0
|
specifier: ^5.8.4
|
||||||
version: 4.29.0(@tanstack/react-query@4.28.0)(react-dom@18.2.0)(react@18.2.0)
|
version: 5.8.4(@tanstack/react-query@5.8.4)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@tanstack/react-table':
|
'@tanstack/react-table':
|
||||||
specifier: ^8.9.2
|
specifier: ^8.9.2
|
||||||
version: 8.9.2(react-dom@18.2.0)(react@18.2.0)
|
version: 8.9.2(react-dom@18.2.0)(react@18.2.0)
|
||||||
@@ -139,8 +139,8 @@ importers:
|
|||||||
specifier: ^0.4.0
|
specifier: ^0.4.0
|
||||||
version: 0.4.0
|
version: 0.4.0
|
||||||
'@tanstack/eslint-plugin-query':
|
'@tanstack/eslint-plugin-query':
|
||||||
specifier: ^4.26.2
|
specifier: ^5.8.4
|
||||||
version: 4.26.2
|
version: 5.8.4(eslint@8.53.0)(typescript@5.2.2)
|
||||||
'@testing-library/jest-dom':
|
'@testing-library/jest-dom':
|
||||||
specifier: ^5.16.5
|
specifier: ^5.16.5
|
||||||
version: 5.16.5
|
version: 5.16.5
|
||||||
@@ -2704,41 +2704,44 @@ packages:
|
|||||||
defer-to-connect: 2.0.1
|
defer-to-connect: 2.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@tanstack/eslint-plugin-query@4.26.2:
|
/@tanstack/eslint-plugin-query@5.8.4(eslint@8.53.0)(typescript@5.2.2):
|
||||||
resolution: {integrity: sha512-ugAvl6Is+bUMLt9BlAnXK6Wi7UnGV+4RwJ2W1ToFoucPvUb2Uf+ADU38JkHaNsI/TFgE3+kePhKh0zzDBhkw0Q==}
|
resolution: {integrity: sha512-KVgcMc+Bn1qbwkxYVWQoiVSNEIN4IAiLj3cUH/SAHT8m8E59Y97o8ON1syp0Rcw094ItG8pEVZFyQuOaH6PDgQ==}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^8.0.0
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/utils': 5.62.0(eslint@8.53.0)(typescript@5.2.2)
|
||||||
|
eslint: 8.53.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
- typescript
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@tanstack/match-sorter-utils@8.7.6:
|
/@tanstack/query-core@5.8.3:
|
||||||
resolution: {integrity: sha512-2AMpRiA6QivHOUiBpQAVxjiHAA68Ei23ZUMNaRJrN6omWiSFLoYrxGcT6BXtuzp0Jw4h6HZCmGGIM/gbwebO2A==}
|
resolution: {integrity: sha512-SWFMFtcHfttLYif6pevnnMYnBvxKf3C+MHMH7bevyYfpXpTMsLB9O6nNGBdWSoPwnZRXFNyNeVZOw25Wmdasow==}
|
||||||
engines: {node: '>=12'}
|
|
||||||
dependencies:
|
|
||||||
remove-accents: 0.4.2
|
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@tanstack/query-core@4.27.0:
|
/@tanstack/query-devtools@5.8.4:
|
||||||
resolution: {integrity: sha512-sm+QncWaPmM73IPwFlmWSKPqjdTXZeFf/7aEmWh00z7yl2FjqophPt0dE1EHW9P1giMC5rMviv7OUbSDmWzXXA==}
|
resolution: {integrity: sha512-F1dRbITNt9tMUoM9WCH8WQ2c54116hv52m/PKK8ZiN/pO2wGVzTZtKuLanF8pFpwmNchjIixcMw/a57HY5ivcw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@tanstack/react-query-devtools@4.29.0(@tanstack/react-query@4.28.0)(react-dom@18.2.0)(react@18.2.0):
|
/@tanstack/react-query-devtools@5.8.4(@tanstack/react-query@5.8.4)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-bzotqin4Wa/GlPgJ2dI7eggQcbMDLIOwEClHGrkyie76DbT8vEEmEV9Kbh6kriKVSqCLpa9ZrgG/f8/Bx1zIwA==}
|
resolution: {integrity: sha512-mffs51FJqXU/5rwhbwv393DccL6et7uK2pRLwOcmMrWbPyW8vpxr9oidaghHX4cdVeP/7u5owW9yMpBhBAJfcQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tanstack/react-query': 4.28.0
|
'@tanstack/react-query': ^5.8.4
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
react: ^18.0.0
|
||||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
react-dom: ^18.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/match-sorter-utils': 8.7.6
|
'@tanstack/query-devtools': 5.8.4
|
||||||
'@tanstack/react-query': 4.28.0(react-dom@18.2.0)(react@18.2.0)
|
'@tanstack/react-query': 5.8.4(react-dom@18.2.0)(react@18.2.0)
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
superjson: 1.12.1
|
|
||||||
use-sync-external-store: 1.2.0(react@18.2.0)
|
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@tanstack/react-query@4.28.0(react-dom@18.2.0)(react@18.2.0):
|
/@tanstack/react-query@5.8.4(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-8cGBV5300RHlvYdS4ea+G1JcZIt5CIuprXYFnsWggkmGoC0b5JaqG0fIX3qwDL9PTNkKvG76NGThIWbpXivMrQ==}
|
resolution: {integrity: sha512-CD+AkXzg8J72JrE6ocmuBEJfGzEzu/bzkD6sFXFDDB5yji9N20JofXZlN6n0+CaPJuIi+e4YLCbGsyPFKkfNQA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
react: ^18.0.0
|
||||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
react-dom: ^18.0.0
|
||||||
react-native: '*'
|
react-native: '*'
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
react-dom:
|
react-dom:
|
||||||
@@ -2746,10 +2749,9 @@ packages:
|
|||||||
react-native:
|
react-native:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/query-core': 4.27.0
|
'@tanstack/query-core': 5.8.3
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
use-sync-external-store: 1.2.0(react@18.2.0)
|
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@tanstack/react-table@8.9.2(react-dom@18.2.0)(react@18.2.0):
|
/@tanstack/react-table@8.9.2(react-dom@18.2.0)(react@18.2.0):
|
||||||
@@ -4243,13 +4245,6 @@ packages:
|
|||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/copy-anything@3.0.3:
|
|
||||||
resolution: {integrity: sha512-fpW2W/BqEzqPp29QS+MwwfisHCQZtiduTe/m8idFo0xbti9fIZ2WVhAsCv4ggFVH3AgCkVdpoOCtQC6gBrdhjw==}
|
|
||||||
engines: {node: '>=12.13'}
|
|
||||||
dependencies:
|
|
||||||
is-what: 4.1.8
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/copy-to-clipboard@3.3.3:
|
/copy-to-clipboard@3.3.3:
|
||||||
resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
|
resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6131,11 +6126,6 @@ packages:
|
|||||||
get-intrinsic: 1.1.3
|
get-intrinsic: 1.1.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/is-what@4.1.8:
|
|
||||||
resolution: {integrity: sha512-yq8gMao5upkPoGEU9LsB2P+K3Kt8Q3fQFCGyNCWOAnJAMzEXVV9drYb0TXr42TTliLLhKIBvulgAXgtLLnwzGA==}
|
|
||||||
engines: {node: '>=12.13'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/is-wsl@2.2.0:
|
/is-wsl@2.2.0:
|
||||||
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
|
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -7488,10 +7478,6 @@ packages:
|
|||||||
functions-have-names: 1.2.3
|
functions-have-names: 1.2.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/remove-accents@0.4.2:
|
|
||||||
resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/require-directory@2.1.1:
|
/require-directory@2.1.1:
|
||||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -8001,13 +7987,6 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/superjson@1.12.1:
|
|
||||||
resolution: {integrity: sha512-HMTj43zvwW5bD+JCZCvFf4DkZQCmiLTen4C+W1Xogj0SPOpnhxsriogM04QmBVGH5b3kcIIOr6FqQ/aoIDx7TQ==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
copy-anything: 3.0.3
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/supports-color@5.5.0:
|
/supports-color@5.5.0:
|
||||||
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
|
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|||||||
Reference in New Issue
Block a user