Skip to content

Commit e325547

Browse files
authored
refactor: Rename DashboardWidgets to Widgets for dynamic dashboard (#97)
- Rename DashboardWidget model to Widget with table name 'widgets' - Update handler methods: ListWidgets, GetWidget, CreateWidget, etc. - Change API routes from /api/dashboard/widgets to /api/widgets - Rename frontend service from dashboardWidgetsService to widgetsService - Update test utilities and test files accordingly - Add grid-layout-plus dependency for dashboard layout
1 parent fe54ef0 commit e325547

File tree

11 files changed

+1017
-437
lines changed

11 files changed

+1017
-437
lines changed

cmd/whatomate/main.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -604,16 +604,16 @@ func setupRoutes(g *fastglue.Fastglue, app *handlers.App, lo logf.Logger, basePa
604604
g.GET("/api/analytics/agents/{id}", app.GetAgentDetails)
605605
g.GET("/api/analytics/agents/comparison", app.GetAgentComparison)
606606

607-
// Dashboard Widgets (customizable analytics)
608-
g.GET("/api/dashboard/widgets", app.ListDashboardWidgets)
609-
g.POST("/api/dashboard/widgets", app.CreateDashboardWidget)
610-
g.GET("/api/dashboard/widgets/data-sources", app.GetWidgetDataSources)
611-
g.GET("/api/dashboard/widgets/data", app.GetAllWidgetsData)
612-
g.GET("/api/dashboard/widgets/{id}", app.GetDashboardWidget)
613-
g.PUT("/api/dashboard/widgets/{id}", app.UpdateDashboardWidget)
614-
g.DELETE("/api/dashboard/widgets/{id}", app.DeleteDashboardWidget)
615-
g.GET("/api/dashboard/widgets/{id}/data", app.GetWidgetData)
616-
g.POST("/api/dashboard/widgets/reorder", app.ReorderDashboardWidgets)
607+
// Widgets (customizable analytics)
608+
g.GET("/api/widgets", app.ListWidgets)
609+
g.POST("/api/widgets", app.CreateWidget)
610+
g.GET("/api/widgets/data-sources", app.GetWidgetDataSources)
611+
g.GET("/api/widgets/data", app.GetAllWidgetsData)
612+
g.GET("/api/widgets/{id}", app.GetWidget)
613+
g.PUT("/api/widgets/{id}", app.UpdateWidget)
614+
g.DELETE("/api/widgets/{id}", app.DeleteWidget)
615+
g.GET("/api/widgets/{id}/data", app.GetWidgetData)
616+
g.POST("/api/widgets/layout", app.SaveWidgetLayout)
617617

618618
// Organization Settings
619619
g.GET("/api/org/settings", app.GetOrganizationSettings)

frontend/e2e/tests/dashboard/dashboard.spec.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,16 @@ test.describe('Dashboard', () => {
4141
await expect(page.locator('button[role="combobox"]').first()).toContainText('Last 7 days')
4242
})
4343

44-
test('should display recent messages section', async ({ page }) => {
45-
await expect(page.getByRole('heading', { name: 'Recent Messages' })).toBeVisible()
44+
test('should display recent messages widget', async ({ page }) => {
45+
// Widget names are displayed in spans, not headings
46+
await expect(page.getByText('Recent Messages', { exact: true })).toBeVisible({ timeout: 15000 })
4647
await expect(page.getByText('Latest conversations from your contacts')).toBeVisible()
4748
})
4849

49-
test('should display quick actions section', async ({ page }) => {
50+
test('should display quick actions widget', async ({ page }) => {
5051
const main = page.locator('main')
51-
await expect(main.locator('text=Quick Actions')).toBeVisible()
52-
await expect(main.locator('text=Common tasks and shortcuts')).toBeVisible()
52+
await expect(main.getByText('Quick Actions', { exact: true })).toBeVisible({ timeout: 15000 })
53+
await expect(main.getByText('Common tasks and shortcuts')).toBeVisible()
5354

5455
// Check for quick action links - scope to main to avoid sidebar duplicates
5556
await expect(main.locator('a[href="/chat"]')).toBeVisible()

frontend/package-lock.json

Lines changed: 56 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"class-variance-authority": "^0.7.0",
2727
"clsx": "^2.1.0",
2828
"dompurify": "^3.3.1",
29+
"grid-layout-plus": "^1.1.1",
2930
"lucide-vue-next": "^0.303.0",
3031
"pinia": "^2.1.7",
3132
"reka-ui": "^2.7.0",

frontend/src/services/api.ts

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,11 @@ export interface DashboardWidget {
328328
color: string
329329
size: string
330330
display_order: number
331+
grid_x: number
332+
grid_y: number
333+
grid_w: number
334+
grid_h: number
335+
config: Record<string, any>
331336
is_shared: boolean
332337
is_default: boolean
333338
is_owner: boolean
@@ -347,6 +352,14 @@ export interface WidgetData {
347352
labels: string[]
348353
datasets: Array<{ label: string; data: number[] }>
349354
}
355+
table_rows?: Array<{
356+
id: string
357+
label: string
358+
sub_label: string
359+
status: string
360+
direction?: string
361+
created_at: string
362+
}>
350363
}
351364

352365
export interface DataSourceInfo {
@@ -355,9 +368,17 @@ export interface DataSourceInfo {
355368
fields: string[]
356369
}
357370

358-
export const dashboardWidgetsService = {
359-
list: () => api.get<{ widgets: DashboardWidget[] }>('/dashboard/widgets'),
360-
get: (id: string) => api.get<DashboardWidget>(`/dashboard/widgets/${id}`),
371+
export interface LayoutItem {
372+
id: string
373+
grid_x: number
374+
grid_y: number
375+
grid_w: number
376+
grid_h: number
377+
}
378+
379+
export const widgetsService = {
380+
list: () => api.get<{ widgets: DashboardWidget[] }>('/widgets'),
381+
get: (id: string) => api.get<DashboardWidget>(`/widgets/${id}`),
361382
create: (data: {
362383
name: string
363384
description?: string
@@ -371,8 +392,9 @@ export const dashboardWidgetsService = {
371392
show_change?: boolean
372393
color?: string
373394
size?: string
395+
config?: Record<string, any>
374396
is_shared?: boolean
375-
}) => api.post<DashboardWidget>('/dashboard/widgets', data),
397+
}) => api.post<DashboardWidget>('/widgets', data),
376398
update: (id: string, data: Partial<{
377399
name: string
378400
description: string
@@ -386,21 +408,22 @@ export const dashboardWidgetsService = {
386408
show_change: boolean
387409
color: string
388410
size: string
411+
config: Record<string, any>
389412
is_shared: boolean
390-
}>) => api.put<DashboardWidget>(`/dashboard/widgets/${id}`, data),
391-
delete: (id: string) => api.delete(`/dashboard/widgets/${id}`),
413+
}>) => api.put<DashboardWidget>(`/widgets/${id}`, data),
414+
delete: (id: string) => api.delete(`/widgets/${id}`),
392415
getData: (id: string, params?: { from?: string; to?: string }) =>
393-
api.get<WidgetData>(`/dashboard/widgets/${id}/data`, { params }),
416+
api.get<WidgetData>(`/widgets/${id}/data`, { params }),
394417
getAllData: (params?: { from?: string; to?: string }) =>
395-
api.get<{ data: Record<string, WidgetData> }>('/dashboard/widgets/data', { params }),
418+
api.get<{ data: Record<string, WidgetData> }>('/widgets/data', { params }),
396419
getDataSources: () => api.get<{
397420
data_sources: DataSourceInfo[]
398421
metrics: string[]
399422
display_types: string[]
400423
operators: Array<{ value: string; label: string }>
401-
}>('/dashboard/widgets/data-sources'),
402-
reorder: (widgetIds: string[]) =>
403-
api.post('/dashboard/widgets/reorder', { widget_ids: widgetIds })
424+
}>('/widgets/data-sources'),
425+
saveLayout: (layout: LayoutItem[]) =>
426+
api.post('/widgets/layout', { layout })
404427
}
405428

406429
export const organizationService = {

0 commit comments

Comments
 (0)