diff --git a/src/components/resource-policy/PolicyAccessRulesTable.tsx b/src/components/resource-policy/PolicyAccessRulesTable.tsx index dba282342..f2d182c73 100644 --- a/src/components/resource-policy/PolicyAccessRulesTable.tsx +++ b/src/components/resource-policy/PolicyAccessRulesTable.tsx @@ -54,11 +54,15 @@ import { GripVertical, LockIcon } from "lucide-react"; +import { useCommandState } from "cmdk"; import { useTranslations } from "next-intl"; import { useCallback, + useEffect, useMemo, + useRef, useState, + type ComponentProps, type DragEvent, type ReactNode } from "react"; @@ -114,6 +118,36 @@ function getColumnClassName(columnId: string) { return ""; } +// cmdk keeps the list's scroll offset when the search text changes, so a +// filtered list can be left scrolled past its (few) matches and look empty. +// Jump back to the top whenever the search changes. +function ResettingCommandList(props: ComponentProps) { + const search = useCommandState((state) => state.search); + const listRef = useRef(null); + + useEffect(() => { + listRef.current?.scrollTo({ top: 0 }); + }, [search]); + + return ; +} + +// Plain case-insensitive substring match on the country name or code, with +// prefix matches ranked first. cmdk's default fuzzy scorer matches unrelated +// countries (e.g. "Russia") and buries the exact one. +function filterCountry(value: string, search: string, keywords?: string[]) { + const query = search.trim().toLowerCase(); + if (!query) { + return 1; + } + const name = value.toLowerCase(); + const code = keywords?.[0]?.toLowerCase() ?? ""; + if (name.startsWith(query) || code === query) { + return 1; + } + return name.includes(query) ? 0.5 : 0; +} + // A METHOD rule stores its methods as a comma-separated list in rule.value, // e.g. "POST,PUT". Only the common methods are offered here; a value set // through a blueprint or the API may contain other methods (the WebDAV verbs, @@ -155,7 +189,9 @@ function RuleMethodSelect({ className="w-full min-w-0 justify-between" > - {selected.length > 0 ? selected.join(", ") : placeholder} + {selected.length > 0 + ? selected.join(", ") + : placeholder} @@ -616,11 +652,11 @@ export function PolicyAccessRulesTable({ - + - + {t("noCountryFound")} @@ -629,6 +665,7 @@ export function PolicyAccessRulesTable({ updateRule( row.original.ruleId, @@ -653,7 +690,7 @@ export function PolicyAccessRulesTable({ ))} - + @@ -686,7 +723,7 @@ export function PolicyAccessRulesTable({ - + No ASN found. Enter a custom ASN below. @@ -714,7 +751,7 @@ export function PolicyAccessRulesTable({ ))} - +
- + {t("noRegionFound")} @@ -848,7 +885,7 @@ export function PolicyAccessRulesTable({ )} ))} - +