From cf269e42854864c19981503b1efe070261fa6792 Mon Sep 17 00:00:00 2001 From: malmen237 Date: Wed, 16 Oct 2024 13:14:51 +0200 Subject: [PATCH 1/4] feat: possibility to delete layouts from production --- src/api/manager/multiviews.ts | 10 +++ src/app/api/manager/multiviews/[id]/route.ts | 30 ++++++- .../MultiviewLayoutSettings.tsx | 90 ++++++++++++++++--- .../MultiviewSettings.tsx | 2 +- src/hooks/multiviewLayout.ts | 25 +++++- src/i18n/locales/en.ts | 5 +- src/i18n/locales/sv.ts | 5 +- 7 files changed, 148 insertions(+), 19 deletions(-) diff --git a/src/api/manager/multiviews.ts b/src/api/manager/multiviews.ts index cf845092..dafff9a5 100644 --- a/src/api/manager/multiviews.ts +++ b/src/api/manager/multiviews.ts @@ -1,6 +1,7 @@ import { ObjectId, WithId } from 'mongodb'; import { MultiviewPreset } from '../../interfaces/preset'; import { getDatabase } from '../mongoClient/dbClient'; +import { Log } from '../logger'; export async function getMultiviewLayouts(): Promise { const db = await getDatabase(); @@ -36,3 +37,12 @@ export async function putMultiviewLayout( await collection.insertOne({ ...newMultiviewLayout, _id: new ObjectId() }); } } + +export async function deleteLayout(id: string): Promise { + const db = await getDatabase(); + + await db.collection('multiviews').deleteOne({ + _id: { $eq: new ObjectId(id) } + }); + Log().info('Deleted multiview layout', id); +} diff --git a/src/app/api/manager/multiviews/[id]/route.ts b/src/app/api/manager/multiviews/[id]/route.ts index 139ff567..3e65b078 100644 --- a/src/app/api/manager/multiviews/[id]/route.ts +++ b/src/app/api/manager/multiviews/[id]/route.ts @@ -3,7 +3,10 @@ import { isAuthenticated } from '../../../../../api/manager/auth'; import { Params } from 'next/dist/shared/lib/router/utils/route-matcher'; import { updateMultiviewForPipeline } from '../../../../../api/ateliereLive/pipelines/multiviews/multiviews'; import { MultiviewViews } from '../../../../../interfaces/multiview'; -import { getMultiviewLayout } from '../../../../../api/manager/multiviews'; +import { + deleteLayout, + getMultiviewLayout +} from '../../../../../api/manager/multiviews'; type PutMultiviewRequest = { pipelineId: string; @@ -52,3 +55,28 @@ export async function PUT( }); } } + +export async function DELETE( + request: NextRequest, + { params }: { params: Params } +): Promise { + if (!(await isAuthenticated())) { + return new NextResponse(`Not Authorized!`, { + status: 403 + }); + } + try { + await deleteLayout(params.id); + return new NextResponse(null, { + status: 200 + }); + } catch (error) { + console.log(error); + return new NextResponse( + `Error occurred while posting to DB! Error: ${error}`, + { + status: 500 + } + ); + } +} diff --git a/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayoutSettings.tsx b/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayoutSettings.tsx index 5e370148..b515b797 100644 --- a/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayoutSettings.tsx +++ b/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayoutSettings.tsx @@ -3,7 +3,10 @@ import { useMultiviewPresets } from '../../../../hooks/multiviewPreset'; import { MultiviewPreset } from '../../../../interfaces/preset'; import { useTranslate } from '../../../../i18n/useTranslate'; import { useSetupMultiviewLayout } from '../../../../hooks/useSetupMultiviewLayout'; -import { useMultiviewLayouts } from '../../../../hooks/multiviewLayout'; +import { + useDeleteMultiviewLayout, + useMultiviewLayouts +} from '../../../../hooks/multiviewLayout'; import { Production } from '../../../../interfaces/production'; import { useConfigureMultiviewLayout } from '../../../../hooks/useConfigureMultiviewLayout'; import { TMultiviewLayout } from '../../../../interfaces/preset'; @@ -12,6 +15,9 @@ import { TListSource } from '../../../../interfaces/multiview'; import Options from '../../configureOutputModal/Options'; import Input from '../../configureOutputModal/Input'; import MultiviewLayout from './MultiviewLayout'; +import { IconTrash } from '@tabler/icons-react'; +import toast from 'react-hot-toast'; +import { set } from 'lodash'; type ChangeLayout = { defaultLabel?: string; @@ -28,10 +34,12 @@ export default function MultiviewLayoutSettings({ }) { const [selectedMultiviewPreset, setSelectedMultiviewPreset] = useState(null); + const [refresh, setRefresh] = + useState(true); const [changedLayout, setChangedLayout] = useState(null); const [newPresetName, setNewPresetName] = useState(null); const [layoutToChange, setLayoutToChange] = useState(''); - const [multiviewLayouts] = useMultiviewLayouts(); + const [multiviewLayouts] = useMultiviewLayouts(refresh); const [multiviewPresets] = useMultiviewPresets(); const { multiviewPresetLayout } = useSetupMultiviewLayout( selectedMultiviewPreset @@ -45,6 +53,7 @@ export default function MultiviewLayoutSettings({ newPresetName ); const { inputList } = useCreateInputArray(production); + const deleteLayout = useDeleteMultiviewLayout(); const t = useTranslate(); const multiviewPresetNames = multiviewPresets?.map((preset) => preset.name) @@ -57,6 +66,15 @@ export default function MultiviewLayoutSettings({ const multiviewLayoutNames = availableMultiviewLayouts?.map((layout) => layout.name) || []; + const productionLayouts = + multiviewLayouts?.filter( + (layout) => layout.productionId === production?._id + ) || []; + const globalMultiviewLayouts = multiviewLayouts?.filter( + (layout) => !layout.productionId + ); + const deleteDisabled = productionLayouts.length < 1; + // This useEffect is used to set the drawn layout of the multiviewer on start, // if this fails then the modal will be empty useEffect(() => { @@ -65,6 +83,12 @@ export default function MultiviewLayoutSettings({ } }, [multiviewPresets]); + useEffect(() => { + if (multiviewLayouts) { + setRefresh(false); + } + }, [multiviewLayouts]); + const layoutNameAlreadyExist = availableMultiviewLayouts?.find( (singlePreset) => singlePreset.name === multiviewLayout?.name )?.name; @@ -122,21 +146,63 @@ export default function MultiviewLayoutSettings({ } }; + const removeMultiviewLayout = () => { + const layoutToRemove = productionLayouts.find( + (layout) => layout.name === newPresetName + ); + const globalLayoutToRemove = globalMultiviewLayouts?.find( + (layout) => layout.name === newPresetName + ); + + if (!layoutToRemove && globalLayoutToRemove) { + toast.error(t('preset.not_possible_delete_global_layout')); + return; + } + if (layoutToRemove && !layoutToRemove._id) { + toast.error(t('preset.could_not_delete_layout')); + return; + } + if (layoutToRemove && layoutToRemove._id) { + deleteLayout(layoutToRemove._id.toString()).then(() => { + setRefresh(true); + setNewPresetName(''); + toast.success(t('preset.layout_deleted')); + }); + } + }; + return ( <> {selectedMultiviewPreset && (
- ({ - label: singleItem - }))} - value={ - selectedMultiviewPreset ? selectedMultiviewPreset.name : '' - } - update={(value) => handleLayoutUpdate(value, 'layout')} - /> +
+ ({ + label: singleItem + }))} + value={ + selectedMultiviewPreset ? selectedMultiviewPreset.name : '' + } + update={(value) => handleLayoutUpdate(value, 'layout')} + /> + +
({ diff --git a/src/components/modal/configureMultiviewModal/MultiviewSettings.tsx b/src/components/modal/configureMultiviewModal/MultiviewSettings.tsx index a1fdb1cd..e601e1c5 100644 --- a/src/components/modal/configureMultiviewModal/MultiviewSettings.tsx +++ b/src/components/modal/configureMultiviewModal/MultiviewSettings.tsx @@ -28,7 +28,7 @@ export default function MultiviewSettingsConfig({ productionId }: MultiviewSettingsProps) { const t = useTranslate(); - const [multiviewLayouts] = useMultiviewLayouts(); + const [multiviewLayouts] = useMultiviewLayouts(true); const [selectedMultiviewLayout, setSelectedMultiviewLayout] = useState< TMultiviewLayout | undefined >(); diff --git a/src/hooks/multiviewLayout.ts b/src/hooks/multiviewLayout.ts index 13525d1a..f1197f4c 100644 --- a/src/hooks/multiviewLayout.ts +++ b/src/hooks/multiviewLayout.ts @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { TMultiviewLayout } from '../interfaces/preset'; import { DataHook } from './types'; import { WithId } from 'mongodb'; @@ -30,13 +30,19 @@ export function useGetMultiviewLayout() { }; } -export function useMultiviewLayouts(): DataHook { +export function useMultiviewLayouts(refresh: boolean): DataHook { const [loading, setLoading] = useState(true); const [multiviewLayouts, setmultiviewLayouts] = useState( [] ); useEffect(() => { + setmultiviewLayouts([]); + + if(!refresh) { + return; + } + setLoading(true); fetch('/api/manager/multiviews', { method: 'GET', @@ -48,7 +54,7 @@ export function useMultiviewLayouts(): DataHook { } }) .finally(() => setLoading(false)); - }, []); + }, [refresh]); return [multiviewLayouts, loading, undefined]; } @@ -66,3 +72,16 @@ export function usePutMultiviewLayout() { throw await response.text(); }; } + +export function useDeleteMultiviewLayout() { + return async (id: string): Promise => { + const response = await fetch(`/api/manager/multiviews/${id}`, { + method: 'DELETE', + headers: [['x-api-key', `Bearer ${API_SECRET_KEY}`]] + }); + if (response.ok) { + return; + } + throw await response.text(); + }; +} diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index eff6a487..59fcd659 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -672,7 +672,10 @@ export const en = { layout_already_exist: 'Layout {{layoutNameAlreadyExist}} will be replaced on save', remove_multiview: 'Remove multiview', - add_another_multiview: 'Add another multiview' + add_another_multiview: 'Add another multiview', + not_possible_delete_global_layout: 'Global layout can not be deleted', + could_not_delete_layout: 'Could not delete layout', + layout_deleted: 'Layout deleted' }, error: { missing_sources_in_db: 'Missing sources, please restart production.', diff --git a/src/i18n/locales/sv.ts b/src/i18n/locales/sv.ts index 24e1879d..1051c0a5 100644 --- a/src/i18n/locales/sv.ts +++ b/src/i18n/locales/sv.ts @@ -676,7 +676,10 @@ export const sv = { layout_already_exist: 'Konfigurationen {{layoutNameAlreadyExist}} skrivs över om du sparar', remove_multiview: 'Ta bort multiview', - add_another_multiview: 'Lägg till ny multiview' + add_another_multiview: 'Lägg till ny multiview', + layout_deleted: 'Kompositionen har tagits bort', + not_possible_delete_global_layout: 'Det går inte att ta bort globala kompositioner', + could_not_delete_layout: 'Kunde inte ta bort kompositionen' }, error: { missing_sources_in_db: 'Källor saknas, var god starta om produktionen.', From 86eed4b08c95491413df9c528699cc91c7a03aaf Mon Sep 17 00:00:00 2001 From: malmen237 Date: Wed, 16 Oct 2024 16:02:56 +0200 Subject: [PATCH 2/4] fix: clear layout to default when delete is done, updated some variable-names --- .../MultiviewLayoutSettings/MultiviewLayout.tsx | 2 +- .../MultiviewLayoutSettings.tsx | 6 +++++- .../modal/configureOutputModal/Options.tsx | 12 ++++++------ src/i18n/locales/en.ts | 1 + src/i18n/locales/sv.ts | 1 + 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayout.tsx b/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayout.tsx index 9d345135..008f0024 100644 --- a/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayout.tsx +++ b/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayout.tsx @@ -45,7 +45,7 @@ export default function MultiviewLayout({ id: singleSource.id, label: singleSource.label }))} - value={label || ''} + value="" update={(value) => handleChange(id || '', value)} columnStyle /> diff --git a/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayoutSettings.tsx b/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayoutSettings.tsx index b515b797..8db8ea8d 100644 --- a/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayoutSettings.tsx +++ b/src/components/modal/configureMultiviewModal/MultiviewLayoutSettings/MultiviewLayoutSettings.tsx @@ -135,6 +135,7 @@ export default function MultiviewLayoutSettings({ const defaultLabel = availableMultiviewLayouts[0].layout.views.find( (item) => item.input_slot === idFirstInputView )?.label; + inputList.map((source) => { if (value === '') { setChangedLayout({ defaultLabel, viewId }); @@ -165,6 +166,9 @@ export default function MultiviewLayoutSettings({ if (layoutToRemove && layoutToRemove._id) { deleteLayout(layoutToRemove._id.toString()).then(() => { setRefresh(true); + if (multiviewPresets && multiviewPresets[0]) { + setSelectedMultiviewPreset(multiviewPresets[0]); + } setNewPresetName(''); toast.success(t('preset.layout_deleted')); }); @@ -189,7 +193,7 @@ export default function MultiviewLayoutSettings({ /> + {!production?.isActive && ( + + )}
{ if (!production) return; diff --git a/src/hooks/multiviewLayout.ts b/src/hooks/multiviewLayout.ts index f1197f4c..b971e3ad 100644 --- a/src/hooks/multiviewLayout.ts +++ b/src/hooks/multiviewLayout.ts @@ -30,7 +30,9 @@ export function useGetMultiviewLayout() { }; } -export function useMultiviewLayouts(refresh: boolean): DataHook { +export function useMultiviewLayouts( + refresh: boolean +): DataHook { const [loading, setLoading] = useState(true); const [multiviewLayouts, setmultiviewLayouts] = useState( [] @@ -39,7 +41,7 @@ export function useMultiviewLayouts(refresh: boolean): DataHook { setmultiviewLayouts([]); - if(!refresh) { + if (!refresh) { return; } diff --git a/src/i18n/locales/sv.ts b/src/i18n/locales/sv.ts index 016d9473..2206d44e 100644 --- a/src/i18n/locales/sv.ts +++ b/src/i18n/locales/sv.ts @@ -679,7 +679,8 @@ export const sv = { remove_layout: 'Ta bort komposition', add_another_multiview: 'Lägg till ny multiview', layout_deleted: 'Kompositionen har tagits bort', - not_possible_delete_global_layout: 'Det går inte att ta bort globala kompositioner', + not_possible_delete_global_layout: + 'Det går inte att ta bort globala kompositioner', could_not_delete_layout: 'Kunde inte ta bort kompositionen' }, error: { From 69b3bf6607df9f23f96c6ac91b0e4303774fa275 Mon Sep 17 00:00:00 2001 From: malmen237 Date: Thu, 17 Oct 2024 10:26:31 +0200 Subject: [PATCH 4/4] fix: updated error-message --- src/app/api/manager/multiviews/[id]/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/manager/multiviews/[id]/route.ts b/src/app/api/manager/multiviews/[id]/route.ts index 3e65b078..56d8af54 100644 --- a/src/app/api/manager/multiviews/[id]/route.ts +++ b/src/app/api/manager/multiviews/[id]/route.ts @@ -73,7 +73,7 @@ export async function DELETE( } catch (error) { console.log(error); return new NextResponse( - `Error occurred while posting to DB! Error: ${error}`, + `Error occurred while deleting from DB! Error: ${error}`, { status: 500 }