mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-18 18:23:18 +02:00
improve resource type picker
This commit is contained in:
@@ -12,9 +12,9 @@ import {
|
||||
} from "@app/components/Settings";
|
||||
import HeaderTitle from "@app/components/SettingsSectionTitle";
|
||||
import {
|
||||
OptionSelect,
|
||||
type OptionSelectOption
|
||||
} from "@app/components/OptionSelect";
|
||||
DescribedSelect,
|
||||
type DescribedSelectOption
|
||||
} from "@app/components/DescribedSelect";
|
||||
import DomainPicker from "@app/components/DomainPicker";
|
||||
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
||||
import { Button } from "@app/components/ui/button";
|
||||
@@ -147,24 +147,35 @@ export default function CreatePrivateResourcePage() {
|
||||
const authDaemonMode = form.watch("authDaemonMode");
|
||||
const isNativeSsh = mode === "ssh" && authDaemonMode === "native";
|
||||
|
||||
const modeOptions: OptionSelectOption<PrivateResourceMode>[] = [
|
||||
{ value: "host", label: t("createInternalResourceDialogModeHost") },
|
||||
{ value: "cidr", label: t("createInternalResourceDialogModeCidr") },
|
||||
const modeOptions: DescribedSelectOption<PrivateResourceMode>[] = [
|
||||
{
|
||||
value: "host",
|
||||
title: t("createInternalResourceDialogModeHost"),
|
||||
description: t("privateResourceTypeHostDescription")
|
||||
},
|
||||
{
|
||||
value: "cidr",
|
||||
title: t("createInternalResourceDialogModeCidr"),
|
||||
description: t("privateResourceTypeCidrDescription")
|
||||
},
|
||||
...(!disableEnterpriseFeatures
|
||||
? [
|
||||
{
|
||||
value: "http" as const,
|
||||
label: t("createInternalResourceDialogModeHttp")
|
||||
title: t("createInternalResourceDialogModeHttp"),
|
||||
description: t("privateResourceTypeHttpDescription")
|
||||
},
|
||||
{
|
||||
value: "ssh" as const,
|
||||
label: t("createInternalResourceDialogModeSsh")
|
||||
title: t("createInternalResourceDialogModeSsh"),
|
||||
description: t("privateResourceTypeSshDescription")
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
value: "inference" as const,
|
||||
label: t("createInternalResourceDialogModeInference")
|
||||
title: t("createInternalResourceDialogModeInference"),
|
||||
description: t("resourceTypeInferenceDescription")
|
||||
}
|
||||
];
|
||||
|
||||
@@ -260,6 +271,110 @@ export default function CreatePrivateResourcePage() {
|
||||
<SettingsSectionBody>
|
||||
<SettingsSectionForm variant="half">
|
||||
<SettingsFormGrid>
|
||||
<SettingsFormCell span="half">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="mode"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t("type")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<DescribedSelect<PrivateResourceMode>
|
||||
options={
|
||||
modeOptions
|
||||
}
|
||||
value={field.value}
|
||||
onChange={(
|
||||
newMode
|
||||
) => {
|
||||
field.onChange(
|
||||
newMode
|
||||
);
|
||||
if (
|
||||
newMode ===
|
||||
"ssh"
|
||||
) {
|
||||
form.setValue(
|
||||
"authDaemonMode",
|
||||
"native"
|
||||
);
|
||||
form.setValue(
|
||||
"standardDaemonLocation",
|
||||
"site"
|
||||
);
|
||||
form.setValue(
|
||||
"destination",
|
||||
null
|
||||
);
|
||||
form.setValue(
|
||||
"destinationPort",
|
||||
null
|
||||
);
|
||||
} else if (
|
||||
newMode ===
|
||||
"http"
|
||||
) {
|
||||
form.setValue(
|
||||
"destinationPort",
|
||||
443
|
||||
);
|
||||
} else if (
|
||||
newMode ===
|
||||
"inference"
|
||||
) {
|
||||
form.setValue(
|
||||
"siteIds",
|
||||
[]
|
||||
);
|
||||
setSelectedSites(
|
||||
[]
|
||||
);
|
||||
form.setValue(
|
||||
"destination",
|
||||
null
|
||||
);
|
||||
form.setValue(
|
||||
"destinationPort",
|
||||
null
|
||||
);
|
||||
form.setValue(
|
||||
"providerIds",
|
||||
[]
|
||||
);
|
||||
setSelectedProviders(
|
||||
[]
|
||||
);
|
||||
} else {
|
||||
form.setValue(
|
||||
"destinationPort",
|
||||
null
|
||||
);
|
||||
}
|
||||
}}
|
||||
searchPlaceholder={t(
|
||||
"resourceTypeSearch"
|
||||
)}
|
||||
emptyMessage={t(
|
||||
"resourceTypeNotFound"
|
||||
)}
|
||||
placeholder={t(
|
||||
"noneSelected"
|
||||
)}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
<FormDescription>
|
||||
{t(
|
||||
"privateResourceTypeDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</SettingsFormCell>
|
||||
|
||||
<SettingsFormCell span="half">
|
||||
<FormField
|
||||
control={form.control}
|
||||
@@ -283,91 +398,6 @@ export default function CreatePrivateResourcePage() {
|
||||
/>
|
||||
</SettingsFormCell>
|
||||
|
||||
<SettingsFormCell span="full">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="mode"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{t("type")}
|
||||
</FormLabel>
|
||||
<OptionSelect<PrivateResourceMode>
|
||||
options={modeOptions}
|
||||
value={field.value}
|
||||
onChange={(newMode) => {
|
||||
field.onChange(
|
||||
newMode
|
||||
);
|
||||
if (
|
||||
newMode ===
|
||||
"ssh"
|
||||
) {
|
||||
form.setValue(
|
||||
"authDaemonMode",
|
||||
"native"
|
||||
);
|
||||
form.setValue(
|
||||
"standardDaemonLocation",
|
||||
"site"
|
||||
);
|
||||
form.setValue(
|
||||
"destination",
|
||||
null
|
||||
);
|
||||
form.setValue(
|
||||
"destinationPort",
|
||||
null
|
||||
);
|
||||
} else if (
|
||||
newMode ===
|
||||
"http"
|
||||
) {
|
||||
form.setValue(
|
||||
"destinationPort",
|
||||
443
|
||||
);
|
||||
} else if (
|
||||
newMode ===
|
||||
"inference"
|
||||
) {
|
||||
form.setValue(
|
||||
"siteIds",
|
||||
[]
|
||||
);
|
||||
setSelectedSites(
|
||||
[]
|
||||
);
|
||||
form.setValue(
|
||||
"destination",
|
||||
null
|
||||
);
|
||||
form.setValue(
|
||||
"destinationPort",
|
||||
null
|
||||
);
|
||||
form.setValue(
|
||||
"providerIds",
|
||||
[]
|
||||
);
|
||||
setSelectedProviders(
|
||||
[]
|
||||
);
|
||||
} else {
|
||||
form.setValue(
|
||||
"destinationPort",
|
||||
null
|
||||
);
|
||||
}
|
||||
}}
|
||||
cols={4}
|
||||
/>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</SettingsFormCell>
|
||||
|
||||
{(mode === "http" ||
|
||||
mode === "inference") && (
|
||||
<SettingsFormCell span="full">
|
||||
|
||||
@@ -18,9 +18,9 @@ import {
|
||||
} from "@app/components/Settings";
|
||||
import HeaderTitle from "@app/components/SettingsSectionTitle";
|
||||
import {
|
||||
OptionSelect,
|
||||
type OptionSelectOption
|
||||
} from "@app/components/OptionSelect";
|
||||
DescribedSelect,
|
||||
type DescribedSelectOption
|
||||
} from "@app/components/DescribedSelect";
|
||||
import {
|
||||
StrategySelect,
|
||||
type StrategyOption
|
||||
@@ -775,26 +775,45 @@ export default function Page() {
|
||||
}
|
||||
];
|
||||
|
||||
let typeLabels: Partial<Record<NewResourceType, string>> = {
|
||||
http: "HTTP",
|
||||
inference: t("createInternalResourceDialogModeInference"),
|
||||
tcp: "TCP",
|
||||
udp: "UDP"
|
||||
const typeMeta: Record<
|
||||
NewResourceType,
|
||||
{ title: string; description: string }
|
||||
> = {
|
||||
http: {
|
||||
title: t("createInternalResourceDialogModeHttp"),
|
||||
description: t("resourceTypeHttpDescription")
|
||||
},
|
||||
inference: {
|
||||
title: t("createInternalResourceDialogModeInference"),
|
||||
description: t("resourceTypeInferenceDescription")
|
||||
},
|
||||
ssh: {
|
||||
title: t("createInternalResourceDialogModeSsh"),
|
||||
description: t("resourceTypeSshDescription")
|
||||
},
|
||||
rdp: {
|
||||
title: t("rdpTitle"),
|
||||
description: t("resourceTypeRdpDescription")
|
||||
},
|
||||
vnc: {
|
||||
title: t("vncTitle"),
|
||||
description: t("resourceTypeVncDescription")
|
||||
},
|
||||
tcp: {
|
||||
title: t("createInternalResourceDialogTcp"),
|
||||
description: t("resourceTypeTcpDescription")
|
||||
},
|
||||
udp: {
|
||||
title: t("createInternalResourceDialogUdp"),
|
||||
description: t("resourceTypeUdpDescription")
|
||||
}
|
||||
};
|
||||
|
||||
if (enterpriseModesAllowed) {
|
||||
typeLabels = {
|
||||
...typeLabels,
|
||||
ssh: "SSH",
|
||||
rdp: "RDP",
|
||||
vnc: "VNC"
|
||||
};
|
||||
}
|
||||
|
||||
const typeOptions: OptionSelectOption<NewResourceType>[] =
|
||||
const typeOptions: DescribedSelectOption<NewResourceType>[] =
|
||||
availableTypes.map((type) => ({
|
||||
value: type,
|
||||
label: typeLabels[type] ?? type.toUpperCase()
|
||||
title: typeMeta[type].title,
|
||||
description: typeMeta[type].description
|
||||
}));
|
||||
|
||||
return (
|
||||
@@ -831,6 +850,35 @@ export default function Page() {
|
||||
<SettingsSectionBody>
|
||||
<SettingsSectionForm variant="half">
|
||||
<SettingsFormGrid>
|
||||
<SettingsFormCell span="half">
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
{t("type")}
|
||||
</Label>
|
||||
<DescribedSelect<NewResourceType>
|
||||
options={typeOptions}
|
||||
value={resourceType}
|
||||
onChange={
|
||||
setResourceType
|
||||
}
|
||||
searchPlaceholder={t(
|
||||
"resourceTypeSearch"
|
||||
)}
|
||||
emptyMessage={t(
|
||||
"resourceTypeNotFound"
|
||||
)}
|
||||
placeholder={t(
|
||||
"noneSelected"
|
||||
)}
|
||||
/>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t(
|
||||
"resourceTypeDescription"
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</SettingsFormCell>
|
||||
|
||||
<SettingsFormCell span="half">
|
||||
<Form {...baseForm}>
|
||||
<form
|
||||
@@ -876,27 +924,6 @@ export default function Page() {
|
||||
</Form>
|
||||
</SettingsFormCell>
|
||||
|
||||
<SettingsFormCell span="full">
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm font-medium">
|
||||
{t("type")}
|
||||
</p>
|
||||
<OptionSelect<NewResourceType>
|
||||
options={typeOptions}
|
||||
value={resourceType}
|
||||
onChange={
|
||||
setResourceType
|
||||
}
|
||||
cols={6}
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t(
|
||||
"resourceTypeDescription"
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</SettingsFormCell>
|
||||
|
||||
{isHttpResource && (
|
||||
<SettingsFormCell span="full">
|
||||
<Form {...httpForm}>
|
||||
|
||||
Reference in New Issue
Block a user