Skip to content

Commit 96dd278

Browse files
committed
update form
1 parent c50be77 commit 96dd278

File tree

7 files changed

+168
-103
lines changed

7 files changed

+168
-103
lines changed

packages/app/src/actions/data/queries/addComputedColumn.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,31 @@ import { revalidateQueryCache } from "@/lib/dal/queries";
66
import { addComputedColumn } from "@/db/crud/query";
77
import { ComputedColumn } from "@common/db/schema/query";
88

9+
import {
10+
actionError,
11+
actionResult,
12+
runActionServer,
13+
} from "@/lib/actions/utils";
14+
915
export async function addComputedColumnAction(
1016
projectId: string,
1117
queryId: string,
12-
column: ComputedColumn,
13-
): Promise<void> {
14-
const user = await getServerUser();
15-
const userProject = await getProjectForUser(user, projectId);
18+
column: Omit<ComputedColumn, "id">,
19+
) {
20+
return runActionServer(async () => {
21+
const user = await getServerUser();
22+
const userProject = await getProjectForUser(user, projectId);
23+
24+
if (!userProject) {
25+
return actionError("Project not found");
26+
}
1627

17-
if (!userProject) {
18-
throw new Error("Project not found");
19-
}
28+
const newComputedColumn = await addComputedColumn(queryId, {
29+
...column,
30+
});
2031

21-
await addComputedColumn(queryId, column);
32+
revalidateQueryCache(queryId, projectId);
2233

23-
revalidateQueryCache(queryId, projectId);
34+
return actionResult(newComputedColumn);
35+
});
2436
}

packages/app/src/actions/data/queries/updateComputedColumn.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,34 @@ import { getProjectForUser } from "@/lib/dal/projects";
55
import { revalidateQueryCache } from "@/lib/dal/queries";
66
import { updateComputedColumn } from "@/db/crud/query";
77
import { ComputedColumn } from "@common/db/schema/query";
8+
import {
9+
runActionServer,
10+
actionError,
11+
actionResult,
12+
} from "@/lib/actions/utils";
813

914
export async function updateComputedColumnAction(
1015
projectId: string,
1116
queryId: string,
12-
columnName: string,
13-
column: ComputedColumn,
14-
): Promise<void> {
15-
const user = await getServerUser();
16-
const userProject = await getProjectForUser(user, projectId);
17+
columnId: string,
18+
column: Omit<ComputedColumn, "id">,
19+
) {
20+
return runActionServer(async () => {
21+
const user = await getServerUser();
22+
const userProject = await getProjectForUser(user, projectId);
1723

18-
if (!userProject) {
19-
throw new Error("Project not found");
20-
}
24+
if (!userProject) {
25+
return actionError("Project not found");
26+
}
2127

22-
await updateComputedColumn(queryId, columnName, column);
28+
const updatedComputedColumn = await updateComputedColumn(
29+
queryId,
30+
columnId,
31+
column,
32+
);
2333

24-
revalidateQueryCache(queryId, projectId);
34+
revalidateQueryCache(queryId, projectId);
35+
36+
return actionResult(updatedComputedColumn);
37+
});
2538
}

packages/app/src/components/data/query/query-layout-client.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function QueryLayoutClient({
5959
minSize={50}
6060
maxSize={95}
6161
>
62-
<div className="flex flex-1 flex-col">
62+
<div className="flex h-full flex-1 flex-col">
6363
{/* Header with name input, breadcrumbs, and toggle button */}
6464
<div className="flex items-center justify-between px-6 py-4">
6565
<div className="flex items-center gap-4">

packages/app/src/components/data/query/query-sidebar.tsx

Lines changed: 78 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ const computedColumnSchema = z.object({
4040

4141
type ComputedColumnFormData = z.infer<typeof computedColumnSchema>;
4242

43+
const defaultFunctionBody = `
44+
// Enter function body for computed column
45+
// Examples:
46+
// Simple: category + '_' + status
47+
// With logic:
48+
// if(priority > 3) {
49+
// return 'High'
50+
// }
51+
// return 'Low'
52+
`;
53+
4354
type QuerySidebarProps = {
4455
query: Query;
4556
projectId: string;
@@ -166,16 +177,15 @@ export function QuerySidebar({
166177
onClose,
167178
queryData: _queryData,
168179
}: QuerySidebarProps) {
169-
const [selectedColumn, setSelectedColumn] = useState<string | null>(null);
180+
const [selectedColumnId, setSelectedColumnId] = useState<string | null>(null);
170181
const [isSubmitting, setIsSubmitting] = useState(false);
171182
const [isCreating, setIsCreating] = useState(false);
172183

173184
const form = useForm<ComputedColumnFormData>({
174185
resolver: zodResolver(computedColumnSchema),
175186
defaultValues: {
176187
name: "",
177-
functionBody:
178-
"// Enter function body for computed column\n// Examples:\n// Simple: category + '_' + status\n// With logic:\n// if(priority > 3) {\n// return 'High'\n// }\n// return 'Low'",
188+
functionBody: defaultFunctionBody,
179189
},
180190
});
181191

@@ -184,62 +194,60 @@ export function QuerySidebar({
184194

185195
// Set default column on component load
186196
useEffect(() => {
187-
if (hasComputedColumns && !selectedColumn) {
197+
if (hasComputedColumns && !selectedColumnId) {
188198
const firstColumn = query.computedColumns[0];
189199
handleEditColumn(firstColumn);
190200
}
191-
}, [hasComputedColumns, selectedColumn]);
201+
}, [hasComputedColumns, selectedColumnId]);
192202

193203
const handleEditColumn = (column: ComputedColumn) => {
194-
setSelectedColumn(column.name);
204+
setSelectedColumnId(column.id);
195205
form.reset({
196206
name: column.name,
197207
functionBody: column.functionBody,
198208
});
199209
};
200210

201211
const handleNewColumn = async () => {
202-
const defaultBody =
203-
"// Enter function body for computed column\n// Examples:\n// Simple: category + '_' + status\n// With logic:\n// if(priority > 3) {\n// return 'High'\n// }\n// return 'Low'";
204-
205212
setIsCreating(true);
206-
try {
207-
// Create new column in database
208-
await addComputedColumnAction(projectId, query.id, {
209-
name: "Untitled",
210-
functionBody: defaultBody,
211-
});
212213

213-
// Select the newly created column
214-
const newColumn = {
215-
name: "Untitled",
216-
functionBody: defaultBody,
217-
};
214+
// Create new column in database
215+
const result = await addComputedColumnAction(projectId, query.id, {
216+
name: "Untitled",
217+
functionBody: defaultFunctionBody,
218+
});
219+
220+
if (!result.success) {
221+
console.error("Failed to create new column:", result.error);
222+
return;
223+
} else {
224+
const newColumn = result.data;
218225
handleEditColumn(newColumn);
219-
} catch (error) {
220-
console.error("Failed to create new column:", error);
221-
} finally {
222-
setIsCreating(false);
223226
}
227+
228+
setIsCreating(false);
224229
};
225230

226231
const handleCancelEdit = () => {
227-
setSelectedColumn(null);
232+
setSelectedColumnId(null);
228233
form.reset();
229234
};
230235

231-
const handleDeleteColumn = async (columnName: string) => {
236+
const handleDeleteColumn = async (columnId: string) => {
237+
const column = query.computedColumns.find((col) => col.id === columnId);
238+
if (!column) return;
239+
232240
if (
233241
confirm(
234-
`Are you sure you want to delete the computed column "${columnName}"?`,
242+
`Are you sure you want to delete the computed column "${column.name}"?`,
235243
)
236244
) {
237245
try {
238-
await deleteComputedColumnAction(projectId, query.id, columnName);
239-
console.log("Deleted computed column:", columnName);
246+
await deleteComputedColumnAction(projectId, query.id, columnId);
247+
console.log("Deleted computed column:", column.name);
240248

241249
// Clear form after successful deletion
242-
setSelectedColumn(null);
250+
setSelectedColumnId(null);
243251
form.reset();
244252
} catch (error) {
245253
console.error("Failed to delete computed column:", error);
@@ -249,36 +257,39 @@ export function QuerySidebar({
249257

250258
const onSubmit = async (data: ComputedColumnFormData) => {
251259
setIsSubmitting(true);
252-
try {
253-
if (selectedColumn) {
254-
await updateComputedColumnAction(projectId, query.id, selectedColumn, {
260+
261+
if (selectedColumnId) {
262+
const result = await updateComputedColumnAction(
263+
projectId,
264+
query.id,
265+
selectedColumnId,
266+
{
255267
name: data.name.trim(),
256268
functionBody: data.functionBody.trim(),
257-
});
258-
// After updating, select the updated column
259-
const updatedColumn = query.computedColumns.find(
260-
(col) => col.name === selectedColumn,
261-
);
262-
if (updatedColumn) {
263-
handleEditColumn(updatedColumn);
264-
}
269+
},
270+
);
271+
272+
if (!result.success) {
273+
console.error("Failed to update computed column:", result.error);
274+
return;
265275
} else {
266-
await addComputedColumnAction(projectId, query.id, {
267-
name: data.name.trim(),
268-
functionBody: data.functionBody.trim(),
269-
});
270-
// After adding, select the newly created column
271-
const newColumn = {
272-
name: data.name.trim(),
273-
functionBody: data.functionBody.trim(),
274-
};
275-
handleEditColumn(newColumn);
276+
handleEditColumn(result.data);
277+
}
278+
} else {
279+
const result = await addComputedColumnAction(projectId, query.id, {
280+
name: data.name.trim(),
281+
functionBody: data.functionBody.trim(),
282+
});
283+
284+
if (!result.success) {
285+
console.error("Failed to add computed column:", result.error);
286+
return;
287+
} else {
288+
handleEditColumn(result.data);
276289
}
277-
} catch (error) {
278-
console.error("Failed to save computed column:", error);
279-
} finally {
280-
setIsSubmitting(false);
281290
}
291+
292+
setIsSubmitting(false);
282293
};
283294

284295
return (
@@ -309,18 +320,18 @@ export function QuerySidebar({
309320
<Select
310321
onValueChange={(value) => {
311322
const column = query.computedColumns.find(
312-
(col) => col.name === value,
323+
(col) => col.id === value,
313324
);
314325
if (column) handleEditColumn(column);
315326
}}
316-
value={selectedColumn || ""}
327+
value={selectedColumnId || ""}
317328
>
318329
<SelectTrigger>
319330
<SelectValue placeholder="Select column" />
320331
</SelectTrigger>
321332
<SelectContent>
322333
{query.computedColumns.map((column) => (
323-
<SelectItem key={column.name} value={column.name}>
334+
<SelectItem key={column.id} value={column.id}>
324335
{column.name}
325336
</SelectItem>
326337
))}
@@ -390,24 +401,25 @@ export function QuerySidebar({
390401

391402
{/* Action Buttons */}
392403
<div className="flex gap-2">
393-
{selectedColumn && (
404+
{selectedColumnId && (
394405
<Button
395406
type="button"
396407
variant="outline"
397408
size="sm"
398409
onClick={handleCancelEdit}
399410
className="flex items-center gap-2"
411+
disabled={!form.formState.isDirty}
400412
>
401413
Cancel
402414
</Button>
403415
)}
404416

405-
{selectedColumn && (
417+
{selectedColumnId && (
406418
<Button
407419
type="button"
408420
variant="outline"
409421
size="sm"
410-
onClick={() => handleDeleteColumn(selectedColumn)}
422+
onClick={() => handleDeleteColumn(selectedColumnId)}
411423
className="flex items-center gap-2 text-destructive hover:bg-destructive/10 hover:text-destructive"
412424
>
413425
<Trash2 className="h-4 w-4" />
@@ -419,7 +431,11 @@ export function QuerySidebar({
419431
type="submit"
420432
variant="default"
421433
size="sm"
422-
disabled={isSubmitting || !form.formState.isValid}
434+
disabled={
435+
isSubmitting ||
436+
!form.formState.isValid ||
437+
!form.formState.isDirty
438+
}
423439
className="flex items-center gap-2"
424440
>
425441
<Save className="h-4 w-4" />

0 commit comments

Comments
 (0)