Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions src/ui/src/components/data-table/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ export interface DataTableProps<TData, TSectionMeta = unknown> {
onRowDoubleClick?: (row: TData) => void;
/** For middle-click: returns URL for new tab, or undefined to call onRowClick */
getRowHref?: (row: TData) => string | undefined;
/** Native tooltip (title attribute) for a row, shown on hover */
getRowTitle?: (row: TData) => string | undefined;
selectedRowId?: string;
/** Override default header cell padding/styling for all columns (default: "px-4 py-3") */
headerClassName?: string;
Expand Down Expand Up @@ -141,6 +143,7 @@ function DataTableInner<TData, TSectionMeta = unknown>({
onFocusedRowChange,
onRowDoubleClick,
getRowHref,
getRowTitle,
selectedRowId,
headerClassName: tableHeaderClassName,
theadClassName,
Expand Down Expand Up @@ -565,6 +568,7 @@ function DataTableInner<TData, TSectionMeta = unknown>({
onRowClick={onRowClick}
onRowDoubleClick={onRowDoubleClick}
getRowHref={getRowHref}
getRowTitle={getRowTitle}
selectedRowId={selectedRowId}
getRowId={getRowId}
rowClassName={rowClassName}
Expand Down
4 changes: 4 additions & 0 deletions src/ui/src/components/data-table/virtual-table-body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export interface VirtualTableBodyProps<TData, TSectionMeta = unknown> {
onRowDoubleClick?: (item: TData, index: number) => void;
/** Returns URL for middle-click "open in new tab", or undefined to fall back to onRowClick */
getRowHref?: (item: TData) => string | undefined;
/** Native tooltip (title attribute) for a row, shown on hover */
getRowTitle?: (item: TData) => string | undefined;
selectedRowId?: string;
getRowId?: (item: TData) => string;
rowClassName?: string | ((item: TData, index: number) => string);
Expand All @@ -61,6 +63,7 @@ function VirtualTableBodyInner<TData, TSectionMeta = unknown>({
onRowClick,
onRowDoubleClick,
getRowHref,
getRowTitle,
selectedRowId,
getRowId,
rowClassName,
Expand Down Expand Up @@ -276,6 +279,7 @@ function VirtualTableBodyInner<TData, TSectionMeta = unknown>({
data-interactive={isInteractive || undefined}
aria-rowindex={virtualRow.index + 2}
aria-selected={isSelected ? true : undefined}
title={getRowTitle?.(rowData)}
tabIndex={tabIndex}
className={cn(
"data-table-row border-b border-zinc-200 dark:border-zinc-800",
Expand Down
5 changes: 4 additions & 1 deletion src/ui/src/components/filter-bar/filter-bar-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,10 @@ function SuggestionItemInner<T>({ suggestion, onSelect }: SuggestionItemProps<T>
{suggestion.type === "field" ? (
<span className="fb-suggestion-field-prefix">{suggestion.label}</span>
) : (
<span>{suggestion.label}</span>
<span>
<span className="fb-suggestion-field-prefix">{suggestion.field.prefix}</span>
{suggestion.label.slice(suggestion.field.prefix.length)}
</span>
)}
</span>
{suggestion.hint && <span className="text-muted-foreground ml-2 shrink-0 text-xs">{suggestion.hint}</span>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function PriorityBadge({ value, colorClass }: { value: number; colorClass: strin
);
}

function buildWorkflowsUrl(row: OccupancyFlatRow, groupBy: OccupancyGroupBy, searchChips: SearchChip[]): string {
export function buildWorkflowsUrl(row: OccupancyFlatRow, groupBy: OccupancyGroupBy, searchChips: SearchChip[]): string {
const params: string[] = [];
if (row._type === "parent") {
params.push(`f=${groupBy}:${encodeURIComponent(row.key)}`);
Expand Down Expand Up @@ -198,13 +198,9 @@ export function createOccupancyColumns(
const href = buildWorkflowsUrl(original, groupBy, searchChips);
if (original._type === "child") {
return (
<Link
href={href}
className="hover:text-primary pl-2 text-sm text-zinc-600 underline decoration-zinc-400/50 underline-offset-2 transition-colors hover:decoration-current dark:text-zinc-400"
onClick={(e) => e.stopPropagation()}
>
<span className="pl-2 text-sm text-zinc-600 dark:text-zinc-400">
{original.key}
</Link>
</span>
);
}
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"use client";

import { useMemo, useCallback, memo } from "react";
import { useRouter } from "next/navigation";
import { DataTable } from "@/components/data-table/data-table";
import { TableEmptyState } from "@/components/data-table/table-empty-state";
import { TableLoadingSkeleton, TableErrorState } from "@/components/data-table/table-states";
Expand All @@ -31,12 +32,11 @@ import {
asOccupancyColumnIds,
OCCUPANCY_COLUMN_SIZE_CONFIG,
} from "@/features/occupancy/lib/occupancy-columns";
import { createOccupancyColumns } from "@/features/occupancy/components/occupancy-column-defs";
import { createOccupancyColumns, buildWorkflowsUrl } from "@/features/occupancy/components/occupancy-column-defs";
import { useOccupancyTableStore } from "@/features/occupancy/stores/occupancy-table-store";
import "@/features/occupancy/styles/occupancy.css";

const FIXED_COLUMNS = Array.from(MANDATORY_COLUMN_IDS);
const isOccupancyRowInteractive = (row: OccupancyFlatRow) => row._type === "parent";

function flattenForTable(groups: OccupancyGroup[], expandedKeys: Set<string>): OccupancyFlatRow[] {
return groups.flatMap((group, groupIndex) => {
Expand Down Expand Up @@ -88,6 +88,7 @@ export const OccupancyDataTable = memo(function OccupancyDataTable({
error,
onRetry,
}: OccupancyDataTableProps) {
const router = useRouter();
const compactMode = useCompactMode();
const rowHeight = compactMode ? TABLE_ROW_HEIGHTS.COMPACT : TABLE_ROW_HEIGHTS.NORMAL;

Expand All @@ -114,9 +115,30 @@ export const OccupancyDataTable = memo(function OccupancyDataTable({

const handleRowClick = useCallback(
(row: OccupancyFlatRow) => {
if (isOccupancyRowInteractive(row)) onToggleExpand(row.key);
if (row._type === "parent") {
onToggleExpand(row.key);
} else {
router.push(buildWorkflowsUrl(row, groupBy, searchChips));
}
},
[onToggleExpand],
[onToggleExpand, router, groupBy, searchChips],
);

const getRowHref = useCallback(
(row: OccupancyFlatRow) => {
if (row._type === "child") return buildWorkflowsUrl(row, groupBy, searchChips);
return undefined;
},
[groupBy, searchChips],
);

const getRowTitle = useCallback(
(row: OccupancyFlatRow) => {
if (row._type !== "child") return undefined;
if (groupBy === "pool") return `View ${row.key}'s workflows`;
return `View workflows for ${row.key}`;
},
[groupBy],
);

// Zebra striping keyed on group index so parent + children share the same stripe
Expand Down Expand Up @@ -171,8 +193,9 @@ export const OccupancyDataTable = memo(function OccupancyDataTable({
isLoading={isLoading}
emptyContent={emptyContent}
onRowClick={handleRowClick}
getRowHref={getRowHref}
getRowTitle={getRowTitle}
rowClassName={rowClassName}
isRowInteractive={isOccupancyRowInteractive}
/>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/ui/src/features/occupancy/styles/occupancy.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
}

.occupancy-row--child {
@apply cursor-default text-sm;
@apply cursor-pointer text-sm;
}

.occupancy-row:not(.occupancy-row--child):hover {
Expand Down
Loading