refactor: update volume backup and environment description handling to use undefined instead of null for improved consistency; enhance error handling in AI component

This commit is contained in:
Mauricio Siu
2026-02-24 13:03:42 -06:00
parent 7b6ece0b65
commit 53b612534d
4 changed files with 85 additions and 48 deletions

View File

@@ -207,7 +207,7 @@ export const HandleVolumeBackups = ({
await mutateAsync({
...values,
keepLatestCount: preparedKeepLatestCount,
keepLatestCount: preparedKeepLatestCount ?? undefined,
destinationId: values.destinationId,
volumeBackupId: volumeBackupId || "",
serviceType: volumeBackupType,

View File

@@ -93,7 +93,7 @@ export const AdvancedEnvironmentSelector = ({
await createEnvironment.mutateAsync({
projectId,
name: name.trim(),
description: description.trim() || null,
description: description.trim() || undefined,
});
toast.success("Environment created successfully");
@@ -115,7 +115,7 @@ export const AdvancedEnvironmentSelector = ({
await updateEnvironment.mutateAsync({
environmentId: selectedEnvironment.environmentId,
name: name.trim(),
description: description.trim() || null,
description: description.trim() || undefined,
});
toast.success("Environment updated successfully");
@@ -168,7 +168,7 @@ export const AdvancedEnvironmentSelector = ({
const result = await duplicateEnvironment.mutateAsync({
environmentId: environment.environmentId,
name: `${environment.name}-copy`,
description: environment.description,
description: environment.description || undefined,
});
toast.success("Environment duplicated successfully");

View File

@@ -57,7 +57,6 @@ interface Props {
export const HandleAi = ({ aiId }: Props) => {
const utils = api.useUtils();
const [error, setError] = useState<string | null>(null);
const [open, setOpen] = useState(false);
const [modelPopoverOpen, setModelPopoverOpen] = useState(false);
const [modelSearch, setModelSearch] = useState("");
@@ -102,19 +101,19 @@ export const HandleAi = ({ aiId }: Props) => {
const apiKey = form.watch("apiKey");
const isOllama = apiUrl.includes(":11434") || apiUrl.includes("ollama");
const { data: models, isPending: isLoadingServerModels } =
api.ai.getModels.useQuery(
{
apiUrl: apiUrl ?? "",
apiKey: apiKey ?? "",
},
{
enabled: !!apiUrl && (isOllama || !!apiKey),
onError: (error) => {
setError(`Failed to fetch models: ${error.message}`);
},
},
);
const {
data: models,
isPending: isLoadingServerModels,
error: modelsError,
} = api.ai.getModels.useQuery(
{
apiUrl: apiUrl ?? "",
apiKey: apiKey ?? "",
},
{
enabled: !!apiUrl && (isOllama || !!apiKey),
},
);
const onSubmit = async (data: Schema) => {
try {
@@ -169,7 +168,9 @@ export const HandleAi = ({ aiId }: Props) => {
</DialogDescription>
</DialogHeader>
<Form {...form}>
{error && <AlertBlock type="error">{error}</AlertBlock>}
{modelsError && (
<AlertBlock type="error">{modelsError.message}</AlertBlock>
)}
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-2">
<FormField
control={form.control}

View File

@@ -7,6 +7,7 @@ import {
text,
timestamp,
} from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { nanoid } from "nanoid";
import { z } from "zod";
import { account, apikey, organization } from "./account";
@@ -80,41 +81,76 @@ export const usersRelations = relations(user, ({ one, many }) => ({
schedules: many(schedules),
}));
export const apiCreateUserInvitation = z.object({
const createSchema = createInsertSchema(user, {
id: z.string().min(1),
isRegistered: z.boolean().optional(),
}).omit({
role: true,
trustedOrigins: true,
isValidEnterpriseLicense: true,
});
export const apiCreateUserInvitation = createSchema.pick({}).extend({
email: z.string().email(),
});
export const apiRemoveUser = z.object({
id: z.string().min(1),
});
export const apiRemoveUser = createSchema
.pick({
id: true,
})
.required();
export const apiFindOneToken = z.object({
token: z.string().min(1),
});
export const apiFindOneToken = createSchema
.pick({})
.required()
.extend({
token: z.string().min(1),
});
export const apiAssignPermissions = z.object({
id: z.string().min(1),
accessedProjects: z.array(z.string()).optional(),
accessedEnvironments: z.array(z.string()).optional(),
accessedServices: z.array(z.string()).optional(),
canCreateProjects: z.boolean().optional(),
canCreateServices: z.boolean().optional(),
canDeleteProjects: z.boolean().optional(),
canDeleteServices: z.boolean().optional(),
canAccessToDocker: z.boolean().optional(),
canAccessToTraefikFiles: z.boolean().optional(),
canAccessToAPI: z.boolean().optional(),
canAccessToSSHKeys: z.boolean().optional(),
canAccessToGitProviders: z.boolean().optional(),
canDeleteEnvironments: z.boolean().optional(),
canCreateEnvironments: z.boolean().optional(),
});
export const apiAssignPermissions = createSchema
.pick({
id: true,
// canCreateProjects: true,
// canCreateServices: true,
// canDeleteProjects: true,
// canDeleteServices: true,
// accessedProjects: true,
// accessedServices: true,
// canAccessToTraefikFiles: true,
// canAccessToDocker: true,
// canAccessToAPI: true,
// canAccessToSSHKeys: true,
// canAccessToGitProviders: true,
})
.extend({
accessedProjects: z.array(z.string()).optional(),
accessedEnvironments: z.array(z.string()).optional(),
accessedServices: z.array(z.string()).optional(),
canCreateProjects: z.boolean().optional(),
canCreateServices: z.boolean().optional(),
canDeleteProjects: z.boolean().optional(),
canDeleteServices: z.boolean().optional(),
canAccessToDocker: z.boolean().optional(),
canAccessToTraefikFiles: z.boolean().optional(),
canAccessToAPI: z.boolean().optional(),
canAccessToSSHKeys: z.boolean().optional(),
canAccessToGitProviders: z.boolean().optional(),
canDeleteEnvironments: z.boolean().optional(),
canCreateEnvironments: z.boolean().optional(),
})
.required();
export const apiFindOneUser = z.object({
id: z.string().min(1),
});
export const apiFindOneUser = createSchema
.pick({
id: true,
})
.required();
export const apiFindOneUserByAuth = z.object({});
export const apiFindOneUserByAuth = createSchema
.pick({
// authId: true,
})
.required();
export const apiTraefikConfig = z.object({
traefikConfig: z.string().min(1),
@@ -183,7 +219,7 @@ export const apiReadStatsLogs = z.object({
.optional(),
});
export const apiUpdateUser = z.object({
export const apiUpdateUser = createSchema.partial().extend({
email: z
.string()
.email("Please enter a valid email address")