refactor: WS (#1622)

* refactor: WS

* refactor refetch

extract refetch keys to package/types

auto invalidata all keys

use refetch keys for project data

no need for constant update of info, just fetch when looking at it

split refetch and query keys

rename types

* refactor viewSettings

* fixup! refactor: WS

* rearange files and make types for api calls

* cleanup viewsettings

* switch exhaustiveCheck

* combine send socket function

* exhaustive check

* rename type to tag

* fixup! fixup! refactor: WS

* remove custom etag solution

* get errors from socket

* lint

* small change

---------

Co-authored-by: Carlos Valente <carlosvalente@pm.me>
This commit is contained in:
Alex Christoffer Rasmussen
2025-06-21 12:18:59 +02:00
committed by GitHub
parent c8fe0bbcba
commit 31d47ed1e5
28 changed files with 377 additions and 333 deletions
@@ -4,7 +4,6 @@ import { Button, Input, Switch, useDisclosure } from '@chakra-ui/react';
import { ViewSettings } from 'ontime-types';
import { maybeAxiosError } from '../../../../common/api/utils';
import { postViewSettings } from '../../../../common/api/viewSettings';
import Info from '../../../../common/components/info/Info';
import { SwatchPickerRHF } from '../../../../common/components/input/colour-input/SwatchPicker';
import ExternalLink from '../../../../common/components/link/external-link/ExternalLink';
@@ -19,17 +18,17 @@ import CodeEditorModal from './StyleEditorModal';
const cssOverrideDocsUrl = 'https://docs.getontime.no/features/custom-styling/';
export default function ViewSettingsForm() {
const { data, status, refetch } = useViewSettings();
const { data, isPending, mutateAsync } = useViewSettings();
const { data: info, status: infoStatus } = useInfo();
const { isOpen: isCodeEditorOpen, onOpen: onCodeEditorOpen, onClose: onCodeEditorClose } = useDisclosure();
const {
control,
handleSubmit,
setError,
register,
reset,
setError,
formState: { isSubmitting, isDirty },
formState: { isSubmitting, isDirty, errors },
} = useForm<ViewSettings>({
defaultValues: data,
values: data,
@@ -46,17 +45,11 @@ export default function ViewSettingsForm() {
}, [data, reset]);
const onSubmit = async (formData: ViewSettings) => {
const newData = {
...formData,
};
try {
await postViewSettings(newData);
mutateAsync(formData);
} catch (error) {
const message = maybeAxiosError(error);
setError('root', { message });
} finally {
await refetch();
}
};
@@ -68,7 +61,7 @@ export default function ViewSettingsForm() {
return null;
}
const isLoading = status === 'pending' || infoStatus === 'pending';
const isLoading = isPending || infoStatus === 'pending';
return (
<Panel.Section
@@ -105,6 +98,7 @@ export default function ViewSettingsForm() {
</Info>
<Panel.Section>
<Panel.Loader isLoading={isLoading} />
<Panel.Error>{errors.root?.message}</Panel.Error>
<Panel.ListGroup>
<CodeEditorModal isOpen={isCodeEditorOpen} onClose={onCodeEditorClose} />
<Panel.ListItem>
@@ -1,8 +1,9 @@
import { useEffect } from 'react';
import { MessageTag } from 'ontime-types';
import useScrollIntoView from '../../../../common/hooks/useScrollIntoView';
import { usePing } from '../../../../common/hooks/useSocket';
import { socketSendJson } from '../../../../common/utils/socket';
import { sendSocket } from '../../../../common/utils/socket';
import { isDockerImage, isOntimeCloud } from '../../../../externals';
import type { PanelBaseProps } from '../../panel-list/PanelList';
import * as Panel from '../../panel-utils/PanelUtils';
@@ -57,10 +58,10 @@ function OntimeCloudStats() {
* Send immediate ping request, and keep sending on an interval
*/
useEffect(() => {
socketSendJson('ping', new Date());
sendSocket(MessageTag.Ping, new Date());
const doPing = setInterval(() => {
socketSendJson('ping', new Date());
sendSocket(MessageTag.Ping, new Date());
}, 5000);
return () => {
@@ -158,8 +158,10 @@ export default function RundownEntry(props: RundownEntryProps) {
return emitError(`Unknown field: ${field}`);
}
default:
default: {
action satisfies never;
throw new Error(`Unhandled event ${action}`);
}
}
});
@@ -37,8 +37,10 @@ export function getTimerByType(
return timerObject.clock;
case TimerType.None:
return null;
default:
default: {
viewTimerType satisfies never;
return null;
}
}
}