From 4d9a5aa7e008eb9a747e20251c1cf8db708a1963 Mon Sep 17 00:00:00 2001 From: Zuri Klaschka Date: Sun, 31 Dec 2023 16:41:37 +0100 Subject: [PATCH] TELESTION-442 Migration with deleted widget type Replaces widget instances of no-longer existing widgets with `"."` (i.e., empty spaces) in dashboard layouts during migration --- .../application/routes/migration/routing.ts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/frontend-react/src/lib/application/routes/migration/routing.ts b/frontend-react/src/lib/application/routes/migration/routing.ts index 85fbfa83..3c656962 100644 --- a/frontend-react/src/lib/application/routes/migration/routing.ts +++ b/frontend-react/src/lib/application/routes/migration/routing.ts @@ -95,9 +95,22 @@ export function migrationAction({ (entry): entry is [id: string, instance: WidgetInstance] => !!entry ); + const availableWidgetInstances = new Set( + newInstances.map(([widgetInstanceId]) => widgetInstanceId) + ); + + // filter dashboard layouts for no longer existing widgets + const newDashboards = Object.entries(oldUserData.dashboards).map( + dashboardTuple => + migrateDashboardConfig(dashboardTuple, availableWidgetInstances) + ); + setUserData({ ...oldUserData, version: version, + dashboards: { + ...Object.fromEntries(newDashboards) + }, widgetInstances: { ...Object.fromEntries(newInstances) } @@ -131,6 +144,44 @@ async function parseUserData( return userDataSchema.parse(JSON.parse(rawUserData)); } +/** + * Accepts a tuple of a dashboard id and the associated dashboard and performs a + * dashboard configuration migration by replacing all widget ids that are no + * longer registered with a dot (i.e., empty space). + * @param id - the id of the dashboard + * @param dashboard - the dashboard with the outdated widget ids + * @param availableWidgetInstances - a set of all available widget instance ids + * @returns a tuple of a dashboard with an up-to-date widget configuration + */ +function migrateDashboardConfig( + [id, dashboard]: [string, UserData['dashboards'][string]], + availableWidgetInstances: Set +): [string, UserData['dashboards'][string]] { + return [ + id, + { + ...dashboard, + layout: dashboard.layout.map(row => + row.map(widgetInstanceId => { + if (widgetInstanceId === '.') { + return '.'; + } + + if (!availableWidgetInstances.has(widgetInstanceId)) { + console.warn( + `Widget with id "${widgetInstanceId}" not found. Replacing with "."` + ); + + return '.'; + } + + return widgetInstanceId; + }) + ) + } + ]; +} + /** * Accepts a tuple of a widget instance and the associated id and performs a * widget configuration migration via the widget's {@link createConfig} function.