chore: consolidate platform split checks
This commit is contained in:
84
webui/src/components/ConnectionTree.tsx
Normal file
84
webui/src/components/ConnectionTree.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import type { CSSProperties, ReactNode } from "react";
|
||||
|
||||
export type ConnectionTreeColumn<T> = {
|
||||
id: string;
|
||||
header: ReactNode;
|
||||
width?: string;
|
||||
align?: "left" | "center" | "right";
|
||||
render: (row: T, depth: number) => ReactNode;
|
||||
};
|
||||
|
||||
export type ConnectionTreeProps<T> = {
|
||||
rows: T[];
|
||||
columns: ConnectionTreeColumn<T>[];
|
||||
getRowKey: (row: T) => string;
|
||||
getChildren?: (row: T) => T[];
|
||||
renderActions?: (row: T, depth: number) => ReactNode;
|
||||
emptyText?: ReactNode;
|
||||
className?: string;
|
||||
rowClassName?: (row: T, depth: number) => string;
|
||||
};
|
||||
|
||||
type FlatRow<T> = {
|
||||
row: T;
|
||||
depth: number;
|
||||
};
|
||||
|
||||
export default function ConnectionTree<T>({
|
||||
rows,
|
||||
columns,
|
||||
getRowKey,
|
||||
getChildren,
|
||||
renderActions,
|
||||
emptyText = "i18n:govoplan-core.no_entries_configured.48e7b97c",
|
||||
className = "",
|
||||
rowClassName
|
||||
}: ConnectionTreeProps<T>) {
|
||||
const flatRows = flattenRows(rows, getChildren);
|
||||
const gridTemplateColumns = `${columns.map((column) => column.width || "minmax(0, 1fr)").join(" ")} ${renderActions ? "var(--connection-tree-actions-column, 196px)" : ""}`.trim();
|
||||
|
||||
return (
|
||||
<div className={`connection-tree ${className}`.trim()}>
|
||||
<div className="connection-tree-header" style={{ gridTemplateColumns }}>
|
||||
{columns.map((column) =>
|
||||
<div className={`connection-tree-cell ${column.align ? `align-${column.align}` : ""}`.trim()} key={column.id}>
|
||||
{column.header}
|
||||
</div>
|
||||
)}
|
||||
{renderActions && <div className="connection-tree-cell align-right">i18n:govoplan-core.actions.c3cd636a</div>}
|
||||
</div>
|
||||
{flatRows.length === 0 && <div className="connection-tree-empty">{emptyText}</div>}
|
||||
{flatRows.map(({ row, depth }) => {
|
||||
const className = ["connection-tree-row", depth > 0 ? "is-child" : "is-parent", rowClassName?.(row, depth) || ""].filter(Boolean).join(" ");
|
||||
return (
|
||||
<div className={className} style={{ gridTemplateColumns }} key={getRowKey(row)}>
|
||||
{columns.map((column, index) =>
|
||||
<div
|
||||
className={`connection-tree-cell ${column.align ? `align-${column.align}` : ""} ${index === 0 ? "connection-tree-primary-cell" : ""}`.trim()}
|
||||
key={column.id}>
|
||||
{index === 0 ?
|
||||
<div className="connection-tree-primary-content" style={{ "--connection-tree-depth": String(depth) } as CSSProperties}>
|
||||
{column.render(row, depth)}
|
||||
</div> :
|
||||
column.render(row, depth)
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
{renderActions && <div className="connection-tree-cell align-right connection-tree-actions">{renderActions(row, depth)}</div>}
|
||||
</div>);
|
||||
|
||||
})}
|
||||
</div>);
|
||||
|
||||
}
|
||||
|
||||
function flattenRows<T>(rows: T[], getChildren?: (row: T) => T[]): FlatRow<T>[] {
|
||||
const result: FlatRow<T>[] = [];
|
||||
for (const row of rows) {
|
||||
result.push({ row, depth: 0 });
|
||||
for (const child of getChildren?.(row) ?? []) {
|
||||
result.push({ row: child, depth: 1 });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user