Skip to content

Commit bad19a3

Browse files
authored
Finish DataGrid CRUD delete/update and create rows (#1027)
1 parent aa22b08 commit bad19a3

File tree

41 files changed

+892
-320
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+892
-320
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use server'
2+
3+
import { z } from 'zod'
4+
import { createDatasetEmptyRow } from '@latitude-data/core/services/datasetRows/createEmptyRow'
5+
import { DatasetsV2Repository } from '@latitude-data/core/repositories'
6+
import { authProcedure } from '$/actions/procedures'
7+
8+
export const createDatasetRowAction = authProcedure
9+
.createServerAction()
10+
.input(z.object({ datasetId: z.number() }), { type: 'json' })
11+
.handler(async ({ ctx, input }) => {
12+
const datasetRepo = new DatasetsV2Repository(ctx.workspace.id)
13+
const dataset = await datasetRepo
14+
.find(input.datasetId)
15+
.then((r) => r.unwrap())
16+
17+
return createDatasetEmptyRow({
18+
workspace: ctx.workspace,
19+
dataset,
20+
}).then((r) => r.unwrap())
21+
})
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use server'
2+
3+
import { z } from 'zod'
4+
import { deleteManyRows } from '@latitude-data/core/services/datasetRows/deleteManyRows'
5+
import {
6+
DatasetRowsRepository,
7+
DatasetsV2Repository,
8+
} from '@latitude-data/core/repositories'
9+
import { authProcedure } from '$/actions/procedures'
10+
11+
export const deleteRowsAction = authProcedure
12+
.createServerAction()
13+
.input(
14+
z.object({
15+
datasetId: z.number(),
16+
rowIds: z.array(z.number()),
17+
}),
18+
{ type: 'json' },
19+
)
20+
.handler(async ({ ctx, input }) => {
21+
const datasetRepo = new DatasetsV2Repository(ctx.workspace.id)
22+
const dataset = await datasetRepo
23+
.find(input.datasetId)
24+
.then((r) => r.unwrap())
25+
const scope = new DatasetRowsRepository(ctx.workspace.id)
26+
const rows = await scope.findManyByDataset({
27+
dataset,
28+
rowIds: input.rowIds,
29+
})
30+
31+
return deleteManyRows({
32+
dataset,
33+
rows,
34+
}).then((r) => r.unwrap())
35+
})

apps/web/src/actions/datasetRows/update.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { DatasetRowDataContent } from '@latitude-data/core/schema'
1212
const rowDataSchema = z.record(
1313
z.custom<DatasetRowDataContent>((val) => {
1414
return (
15-
['string', 'number', 'boolean'].includes(typeof val) ||
15+
['string', 'number', 'boolean', 'object'].includes(typeof val) ||
1616
val === null ||
1717
val === undefined
1818
)

apps/web/src/app/(private)/datasets/[datasetId]/DatasetDetailTable/DataGrid/EditCell/index.tsx

Lines changed: 0 additions & 133 deletions
This file was deleted.

apps/web/src/app/(private)/datasets/[datasetId]/DatasetDetailTable/DataGrid/index.tsx

Lines changed: 87 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import type {
77
CellClickArgs,
88
CellMouseEvent,
99
} from '@latitude-data/web-ui/data-grid'
10-
import { Text } from '@latitude-data/web-ui'
10+
import { DataGridCellEditor, type EditorCellProps } from '@latitude-data/web-ui'
11+
import { Text, FloatingPanel, Button } from '@latitude-data/web-ui'
1112
import { DatasetRoleStyle } from '$/hooks/useDatasetRoles'
1213
import { DatasetV2 } from '@latitude-data/core/browser'
1314
import { ClientPagination } from '@latitude-data/core/lib/pagination/buildPagination'
1415
import { useCallback, useMemo, useState } from 'react'
1516
import { LinkableTablePaginationFooter } from '$/components/TablePaginationFooter'
16-
import { EditCell } from '$/app/(private)/datasets/[datasetId]/DatasetDetailTable/DataGrid/EditCell'
1717
import { ClientDatasetRow } from '$/stores/datasetRows/rowSerializationHelpers'
1818
import useDatasetRows from '$/stores/datasetRows'
1919

@@ -38,18 +38,55 @@ function renderCell(props: RenderCellProps<ClientDatasetRow, unknown>) {
3838
)
3939
}
4040

41+
function tryToParseJSON(value: string) {
42+
try {
43+
return JSON.parse(value)
44+
} catch {
45+
return value
46+
}
47+
}
48+
4149
function renderEditCell(props: RenderEditCellProps<ClientDatasetRow, unknown>) {
42-
return <EditCell {...props} />
50+
const row = props.row
51+
const column = props.column
52+
const onRowChange = props.onRowChange
53+
const onChange = useCallback(
54+
({ value, commitChanges }: Parameters<EditorCellProps['onChange']>[0]) => {
55+
const prevData = row.rowData
56+
const newRow = {
57+
...row,
58+
rowData: { ...prevData, [column.key]: tryToParseJSON(value) },
59+
}
60+
onRowChange(newRow, commitChanges)
61+
},
62+
[row, column.key, onRowChange],
63+
)
64+
const storedRowValue = row.rowData[column.key]
65+
const rawValue = row.processedRowData[column.key]
66+
const initialValue = rawValue === undefined ? '' : String(rawValue)
67+
const valueType = typeof storedRowValue === 'object' ? 'json' : 'text'
68+
return (
69+
<DataGridCellEditor
70+
valueType={valueType}
71+
value={initialValue}
72+
onChange={onChange}
73+
/>
74+
)
4375
}
4476

4577
type Props = DatasetRowsTableProps & {
4678
updateRows: ReturnType<typeof useDatasetRows>['updateRows']
79+
deleteRows: ReturnType<typeof useDatasetRows>['deleteRows']
80+
isDeleting: boolean
4781
}
4882

83+
const countLabel = (count: number) => `${count} rows`
4984
export default function DataGrid({
5085
dataset,
5186
rows,
5287
updateRows,
88+
deleteRows,
89+
isDeleting,
5390
pagination,
5491
}: Props) {
5592
const [selectedRows, setSelectedRows] = useState(() => new Set<number>())
@@ -88,16 +125,53 @@ export default function DataGrid({
88125
},
89126
[updateRows],
90127
)
128+
const onClickDelete = useCallback(async () => {
129+
const rowIdsToDelete = Array.from(selectedRows)
130+
await deleteRows({
131+
datasetId: dataset.id,
132+
rowIds: rowIdsToDelete,
133+
})
134+
setSelectedRows(new Set<number>())
135+
}, [deleteRows, selectedRows, dataset.id, setSelectedRows])
136+
91137
return (
92-
<BaseDataGrid<ClientDatasetRow, unknown, number>
93-
rowKeyGetter={rowKeyGetter}
94-
rows={rows}
95-
columns={columns}
96-
onRowsChange={onRowsChange}
97-
onCellClick={onCellClick}
98-
selectedRows={selectedRows}
99-
onSelectedRowsChange={setSelectedRows}
100-
footer={<LinkableTablePaginationFooter pagination={pagination} />}
101-
/>
138+
<>
139+
<BaseDataGrid<ClientDatasetRow, unknown, number>
140+
rowKeyGetter={rowKeyGetter}
141+
rows={rows}
142+
columns={columns}
143+
onRowsChange={onRowsChange}
144+
onCellClick={onCellClick}
145+
selectedRows={selectedRows}
146+
onSelectedRowsChange={setSelectedRows}
147+
footer={
148+
<LinkableTablePaginationFooter
149+
pagination={pagination}
150+
countLabel={countLabel}
151+
/>
152+
}
153+
/>
154+
<div className='z-40 flex justify-center absolute left-0 right-0 bottom-4 pointer-events-none'>
155+
<FloatingPanel visible={selectedRows.size > 0}>
156+
<div className='flex flex-row justify-between gap-x-4'>
157+
<Button
158+
fancy
159+
variant='destructive'
160+
disabled={isDeleting || selectedRows.size === 0}
161+
onClick={onClickDelete}
162+
>
163+
{isDeleting ? 'Deleting rows...' : 'Delete rows'}
164+
</Button>
165+
<Button
166+
fancy
167+
variant='outline'
168+
onClick={() => setSelectedRows(new Set<number>())}
169+
>
170+
Clear selection
171+
</Button>
172+
</div>
173+
</FloatingPanel>
174+
</div>
175+
</>
102176
)
103177
}

apps/web/src/app/(private)/datasets/[datasetId]/DatasetDetailTable/SimpleTable/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function SimpleTable({
5151
className={backgroundCssClasses[role]}
5252
>
5353
<Text.H5 wordBreak='breakAll' ellipsis lineClamp={1}>
54-
{cell}
54+
{String(cell)}
5555
</Text.H5>
5656
</TableCell>
5757
)

0 commit comments

Comments
 (0)