mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-27 19:22:50 +00:00
Clean up the ui a bit
This commit is contained in:
@@ -220,8 +220,9 @@
|
||||
"resourceRawDescriptionCloud": "Proxy requests over raw TCP/UDP using a port number. Requires sites to connect to a remote node.",
|
||||
"resourceCreate": "Create Resource",
|
||||
"resourceCreateDescription": "Follow the steps below to create a new resource",
|
||||
"resourceCreateGeneralDescription": "Configure the basic resource settings including the name and the type",
|
||||
"resourceSeeAll": "See All Resources",
|
||||
"resourceInfo": "Resource Information",
|
||||
"resourceCreateGeneral": "General",
|
||||
"resourceNameDescription": "This is the display name for the resource.",
|
||||
"siteSelect": "Select site",
|
||||
"siteSearch": "Search site",
|
||||
@@ -231,9 +232,11 @@
|
||||
"noCountryFound": "No country found.",
|
||||
"siteSelectionDescription": "This site will provide connectivity to the target.",
|
||||
"resourceType": "Resource Type",
|
||||
"resourceTypeDescription": "Determine how to access the resource",
|
||||
"resourceTypeDescription": "This controls the resource protocol and how it will be rendered in the browser. This can’t be changed later.",
|
||||
"resourceDomainDescription": "The resource will be served at this fully qualified domain name.",
|
||||
"resourceHTTPSSettings": "HTTPS Settings",
|
||||
"resourceHTTPSSettingsDescription": "Configure how the resource will be accessed over HTTPS",
|
||||
"resourcePortDescription": "The external port on the Pangolin instance or node where the resource will be accessible.",
|
||||
"domainType": "Domain Type",
|
||||
"subdomain": "Subdomain",
|
||||
"baseDomain": "Base Domain",
|
||||
@@ -1982,9 +1985,9 @@
|
||||
"sshServerMode": "Mode",
|
||||
"sshServerModeStandard": "Standard SSH Server",
|
||||
"sshServerModePangolin": "Pangolin SSH",
|
||||
"sshServerModeStandardDescription": "Uses a Pangolin auth daemon to manage SSH authentication on the site or remote host.",
|
||||
"sshServerModeStandardDescription": "Routes commands over network to an SSH server such as OpenSSH.",
|
||||
"sshServerModeNative": "Native SSH Server",
|
||||
"sshServerModeNativeDescription": "SSH authentication is handled natively by an existing SSH server without a separate auth daemon.",
|
||||
"sshServerModeNativeDescription": "Executes commands directly on the host via the Site Connector. No network config required.",
|
||||
"sshAuthenticationMethod": "Authentication Method",
|
||||
"sshAuthMethodManual": "Manual Authentication",
|
||||
"sshAuthMethodManualDescription": "Requires existing host credentials. Bypasses automatic provisioning.",
|
||||
@@ -3354,5 +3357,6 @@
|
||||
"memberPortalResourceDisabled": "Resource Disabled",
|
||||
"memberPortalShowingResources": "Showing {start}-{end} of {total} resources",
|
||||
"memberPortalPrevious": "Previous",
|
||||
"memberPortalNext": "Next"
|
||||
"memberPortalNext": "Next",
|
||||
"httpSettings": "HTTP Settings"
|
||||
}
|
||||
|
||||
@@ -19,7 +19,14 @@ import {
|
||||
SettingsSectionTitle
|
||||
} from "@app/components/Settings";
|
||||
import HeaderTitle from "@app/components/SettingsSectionTitle";
|
||||
import { StrategySelect, type StrategyOption } from "@app/components/StrategySelect";
|
||||
import {
|
||||
OptionSelect,
|
||||
type OptionSelectOption
|
||||
} from "@app/components/OptionSelect";
|
||||
import {
|
||||
StrategySelect,
|
||||
type StrategyOption
|
||||
} from "@app/components/StrategySelect";
|
||||
import { ResourceTargetAddressItem } from "@app/components/resource-target-address-item";
|
||||
import { BrowserGatewayTargetForm } from "@app/components/BrowserGatewayTargetForm";
|
||||
import {
|
||||
@@ -565,7 +572,9 @@ export default function Page() {
|
||||
}
|
||||
|
||||
const res = await api
|
||||
.put<AxiosResponse<Resource>>(`/org/${orgId}/resource/`, payload)
|
||||
.put<
|
||||
AxiosResponse<Resource>
|
||||
>(`/org/${orgId}/resource/`, payload)
|
||||
.catch((e) => {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
@@ -880,9 +889,7 @@ export default function Page() {
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-7 text-xs gap-1"
|
||||
onClick={() =>
|
||||
openHealthCheckDialog(row.original)
|
||||
}
|
||||
onClick={() => openHealthCheckDialog(row.original)}
|
||||
>
|
||||
<Settings className="h-3.5 w-3.5" />
|
||||
{row.original.hcEnabled ? (
|
||||
@@ -1224,6 +1231,12 @@ export default function Page() {
|
||||
udp: "UDP"
|
||||
};
|
||||
|
||||
const typeOptions: OptionSelectOption<NewResourceType>[] =
|
||||
availableTypes.map((type) => ({
|
||||
value: type,
|
||||
label: typeLabels[type]
|
||||
}));
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex justify-between">
|
||||
@@ -1249,14 +1262,14 @@ export default function Page() {
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t("resourceInfo")}
|
||||
{t("resourceCreateGeneral")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t("resourceCreateDescription")}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
<SettingsSectionForm>
|
||||
<SettingsSectionForm variant="half">
|
||||
{/* Name */}
|
||||
<Form {...baseForm}>
|
||||
<form
|
||||
@@ -1298,28 +1311,12 @@ export default function Page() {
|
||||
<p className="text-sm font-medium">
|
||||
{t("type")}
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{availableTypes.map((type) => (
|
||||
<button
|
||||
key={type}
|
||||
type="button"
|
||||
onClick={() =>
|
||||
setResourceType(
|
||||
type
|
||||
)
|
||||
}
|
||||
className={cn(
|
||||
"px-4 py-1.5 rounded-md border text-sm font-medium transition-colors",
|
||||
resourceType ===
|
||||
type
|
||||
? "border-primary bg-primary/10 text-primary"
|
||||
: "border-input bg-background hover:bg-accent text-foreground"
|
||||
)}
|
||||
>
|
||||
{typeLabels[type]}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<OptionSelect<NewResourceType>
|
||||
options={typeOptions}
|
||||
value={resourceType}
|
||||
onChange={setResourceType}
|
||||
cols={6}
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t("resourceTypeDescription")}
|
||||
</p>
|
||||
@@ -1327,24 +1324,32 @@ export default function Page() {
|
||||
|
||||
{/* Domain/Subdomain (HTTP-based types) */}
|
||||
{isHttpResource && (
|
||||
<DomainPicker
|
||||
allowWildcard={true}
|
||||
orgId={orgId as string}
|
||||
warnOnProvidedDomain={
|
||||
remoteExitNodes.length >= 1
|
||||
}
|
||||
onDomainChange={(res) => {
|
||||
if (!res) return;
|
||||
httpForm.setValue(
|
||||
"subdomain",
|
||||
res.subdomain
|
||||
);
|
||||
httpForm.setValue(
|
||||
"domainId",
|
||||
res.domainId
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<div className="space-y-2">
|
||||
<DomainPicker
|
||||
allowWildcard={true}
|
||||
orgId={orgId as string}
|
||||
warnOnProvidedDomain={
|
||||
remoteExitNodes.length >=
|
||||
1
|
||||
}
|
||||
onDomainChange={(res) => {
|
||||
if (!res) return;
|
||||
httpForm.setValue(
|
||||
"subdomain",
|
||||
res.subdomain
|
||||
);
|
||||
httpForm.setValue(
|
||||
"domainId",
|
||||
res.domainId
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t(
|
||||
"resourceDomainDescription"
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Proxy Port (TCP/UDP types) */}
|
||||
@@ -1396,6 +1401,11 @@ export default function Page() {
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
<FormDescription>
|
||||
{t(
|
||||
"resourcePortDescription"
|
||||
)}
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
@@ -1786,7 +1796,8 @@ export default function Page() {
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel()
|
||||
.rows?.length ? (
|
||||
.rows
|
||||
?.length ? (
|
||||
table
|
||||
.getRowModel()
|
||||
.rows.map(
|
||||
|
||||
Reference in New Issue
Block a user