mirror of
https://github.com/fosrl/pangolin.git
synced 2025-08-31 06:59:33 +02:00
add snippets to create resource
This commit is contained in:
parent
599d0a52bf
commit
18e6f16ce7
5 changed files with 634 additions and 496 deletions
|
@ -137,7 +137,8 @@ LQIDAQAB
|
|||
hostId: this.hostId,
|
||||
isHostLicensed: true,
|
||||
isLicenseValid: false,
|
||||
maxSites: undefined
|
||||
maxSites: undefined,
|
||||
usedSites: siteCount.value
|
||||
};
|
||||
|
||||
try {
|
||||
|
|
|
@ -67,6 +67,12 @@ import { SwitchInput } from "@app/components/SwitchInput";
|
|||
import { useRouter } from "next/navigation";
|
||||
import { isTargetValid } from "@server/lib/validators";
|
||||
import { tlsNameSchema } from "@server/lib/schemas";
|
||||
import { ChevronsUpDown } from "lucide-react";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger
|
||||
} from "@app/components/ui/collapsible";
|
||||
|
||||
const addTargetSchema = z.object({
|
||||
ip: z.string().refine(isTargetValid),
|
||||
|
@ -145,6 +151,7 @@ export default function ReverseProxyTargets(props: {
|
|||
const [proxySettingsLoading, setProxySettingsLoading] = useState(false);
|
||||
|
||||
const [pageLoading, setPageLoading] = useState(true);
|
||||
const [isAdvancedOpen, setIsAdvancedOpen] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
const addTargetForm = useForm({
|
||||
|
@ -589,26 +596,57 @@ export default function ReverseProxyTargets(props: {
|
|||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<Collapsible
|
||||
open={isAdvancedOpen}
|
||||
onOpenChange={setIsAdvancedOpen}
|
||||
className="space-y-2"
|
||||
>
|
||||
<div className="flex items-center justify-between space-x-4">
|
||||
<CollapsibleTrigger asChild>
|
||||
<Button
|
||||
variant="text"
|
||||
size="sm"
|
||||
className="p-0 flex items-center justify-start gap-2 w-full"
|
||||
>
|
||||
<h4 className="text-sm font-semibold">
|
||||
Advanced TLS Settings
|
||||
</h4>
|
||||
<div>
|
||||
<ChevronsUpDown className="h-4 w-4" />
|
||||
<span className="sr-only">
|
||||
Toggle
|
||||
</span>
|
||||
</div>
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
</div>
|
||||
<CollapsibleContent className="space-y-2">
|
||||
<FormField
|
||||
control={tlsSettingsForm.control}
|
||||
control={
|
||||
tlsSettingsForm.control
|
||||
}
|
||||
name="tlsServerName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
TLS Server Name (SNI)
|
||||
TLS Server Name
|
||||
(SNI)
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
The TLS Server Name to use
|
||||
for SNI. Leave empty to use
|
||||
The TLS Server Name
|
||||
to use for SNI.
|
||||
Leave empty to use
|
||||
the default.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
</form>
|
||||
</Form>
|
||||
</SettingsSectionForm>
|
||||
|
|
|
@ -59,6 +59,9 @@ import {
|
|||
} from "@app/components/ui/popover";
|
||||
import { CaretSortIcon, CheckIcon } from "@radix-ui/react-icons";
|
||||
import { cn } from "@app/lib/cn";
|
||||
import { SquareArrowOutUpRight } from "lucide-react";
|
||||
import CopyTextBox from "@app/components/CopyTextBox";
|
||||
import Link from "next/link";
|
||||
|
||||
const baseResourceFormSchema = z.object({
|
||||
name: z.string().min(1).max(255),
|
||||
|
@ -108,6 +111,8 @@ export default function Page() {
|
|||
{ domainId: string; baseDomain: string }[]
|
||||
>([]);
|
||||
const [createLoading, setCreateLoading] = useState(false);
|
||||
const [showSnippets, setShowSnippets] = useState(false);
|
||||
const [resourceId, setResourceId] = useState<number | null>(null);
|
||||
|
||||
const resourceTypes: ReadonlyArray<ResourceTypeOption> = [
|
||||
{
|
||||
|
@ -202,7 +207,14 @@ export default function Page() {
|
|||
|
||||
if (res && res.status === 201) {
|
||||
const id = res.data.data.resourceId;
|
||||
setResourceId(id);
|
||||
|
||||
if (isHttp) {
|
||||
router.push(`/${orgId}/settings/resources/${id}`);
|
||||
} else {
|
||||
setShowSnippets(true);
|
||||
router.refresh();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error creating resource:", e);
|
||||
|
@ -301,6 +313,7 @@ export default function Page() {
|
|||
|
||||
{!loadingPage && (
|
||||
<div>
|
||||
{!showSnippets ? (
|
||||
<SettingsContainer>
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
|
@ -324,13 +337,15 @@ export default function Page() {
|
|||
Name
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
<Input
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
<FormDescription>
|
||||
This is the display
|
||||
name for the
|
||||
resource.
|
||||
This is the
|
||||
display name for
|
||||
the resource.
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
|
@ -421,8 +436,9 @@ export default function Page() {
|
|||
<FormMessage />
|
||||
<FormDescription>
|
||||
This site will
|
||||
provide connectivity
|
||||
to the resource.
|
||||
provide
|
||||
connectivity to
|
||||
the resource.
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
|
@ -483,10 +499,13 @@ export default function Page() {
|
|||
httpForm.control
|
||||
}
|
||||
name="isBaseDomain"
|
||||
render={({ field }) => (
|
||||
render={({
|
||||
field
|
||||
}) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Domain Type
|
||||
Domain
|
||||
Type
|
||||
</FormLabel>
|
||||
<Select
|
||||
value={
|
||||
|
@ -608,9 +627,10 @@ export default function Page() {
|
|||
</div>
|
||||
</div>
|
||||
<FormDescription>
|
||||
The subdomain where
|
||||
your resource will
|
||||
be accessible.
|
||||
The subdomain
|
||||
where your
|
||||
resource will be
|
||||
accessible.
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
|
@ -623,10 +643,13 @@ export default function Page() {
|
|||
httpForm.control
|
||||
}
|
||||
name="domainId"
|
||||
render={({ field }) => (
|
||||
render={({
|
||||
field
|
||||
}) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Base Domain
|
||||
Base
|
||||
Domain
|
||||
</FormLabel>
|
||||
<Select
|
||||
onValueChange={
|
||||
|
@ -692,7 +715,9 @@ export default function Page() {
|
|||
id="tcp-udp-settings-form"
|
||||
>
|
||||
<Controller
|
||||
control={tcpUdpForm.control}
|
||||
control={
|
||||
tcpUdpForm.control
|
||||
}
|
||||
name="protocol"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
|
@ -725,7 +750,9 @@ export default function Page() {
|
|||
/>
|
||||
|
||||
<FormField
|
||||
control={tcpUdpForm.control}
|
||||
control={
|
||||
tcpUdpForm.control
|
||||
}
|
||||
name="proxyPort"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
|
@ -759,8 +786,9 @@ export default function Page() {
|
|||
<FormMessage />
|
||||
<FormDescription>
|
||||
The external
|
||||
port number to
|
||||
proxy requests.
|
||||
port number
|
||||
to proxy
|
||||
requests.
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
|
@ -771,7 +799,6 @@ export default function Page() {
|
|||
</SettingsSectionBody>
|
||||
</SettingsSection>
|
||||
)}
|
||||
</SettingsContainer>
|
||||
|
||||
<div className="flex justify-end space-x-2 mt-8">
|
||||
<Button
|
||||
|
@ -801,6 +828,81 @@ export default function Page() {
|
|||
Create Resource
|
||||
</Button>
|
||||
</div>
|
||||
</SettingsContainer>
|
||||
) : (
|
||||
<SettingsContainer>
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
Configuration Snippets
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
Copy and paste these configuration snippets to set up your TCP/UDP resource
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-lg font-semibold">
|
||||
Traefik: Add Entrypoints
|
||||
</h3>
|
||||
<CopyTextBox
|
||||
text={`entryPoints:
|
||||
${tcpUdpForm.getValues("protocol")}-${tcpUdpForm.getValues("proxyPort")}:
|
||||
address: ":${tcpUdpForm.getValues("proxyPort")}/${tcpUdpForm.getValues("protocol")}"`}
|
||||
wrapText={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-lg font-semibold">
|
||||
Gerbil: Expose Ports in Docker Compose
|
||||
</h3>
|
||||
<CopyTextBox
|
||||
text={`ports:
|
||||
- ${tcpUdpForm.getValues("proxyPort")}:${tcpUdpForm.getValues("proxyPort")}${tcpUdpForm.getValues("protocol") === "tcp" ? "" : "/" + tcpUdpForm.getValues("protocol")}`}
|
||||
wrapText={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
className="text-sm text-primary flex items-center gap-1"
|
||||
href="https://docs.fossorial.io/Pangolin/tcp-udp"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<span>
|
||||
Learn how to configure TCP/UDP resources
|
||||
</span>
|
||||
<SquareArrowOutUpRight size={14} />
|
||||
</Link>
|
||||
</div>
|
||||
</SettingsSectionBody>
|
||||
</SettingsSection>
|
||||
|
||||
<div className="flex justify-end space-x-2 mt-8">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
router.push(`/${orgId}/settings/resources`)
|
||||
}
|
||||
>
|
||||
Back to Resources
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
router.push(
|
||||
`/${orgId}/settings/resources/${resourceId}`
|
||||
)
|
||||
}
|
||||
>
|
||||
Go to Resource
|
||||
</Button>
|
||||
</div>
|
||||
</SettingsContainer>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
|
|
@ -57,9 +57,7 @@ import {
|
|||
import { CheckIcon, ChevronsUpDown } from "lucide-react";
|
||||
import { Checkbox } from "@app/components/ui/checkbox";
|
||||
import { GenerateAccessTokenResponse } from "@server/routers/accessToken";
|
||||
import {
|
||||
constructShareLink
|
||||
} from "@app/lib/shareLinks";
|
||||
import { constructShareLink } from "@app/lib/shareLinks";
|
||||
import { ShareLinkRow } from "./ShareLinksTable";
|
||||
import { QRCodeCanvas, QRCodeSVG } from "qrcode.react";
|
||||
import {
|
||||
|
@ -528,11 +526,9 @@ export default function CreateShareLinkForm({
|
|||
accessTokenId
|
||||
}
|
||||
token={accessToken}
|
||||
resourceUrl={
|
||||
form.getValues(
|
||||
resourceUrl={form.getValues(
|
||||
"resourceUrl"
|
||||
)
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -33,9 +33,10 @@ export default function LicenseViolation() {
|
|||
return (
|
||||
<div className="fixed bottom-0 left-0 right-0 w-full bg-yellow-500 text-black p-4 text-center z-50">
|
||||
<p>
|
||||
License Violation: Using {licenseStatus.usedSites} sites
|
||||
exceeds your licensed limit of {licenseStatus.maxSites}{" "}
|
||||
sites. Follow license terms to continue using all features.
|
||||
License Violation: This server is using{" "}
|
||||
{licenseStatus.usedSites} sites which exceeds its licensed
|
||||
limit of {licenseStatus.maxSites} sites. Follow license
|
||||
terms to continue using all features.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue