mirror of
https://github.com/LukeHagar/dokploy.git
synced 2025-12-09 12:27:48 +00:00
feat: add dokploy cloud modal
This commit is contained in:
@@ -145,7 +145,7 @@ export const SetupServer = ({ serverId }: Props) => {
|
|||||||
Automatic process
|
Automatic process
|
||||||
</span>
|
</span>
|
||||||
<Link
|
<Link
|
||||||
href="https://docs.dokploy.com/en/docs/core/get-started/introduction"
|
href="https://docs.dokploy.com/docs/core/multi-server/instructions#requirements"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="text-primary flex flex-row gap-2"
|
className="text-primary flex flex-row gap-2"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -31,8 +31,12 @@ import { SetupServer } from "./setup-server";
|
|||||||
import { ShowDockerContainersModal } from "./show-docker-containers-modal";
|
import { ShowDockerContainersModal } from "./show-docker-containers-modal";
|
||||||
import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal";
|
import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal";
|
||||||
import { UpdateServer } from "./update-server";
|
import { UpdateServer } from "./update-server";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
import { WelcomeSuscription } from "./welcome-stripe/welcome-suscription";
|
||||||
|
|
||||||
export const ShowServers = () => {
|
export const ShowServers = () => {
|
||||||
|
const router = useRouter();
|
||||||
|
const query = router.query;
|
||||||
const { data, refetch } = api.server.all.useQuery();
|
const { data, refetch } = api.server.all.useQuery();
|
||||||
const { mutateAsync } = api.server.remove.useMutation();
|
const { mutateAsync } = api.server.remove.useMutation();
|
||||||
const { data: sshKeys } = api.sshKey.all.useQuery();
|
const { data: sshKeys } = api.sshKey.all.useQuery();
|
||||||
@@ -42,6 +46,7 @@ export const ShowServers = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-6 space-y-6">
|
<div className="p-6 space-y-6">
|
||||||
|
{query?.success && <WelcomeSuscription />}
|
||||||
<div className="space-y-2 flex flex-row justify-between items-end">
|
<div className="space-y-2 flex flex-row justify-between items-end">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-bold">Servers</h1>
|
<h1 className="text-2xl font-bold">Servers</h1>
|
||||||
|
|||||||
@@ -0,0 +1,284 @@
|
|||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { DialogFooter } from "@/components/ui/dialog";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { PlusIcon } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
const Schema = z.object({
|
||||||
|
name: z.string().min(1, {
|
||||||
|
message: "Name is required",
|
||||||
|
}),
|
||||||
|
description: z.string().optional(),
|
||||||
|
ipAddress: z.string().min(1, {
|
||||||
|
message: "IP Address is required",
|
||||||
|
}),
|
||||||
|
port: z.number().optional(),
|
||||||
|
username: z.string().optional(),
|
||||||
|
sshKeyId: z.string().min(1, {
|
||||||
|
message: "SSH Key is required",
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
type Schema = z.infer<typeof Schema>;
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
stepper: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CreateServer = ({ stepper }: Props) => {
|
||||||
|
const { data: sshKeys } = api.sshKey.all.useQuery();
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const { data: canCreateMoreServers, refetch } =
|
||||||
|
api.stripe.canCreateMoreServers.useQuery();
|
||||||
|
const { mutateAsync, error, isError } = api.server.create.useMutation();
|
||||||
|
const cloudSSHKey = sshKeys?.find(
|
||||||
|
(sshKey) => sshKey.name === "dokploy-cloud-ssh-key",
|
||||||
|
);
|
||||||
|
|
||||||
|
const form = useForm<Schema>({
|
||||||
|
defaultValues: {
|
||||||
|
description: "Dokploy Cloud Server",
|
||||||
|
name: "My First Server",
|
||||||
|
ipAddress: "",
|
||||||
|
port: 22,
|
||||||
|
username: "root",
|
||||||
|
sshKeyId: cloudSSHKey?.sshKeyId || "",
|
||||||
|
},
|
||||||
|
resolver: zodResolver(Schema),
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
form.reset({
|
||||||
|
description: "Dokploy Cloud Server",
|
||||||
|
name: "My First Server",
|
||||||
|
ipAddress: "",
|
||||||
|
port: 22,
|
||||||
|
username: "root",
|
||||||
|
sshKeyId: cloudSSHKey?.sshKeyId || "",
|
||||||
|
});
|
||||||
|
}, [form, form.reset, form.formState.isSubmitSuccessful, sshKeys]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
refetch();
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
|
const onSubmit = async (data: Schema) => {
|
||||||
|
await mutateAsync({
|
||||||
|
name: data.name,
|
||||||
|
description: data.description || "",
|
||||||
|
ipAddress: data.ipAddress || "",
|
||||||
|
port: data.port || 22,
|
||||||
|
username: data.username || "root",
|
||||||
|
sshKeyId: data.sshKeyId || "",
|
||||||
|
})
|
||||||
|
.then(async (data) => {
|
||||||
|
toast.success("Server Created");
|
||||||
|
stepper.next();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
toast.error("Error to create a server");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Card className="bg-background flex flex-col gap-4">
|
||||||
|
<div className="flex flex-col gap-2 pt-5 px-4">
|
||||||
|
{!canCreateMoreServers && (
|
||||||
|
<AlertBlock type="warning">
|
||||||
|
You cannot create more servers,{" "}
|
||||||
|
<Link href="/dashboard/settings/billing" className="text-primary">
|
||||||
|
Please upgrade your plan
|
||||||
|
</Link>
|
||||||
|
</AlertBlock>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CardContent className="flex flex-col">
|
||||||
|
<Form {...form}>
|
||||||
|
<form
|
||||||
|
id="hook-form-add-server"
|
||||||
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
|
className="grid w-full gap-4"
|
||||||
|
>
|
||||||
|
<div className="flex flex-col gap-4 ">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="name"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Name</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder="Hostinger Server" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="description"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Description</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Textarea
|
||||||
|
placeholder="This server is for databases..."
|
||||||
|
className="resize-none"
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="sshKeyId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Select a SSH Key</FormLabel>
|
||||||
|
{!cloudSSHKey && (
|
||||||
|
<AlertBlock>
|
||||||
|
Looks like you didn't have the SSH Key yet, you can create
|
||||||
|
one{" "}
|
||||||
|
<Link
|
||||||
|
href="/dashboard/settings/ssh-keys"
|
||||||
|
className="text-primary"
|
||||||
|
>
|
||||||
|
here
|
||||||
|
</Link>
|
||||||
|
</AlertBlock>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Select
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
defaultValue={field.value}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a SSH Key" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
{sshKeys?.map((sshKey) => (
|
||||||
|
<SelectItem
|
||||||
|
key={sshKey.sshKeyId}
|
||||||
|
value={sshKey.sshKeyId}
|
||||||
|
>
|
||||||
|
{sshKey.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
<SelectLabel>
|
||||||
|
Registries ({sshKeys?.length})
|
||||||
|
</SelectLabel>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="ipAddress"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>IP Address</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder="192.168.1.100" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="port"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Port</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
placeholder="22"
|
||||||
|
{...field}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
if (value === "") {
|
||||||
|
field.onChange(0);
|
||||||
|
} else {
|
||||||
|
const number = Number.parseInt(value, 10);
|
||||||
|
if (!Number.isNaN(number)) {
|
||||||
|
field.onChange(number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="username"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Username</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder="root" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<DialogFooter className="pt-5">
|
||||||
|
<Button
|
||||||
|
isLoading={form.formState.isSubmitting}
|
||||||
|
// disabled={!canCreateMoreServers}
|
||||||
|
form="hook-form-add-server"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Create
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</Form>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
import { ExternalLinkIcon, Loader2 } from "lucide-react";
|
||||||
|
import copy from "copy-to-clipboard";
|
||||||
|
import { CopyIcon } from "lucide-react";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { CodeEditor } from "@/components/shared/code-editor";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export const CreateSSHKey = () => {
|
||||||
|
const { data, refetch } = api.sshKey.all.useQuery();
|
||||||
|
const generateMutation = api.sshKey.generate.useMutation();
|
||||||
|
const { mutateAsync, isLoading } = api.sshKey.create.useMutation();
|
||||||
|
const hasCreatedKey = useRef(false);
|
||||||
|
|
||||||
|
const cloudSSHKey = data?.find(
|
||||||
|
(sshKey) => sshKey.name === "dokploy-cloud-ssh-key",
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const createKey = async () => {
|
||||||
|
if (!data || cloudSSHKey || hasCreatedKey.current || isLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasCreatedKey.current = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const keys = await generateMutation.mutateAsync({
|
||||||
|
type: "rsa",
|
||||||
|
});
|
||||||
|
await mutateAsync({
|
||||||
|
name: "dokploy-cloud-ssh-key",
|
||||||
|
description: "Used on Dokploy Cloud",
|
||||||
|
privateKey: keys.privateKey,
|
||||||
|
publicKey: keys.publicKey,
|
||||||
|
});
|
||||||
|
await refetch();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating SSH key:", error);
|
||||||
|
hasCreatedKey.current = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
createKey();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="h-full bg-transparent">
|
||||||
|
<CardContent>
|
||||||
|
<div className="grid w-full gap-4 pt-4">
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="min-h-[25vh] justify-center flex items-center gap-4">
|
||||||
|
<Loader2
|
||||||
|
className="animate-spin text-muted-foreground"
|
||||||
|
size={32}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col gap-2 text-sm text-muted-foreground">
|
||||||
|
<p className="text-primary text-base font-semibold">
|
||||||
|
You have two options to add SSH Keys to your server:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>1. Add The SSH Key to Server Manually</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
2. Add the public SSH Key when you create a server in your
|
||||||
|
preffered provider (Hostinger, Digital Ocean, Hetzner, etc){" "}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2 w-full border rounded-lg p-4">
|
||||||
|
<span className="text-base font-semibold text-primary">
|
||||||
|
Option 1
|
||||||
|
</span>
|
||||||
|
<ul>
|
||||||
|
<li className="items-center flex gap-1">
|
||||||
|
1. Login to your server{" "}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
2. When you are logged in run the following command
|
||||||
|
<div className="flex relative flex-col gap-4 w-full mt-2">
|
||||||
|
<CodeEditor
|
||||||
|
lineWrapping
|
||||||
|
language="properties"
|
||||||
|
value={`echo "${cloudSSHKey?.publicKey}" >> ~/.ssh/authorized_keys`}
|
||||||
|
readOnly
|
||||||
|
className="font-mono opacity-60"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="absolute right-2 top-2"
|
||||||
|
onClick={() => {
|
||||||
|
copy(
|
||||||
|
`echo "${cloudSSHKey?.publicKey}" >> ~/.ssh/authorized_keys`,
|
||||||
|
);
|
||||||
|
toast.success("Copied to clipboard");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CopyIcon className="size-4" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li className="mt-1">
|
||||||
|
3. You're done, follow the next step to insert the details
|
||||||
|
of your server.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 w-full mt-2 border rounded-lg p-4">
|
||||||
|
<span className="text-base font-semibold text-primary">
|
||||||
|
Option 2
|
||||||
|
</span>
|
||||||
|
<div className="flex flex-col gap-4 w-full overflow-auto">
|
||||||
|
<div className="flex relative flex-col gap-2 overflow-y-auto">
|
||||||
|
<div className="text-sm text-primary flex flex-row gap-2 items-center">
|
||||||
|
Copy Public Key
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className=" right-2 top-8"
|
||||||
|
onClick={() => {
|
||||||
|
copy(
|
||||||
|
cloudSSHKey?.publicKey || "Generate a SSH Key",
|
||||||
|
);
|
||||||
|
toast.success("SSH Copied to clipboard");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CopyIcon className="size-4 text-muted-foreground" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
href="https://docs.dokploy.com/docs/core/multi-server/instructions#requirements"
|
||||||
|
target="_blank"
|
||||||
|
className="text-primary flex flex-row gap-2"
|
||||||
|
>
|
||||||
|
View Tutorial <ExternalLinkIcon className="size-4" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
import { ShowDeployment } from "@/components/dashboard/application/deployments/show-deployment";
|
||||||
|
import { DateTooltip } from "@/components/shared/date-tooltip";
|
||||||
|
import { DialogAction } from "@/components/shared/dialog-action";
|
||||||
|
import { StatusTooltip } from "@/components/shared/status-tooltip";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
CardDescription,
|
||||||
|
CardContent,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import { RocketIcon } from "lucide-react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { EditScript } from "../edit-script";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
|
||||||
|
export const Setup = () => {
|
||||||
|
const { data: servers } = api.server.all.useQuery();
|
||||||
|
const [serverId, setServerId] = useState<string>(
|
||||||
|
servers?.[0]?.serverId || "",
|
||||||
|
);
|
||||||
|
const { data: server } = api.server.one.useQuery(
|
||||||
|
{
|
||||||
|
serverId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enabled: !!serverId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const [activeLog, setActiveLog] = useState<string | null>(null);
|
||||||
|
const { data: deployments, refetch } = api.deployment.allByServer.useQuery(
|
||||||
|
{ serverId },
|
||||||
|
{
|
||||||
|
enabled: !!serverId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const { mutateAsync, isLoading } = api.server.setup.useMutation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<Card className="bg-background">
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between flex-wrap gap-2">
|
||||||
|
<div className="flex flex-col gap-2 w-full">
|
||||||
|
<Label>Select a server</Label>
|
||||||
|
<Select onValueChange={setServerId} defaultValue={serverId}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a server" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
{servers?.map((server) => (
|
||||||
|
<SelectItem key={server.serverId} value={server.serverId}>
|
||||||
|
{server.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
<SelectLabel>Servers ({servers?.length})</SelectLabel>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-row gap-2 justify-between w-full max-sm:flex-col">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<CardTitle className="text-xl">Deployments</CardTitle>
|
||||||
|
<CardDescription>See all the 5 Server Setup</CardDescription>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-row gap-2">
|
||||||
|
<EditScript serverId={server?.serverId || ""} />
|
||||||
|
<DialogAction
|
||||||
|
title={"Setup Server?"}
|
||||||
|
description="This will setup the server and all associated data"
|
||||||
|
onClick={async () => {
|
||||||
|
await mutateAsync({
|
||||||
|
serverId: server?.serverId || "",
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
refetch();
|
||||||
|
toast.success("Server setup successfully");
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
toast.error("Error configuring server");
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button isLoading={isLoading}>Setup Server</Button>
|
||||||
|
</DialogAction>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-col gap-4 min-h-[30vh]">
|
||||||
|
{server?.deployments?.length === 0 ? (
|
||||||
|
<div className="flex w-full flex-col items-center justify-center gap-3 pt-10">
|
||||||
|
<RocketIcon className="size-8 text-muted-foreground" />
|
||||||
|
<span className="text-base text-muted-foreground">
|
||||||
|
No deployments found
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
{deployments?.map((deployment) => (
|
||||||
|
<div
|
||||||
|
key={deployment.deploymentId}
|
||||||
|
className="flex items-center justify-between rounded-lg border p-4 gap-2"
|
||||||
|
>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<span className="flex items-center gap-4 font-medium capitalize text-foreground">
|
||||||
|
{deployment.status}
|
||||||
|
|
||||||
|
<StatusTooltip
|
||||||
|
status={deployment?.status}
|
||||||
|
className="size-2.5"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
{deployment.title}
|
||||||
|
</span>
|
||||||
|
{deployment.description && (
|
||||||
|
<span className="break-all text-sm text-muted-foreground">
|
||||||
|
{deployment.description}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-end gap-2">
|
||||||
|
<div className="text-sm capitalize text-muted-foreground">
|
||||||
|
<DateTooltip date={deployment.createdAt} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setActiveLog(deployment.logPath);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<ShowDeployment
|
||||||
|
open={activeLog !== null}
|
||||||
|
onClose={() => setActiveLog(null)}
|
||||||
|
logPath={activeLog}
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
CardDescription,
|
||||||
|
CardContent,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import { Loader2, PcCase, RefreshCw } from "lucide-react";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { StatusRow } from "../gpu-support";
|
||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
|
|
||||||
|
export const Verify = () => {
|
||||||
|
const { data: servers } = api.server.all.useQuery();
|
||||||
|
const [serverId, setServerId] = useState<string>(
|
||||||
|
servers?.[0]?.serverId || "",
|
||||||
|
);
|
||||||
|
const { data, refetch, error, isLoading, isError } =
|
||||||
|
api.server.validate.useQuery(
|
||||||
|
{ serverId },
|
||||||
|
{
|
||||||
|
enabled: !!serverId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||||
|
|
||||||
|
const { data: server } = api.server.one.useQuery(
|
||||||
|
{
|
||||||
|
serverId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enabled: !!serverId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CardContent className="p-0">
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<Card className="bg-background">
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between flex-wrap gap-2">
|
||||||
|
<div className="flex flex-col gap-2 w-full">
|
||||||
|
<Label>Select a server</Label>
|
||||||
|
<Select onValueChange={setServerId} defaultValue={serverId}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a server" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
{servers?.map((server) => (
|
||||||
|
<SelectItem key={server.serverId} value={server.serverId}>
|
||||||
|
{server.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
<SelectLabel>Servers ({servers?.length})</SelectLabel>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-row gap-2 justify-between w-full max-sm:flex-col">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<PcCase className="size-5" />
|
||||||
|
<CardTitle className="text-xl">Setup Validation</CardTitle>
|
||||||
|
</div>
|
||||||
|
<CardDescription>
|
||||||
|
Check if your server is ready for deployment
|
||||||
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
isLoading={isRefreshing}
|
||||||
|
onClick={async () => {
|
||||||
|
setIsRefreshing(true);
|
||||||
|
await refetch();
|
||||||
|
setIsRefreshing(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RefreshCw className="size-4" />
|
||||||
|
Refresh
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 w-full">
|
||||||
|
{isError && (
|
||||||
|
<AlertBlock type="error" className="w-full">
|
||||||
|
{error.message}
|
||||||
|
</AlertBlock>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<CardContent className="flex flex-col gap-4 min-h-[25vh]">
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex items-center justify-center text-muted-foreground py-4">
|
||||||
|
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||||
|
<span>Checking Server configuration</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="grid w-full gap-4">
|
||||||
|
<div className="border rounded-lg p-4">
|
||||||
|
<h3 className="text-lg font-semibold mb-1">Status</h3>
|
||||||
|
<p className="text-sm text-muted-foreground mb-4">
|
||||||
|
Shows the server configuration status
|
||||||
|
</p>
|
||||||
|
<div className="grid gap-2.5">
|
||||||
|
<StatusRow
|
||||||
|
label="Docker Installed"
|
||||||
|
isEnabled={data?.docker?.enabled}
|
||||||
|
description={
|
||||||
|
data?.docker?.enabled
|
||||||
|
? `Installed: ${data?.docker?.version}`
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<StatusRow
|
||||||
|
label="RClone Installed"
|
||||||
|
isEnabled={data?.rclone?.enabled}
|
||||||
|
description={
|
||||||
|
data?.rclone?.enabled
|
||||||
|
? `Installed: ${data?.rclone?.version}`
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<StatusRow
|
||||||
|
label="Nixpacks Installed"
|
||||||
|
isEnabled={data?.nixpacks?.enabled}
|
||||||
|
description={
|
||||||
|
data?.nixpacks?.enabled
|
||||||
|
? `Installed: ${data?.nixpacks?.version}`
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<StatusRow
|
||||||
|
label="Buildpacks Installed"
|
||||||
|
isEnabled={data?.buildpacks?.enabled}
|
||||||
|
description={
|
||||||
|
data?.buildpacks?.enabled
|
||||||
|
? `Installed: ${data?.buildpacks?.version}`
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<StatusRow
|
||||||
|
label="Docker Swarm Initialized"
|
||||||
|
isEnabled={data?.isSwarmInstalled}
|
||||||
|
description={
|
||||||
|
data?.isSwarmInstalled
|
||||||
|
? "Initialized"
|
||||||
|
: "Not Initialized"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<StatusRow
|
||||||
|
label="Dokploy Network Created"
|
||||||
|
isEnabled={data?.isDokployNetworkInstalled}
|
||||||
|
description={
|
||||||
|
data?.isDokployNetworkInstalled
|
||||||
|
? "Created"
|
||||||
|
: "Not Created"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<StatusRow
|
||||||
|
label="Main Directory Created"
|
||||||
|
isEnabled={data?.isMainDirectoryInstalled}
|
||||||
|
description={
|
||||||
|
data?.isMainDirectoryInstalled
|
||||||
|
? "Created"
|
||||||
|
: "Not Created"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,366 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { Puzzle } from "lucide-react";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { defineStepper } from "@stepperize/react";
|
||||||
|
import React from "react";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
|
import { CreateServer } from "./create-server";
|
||||||
|
import { CreateSSHKey } from "./create-ssh-key";
|
||||||
|
import { Setup } from "./setup";
|
||||||
|
import { Verify } from "./verify";
|
||||||
|
import {
|
||||||
|
Database,
|
||||||
|
Globe,
|
||||||
|
GitMerge,
|
||||||
|
Code,
|
||||||
|
Users,
|
||||||
|
Code2,
|
||||||
|
Plug,
|
||||||
|
} from "lucide-react";
|
||||||
|
import ConfettiExplosion from "react-confetti-explosion";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const { useStepper, steps, Scoped } = defineStepper(
|
||||||
|
{
|
||||||
|
id: "requisites",
|
||||||
|
title: "Requisites",
|
||||||
|
description: "Check your requisites",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "create-ssh-key",
|
||||||
|
title: "SSH Key",
|
||||||
|
description: "Create your ssh key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "connect-server",
|
||||||
|
title: "Connect",
|
||||||
|
description: "Connect",
|
||||||
|
},
|
||||||
|
{ id: "setup", title: "Setup", description: "Setup your server" },
|
||||||
|
{ id: "verify", title: "Verify", description: "Verify your server" },
|
||||||
|
{ id: "complete", title: "Complete", description: "Checkout complete" },
|
||||||
|
);
|
||||||
|
|
||||||
|
export const WelcomeSuscription = ({ children }: Props) => {
|
||||||
|
const [showConfetti, setShowConfetti] = useState(false);
|
||||||
|
const stepper = useStepper();
|
||||||
|
const [isOpen, setIsOpen] = useState(true);
|
||||||
|
const { push } = useRouter();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const confettiShown = localStorage.getItem("hasShownConfetti");
|
||||||
|
if (!confettiShown) {
|
||||||
|
setShowConfetti(true);
|
||||||
|
localStorage.setItem("hasShownConfetti", "true");
|
||||||
|
}
|
||||||
|
}, [showConfetti]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={isOpen}>
|
||||||
|
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-7xl min-h-[75vh]">
|
||||||
|
{showConfetti ?? "Flaso"}
|
||||||
|
<div className="flex justify-center items-center w-full">
|
||||||
|
{showConfetti && (
|
||||||
|
<ConfettiExplosion
|
||||||
|
duration={3000}
|
||||||
|
force={0.3}
|
||||||
|
particleSize={12}
|
||||||
|
particleCount={300}
|
||||||
|
className="z-[9999]"
|
||||||
|
zIndex={9999}
|
||||||
|
width={1500}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="text-2xl text-center">
|
||||||
|
Welcome To Dokploy Cloud 🎉
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription className="text-center">
|
||||||
|
Thank you for choosing Dokploy Cloud, before you start you need to
|
||||||
|
configure your remote server
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="grid gap-4">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<h2 className="text-lg font-semibold">Steps</h2>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
Step {stepper.current.index + 1} of {steps.length}
|
||||||
|
</span>
|
||||||
|
<div />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Scoped>
|
||||||
|
<nav aria-label="Checkout Steps" className="group my-4">
|
||||||
|
<ol
|
||||||
|
className="flex items-center justify-between gap-2"
|
||||||
|
aria-orientation="horizontal"
|
||||||
|
>
|
||||||
|
{stepper.all.map((step, index, array) => (
|
||||||
|
<React.Fragment key={step.id}>
|
||||||
|
<li className="flex items-center gap-4 flex-shrink-0">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
role="tab"
|
||||||
|
variant={
|
||||||
|
index <= stepper.current.index
|
||||||
|
? "default"
|
||||||
|
: "secondary"
|
||||||
|
}
|
||||||
|
aria-current={
|
||||||
|
stepper.current.id === step.id ? "step" : undefined
|
||||||
|
}
|
||||||
|
aria-posinset={index + 1}
|
||||||
|
aria-setsize={steps.length}
|
||||||
|
aria-selected={stepper.current.id === step.id}
|
||||||
|
className="flex size-10 items-center justify-center rounded-full"
|
||||||
|
onClick={() => stepper.goTo(step.id)}
|
||||||
|
>
|
||||||
|
{index + 1}
|
||||||
|
</Button>
|
||||||
|
<span className="text-sm font-medium">{step.title}</span>
|
||||||
|
</li>
|
||||||
|
{index < array.length - 1 && (
|
||||||
|
<Separator
|
||||||
|
className={`flex-1 ${
|
||||||
|
index < stepper.current.index
|
||||||
|
? "bg-primary"
|
||||||
|
: "bg-muted"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
{stepper.switch({
|
||||||
|
requisites: () => (
|
||||||
|
<div className="flex flex-col gap-2 border p-4 rounded-lg">
|
||||||
|
<span className="text-primary text-base font-bold">
|
||||||
|
Before getting started, please follow the steps below to
|
||||||
|
ensure the best experience:
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
<p className="text-primary text-sm font-medium">
|
||||||
|
Supported Distributions:
|
||||||
|
</p>
|
||||||
|
<ul className="list-inside list-disc pl-4 text-sm text-muted-foreground mt-4">
|
||||||
|
<li>Ubuntu 24.04 LTS</li>
|
||||||
|
<li>Ubuntu 23.10</li>
|
||||||
|
<li>Ubuntu 22.04 LTS</li>
|
||||||
|
<li>Ubuntu 20.04 LTS</li>
|
||||||
|
<li>Ubuntu 18.04 LTS</li>
|
||||||
|
<li>Debian 12</li>
|
||||||
|
<li>Debian 11</li>
|
||||||
|
<li>Debian 10</li>
|
||||||
|
<li>Fedora 40</li>
|
||||||
|
<li>CentOS 9</li>
|
||||||
|
<li>CentOS 8</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-primary text-sm font-medium">
|
||||||
|
You will need to purchase or rent a Virtual Private Server
|
||||||
|
(VPS) to proceed, we recommend to use one of these
|
||||||
|
providers since has been heavily tested.
|
||||||
|
</p>
|
||||||
|
<ul className="list-inside list-disc pl-4 text-sm text-muted-foreground mt-4">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://www.hostinger.com/vps-hosting?REFERRALCODE=1SIUMAURICI97"
|
||||||
|
className="text-link underline"
|
||||||
|
>
|
||||||
|
Hostinger - Get 20% Discount
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://m.do.co/c/db24efd43f35"
|
||||||
|
className="text-link underline"
|
||||||
|
>
|
||||||
|
DigitalOcean - Get $200 Credits
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://hetzner.cloud/?ref=vou4fhxJ1W2D"
|
||||||
|
className="text-link underline"
|
||||||
|
>
|
||||||
|
Hetzner - Get €20 Credits
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://www.vultr.com/?ref=9679828"
|
||||||
|
className="text-link underline"
|
||||||
|
>
|
||||||
|
Vultr
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://www.linode.com/es/pricing/#compute-shared"
|
||||||
|
className="text-link underline"
|
||||||
|
>
|
||||||
|
Linode
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<AlertBlock className="mt-4 px-4">
|
||||||
|
You are free to use whatever provider, but we recommend to
|
||||||
|
use one of the above, to avoid issues.
|
||||||
|
</AlertBlock>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
"create-ssh-key": () => <CreateSSHKey />,
|
||||||
|
"connect-server": () => <CreateServer stepper={stepper} />,
|
||||||
|
setup: () => <Setup />,
|
||||||
|
verify: () => <Verify />,
|
||||||
|
complete: () => {
|
||||||
|
const features = [
|
||||||
|
{
|
||||||
|
title: "Scalable Deployments",
|
||||||
|
description:
|
||||||
|
"Deploy and scale your applications effortlessly to handle any workload.",
|
||||||
|
icon: <Database className="text-primary" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Automated Backups",
|
||||||
|
description: "Protect your data with automatic backups",
|
||||||
|
icon: <Database className="text-primary" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Open Source Templates",
|
||||||
|
description:
|
||||||
|
"Big list of common open source templates in one-click",
|
||||||
|
icon: <Puzzle className="text-primary" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Custom Domains",
|
||||||
|
description:
|
||||||
|
"Link your own domains to your applications for a professional presence.",
|
||||||
|
icon: <Globe className="text-primary" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "CI/CD Integration",
|
||||||
|
description:
|
||||||
|
"Implement continuous integration and deployment workflows to streamline development.",
|
||||||
|
icon: <GitMerge className="text-primary" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Database Management",
|
||||||
|
description:
|
||||||
|
"Efficiently manage your databases with intuitive tools.",
|
||||||
|
icon: <Database className="text-primary" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Team Collaboration",
|
||||||
|
description:
|
||||||
|
"Collaborate with your team on shared projects with customizable permissions.",
|
||||||
|
icon: <Users className="text-primary" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Multi-language Support",
|
||||||
|
description:
|
||||||
|
"Deploy applications in multiple programming languages to suit your needs.",
|
||||||
|
icon: <Code2 className="text-primary" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "API Access",
|
||||||
|
description:
|
||||||
|
"Integrate and manage your applications via robust and well-documented APIs.",
|
||||||
|
icon: <Plug className="text-primary" />,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-6">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<h2 className="text-xl font-semibold">You're All Set!</h2>
|
||||||
|
<p className=" text-muted-foreground">
|
||||||
|
Did you know you can deploy any number of applications
|
||||||
|
that your server can handle?
|
||||||
|
</p>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Here are some of the things you can do with Dokploy
|
||||||
|
Cloud:
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
||||||
|
{features.map((feature, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="flex flex-col items-start p-4 bg-card rounded-lg shadow-md hover:shadow-lg transition-shadow"
|
||||||
|
>
|
||||||
|
<div className="text-3xl mb-2">{feature.icon}</div>
|
||||||
|
<h3 className="text-lg font-medium mb-1">
|
||||||
|
{feature.title}
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
{feature.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
</Scoped>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<div className="flex items-center justify-between w-full">
|
||||||
|
{!stepper.isLast && (
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
onClick={() => {
|
||||||
|
setIsOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Skip for now
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2 w-full justify-end">
|
||||||
|
<Button
|
||||||
|
onClick={stepper.prev}
|
||||||
|
disabled={stepper.isFirst}
|
||||||
|
variant="secondary"
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
if (stepper.isLast) {
|
||||||
|
setIsOpen(false);
|
||||||
|
push("/dashboard/projects");
|
||||||
|
} else {
|
||||||
|
stepper.next();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{stepper.isLast ? "Complete" : "Next"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -35,7 +35,8 @@
|
|||||||
"test": "vitest --config __test__/vitest.config.ts"
|
"test": "vitest --config __test__/vitest.config.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@reactour/tour": "3.7.0",
|
"react-confetti-explosion":"2.1.2",
|
||||||
|
"@stepperize/react": "4.0.1",
|
||||||
"@codemirror/lang-json": "^6.0.1",
|
"@codemirror/lang-json": "^6.0.1",
|
||||||
"@codemirror/lang-yaml": "^6.1.1",
|
"@codemirror/lang-yaml": "^6.1.1",
|
||||||
"@codemirror/language": "^6.10.1",
|
"@codemirror/language": "^6.10.1",
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { SearchCommand } from "@/components/dashboard/search-command";
|
|||||||
import { Toaster } from "@/components/ui/sonner";
|
import { Toaster } from "@/components/ui/sonner";
|
||||||
import { Languages } from "@/lib/languages";
|
import { Languages } from "@/lib/languages";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { TourProvider } from "@reactour/tour";
|
|
||||||
import type { NextPage } from "next";
|
import type { NextPage } from "next";
|
||||||
import { appWithTranslation } from "next-i18next";
|
import { appWithTranslation } from "next-i18next";
|
||||||
import { ThemeProvider } from "next-themes";
|
import { ThemeProvider } from "next-themes";
|
||||||
@@ -16,21 +15,6 @@ import type { ReactElement, ReactNode } from "react";
|
|||||||
|
|
||||||
const inter = Inter({ subsets: ["latin"] });
|
const inter = Inter({ subsets: ["latin"] });
|
||||||
|
|
||||||
export const steps = [
|
|
||||||
{
|
|
||||||
selector: ".first-step",
|
|
||||||
content: "This is the first Step",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
selector: ".second-step",
|
|
||||||
content: "This is the second Step",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
selector: ".third-step",
|
|
||||||
content: "This is the third Step",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
|
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
|
||||||
getLayout?: (page: ReactElement) => ReactNode;
|
getLayout?: (page: ReactElement) => ReactNode;
|
||||||
// session: Session | null;
|
// session: Session | null;
|
||||||
@@ -65,7 +49,6 @@ const MyApp = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<TourProvider steps={steps}>
|
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
attribute="class"
|
attribute="class"
|
||||||
defaultTheme="system"
|
defaultTheme="system"
|
||||||
@@ -77,7 +60,6 @@ const MyApp = ({
|
|||||||
<SearchCommand />
|
<SearchCommand />
|
||||||
{getLayout(<Component {...pageProps} />)}
|
{getLayout(<Component {...pageProps} />)}
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</TourProvider>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
updateSSHKeyById,
|
updateSSHKeyById,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
import { desc, eq } from "drizzle-orm";
|
||||||
|
|
||||||
export const sshRouter = createTRPCRouter({
|
export const sshRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
@@ -71,6 +71,7 @@ export const sshRouter = createTRPCRouter({
|
|||||||
all: protectedProcedure.query(async ({ ctx }) => {
|
all: protectedProcedure.query(async ({ ctx }) => {
|
||||||
return await db.query.sshKeys.findMany({
|
return await db.query.sshKeys.findMany({
|
||||||
...(IS_CLOUD && { where: eq(sshKeys.adminId, ctx.user.adminId) }),
|
...(IS_CLOUD && { where: eq(sshKeys.adminId, ctx.user.adminId) }),
|
||||||
|
orderBy: desc(sshKeys.createdAt),
|
||||||
});
|
});
|
||||||
// TODO: Remove this line when the cloud version is ready
|
// TODO: Remove this line when the cloud version is ready
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export const stripeRouter = createTRPCRouter({
|
|||||||
adminId: admin.adminId,
|
adminId: admin.adminId,
|
||||||
},
|
},
|
||||||
allow_promotion_codes: true,
|
allow_promotion_codes: true,
|
||||||
success_url: `${WEBSITE_URL}/dashboard/settings/billing`,
|
success_url: `${WEBSITE_URL}/dashboard/settings/servers?success=true`,
|
||||||
cancel_url: `${WEBSITE_URL}/dashboard/settings/billing`,
|
cancel_url: `${WEBSITE_URL}/dashboard/settings/billing`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const serverSetup = async (serverId: string) => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
await updateDeploymentStatus(deployment.deploymentId, "error");
|
await updateDeploymentStatus(deployment.deploymentId, "error");
|
||||||
writeStream.write(err);
|
writeStream.write(`${err} ❌\n`);
|
||||||
writeStream.close();
|
writeStream.close();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
318
pnpm-lock.yaml
generated
318
pnpm-lock.yaml
generated
@@ -178,9 +178,9 @@ importers:
|
|||||||
'@radix-ui/react-tooltip':
|
'@radix-ui/react-tooltip':
|
||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||||
'@reactour/tour':
|
'@stepperize/react':
|
||||||
specifier: 3.7.0
|
specifier: 4.0.1
|
||||||
version: 3.7.0(react@18.2.0)
|
version: 4.0.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||||
'@stripe/stripe-js':
|
'@stripe/stripe-js':
|
||||||
specifier: 4.8.0
|
specifier: 4.8.0
|
||||||
version: 4.8.0
|
version: 4.8.0
|
||||||
@@ -301,6 +301,9 @@ importers:
|
|||||||
react:
|
react:
|
||||||
specifier: 18.2.0
|
specifier: 18.2.0
|
||||||
version: 18.2.0
|
version: 18.2.0
|
||||||
|
react-confetti-explosion:
|
||||||
|
specifier: 2.1.2
|
||||||
|
version: 2.1.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||||
react-dom:
|
react-dom:
|
||||||
specifier: 18.2.0
|
specifier: 18.2.0
|
||||||
version: 18.2.0(react@18.2.0)
|
version: 18.2.0(react@18.2.0)
|
||||||
@@ -863,6 +866,12 @@ packages:
|
|||||||
'@emnapi/runtime@1.3.1':
|
'@emnapi/runtime@1.3.1':
|
||||||
resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==}
|
resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==}
|
||||||
|
|
||||||
|
'@emotion/is-prop-valid@0.7.3':
|
||||||
|
resolution: {integrity: sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA==}
|
||||||
|
|
||||||
|
'@emotion/memoize@0.7.1':
|
||||||
|
resolution: {integrity: sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==}
|
||||||
|
|
||||||
'@esbuild-kit/core-utils@3.3.2':
|
'@esbuild-kit/core-utils@3.3.2':
|
||||||
resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==}
|
resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==}
|
||||||
|
|
||||||
@@ -2874,26 +2883,6 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^18.2.0
|
react: ^18.2.0
|
||||||
|
|
||||||
'@reactour/mask@1.1.0':
|
|
||||||
resolution: {integrity: sha512-GkJMLuTs3vTsm4Ryq2uXcE4sMzRP1p4xSd6juSOMqbHa7IVD/UiLCLqJWHR9xGSQPbYhpZAZAORUG5cS0U5tBA==}
|
|
||||||
peerDependencies:
|
|
||||||
react: 16.x || 17.x || 18.x
|
|
||||||
|
|
||||||
'@reactour/popover@1.2.0':
|
|
||||||
resolution: {integrity: sha512-1JMykZ+MmDmRlEVC5+DwlvK1exwV5bFHtiSFwVXnoPZmsSfwId6SLyjo9H6bybeuNtNEzviKdsF/ZBC1UQbDqg==}
|
|
||||||
peerDependencies:
|
|
||||||
react: 16.x || 17.x || 18.x
|
|
||||||
|
|
||||||
'@reactour/tour@3.7.0':
|
|
||||||
resolution: {integrity: sha512-p0USaOBc5fcNBS5ZiQ2lsmztAhIGCUfx913Zw14FbEM8bhSXpR1F2JD0alVj9Ya1N+pnTNYatf14rSNGJsEnCg==}
|
|
||||||
peerDependencies:
|
|
||||||
react: 16.x || 17.x || 18.x
|
|
||||||
|
|
||||||
'@reactour/utils@0.5.0':
|
|
||||||
resolution: {integrity: sha512-yQs5Nm/Dg1xRM7d/S/UILBV5OInrTgrjGzgc81/RP5khqdO5KnpOaC46yF83kDtCalte8X3RCwp+F2YA509k1w==}
|
|
||||||
peerDependencies:
|
|
||||||
react: 16.x || 17.x || 18.x
|
|
||||||
|
|
||||||
'@redis/bloom@1.2.0':
|
'@redis/bloom@1.2.0':
|
||||||
resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==}
|
resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3003,11 +2992,6 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@rooks/use-mutation-observer@4.11.2':
|
|
||||||
resolution: {integrity: sha512-vpsdrZdr6TkB1zZJcHx+fR1YC/pHs2BaqcuYiEGjBVbwY5xcC49+h0hAUtQKHth3oJqXfIX/Ng8S7s5HFHdM/A==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=16.8.0'
|
|
||||||
|
|
||||||
'@selderee/plugin-htmlparser2@0.11.0':
|
'@selderee/plugin-htmlparser2@0.11.0':
|
||||||
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
||||||
|
|
||||||
@@ -3022,6 +3006,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
|
resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@stepperize/react@4.0.1':
|
||||||
|
resolution: {integrity: sha512-LAOcfi3d2mM/Jn740Xy35qsuTwmoLIuitvWZTZRURYeGsc7a6sIKAkk3+L1joZGkLFvf5q4I6V7LxWWfB5hDvg==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
|
react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
|
|
||||||
'@stripe/stripe-js@4.8.0':
|
'@stripe/stripe-js@4.8.0':
|
||||||
resolution: {integrity: sha512-+4Cb0bVHlV4BJXxkJ3cCLSLuWxm3pXKtgcRacox146EuugjCzRRII5T5gUMgL4HpzrBLVwVxjKaZqntNWAXawQ==}
|
resolution: {integrity: sha512-+4Cb0bVHlV4BJXxkJ3cCLSLuWxm3pXKtgcRacox146EuugjCzRRII5T5gUMgL4HpzrBLVwVxjKaZqntNWAXawQ==}
|
||||||
engines: {node: '>=12.16'}
|
engines: {node: '>=12.16'}
|
||||||
@@ -3985,6 +3975,12 @@ packages:
|
|||||||
uWebSockets.js:
|
uWebSockets.js:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
css-jss@10.10.0:
|
||||||
|
resolution: {integrity: sha512-YyMIS/LsSKEGXEaVJdjonWe18p4vXLo8CMA4FrW/kcaEyqdIGKCFXao31gbJddXEdIxSXFFURWrenBJPlKTgAA==}
|
||||||
|
|
||||||
|
css-vendor@2.0.8:
|
||||||
|
resolution: {integrity: sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==}
|
||||||
|
|
||||||
css.escape@1.5.1:
|
css.escape@1.5.1:
|
||||||
resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
|
resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
|
||||||
|
|
||||||
@@ -4754,6 +4750,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==}
|
resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==}
|
||||||
engines: {node: '>=10.18'}
|
engines: {node: '>=10.18'}
|
||||||
|
|
||||||
|
hyphenate-style-name@1.1.0:
|
||||||
|
resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==}
|
||||||
|
|
||||||
i18next-fs-backend@2.3.2:
|
i18next-fs-backend@2.3.2:
|
||||||
resolution: {integrity: sha512-LIwUlkqDZnUI8lnUxBnEj8K/FrHQTT/Sc+1rvDm9E8YvvY5YxzoEAASNx+W5M9DfD5s77lI5vSAFWeTp26B/3Q==}
|
resolution: {integrity: sha512-LIwUlkqDZnUI8lnUxBnEj8K/FrHQTT/Sc+1rvDm9E8YvvY5YxzoEAASNx+W5M9DfD5s77lI5vSAFWeTp26B/3Q==}
|
||||||
|
|
||||||
@@ -4878,6 +4877,9 @@ packages:
|
|||||||
is-hexadecimal@1.0.4:
|
is-hexadecimal@1.0.4:
|
||||||
resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==}
|
resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==}
|
||||||
|
|
||||||
|
is-in-browser@1.1.3:
|
||||||
|
resolution: {integrity: sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==}
|
||||||
|
|
||||||
is-ip@4.0.0:
|
is-ip@4.0.0:
|
||||||
resolution: {integrity: sha512-4B4XA2HEIm/PY+OSpeMBXr8pGWBYbXuHgjMAqrwbLO3CPTCAd9ArEJzBUKGZtk9viY6+aSfadGnWyjY3ydYZkw==}
|
resolution: {integrity: sha512-4B4XA2HEIm/PY+OSpeMBXr8pGWBYbXuHgjMAqrwbLO3CPTCAd9ArEJzBUKGZtk9viY6+aSfadGnWyjY3ydYZkw==}
|
||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
@@ -4969,6 +4971,48 @@ packages:
|
|||||||
resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
|
resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
|
||||||
engines: {node: '>=12', npm: '>=6'}
|
engines: {node: '>=12', npm: '>=6'}
|
||||||
|
|
||||||
|
jss-plugin-camel-case@10.10.0:
|
||||||
|
resolution: {integrity: sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==}
|
||||||
|
|
||||||
|
jss-plugin-compose@10.10.0:
|
||||||
|
resolution: {integrity: sha512-F5kgtWpI2XfZ3Z8eP78tZEYFdgTIbpA/TMuX3a8vwrNolYtN1N4qJR/Ob0LAsqIwCMLojtxN7c7Oo/+Vz6THow==}
|
||||||
|
|
||||||
|
jss-plugin-default-unit@10.10.0:
|
||||||
|
resolution: {integrity: sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==}
|
||||||
|
|
||||||
|
jss-plugin-expand@10.10.0:
|
||||||
|
resolution: {integrity: sha512-ymT62W2OyDxBxr7A6JR87vVX9vTq2ep5jZLIdUSusfBIEENLdkkc0lL/Xaq8W9s3opUq7R0sZQpzRWELrfVYzA==}
|
||||||
|
|
||||||
|
jss-plugin-extend@10.10.0:
|
||||||
|
resolution: {integrity: sha512-sKYrcMfr4xxigmIwqTjxNcHwXJIfvhvjTNxF+Tbc1NmNdyspGW47Ey6sGH8BcQ4FFQhLXctpWCQSpDwdNmXSwg==}
|
||||||
|
|
||||||
|
jss-plugin-global@10.10.0:
|
||||||
|
resolution: {integrity: sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==}
|
||||||
|
|
||||||
|
jss-plugin-nested@10.10.0:
|
||||||
|
resolution: {integrity: sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==}
|
||||||
|
|
||||||
|
jss-plugin-props-sort@10.10.0:
|
||||||
|
resolution: {integrity: sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==}
|
||||||
|
|
||||||
|
jss-plugin-rule-value-function@10.10.0:
|
||||||
|
resolution: {integrity: sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==}
|
||||||
|
|
||||||
|
jss-plugin-rule-value-observable@10.10.0:
|
||||||
|
resolution: {integrity: sha512-ZLMaYrR3QE+vD7nl3oNXuj79VZl9Kp8/u6A1IbTPDcuOu8b56cFdWRZNZ0vNr8jHewooEeq2doy8Oxtymr2ZPA==}
|
||||||
|
|
||||||
|
jss-plugin-template@10.10.0:
|
||||||
|
resolution: {integrity: sha512-ocXZBIOJOA+jISPdsgkTs8wwpK6UbsvtZK5JI7VUggTD6LWKbtoxUzadd2TpfF+lEtlhUmMsCkTRNkITdPKa6w==}
|
||||||
|
|
||||||
|
jss-plugin-vendor-prefixer@10.10.0:
|
||||||
|
resolution: {integrity: sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==}
|
||||||
|
|
||||||
|
jss-preset-default@10.10.0:
|
||||||
|
resolution: {integrity: sha512-GL175Wt2FGhjE+f+Y3aWh+JioL06/QWFgZp53CbNNq6ZkVU0TDplD8Bxm9KnkotAYn3FlplNqoW5CjyLXcoJ7Q==}
|
||||||
|
|
||||||
|
jss@10.10.0:
|
||||||
|
resolution: {integrity: sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==}
|
||||||
|
|
||||||
jwa@1.4.1:
|
jwa@1.4.1:
|
||||||
resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
|
resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
|
||||||
|
|
||||||
@@ -5827,6 +5871,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
|
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
react-confetti-explosion@2.1.2:
|
||||||
|
resolution: {integrity: sha512-4UzDFBajAGXmF9TSJoRMO2QOBCIXc66idTxH8l7Mkul48HLGtk+tMzK9HYDYsy7Zmw5sEGchi2fbn4AJUuLrZw==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^18.x
|
||||||
|
react-dom: ^18.x
|
||||||
|
|
||||||
react-copy-to-clipboard@5.1.0:
|
react-copy-to-clipboard@5.1.0:
|
||||||
resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==}
|
resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -5837,6 +5887,9 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^15.3.0 || 16 || 17 || 18
|
react: ^15.3.0 || 16 || 17 || 18
|
||||||
|
|
||||||
|
react-display-name@0.2.5:
|
||||||
|
resolution: {integrity: sha512-I+vcaK9t4+kypiSgaiVWAipqHRXYmZIuAiS8vzFvXHHXVigg/sMKwlRgLy6LH2i3rmP+0Vzfl5lFsFRwF1r3pg==}
|
||||||
|
|
||||||
react-dom@18.2.0:
|
react-dom@18.2.0:
|
||||||
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
|
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -5884,6 +5937,11 @@ packages:
|
|||||||
react-is@18.3.1:
|
react-is@18.3.1:
|
||||||
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
|
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
|
||||||
|
|
||||||
|
react-jss@10.10.0:
|
||||||
|
resolution: {integrity: sha512-WLiq84UYWqNBF6579/uprcIUnM1TSywYq6AIjKTTTG5ziJl9Uy+pwuvpN3apuyVwflMbD60PraeTKT7uWH9XEQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8.6'
|
||||||
|
|
||||||
react-promise-suspense@0.3.4:
|
react-promise-suspense@0.3.4:
|
||||||
resolution: {integrity: sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==}
|
resolution: {integrity: sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==}
|
||||||
|
|
||||||
@@ -6040,9 +6098,6 @@ packages:
|
|||||||
reselect@5.1.1:
|
reselect@5.1.1:
|
||||||
resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==}
|
resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==}
|
||||||
|
|
||||||
resize-observer-polyfill@1.5.1:
|
|
||||||
resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
|
|
||||||
|
|
||||||
resolve-alpn@1.2.1:
|
resolve-alpn@1.2.1:
|
||||||
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
|
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
|
||||||
|
|
||||||
@@ -6162,6 +6217,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==}
|
resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
shallow-equal@1.2.1:
|
||||||
|
resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==}
|
||||||
|
|
||||||
sharp@0.33.5:
|
sharp@0.33.5:
|
||||||
resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==}
|
resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==}
|
||||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||||
@@ -6373,6 +6431,10 @@ packages:
|
|||||||
react: '>=16.8.0 <19'
|
react: '>=16.8.0 <19'
|
||||||
react-dom: '>=16.8.0 <19'
|
react-dom: '>=16.8.0 <19'
|
||||||
|
|
||||||
|
symbol-observable@1.2.0:
|
||||||
|
resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
tailwind-merge@2.4.0:
|
tailwind-merge@2.4.0:
|
||||||
resolution: {integrity: sha512-49AwoOQNKdqKPd9CViyH5wJoSKsCDjUlzL8DxuGp3P1FsGY36NJDAa18jLZcaHAUUuTj+JB8IAo8zWgBNvBF7A==}
|
resolution: {integrity: sha512-49AwoOQNKdqKPd9CViyH5wJoSKsCDjUlzL8DxuGp3P1FsGY36NJDAa18jLZcaHAUUuTj+JB8IAo8zWgBNvBF7A==}
|
||||||
|
|
||||||
@@ -6426,6 +6488,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==}
|
resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
theming@3.3.0:
|
||||||
|
resolution: {integrity: sha512-u6l4qTJRDaWZsqa8JugaNt7Xd8PPl9+gonZaIe28vAhqgHMIG/DOyFPqiKN/gQLQYj05tHv+YQdNILL4zoiAVA==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.3'
|
||||||
|
|
||||||
thenify-all@1.6.0:
|
thenify-all@1.6.0:
|
||||||
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
|
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
|
||||||
engines: {node: '>=0.8'}
|
engines: {node: '>=0.8'}
|
||||||
@@ -6452,6 +6520,9 @@ packages:
|
|||||||
tiny-invariant@1.3.3:
|
tiny-invariant@1.3.3:
|
||||||
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
|
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
|
||||||
|
|
||||||
|
tiny-warning@1.0.3:
|
||||||
|
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
||||||
|
|
||||||
tinybench@2.8.0:
|
tinybench@2.8.0:
|
||||||
resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==}
|
resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==}
|
||||||
|
|
||||||
@@ -7146,6 +7217,12 @@ snapshots:
|
|||||||
tslib: 2.6.3
|
tslib: 2.6.3
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@emotion/is-prop-valid@0.7.3':
|
||||||
|
dependencies:
|
||||||
|
'@emotion/memoize': 0.7.1
|
||||||
|
|
||||||
|
'@emotion/memoize@0.7.1': {}
|
||||||
|
|
||||||
'@esbuild-kit/core-utils@3.3.2':
|
'@esbuild-kit/core-utils@3.3.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.18.20
|
esbuild: 0.18.20
|
||||||
@@ -8859,29 +8936,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
|
|
||||||
'@reactour/mask@1.1.0(react@18.2.0)':
|
|
||||||
dependencies:
|
|
||||||
'@reactour/utils': 0.5.0(react@18.2.0)
|
|
||||||
react: 18.2.0
|
|
||||||
|
|
||||||
'@reactour/popover@1.2.0(react@18.2.0)':
|
|
||||||
dependencies:
|
|
||||||
'@reactour/utils': 0.5.0(react@18.2.0)
|
|
||||||
react: 18.2.0
|
|
||||||
|
|
||||||
'@reactour/tour@3.7.0(react@18.2.0)':
|
|
||||||
dependencies:
|
|
||||||
'@reactour/mask': 1.1.0(react@18.2.0)
|
|
||||||
'@reactour/popover': 1.2.0(react@18.2.0)
|
|
||||||
'@reactour/utils': 0.5.0(react@18.2.0)
|
|
||||||
react: 18.2.0
|
|
||||||
|
|
||||||
'@reactour/utils@0.5.0(react@18.2.0)':
|
|
||||||
dependencies:
|
|
||||||
'@rooks/use-mutation-observer': 4.11.2(react@18.2.0)
|
|
||||||
react: 18.2.0
|
|
||||||
resize-observer-polyfill: 1.5.1
|
|
||||||
|
|
||||||
'@redis/bloom@1.2.0(@redis/client@1.6.0)':
|
'@redis/bloom@1.2.0(@redis/client@1.6.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@redis/client': 1.6.0
|
'@redis/client': 1.6.0
|
||||||
@@ -8956,10 +9010,6 @@ snapshots:
|
|||||||
'@rollup/rollup-win32-x64-msvc@4.19.1':
|
'@rollup/rollup-win32-x64-msvc@4.19.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@rooks/use-mutation-observer@4.11.2(react@18.2.0)':
|
|
||||||
dependencies:
|
|
||||||
react: 18.2.0
|
|
||||||
|
|
||||||
'@selderee/plugin-htmlparser2@0.11.0':
|
'@selderee/plugin-htmlparser2@0.11.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
domhandler: 5.0.3
|
domhandler: 5.0.3
|
||||||
@@ -8971,6 +9021,11 @@ snapshots:
|
|||||||
|
|
||||||
'@sindresorhus/merge-streams@2.3.0': {}
|
'@sindresorhus/merge-streams@2.3.0': {}
|
||||||
|
|
||||||
|
'@stepperize/react@4.0.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||||
|
dependencies:
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
|
||||||
'@stripe/stripe-js@4.8.0': {}
|
'@stripe/stripe-js@4.8.0': {}
|
||||||
|
|
||||||
'@swagger-api/apidom-ast@1.0.0-alpha.9':
|
'@swagger-api/apidom-ast@1.0.0-alpha.9':
|
||||||
@@ -10270,6 +10325,17 @@ snapshots:
|
|||||||
|
|
||||||
crossws@0.2.4: {}
|
crossws@0.2.4: {}
|
||||||
|
|
||||||
|
css-jss@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
jss-preset-default: 10.10.0
|
||||||
|
|
||||||
|
css-vendor@2.0.8:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
is-in-browser: 1.1.3
|
||||||
|
|
||||||
css.escape@1.5.1: {}
|
css.escape@1.5.1: {}
|
||||||
|
|
||||||
cssesc@3.0.0: {}
|
cssesc@3.0.0: {}
|
||||||
@@ -11049,6 +11115,8 @@ snapshots:
|
|||||||
|
|
||||||
hyperdyperid@1.2.0: {}
|
hyperdyperid@1.2.0: {}
|
||||||
|
|
||||||
|
hyphenate-style-name@1.1.0: {}
|
||||||
|
|
||||||
i18next-fs-backend@2.3.2: {}
|
i18next-fs-backend@2.3.2: {}
|
||||||
|
|
||||||
i18next@23.16.5:
|
i18next@23.16.5:
|
||||||
@@ -11156,6 +11224,8 @@ snapshots:
|
|||||||
|
|
||||||
is-hexadecimal@1.0.4: {}
|
is-hexadecimal@1.0.4: {}
|
||||||
|
|
||||||
|
is-in-browser@1.1.3: {}
|
||||||
|
|
||||||
is-ip@4.0.0:
|
is-ip@4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ip-regex: 5.0.0
|
ip-regex: 5.0.0
|
||||||
@@ -11241,6 +11311,98 @@ snapshots:
|
|||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
semver: 7.6.2
|
semver: 7.6.2
|
||||||
|
|
||||||
|
jss-plugin-camel-case@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
hyphenate-style-name: 1.1.0
|
||||||
|
jss: 10.10.0
|
||||||
|
|
||||||
|
jss-plugin-compose@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
tiny-warning: 1.0.3
|
||||||
|
|
||||||
|
jss-plugin-default-unit@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
|
||||||
|
jss-plugin-expand@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
|
||||||
|
jss-plugin-extend@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
tiny-warning: 1.0.3
|
||||||
|
|
||||||
|
jss-plugin-global@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
|
||||||
|
jss-plugin-nested@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
tiny-warning: 1.0.3
|
||||||
|
|
||||||
|
jss-plugin-props-sort@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
|
||||||
|
jss-plugin-rule-value-function@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
tiny-warning: 1.0.3
|
||||||
|
|
||||||
|
jss-plugin-rule-value-observable@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
symbol-observable: 1.2.0
|
||||||
|
|
||||||
|
jss-plugin-template@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
tiny-warning: 1.0.3
|
||||||
|
|
||||||
|
jss-plugin-vendor-prefixer@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
css-vendor: 2.0.8
|
||||||
|
jss: 10.10.0
|
||||||
|
|
||||||
|
jss-preset-default@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
jss: 10.10.0
|
||||||
|
jss-plugin-camel-case: 10.10.0
|
||||||
|
jss-plugin-compose: 10.10.0
|
||||||
|
jss-plugin-default-unit: 10.10.0
|
||||||
|
jss-plugin-expand: 10.10.0
|
||||||
|
jss-plugin-extend: 10.10.0
|
||||||
|
jss-plugin-global: 10.10.0
|
||||||
|
jss-plugin-nested: 10.10.0
|
||||||
|
jss-plugin-props-sort: 10.10.0
|
||||||
|
jss-plugin-rule-value-function: 10.10.0
|
||||||
|
jss-plugin-rule-value-observable: 10.10.0
|
||||||
|
jss-plugin-template: 10.10.0
|
||||||
|
jss-plugin-vendor-prefixer: 10.10.0
|
||||||
|
|
||||||
|
jss@10.10.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
csstype: 3.1.3
|
||||||
|
is-in-browser: 1.1.3
|
||||||
|
tiny-warning: 1.0.3
|
||||||
|
|
||||||
jwa@1.4.1:
|
jwa@1.4.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
buffer-equal-constant-time: 1.0.1
|
buffer-equal-constant-time: 1.0.1
|
||||||
@@ -12077,6 +12239,13 @@ snapshots:
|
|||||||
strip-json-comments: 2.0.1
|
strip-json-comments: 2.0.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
react-confetti-explosion@2.1.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
|
||||||
|
dependencies:
|
||||||
|
lodash: 4.17.21
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
react-jss: 10.10.0(react@18.2.0)
|
||||||
|
|
||||||
react-copy-to-clipboard@5.1.0(react@18.2.0):
|
react-copy-to-clipboard@5.1.0(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
copy-to-clipboard: 3.3.3
|
copy-to-clipboard: 3.3.3
|
||||||
@@ -12089,6 +12258,8 @@ snapshots:
|
|||||||
prop-types: 15.8.1
|
prop-types: 15.8.1
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
|
|
||||||
|
react-display-name@0.2.5: {}
|
||||||
|
|
||||||
react-dom@18.2.0(react@18.2.0):
|
react-dom@18.2.0(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
@@ -12127,6 +12298,21 @@ snapshots:
|
|||||||
|
|
||||||
react-is@18.3.1: {}
|
react-is@18.3.1: {}
|
||||||
|
|
||||||
|
react-jss@10.10.0(react@18.2.0):
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.25.0
|
||||||
|
'@emotion/is-prop-valid': 0.7.3
|
||||||
|
css-jss: 10.10.0
|
||||||
|
hoist-non-react-statics: 3.3.2
|
||||||
|
is-in-browser: 1.1.3
|
||||||
|
jss: 10.10.0
|
||||||
|
jss-preset-default: 10.10.0
|
||||||
|
prop-types: 15.8.1
|
||||||
|
react: 18.2.0
|
||||||
|
shallow-equal: 1.2.1
|
||||||
|
theming: 3.3.0(react@18.2.0)
|
||||||
|
tiny-warning: 1.0.3
|
||||||
|
|
||||||
react-promise-suspense@0.3.4:
|
react-promise-suspense@0.3.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
fast-deep-equal: 2.0.1
|
fast-deep-equal: 2.0.1
|
||||||
@@ -12296,8 +12482,6 @@ snapshots:
|
|||||||
|
|
||||||
reselect@5.1.1: {}
|
reselect@5.1.1: {}
|
||||||
|
|
||||||
resize-observer-polyfill@1.5.1: {}
|
|
||||||
|
|
||||||
resolve-alpn@1.2.1: {}
|
resolve-alpn@1.2.1: {}
|
||||||
|
|
||||||
resolve-from@4.0.0: {}
|
resolve-from@4.0.0: {}
|
||||||
@@ -12423,6 +12607,8 @@ snapshots:
|
|||||||
inherits: 2.0.4
|
inherits: 2.0.4
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
|
shallow-equal@1.2.1: {}
|
||||||
|
|
||||||
sharp@0.33.5:
|
sharp@0.33.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
color: 4.2.3
|
color: 4.2.3
|
||||||
@@ -12692,6 +12878,8 @@ snapshots:
|
|||||||
- '@types/react'
|
- '@types/react'
|
||||||
- debug
|
- debug
|
||||||
|
|
||||||
|
symbol-observable@1.2.0: {}
|
||||||
|
|
||||||
tailwind-merge@2.4.0: {}
|
tailwind-merge@2.4.0: {}
|
||||||
|
|
||||||
tailwindcss-animate@1.0.7(tailwindcss@3.4.7):
|
tailwindcss-animate@1.0.7(tailwindcss@3.4.7):
|
||||||
@@ -12771,6 +12959,14 @@ snapshots:
|
|||||||
|
|
||||||
text-extensions@2.4.0: {}
|
text-extensions@2.4.0: {}
|
||||||
|
|
||||||
|
theming@3.3.0(react@18.2.0):
|
||||||
|
dependencies:
|
||||||
|
hoist-non-react-statics: 3.3.2
|
||||||
|
prop-types: 15.8.1
|
||||||
|
react: 18.2.0
|
||||||
|
react-display-name: 0.2.5
|
||||||
|
tiny-warning: 1.0.3
|
||||||
|
|
||||||
thenify-all@1.6.0:
|
thenify-all@1.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
thenify: 3.3.1
|
thenify: 3.3.1
|
||||||
@@ -12796,6 +12992,8 @@ snapshots:
|
|||||||
|
|
||||||
tiny-invariant@1.3.3: {}
|
tiny-invariant@1.3.3: {}
|
||||||
|
|
||||||
|
tiny-warning@1.0.3: {}
|
||||||
|
|
||||||
tinybench@2.8.0: {}
|
tinybench@2.8.0: {}
|
||||||
|
|
||||||
tinypool@0.8.4: {}
|
tinypool@0.8.4: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user