import { schema, denormalize as baseDenormalize } from 'normalizr'; import { EntityWithBindings6, PageDSL8, WidgetProps, WidgetProps8, WidgetTypes } from '../types/index.js'; import { getNextEntityName } from './string.js'; const widgetSchema = new schema.Entity('canvasWidgets', {}, { idAttribute: 'widgetId' }); widgetSchema.define({ children: [widgetSchema] }); export type FlattenedWidgetProps = Omit & { type: keyof typeof WidgetTypes; children?: string[]; } & EntityWithBindings6; const PAGE_WIDGET_ID = '0'; type WidgetMap = Record; /** * Fixes invalid DSL from previous bugs on initial load. * 1. removes duplicate IDs * 2. de-duplicates identical Section and Canvas names because their names don't matter * 3. removes timers and stateVars from the page widget, as they are processed separately */ export function normalize( dsl?: PageDSL8 ): { entities: { canvasWidgets: T; }; result: string; } { if (!dsl) return { entities: { canvasWidgets: {} as T }, result: '' }; const flattenedWidgets = {} as T; const previouslySeenCanvasNames = new Set(); function flattenWidget(widget: WidgetProps8): void { if (flattenedWidgets[widget.widgetId]) return; if (widget.children) { flattenedWidgets[widget.widgetId] = { ...widget, children: Array.from(new Set(widget.children?.map((child) => child.widgetId))) } as FlattenedWidgetProps; } else { flattenedWidgets[widget.widgetId] = widget as FlattenedWidgetProps; } if (widget.widgetId === PAGE_WIDGET_ID) { // Extracted separately delete widget.stateVars; delete widget.timers; delete widget.events; } if ( (widget.type === WidgetTypes.CANVAS_WIDGET || widget.type === WidgetTypes.SECTION_WIDGET) && previouslySeenCanvasNames.has(widget.widgetName) ) { const newName = getNextEntityName(widget.widgetName, Array.from(previouslySeenCanvasNames)); flattenedWidgets[widget.widgetId].widgetName = newName; previouslySeenCanvasNames.add(newName); } else { previouslySeenCanvasNames.add(widget.widgetName); } if (widget.children) { widget.children.forEach(flattenWidget); } } flattenWidget(dsl); return { entities: { canvasWidgets: flattenedWidgets }, result: dsl.widgetId }; } export function denormalize(pageWidgetId: string, entities: { canvasWidgets: T }): PageDSL8 { return baseDenormalize(pageWidgetId, widgetSchema, entities); }