Skip to content

Commit ed6fb79

Browse files
feat: add data table toggle to HistoricalTrendWidget properties and implement table view in widget UI
1 parent bddf6e7 commit ed6fb79

2 files changed

Lines changed: 54 additions & 18 deletions

File tree

src/components/dashboard-builder/PropertiesPanel.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,16 @@ export default function PropertiesPanel() {
199199
/>
200200
<Label htmlFor="showMax" className="font-normal cursor-pointer text-sm">Show Max Value</Label>
201201
</div>
202+
<div className="flex items-center gap-2">
203+
<input
204+
type="checkbox"
205+
id="showTable"
206+
className="w-4 h-4 rounded border-input text-primary focus:ring-primary cursor-pointer"
207+
checked={draftConfig.showTable === true}
208+
onChange={(e) => handleConfigChange({ showTable: e.target.checked })}
209+
/>
210+
<Label htmlFor="showTable" className="font-normal cursor-pointer text-sm">Show Data Table</Label>
211+
</div>
202212
</div>
203213
</div>
204214
)}

src/components/dashboard-builder/widgets/HistoricalTrendWidget.tsx

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export function HistoricalTrendWidget({
4242
const deviceKey = config.config.deviceKey;
4343
const strokeColor = config.config.strokeColor || "hsl(var(--primary))";
4444
const unit = config.config.unit;
45-
45+
4646
const showLatest = config.config.showLatest !== false;
4747
const showMin = config.config.showMin !== false;
4848
const showAvg = config.config.showAvg !== false;
@@ -113,7 +113,7 @@ export function HistoricalTrendWidget({
113113
const series = [];
114114
for (let i = 0; i < rawSeries.length; i++) {
115115
const point = { ...rawSeries[i] };
116-
116+
117117
let isGapStart = false;
118118
let isGapEnd = false;
119119

@@ -129,7 +129,9 @@ export function HistoricalTrendWidget({
129129
}
130130

131131
if (isGapStart || isGapEnd) {
132-
point[`${deviceKey}_gap`] = point[deviceKey];
132+
point[`${deviceKey}_gap`] = point[deviceKey];
133+
} else {
134+
point[`${deviceKey}_gap`] = null;
133135
}
134136

135137
series.push(point);
@@ -139,7 +141,7 @@ export function HistoricalTrendWidget({
139141
const nextTs = rawSeries[i + 1].timestamp;
140142
const currentVal = point[deviceKey];
141143
const nextVal = rawSeries[i + 1][deviceKey];
142-
144+
143145
series.push({
144146
time: new Date((currentTs + (nextTs - currentTs) / 2) * 1000).toLocaleString(undefined, {
145147
year: "numeric",
@@ -205,7 +207,7 @@ export function HistoricalTrendWidget({
205207

206208
let lastValue = undefined;
207209
let lastTime = "";
208-
210+
209211
for (let i = data.length - 1; i >= 0; i--) {
210212
if (data[i][deviceKey] !== null && data[i][deviceKey] !== undefined) {
211213
lastValue = data[i][deviceKey];
@@ -315,18 +317,18 @@ export function HistoricalTrendWidget({
315317
No data available
316318
</div>
317319
) : (
318-
<>
319-
{stats && showLatest && (
320-
<div className="absolute top-2 right-4 z-10 flex flex-col items-end text-right p-1.5 rounded pointer-events-none">
321-
{/* <span className="text-[10px] uppercase font-semibold text-muted-foreground tracking-wider leading-none">Latest Value</span> */}
322-
<div className="flex items-baseline gap-1 mt-0.5">
323-
<span className="text-xl font-bold text-foreground leading-none">{stats.last}</span>
324-
{unit && <span className="text-xs font-semibold text-muted-foreground">{unit}</span>}
320+
<div className={`absolute inset-4 flex ${config.config.showTable ? "gap-4" : ""}`}>
321+
<div className={`relative ${config.config.showTable ? "basis-[60%] overflow-hidden" : "w-full overflow-hidden"}`} style={{ height: "100%" }}>
322+
{stats && showLatest && (
323+
<div className="absolute top-0 right-1 z-10 flex flex-col items-end text-right p-1.5 rounded pointer-events-none">
324+
{/* <span className="text-[10px] uppercase font-semibold text-muted-foreground tracking-wider leading-none">Latest Value</span> */}
325+
<div className="flex items-baseline gap-1 mt-0.5">
326+
<span className="text-xl font-bold text-foreground leading-none">{stats.last}</span>
327+
{unit && <span className="text-xs font-semibold text-muted-foreground">{unit}</span>}
328+
</div>
329+
<span className="text-[9px] text-muted-foreground mt-0.5 leading-none">{stats.lastTime}</span>
325330
</div>
326-
<span className="text-[9px] text-muted-foreground mt-0.5 leading-none">{stats.lastTime}</span>
327-
</div>
328-
)}
329-
<div className="absolute inset-4">
331+
)}
330332
<ResponsiveContainer width="100%" height="100%">
331333
<ComposedChart data={data}>
332334
<defs>
@@ -416,7 +418,31 @@ export function HistoricalTrendWidget({
416418
</ComposedChart>
417419
</ResponsiveContainer>
418420
</div>
419-
</>
421+
422+
{config.config.showTable && (
423+
<div className="basis-[40%] flex flex-col h-full border rounded bg-card overflow-hidden">
424+
<div className="bg-muted/50 px-3 py-1.5 border-b text-xs font-semibold flex justify-between">
425+
<span>Time</span>
426+
<span>{config.title} {unit ? `(${unit})` : ''}</span>
427+
</div>
428+
<div className="flex-1 overflow-y-auto">
429+
<table className="w-full text-xs text-left">
430+
<tbody className="divide-y divide-border">
431+
{data
432+
.filter((d) => d[deviceKey] !== null && d[deviceKey] !== undefined)
433+
.reverse()
434+
.map((row, idx) => (
435+
<tr key={`${row.timestamp}-${idx}`} className="hover:bg-muted/30">
436+
<td className="px-3 py-1.5 truncate text-muted-foreground whitespace-nowrap">{row.time}</td>
437+
<td className="px-3 py-1.5 whitespace-nowrap text-right font-medium">{row[deviceKey]}</td>
438+
</tr>
439+
))}
440+
</tbody>
441+
</table>
442+
</div>
443+
</div>
444+
)}
445+
</div>
420446
)}
421447
</CardContent>
422448
{stats && showFooter && (
@@ -427,7 +453,7 @@ export function HistoricalTrendWidget({
427453
<span className="font-medium text-foreground truncate w-full">{stats.min}{unit ? ` ${unit}` : ''} | {stats.minTime}</span>
428454
</div>
429455
)}
430-
456+
431457
{showAvg && (
432458
<div className="flex flex-col items-center text-center truncate flex-1">
433459
<span className="text-[10px] font-semibold uppercase text-muted-foreground tracking-wider">Avg</span>

0 commit comments

Comments
 (0)