mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-21 23:19:09 +00:00
feat: starting to cleanup
This commit is contained in:
@@ -72,14 +72,6 @@ export async function getAliases(): Promise<Alias[]> {
|
|||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description HTTP request to mutate aliases
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
export async function postAliases(data: Alias[]) {
|
|
||||||
return axios.post(`${ontimeURL}/aliases`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description HTTP request to create an alias
|
* @description HTTP request to create an alias
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
|
|||||||
@@ -1,180 +0,0 @@
|
|||||||
import { useEffect } from 'react';
|
|
||||||
import { useFieldArray, useForm } from 'react-hook-form';
|
|
||||||
import { Alert, AlertDescription, AlertIcon, AlertTitle, Button, IconButton, Input, Switch } from '@chakra-ui/react';
|
|
||||||
import { IoOpenOutline } from '@react-icons/all-files/io5/IoOpenOutline';
|
|
||||||
import { IoRemove } from '@react-icons/all-files/io5/IoRemove';
|
|
||||||
import { Alias } from 'ontime-types';
|
|
||||||
|
|
||||||
import { logAxiosError } from '../../../common/api/apiUtils';
|
|
||||||
import { postAliases } from '../../../common/api/ontimeApi';
|
|
||||||
import TooltipActionBtn from '../../../common/components/buttons/TooltipActionBtn';
|
|
||||||
import useAliases from '../../../common/hooks-query/useAliases';
|
|
||||||
import { useEmitLog } from '../../../common/stores/logger';
|
|
||||||
import { handleLinks } from '../../../common/utils/linkUtils';
|
|
||||||
import ModalLoader from '../modal-loader/ModalLoader';
|
|
||||||
import { inputProps } from '../modalHelper';
|
|
||||||
import ModalLink from '../ModalLink';
|
|
||||||
import OntimeModalFooter from '../OntimeModalFooter';
|
|
||||||
|
|
||||||
import style from './SettingsModal.module.scss';
|
|
||||||
|
|
||||||
const aliasesDocsUrl = 'https://ontime.gitbook.io/v2/features/url-aliases';
|
|
||||||
|
|
||||||
// we wrap the array in an object to be simplify react-hook-form
|
|
||||||
type Aliases = {
|
|
||||||
aliases: Alias[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function AliasesForm() {
|
|
||||||
const { data, status, isFetching, refetch } = useAliases();
|
|
||||||
const { emitError } = useEmitLog();
|
|
||||||
const {
|
|
||||||
control,
|
|
||||||
handleSubmit,
|
|
||||||
register,
|
|
||||||
reset,
|
|
||||||
formState: { isSubmitting, isDirty, isValid },
|
|
||||||
} = useForm<Aliases>({
|
|
||||||
defaultValues: { aliases: data },
|
|
||||||
values: { aliases: data || [] },
|
|
||||||
resetOptions: {
|
|
||||||
keepDirtyValues: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const { fields, append, remove } = useFieldArray({
|
|
||||||
name: 'aliases',
|
|
||||||
control,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (data) {
|
|
||||||
reset({ aliases: data });
|
|
||||||
}
|
|
||||||
}, [data, reset]);
|
|
||||||
|
|
||||||
const onSubmit = async (formData: Aliases) => {
|
|
||||||
try {
|
|
||||||
await postAliases(formData.aliases);
|
|
||||||
} catch (error) {
|
|
||||||
logAxiosError('Error saving aliases', error);
|
|
||||||
} finally {
|
|
||||||
await refetch();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onReset = () => {
|
|
||||||
reset({ aliases: data });
|
|
||||||
};
|
|
||||||
|
|
||||||
const addNew = () => {
|
|
||||||
if (fields.length > 20) {
|
|
||||||
emitError('Maximum amount of aliases reached (20)');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
append({
|
|
||||||
enabled: false,
|
|
||||||
alias: '',
|
|
||||||
pathAndParams: '',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const disableInputs = status === 'pending';
|
|
||||||
const hasTooManyOptions = fields.length >= 20;
|
|
||||||
|
|
||||||
if (isFetching) {
|
|
||||||
return <ModalLoader />;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log({ fields });
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={handleSubmit(onSubmit)} id='aliases' className={style.sectionContainer}>
|
|
||||||
<div style={{ height: '16px' }} />
|
|
||||||
<Alert status='info' variant='ontime-on-light-info'>
|
|
||||||
<AlertIcon />
|
|
||||||
<div className={style.column}>
|
|
||||||
<AlertTitle>URL Aliases</AlertTitle>
|
|
||||||
<AlertDescription>
|
|
||||||
Custom aliases allow providing a short name for any ontime URL. <br />
|
|
||||||
It serves two primary purposes: <br />
|
|
||||||
- Providing dynamic URLs for automation or unattended screens <br />- Simplifying complex URLs
|
|
||||||
<ModalLink href={aliasesDocsUrl}>For more information, see the docs</ModalLink>
|
|
||||||
</AlertDescription>
|
|
||||||
</div>
|
|
||||||
</Alert>
|
|
||||||
<div style={{ height: '16px' }} />
|
|
||||||
<ul className={style.aliases}>
|
|
||||||
{fields.map((alias, index) => {
|
|
||||||
return (
|
|
||||||
<li className={style.aliasRow} key={alias.id}>
|
|
||||||
<IconButton
|
|
||||||
onClick={() => remove(index)}
|
|
||||||
aria-label='delete'
|
|
||||||
size='xs'
|
|
||||||
icon={<IoRemove />}
|
|
||||||
colorScheme='red'
|
|
||||||
isDisabled={disableInputs}
|
|
||||||
data-testid={`field__delete_${index}`}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
{...inputProps}
|
|
||||||
{...register(`aliases.${index}.alias`)}
|
|
||||||
width='12em'
|
|
||||||
size='xs'
|
|
||||||
variant='ontime-filled-on-light'
|
|
||||||
placeholder='URL Alias'
|
|
||||||
isDisabled={disableInputs}
|
|
||||||
data-testid={`field__alias_${index}`}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
{...inputProps}
|
|
||||||
{...register(`aliases.${index}.pathAndParams`)}
|
|
||||||
className={style.grow}
|
|
||||||
size='xs'
|
|
||||||
variant='ontime-filled-on-light'
|
|
||||||
placeholder='URL (portion after ontime Port)'
|
|
||||||
isDisabled={disableInputs}
|
|
||||||
data-testid={`field__url_${index}`}
|
|
||||||
/>
|
|
||||||
<TooltipActionBtn
|
|
||||||
clickHandler={(event) => handleLinks(event, alias.alias)}
|
|
||||||
tooltip='Test alias'
|
|
||||||
aria-label='Test alias'
|
|
||||||
size='xs'
|
|
||||||
variant='ontime-ghost-on-light'
|
|
||||||
icon={<IoOpenOutline />}
|
|
||||||
colorScheme='red'
|
|
||||||
isDisabled={disableInputs}
|
|
||||||
data-testid={`field__test_${index}`}
|
|
||||||
/>
|
|
||||||
<Switch
|
|
||||||
{...register(`aliases.${index}.enabled`)}
|
|
||||||
variant='ontime-on-light'
|
|
||||||
isDisabled={disableInputs}
|
|
||||||
data-testid={`field__enable_${index}`}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
<Button
|
|
||||||
onClick={addNew}
|
|
||||||
className={style.shiftRight}
|
|
||||||
isDisabled={hasTooManyOptions}
|
|
||||||
size='xs'
|
|
||||||
colorScheme='blue'
|
|
||||||
variant='outline'
|
|
||||||
padding='0 2em'
|
|
||||||
>
|
|
||||||
Add new
|
|
||||||
</Button>
|
|
||||||
<OntimeModalFooter
|
|
||||||
formId='aliases'
|
|
||||||
handleRevert={onReset}
|
|
||||||
isDirty={isDirty}
|
|
||||||
isValid={isValid}
|
|
||||||
isSubmitting={isSubmitting}
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,6 @@ import { ModalBody, Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/r
|
|||||||
|
|
||||||
import ModalWrapper from '../ModalWrapper';
|
import ModalWrapper from '../ModalWrapper';
|
||||||
|
|
||||||
import AliasesForm from './AliasesForm';
|
|
||||||
import AppSettingsModal from './AppSettings';
|
import AppSettingsModal from './AppSettings';
|
||||||
import CuesheetSettingsForm from './CuesheetSettingsForm';
|
import CuesheetSettingsForm from './CuesheetSettingsForm';
|
||||||
import EditorSettings from './EditorSettings';
|
import EditorSettings from './EditorSettings';
|
||||||
@@ -44,9 +43,6 @@ export default function SettingsModal(props: ModalManagerProps) {
|
|||||||
<TabPanel>
|
<TabPanel>
|
||||||
<ViewSettingsForm />
|
<ViewSettingsForm />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
|
||||||
<AliasesForm />
|
|
||||||
</TabPanel>
|
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ export class DataProvider {
|
|||||||
return data.aliases;
|
return data.aliases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove this when I change the data model
|
||||||
static async setAliases(newData: Alias[]) {
|
static async setAliases(newData: Alias[]) {
|
||||||
data.aliases = newData;
|
data.aliases = newData;
|
||||||
await this.persist();
|
await this.persist();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { LogOrigin } from 'ontime-types';
|
import { LogOrigin } from 'ontime-types';
|
||||||
import type {
|
import type {
|
||||||
Alias,
|
|
||||||
DatabaseModel,
|
DatabaseModel,
|
||||||
GetInfo,
|
GetInfo,
|
||||||
HttpSettings,
|
HttpSettings,
|
||||||
@@ -19,7 +18,7 @@ import { copyFile, rename, writeFile } from 'fs/promises';
|
|||||||
|
|
||||||
import { fileHandler } from '../utils/parser.js';
|
import { fileHandler } from '../utils/parser.js';
|
||||||
import { DataProvider } from '../classes/data-provider/DataProvider.js';
|
import { DataProvider } from '../classes/data-provider/DataProvider.js';
|
||||||
import { failEmptyObjects, failIsNotArray } from '../utils/routerUtils.js';
|
import { failEmptyObjects } from '../utils/routerUtils.js';
|
||||||
import { runtimeService } from '../services/runtime-service/RuntimeService.js';
|
import { runtimeService } from '../services/runtime-service/RuntimeService.js';
|
||||||
import { eventStore } from '../stores/EventStore.js';
|
import { eventStore } from '../stores/EventStore.js';
|
||||||
import {
|
import {
|
||||||
@@ -167,28 +166,6 @@ export const getAliases = async (_req: Request, res: Response) => {
|
|||||||
res.status(200).send(aliases);
|
res.status(200).send(aliases);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create controller for POST request to '/ontime/aliases'
|
|
||||||
// Returns ACK message
|
|
||||||
export const postAliases = async (req: Request, res: Response) => {
|
|
||||||
if (failIsNotArray(req.body, res)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const newAliases: Alias[] = [];
|
|
||||||
req.body.forEach((a) => {
|
|
||||||
newAliases.push({
|
|
||||||
enabled: a.enabled,
|
|
||||||
alias: a.alias,
|
|
||||||
pathAndParams: a.pathAndParams,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
await DataProvider.setAliases(newAliases);
|
|
||||||
res.status(200).send(newAliases);
|
|
||||||
} catch (error) {
|
|
||||||
res.status(400).send({ message: String(error) });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create controller for POST request to '/ontime/aliases'
|
// Create controller for POST request to '/ontime/aliases'
|
||||||
// Returns ACK message
|
// Returns ACK message
|
||||||
export const postAlias = async (req: Request, res: Response) => {
|
export const postAlias = async (req: Request, res: Response) => {
|
||||||
|
|||||||
@@ -87,9 +87,6 @@ router.post('/views', viewValidator, postViewSettings);
|
|||||||
// create route between controller and '/ontime/aliases' endpoint
|
// create route between controller and '/ontime/aliases' endpoint
|
||||||
router.get('/aliases', getAliases);
|
router.get('/aliases', getAliases);
|
||||||
|
|
||||||
// // create route between controller and '/ontime/aliases' endpoint
|
|
||||||
// router.post('/aliases', validateAliases, postAliases);
|
|
||||||
|
|
||||||
// create route between controller and '/ontime/aliases' endpoint
|
// create route between controller and '/ontime/aliases' endpoint
|
||||||
router.post('/aliases', validateCreateAlias, postAlias);
|
router.post('/aliases', validateCreateAlias, postAlias);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user