feat: add update server ip

This commit is contained in:
Krzysztof Durek 2024-11-17 18:18:00 +01:00
parent 82fc9897d2
commit 74374bd643
9 changed files with 168 additions and 20 deletions

View File

@ -1,6 +1,7 @@
import { Button } from "@/components/ui/button";
import React from "react";
import { UpdateServerIp } from "@/components/dashboard/settings/web-server/update-server-ip";
import {
DropdownMenu,
DropdownMenuContent,
@ -39,12 +40,26 @@ export const ShowDokployActions = () => {
toast.success("Server Reloaded");
});
}}
className="cursor-pointer"
>
<span>Reload</span>
Reload
</DropdownMenuItem>
<ShowModalLogs appName="dokploy">
<span>Watch logs</span>
<DropdownMenuItem
className="cursor-pointer"
onSelect={(e) => e.preventDefault()}
>
Watch Logs
</DropdownMenuItem>
</ShowModalLogs>
<UpdateServerIp>
<DropdownMenuItem
className="cursor-pointer"
onSelect={(e) => e.preventDefault()}
>
Update Server IP
</DropdownMenuItem>
</UpdateServerIp>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>

View File

@ -1,4 +1,3 @@
import { CardDescription, CardTitle } from "@/components/ui/card";
import {
Dialog,
DialogContent,
@ -21,13 +20,13 @@ export const ShowServerActions = ({ serverId }: Props) => {
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>
<DropdownMenuItem
className="w-full cursor-pointer "
className="w-full cursor-pointer"
onSelect={(e) => e.preventDefault()}
>
View Actions
</DropdownMenuItem>
</DialogTrigger>
<DialogContent className="sm:max-w-xl overflow-y-auto max-h-screen ">
<DialogContent className="sm:max-w-xl overflow-y-auto max-h-screen">
<div className="flex flex-col gap-1">
<DialogTitle className="text-xl">Web server settings</DialogTitle>
<DialogDescription>Reload or clean the web server.</DialogDescription>

View File

@ -85,7 +85,7 @@ export const ShowStorageActions = ({ serverId }: Props) => {
});
}}
>
<span>Clean unused images</span>
<span>Clean Unused Images</span>
</DropdownMenuItem>
<DropdownMenuItem
className="w-full cursor-pointer"
@ -101,7 +101,7 @@ export const ShowStorageActions = ({ serverId }: Props) => {
});
}}
>
<span>Clean unused volumes</span>
<span>Clean Unused Volumes</span>
</DropdownMenuItem>
<DropdownMenuItem
@ -118,7 +118,7 @@ export const ShowStorageActions = ({ serverId }: Props) => {
});
}}
>
<span>Clean stopped containers</span>
<span>Clean Stopped Containers</span>
</DropdownMenuItem>
<DropdownMenuItem
@ -168,7 +168,7 @@ export const ShowStorageActions = ({ serverId }: Props) => {
});
}}
>
<span>Clean all</span>
<span>Clean All</span>
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>

View File

@ -70,16 +70,22 @@ export const ShowTraefikActions = ({ serverId }: Props) => {
toast.error("Error to reload the traefik");
});
}}
className="cursor-pointer"
>
<span>Reload</span>
</DropdownMenuItem>
<ShowModalLogs appName="dokploy-traefik" serverId={serverId}>
<span>Watch logs</span>
<DropdownMenuItem
onSelect={(e) => e.preventDefault()}
className="cursor-pointer"
>
Watch Logs
</DropdownMenuItem>
</ShowModalLogs>
<EditTraefikEnv serverId={serverId}>
<DropdownMenuItem
onSelect={(e) => e.preventDefault()}
className="w-full cursor-pointer space-x-3"
className="cursor-pointer"
>
<span>Modify Env</span>
</DropdownMenuItem>

View File

@ -58,14 +58,7 @@ export const ShowModalLogs = ({ appName, children, serverId }: Props) => {
}, [data]);
return (
<Dialog>
<DialogTrigger asChild>
<DropdownMenuItem
className="w-full cursor-pointer space-x-3"
onSelect={(e) => e.preventDefault()}
>
{children}
</DropdownMenuItem>
</DialogTrigger>
<DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-7xl">
<DialogHeader>
<DialogTitle>View Logs</DialogTitle>

View File

@ -0,0 +1,125 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { CodeEditor } from "@/components/shared/code-editor";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const schema = z.object({
serverIp: z.string(),
});
type Schema = z.infer<typeof schema>;
interface Props {
children?: React.ReactNode;
serverId?: string;
}
export const UpdateServerIp = ({ children, serverId }: Props) => {
const [isOpen, setIsOpen] = useState(false);
const { data } = api.admin.one.useQuery();
const { mutateAsync, isLoading, error, isError } =
api.admin.update.useMutation();
const form = useForm<Schema>({
defaultValues: {
serverIp: data?.serverIp || "",
},
resolver: zodResolver(schema),
});
useEffect(() => {
if (data) {
form.reset({
serverIp: data.serverIp || "",
});
}
}, [form, form.reset, data]);
const utils = api.useUtils();
const onSubmit = async (data: Schema) => {
await mutateAsync({
serverIp: data.serverIp,
})
.then(async () => {
toast.success("Server IP Updated");
await utils.admin.one.invalidate();
setIsOpen(false);
})
.catch(() => {
toast.error("Error to update the IP of the server");
});
};
return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Update Server IP</DialogTitle>
<DialogDescription>Update the IP of the server</DialogDescription>
</DialogHeader>
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form
id="hook-form-update-server-ip"
onSubmit={form.handleSubmit(onSubmit)}
>
<FormField
control={form.control}
name="serverIp"
render={({ field }) => (
<FormItem>
<FormLabel>Server IP</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<pre>
<FormMessage />
</pre>
</FormItem>
)}
/>
</form>
<DialogFooter>
<Button
isLoading={isLoading}
disabled={isLoading}
form="hook-form-update-server-ip"
type="submit"
>
Update
</Button>
</DialogFooter>
</Form>
</DialogContent>
</Dialog>
);
};

View File

@ -87,7 +87,7 @@ export const UpdateServer = () => {
}}
isLoading={isLoading}
>
Check updates
Check Updates
</Button>
)}
</div>

View File

@ -4,6 +4,7 @@ import {
apiCreateUserInvitation,
apiFindOneToken,
apiRemoveUser,
apiUpdateAdmin,
users,
} from "@/server/db/schema";
import {
@ -13,6 +14,7 @@ import {
findUserById,
getUserByToken,
removeUserByAuthId,
updateAdmin,
} from "@dokploy/server";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
@ -26,6 +28,12 @@ export const adminRouter = createTRPCRouter({
...rest,
};
}),
update: adminProcedure
.input(apiUpdateAdmin)
.mutation(async ({ input, ctx }) => {
const { authId } = await findAdminById(ctx.user.adminId);
return updateAdmin(authId, input);
}),
createUserInvitation: adminProcedure
.input(apiCreateUserInvitation)
.mutation(async ({ input, ctx }) => {

View File

@ -53,6 +53,8 @@ const createSchema = createInsertSchema(admins, {
letsEncryptEmail: z.string().optional(),
});
export const apiUpdateAdmin = createSchema.partial();
export const apiSaveSSHKey = createSchema
.pick({
sshPrivateKey: true,