mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-14 16:30:15 +02:00
various ui improvements
This commit is contained in:
@@ -271,14 +271,14 @@ export default function CreateAiProviderPage() {
|
||||
value
|
||||
)
|
||||
);
|
||||
const currentName =
|
||||
form.getValues(
|
||||
"name"
|
||||
);
|
||||
if (
|
||||
value !==
|
||||
"custom"
|
||||
) {
|
||||
const currentName =
|
||||
form.getValues(
|
||||
"name"
|
||||
);
|
||||
const previousLabel =
|
||||
t(
|
||||
aiProviderTypeLabelMap[
|
||||
@@ -305,6 +305,30 @@ export default function CreateAiProviderPage() {
|
||||
);
|
||||
targetsRef.current =
|
||||
[];
|
||||
} else {
|
||||
const isDefaultName =
|
||||
Object.entries(
|
||||
aiProviderTypeLabelMap
|
||||
).some(
|
||||
([
|
||||
type,
|
||||
key
|
||||
]) =>
|
||||
type !==
|
||||
"custom" &&
|
||||
currentName ===
|
||||
t(
|
||||
key
|
||||
)
|
||||
);
|
||||
if (
|
||||
isDefaultName
|
||||
) {
|
||||
form.setValue(
|
||||
"name",
|
||||
""
|
||||
);
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -86,6 +86,13 @@ export type ProxyResourceTargetsFormHandle = {
|
||||
save: (options?: { silent?: boolean }) => Promise<boolean>;
|
||||
};
|
||||
|
||||
const DEFAULT_ALLOWED_METHODS: ("http" | "https" | "h2c")[] = [
|
||||
"http",
|
||||
"https",
|
||||
"h2c"
|
||||
];
|
||||
const EMPTY_TARGETS: LocalTarget[] = [];
|
||||
|
||||
type ProxyResourceTargetsFormProps = {
|
||||
orgId: string;
|
||||
isHttp: boolean;
|
||||
@@ -115,12 +122,12 @@ export const ProxyResourceTargetsForm = forwardRef<
|
||||
{
|
||||
orgId,
|
||||
isHttp,
|
||||
initialTargets = [],
|
||||
initialTargets = EMPTY_TARGETS,
|
||||
resource,
|
||||
providerId,
|
||||
updateResource,
|
||||
onChange,
|
||||
allowedMethods = ["http", "https", "h2c"],
|
||||
allowedMethods = DEFAULT_ALLOWED_METHODS,
|
||||
emptyMessage,
|
||||
embedded = false,
|
||||
hideSaveButton = false,
|
||||
@@ -266,7 +273,7 @@ export const ProxyResourceTargetsForm = forwardRef<
|
||||
);
|
||||
});
|
||||
},
|
||||
[sites]
|
||||
[]
|
||||
);
|
||||
|
||||
const openHealthCheckDialog = useCallback((target: LocalTarget) => {
|
||||
@@ -616,7 +623,6 @@ export const ProxyResourceTargetsForm = forwardRef<
|
||||
}, [
|
||||
isAdvancedMode,
|
||||
isHttp,
|
||||
sites,
|
||||
updateTarget,
|
||||
getDockerStateForSite,
|
||||
refreshContainersForSite,
|
||||
|
||||
@@ -350,28 +350,24 @@ export function AiProviderModelListEditor({
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<div>
|
||||
<div className="relative">
|
||||
<div
|
||||
ref={gridRef}
|
||||
className={cn(
|
||||
"grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-3",
|
||||
isCollapsed && "overflow-hidden"
|
||||
)}
|
||||
style={
|
||||
isCollapsed && clipHeight != null
|
||||
? { maxHeight: clipHeight }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{items.length === 0 ? (
|
||||
<div className="flex min-w-0 items-center justify-center rounded-md border border-dashed border-input px-2.5 py-2">
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{emptyMessage}
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
items.map((item) => (
|
||||
{items.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground">{emptyMessage}</p>
|
||||
) : (
|
||||
<div>
|
||||
<div className="relative">
|
||||
<div
|
||||
ref={gridRef}
|
||||
className={cn(
|
||||
"grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-3",
|
||||
isCollapsed && "overflow-hidden"
|
||||
)}
|
||||
style={
|
||||
isCollapsed && clipHeight != null
|
||||
? { maxHeight: clipHeight }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{items.map((item) => (
|
||||
<ModelCard
|
||||
key={item.clientId}
|
||||
item={item}
|
||||
@@ -385,42 +381,42 @@ export function AiProviderModelListEditor({
|
||||
}
|
||||
onRemove={() => removeModel(item.clientId)}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
{isCollapsed ? (
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-14 bg-gradient-to-t from-card from-25% via-card/80 to-transparent" />
|
||||
) : null}
|
||||
</div>
|
||||
{isCollapsed ? (
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-14 bg-gradient-to-t from-card from-25% via-card/80 to-transparent" />
|
||||
<div className="relative z-10 flex justify-center pt-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="text"
|
||||
size="sm"
|
||||
className="bg-card px-2 text-muted-foreground hover:text-foreground"
|
||||
onClick={() => setListExpanded(true)}
|
||||
>
|
||||
{t("aiProviderModelsViewMore", {
|
||||
count: items.length - collapsedLimit
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
{hasOverflow && listExpanded ? (
|
||||
<div className="flex justify-center pt-1">
|
||||
<Button
|
||||
type="button"
|
||||
variant="text"
|
||||
size="sm"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
onClick={() => setListExpanded(false)}
|
||||
>
|
||||
{t("aiProviderModelsViewLess")}
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{isCollapsed ? (
|
||||
<div className="relative z-10 flex justify-center pt-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="text"
|
||||
size="sm"
|
||||
className="bg-card px-2 text-muted-foreground hover:text-foreground"
|
||||
onClick={() => setListExpanded(true)}
|
||||
>
|
||||
{t("aiProviderModelsViewMore", {
|
||||
count: items.length - collapsedLimit
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
{hasOverflow && listExpanded ? (
|
||||
<div className="flex justify-center pt-1">
|
||||
<Button
|
||||
type="button"
|
||||
variant="text"
|
||||
size="sm"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
onClick={() => setListExpanded(false)}
|
||||
>
|
||||
{t("aiProviderModelsViewLess")}
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Popover
|
||||
@@ -828,9 +824,7 @@ function EditModelCredenza({
|
||||
defaultValues: { modelKey: item.modelKey }
|
||||
});
|
||||
|
||||
const [pendingBudgetRows, setPendingBudgetRows] = useState<BudgetRow[]>(
|
||||
[]
|
||||
);
|
||||
const [pendingBudgetRows, setPendingBudgetRows] = useState<BudgetRow[]>([]);
|
||||
const [attemptedBudgetsSave, setAttemptedBudgetsSave] = useState(false);
|
||||
const [savingBudgets, setSavingBudgets] = useState(false);
|
||||
|
||||
@@ -929,9 +923,7 @@ function EditModelCredenza({
|
||||
items={[
|
||||
{ title: t("general"), href: "#" },
|
||||
{
|
||||
title: t(
|
||||
"aiProviderModelsBudgetTab"
|
||||
),
|
||||
title: t("aiProviderModelsBudgetTab"),
|
||||
href: "#"
|
||||
}
|
||||
]}
|
||||
@@ -970,9 +962,7 @@ function EditModelCredenza({
|
||||
</p>
|
||||
<BudgetRowsFields
|
||||
rows={pendingBudgetRows}
|
||||
onChange={
|
||||
setPendingBudgetRows
|
||||
}
|
||||
onChange={setPendingBudgetRows}
|
||||
disabled={
|
||||
budgetsQuery.isLoading ||
|
||||
savingBudgets
|
||||
@@ -984,9 +974,7 @@ function EditModelCredenza({
|
||||
</>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t(
|
||||
"aiProviderModelsBudgetUnsaved"
|
||||
)}
|
||||
{t("aiProviderModelsBudgetUnsaved")}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -573,7 +573,6 @@ export function PolicyAuthStackSectionEdit({
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
{inferenceResourceUrl}
|
||||
<ExternalLink className="ml-1 inline size-3.5 shrink-0 align-text-bottom" />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -142,6 +142,8 @@ export function ResourceTargetAddressItem({
|
||||
isHttp,
|
||||
allowedMethods = ["http", "https", "h2c"]
|
||||
}: ResourceTargetAddressItemProps) {
|
||||
"use no memo";
|
||||
|
||||
return (
|
||||
<div className="flex items-center w-full" key={proxyTarget.targetId}>
|
||||
<div className="flex items-center w-full justify-start py-0 space-x-2 px-0 cursor-default border border-input rounded-md">
|
||||
|
||||
Reference in New Issue
Block a user