mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-10 00:29:41 +00:00
add http subscription to integration modal
This commit is contained in:
@@ -6,6 +6,7 @@ export const RUNDOWN_TABLE_KEY = 'rundown';
|
|||||||
export const RUNDOWN_TABLE = [RUNDOWN_TABLE_KEY];
|
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 HTTP_SETTINGS = ['httpSettings'];
|
||||||
export const APP_SETTINGS = ['appSettings'];
|
export const APP_SETTINGS = ['appSettings'];
|
||||||
export const VIEW_SETTINGS = ['viewSettings'];
|
export const VIEW_SETTINGS = ['viewSettings'];
|
||||||
export const RUNTIME = ['runtimeStore'];
|
export const RUNTIME = ['runtimeStore'];
|
||||||
|
|||||||
@@ -93,6 +93,18 @@ export async function getOSC(): Promise<OSCSettings> {
|
|||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description HTTP request to retrieve http settings
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
export async function getHTTP(): Promise<HTTPSettings> {
|
||||||
|
console.log('getHTTP')
|
||||||
|
const res = await axios.get(`${ontimeURL}/http`);
|
||||||
|
console.log(res)
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description HTTP request to mutate osc settings
|
* @description HTTP request to mutate osc settings
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
@@ -105,10 +117,18 @@ export async function postOSC(data: OSCSettings) {
|
|||||||
* @description HTTP request to mutate osc subscriptions
|
* @description HTTP request to mutate osc subscriptions
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
export async function postOscSubscriptions(data: OscSubscription) {
|
export async function postOscSubscriptions(data: Subscription) {
|
||||||
return axios.post(`${ontimeURL}/osc-subscriptions`, data);
|
return axios.post(`${ontimeURL}/osc-subscriptions`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description HTTP request to mutate osc subscriptions
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
export async function postHttpSubscriptions(data: Subscription) {
|
||||||
|
return axios.post(`${ontimeURL}/http-subscriptions`, data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description HTTP request to download db in CSV format
|
* @description HTTP request to download db in CSV format
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
|
import { HTTPSettings } from 'ontime-types';
|
||||||
|
|
||||||
|
import { queryRefetchIntervalSlow } from '../../ontimeConfig';
|
||||||
|
import { HTTP_SETTINGS } from '../api/apiConstants';
|
||||||
|
import { logAxiosError } from '../api/apiUtils';
|
||||||
|
import { getHTTP, postHttpSubscriptions } from '../api/ontimeApi';
|
||||||
|
import { httpPlaceholder } from '../models/Http';
|
||||||
|
import { ontimeQueryClient } from '../queryClient';
|
||||||
|
|
||||||
|
export default function useHttpSettings() {
|
||||||
|
const { data, status, isFetching, isError, refetch } = useQuery({
|
||||||
|
queryKey: HTTP_SETTINGS,
|
||||||
|
queryFn: getHTTP,
|
||||||
|
placeholderData: httpPlaceholder,
|
||||||
|
retry: 5,
|
||||||
|
retryDelay: (attempt: number) => attempt * 2500,
|
||||||
|
refetchInterval: queryRefetchIntervalSlow,
|
||||||
|
networkMode: 'always',
|
||||||
|
});
|
||||||
|
|
||||||
|
// we need to jump through some hoops because of the type op port
|
||||||
|
return { data: data! as unknown as HTTPSettings, status, isFetching, isError, refetch };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function usePostHttpSubscriptions() {
|
||||||
|
const { isLoading, mutateAsync } = useMutation({
|
||||||
|
mutationFn: postHttpSubscriptions,
|
||||||
|
onError: (error) => logAxiosError('Error saving HTTP settings', error),
|
||||||
|
onSettled: () => ontimeQueryClient.invalidateQueries({ queryKey: HTTP_SETTINGS }),
|
||||||
|
});
|
||||||
|
return { isLoading, mutateAsync };
|
||||||
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import type { Subscription } from 'ontime-types';
|
||||||
|
import { TimerLifeCycle } from 'ontime-types';
|
||||||
|
|
||||||
|
import useHttpSettings, { usePostHttpSubscriptions } from '../../../common/hooks-query/useHttpSettings';
|
||||||
|
import { useEmitLog } from '../../../common/stores/logger';
|
||||||
|
import ModalLoader from '../modal-loader/ModalLoader';
|
||||||
|
import OntimeModalFooter from '../OntimeModalFooter';
|
||||||
|
|
||||||
|
import SubscriptionRow from './SubscriptionRow';
|
||||||
|
|
||||||
|
import styles from '../Modal.module.scss';
|
||||||
|
|
||||||
|
type OntimeCycle = keyof typeof TimerLifeCycle;
|
||||||
|
|
||||||
|
const sectionText: { [key in TimerLifeCycle]: { title: string; subtitle: string } } = {
|
||||||
|
onLoad: {
|
||||||
|
title: 'On Load',
|
||||||
|
subtitle: 'Triggers when a timer is loaded',
|
||||||
|
},
|
||||||
|
onStart: {
|
||||||
|
title: 'On Start',
|
||||||
|
subtitle: 'Triggers when a timer starts',
|
||||||
|
},
|
||||||
|
onPause: {
|
||||||
|
title: 'On Pause',
|
||||||
|
subtitle: 'Triggers when a running timer is paused',
|
||||||
|
},
|
||||||
|
onStop: {
|
||||||
|
title: 'On Stop',
|
||||||
|
subtitle: 'Triggers when a running timer is stopped',
|
||||||
|
},
|
||||||
|
onUpdate: {
|
||||||
|
title: 'On Every Second',
|
||||||
|
subtitle: 'Triggers when a running timer is updated (at least once a second, can be more)',
|
||||||
|
},
|
||||||
|
onFinish: {
|
||||||
|
title: 'On Finish',
|
||||||
|
subtitle: 'Triggers when a running reaches 0',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function HttpIntegration() {
|
||||||
|
const { data, isFetching } = useHttpSettings();
|
||||||
|
const { mutateAsync } = usePostHttpSubscriptions();
|
||||||
|
const { emitError } = useEmitLog();
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
handleSubmit,
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
formState: { isSubmitting, isDirty, isValid },
|
||||||
|
} = useForm<Subscription>({
|
||||||
|
defaultValues: data.subscriptions,
|
||||||
|
values: data.subscriptions,
|
||||||
|
resetOptions: {
|
||||||
|
keepDirtyValues: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [showSection, setShowSection] = useState<OntimeCycle>(TimerLifeCycle.onLoad);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
reset(data.subscriptions);
|
||||||
|
}
|
||||||
|
}, [data, reset]);
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
reset(data.subscriptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = async (values: Subscription) => {
|
||||||
|
try {
|
||||||
|
const subscriptions = {
|
||||||
|
onLoad: values.onLoad ?? [],
|
||||||
|
onStart: values.onStart ?? [],
|
||||||
|
onPause: values.onPause ?? [],
|
||||||
|
onStop: values.onStop ?? [],
|
||||||
|
onUpdate: values.onUpdate ?? [],
|
||||||
|
onFinish: values.onFinish ?? [],
|
||||||
|
};
|
||||||
|
|
||||||
|
await mutateAsync(subscriptions);
|
||||||
|
} catch (error) {
|
||||||
|
emitError(`Error setting HTML: ${error}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isFetching) {
|
||||||
|
return <ModalLoader />;
|
||||||
|
}
|
||||||
|
const placeholder = 'http://x.x.x.x:xxxx/api/path'
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)} className={styles.sectionContainer} id='http-subscriptions'>
|
||||||
|
<SubscriptionRow
|
||||||
|
cycle={TimerLifeCycle.onLoad}
|
||||||
|
title={sectionText.onLoad.title}
|
||||||
|
subtitle={sectionText.onLoad.subtitle}
|
||||||
|
visible={showSection === TimerLifeCycle.onLoad}
|
||||||
|
setShowSection={setShowSection}
|
||||||
|
register={register}
|
||||||
|
control={control}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
<SubscriptionRow
|
||||||
|
cycle={TimerLifeCycle.onStart}
|
||||||
|
title={sectionText.onStart.title}
|
||||||
|
subtitle={sectionText.onStart.subtitle}
|
||||||
|
visible={showSection === TimerLifeCycle.onStart}
|
||||||
|
setShowSection={setShowSection}
|
||||||
|
register={register}
|
||||||
|
control={control}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
<SubscriptionRow
|
||||||
|
cycle={TimerLifeCycle.onPause}
|
||||||
|
title={sectionText.onPause.title}
|
||||||
|
subtitle={sectionText.onPause.subtitle}
|
||||||
|
visible={showSection === TimerLifeCycle.onPause}
|
||||||
|
setShowSection={setShowSection}
|
||||||
|
register={register}
|
||||||
|
control={control}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
<SubscriptionRow
|
||||||
|
cycle={TimerLifeCycle.onStop}
|
||||||
|
title={sectionText.onStop.title}
|
||||||
|
subtitle={sectionText.onStop.subtitle}
|
||||||
|
visible={showSection === TimerLifeCycle.onStop}
|
||||||
|
setShowSection={setShowSection}
|
||||||
|
register={register}
|
||||||
|
control={control}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
<SubscriptionRow
|
||||||
|
cycle={TimerLifeCycle.onUpdate}
|
||||||
|
title={sectionText.onUpdate.title}
|
||||||
|
subtitle={sectionText.onUpdate.subtitle}
|
||||||
|
visible={showSection === TimerLifeCycle.onUpdate}
|
||||||
|
setShowSection={setShowSection}
|
||||||
|
register={register}
|
||||||
|
control={control}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
<SubscriptionRow
|
||||||
|
cycle={TimerLifeCycle.onFinish}
|
||||||
|
title={sectionText.onFinish.title}
|
||||||
|
subtitle={sectionText.onFinish.subtitle}
|
||||||
|
visible={showSection === TimerLifeCycle.onFinish}
|
||||||
|
setShowSection={setShowSection}
|
||||||
|
register={register}
|
||||||
|
control={control}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
<OntimeModalFooter
|
||||||
|
formId='http-subscriptions'
|
||||||
|
handleRevert={resetForm}
|
||||||
|
isDirty={isDirty}
|
||||||
|
isValid={isValid}
|
||||||
|
isSubmitting={isSubmitting}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ import ModalWrapper from '../ModalWrapper';
|
|||||||
import OscIntegration from './OscIntegration';
|
import OscIntegration from './OscIntegration';
|
||||||
import OscSettings from './OscSettings';
|
import OscSettings from './OscSettings';
|
||||||
|
|
||||||
|
import HttpIntegration from './HttpIntegration';
|
||||||
|
|
||||||
import styles from '../Modal.module.scss';
|
import styles from '../Modal.module.scss';
|
||||||
|
|
||||||
interface IntegrationModalProps {
|
interface IntegrationModalProps {
|
||||||
@@ -30,6 +32,7 @@ export default function IntegrationModal(props: IntegrationModalProps) {
|
|||||||
<TabList>
|
<TabList>
|
||||||
<Tab>OSC</Tab>
|
<Tab>OSC</Tab>
|
||||||
<Tab>OSC Integration</Tab>
|
<Tab>OSC Integration</Tab>
|
||||||
|
<Tab>HTML Integration</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
@@ -38,6 +41,9 @@ export default function IntegrationModal(props: IntegrationModalProps) {
|
|||||||
<TabPanel>
|
<TabPanel>
|
||||||
<OscIntegration />
|
<OscIntegration />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
<TabPanel>
|
||||||
|
<HttpIntegration />
|
||||||
|
</TabPanel>
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|||||||
Reference in New Issue
Block a user