mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
Merge pull request #2244 from jhon2c/feat/improve-server-ux
feat(ux): Improve UX Based on Community Feedback
This commit is contained in:
@@ -1,3 +1,9 @@
|
|||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { Folder, HelpCircle } from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { z } from "zod";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
@@ -37,12 +43,6 @@ import {
|
|||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { slugify } from "@/lib/slug";
|
import { slugify } from "@/lib/slug";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import { Folder, HelpCircle } from "lucide-react";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
const AddTemplateSchema = z.object({
|
const AddTemplateSchema = z.object({
|
||||||
name: z.string().min(1, {
|
name: z.string().min(1, {
|
||||||
@@ -75,6 +75,8 @@ export const AddApplication = ({ projectId, projectName }: Props) => {
|
|||||||
const slug = slugify(projectName);
|
const slug = slugify(projectName);
|
||||||
const { data: servers } = api.server.withSSHKey.useQuery();
|
const { data: servers } = api.server.withSSHKey.useQuery();
|
||||||
|
|
||||||
|
const hasServers = servers && servers.length > 0;
|
||||||
|
|
||||||
const { mutateAsync, isLoading, error, isError } =
|
const { mutateAsync, isLoading, error, isError } =
|
||||||
api.application.create.useMutation();
|
api.application.create.useMutation();
|
||||||
|
|
||||||
@@ -155,62 +157,64 @@ export const AddApplication = ({ projectId, projectName }: Props) => {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<FormField
|
{hasServers && (
|
||||||
control={form.control}
|
<FormField
|
||||||
name="serverId"
|
control={form.control}
|
||||||
render={({ field }) => (
|
name="serverId"
|
||||||
<FormItem>
|
render={({ field }) => (
|
||||||
<TooltipProvider delayDuration={0}>
|
<FormItem>
|
||||||
<Tooltip>
|
<TooltipProvider delayDuration={0}>
|
||||||
<TooltipTrigger asChild>
|
<Tooltip>
|
||||||
<FormLabel className="break-all w-fit flex flex-row gap-1 items-center">
|
<TooltipTrigger asChild>
|
||||||
Select a Server {!isCloud ? "(Optional)" : ""}
|
<FormLabel className="break-all w-fit flex flex-row gap-1 items-center">
|
||||||
<HelpCircle className="size-4 text-muted-foreground" />
|
Select a Server {!isCloud ? "(Optional)" : ""}
|
||||||
</FormLabel>
|
<HelpCircle className="size-4 text-muted-foreground" />
|
||||||
</TooltipTrigger>
|
</FormLabel>
|
||||||
<TooltipContent
|
</TooltipTrigger>
|
||||||
className="z-[999] w-[300px]"
|
<TooltipContent
|
||||||
align="start"
|
className="z-[999] w-[300px]"
|
||||||
side="top"
|
align="start"
|
||||||
>
|
side="top"
|
||||||
<span>
|
>
|
||||||
If no server is selected, the application will be
|
<span>
|
||||||
deployed on the server where the user is logged in.
|
If no server is selected, the application will be
|
||||||
</span>
|
deployed on the server where the user is logged in.
|
||||||
</TooltipContent>
|
</span>
|
||||||
</Tooltip>
|
</TooltipContent>
|
||||||
</TooltipProvider>
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
onValueChange={field.onChange}
|
onValueChange={field.onChange}
|
||||||
defaultValue={field.value}
|
defaultValue={field.value}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Select a Server" />
|
<SelectValue placeholder="Select a Server" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
{servers?.map((server) => (
|
{servers?.map((server) => (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
key={server.serverId}
|
key={server.serverId}
|
||||||
value={server.serverId}
|
value={server.serverId}
|
||||||
>
|
>
|
||||||
<span className="flex items-center gap-2 justify-between w-full">
|
<span className="flex items-center gap-2 justify-between w-full">
|
||||||
<span>{server.name}</span>
|
<span>{server.name}</span>
|
||||||
<span className="text-muted-foreground text-xs self-center">
|
<span className="text-muted-foreground text-xs self-center">
|
||||||
{server.ipAddress}
|
{server.ipAddress}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</SelectItem>
|
||||||
</SelectItem>
|
))}
|
||||||
))}
|
<SelectLabel>Servers ({servers?.length})</SelectLabel>
|
||||||
<SelectLabel>Servers ({servers?.length})</SelectLabel>
|
</SelectGroup>
|
||||||
</SelectGroup>
|
</SelectContent>
|
||||||
</SelectContent>
|
</Select>
|
||||||
</Select>
|
<FormMessage />
|
||||||
<FormMessage />
|
</FormItem>
|
||||||
</FormItem>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
)}
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="appName"
|
name="appName"
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { CircuitBoard, HelpCircle } from "lucide-react";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { z } from "zod";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
@@ -37,12 +43,6 @@ import {
|
|||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { slugify } from "@/lib/slug";
|
import { slugify } from "@/lib/slug";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import { CircuitBoard, HelpCircle } from "lucide-react";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
const AddComposeSchema = z.object({
|
const AddComposeSchema = z.object({
|
||||||
composeType: z.enum(["docker-compose", "stack"]).optional(),
|
composeType: z.enum(["docker-compose", "stack"]).optional(),
|
||||||
@@ -78,6 +78,8 @@ export const AddCompose = ({ projectId, projectName }: Props) => {
|
|||||||
const { mutateAsync, isLoading, error, isError } =
|
const { mutateAsync, isLoading, error, isError } =
|
||||||
api.compose.create.useMutation();
|
api.compose.create.useMutation();
|
||||||
|
|
||||||
|
const hasServers = servers && servers.length > 0;
|
||||||
|
|
||||||
const form = useForm<AddCompose>({
|
const form = useForm<AddCompose>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
name: "",
|
name: "",
|
||||||
@@ -163,62 +165,64 @@ export const AddCompose = ({ projectId, projectName }: Props) => {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<FormField
|
{hasServers && (
|
||||||
control={form.control}
|
<FormField
|
||||||
name="serverId"
|
control={form.control}
|
||||||
render={({ field }) => (
|
name="serverId"
|
||||||
<FormItem>
|
render={({ field }) => (
|
||||||
<TooltipProvider delayDuration={0}>
|
<FormItem>
|
||||||
<Tooltip>
|
<TooltipProvider delayDuration={0}>
|
||||||
<TooltipTrigger asChild>
|
<Tooltip>
|
||||||
<FormLabel className="break-all w-fit flex flex-row gap-1 items-center">
|
<TooltipTrigger asChild>
|
||||||
Select a Server {!isCloud ? "(Optional)" : ""}
|
<FormLabel className="break-all w-fit flex flex-row gap-1 items-center">
|
||||||
<HelpCircle className="size-4 text-muted-foreground" />
|
Select a Server {!isCloud ? "(Optional)" : ""}
|
||||||
</FormLabel>
|
<HelpCircle className="size-4 text-muted-foreground" />
|
||||||
</TooltipTrigger>
|
</FormLabel>
|
||||||
<TooltipContent
|
</TooltipTrigger>
|
||||||
className="z-[999] w-[300px]"
|
<TooltipContent
|
||||||
align="start"
|
className="z-[999] w-[300px]"
|
||||||
side="top"
|
align="start"
|
||||||
>
|
side="top"
|
||||||
<span>
|
>
|
||||||
If no server is selected, the application will be
|
<span>
|
||||||
deployed on the server where the user is logged in.
|
If no server is selected, the application will be
|
||||||
</span>
|
deployed on the server where the user is logged in.
|
||||||
</TooltipContent>
|
</span>
|
||||||
</Tooltip>
|
</TooltipContent>
|
||||||
</TooltipProvider>
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
onValueChange={field.onChange}
|
onValueChange={field.onChange}
|
||||||
defaultValue={field.value}
|
defaultValue={field.value}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Select a Server" />
|
<SelectValue placeholder="Select a Server" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
{servers?.map((server) => (
|
{servers?.map((server) => (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
key={server.serverId}
|
key={server.serverId}
|
||||||
value={server.serverId}
|
value={server.serverId}
|
||||||
>
|
>
|
||||||
<span className="flex items-center gap-2 justify-between w-full">
|
<span className="flex items-center gap-2 justify-between w-full">
|
||||||
<span>{server.name}</span>
|
<span>{server.name}</span>
|
||||||
<span className="text-muted-foreground text-xs self-center">
|
<span className="text-muted-foreground text-xs self-center">
|
||||||
{server.ipAddress}
|
{server.ipAddress}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</SelectItem>
|
||||||
</SelectItem>
|
))}
|
||||||
))}
|
<SelectLabel>Servers ({servers?.length})</SelectLabel>
|
||||||
<SelectLabel>Servers ({servers?.length})</SelectLabel>
|
</SelectGroup>
|
||||||
</SelectGroup>
|
</SelectContent>
|
||||||
</SelectContent>
|
</Select>
|
||||||
</Select>
|
<FormMessage />
|
||||||
<FormMessage />
|
</FormItem>
|
||||||
</FormItem>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
)}
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="appName"
|
name="appName"
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { AlertTriangle, Database } from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { z } from "zod";
|
||||||
import {
|
import {
|
||||||
MariadbIcon,
|
MariadbIcon,
|
||||||
MongodbIcon,
|
MongodbIcon,
|
||||||
@@ -39,12 +45,6 @@ import { Switch } from "@/components/ui/switch";
|
|||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { slugify } from "@/lib/slug";
|
import { slugify } from "@/lib/slug";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import { AlertTriangle, Database } from "lucide-react";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
type DbType = typeof mySchema._type.type;
|
type DbType = typeof mySchema._type.type;
|
||||||
|
|
||||||
@@ -163,6 +163,8 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
|
|||||||
const mariadbMutation = api.mariadb.create.useMutation();
|
const mariadbMutation = api.mariadb.create.useMutation();
|
||||||
const mysqlMutation = api.mysql.create.useMutation();
|
const mysqlMutation = api.mysql.create.useMutation();
|
||||||
|
|
||||||
|
const hasServers = servers && servers.length > 0;
|
||||||
|
|
||||||
const form = useForm<AddDatabase>({
|
const form = useForm<AddDatabase>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
type: "postgres",
|
type: "postgres",
|
||||||
@@ -374,39 +376,41 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<FormField
|
{hasServers && (
|
||||||
control={form.control}
|
<FormField
|
||||||
name="serverId"
|
control={form.control}
|
||||||
render={({ field }) => (
|
name="serverId"
|
||||||
<FormItem>
|
render={({ field }) => (
|
||||||
<FormLabel>Select a Server</FormLabel>
|
<FormItem>
|
||||||
<Select
|
<FormLabel>Select a Server</FormLabel>
|
||||||
onValueChange={field.onChange}
|
<Select
|
||||||
defaultValue={field.value || ""}
|
onValueChange={field.onChange}
|
||||||
>
|
defaultValue={field.value || ""}
|
||||||
<SelectTrigger>
|
>
|
||||||
<SelectValue placeholder="Select a Server" />
|
<SelectTrigger>
|
||||||
</SelectTrigger>
|
<SelectValue placeholder="Select a Server" />
|
||||||
<SelectContent>
|
</SelectTrigger>
|
||||||
<SelectGroup>
|
<SelectContent>
|
||||||
{servers?.map((server) => (
|
<SelectGroup>
|
||||||
<SelectItem
|
{servers?.map((server) => (
|
||||||
key={server.serverId}
|
<SelectItem
|
||||||
value={server.serverId}
|
key={server.serverId}
|
||||||
>
|
value={server.serverId}
|
||||||
{server.name}
|
>
|
||||||
</SelectItem>
|
{server.name}
|
||||||
))}
|
</SelectItem>
|
||||||
<SelectLabel>
|
))}
|
||||||
Servers ({servers?.length})
|
<SelectLabel>
|
||||||
</SelectLabel>
|
Servers ({servers?.length})
|
||||||
</SelectGroup>
|
</SelectLabel>
|
||||||
</SelectContent>
|
</SelectGroup>
|
||||||
</Select>
|
</SelectContent>
|
||||||
<FormMessage />
|
</Select>
|
||||||
</FormItem>
|
<FormMessage />
|
||||||
)}
|
</FormItem>
|
||||||
/>
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="appName"
|
name="appName"
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
import {
|
||||||
|
BookText,
|
||||||
|
CheckIcon,
|
||||||
|
ChevronsUpDown,
|
||||||
|
Globe,
|
||||||
|
HelpCircle,
|
||||||
|
LayoutGrid,
|
||||||
|
List,
|
||||||
|
Loader2,
|
||||||
|
PuzzleIcon,
|
||||||
|
SearchIcon,
|
||||||
|
} from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { GithubIcon } from "@/components/icons/data-tools-icons";
|
import { GithubIcon } from "@/components/icons/data-tools-icons";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import {
|
import {
|
||||||
@@ -54,21 +69,6 @@ import {
|
|||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import {
|
|
||||||
BookText,
|
|
||||||
CheckIcon,
|
|
||||||
ChevronsUpDown,
|
|
||||||
Globe,
|
|
||||||
HelpCircle,
|
|
||||||
LayoutGrid,
|
|
||||||
List,
|
|
||||||
Loader2,
|
|
||||||
PuzzleIcon,
|
|
||||||
SearchIcon,
|
|
||||||
} from "lucide-react";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
|
|
||||||
const TEMPLATE_BASE_URL_KEY = "dokploy_template_base_url";
|
const TEMPLATE_BASE_URL_KEY = "dokploy_template_base_url";
|
||||||
|
|
||||||
@@ -137,6 +137,8 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
|
|||||||
return matchesTags && matchesQuery;
|
return matchesTags && matchesQuery;
|
||||||
}) || [];
|
}) || [];
|
||||||
|
|
||||||
|
const hasServers = servers && servers.length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
<DialogTrigger className="w-full">
|
<DialogTrigger className="w-full">
|
||||||
@@ -425,60 +427,62 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
|
|||||||
project.
|
project.
|
||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
|
|
||||||
<div>
|
{hasServers && (
|
||||||
<TooltipProvider delayDuration={0}>
|
<div>
|
||||||
<Tooltip>
|
<TooltipProvider delayDuration={0}>
|
||||||
<TooltipTrigger asChild>
|
<Tooltip>
|
||||||
<Label className="break-all w-fit flex flex-row gap-1 items-center pb-2 pt-3.5">
|
<TooltipTrigger asChild>
|
||||||
Select a Server{" "}
|
<Label className="break-all w-fit flex flex-row gap-1 items-center pb-2 pt-3.5">
|
||||||
{!isCloud ? "(Optional)" : ""}
|
Select a Server{" "}
|
||||||
<HelpCircle className="size-4 text-muted-foreground" />
|
{!isCloud ? "(Optional)" : ""}
|
||||||
</Label>
|
<HelpCircle className="size-4 text-muted-foreground" />
|
||||||
</TooltipTrigger>
|
</Label>
|
||||||
<TooltipContent
|
</TooltipTrigger>
|
||||||
className="z-[999] w-[300px]"
|
<TooltipContent
|
||||||
align="start"
|
className="z-[999] w-[300px]"
|
||||||
side="top"
|
align="start"
|
||||||
>
|
side="top"
|
||||||
<span>
|
>
|
||||||
If no server is selected, the application
|
<span>
|
||||||
will be deployed on the server where the
|
If no server is selected, the
|
||||||
user is logged in.
|
application will be deployed on the
|
||||||
</span>
|
server where the user is logged in.
|
||||||
</TooltipContent>
|
</span>
|
||||||
</Tooltip>
|
</TooltipContent>
|
||||||
</TooltipProvider>
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
onValueChange={(e) => {
|
onValueChange={(e) => {
|
||||||
setServerId(e);
|
setServerId(e);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Select a Server" />
|
<SelectValue placeholder="Select a Server" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
{servers?.map((server) => (
|
{servers?.map((server) => (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
key={server.serverId}
|
key={server.serverId}
|
||||||
value={server.serverId}
|
value={server.serverId}
|
||||||
>
|
>
|
||||||
<span className="flex items-center gap-2 justify-between w-full">
|
<span className="flex items-center gap-2 justify-between w-full">
|
||||||
<span>{server.name}</span>
|
<span>{server.name}</span>
|
||||||
<span className="text-muted-foreground text-xs self-center">
|
<span className="text-muted-foreground text-xs self-center">
|
||||||
{server.ipAddress}
|
{server.ipAddress}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</SelectItem>
|
||||||
</SelectItem>
|
))}
|
||||||
))}
|
<SelectLabel>
|
||||||
<SelectLabel>
|
Servers ({servers?.length})
|
||||||
Servers ({servers?.length})
|
</SelectLabel>
|
||||||
</SelectLabel>
|
</SelectGroup>
|
||||||
</SelectGroup>
|
</SelectContent>
|
||||||
</SelectContent>
|
</Select>
|
||||||
</Select>
|
</div>
|
||||||
</div>
|
)}
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const examples = [
|
|||||||
export const StepOne = ({ setTemplateInfo, templateInfo }: any) => {
|
export const StepOne = ({ setTemplateInfo, templateInfo }: any) => {
|
||||||
// Get servers from the API
|
// Get servers from the API
|
||||||
const { data: servers } = api.server.withSSHKey.useQuery();
|
const { data: servers } = api.server.withSSHKey.useQuery();
|
||||||
|
const hasServers = servers && servers.length > 0;
|
||||||
|
|
||||||
const handleExampleClick = (example: string) => {
|
const handleExampleClick = (example: string) => {
|
||||||
setTemplateInfo({ ...templateInfo, userInput: example });
|
setTemplateInfo({ ...templateInfo, userInput: example });
|
||||||
@@ -47,37 +48,39 @@ export const StepOne = ({ setTemplateInfo, templateInfo }: any) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
{hasServers && (
|
||||||
<Label htmlFor="server-deploy">
|
<div className="space-y-2">
|
||||||
Select the server where you want to deploy (optional)
|
<Label htmlFor="server-deploy">
|
||||||
</Label>
|
Select the server where you want to deploy (optional)
|
||||||
<Select
|
</Label>
|
||||||
value={templateInfo.server?.serverId}
|
<Select
|
||||||
onValueChange={(value) => {
|
value={templateInfo.server?.serverId}
|
||||||
const server = servers?.find((s) => s.serverId === value);
|
onValueChange={(value) => {
|
||||||
if (server) {
|
const server = servers?.find((s) => s.serverId === value);
|
||||||
setTemplateInfo({
|
if (server) {
|
||||||
...templateInfo,
|
setTemplateInfo({
|
||||||
server: server,
|
...templateInfo,
|
||||||
});
|
server: server,
|
||||||
}
|
});
|
||||||
}}
|
}
|
||||||
>
|
}}
|
||||||
<SelectTrigger className="w-full">
|
>
|
||||||
<SelectValue placeholder="Select a server" />
|
<SelectTrigger className="w-full">
|
||||||
</SelectTrigger>
|
<SelectValue placeholder="Select a server" />
|
||||||
<SelectContent>
|
</SelectTrigger>
|
||||||
<SelectGroup>
|
<SelectContent>
|
||||||
{servers?.map((server) => (
|
<SelectGroup>
|
||||||
<SelectItem key={server.serverId} value={server.serverId}>
|
{servers?.map((server) => (
|
||||||
{server.name}
|
<SelectItem key={server.serverId} value={server.serverId}>
|
||||||
</SelectItem>
|
{server.name}
|
||||||
))}
|
</SelectItem>
|
||||||
<SelectLabel>Servers ({servers?.length})</SelectLabel>
|
))}
|
||||||
</SelectGroup>
|
<SelectLabel>Servers ({servers?.length})</SelectLabel>
|
||||||
</SelectContent>
|
</SelectGroup>
|
||||||
</Select>
|
</SelectContent>
|
||||||
</div>
|
</Select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Examples:</Label>
|
<Label>Examples:</Label>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import { AddGithubProvider } from "./github/add-github-provider";
|
|||||||
import { EditGithubProvider } from "./github/edit-github-provider";
|
import { EditGithubProvider } from "./github/edit-github-provider";
|
||||||
import { AddGitlabProvider } from "./gitlab/add-gitlab-provider";
|
import { AddGitlabProvider } from "./gitlab/add-gitlab-provider";
|
||||||
import { EditGitlabProvider } from "./gitlab/edit-gitlab-provider";
|
import { EditGitlabProvider } from "./gitlab/edit-gitlab-provider";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
|
||||||
export const ShowGitProviders = () => {
|
export const ShowGitProviders = () => {
|
||||||
const { data, isLoading, refetch } = api.gitProvider.getAll.useQuery();
|
const { data, isLoading, refetch } = api.gitProvider.getAll.useQuery();
|
||||||
@@ -158,7 +159,13 @@ export const ShowGitProviders = () => {
|
|||||||
|
|
||||||
<div className="flex flex-row gap-1">
|
<div className="flex flex-row gap-1">
|
||||||
{!haveGithubRequirements && isGithub && (
|
{!haveGithubRequirements && isGithub && (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-row gap-1 items-center">
|
||||||
|
<Badge
|
||||||
|
variant="outline"
|
||||||
|
className="text-xs"
|
||||||
|
>
|
||||||
|
Action Required
|
||||||
|
</Badge>
|
||||||
<Link
|
<Link
|
||||||
href={`${gitProvider?.github?.githubAppName}/installations/new?state=gh_setup:${gitProvider?.github.githubId}`}
|
href={`${gitProvider?.github?.githubAppName}/installations/new?state=gh_setup:${gitProvider?.github.githubId}`}
|
||||||
className={buttonVariants({
|
className={buttonVariants({
|
||||||
@@ -185,7 +192,13 @@ export const ShowGitProviders = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!haveGitlabRequirements && isGitlab && (
|
{!haveGitlabRequirements && isGitlab && (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-row gap-1 items-center">
|
||||||
|
<Badge
|
||||||
|
variant="outline"
|
||||||
|
className="text-xs"
|
||||||
|
>
|
||||||
|
Action Required
|
||||||
|
</Badge>
|
||||||
<Link
|
<Link
|
||||||
href={getGitlabUrl(
|
href={getGitlabUrl(
|
||||||
gitProvider.gitlab?.applicationId || "",
|
gitProvider.gitlab?.applicationId || "",
|
||||||
|
|||||||
Reference in New Issue
Block a user