Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ function humanizeChartType(type: string): string {
return 'Funnel';
case 'metric':
return 'Metric';
case 'table':
return 'Table';
case 'retention':
return 'Retention';
case 'histogram':
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { List, Rows3, Search, X } from 'lucide-react';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import { Switch } from '@/components/ui/switch';
import { Columns3, List, Rows3, Search, X } from 'lucide-react';

export type ReportTableAliasableColumn = {
key: string;
label: string;
};

interface ReportTableToolbarProps {
grouped?: boolean;
onToggleGrouped?: () => void;
search: string;
onSearchChange?: (value: string) => void;
onUnselectAll?: () => void;
aliasableColumns?: ReportTableAliasableColumn[];
columnAliases?: Record<string, string>;
hiddenColumnKeys?: string[];
dateMode?: 'columns' | 'aggregate';
onColumnAliasChange?: (key: string, alias: string) => void;
onColumnVisibilityChange?: (key: string, visible: boolean) => void;
onDateModeChange?: (dateMode: 'columns' | 'aggregate') => void;
}

export function ReportTableToolbar({
Expand All @@ -16,7 +35,18 @@ export function ReportTableToolbar({
search,
onSearchChange,
onUnselectAll,
aliasableColumns = [],
columnAliases = {},
hiddenColumnKeys = [],
dateMode = 'columns',
onColumnAliasChange,
onColumnVisibilityChange,
onDateModeChange,
}: ReportTableToolbarProps) {
const showColumnControls =
(!!onColumnAliasChange || !!onColumnVisibilityChange || !!onDateModeChange) &&
aliasableColumns.length > 0;

return (
<div className="col md:row md:items-center gap-2 p-2 border-b md:justify-between">
{onSearchChange && (
Expand All @@ -31,6 +61,73 @@ export function ReportTableToolbar({
</div>
)}
<div className="flex items-center gap-2">
{showColumnControls && (
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" size="sm" icon={Columns3}>
Columns
</Button>
</PopoverTrigger>
<PopoverContent align="end" className="w-96 p-0" portal>
<div className="border-b p-3">
<div className="font-medium">Table columns</div>
<p className="mt-1 text-xs text-muted-foreground">
Show, hide, and rename columns for this table chart only.
</p>
</div>
{onDateModeChange && (
<div className="flex items-center justify-between gap-4 border-b p-3">
<div>
<div className="text-sm font-medium">
Aggregate date columns
</div>
<p className="mt-1 text-xs text-muted-foreground">
Show one total column instead of one column per interval.
</p>
</div>
<Switch
checked={dateMode === 'aggregate'}
onCheckedChange={(checked) =>
onDateModeChange(checked ? 'aggregate' : 'columns')
}
/>
</div>
)}
<div className="max-h-96 overflow-auto p-3">
<div className="flex flex-col gap-3">
{aliasableColumns.map((column) => (
<div key={column.key} className="flex items-start gap-2">
{onColumnVisibilityChange && (
<Checkbox
checked={!hiddenColumnKeys.includes(column.key)}
onCheckedChange={(checked) =>
onColumnVisibilityChange(column.key, checked === true)
}
className="mt-6 h-4 w-4 shrink-0"
/>
)}
<label className="flex min-w-0 flex-1 flex-col gap-1">
<span className="text-xs font-medium text-muted-foreground">
{column.label}
</span>
<Input
placeholder={column.label}
value={columnAliases[column.key] ?? ''}
onChange={(event) =>
onColumnAliasChange?.(
column.key,
event.target.value,
)
}
/>
</label>
</div>
))}
</div>
</div>
</PopoverContent>
</Popover>
)}
{onToggleGrouped && (
<Button
variant={'outline'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,20 @@ function getBreakdownPropertyNames(
return Array.from({ length: breakdownCount }, (_, i) => `Breakdown ${i + 1}`);
}

function getBreakdownPropertyKeys(
series: IChartData['series'],
breakdowns: Array<{ name: string }>,
): string[] {
if (breakdowns.length > 0) {
return breakdowns.map((b, index) => `${b.name}#${index}`);
}

if (series.length === 0) return [];
const firstSerie = series[0];
const breakdownCount = firstSerie.names.length - 1;
return Array.from({ length: breakdownCount }, (_, i) => `breakdown-${i + 1}`);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* Transform series into flat table rows
*/
Expand Down Expand Up @@ -659,16 +673,24 @@ export function transformToTableData(
rows: TableRow[] | GroupedTableRow[];
dates: string[];
breakdownPropertyNames: string[];
breakdownPropertyKeys: string[];
} {
const dates = getUniqueDates(data.series);
const originalBreakdownPropertyNames = getBreakdownPropertyNames(
data.series,
breakdowns,
);
const originalBreakdownPropertyKeys = getBreakdownPropertyKeys(
data.series,
breakdowns,
);

// Reorder breakdowns by unique count (fewest first)
const { reorderedNames: breakdownPropertyNames, reorderMap } =
reorderBreakdownsByUniqueCount(data.series, originalBreakdownPropertyNames);
const breakdownPropertyKeys = reorderMap.map(
(oldIndex) => originalBreakdownPropertyKeys[oldIndex] ?? `breakdown-${oldIndex + 1}`,
);

// Reorder breakdown values in series before creating rows
const reorderedSeries = data.series.map((serie) => {
Expand All @@ -695,6 +717,7 @@ export function transformToTableData(
rows,
dates,
breakdownPropertyNames,
breakdownPropertyKeys,
};
}

Expand All @@ -709,16 +732,24 @@ export function transformToHierarchicalGroups(
groups: Array<GroupedItem<TableRow>>;
dates: string[];
breakdownPropertyNames: string[];
breakdownPropertyKeys: string[];
} {
const dates = getUniqueDates(data.series);
const originalBreakdownPropertyNames = getBreakdownPropertyNames(
data.series,
breakdowns,
);
const originalBreakdownPropertyKeys = getBreakdownPropertyKeys(
data.series,
breakdowns,
);

// Reorder breakdowns by unique count (fewest first)
const { reorderedNames: breakdownPropertyNames, reorderMap } =
reorderBreakdownsByUniqueCount(data.series, originalBreakdownPropertyNames);
const breakdownPropertyKeys = reorderMap.map(
(oldIndex) => originalBreakdownPropertyKeys[oldIndex] ?? `breakdown-${oldIndex + 1}`,
);

// Reorder breakdown values in series before creating rows
const reorderedSeries = data.series.map((serie) => {
Expand All @@ -738,5 +769,6 @@ export function transformToHierarchicalGroups(
groups,
dates,
breakdownPropertyNames,
breakdownPropertyKeys,
};
}
Loading