@@ -51,6 +51,27 @@ function createWidgetId(): string {
5151 return `widget_${ Date . now ( ) } _${ widgetCounter } ` ;
5252}
5353
54+ // ---------------------------------------------------------------------------
55+ // Helpers
56+ // ---------------------------------------------------------------------------
57+
58+ /** Ensure every widget in the schema has a unique id. */
59+ function ensureWidgetIds ( schema : DashboardSchema ) : DashboardSchema {
60+ if ( ! schema . widgets ?. length ) return schema ;
61+ const needsFix = schema . widgets . some ( ( w ) => ! w . id ) ;
62+ if ( ! needsFix ) return schema ;
63+ return {
64+ ...schema ,
65+ widgets : schema . widgets . map ( ( w ) => ( w . id ? w : { ...w , id : createWidgetId ( ) } ) ) ,
66+ } ;
67+ }
68+
69+ /** Resolve a human-friendly default title for a new widget type. */
70+ function defaultWidgetTitle ( type : string ) : string {
71+ const entry = WIDGET_TYPES . find ( ( t ) => t . type === type ) ;
72+ return entry ? `New ${ entry . label } ` : 'New Widget' ;
73+ }
74+
5475// ---------------------------------------------------------------------------
5576// Helpers: flatten / unflatten widget config for WidgetConfigPanel
5677// ---------------------------------------------------------------------------
@@ -120,7 +141,7 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {
120141 queueMicrotask ( ( ) => setIsLoading ( false ) ) ;
121142 } , [ dashboardName ] ) ;
122143
123- const { dashboards } = useMetadata ( ) ;
144+ const { dashboards, objects : metadataObjects } = useMetadata ( ) ;
124145 const dashboard = dashboards ?. find ( ( d : any ) => d . name === dashboardName ) ;
125146
126147 // Local schema state for live preview — initialized from metadata
@@ -142,7 +163,7 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {
142163
143164 // ---- Open / close config panel ------------------------------------------
144165 const handleOpenConfigPanel = useCallback ( ( ) => {
145- setEditSchema ( dashboard as DashboardSchema ) ;
166+ setEditSchema ( ensureWidgetIds ( dashboard as DashboardSchema ) ) ;
146167 setConfigPanelOpen ( true ) ;
147168 setConfigVersion ( ( v ) => v + 1 ) ;
148169 } , [ dashboard ] ) ;
@@ -159,7 +180,7 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {
159180 const id = createWidgetId ( ) ;
160181 const newWidget : DashboardWidgetSchema = {
161182 id,
162- title : '' ,
183+ title : defaultWidgetTitle ( type ) ,
163184 type,
164185 layout : {
165186 x : 0 ,
@@ -290,6 +311,33 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {
290311 [ selectedWidgetId ] ,
291312 ) ;
292313
314+ // ---- Metadata-driven dropdown options -----------------------------------
315+ const availableObjects = useMemo ( ( ) => {
316+ if ( ! metadataObjects ?. length ) return undefined ;
317+ return metadataObjects . map ( ( obj : any ) => ( {
318+ value : obj . name ,
319+ label : obj . label || obj . name ,
320+ } ) ) ;
321+ } , [ metadataObjects ] ) ;
322+
323+ const availableFields = useMemo ( ( ) => {
324+ const objectName = selectedWidget ?. object ;
325+ if ( ! objectName || ! metadataObjects ?. length ) return undefined ;
326+ const obj = metadataObjects . find ( ( o : any ) => o . name === objectName ) ;
327+ if ( ! obj ?. fields ) return undefined ;
328+ const fields = obj . fields ;
329+ if ( Array . isArray ( fields ) ) {
330+ return fields
331+ . filter ( ( f : any ) => f . name )
332+ . map ( ( f : any ) => ( { value : f . name , label : f . label || f . name } ) ) ;
333+ }
334+ // fields can be Record<string, FieldMetadata>
335+ return Object . entries ( fields ) . map ( ( [ key , f ] : [ string , any ] ) => ( {
336+ value : key ,
337+ label : f . label || key ,
338+ } ) ) ;
339+ } , [ selectedWidget ?. object , metadataObjects ] ) ;
340+
293341 // ---- Loading / not-found guards -----------------------------------------
294342 if ( isLoading ) {
295343 return < SkeletonDashboard /> ;
@@ -377,6 +425,8 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {
377425 config = { widgetConfig }
378426 onSave = { handleWidgetConfigSave }
379427 onFieldChange = { handleWidgetFieldChange }
428+ availableObjects = { availableObjects }
429+ availableFields = { availableFields }
380430 headerExtra = {
381431 < Button
382432 size = "sm"
0 commit comments