This commit is contained in:
Fred KISSIE
2026-04-23 06:33:57 +02:00
parent 53c48e6f04
commit b9bee2836b
4 changed files with 135 additions and 54 deletions

View File

@@ -40,7 +40,12 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
import { UserType } from "@server/types/UserTypes";
import { useQuery } from "@tanstack/react-query";
import { ChevronsUpDown, ExternalLink } from "lucide-react";
import {
ArrowDownIcon,
ChevronDownIcon,
ChevronsUpDown,
ExternalLink
} from "lucide-react";
import { useTranslations } from "next-intl";
import { useEffect, useRef, useState } from "react";
import { useForm } from "react-hook-form";
@@ -50,7 +55,7 @@ import {
formatMultiSitesSelectorLabel
} from "./multi-site-selector";
import type { Selectedsite } from "./site-selector";
import { CaretSortIcon } from "@radix-ui/react-icons";
import { MachinesSelector } from "./machines-selector";
import DomainPicker from "@app/components/DomainPicker";
import { SwitchInput } from "@app/components/SwitchInput";
@@ -155,7 +160,7 @@ export type InternalResourceData = {
const tagSchema = z.object({ id: z.string(), text: z.string() });
function buildSelectedSitesForResource(
resource: InternalResourceData,
resource: InternalResourceData
): Selectedsite[] {
return resource.siteIds.map((siteId, idx) => ({
name: resource.siteNames[idx] ?? "",
@@ -608,9 +613,7 @@ export function InternalResourceForm({
users: [],
clients: []
});
setSelectedSites(
buildSelectedSitesForResource(resource)
);
setSelectedSites(buildSelectedSitesForResource(resource));
setTcpPortMode(
getPortModeFromString(resource.tcpPortRangeString)
);
@@ -877,7 +880,9 @@ export function InternalResourceForm({
field.value ??
"http"
}
disabled={httpSectionDisabled}
disabled={
httpSectionDisabled
}
>
<FormControl>
<SelectTrigger className="w-full">
@@ -918,7 +923,10 @@ export function InternalResourceForm({
<Input
{...field}
className="w-full"
disabled={isHttpMode && httpSectionDisabled}
disabled={
isHttpMode &&
httpSectionDisabled
}
/>
</FormControl>
<FormMessage />
@@ -974,7 +982,9 @@ export function InternalResourceForm({
field.value ??
""
}
disabled={httpSectionDisabled}
disabled={
httpSectionDisabled
}
onChange={(e) => {
const raw =
e.target
@@ -1009,7 +1019,9 @@ export function InternalResourceForm({
</div>
{isHttpMode && (
<PaidFeaturesAlert tiers={tierMatrix.httpPrivateResources} />
<PaidFeaturesAlert
tiers={tierMatrix.httpPrivateResources}
/>
)}
{isHttpMode ? (
@@ -1022,55 +1034,61 @@ export function InternalResourceForm({
{t(httpConfigurationDescriptionKey)}
</div>
</div>
<div className={httpSectionDisabled ? "pointer-events-none opacity-50" : undefined}>
<DomainPicker
key={
variant === "edit" && siteResourceId
? `http-domain-${siteResourceId}`
: "http-domain-create"
<div
className={
httpSectionDisabled
? "pointer-events-none opacity-50"
: undefined
}
orgId={orgId}
cols={2}
hideFreeDomain
defaultSubdomain={
httpConfigSubdomain ?? undefined
}
defaultDomainId={
httpConfigDomainId ?? undefined
}
defaultFullDomain={
httpConfigFullDomain ?? undefined
}
onDomainChange={(res) => {
if (res === null) {
>
<DomainPicker
key={
variant === "edit" && siteResourceId
? `http-domain-${siteResourceId}`
: "http-domain-create"
}
orgId={orgId}
cols={2}
hideFreeDomain
defaultSubdomain={
httpConfigSubdomain ?? undefined
}
defaultDomainId={
httpConfigDomainId ?? undefined
}
defaultFullDomain={
httpConfigFullDomain ?? undefined
}
onDomainChange={(res) => {
if (res === null) {
form.setValue(
"httpConfigSubdomain",
null
);
form.setValue(
"httpConfigDomainId",
null
);
form.setValue(
"httpConfigFullDomain",
null
);
return;
}
form.setValue(
"httpConfigSubdomain",
null
res.subdomain ?? null
);
form.setValue(
"httpConfigDomainId",
null
res.domainId
);
form.setValue(
"httpConfigFullDomain",
null
res.fullDomain
);
return;
}
form.setValue(
"httpConfigSubdomain",
res.subdomain ?? null
);
form.setValue(
"httpConfigDomainId",
res.domainId
);
form.setValue(
"httpConfigFullDomain",
res.fullDomain
);
}}
/>
}}
/>
</div>
<FormField
control={form.control}
@@ -1088,7 +1106,9 @@ export function InternalResourceForm({
onCheckedChange={
field.onChange
}
disabled={httpSectionDisabled}
disabled={
httpSectionDisabled
}
/>
</FormControl>
</FormItem>
@@ -1511,7 +1531,7 @@ export function InternalResourceForm({
role="combobox"
className={cn(
"justify-between w-full",
"text-muted-foreground pl-1.5"
"text-muted-foreground pl-1.5 cursor-text"
)}
>
<span
@@ -1548,7 +1568,7 @@ export function InternalResourceForm({
)}
</span>
</span>
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
<ChevronDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>

View File

@@ -5,7 +5,7 @@ import { useMemo, useState } from "react";
import { useDebounce } from "use-debounce";
import { useTranslations } from "next-intl";
import { MultiSelectTags } from "./multi-select-tags";
import { MultiSelectTags } from "./multi-select/multi-select-tags";
export type SelectedMachine = Pick<
ListClientsResponse["clients"][number],

View File

@@ -0,0 +1,61 @@
import {
Popover,
PopoverContent,
PopoverTrigger
} from "@app/components/ui/popover";
import { Button } from "@app/components/ui/button";
import { cn } from "@app/lib/cn";
import { ChevronDownIcon } from "lucide-react";
import {
type TagValue,
type MultiSelectTagsProps,
MultiSelectTags
} from "./multi-select-tags";
export interface MultiSelectInputProps<
T extends TagValue
> extends MultiSelectTagsProps<T> {
buttonText?: string;
}
export function MultiSelectInput<T extends TagValue>({
buttonText,
...props
}: MultiSelectInputProps<T>) {
return (
<Popover>
<PopoverTrigger>
<div
className={cn(
"justify-between w-full",
"text-muted-foreground pl-1.5 cursor-text"
)}
>
<span
className={cn(
"inline-flex items-center gap-1",
"overflow-x-auto"
)}
>
{/* {(field.value ?? []).map((client) => (
<span
key={client.clientId}
className={cn(
"bg-muted-foreground/20 font-normal text-foreground rounded-sm",
"py-1 px-1.5 text-xs"
)}
>
{client.name}
</span>
))} */}
<span className="pl-1 font-normal">{buttonText}</span>
</span>
<ChevronDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</div>
</PopoverTrigger>
<PopoverContent className="p-0">
<MultiSelectTags {...props} />
</PopoverContent>
</Popover>
);
}

View File

@@ -6,7 +6,7 @@ import {
CommandInput,
CommandItem,
CommandList
} from "./ui/command";
} from "../ui/command";
import { cn } from "@app/lib/cn";
import { CheckIcon } from "lucide-react";