feat: allow user to duplicate a rundown

This commit is contained in:
Carlos Valente
2025-10-26 13:35:10 +01:00
committed by Carlos Valente
parent 17f80baf48
commit 32bf0f53f6
6 changed files with 97 additions and 5 deletions
+7
View File
@@ -38,6 +38,13 @@ export async function createRundown(title: string): Promise<AxiosResponse<Projec
return axios.post(rundownPath, { title });
}
/**
* HTTP request to duplicate an existing rundown
*/
export async function duplicateRundown(rundownId: RundownId): Promise<AxiosResponse<ProjectRundownsList>> {
return axios.post(`${rundownPath}/${rundownId}/duplicate`);
}
/**
* HTTP request to delete a rundown
*/
@@ -3,7 +3,7 @@ import { ProjectRundownsList } from 'ontime-types';
import { queryRefetchIntervalSlow } from '../../ontimeConfig';
import { PROJECT_RUNDOWNS } from '../api/constants';
import { createRundown, deleteRundown, fetchProjectRundownList, loadRundown } from '../api/rundown';
import { createRundown, deleteRundown, duplicateRundown, fetchProjectRundownList, loadRundown } from '../api/rundown';
/**
* Project rundowns
@@ -30,6 +30,16 @@ export function useMutateProjectRundowns() {
ontimeQueryClient.setQueryData(PROJECT_RUNDOWNS, response.data);
},
});
const { mutateAsync: duplicate } = useMutation({
mutationFn: duplicateRundown,
onMutate: () => {
ontimeQueryClient.cancelQueries({ queryKey: PROJECT_RUNDOWNS });
},
onSuccess: (response) => {
ontimeQueryClient.setQueryData(PROJECT_RUNDOWNS, response.data);
},
});
const { mutateAsync: remove } = useMutation({
mutationFn: deleteRundown,
@@ -51,5 +61,5 @@ export function useMutateProjectRundowns() {
},
});
return { create, remove, load };
return { create, duplicate, remove, load };
}
@@ -1,5 +1,5 @@
import { useState } from 'react';
import { IoAdd, IoDocumentOutline, IoDownloadOutline, IoEllipsisHorizontal, IoTrash } from 'react-icons/io5';
import { IoAdd, IoDocumentOutline, IoDownloadOutline, IoDuplicateOutline, IoEllipsisHorizontal, IoTrash } from 'react-icons/io5';
import { useDisclosure } from '@mantine/hooks';
import { downloadAsExcel } from '../../../../common/api/excel';
@@ -19,7 +19,7 @@ import style from './ManagePanel.module.scss';
export default function ManageRundowns() {
const { data } = useProjectRundowns();
const { remove, load } = useMutateProjectRundowns();
const { duplicate, remove, load } = useMutateProjectRundowns();
const [isOpenDelete, deleteHandlers] = useDisclosure();
const [isOpenLoad, loadHandlers] = useDisclosure();
const [isNewLoad, newHandlers] = useDisclosure();
@@ -48,6 +48,18 @@ export default function ManageRundowns() {
}
};
const submitRundownDuplicate = async (id: string) => {
setActionError(null);
setRenamingRundown(null);
setTargetRundown('');
try {
await duplicate(id);
} catch (error) {
setActionError(`Failed to duplicate rundown. ${maybeAxiosError(error)}`);
}
};
const submitRundownDelete = async () => {
try {
await remove(targetRundown);
@@ -117,6 +129,13 @@ export default function ManageRundowns() {
label: 'Download .xlsx',
onClick: () => handleDownloadXlsx(id, title),
},
{
type: 'item',
icon: IoDuplicateOutline,
label: 'Duplicate',
onClick: () => submitRundownDuplicate(id),
},
{ type: 'divider' },
{
type: 'item',
icon: IoTrash,