feat: add dashboards — tables, CRUD API, widget data endpoint
- New dashboards table (name, description, layout, is_default) - New dashboard_widgets table (view_id, title, widget_type, position, config) - GET/POST/PATCH/DELETE /dashboards - GET/POST/PATCH/DELETE /dashboards/:id/widgets - GET /dashboards/:id/widgets/:id/data — runs saved view filters, returns pre-aggregated data for count/ticket_list/status_chart/grouped_counts - is_default uniqueness enforced on PATCH Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
39
web/src/components/widgets/grouped-counts-widget.tsx
Normal file
39
web/src/components/widgets/grouped-counts-widget.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
"use client";
|
||||
|
||||
import type { WidgetData } from "@/lib/types";
|
||||
|
||||
export function GroupedCountsWidget({ data }: { data: WidgetData }) {
|
||||
const groups = data.groups ?? {};
|
||||
const entries = Object.entries(groups).sort(([, a], [, b]) => b - a);
|
||||
const max = entries.length > 0 ? Math.max(...entries.map(([, c]) => c)) : 1;
|
||||
|
||||
if (entries.length === 0) {
|
||||
return (
|
||||
<div className="flex h-full items-center justify-center rounded-lg border border-border bg-card p-4">
|
||||
<p className="text-xs text-muted-foreground">No data</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col overflow-hidden rounded-lg border border-border bg-card">
|
||||
<div className="border-b border-border px-3 py-2">
|
||||
<span className="text-xs font-semibold text-foreground">{data.title}</span>
|
||||
</div>
|
||||
<div className="flex-1 space-y-1.5 overflow-auto p-3">
|
||||
{entries.map(([label, count]) => (
|
||||
<div key={label} className="flex items-center gap-2 text-xs">
|
||||
<span className="w-20 shrink-0 truncate text-foreground">{label}</span>
|
||||
<div className="flex-1">
|
||||
<div
|
||||
className="h-2.5 rounded-sm bg-primary/60 transition-all"
|
||||
style={{ width: `${Math.round((count / max) * 100)}%` }}
|
||||
/>
|
||||
</div>
|
||||
<span className="w-8 shrink-0 text-right tabular-nums text-muted-foreground">{count}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user