feat(database-view): add row creation
The client only supported editing existing rows (use-update-row = PATCH only); a freshly created table had no rows and no way to add one. Add useCreateRow (POST /api/v1/tables/:tableId/rows, bridge already supports it) and an 'Ajouter une ligne' button in the grid renderer, gated by canWriteRows, with view-cache invalidation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5e0f5cf49e
commit
7a11ff4e85
2 changed files with 58 additions and 0 deletions
|
|
@ -0,0 +1,43 @@
|
|||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { getBridgeClient, resolveBridgeUrl } from "../services/bridge-client";
|
||||
import type { BridgeRow } from "../types/database-view.types";
|
||||
import { VIEW_DATA_QUERY_KEY } from "./use-view-data";
|
||||
|
||||
interface UseCreateRowOptions {
|
||||
tableId: string;
|
||||
viewId: string;
|
||||
bridgeUrl?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new row in the table via the bridge, then invalidate the view
|
||||
* cache so the row appears.
|
||||
*
|
||||
* Server-first (no optimistic insert): the bridge assigns the row id, and the
|
||||
* inline editor PATCHes by id afterwards — fabricating a temporary id here
|
||||
* would desync the first edit. An empty payload creates a blank row (Baserow
|
||||
* fills defaults); callers may pass initial field values.
|
||||
*/
|
||||
export function useCreateRow({ tableId, viewId, bridgeUrl }: UseCreateRowOptions) {
|
||||
const queryClient = useQueryClient();
|
||||
const url = resolveBridgeUrl(bridgeUrl);
|
||||
|
||||
return useMutation<BridgeRow, Error, Record<string, unknown> | void>({
|
||||
mutationFn: async (fields) => {
|
||||
const client = getBridgeClient(url);
|
||||
return (await (client.post(
|
||||
`/api/v1/tables/${tableId}/rows`,
|
||||
fields ?? {},
|
||||
) as unknown)) as BridgeRow;
|
||||
},
|
||||
|
||||
onSettled: () => {
|
||||
// Reconcile with the server. The bridge also emits an SSE row.created
|
||||
// event which triggers the same invalidation — idempotent.
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [VIEW_DATA_QUERY_KEY, viewId],
|
||||
exact: false,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ import { modals } from "@mantine/modals";
|
|||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useViewData } from "../hooks/use-view-data";
|
||||
import { useUpdateRow } from "../hooks/use-update-row";
|
||||
import { useCreateRow } from "../hooks/use-create-row";
|
||||
import { useDatabaseRealtimeUpdates } from "../hooks/use-database-realtime-updates";
|
||||
import { usePermissions } from "../hooks/use-permissions";
|
||||
import { useAcadenicePermissions } from "@/features/acadenice/rbac/hooks/use-acadenice-permissions";
|
||||
|
|
@ -186,6 +187,7 @@ export function TableRenderer({ tableId, viewId, bridgeUrl }: TableRendererProps
|
|||
const canAdminTables = acadenicePerms.hasPermission("tables:write");
|
||||
const queryClient = useQueryClient();
|
||||
const updateRow = useUpdateRow({ tableId, viewId, bridgeUrl });
|
||||
const createRow = useCreateRow({ tableId, viewId, bridgeUrl });
|
||||
|
||||
// Field admin modal state.
|
||||
const [fieldModalOpen, setFieldModalOpen] = useState(false);
|
||||
|
|
@ -352,6 +354,19 @@ export function TableRenderer({ tableId, viewId, bridgeUrl }: TableRendererProps
|
|||
</table>
|
||||
</div>
|
||||
|
||||
{canWriteRows && (
|
||||
<Button
|
||||
size="xs"
|
||||
variant="subtle"
|
||||
leftSection={<IconPlus size={14} />}
|
||||
onClick={() => createRow.mutate()}
|
||||
loading={createRow.isPending}
|
||||
mt="xs"
|
||||
>
|
||||
{t("database_view.table.add_row", "Ajouter une ligne")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* Pagination — only shown when there is more than one page. */}
|
||||
{(page > 1 || hasNextPage) && (
|
||||
<div className={styles.pagination}>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue