Skip to content

Dashboard ux#1579

Merged
lyubov-voloshko merged 13 commits intorocket-admin:mainfrom
karinakharchenko:dashboard-ux
Feb 8, 2026
Merged

Dashboard ux#1579
lyubov-voloshko merged 13 commits intorocket-admin:mainfrom
karinakharchenko:dashboard-ux

Conversation

@karinakharchenko
Copy link
Contributor

No description provided.

karinakharchenko and others added 4 commits February 6, 2026 15:25
…vigation

- Add sidebar navigation for Dashboards section with Dashboards/Widgets tabs
- Convert dashboards list from table to responsive card grid with widget count
- Convert widgets list to card grid with chart type mini previews
- Add ChartMiniPreviewComponent with SVG visualizations for bar, line, pie, doughnut, polar area charts
- Add "Create new query" option inside dropdown in Add Chart dialog
- Backend: include widgets in dashboards list response for accurate counts
- Fix sidebar state persistence with localStorage
- Fix sidebar animation flash on navigation
- Auto-refresh dashboard cards when widgets are added/deleted
- Various styling improvements for dark mode support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Convert widgets list from cards to table with columns: Type, Name, Description, Updated, Actions
- Add chart type mini preview icons in first column with tooltip on hover
- Show relative time for recent updates (e.g., "2 hours ago")
- Simplify bar chart preview to 3 bars
- Enlarge pie, doughnut, polar area chart previews
- Rename "Edit Saved Query" to "Edit Widget"
- Fix spinner alignment in Test Query button
- Add top margin to query inputs to prevent label overlap

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@lyubov-voloshko lyubov-voloshko marked this pull request as ready for review February 8, 2026 21:24
Copilot AI review requested due to automatic review settings February 8, 2026 21:24
@lyubov-voloshko lyubov-voloshko merged commit 03dae76 into rocket-admin:main Feb 8, 2026
13 of 14 checks passed
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the dashboards/widgets UX by adding a collapsible sidebar for navigation between Dashboards and Widgets (Saved Queries), refreshing the dashboard list presentation, and improving widget creation flows (including a “create query” path). It also adjusts backend dashboard fetching to include widget data for richer list displays.

Changes:

  • Add a reusable dashboards/widgets sidebar with persisted collapsed state in UI settings.
  • Redesign dashboards list into a card/grid layout and align charts list to “Widgets” terminology with richer table rows (preview + relative updated time).
  • Improve widget add/edit dialog UX to handle empty saved-query states and offer “create query” navigation.

Reviewed changes

Copilot reviewed 28 out of 29 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
frontend/src/app/services/ui-settings.service.ts Adjusts table-setting updates (currently introduces a runtime risk + debug log).
frontend/src/app/services/dashboards.service.ts Adds clearDashboardsUpdated() and marks dashboards updated when widgets are created/deleted.
frontend/src/app/models/ui-settings.ts Adds persisted dashboardsSidebarCollapsed connection setting.
frontend/src/app/components/dashboards/widget-edit-dialog/widget-edit-dialog.component.ts Adds router-based navigation for “create query” and updates dialog wiring/imports.
frontend/src/app/components/dashboards/widget-edit-dialog/widget-edit-dialog.component.html Improves dialog UX: empty state, create-query action, and form submit handling.
frontend/src/app/components/dashboards/widget-edit-dialog/widget-edit-dialog.component.css Styles empty state and create option within the select.
frontend/src/app/components/dashboards/dashboards-sidebar/dashboards-sidebar.component.ts New collapsible sidebar component that reads/writes collapsed state via UI settings.
frontend/src/app/components/dashboards/dashboards-sidebar/dashboards-sidebar.component.html Sidebar layout + navigation links for dashboards/widgets.
frontend/src/app/components/dashboards/dashboards-sidebar/dashboards-sidebar.component.css Sidebar styling (collapsed/expanded, active link, mobile behavior).
frontend/src/app/components/dashboards/dashboards-list/dashboards-list.component.ts Integrates sidebar and improves refresh behavior after dashboard updates.
frontend/src/app/components/dashboards/dashboards-list/dashboards-list.component.spec.ts Updates mocks for new dashboards service call.
frontend/src/app/components/dashboards/dashboards-list/dashboards-list.component.html Replaces table layout with a grid of dashboard cards and adds sidebar layout.
frontend/src/app/components/dashboards/dashboards-list/dashboards-list.component.css Adds layout/grid/card styling for the updated dashboards list page.
frontend/src/app/components/dashboards/dashboard-view/dashboard-view.component.html Shows header edit/add actions only when widgets exist; updates empty-state button style.
frontend/src/app/components/dashboards/dashboard-edit-dialog/dashboard-edit-dialog.component.html Converts dialog to a proper form submit pattern.
frontend/src/app/components/dashboards/dashboard-edit-dialog/dashboard-edit-dialog.component.css Minor spacing adjustment for dialog form.
frontend/src/app/components/dashboards/chart-mini-preview/chart-mini-preview.component.ts New mini chart preview component for widget list rows.
frontend/src/app/components/dashboards/chart-mini-preview/chart-mini-preview.component.html SVG-based previews for different chart types.
frontend/src/app/components/dashboards/chart-mini-preview/chart-mini-preview.component.css Styles for the mini previews and dark-mode tweaks.
frontend/src/app/components/dashboard/db-table-view/db-table-widgets/db-table-widgets.component.ts Removes Markdown editor import from standalone imports list.
frontend/src/app/components/charts/charts-list/charts-list.component.ts Renames UX to “Widgets”, adds preview column support, and relative updated-time formatting.
frontend/src/app/components/charts/charts-list/charts-list.component.spec.ts Updates expected displayed columns.
frontend/src/app/components/charts/charts-list/charts-list.component.html Adds sidebar layout and updates widgets table columns (preview + relative updated).
frontend/src/app/components/charts/charts-list/charts-list.component.css Adds layout and styles for the updated widgets table and empty state.
frontend/src/app/components/charts/chart-edit/chart-edit.component.ts Integrates the sidebar into the chart/widget editor page.
frontend/src/app/components/charts/chart-edit/chart-edit.component.spec.ts Updates UiSettingsService mock to include getUiSettings.
frontend/src/app/components/charts/chart-edit/chart-edit.component.html Adds sidebar layout and updates labels (“Widget” terminology).
frontend/src/app/components/charts/chart-edit/chart-edit.component.css Updates editor layout and makes actions sticky at the bottom.
backend/src/entities/visualizations/dashboard/repository/dashboard-custom-repository-extension.ts Changes dashboard list query to join widgets (now duplicates another repository method).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +49 to +52
private _loadCollapsedState(): void {
this._uiSettings.getUiSettings().subscribe((settings) => {
this.collapsed.set(settings?.connections?.[this.connectionId()]?.dashboardsSidebarCollapsed ?? false);
});
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This subscription can leak because UiSettingsService.getUiSettings() returns a non-completing Observable once settings are cached (new Observable((s) => s.next(...))). Use take(1)/firstValueFrom/toSignal (or fix getUiSettings() to return of(...)) so the sidebar doesn’t keep a live subscription per instance.

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +27
const qb = this.createQueryBuilder('dashboard')
.leftJoinAndSelect('dashboard.widgets', 'widgets')
.where('dashboard.connection_id = :connectionId', { connectionId })
.orderBy('dashboard.created_at', 'DESC');
return await qb.getMany();
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findAllDashboardsByConnectionId now eagerly loads dashboard.widgets and is effectively identical to findAllDashboardsWithWidgetsByConnectionId. This makes the method name misleading and adds avoidable query/payload cost for callers that only need dashboards. Either revert this method to a lightweight find (no join) or remove/merge the duplicate API to keep semantics clear.

Suggested change
const qb = this.createQueryBuilder('dashboard')
.leftJoinAndSelect('dashboard.widgets', 'widgets')
.where('dashboard.connection_id = :connectionId', { connectionId })
.orderBy('dashboard.created_at', 'DESC');
return await qb.getMany();
return await this.find({
where: { connection_id: connectionId },
order: { created_at: 'DESC' },
});

Copilot uses AI. Check for mistakes.
Comment on lines 23 to 26
import { CodeEditComponent } from '../../../ui-components/record-edit-fields/code/code.component';
import { ImageEditComponent } from '../../../ui-components/record-edit-fields/image/image.component';
import { LongTextEditComponent } from '../../../ui-components/record-edit-fields/long-text/long-text.component';
import { MarkdownEditComponent } from '../../../ui-components/record-edit-fields/markdown/markdown.component';
import { PasswordEditComponent } from '../../../ui-components/record-edit-fields/password/password.component';
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MarkdownEditComponent was removed from this component’s imports, but DbTableWidgetsComponent unit test still calls TestBed.overrideComponent(MarkdownEditComponent, ...) (in db-table-widgets.component.spec.ts). Angular will throw when overriding a component that isn’t part of the testing module, so the test setup needs to be updated (remove that override or re-add the import if Markdown widgets are still required here).

Copilot uses AI. Check for mistakes.
});
}

formatUpdatedAt(date: string): string {
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatUpdatedAt introduces date-relative formatting logic used by the UI, but it isn’t covered by unit tests in charts-list.component.spec.ts. Add tests for the main boundaries ("Just now", minutes, hours, days, and the >=7 days fallback) to prevent regressions.

Copilot uses AI. Check for mistakes.
if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;
if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;

return updated.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The toLocaleDateString('en-US', ...) fallback hard-codes the US locale, which can produce inconsistent formatting vs the rest of the app (Angular date pipe uses the active locale). Prefer using Intl.DateTimeFormat(undefined, ...) or the Angular DatePipe so formatting follows the user/app locale.

Suggested change
return updated.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
return new Intl.DateTimeFormat(undefined, { month: 'short', day: 'numeric', year: 'numeric' }).format(updated);

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +56
this.settings.connections[connectionId] = { shownTableTitles: false, tables: {} };
}
// if (!this.settings.connections[connectionId].tables[tableName]) {
// this.settings.connections[connectionId].tables[tableName] = { shownColumns: [] };
// }
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updateTableSetting writes to this.settings.connections[connectionId].tables[tableName][key] without ensuring tables[tableName] is initialized. If this table has no existing settings, this will throw at runtime. Initialize tables[tableName] (and tables if needed) before indexing, similar to the commented-out block.

Suggested change
this.settings.connections[connectionId] = { shownTableTitles: false, tables: {} };
}
// if (!this.settings.connections[connectionId].tables[tableName]) {
// this.settings.connections[connectionId].tables[tableName] = { shownColumns: [] };
// }
this.settings.connections[connectionId] = { shownTableTitles: false, tables: {} };
}
if (!this.settings.connections[connectionId].tables) {
this.settings.connections[connectionId].tables = {};
}
if (!this.settings.connections[connectionId].tables[tableName]) {
this.settings.connections[connectionId].tables[tableName] = { shownColumns: [] };
}

Copilot uses AI. Check for mistakes.
this.syncUiSettings().subscribe();
}
updateTableSetting(connectionId: string, tableName: string, key: string, value: any) {
console.log('updateTableSetting')
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the console.log('updateTableSetting') debug statement (and consider using the app’s notifications/logging approach if this is needed). Leaving console logs in a shared service is noisy in production and tests.

Suggested change
console.log('updateTableSetting')

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants