mirror of
https://github.com/fosrl/pangolin.git
synced 2025-08-29 22:19:31 +02:00
add copy code snippets to raw tcp/udp
This commit is contained in:
parent
f40d91ff9e
commit
844b12d363
3 changed files with 320 additions and 232 deletions
|
@ -60,7 +60,6 @@ const configSchema = z.object({
|
||||||
.transform(stoi)
|
.transform(stoi)
|
||||||
.pipe(portSchema),
|
.pipe(portSchema),
|
||||||
internal_hostname: z.string().transform((url) => url.toLowerCase()),
|
internal_hostname: z.string().transform((url) => url.toLowerCase()),
|
||||||
secure_cookies: z.boolean(),
|
|
||||||
session_cookie_name: z.string(),
|
session_cookie_name: z.string(),
|
||||||
resource_access_token_param: z.string(),
|
resource_access_token_param: z.string(),
|
||||||
resource_session_request_param: z.string(),
|
resource_session_request_param: z.string(),
|
||||||
|
|
|
@ -62,6 +62,7 @@ import {
|
||||||
import { subdomainSchema } from "@server/schemas/subdomainSchema";
|
import { subdomainSchema } from "@server/schemas/subdomainSchema";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { SquareArrowOutUpRight } from "lucide-react";
|
import { SquareArrowOutUpRight } from "lucide-react";
|
||||||
|
import CopyTextBox from "@app/components/CopyTextBox";
|
||||||
|
|
||||||
const createResourceFormSchema = z
|
const createResourceFormSchema = z
|
||||||
.object({
|
.object({
|
||||||
|
@ -129,6 +130,10 @@ export default function CreateResourceForm({
|
||||||
const [sites, setSites] = useState<ListSitesResponse["sites"]>([]);
|
const [sites, setSites] = useState<ListSitesResponse["sites"]>([]);
|
||||||
const [domainSuffix, setDomainSuffix] = useState<string>(org.org.domain);
|
const [domainSuffix, setDomainSuffix] = useState<string>(org.org.domain);
|
||||||
|
|
||||||
|
const [showSnippets, setShowSnippets] = useState(false);
|
||||||
|
|
||||||
|
const [resourceId, setResourceId] = useState<number | null>(null);
|
||||||
|
|
||||||
const form = useForm<CreateResourceFormValues>({
|
const form = useForm<CreateResourceFormValues>({
|
||||||
resolver: zodResolver(createResourceFormSchema),
|
resolver: zodResolver(createResourceFormSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
|
@ -186,11 +191,21 @@ export default function CreateResourceForm({
|
||||||
|
|
||||||
if (res && res.status === 201) {
|
if (res && res.status === 201) {
|
||||||
const id = res.data.data.resourceId;
|
const id = res.data.data.resourceId;
|
||||||
// navigate to the resource page
|
setResourceId(id);
|
||||||
router.push(`/${orgId}/settings/resources/${id}`);
|
|
||||||
|
if (data.http) {
|
||||||
|
goToResource();
|
||||||
|
} else {
|
||||||
|
setShowSnippets(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goToResource() {
|
||||||
|
// navigate to the resource page
|
||||||
|
router.push(`/${orgId}/settings/resources/${resourceId}`);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Credenza
|
<Credenza
|
||||||
|
@ -211,284 +226,358 @@ export default function CreateResourceForm({
|
||||||
</CredenzaDescription>
|
</CredenzaDescription>
|
||||||
</CredenzaHeader>
|
</CredenzaHeader>
|
||||||
<CredenzaBody>
|
<CredenzaBody>
|
||||||
<Form {...form}>
|
{!showSnippets && (
|
||||||
<form
|
<Form {...form}>
|
||||||
onSubmit={form.handleSubmit(onSubmit)}
|
<form
|
||||||
className="space-y-4"
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
id="create-resource-form"
|
className="space-y-4"
|
||||||
>
|
id="create-resource-form"
|
||||||
<FormField
|
>
|
||||||
control={form.control}
|
|
||||||
name="name"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>Name</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
placeholder="Your name"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
This is the name that will be
|
|
||||||
displayed for this resource.
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{!env.flags.allowRawResources || (
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="http"
|
name="name"
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
|
||||||
<div className="space-y-0.5">
|
|
||||||
<FormLabel className="text-base">
|
|
||||||
HTTP Resource
|
|
||||||
</FormLabel>
|
|
||||||
<FormDescription>
|
|
||||||
Toggle if this is an
|
|
||||||
HTTP resource or a raw
|
|
||||||
TCP/UDP resource
|
|
||||||
</FormDescription>
|
|
||||||
</div>
|
|
||||||
<FormControl>
|
|
||||||
<Switch
|
|
||||||
checked={field.value}
|
|
||||||
onCheckedChange={
|
|
||||||
field.onChange
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{form.watch("http") && (
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="subdomain"
|
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Subdomain</FormLabel>
|
<FormLabel>Name</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<CustomDomainInput
|
<Input
|
||||||
value={
|
placeholder="Your name"
|
||||||
field.value ?? ""
|
{...field}
|
||||||
}
|
|
||||||
domainSuffix={
|
|
||||||
domainSuffix
|
|
||||||
}
|
|
||||||
placeholder="Enter subdomain"
|
|
||||||
onChange={(value) =>
|
|
||||||
form.setValue(
|
|
||||||
"subdomain",
|
|
||||||
value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
This is the fully qualified
|
This is the name that will
|
||||||
domain name that will be
|
be displayed for this
|
||||||
used to access the resource.
|
resource.
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
|
|
||||||
{!form.watch("http") && (
|
{!env.flags.allowRawResources || (
|
||||||
<Link
|
|
||||||
className="text-sm text-primary flex items-center gap-1"
|
|
||||||
href="https://docs.fossorial.io/Getting%20Started/tcp-udp"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
Learn how to configure TCP/UDP resources
|
|
||||||
</span>
|
|
||||||
<SquareArrowOutUpRight size={14} />
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!form.watch("http") && (
|
|
||||||
<>
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="protocol"
|
name="http"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
||||||
<FormLabel>
|
<div className="space-y-0.5">
|
||||||
Protocol
|
<FormLabel className="text-base">
|
||||||
</FormLabel>
|
HTTP Resource
|
||||||
<Select
|
</FormLabel>
|
||||||
value={field.value}
|
<FormDescription>
|
||||||
onValueChange={
|
Toggle if this is an
|
||||||
field.onChange
|
HTTP resource or a
|
||||||
}
|
raw TCP/UDP resource
|
||||||
>
|
</FormDescription>
|
||||||
<FormControl>
|
</div>
|
||||||
<SelectTrigger>
|
<FormControl>
|
||||||
<SelectValue placeholder="Select a protocol" />
|
<Switch
|
||||||
</SelectTrigger>
|
checked={
|
||||||
</FormControl>
|
field.value
|
||||||
<SelectContent>
|
}
|
||||||
<SelectItem value="tcp">
|
onCheckedChange={
|
||||||
TCP
|
field.onChange
|
||||||
</SelectItem>
|
}
|
||||||
<SelectItem value="udp">
|
/>
|
||||||
UDP
|
</FormControl>
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
<FormDescription>
|
|
||||||
The protocol to use for
|
|
||||||
the resource
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{form.watch("http") && (
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="proxyPort"
|
name="subdomain"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
Port Number
|
Subdomain
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<CustomDomainInput
|
||||||
type="number"
|
|
||||||
placeholder="Enter port number"
|
|
||||||
value={
|
value={
|
||||||
field.value ??
|
field.value ??
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
onChange={(e) =>
|
domainSuffix={
|
||||||
field.onChange(
|
domainSuffix
|
||||||
e.target
|
}
|
||||||
.value
|
placeholder="Enter subdomain"
|
||||||
? parseInt(
|
onChange={(value) =>
|
||||||
e
|
form.setValue(
|
||||||
.target
|
"subdomain",
|
||||||
.value
|
value
|
||||||
)
|
|
||||||
: null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
The port number to proxy
|
This is the fully
|
||||||
requests to (required
|
qualified domain name
|
||||||
for non-HTTP resources)
|
that will be used to
|
||||||
|
access the resource.
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="siteId"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem className="flex flex-col">
|
|
||||||
<FormLabel>Site</FormLabel>
|
|
||||||
<Popover>
|
|
||||||
<PopoverTrigger asChild>
|
|
||||||
<FormControl>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
role="combobox"
|
|
||||||
className={cn(
|
|
||||||
"justify-between",
|
|
||||||
!field.value &&
|
|
||||||
"text-muted-foreground"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{field.value
|
|
||||||
? sites.find(
|
|
||||||
(site) =>
|
|
||||||
site.siteId ===
|
|
||||||
field.value
|
|
||||||
)?.name
|
|
||||||
: "Select site"}
|
|
||||||
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
||||||
</Button>
|
|
||||||
</FormControl>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent className="p-0">
|
|
||||||
<Command>
|
|
||||||
<CommandInput placeholder="Search site..." />
|
|
||||||
<CommandList>
|
|
||||||
<CommandEmpty>
|
|
||||||
No site found.
|
|
||||||
</CommandEmpty>
|
|
||||||
<CommandGroup>
|
|
||||||
{sites.map(
|
|
||||||
(site) => (
|
|
||||||
<CommandItem
|
|
||||||
value={
|
|
||||||
site.niceId
|
|
||||||
}
|
|
||||||
key={
|
|
||||||
site.siteId
|
|
||||||
}
|
|
||||||
onSelect={() => {
|
|
||||||
form.setValue(
|
|
||||||
"siteId",
|
|
||||||
site.siteId
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CheckIcon
|
|
||||||
className={cn(
|
|
||||||
"mr-2 h-4 w-4",
|
|
||||||
site.siteId ===
|
|
||||||
field.value
|
|
||||||
? "opacity-100"
|
|
||||||
: "opacity-0"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{
|
|
||||||
site.name
|
|
||||||
}
|
|
||||||
</CommandItem>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</CommandGroup>
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
<FormDescription>
|
|
||||||
This is the site that will be
|
|
||||||
used in the dashboard.
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
)}
|
||||||
/>
|
|
||||||
</form>
|
{!form.watch("http") && (
|
||||||
</Form>
|
<Link
|
||||||
|
className="text-sm text-primary flex items-center gap-1"
|
||||||
|
href="https://docs.fossorial.io/Getting%20Started/tcp-udp"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Learn how to configure TCP/UDP
|
||||||
|
resources
|
||||||
|
</span>
|
||||||
|
<SquareArrowOutUpRight size={14} />
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!form.watch("http") && (
|
||||||
|
<>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="protocol"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
Protocol
|
||||||
|
</FormLabel>
|
||||||
|
<Select
|
||||||
|
value={field.value}
|
||||||
|
onValueChange={
|
||||||
|
field.onChange
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a protocol" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="tcp">
|
||||||
|
TCP
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="udp">
|
||||||
|
UDP
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormDescription>
|
||||||
|
The protocol to use
|
||||||
|
for the resource
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="proxyPort"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
Port Number
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
placeholder="Enter port number"
|
||||||
|
value={
|
||||||
|
field.value ??
|
||||||
|
""
|
||||||
|
}
|
||||||
|
onChange={(e) =>
|
||||||
|
field.onChange(
|
||||||
|
e.target
|
||||||
|
.value
|
||||||
|
? parseInt(
|
||||||
|
e
|
||||||
|
.target
|
||||||
|
.value
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
The port number to
|
||||||
|
proxy requests to
|
||||||
|
(required for
|
||||||
|
non-HTTP resources)
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="siteId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex flex-col">
|
||||||
|
<FormLabel>Site</FormLabel>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<FormControl>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
role="combobox"
|
||||||
|
className={cn(
|
||||||
|
"justify-between",
|
||||||
|
!field.value &&
|
||||||
|
"text-muted-foreground"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{field.value
|
||||||
|
? sites.find(
|
||||||
|
(
|
||||||
|
site
|
||||||
|
) =>
|
||||||
|
site.siteId ===
|
||||||
|
field.value
|
||||||
|
)?.name
|
||||||
|
: "Select site"}
|
||||||
|
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</FormControl>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="p-0">
|
||||||
|
<Command>
|
||||||
|
<CommandInput placeholder="Search site..." />
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>
|
||||||
|
No site
|
||||||
|
found.
|
||||||
|
</CommandEmpty>
|
||||||
|
<CommandGroup>
|
||||||
|
{sites.map(
|
||||||
|
(
|
||||||
|
site
|
||||||
|
) => (
|
||||||
|
<CommandItem
|
||||||
|
value={
|
||||||
|
site.niceId
|
||||||
|
}
|
||||||
|
key={
|
||||||
|
site.siteId
|
||||||
|
}
|
||||||
|
onSelect={() => {
|
||||||
|
form.setValue(
|
||||||
|
"siteId",
|
||||||
|
site.siteId
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CheckIcon
|
||||||
|
className={cn(
|
||||||
|
"mr-2 h-4 w-4",
|
||||||
|
site.siteId ===
|
||||||
|
field.value
|
||||||
|
? "opacity-100"
|
||||||
|
: "opacity-0"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{
|
||||||
|
site.name
|
||||||
|
}
|
||||||
|
</CommandItem>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<FormDescription>
|
||||||
|
This is the site that will
|
||||||
|
be used in the dashboard.
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{showSnippets && (
|
||||||
|
<div>
|
||||||
|
<div className="flex items-start space-x-4 mb-6 last:mb-0">
|
||||||
|
<div className="flex-shrink-0 w-8 h-8 bg-muted text-primary-foreground rounded-full flex items-center justify-center font-bold">
|
||||||
|
1
|
||||||
|
</div>
|
||||||
|
<div className="flex-grow">
|
||||||
|
<h3 className="text-lg font-semibold mb-3">
|
||||||
|
Traefik: Add Entrypoints
|
||||||
|
</h3>
|
||||||
|
<CopyTextBox
|
||||||
|
text={`entryPoints:
|
||||||
|
${form.getValues("protocol")}-${form.getValues("proxyPort")}:
|
||||||
|
address: ":${form.getValues("proxyPort")}/${form.getValues("protocol")}"`}
|
||||||
|
wrapText={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-start space-x-4 mb-6 last:mb-0">
|
||||||
|
<div className="flex-shrink-0 w-8 h-8 bg-muted text-primary-foreground rounded-full flex items-center justify-center font-bold">
|
||||||
|
2
|
||||||
|
</div>
|
||||||
|
<div className="flex-grow">
|
||||||
|
<h3 className="text-lg font-semibold mb-3">
|
||||||
|
Gerbil: Expose Ports in Docker
|
||||||
|
Compose
|
||||||
|
</h3>
|
||||||
|
<CopyTextBox
|
||||||
|
text={`ports:
|
||||||
|
- ${form.getValues("proxyPort")}:${form.getValues("proxyPort")}${form.getValues("protocol") === "tcp" ? "" : "/" + form.getValues("protocol")}`}
|
||||||
|
wrapText={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
className="text-sm text-primary flex items-center gap-1"
|
||||||
|
href="https://docs.fossorial.io/Getting%20Started/tcp-udp"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Make sure to follow the full guide
|
||||||
|
</span>
|
||||||
|
<SquareArrowOutUpRight size={14} />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</CredenzaBody>
|
</CredenzaBody>
|
||||||
<CredenzaFooter>
|
<CredenzaFooter>
|
||||||
<Button
|
{!showSnippets && <Button
|
||||||
type="submit"
|
type="submit"
|
||||||
form="create-resource-form"
|
form="create-resource-form"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
>
|
>
|
||||||
Create Resource
|
Create Resource
|
||||||
</Button>
|
</Button>}
|
||||||
|
|
||||||
|
{showSnippets && <Button
|
||||||
|
loading={loading}
|
||||||
|
onClick={() => goToResource()}
|
||||||
|
>
|
||||||
|
Go to Resource
|
||||||
|
</Button>}
|
||||||
|
|
||||||
<CredenzaClose asChild>
|
<CredenzaClose asChild>
|
||||||
<Button variant="outline">Close</Button>
|
<Button variant="outline">Close</Button>
|
||||||
</CredenzaClose>
|
</CredenzaClose>
|
||||||
|
|
|
@ -130,7 +130,7 @@ export default function ReverseProxyTargets(props: {
|
||||||
const addTargetForm = useForm({
|
const addTargetForm = useForm({
|
||||||
resolver: zodResolver(addTargetSchema),
|
resolver: zodResolver(addTargetSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
ip: "localhost",
|
ip: "",
|
||||||
method: resource.http ? "http" : null,
|
method: resource.http ? "http" : null,
|
||||||
port: resource.http ? 80 : resource.proxyPort || 1234
|
port: resource.http ? 80 : resource.proxyPort || 1234
|
||||||
// protocol: "TCP",
|
// protocol: "TCP",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue