implement controlled edit / delete dialogs
This commit is contained in:
parent
17578d50d6
commit
89e338a0ac
BIN
prisma/dev.db
BIN
prisma/dev.db
Binary file not shown.
|
@ -706,22 +706,6 @@ body {
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.col-span-full {
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.col-start-1 {
|
|
||||||
grid-column-start: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.col-start-3 {
|
|
||||||
grid-column-start: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.col-end-3 {
|
|
||||||
grid-column-end: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.m-auto {
|
.m-auto {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
@ -975,18 +959,6 @@ body {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.w-1 {
|
|
||||||
width: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-6 {
|
|
||||||
width: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-32 {
|
|
||||||
width: 8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.min-w-\[8rem\] {
|
.min-w-\[8rem\] {
|
||||||
min-width: 8rem;
|
min-width: 8rem;
|
||||||
}
|
}
|
||||||
|
@ -1012,10 +984,6 @@ body {
|
||||||
max-width: 24rem;
|
max-width: 24rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.max-w-28 {
|
|
||||||
max-width: 7rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-w-xs {
|
.max-w-xs {
|
||||||
max-width: 20rem;
|
max-width: 20rem;
|
||||||
}
|
}
|
||||||
|
@ -1088,10 +1056,6 @@ body {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-cols-12 {
|
|
||||||
grid-template-columns: repeat(12, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-row {
|
.flex-row {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
@ -1132,10 +1096,6 @@ body {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.justify-around {
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gap-1 {
|
.gap-1 {
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
}
|
}
|
||||||
|
@ -1148,14 +1108,6 @@ body {
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gap-3 {
|
|
||||||
gap: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gap-44 {
|
|
||||||
gap: 11rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gap-x-16 {
|
.gap-x-16 {
|
||||||
-moz-column-gap: 4rem;
|
-moz-column-gap: 4rem;
|
||||||
column-gap: 4rem;
|
column-gap: 4rem;
|
||||||
|
@ -1169,10 +1121,6 @@ body {
|
||||||
row-gap: 2rem;
|
row-gap: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gap-y-4 {
|
|
||||||
row-gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.space-x-1 > :not([hidden]) ~ :not([hidden]) {
|
.space-x-1 > :not([hidden]) ~ :not([hidden]) {
|
||||||
--tw-space-x-reverse: 0;
|
--tw-space-x-reverse: 0;
|
||||||
margin-right: calc(0.25rem * var(--tw-space-x-reverse));
|
margin-right: calc(0.25rem * var(--tw-space-x-reverse));
|
||||||
|
|
|
@ -8,14 +8,12 @@ import { Row, Table, TableState } from "@tanstack/react-table"
|
||||||
import { tableNameToItemName } from "app/lib/nameMaps"
|
import { tableNameToItemName } from "app/lib/nameMaps"
|
||||||
import EditSubmissionDialog from "app/submission/edit"
|
import EditSubmissionDialog from "app/submission/edit"
|
||||||
|
|
||||||
export default function FormContextMenu({ table, row }: ComponentProps<"div"> & { table: Table<any>, row: Row<any> }) {
|
export default function FormContextMenu({ table, row, openEditDialog, openDeleteDialog }: ComponentProps<"div"> & { table: Table<any>, row: Row<any>, openEditDialog: (row: Row<any>) => void, openDeleteDialog: (row: Row<any>) => void }) {
|
||||||
const pathname = table.options.meta.pathname
|
const pathname = table.options.meta.pathname
|
||||||
const selectedRows = table.getSelectedRowModel().flatRows
|
const selectedRows = table.getSelectedRowModel().flatRows
|
||||||
|
|
||||||
const [dialog, setDialog] = useState<"edit" | "delete" | null>("delete")
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog modal={true}>
|
|
||||||
<ContextMenuContent >
|
<ContextMenuContent >
|
||||||
{pathname !== "/submission" && selectedRows.length <= 1 ?
|
{pathname !== "/submission" && selectedRows.length <= 1 ?
|
||||||
<>
|
<>
|
||||||
|
@ -29,11 +27,9 @@ export default function FormContextMenu({ table, row }: ComponentProps<"div"> &
|
||||||
{
|
{
|
||||||
pathname === "/submission" ?
|
pathname === "/submission" ?
|
||||||
<>
|
<>
|
||||||
<DialogTrigger asChild>
|
<ContextMenuItem onClick={() => openEditDialog(row)}>
|
||||||
<ContextMenuItem onClick={() => setDialog("edit")}>
|
|
||||||
Edit
|
Edit
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
</DialogTrigger>
|
|
||||||
</>
|
</>
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
|
@ -44,44 +40,8 @@ export default function FormContextMenu({ table, row }: ComponentProps<"div"> &
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
<ContextMenuSeparator />
|
<ContextMenuSeparator />
|
||||||
<DialogTrigger asChild>
|
<ContextMenuItem className="text-destructive" onClick={() => openDeleteDialog(row)}>Delete</ContextMenuItem>
|
||||||
<ContextMenuItem className="text-destructive" onClick={() => setDialog("delete")}>Delete</ContextMenuItem>
|
|
||||||
</DialogTrigger>
|
|
||||||
</ContextMenuContent>
|
</ContextMenuContent>
|
||||||
<DialogContent>
|
|
||||||
{
|
|
||||||
dialog === "delete" ?
|
|
||||||
<>
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Are you sure?</DialogTitle>
|
|
||||||
<DialogDescription>
|
|
||||||
Deleting a {tableNameToItemName(table.options.meta.tableName)} cannot be undone!
|
|
||||||
</DialogDescription>
|
|
||||||
</DialogHeader>
|
|
||||||
<DialogFooter>
|
|
||||||
<DialogClose asChild>
|
|
||||||
<Button variant="destructive"
|
|
||||||
onClick={() => {
|
|
||||||
deleteRecord(row.original.id, pathname)
|
|
||||||
}}>Yes, delete it!
|
|
||||||
</Button>
|
|
||||||
</DialogClose>
|
|
||||||
</DialogFooter>
|
|
||||||
</>
|
|
||||||
: dialog === "edit" ?
|
|
||||||
<EditSubmissionDialog
|
|
||||||
stories={table.options.meta.stories}
|
|
||||||
pubs={table.options.meta.pubs}
|
|
||||||
responses={table.options.meta.responses}
|
|
||||||
defaults={row.original}
|
|
||||||
/>
|
|
||||||
:
|
|
||||||
<>
|
|
||||||
<DialogTitle>Edit/delete dialog</DialogTitle>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@ import {
|
||||||
getFilteredRowModel,
|
getFilteredRowModel,
|
||||||
getCoreRowModel,
|
getCoreRowModel,
|
||||||
getPaginationRowModel,
|
getPaginationRowModel,
|
||||||
useReactTable
|
useReactTable,
|
||||||
|
Row
|
||||||
} from "@tanstack/react-table"
|
} from "@tanstack/react-table"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -40,13 +41,15 @@ import {
|
||||||
import { EyeIcon, Trash2 } from "lucide-react"
|
import { EyeIcon, Trash2 } from "lucide-react"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
import FormContextMenu from "./contextMenu"
|
import FormContextMenu from "./contextMenu"
|
||||||
import { deleteRecords } from "app/lib/del"
|
import { deleteRecord, deleteRecords } from "app/lib/del"
|
||||||
import { Pathname } from "app/types"
|
import { Pathname } from "app/types"
|
||||||
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTrigger } from "@/components/ui/dialog"
|
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTrigger } from "@/components/ui/dialog"
|
||||||
import pluralize from "app/lib/pluralize"
|
import pluralize from "app/lib/pluralize"
|
||||||
import { updateField } from "app/lib/update"
|
import { updateField } from "app/lib/update"
|
||||||
import { tableNameToItemName } from "app/lib/nameMaps"
|
import { tableNameToItemName } from "app/lib/nameMaps"
|
||||||
import { Genre, Pub, Response, Story } from "@prisma/client"
|
import { Genre, Pub, Response, Story } from "@prisma/client"
|
||||||
|
import EditSubmissionDialog from "app/submission/edit"
|
||||||
|
import { DialogTitle } from "@radix-ui/react-dialog"
|
||||||
|
|
||||||
export interface DataTableProps<TData, TValue> {
|
export interface DataTableProps<TData, TValue> {
|
||||||
columns: ColumnDef<TData, TValue>[]
|
columns: ColumnDef<TData, TValue>[]
|
||||||
|
@ -65,6 +68,9 @@ export function DataTable<TData, TValue>({
|
||||||
genres
|
genres
|
||||||
}: DataTableProps<TData, TValue> & ComponentProps<"div"> & { tableName: string, stories?: Story[], pubs?: Pub[], responses?: Response[], genres?: Genre[] }) {
|
}: DataTableProps<TData, TValue> & ComponentProps<"div"> & { tableName: string, stories?: Story[], pubs?: Pub[], responses?: Response[], genres?: Genre[] }) {
|
||||||
//STATE
|
//STATE
|
||||||
|
const [isEditDialogVisible, setIsEditDialogVisible] = useState<boolean>(false)
|
||||||
|
const [isDeleteDialogVisible, setIsDeleteDialogVisible] = useState<boolean>(false)
|
||||||
|
const [dialogRow, SetDialogRow] = useState<Row<any> | null>(null)
|
||||||
const [sorting, setSorting] = useState<SortingState>([])
|
const [sorting, setSorting] = useState<SortingState>([])
|
||||||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>(
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>(
|
||||||
[]
|
[]
|
||||||
|
@ -103,6 +109,14 @@ export function DataTable<TData, TValue>({
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
function openEditDialog(row) {
|
||||||
|
setIsEditDialogVisible(true)
|
||||||
|
SetDialogRow(row)
|
||||||
|
}
|
||||||
|
function openDeleteDialog(row) {
|
||||||
|
setIsDeleteDialogVisible(true)
|
||||||
|
SetDialogRow(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const [filterBy, setFilterBy] = useState(table.getAllColumns()[0])
|
const [filterBy, setFilterBy] = useState(table.getAllColumns()[0])
|
||||||
|
@ -143,6 +157,39 @@ export function DataTable<TData, TValue>({
|
||||||
|
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
|
<Dialog open={isEditDialogVisible} onOpenChange={setIsEditDialogVisible}>
|
||||||
|
<DialogContent>
|
||||||
|
<EditSubmissionDialog
|
||||||
|
stories={stories}
|
||||||
|
pubs={pubs}
|
||||||
|
responses={responses}
|
||||||
|
defaults={dialogRow?.original}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
|
||||||
|
<Dialog open={isDeleteDialogVisible} onOpenChange={setIsDeleteDialogVisible}>
|
||||||
|
<DialogContent>
|
||||||
|
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Are you sure?</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Deleting a {tableNameToItemName(tableName)} cannot be undone!
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogFooter>
|
||||||
|
<DialogClose asChild>
|
||||||
|
<Button variant="destructive"
|
||||||
|
onClick={() => {
|
||||||
|
deleteRecord(dialogRow.original.id, pathname)
|
||||||
|
}}>Yes, delete it!
|
||||||
|
</Button>
|
||||||
|
</DialogClose>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
<Dialog>
|
<Dialog>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button variant="destructive" disabled={!(table.getIsSomeRowsSelected() || table.getIsAllRowsSelected())}>
|
<Button variant="destructive" disabled={!(table.getIsSomeRowsSelected() || table.getIsAllRowsSelected())}>
|
||||||
|
@ -227,12 +274,18 @@ export function DataTable<TData, TValue>({
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{table.getRowModel().rows?.length ? (
|
{table.getRowModel().rows?.length ? (
|
||||||
table.getRowModel().rows.map((row) => (
|
table.getRowModel().rows.map((row) => (
|
||||||
<ContextMenu onOpenChange={open => setIsContextMenuOpen(open)} key={row.id + "contextMenu"}>
|
<ContextMenu key={row.id + "contextMenu"}>
|
||||||
<ContextMenuTrigger asChild>
|
<ContextMenuTrigger asChild>
|
||||||
<TableRow
|
<TableRow
|
||||||
key={row.id}
|
key={row.id}
|
||||||
data-state={row.getIsSelected() && "selected"}
|
data-state={row.getIsSelected() && "selected"}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
onDoubleClick={() => {
|
||||||
|
if (tableName === "sub") {
|
||||||
|
openEditDialog(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{row.getVisibleCells().map((cell) => (
|
{row.getVisibleCells().map((cell) => (
|
||||||
<TableCell key={cell.id}>
|
<TableCell key={cell.id}>
|
||||||
|
@ -243,6 +296,8 @@ export function DataTable<TData, TValue>({
|
||||||
key={"formContextMenu" + row.id}
|
key={"formContextMenu" + row.id}
|
||||||
row={row}
|
row={row}
|
||||||
table={table}
|
table={table}
|
||||||
|
openEditDialog={openEditDialog}
|
||||||
|
openDeleteDialog={openDeleteDialog}
|
||||||
/>
|
/>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</ContextMenuTrigger>
|
</ContextMenuTrigger>
|
||||||
|
|
|
@ -83,7 +83,7 @@ export function TextInputCell(props: CellContext<any, any>) {
|
||||||
<FormControl
|
<FormControl
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
className="w-fit"
|
className="w-full"
|
||||||
type="text"
|
type="text"
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
{...field}
|
{...field}
|
||||||
|
|
Loading…
Reference in New Issue