feat: add volume selection functionality to volume backup form

- Introduced a new query to fetch named mounts by application ID, enhancing the volume backup form.
- Updated the form to allow users to select a volume from a dropdown, improving user experience.
- Retained the option for manual input of volume names, ensuring flexibility in volume selection.
This commit is contained in:
Mauricio Siu
2025-06-29 23:24:44 -06:00
parent 12860a0736
commit 819a310d48
2 changed files with 74 additions and 16 deletions
@@ -132,6 +132,11 @@ export const HandleVolumeBackups = ({
{ enabled: !!volumeBackupId }, { enabled: !!volumeBackupId },
); );
const { data: mounts } = api.mounts.allNamedByApplicationId.useQuery(
{ applicationId: id || "" },
{ enabled: !!id },
);
const { const {
data: services, data: services,
isFetching: isLoadingServices, isFetching: isLoadingServices,
@@ -479,22 +484,61 @@ export const HandleVolumeBackups = ({
)} )}
/> />
<FormField {serviceTypeForm === "application" && (
control={form.control} <>
name="volumeName" <FormField
render={({ field }) => ( control={form.control}
<FormItem> name="volumeName"
<FormLabel>Volume Name</FormLabel> render={({ field }) => (
<FormControl> <FormItem>
<Input placeholder="my-volume-name" {...field} /> <FormLabel>Volumes</FormLabel>
</FormControl> <Select
<FormDescription> onValueChange={field.onChange}
The name of the Docker volume to backup defaultValue={field.value || ""}
</FormDescription> >
<FormMessage /> <FormControl>
</FormItem> <SelectTrigger>
)} <SelectValue placeholder="Select a volume name" />
/> </SelectTrigger>
</FormControl>
<SelectContent>
{mounts?.map((mount) => (
<SelectItem
key={mount.mountId}
value={mount.volumeName || ""}
>
{mount.volumeName}
</SelectItem>
))}
</SelectContent>
</Select>
<FormDescription>
Choose the volume to backup, if you dont see the volume
here, you can type the volume name manually
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="volumeName"
render={({ field }) => (
<FormItem>
<FormLabel>Volume Name</FormLabel>
<FormControl>
<Input placeholder="my-volume-name" {...field} />
</FormControl>
<FormDescription>
The name of the Docker volume to backup
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</>
)}
<FormField <FormField
control={form.control} control={form.control}
+14
View File
@@ -3,6 +3,7 @@ import {
apiFindOneMount, apiFindOneMount,
apiRemoveMount, apiRemoveMount,
apiUpdateMount, apiUpdateMount,
mounts,
} from "@/server/db/schema"; } from "@/server/db/schema";
import { import {
createMount, createMount,
@@ -11,6 +12,9 @@ import {
updateMount, updateMount,
} from "@dokploy/server"; } from "@dokploy/server";
import { createTRPCRouter, protectedProcedure } from "../trpc"; import { createTRPCRouter, protectedProcedure } from "../trpc";
import { z } from "zod";
import { and, eq } from "drizzle-orm";
import { db } from "@dokploy/server/db";
export const mountRouter = createTRPCRouter({ export const mountRouter = createTRPCRouter({
create: protectedProcedure create: protectedProcedure
@@ -33,4 +37,14 @@ export const mountRouter = createTRPCRouter({
.mutation(async ({ input }) => { .mutation(async ({ input }) => {
return await updateMount(input.mountId, input); return await updateMount(input.mountId, input);
}), }),
allNamedByApplicationId: protectedProcedure
.input(z.object({ applicationId: z.string().min(1) }))
.query(async ({ input }) => {
return await db.query.mounts.findMany({
where: and(
eq(mounts.applicationId, input.applicationId),
eq(mounts.type, "volume"),
),
});
}),
}); });