Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions apps/console/src/components/DashboardView.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,6 +51,27 @@ function createWidgetId(): string {
return `widget_${Date.now()}_${widgetCounter}`;
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

/** Ensure every widget in the schema has a unique id. */
function ensureWidgetIds(schema: DashboardSchema): DashboardSchema {
if (!schema.widgets?.length) return schema;
const needsFix = schema.widgets.some((w) => !w.id);
if (!needsFix) return schema;
return {
...schema,
widgets: schema.widgets.map((w) => (w.id ? w : { ...w, id: createWidgetId() })),
};
}

/** Resolve a human-friendly default title for a new widget type. */
function defaultWidgetTitle(type: string): string {
const entry = WIDGET_TYPES.find((t) => t.type === type);
return entry ? `New ${entry.label}` : 'New Widget';
}

// ---------------------------------------------------------------------------
// Helpers: flatten / unflatten widget config for WidgetConfigPanel
// ---------------------------------------------------------------------------
Expand DownExpand Up@@ -120,7 +141,7 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {
queueMicrotask(() => setIsLoading(false));
}, [dashboardName]);

const { dashboards } = useMetadata();
const { dashboards, objects: metadataObjects } = useMetadata();
const dashboard = dashboards?.find((d: any) => d.name === dashboardName);

// Local schema state for live preview — initialized from metadata
Expand All@@ -142,7 +163,7 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {

// ---- Open / close config panel ------------------------------------------
const handleOpenConfigPanel = useCallback(() => {
setEditSchema(dashboard as DashboardSchema);
setEditSchema(ensureWidgetIds(dashboard as DashboardSchema));
setConfigPanelOpen(true);
setConfigVersion((v) => v + 1);
}, [dashboard]);
Expand All@@ -159,7 +180,7 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {
const id = createWidgetId();
const newWidget: DashboardWidgetSchema = {
id,
title: '',
title: defaultWidgetTitle(type),
type,
layout: {
x: 0,
Expand DownExpand Up@@ -290,6 +311,33 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {
[selectedWidgetId],
);

// ---- Metadata-driven dropdown options -----------------------------------
const availableObjects = useMemo(() => {
if (!metadataObjects?.length) return undefined;
return metadataObjects.map((obj: any) => ({
value: obj.name,
label: obj.label || obj.name,
}));
}, [metadataObjects]);

const availableFields = useMemo(() => {
const objectName = selectedWidget?.object;
if (!objectName || !metadataObjects?.length) return undefined;
const obj = metadataObjects.find((o: any) => o.name === objectName);
if (!obj?.fields) return undefined;
const fields = obj.fields;
if (Array.isArray(fields)) {
return fields
.filter((f: any) => f.name)
.map((f: any) => ({ value: f.name, label: f.label || f.name }));
}
// fields can be Record<string, FieldMetadata>
return Object.entries(fields).map(([key, f]: [string, any]) => ({
value: key,
label: f.label || key,
}));
}, [selectedWidget?.object, metadataObjects]);

// ---- Loading / not-found guards -----------------------------------------
if (isLoading) {
return <SkeletonDashboard />;
Expand DownExpand Up@@ -377,6 +425,8 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {
config={widgetConfig}
onSave={handleWidgetConfigSave}
onFieldChange={handleWidgetFieldChange}
availableObjects={availableObjects}
availableFields={availableFields}
headerExtra={
<Button
size="sm"
Expand Down
Loading