mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-14 20:03:52 +00:00
deffiretiate main and custom edits
This commit is contained in:
@@ -20,8 +20,17 @@ export async function generateUrl(
|
||||
baseUrl: string,
|
||||
path: string,
|
||||
lock: boolean,
|
||||
lockMainFields: boolean,
|
||||
lockCustomFields: boolean,
|
||||
authenticate: boolean,
|
||||
): Promise<string> {
|
||||
const res = await axios.post(`${sessionPath}/url`, { baseUrl, path, lock, authenticate });
|
||||
const res = await axios.post(`${sessionPath}/url`, {
|
||||
baseUrl,
|
||||
path,
|
||||
lock,
|
||||
lockMainFields,
|
||||
lockCustomFields,
|
||||
authenticate,
|
||||
});
|
||||
return res.data.url;
|
||||
}
|
||||
|
||||
@@ -45,11 +45,14 @@ export function getRouteFromPreset(location: Path, urlPresets: URLPreset[]): str
|
||||
const locked = searchParams.get('locked');
|
||||
const token = searchParams.get('token');
|
||||
|
||||
const lmain = searchParams.get('lmain');
|
||||
const lcustom = searchParams.get('lcustom');
|
||||
|
||||
// we need to check if the whole url is an alias
|
||||
const foundPreset = urlPresets.find((preset) => preset.alias === removeTrailingSlash(currentURL) && preset.enabled);
|
||||
if (foundPreset) {
|
||||
// if so, we can redirect to the preset path
|
||||
return generatePathFromPreset(foundPreset.pathAndParams, foundPreset.alias, locked, token);
|
||||
return generatePathFromPreset(foundPreset.pathAndParams, foundPreset.alias, locked, token, lmain, lcustom);
|
||||
}
|
||||
|
||||
// if the current url is not an alias, we check if the alias is in the search parameters
|
||||
@@ -63,7 +66,7 @@ export function getRouteFromPreset(location: Path, urlPresets: URLPreset[]): str
|
||||
for (const preset of urlPresets) {
|
||||
// if the page has a known enabled alias, we check if we need to redirect
|
||||
if (preset.alias === presetOnPage && preset.enabled) {
|
||||
const newPath = generatePathFromPreset(preset.pathAndParams, preset.alias, locked, token);
|
||||
const newPath = generatePathFromPreset(preset.pathAndParams, preset.alias, locked, token, lmain, lcustom);
|
||||
if (!arePathsEquivalent(currentPath, newPath)) {
|
||||
// if current path is out of date
|
||||
// return new path so we can redirect
|
||||
@@ -77,7 +80,14 @@ export function getRouteFromPreset(location: Path, urlPresets: URLPreset[]): str
|
||||
/**
|
||||
* Handles generating a path and search parameters from a preset
|
||||
*/
|
||||
export function generatePathFromPreset(pathAndParams: string, alias: string, locked: string | null, token: string | null ): string {
|
||||
export function generatePathFromPreset(
|
||||
pathAndParams: string,
|
||||
alias: string,
|
||||
locked: string | null,
|
||||
token: string | null,
|
||||
lmain: string | null,
|
||||
lcustom: string | null,
|
||||
): string {
|
||||
const path = resolvePath(pathAndParams);
|
||||
const searchParams = new URLSearchParams(path.search);
|
||||
|
||||
@@ -93,6 +103,14 @@ export function generatePathFromPreset(pathAndParams: string, alias: string, loc
|
||||
searchParams.set('token', token);
|
||||
}
|
||||
|
||||
if (lmain) {
|
||||
searchParams.set('lmain', lmain);
|
||||
}
|
||||
|
||||
if (lcustom) {
|
||||
searchParams.set('lcustom', lcustom);
|
||||
}
|
||||
|
||||
// return path concatenated without the leading slash
|
||||
return `${path.pathname}?${searchParams}`.substring(1);
|
||||
}
|
||||
@@ -106,16 +124,16 @@ export function generatePathFromPreset(pathAndParams: string, alias: string, loc
|
||||
export function arePathsEquivalent(currentPath: string, newPath: string): boolean {
|
||||
const currentUrl = new URL(currentPath, document.location.origin);
|
||||
const newUrl = new URL(newPath, document.location.origin);
|
||||
|
||||
|
||||
// check path
|
||||
if (currentUrl.pathname !== newUrl.pathname) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
// check search params
|
||||
// if the params match, we dont need further checks
|
||||
if (currentUrl.searchParams.toString() === newUrl.searchParams.toString()) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
// if there is no match, we check the edge cases for the url sharing feature
|
||||
|
||||
+2
-1
@@ -31,7 +31,8 @@ declare module '@tanstack/react-table' {
|
||||
options: {
|
||||
showDelayedTimes: boolean;
|
||||
hideTableSeconds: boolean;
|
||||
allowEdits: boolean;
|
||||
allowMainEdits: boolean;
|
||||
allowCustomEdits: boolean;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ interface GenerateLinkFormOptions {
|
||||
baseUrl: string;
|
||||
path: string;
|
||||
lock: boolean;
|
||||
lockMainFields: boolean;
|
||||
lockCustomFields: boolean;
|
||||
authenticate: boolean;
|
||||
}
|
||||
|
||||
@@ -35,13 +37,15 @@ export default function GenerateLinkForm() {
|
||||
handleSubmit,
|
||||
register,
|
||||
setError,
|
||||
formState: { errors },
|
||||
formState: { errors, dirtyFields },
|
||||
} = useForm<GenerateLinkFormOptions>({
|
||||
mode: 'onChange',
|
||||
defaultValues: {
|
||||
baseUrl: currentHostName,
|
||||
path: '',
|
||||
lock: false,
|
||||
lockMainFields: false,
|
||||
lockCustomFields: false,
|
||||
authenticate: false,
|
||||
},
|
||||
resetOptions: {
|
||||
@@ -53,7 +57,14 @@ export default function GenerateLinkForm() {
|
||||
try {
|
||||
setFormState('loading');
|
||||
const baseUrl = linkToOtherHost(options.baseUrl);
|
||||
const url = await generateUrl(baseUrl, options.path, options.lock, options.authenticate);
|
||||
const url = await generateUrl(
|
||||
baseUrl,
|
||||
options.path,
|
||||
options.lock,
|
||||
options.lockMainFields,
|
||||
options.lockCustomFields,
|
||||
options.authenticate,
|
||||
);
|
||||
await copyToClipboard(url);
|
||||
setUrl(url);
|
||||
setFormState('success');
|
||||
@@ -119,6 +130,18 @@ export default function GenerateLinkForm() {
|
||||
/>
|
||||
<Switch variant='ontime' size='lg' {...register('lock')} />
|
||||
</Panel.ListItem>
|
||||
{dirtyFields.lock && (
|
||||
<>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field title='Lock main field edits' description='Prevent edits to main fields' />
|
||||
<Switch variant='ontime' size='lg' {...register('lockMainFields')} />
|
||||
</Panel.ListItem>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field title='Lock custom field edits' description='Prevent edits to custom fields' />
|
||||
<Switch variant='ontime' size='lg' {...register('lockCustomFields')} />
|
||||
</Panel.ListItem>
|
||||
</>
|
||||
)}
|
||||
<Panel.ListItem>
|
||||
<Panel.Field title='Authenticate' description='Whether the URL should be pre-authenticated' />
|
||||
<Switch variant='ontime' size='lg' {...register('authenticate')} />
|
||||
|
||||
@@ -27,7 +27,8 @@ export default function CuesheetTable(props: CuesheetTableProps) {
|
||||
|
||||
const { updateEvent, updateTimer } = useEventAction();
|
||||
const [searchParams] = useSearchParams();
|
||||
const blockEdits = searchParams.get('locked') ?? false;
|
||||
const allowMainEdits = !searchParams.get('lmain');
|
||||
const allowCustomEdits = !searchParams.get('lcustom');
|
||||
|
||||
const { followSelected, showDelayedTimes, hideTableSeconds } = useCuesheetOptions();
|
||||
const { columnVisibility, columnOrder, columnSizing, resetColumnOrder, setColumnVisibility, setColumnSizing } =
|
||||
@@ -81,7 +82,8 @@ export default function CuesheetTable(props: CuesheetTableProps) {
|
||||
options: {
|
||||
showDelayedTimes,
|
||||
hideTableSeconds,
|
||||
allowEdits: !blockEdits,
|
||||
allowMainEdits,
|
||||
allowCustomEdits,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
+6
-6
@@ -37,7 +37,7 @@ function MakeStart({ getValue, row, table }: CellContext<OntimeRundownEntry, unk
|
||||
onSubmit={update}
|
||||
lockedValue={isStartLocked}
|
||||
delayed={delayValue !== 0}
|
||||
allowEdits={table.options.meta?.options.allowEdits}
|
||||
allowEdits={table.options.meta?.options.allowMainEdits}
|
||||
>
|
||||
{formattedTime}
|
||||
<DelayIndicator delayValue={delayValue} tooltipPrefix={millisToString(startTime)} />
|
||||
@@ -71,7 +71,7 @@ function MakeEnd({ getValue, row, table }: CellContext<OntimeRundownEntry, unkno
|
||||
onSubmit={update}
|
||||
lockedValue={isEndLocked}
|
||||
delayed={delayValue !== 0}
|
||||
allowEdits={table.options.meta?.options.allowEdits}
|
||||
allowEdits={table.options.meta?.options.allowMainEdits}
|
||||
>
|
||||
{formattedTime}
|
||||
<DelayIndicator delayValue={delayValue} tooltipPrefix={millisToString(endTime)} />
|
||||
@@ -97,7 +97,7 @@ function MakeDuration({ getValue, row, table }: CellContext<OntimeRundownEntry,
|
||||
initialValue={duration}
|
||||
onSubmit={update}
|
||||
lockedValue={isDurationLocked}
|
||||
allowEdits={table.options.meta?.options.allowEdits}
|
||||
allowEdits={table.options.meta?.options.allowMainEdits}
|
||||
>
|
||||
{formattedDuration}
|
||||
</TimeInput>
|
||||
@@ -124,7 +124,7 @@ function MakeMultiLineField({ row, column, table }: CellContext<OntimeRundownEnt
|
||||
<MultiLineCell
|
||||
initialValue={initialValue}
|
||||
handleUpdate={update}
|
||||
allowEdits={table.options.meta?.options.allowEdits}
|
||||
allowEdits={table.options.meta?.options.allowMainEdits}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -167,7 +167,7 @@ function MakeSingleLineField({ row, column, table }: CellContext<OntimeRundownEn
|
||||
<SingleLineCell
|
||||
initialValue={initialValue}
|
||||
handleUpdate={update}
|
||||
allowEdits={table.options.meta?.options.allowEdits}
|
||||
allowEdits={table.options.meta?.options.allowMainEdits}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -191,7 +191,7 @@ function MakeCustomField({ row, column, table }: CellContext<OntimeRundownEntry,
|
||||
<MultiLineCell
|
||||
initialValue={initialValue}
|
||||
handleUpdate={update}
|
||||
allowEdits={table.options.meta?.options.allowEdits}
|
||||
allowEdits={table.options.meta?.options.allowCustomEdits}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ export async function generateUrl(req: Request, res: Response<GetUrl | ErrorResp
|
||||
req.body.baseUrl,
|
||||
req.body.path,
|
||||
req.body.lock,
|
||||
req.body.lockMainFields,
|
||||
req.body.lockCustomFields,
|
||||
req.body.authenticate,
|
||||
);
|
||||
res.status(200).send({ url: url.toString() });
|
||||
|
||||
@@ -59,6 +59,8 @@ export function generateAuthenticatedUrl(
|
||||
baseUrl: string,
|
||||
path: string,
|
||||
lock: boolean,
|
||||
lockMainFields: boolean,
|
||||
lockCustomFields: boolean,
|
||||
authenticate: boolean,
|
||||
prefix = routerPrefix,
|
||||
hash = hashedPassword,
|
||||
@@ -72,5 +74,11 @@ export function generateAuthenticatedUrl(
|
||||
if (lock) {
|
||||
url.searchParams.append('locked', 'true');
|
||||
}
|
||||
if (lockMainFields) {
|
||||
url.searchParams.append('lmain', 'true');
|
||||
}
|
||||
if (lockCustomFields) {
|
||||
url.searchParams.append('lcustom', 'true');
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ export const validateGenerateUrl = [
|
||||
body('baseUrl').exists().isString().notEmpty().trim(),
|
||||
body('path').exists().isString().trim(),
|
||||
body('lock').exists().isBoolean(),
|
||||
body('lockMainFields').exists().isBoolean(),
|
||||
body('lockCustomFields').exists().isBoolean(),
|
||||
body('authenticate').exists().isBoolean(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
|
||||
Reference in New Issue
Block a user