fix: custom project data

This commit is contained in:
Carlos Valente
2025-07-25 18:54:27 +02:00
committed by Carlos Valente
parent bda01c886e
commit dc3a32d2bc
3 changed files with 26 additions and 13 deletions
@@ -1,8 +1,8 @@
import { useQuery } from '@tanstack/react-query'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { queryRefetchIntervalSlow } from '../../ontimeConfig'; import { queryRefetchIntervalSlow } from '../../ontimeConfig';
import { PROJECT_DATA } from '../api/constants'; import { PROJECT_DATA } from '../api/constants';
import { getProjectData } from '../api/project'; import { getProjectData, postProjectData } from '../api/project';
import { projectDataPlaceholder } from '../models/ProjectData'; import { projectDataPlaceholder } from '../models/ProjectData';
export default function useProjectData() { export default function useProjectData() {
@@ -10,11 +10,25 @@ export default function useProjectData() {
queryKey: PROJECT_DATA, queryKey: PROJECT_DATA,
queryFn: getProjectData, queryFn: getProjectData,
placeholderData: (previousData, _previousQuery) => previousData, placeholderData: (previousData, _previousQuery) => previousData,
retry: 5,
retryDelay: (attempt) => attempt * 2500,
refetchInterval: queryRefetchIntervalSlow, refetchInterval: queryRefetchIntervalSlow,
networkMode: 'always',
}); });
return { data: data ?? projectDataPlaceholder, status, isFetching, isError, refetch }; return { data: data ?? projectDataPlaceholder, status, isFetching, isError, refetch };
} }
export function useUpdateProjectData() {
const queryClient = useQueryClient();
const updateFn = useMutation({
mutationFn: postProjectData,
onSuccess: (newProjectData) => {
queryClient.setQueryData(PROJECT_DATA, newProjectData);
},
});
return {
updateProjectData: updateFn.mutateAsync,
isMutating: updateFn.isPending,
isMutatingError: updateFn.isError,
};
}
@@ -4,12 +4,12 @@ import { IoAdd, IoDownloadOutline, IoTrash } from 'react-icons/io5';
import { type ProjectData } from 'ontime-types'; import { type ProjectData } from 'ontime-types';
import { projectLogoPath } from '../../../../common/api/constants'; import { projectLogoPath } from '../../../../common/api/constants';
import { postProjectData, uploadProjectLogo } from '../../../../common/api/project'; import { uploadProjectLogo } from '../../../../common/api/project';
import { maybeAxiosError } from '../../../../common/api/utils'; import { maybeAxiosError } from '../../../../common/api/utils';
import Button from '../../../../common/components/buttons/Button'; import Button from '../../../../common/components/buttons/Button';
import Input from '../../../../common/components/input/input/Input'; import Input from '../../../../common/components/input/input/Input';
import Textarea from '../../../../common/components/input/textarea/Textarea'; import Textarea from '../../../../common/components/input/textarea/Textarea';
import useProjectData from '../../../../common/hooks-query/useProjectData'; import useProjectData, { useUpdateProjectData } from '../../../../common/hooks-query/useProjectData';
import { preventEscape } from '../../../../common/utils/keyEvent'; import { preventEscape } from '../../../../common/utils/keyEvent';
import { validateLogo } from '../../../../common/utils/uploadUtils'; import { validateLogo } from '../../../../common/utils/uploadUtils';
import { documentationUrl } from '../../../../externals'; import { documentationUrl } from '../../../../externals';
@@ -19,7 +19,8 @@ import style from './SettingsPanel.module.scss';
export default function ProjectData() { export default function ProjectData() {
'use no memo'; // RHF and react-compiler don't seem to get along 'use no memo'; // RHF and react-compiler don't seem to get along
const { data, status, refetch } = useProjectData(); const { data, status } = useProjectData();
const { updateProjectData } = useUpdateProjectData();
const { const {
handleSubmit, handleSubmit,
@@ -93,16 +94,14 @@ export default function ProjectData() {
const onSubmit = async (formData: ProjectData) => { const onSubmit = async (formData: ProjectData) => {
try { try {
await postProjectData(formData); await updateProjectData(formData);
} catch (error) { } catch (error) {
const message = maybeAxiosError(error); const message = maybeAxiosError(error);
setError('root', { message }); setError('root', { message });
} finally {
await refetch();
} }
}; };
// populate with new data if we get an update // reset data to the initial state
const onReset = () => { const onReset = () => {
reset(data); reset(data);
}; };
@@ -11,7 +11,7 @@ export const projectSanitiser = [
body('custom').optional().isArray(), body('custom').optional().isArray(),
body('custom.*.title').optional().isString().trim().notEmpty(), body('custom.*.title').optional().isString().trim().notEmpty(),
body('custom.*.value').optional().isString().trim().notEmpty(), body('custom.*.value').optional().isString().trim().notEmpty(),
body('custom.*.url').optional().isString().trim().notEmpty(), body('custom.*.url').optional().isString().trim(),
requestValidationFunction, requestValidationFunction,
]; ];