mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-04 22:09:10 +00:00
Refactor error messages (#463)
* refactor: improve error messages to user * refactor: remove unused
This commit is contained in:
@@ -0,0 +1,20 @@
|
|||||||
|
import axios, { AxiosError } from 'axios';
|
||||||
|
import { LogLevel } from 'ontime-types';
|
||||||
|
import { generateId, millisToString } from 'ontime-utils';
|
||||||
|
|
||||||
|
import { addLog } from '../stores/logger';
|
||||||
|
import { nowInMillis } from '../utils/time';
|
||||||
|
|
||||||
|
export function logAxiosError(prepend: string, error: unknown) {
|
||||||
|
const message = axios.isAxiosError(error)
|
||||||
|
? `${prepend}, ${(error as AxiosError).response?.statusText}: ${(error as AxiosError).response?.data}`
|
||||||
|
: `${prepend}: ${error}`;
|
||||||
|
|
||||||
|
addLog({
|
||||||
|
id: generateId(),
|
||||||
|
origin: 'SERVER',
|
||||||
|
time: millisToString(nowInMillis()),
|
||||||
|
level: LogLevel.Error,
|
||||||
|
text: message,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -28,14 +28,6 @@ export async function requestPutEvent(data: Partial<OntimeRundownEntry>) {
|
|||||||
return axios.put(rundownURL, data);
|
return axios.put(rundownURL, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description HTTP request to modify event
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
export async function requestPatchEvent(data: OntimeRundownEntry) {
|
|
||||||
return axios.patch(rundownURL, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ReorderEntry = {
|
export type ReorderEntry = {
|
||||||
eventId: string;
|
eventId: string;
|
||||||
from: number;
|
from: number;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { OSCSettings } from 'ontime-types';
|
|||||||
|
|
||||||
import { queryRefetchIntervalSlow } from '../../ontimeConfig';
|
import { queryRefetchIntervalSlow } from '../../ontimeConfig';
|
||||||
import { OSC_SETTINGS } from '../api/apiConstants';
|
import { OSC_SETTINGS } from '../api/apiConstants';
|
||||||
|
import { logAxiosError } from '../api/apiUtils';
|
||||||
import { getOSC, postOSC, postOscSubscriptions } from '../api/ontimeApi';
|
import { getOSC, postOSC, postOscSubscriptions } from '../api/ontimeApi';
|
||||||
import { oscPlaceholderSettings } from '../models/OscSettings';
|
import { oscPlaceholderSettings } from '../models/OscSettings';
|
||||||
import { ontimeQueryClient } from '../queryClient';
|
import { ontimeQueryClient } from '../queryClient';
|
||||||
@@ -25,6 +26,7 @@ export default function useOscSettings() {
|
|||||||
export function useOscSettingsMutation() {
|
export function useOscSettingsMutation() {
|
||||||
const { isLoading, mutateAsync } = useMutation({
|
const { isLoading, mutateAsync } = useMutation({
|
||||||
mutationFn: postOSC,
|
mutationFn: postOSC,
|
||||||
|
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 }),
|
||||||
});
|
});
|
||||||
@@ -34,6 +36,7 @@ export function useOscSettingsMutation() {
|
|||||||
export function usePostOscSubscriptions() {
|
export function usePostOscSubscriptions() {
|
||||||
const { isLoading, mutateAsync } = useMutation({
|
const { isLoading, mutateAsync } = useMutation({
|
||||||
mutationFn: postOscSubscriptions,
|
mutationFn: postOscSubscriptions,
|
||||||
|
onError: (error) => logAxiosError('Error saving OSC settings', error),
|
||||||
onSettled: () => ontimeQueryClient.invalidateQueries({ queryKey: OSC_SETTINGS }),
|
onSettled: () => ontimeQueryClient.invalidateQueries({ queryKey: OSC_SETTINGS }),
|
||||||
});
|
});
|
||||||
return { isLoading, mutateAsync };
|
return { isLoading, mutateAsync };
|
||||||
|
|||||||
@@ -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 axios, { AxiosError } from 'axios';
|
|
||||||
import { OntimeRundown, OntimeRundownEntry, SupportedEvent } from 'ontime-types';
|
import { OntimeRundown, OntimeRundownEntry, SupportedEvent } from 'ontime-types';
|
||||||
|
|
||||||
import { RUNDOWN_TABLE, RUNDOWN_TABLE_KEY } from '../api/apiConstants';
|
import { RUNDOWN_TABLE, RUNDOWN_TABLE_KEY } from '../api/apiConstants';
|
||||||
|
import { logAxiosError } from '../api/apiUtils';
|
||||||
import {
|
import {
|
||||||
ReorderEntry,
|
ReorderEntry,
|
||||||
requestApplyDelay,
|
requestApplyDelay,
|
||||||
@@ -14,14 +14,12 @@ import {
|
|||||||
requestReorderEvent,
|
requestReorderEvent,
|
||||||
} from '../api/eventsApi';
|
} from '../api/eventsApi';
|
||||||
import { useLocalEvent } from '../stores/localEvent';
|
import { useLocalEvent } from '../stores/localEvent';
|
||||||
import { useEmitLog } from '../stores/logger';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Set of utilities for events
|
* @description Set of utilities for events
|
||||||
*/
|
*/
|
||||||
export const useEventAction = () => {
|
export const useEventAction = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { emitError } = useEmitLog();
|
|
||||||
const eventSettings = useLocalEvent((state) => state.eventSettings);
|
const eventSettings = useLocalEvent((state) => state.eventSettings);
|
||||||
const defaultPublic = eventSettings.defaultPublic;
|
const defaultPublic = eventSettings.defaultPublic;
|
||||||
const startTimeIsLastEnd = eventSettings.startTimeIsLastEnd;
|
const startTimeIsLastEnd = eventSettings.startTimeIsLastEnd;
|
||||||
@@ -94,14 +92,10 @@ export const useEventAction = () => {
|
|||||||
// @ts-expect-error -- we know that the object is well formed now
|
// @ts-expect-error -- we know that the object is well formed now
|
||||||
await _addEventMutation.mutateAsync(newEvent);
|
await _addEventMutation.mutateAsync(newEvent);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!axios.isAxiosError(error)) {
|
logAxiosError('Error fetching data', error);
|
||||||
emitError(`Error fetching data: ${(error as AxiosError).message}`);
|
|
||||||
} else {
|
|
||||||
emitError(`Error fetching data: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[_addEventMutation, defaultPublic, emitError, queryClient, startTimeIsLastEnd],
|
[_addEventMutation, defaultPublic, queryClient, startTimeIsLastEnd],
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -144,14 +138,10 @@ export const useEventAction = () => {
|
|||||||
try {
|
try {
|
||||||
await _updateEventMutation.mutateAsync(event);
|
await _updateEventMutation.mutateAsync(event);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!axios.isAxiosError(error)) {
|
logAxiosError('Error updating event', error);
|
||||||
emitError(`Error updating event: ${(error as AxiosError).message}`);
|
|
||||||
} else {
|
|
||||||
emitError(`Error updating event: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[_updateEventMutation, emitError],
|
[_updateEventMutation],
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -196,14 +186,10 @@ export const useEventAction = () => {
|
|||||||
try {
|
try {
|
||||||
await _deleteEventMutation.mutateAsync(eventId);
|
await _deleteEventMutation.mutateAsync(eventId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!axios.isAxiosError(error)) {
|
logAxiosError('Error deleting event', error);
|
||||||
emitError(`Error deleting event: ${(error as AxiosError).message}`);
|
|
||||||
} else {
|
|
||||||
emitError(`Error deleting event: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[_deleteEventMutation, emitError],
|
[_deleteEventMutation],
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -245,13 +231,9 @@ export const useEventAction = () => {
|
|||||||
try {
|
try {
|
||||||
await _deleteAllEventsMutation.mutateAsync();
|
await _deleteAllEventsMutation.mutateAsync();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!axios.isAxiosError(error)) {
|
logAxiosError('Error deleting events', error);
|
||||||
emitError(`Error deleting events: ${(error as AxiosError).message}`);
|
|
||||||
} else {
|
|
||||||
emitError(`Error deleting events: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [_deleteAllEventsMutation, emitError]);
|
}, [_deleteAllEventsMutation]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls mutation to apply a delay
|
* Calls mutation to apply a delay
|
||||||
@@ -273,14 +255,10 @@ export const useEventAction = () => {
|
|||||||
try {
|
try {
|
||||||
await _applyDelayMutation.mutateAsync(delayEventId);
|
await _applyDelayMutation.mutateAsync(delayEventId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!axios.isAxiosError(error)) {
|
logAxiosError('Error applying delay', error);
|
||||||
emitError(`Error applying delay: ${(error as AxiosError).message}`);
|
|
||||||
} else {
|
|
||||||
emitError(`Error applying delay: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[_applyDelayMutation, emitError],
|
[_applyDelayMutation],
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -332,14 +310,10 @@ export const useEventAction = () => {
|
|||||||
};
|
};
|
||||||
await _reorderEventMutation.mutateAsync(reorderObject);
|
await _reorderEventMutation.mutateAsync(reorderObject);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!axios.isAxiosError(error)) {
|
logAxiosError('Error re-ordering event', error);
|
||||||
emitError(`Error re-ordering event: ${(error as AxiosError).message}`);
|
|
||||||
} else {
|
|
||||||
emitError(`Error re-ordering event: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[_reorderEventMutation, emitError],
|
[_reorderEventMutation],
|
||||||
);
|
);
|
||||||
|
|
||||||
return { addEvent, updateEvent, deleteEvent, deleteAllEvents, applyDelay, reorderEvent };
|
return { addEvent, updateEvent, deleteEvent, deleteAllEvents, applyDelay, reorderEvent };
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { IoOpenOutline } from '@react-icons/all-files/io5/IoOpenOutline';
|
|||||||
import { IoRemove } from '@react-icons/all-files/io5/IoRemove';
|
import { IoRemove } from '@react-icons/all-files/io5/IoRemove';
|
||||||
import { Alias } from 'ontime-types';
|
import { Alias } from 'ontime-types';
|
||||||
|
|
||||||
|
import { logAxiosError } from '../../../common/api/apiUtils';
|
||||||
import { postAliases } from '../../../common/api/ontimeApi';
|
import { postAliases } from '../../../common/api/ontimeApi';
|
||||||
import TooltipActionBtn from '../../../common/components/buttons/TooltipActionBtn';
|
import TooltipActionBtn from '../../../common/components/buttons/TooltipActionBtn';
|
||||||
import useAliases from '../../../common/hooks-query/useAliases';
|
import useAliases from '../../../common/hooks-query/useAliases';
|
||||||
@@ -53,7 +54,7 @@ export default function AliasesForm() {
|
|||||||
try {
|
try {
|
||||||
await postAliases(formData.aliases);
|
await postAliases(formData.aliases);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
emitError(`Error saving aliases: ${error}`);
|
logAxiosError('Error saving aliases', error);
|
||||||
} finally {
|
} finally {
|
||||||
await refetch();
|
await refetch();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { useForm } from 'react-hook-form';
|
|||||||
import { Input, Select } from '@chakra-ui/react';
|
import { Input, Select } from '@chakra-ui/react';
|
||||||
import type { Settings } from 'ontime-types';
|
import type { Settings } from 'ontime-types';
|
||||||
|
|
||||||
|
import { logAxiosError } from '../../../common/api/apiUtils';
|
||||||
import { postSettings } from '../../../common/api/ontimeApi';
|
import { postSettings } from '../../../common/api/ontimeApi';
|
||||||
import useSettings from '../../../common/hooks-query/useSettings';
|
import useSettings from '../../../common/hooks-query/useSettings';
|
||||||
import { useEmitLog } from '../../../common/stores/logger';
|
|
||||||
import { isOnlyNumbers } from '../../../common/utils/regex';
|
import { isOnlyNumbers } from '../../../common/utils/regex';
|
||||||
import ModalLoader from '../modal-loader/ModalLoader';
|
import ModalLoader from '../modal-loader/ModalLoader';
|
||||||
import ModalSplitInput from '../ModalSplitInput';
|
import ModalSplitInput from '../ModalSplitInput';
|
||||||
@@ -17,7 +17,6 @@ import style from './SettingsModal.module.scss';
|
|||||||
|
|
||||||
export default function AppSettingsModal() {
|
export default function AppSettingsModal() {
|
||||||
const { data, status, isFetching, refetch } = useSettings();
|
const { data, status, isFetching, refetch } = useSettings();
|
||||||
const { emitError } = useEmitLog();
|
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
register,
|
register,
|
||||||
@@ -41,7 +40,7 @@ export default function AppSettingsModal() {
|
|||||||
try {
|
try {
|
||||||
await postSettings(formData);
|
await postSettings(formData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
emitError(`Error saving settings: ${error}`);
|
logAxiosError('Error saving settings', error);
|
||||||
} finally {
|
} finally {
|
||||||
await refetch();
|
await refetch();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { useForm } from 'react-hook-form';
|
|||||||
import { Alert, AlertDescription, AlertIcon, AlertTitle, Input } from '@chakra-ui/react';
|
import { Alert, AlertDescription, AlertIcon, AlertTitle, Input } from '@chakra-ui/react';
|
||||||
import { UserFields } from 'ontime-types';
|
import { UserFields } from 'ontime-types';
|
||||||
|
|
||||||
|
import { logAxiosError } from '../../../common/api/apiUtils';
|
||||||
import { postUserFields } from '../../../common/api/ontimeApi';
|
import { postUserFields } from '../../../common/api/ontimeApi';
|
||||||
import useUserFields from '../../../common/hooks-query/useUserFields';
|
import useUserFields from '../../../common/hooks-query/useUserFields';
|
||||||
import { useEmitLog } from '../../../common/stores/logger';
|
|
||||||
import ModalLoader from '../modal-loader/ModalLoader';
|
import ModalLoader from '../modal-loader/ModalLoader';
|
||||||
import { inputProps } from '../modalHelper';
|
import { inputProps } from '../modalHelper';
|
||||||
import ModalLink from '../ModalLink';
|
import ModalLink from '../ModalLink';
|
||||||
@@ -18,7 +18,6 @@ const userFieldsDocsUrl = 'https://ontime.gitbook.io/v2/features/user-fields';
|
|||||||
|
|
||||||
export default function CuesheetSettingsForm() {
|
export default function CuesheetSettingsForm() {
|
||||||
const { data, status, isFetching, refetch } = useUserFields();
|
const { data, status, isFetching, refetch } = useUserFields();
|
||||||
const { emitError } = useEmitLog();
|
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
register,
|
register,
|
||||||
@@ -42,7 +41,7 @@ export default function CuesheetSettingsForm() {
|
|||||||
try {
|
try {
|
||||||
await postUserFields(formData);
|
await postUserFields(formData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
emitError(`Error saving cuesheet settings: ${error}`);
|
logAxiosError('Error saving cuesheet settings', error);
|
||||||
} finally {
|
} finally {
|
||||||
await refetch();
|
await refetch();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { useForm } from 'react-hook-form';
|
|||||||
import { Input, Textarea } from '@chakra-ui/react';
|
import { Input, Textarea } from '@chakra-ui/react';
|
||||||
import { EventData } from 'ontime-types';
|
import { EventData } from 'ontime-types';
|
||||||
|
|
||||||
|
import { logAxiosError } from '../../../common/api/apiUtils';
|
||||||
import { postEventData } from '../../../common/api/eventDataApi';
|
import { postEventData } from '../../../common/api/eventDataApi';
|
||||||
import useEventData from '../../../common/hooks-query/useEventData';
|
import useEventData from '../../../common/hooks-query/useEventData';
|
||||||
import { useEmitLog } from '../../../common/stores/logger';
|
|
||||||
import ModalLoader from '../modal-loader/ModalLoader';
|
import ModalLoader from '../modal-loader/ModalLoader';
|
||||||
import { inputProps } from '../modalHelper';
|
import { inputProps } from '../modalHelper';
|
||||||
import ModalInput from '../ModalInput';
|
import ModalInput from '../ModalInput';
|
||||||
@@ -15,7 +15,6 @@ import style from './SettingsModal.module.scss';
|
|||||||
|
|
||||||
export default function EventDataForm() {
|
export default function EventDataForm() {
|
||||||
const { data, status, isFetching, refetch } = useEventData();
|
const { data, status, isFetching, refetch } = useEventData();
|
||||||
const { emitError } = useEmitLog();
|
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
register,
|
register,
|
||||||
@@ -39,7 +38,7 @@ export default function EventDataForm() {
|
|||||||
try {
|
try {
|
||||||
await postEventData(formData);
|
await postEventData(formData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
emitError(`Error saving event settings: ${error}`);
|
logAxiosError('Error saving event settings', error);
|
||||||
} finally {
|
} finally {
|
||||||
await refetch();
|
await refetch();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,15 @@ import { useForm } from 'react-hook-form';
|
|||||||
import { Input, Switch } from '@chakra-ui/react';
|
import { Input, Switch } from '@chakra-ui/react';
|
||||||
import { ViewSettings } from 'ontime-types';
|
import { ViewSettings } from 'ontime-types';
|
||||||
|
|
||||||
|
import { logAxiosError } from '../../../common/api/apiUtils';
|
||||||
import { postViewSettings } from '../../../common/api/ontimeApi';
|
import { postViewSettings } from '../../../common/api/ontimeApi';
|
||||||
import { PopoverPickerRHF } from '../../../common/components/input/popover-picker/PopoverPicker';
|
import { PopoverPickerRHF } from '../../../common/components/input/popover-picker/PopoverPicker';
|
||||||
import useViewSettings from '../../../common/hooks-query/useViewSettings';
|
import useViewSettings from '../../../common/hooks-query/useViewSettings';
|
||||||
import { useEmitLog } from '../../../common/stores/logger';
|
|
||||||
import { mtm } from '../../../common/utils/timeConstants';
|
import { mtm } from '../../../common/utils/timeConstants';
|
||||||
|
import ModalLoader from '../modal-loader/ModalLoader';
|
||||||
import { inputProps } from '../modalHelper';
|
import { inputProps } from '../modalHelper';
|
||||||
import ModalInput from '../ModalInput';
|
import ModalInput from '../ModalInput';
|
||||||
import ModalSplitInput from '../ModalSplitInput';
|
import ModalSplitInput from '../ModalSplitInput';
|
||||||
import ModalLoader from '../modal-loader/ModalLoader';
|
|
||||||
import OntimeModalFooter from '../OntimeModalFooter';
|
import OntimeModalFooter from '../OntimeModalFooter';
|
||||||
|
|
||||||
import InputMillisWithString from './InputMillisWithString';
|
import InputMillisWithString from './InputMillisWithString';
|
||||||
@@ -20,7 +20,6 @@ import style from './SettingsModal.module.scss';
|
|||||||
|
|
||||||
export default function ViewSettingsForm() {
|
export default function ViewSettingsForm() {
|
||||||
const { data, status, refetch, isFetching } = useViewSettings();
|
const { data, status, refetch, isFetching } = useViewSettings();
|
||||||
const { emitError } = useEmitLog();
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@@ -60,7 +59,7 @@ export default function ViewSettingsForm() {
|
|||||||
try {
|
try {
|
||||||
await postViewSettings(newData);
|
await postViewSettings(newData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
emitError(`Error saving view settings: ${error}`);
|
logAxiosError('Error saving view settings', error);
|
||||||
} finally {
|
} finally {
|
||||||
await refetch();
|
await refetch();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user