mirror of
https://github.com/cssgunc/compass.git
synced 2025-04-06 20:50:17 -04:00
Add editing of table fields, significant refactoring
This makes RowOpenAction obsolete with PrimaryTableCell. Dropdowns to be implemented at a later point. Lots of typing and further styling needed.
This commit is contained in:
parent
b188c783ce
commit
d689e22dd8
|
@ -12,12 +12,14 @@ import {
|
|||
sortingFns,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { ChangeEvent, useState, useEffect, FunctionComponent } from "react";
|
||||
import { ChangeEvent, useState, useEffect, FunctionComponent, useRef, ChangeEventHandler, Key } from "react";
|
||||
import { RowOptionMenu } from "./RowOptionMenu";
|
||||
import { RowOpenAction } from "./RowOpenAction";
|
||||
import { TableAction } from "./TableAction";
|
||||
import { Bars2Icon, AtSymbolIcon, HashtagIcon, ArrowDownCircleIcon } from "@heroicons/react/24/solid";
|
||||
import { rankItem } from "@tanstack/match-sorter-utils";
|
||||
import { TableCell } from "./TableCell";
|
||||
import { PrimaryTableCell } from "./PrimaryTableCell";
|
||||
|
||||
const usersExample = usersImport as unknown as User[];
|
||||
|
||||
|
@ -80,19 +82,19 @@ export const Table = () => {
|
|||
}),
|
||||
columnHelper.accessor("username", {
|
||||
header: () => <><Bars2Icon className="inline align-top h-4 mr-2" /> Username</>,
|
||||
cell: (info) => <RowOpenAction title={info.getValue()} />,
|
||||
cell: PrimaryTableCell,
|
||||
}),
|
||||
columnHelper.accessor("role", {
|
||||
header: () => <><ArrowDownCircleIcon className="inline align-top h-4" /> Role</>,
|
||||
cell: (info) => info.renderValue(),
|
||||
cell: TableCell,
|
||||
}),
|
||||
columnHelper.accessor("email", {
|
||||
header: () => <><AtSymbolIcon className="inline align-top h-4" /> Email</>,
|
||||
cell: (info) => info.renderValue(),
|
||||
cell: TableCell,
|
||||
}),
|
||||
columnHelper.accessor("program", {
|
||||
header: () => <><ArrowDownCircleIcon className="inline align-top h-4" /> Program</>,
|
||||
cell: (info) => info.renderValue(),
|
||||
cell: TableCell,
|
||||
}),
|
||||
];
|
||||
|
||||
|
@ -105,6 +107,11 @@ export const Table = () => {
|
|||
setQuery(String(target.value));
|
||||
}
|
||||
|
||||
const handleCellChange = (e: ChangeEvent, key: Key) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
console.log(key);
|
||||
}
|
||||
|
||||
// TODO: Filtering
|
||||
// TODO: Sorting
|
||||
|
||||
|
@ -121,6 +128,21 @@ export const Table = () => {
|
|||
globalFilterFn: fuzzyFilter,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
meta: {
|
||||
updateData: (rowIndex: number, columnId: string, value: string) => {
|
||||
setData(old =>
|
||||
old.map((row, index) => {
|
||||
if (index === rowIndex) {
|
||||
return {
|
||||
...old[rowIndex],
|
||||
[columnId]: value,
|
||||
};
|
||||
}
|
||||
return row;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -163,7 +185,11 @@ export const Table = () => {
|
|||
key={row.id}
|
||||
>
|
||||
{row.getVisibleCells().map((cell, i) => (
|
||||
<TableCell key={cell.id} cell={cell} />
|
||||
<td key={cell.id}
|
||||
className={"p-2 [&:nth-child(n+3)]:border-x relative first:text-left first:px-0 last:border-none"}
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
);
|
||||
|
@ -173,21 +199,3 @@ export const Table = () => {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type TableCellProps = {
|
||||
cell: Cell<any, any>;
|
||||
//i: number;
|
||||
}
|
||||
|
||||
const TableCell: FunctionComponent<TableCellProps> = ({ cell }) => {
|
||||
return (
|
||||
<td
|
||||
className={
|
||||
"p-2 [&:nth-child(n+3)]:border-x "
|
||||
+ "first:text-left first:px-0 last:border-none"
|
||||
}
|
||||
key={cell.id}
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</td>)
|
||||
}
|
||||
|
|
22
compass/components/Table/PrimaryTableCell.tsx
Normal file
22
compass/components/Table/PrimaryTableCell.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* An extension of TableCell.tsx that includes an "open" button and the drawer.
|
||||
For cells in the "primary" (or first) column of the table. */
|
||||
import Drawer from "@/components/page/Drawer";
|
||||
import { TableCell } from "./TableCell";
|
||||
import { SetStateAction, useState } from "react";
|
||||
|
||||
export const PrimaryTableCell = ({ getValue, row, column, table }) => {
|
||||
const [pageContent, setPageContent] = useState("")
|
||||
|
||||
const handleDrawerContentChange = (newContent: SetStateAction<string>) => {
|
||||
setPageContent(newContent);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="font-semibold group flex flex-row items-center justify-between pr-2">
|
||||
<TableCell getValue={getValue} row={row} column={column} table={table} />
|
||||
<span>
|
||||
<Drawer title={getValue()} editableContent={pageContent} onSave={handleDrawerContentChange}>{pageContent}</Drawer>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -16,7 +16,7 @@ export const RowOptionMenu = ( { onDelete, onHide } ) => {
|
|||
<>
|
||||
<button className="align-center" onClick={() => setMenuOpen(!menuOpen)}><EllipsisVerticalIcon className="h-4"/></button>
|
||||
<div
|
||||
className={"justify-start border border-gray-200 shadow-lg flex flex-col absolute bg-white w-auto p-2 rounded [&>*]:rounded" + (!menuOpen ? " invisible" : "")}
|
||||
className={"justify-start border border-gray-200 shadow-lg flex flex-col absolute bg-white w-auto p-2 rounded [&>*]:rounded z-10" + (!menuOpen ? " invisible" : "")}
|
||||
>
|
||||
<RowOption icon={TrashIcon} label="Delete" onClick={onDelete} />
|
||||
<RowOption icon={ArrowUpRightIcon} label="Open" onClick={() => { /* handle open */ }} />
|
||||
|
|
17
compass/components/Table/TableCell.tsx
Normal file
17
compass/components/Table/TableCell.tsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* A lone table cell. Passed in for "cell" for a TanStack Table. */
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export const TableCell = ({ getValue, row, column, table }) => {
|
||||
const initialValue = getValue();
|
||||
const [value, setValue] = useState(initialValue);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(initialValue);
|
||||
}, [initialValue]);
|
||||
|
||||
const onBlur = () => {
|
||||
table.options.meta?.updateData(row.index, column.id, value);
|
||||
};
|
||||
|
||||
return <input className="w-full py-2 bg-inherit" value={value} onChange={e => setValue(e.target.value)} onBlur={onBlur} />;
|
||||
};
|
|
@ -26,7 +26,7 @@ const Drawer: FunctionComponent<DrawerProps> = ({ title, children, onSave, edita
|
|||
setEditContent(event.target.value);
|
||||
};
|
||||
|
||||
const drawerClassName = `fixed top-0 right-0 w-1/2 h-full bg-white transform ease-in-out duration-300 ${
|
||||
const drawerClassName = `fixed top-0 right-0 w-1/2 h-full bg-white transform ease-in-out duration-300 z-20 ${
|
||||
isOpen ? "translate-x-0 shadow-xl" : "translate-x-full"
|
||||
}`;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user