Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | import { type Column, columnType, renderValue } from "admin/column"; import { config } from "admin/config"; import { TableRow } from "admin/database/routes/[table]/components/table-row"; import { sql } from "drizzle-orm"; import type { BetterSQLite3Database } from "drizzle-orm/better-sqlite3"; import type { Handler } from "handler"; export const POST: Handler = async ({ req, res }) => { const tableName = req.params.table as string; const db = res.locals.database as BetterSQLite3Database< Record<string, unknown> >; const { __row, ...updatedData } = req.body; const columns = db.all<Column>( sql`SELECT * FROM pragma_table_info(${tableName})`, ); const newData: Record<string, unknown> = {}; for (const [key, value] of Object.entries(updatedData)) { const column = columns.find((column) => column.name === key); if (!column) { throw new Error(`Column ${key} not found in table ${tableName}`); } newData[key] = value; if (column.type === "INTEGER") { newData[key] = Number.parseInt(value as string); } else if (column.type === "REAL") { newData[key] = Number.parseFloat(value as string); } } config.verbose >= 1 || console.log("[admin] [database]", "saving row", newData); const oldRow = JSON.parse(__row as string); const setClause = Object.entries(newData) .map(([column, value]) => sql`${sql.identifier(column)} = ${value}`) .reduce((acc, curr) => sql`${acc}, ${curr}`); const whereClause = Object.entries(oldRow) .map(([column, value]) => sql`${sql.identifier(column)} = ${value}`) .reduce((acc, curr) => sql`${acc} AND ${curr}`); db.run( sql`UPDATE ${sql.identifier(tableName)} SET ${setClause} WHERE ${whereClause}`, ); config.verbose >= 1 || console.log("[admin] [database]", "row saved"); return <TableRow tableName={tableName} columns={columns} row={newData} />; }; function estimateNrOfRows(value: string) { return String(Math.max(Math.round(String(value).length / 30), 1)); } export const GET: Handler = async ({ req, res }) => { const tableName = req.params.table as string; const rowData = JSON.parse(decodeURIComponent(req.query.row as string)); const db = res.locals.database as BetterSQLite3Database; const columns = db.all<Column>( sql`SELECT * FROM pragma_table_info(${tableName})`, ); return ( <tr> <td class="w-16 flex items-center justify-center"> <button class="btn btn-xs btn-primary" type="submit" hx-post={`${config.adminBasePath}/database/${tableName}/edit`} hx-include="closest tr" > Save </button> <input type="hidden" name="__row" value={JSON.stringify(rowData)} /> </td> {columns.map((column) => { const tsType = columnType(column.type); const value = rowData[column.name]; const safeFormattedValue = renderValue(value, tsType); return ( <td data-type={tsType} class="border border-neutral px-2 py-1 max-w-32 relative" > {safeFormattedValue} <textarea class="top-0 left-0 w-full py-1 pl-2 m-0 bg-base-200 absolute" rows={estimateNrOfRows(value)} name={column.name} safe > {value} </textarea> </td> ); })} <td> <button class="btn btn-xs ml-1" type="reset" hx-get={`${config.adminBasePath}/database/${tableName}/row?row=${encodeURIComponent(JSON.stringify(rowData))}`} > Cancel </button> </td> </tr> ); }; |