Feat: Make the table last column non-resizable and add a restore columns button
This commit is contained in:
parent
1a65af7602
commit
cdf9d77b45
7 changed files with 187 additions and 30 deletions
26
src/frontend/package-lock.json
generated
26
src/frontend/package-lock.json
generated
|
|
@ -26,6 +26,7 @@
|
|||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-toggle": "^1.0.3",
|
||||
"@radix-ui/react-tooltip": "^1.0.6",
|
||||
"@tabler/icons-react": "^2.32.0",
|
||||
"@tailwindcss/forms": "^0.5.6",
|
||||
|
|
@ -2761,6 +2762,31 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-toggle": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.0.3.tgz",
|
||||
"integrity": "sha512-Pkqg3+Bc98ftZGsl60CLANXQBBQ4W3mTFS9EJvNxKMZ7magklKV69/id1mlAlOFDDfHvlCms0fx8fA4CMKDJHg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/primitive": "1.0.1",
|
||||
"@radix-ui/react-primitive": "1.0.3",
|
||||
"@radix-ui/react-use-controllable-state": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz",
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-toggle": "^1.0.3",
|
||||
"@radix-ui/react-tooltip": "^1.0.6",
|
||||
"@tabler/icons-react": "^2.32.0",
|
||||
"@tailwindcss/forms": "^0.5.6",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
export default function TableToolbar({ children }): JSX.Element {
|
||||
return <div className="align-center flex transition-all">{children}</div>;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import "ag-grid-community/styles/ag-grid.css"; // Mandatory CSS required by the grid
|
||||
import "ag-grid-community/styles/ag-theme-quartz.css"; // Optional Theme applied to the grid
|
||||
import { AgGridReact, AgGridReactProps } from "ag-grid-react";
|
||||
import { ElementRef, forwardRef } from "react";
|
||||
import { ElementRef, forwardRef, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
DEFAULT_TABLE_ALERT_MSG,
|
||||
DEFAULT_TABLE_ALERT_TITLE,
|
||||
|
|
@ -11,6 +11,13 @@ import "../../style/ag-theme-shadcn.css"; // Custom CSS applied to the grid
|
|||
import { cn, toTitleCase } from "../../utils/utils";
|
||||
import ForwardedIconComponent from "../genericIconComponent";
|
||||
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
|
||||
import { Select, SelectContent, SelectTrigger } from "../ui/select";
|
||||
import { SelectItem } from "@radix-ui/react-select";
|
||||
import { Button } from "../ui/button";
|
||||
import { Toggle } from "../ui/toggle";
|
||||
import TableToolbar from "./components/tableToolbar.tsx";
|
||||
import ShadTooltip from "../shadTooltipComponent";
|
||||
import resetGrid from "./utils/reset-grid-columns";
|
||||
|
||||
interface TableComponentProps extends AgGridReactProps {
|
||||
columnDefs: NonNullable<AgGridReactProps["columnDefs"]>;
|
||||
|
|
@ -32,7 +39,67 @@ const TableComponent = forwardRef<
|
|||
},
|
||||
ref,
|
||||
) => {
|
||||
const gridRef = useRef(null);
|
||||
const realRef = ref?.current ? ref : gridRef;
|
||||
const dark = useDarkStore((state) => state.dark);
|
||||
|
||||
const makeLastColumnNonResizable = (columnDefs) => {
|
||||
columnDefs.forEach((colDef, index) => {
|
||||
colDef.resizable = index !== columnDefs.length - 1;
|
||||
});
|
||||
return columnDefs;
|
||||
};
|
||||
|
||||
const onGridReady = (params) => {
|
||||
realRef.current = params;
|
||||
const updatedColumnDefs = makeLastColumnNonResizable([
|
||||
...props.columnDefs,
|
||||
]);
|
||||
params.api.setColumnDefs(updatedColumnDefs);
|
||||
if (props.onGridReady) props.onGridReady(params);
|
||||
};
|
||||
|
||||
const onColumnMoved = (params) => {
|
||||
const updatedColumnDefs = makeLastColumnNonResizable(
|
||||
params.columnApi.getAllGridColumns().map((col) => col.getColDef()),
|
||||
);
|
||||
params.api.setColumnDefs(updatedColumnDefs);
|
||||
if (props.onColumnMoved) props.onColumnMoved(params);
|
||||
};
|
||||
|
||||
let colDef = props.columnDefs.map((col, index) => {
|
||||
let newCol = {
|
||||
...col,
|
||||
headerName: toTitleCase(col.headerName),
|
||||
};
|
||||
if (index === props.columnDefs.length - 1) {
|
||||
newCol = {
|
||||
...col,
|
||||
resizable: false,
|
||||
};
|
||||
}
|
||||
if (props.onSelectionChanged && index === 0) {
|
||||
newCol = {
|
||||
...newCol,
|
||||
checkboxSelection: true,
|
||||
headerCheckboxSelection: true,
|
||||
headerCheckboxSelectionFilteredOnly: true,
|
||||
};
|
||||
}
|
||||
if (
|
||||
(typeof props.editable === "boolean" && props.editable) ||
|
||||
(Array.isArray(props.editable) &&
|
||||
props.editable.includes(newCol.headerName ?? ""))
|
||||
) {
|
||||
newCol = {
|
||||
...newCol,
|
||||
editable: true,
|
||||
};
|
||||
}
|
||||
return newCol;
|
||||
});
|
||||
let rowDef = props.rowData;
|
||||
|
||||
if (props.rowData.length === 0) {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center rounded-md border">
|
||||
|
|
@ -47,39 +114,12 @@ const TableComponent = forwardRef<
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const colDef = props.columnDefs.map((col, index) => {
|
||||
let newCol = {
|
||||
...col,
|
||||
headerName: toTitleCase(col.headerName),
|
||||
};
|
||||
if (props.onSelectionChanged && index === 0) {
|
||||
newCol = {
|
||||
...newCol,
|
||||
checkboxSelection: true,
|
||||
headerCheckboxSelection: true,
|
||||
headerCheckboxSelectionFilteredOnly: true,
|
||||
};
|
||||
}
|
||||
console.log(props.editable, col.headerName);
|
||||
if (
|
||||
(typeof props.editable === "boolean" && props.editable) ||
|
||||
(Array.isArray(props.editable) &&
|
||||
props.editable.includes(newCol.headerName ?? ""))
|
||||
) {
|
||||
newCol = {
|
||||
...newCol,
|
||||
editable: true,
|
||||
};
|
||||
}
|
||||
return newCol;
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
dark ? "ag-theme-quartz-dark" : "ag-theme-quartz",
|
||||
"ag-theme-shadcn flex h-full flex-col",
|
||||
"relative",
|
||||
)} // applying the grid theme
|
||||
>
|
||||
<AgGridReact
|
||||
|
|
@ -89,8 +129,41 @@ const TableComponent = forwardRef<
|
|||
minWidth: 100,
|
||||
}}
|
||||
columnDefs={colDef}
|
||||
ref={ref}
|
||||
rowData={rowDef}
|
||||
ref={realRef}
|
||||
pagination={true}
|
||||
onGridReady={onGridReady}
|
||||
onColumnMoved={onColumnMoved}
|
||||
/>
|
||||
{/*<div className="absolute left-2 bottom-1 cursor-pointer">
|
||||
<div
|
||||
className="flex h-10 items-center justify-center px-2 pl-3 rounded-md border border-ring/60 text-sm text-[#bccadc] ring-offset-background placeholder:text-muted-foreground hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
onClick={() => setShow(!show)}
|
||||
>
|
||||
<ForwardedIconComponent name="Settings"></ForwardedIconComponent>
|
||||
<ForwardedIconComponent name={show ? "ChevronLeft" : "ChevronRight"} className="transition-all"></ForwardedIconComponent>
|
||||
</div>
|
||||
</div>*/}
|
||||
<div
|
||||
className={cn(
|
||||
"absolute bottom-1 left-2 rounded-md border border-border transition-all",
|
||||
)}
|
||||
>
|
||||
<ShadTooltip content={"Reset Columns"} styleClasses="z-50">
|
||||
<Toggle
|
||||
className="h-10 w-10"
|
||||
onClick={() => {
|
||||
resetGrid(realRef);
|
||||
}}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
name="RotateCcw"
|
||||
strokeWidth={2}
|
||||
className="h-8 w-8 text-[#bccadc]"
|
||||
></ForwardedIconComponent>
|
||||
</Toggle>
|
||||
</ShadTooltip>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
export default function resetGrid(ref) {
|
||||
if (ref?.current && ref?.current.api) {
|
||||
ref.current.api.resetColumnState();
|
||||
}
|
||||
}
|
||||
45
src/frontend/src/components/ui/toggle.tsx
Normal file
45
src/frontend/src/components/ui/toggle.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as TogglePrimitive from "@radix-ui/react-toggle";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
|
||||
import { cn } from "../../utils/utils";
|
||||
|
||||
const toggleVariants = cva(
|
||||
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-transparent",
|
||||
outline:
|
||||
"border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 px-3",
|
||||
sm: "h-9 px-2.5",
|
||||
lg: "h-11 px-5",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const Toggle = React.forwardRef<
|
||||
React.ElementRef<typeof TogglePrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
|
||||
VariantProps<typeof toggleVariants>
|
||||
>(({ className, variant, size, ...props }, ref) => (
|
||||
<TogglePrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(toggleVariants({ variant, size, className }))}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
Toggle.displayName = TogglePrimitive.Root.displayName;
|
||||
|
||||
export { Toggle, toggleVariants };
|
||||
|
|
@ -143,6 +143,8 @@ import {
|
|||
X,
|
||||
XCircle,
|
||||
Zap,
|
||||
RotateCcw,
|
||||
Settings,
|
||||
} from "lucide-react";
|
||||
import { FaApple, FaDiscord, FaGithub } from "react-icons/fa";
|
||||
import { AWSIcon } from "../icons/AWS";
|
||||
|
|
@ -526,4 +528,6 @@ export const nodeIconsLucide: iconsType = {
|
|||
FolderPlusIcon,
|
||||
FolderIcon,
|
||||
Discord: FaDiscord,
|
||||
RotateCcw,
|
||||
Settings,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue