From c3fdda026b99de4be55ae1bea4faaba02af9bf1d Mon Sep 17 00:00:00 2001 From: Fred KISSIE Date: Thu, 19 Feb 2026 04:36:42 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20separate=20into=20diff=20c?= =?UTF-8?q?omponents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CreatePolicyForm.tsx | 2250 +++++++++++++-------------- 1 file changed, 1076 insertions(+), 1174 deletions(-) diff --git a/src/components/CreatePolicyForm.tsx b/src/components/CreatePolicyForm.tsx index 666c3b7ea..96154edfe 100644 --- a/src/components/CreatePolicyForm.tsx +++ b/src/components/CreatePolicyForm.tsx @@ -57,7 +57,7 @@ import { useEnvContext } from "@app/hooks/useEnvContext"; import { useOrgContext } from "@app/hooks/useOrgContext"; import { usePaidStatus } from "@app/hooks/usePaidStatus"; import { toast } from "@app/hooks/useToast"; -import { createApiClient } from "@app/lib/api"; + import { getUserDisplayName } from "@app/lib/getUserDisplayName"; import { orgQueries } from "@app/lib/queries"; import { zodResolver } from "@hookform/resolvers/zod"; @@ -91,11 +91,13 @@ import { Key } from "lucide-react"; import { useTranslations } from "next-intl"; -import { useRouter } from "next/navigation"; + import { useActionState, useCallback, useMemo, useState } from "react"; -import { useForm } from "react-hook-form"; +import { UseFormReturn, useForm } from "react-hook-form"; import z from "zod"; +// ─── Schemas & types ────────────────────────────────────────────────────────── + const addRuleSchema = z.object({ action: z.enum(["ACCEPT", "DROP", "PASS"]), match: z.string(), @@ -119,24 +121,9 @@ const createPolicySchema = z.object({ sso: z.boolean().default(true), skipToIdpId: z.number().nullable().optional(), emailWhitelistEnabled: z.boolean().default(false), - roles: z.array( - z.object({ - id: z.string(), - text: z.string() - }) - ), - users: z.array( - z.object({ - id: z.string(), - text: z.string() - }) - ), - emails: z.array( - z.object({ - id: z.string(), - text: z.string() - }) - ), + roles: z.array(z.object({ id: z.string(), text: z.string() })), + users: z.array(z.object({ id: z.string(), text: z.string() })), + emails: z.array(z.object({ id: z.string(), text: z.string() })), applyRules: z.boolean().default(false), rules: z .array( @@ -151,31 +138,31 @@ const createPolicySchema = z.object({ .default([]) }); +type PolicyFormValues = z.infer; + +// ─── CreatePolicyForm ───────────────────────────────────────────────────────── + export type CreatePolicyFormProps = {}; export function CreatePolicyForm({}: CreatePolicyFormProps) { const { org } = useOrgContext(); const t = useTranslations(); const { env } = useEnvContext(); - const api = createApiClient({ env }); const [, formAction, isSubmitting] = useActionState(onSubmit, null); - const router = useRouter(); const { isPaidUser } = usePaidStatus(); - const isMaxmindAvailable = - env.server.maxmind_db_path && env.server.maxmind_db_path.length > 0; - const isMaxmindAsnAvailable = - env.server.maxmind_asn_path && env.server.maxmind_asn_path.length > 0; + const isMaxmindAvailable = !!( + env.server.maxmind_db_path && env.server.maxmind_db_path.length > 0 + ); + const isMaxmindAsnAvailable = !!( + env.server.maxmind_asn_path && env.server.maxmind_asn_path.length > 0 + ); const { data: orgRoles = [], isLoading: isLoadingOrgRoles } = useQuery( - orgQueries.roles({ - orgId: org.org.orgId - }) + orgQueries.roles({ orgId: org.org.orgId }) ); const { data: orgUsers = [], isLoading: isLoadingOrgUsers } = useQuery( - orgQueries.users({ - orgId: org.org.orgId - }) + orgQueries.users({ orgId: org.org.orgId }) ); const { data: orgIdps = [], isLoading: isLoadingOrgIdps } = useQuery( orgQueries.identityProviders({ @@ -184,8 +171,8 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) { }) ); - const form = useForm({ - resolver: zodResolver(createPolicySchema), + const form = useForm({ + resolver: zodResolver(createPolicySchema) as any, defaultValues: { name: "", sso: true, @@ -199,8 +186,135 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) { } }); + async function onSubmit() { + // ... + } + + const allRoles = useMemo( + () => + orgRoles + .map((role) => ({ + id: role.roleId.toString(), + text: role.name + })) + .filter((role) => role.text !== "Admin"), + [orgRoles] + ); + + const allUsers = useMemo( + () => + orgUsers.map((user) => ({ + id: user.id.toString(), + text: `${getUserDisplayName({ email: user.email, username: user.username })}${user.type !== UserType.Internal ? ` (${user.idpName})` : ""}` + })), + [orgUsers] + ); + + const allIdps = useMemo(() => { + if (build === "saas") { + if (isPaidUser(tierMatrix.orgOidc)) { + return orgIdps.map((idp) => ({ + id: idp.idpId, + text: idp.name + })); + } + } else { + return orgIdps.map((idp) => ({ id: idp.idpId, text: idp.name })); + } + return []; + }, [orgIdps, isPaidUser]); + + if (isLoadingOrgRoles || isLoadingOrgUsers || isLoadingOrgIdps) { + return <>; + } + + return ( +
+ + + {/* Name */} + + + + {t("resourcePolicyName")} + + + {t("resourcePolicyNameDescription")} + + + + + ( + + {t("name")} + + + + + + )} + /> + + + + + + + + + + +
+ +
+
+ + ); +} + +// ─── PolicyUsersRolesSection ────────────────────────────────────────────────── + +type PolicyUsersRolesSectionProps = { + form: UseFormReturn; + allRoles: { id: string; text: string }[]; + allUsers: { id: string; text: string }[]; + allIdps: { id: number; text: string }[]; +}; + +function PolicyUsersRolesSection({ + form, + allRoles, + allUsers, + allIdps +}: PolicyUsersRolesSectionProps) { + const t = useTranslations(); const [ssoEnabled, setSsoEnabled] = useState(true); - const [whitelistEnabled, setWhitelistEnabled] = useState(false); const [selectedIdpId, setSelectedIdpId] = useState(null); const [activeRolesTagIndex, setActiveRolesTagIndex] = useState< number | null @@ -208,11 +322,364 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) { const [activeUsersTagIndex, setActiveUsersTagIndex] = useState< number | null >(null); + + return ( + + + + {t("resourceUsersRoles")} + + + {t("resourceUsersRolesDescription")} + + + + + { + setSsoEnabled(val); + form.setValue("sso", val); + }} + /> + + {ssoEnabled && ( + <> + ( + + {t("roles")} + + { + form.setValue( + "roles", + newRoles as [ + Tag, + ...Tag[] + ] + ); + }} + enableAutocomplete={true} + autocompleteOptions={allRoles} + allowDuplicates={false} + restrictTagsToAutocompleteOptions={ + true + } + sortTags={true} + /> + + + + {t("resourceRoleDescription")} + + + )} + /> + ( + + {t("users")} + + { + form.setValue( + "users", + newUsers as [ + Tag, + ...Tag[] + ] + ); + }} + enableAutocomplete={true} + autocompleteOptions={allUsers} + allowDuplicates={false} + restrictTagsToAutocompleteOptions={ + true + } + sortTags={true} + /> + + + + )} + /> + + )} + + {ssoEnabled && allIdps.length > 0 && ( +
+ + +

+ {t("defaultIdentityProviderDescription")} +

+
+ )} +
+
+
+ ); +} + +// ─── PolicyAuthMethodsSection ───────────────────────────────────────────────── + +function PolicyAuthMethodsSection() { + const t = useTranslations(); + return ( + + + + {t("resourceAuthMethods")} + + + {t("resourceAuthMethodsDescriptions")} + + + + +
+
+ + + {t("resourcePasswordProtection", { + status: t("disabled") + })} + +
+ +
+ +
+
+ + + {t("resourcePincodeProtection", { + status: t("disabled") + })} + +
+ +
+ +
+
+ + + {t("resourceHeaderAuthProtectionDisabled")} + +
+ +
+
+
+
+ ); +} + +// ─── PolicyOtpEmailSection ──────────────────────────────────────────────────── + +type PolicyOtpEmailSectionProps = { + form: UseFormReturn; + emailEnabled: boolean; +}; + +function PolicyOtpEmailSection({ + form, + emailEnabled +}: PolicyOtpEmailSectionProps) { + const t = useTranslations(); + const [whitelistEnabled, setWhitelistEnabled] = useState(false); const [activeEmailTagIndex, setActiveEmailTagIndex] = useState< number | null >(null); - // Rules state + return ( + + + + {t("otpEmailTitle")} + + + {t("otpEmailTitleDescription")} + + + + + {!emailEnabled && ( + + + + {t("otpEmailSmtpRequired")} + + + {t("otpEmailSmtpRequiredDescription")} + + + )} + { + setWhitelistEnabled(val); + form.setValue("emailWhitelistEnabled", val); + }} + disabled={!emailEnabled} + /> + + {whitelistEnabled && emailEnabled && ( + ( + + + + + + {/* @ts-ignore */} + { + return z + .email() + .or( + z + .string() + .regex( + /^\*@[\w.-]+\.[a-zA-Z]{2,}$/, + { + message: t( + "otpEmailErrorInvalid" + ) + } + ) + ) + .safeParse(tag).success; + }} + setActiveTagIndex={ + setActiveEmailTagIndex + } + placeholder={t("otpEmailEnter")} + tags={form.getValues().emails} + setTags={(newEmails) => { + form.setValue( + "emails", + newEmails as [Tag, ...Tag[]] + ); + }} + allowDuplicates={false} + sortTags={true} + /> + + + {t("otpEmailEnterDescription")} + + + )} + /> + )} + + + + ); +} + +// ─── PolicyRulesSection ─────────────────────────────────────────────────────── + +type PolicyRulesSectionProps = { + form: UseFormReturn; + isMaxmindAvailable: boolean; + isMaxmindAsnAvailable: boolean; +}; + +function PolicyRulesSection({ + form, + isMaxmindAvailable, + isMaxmindAsnAvailable +}: PolicyRulesSectionProps) { + const t = useTranslations(); const [rules, setRules] = useState([]); const [rulesEnabled, setRulesEnabled] = useState(false); const [openAddRuleCountrySelect, setOpenAddRuleCountrySelect] = @@ -228,195 +695,162 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) { } }); - const RuleAction = useMemo(() => { - return { + const RuleAction = useMemo( + () => ({ ACCEPT: t("alwaysAllow"), DROP: t("alwaysDeny"), PASS: t("passToAuth") - } as const; - }, [t]); + }), + [t] + ); - const RuleMatch = useMemo(() => { - return { + const RuleMatch = useMemo( + () => ({ PATH: t("path"), IP: "IP", CIDR: t("ipAddressRange"), COUNTRY: t("country"), ASN: "ASN" - } as const; - }, [t]); + }), + [t] + ); - async function onSubmit() { - // ... - } - - const addRule = useCallback(function addRule(data: z.infer) { - const isDuplicate = rules.some( - (rule) => - rule.action === data.action && - rule.match === data.match && - rule.value === data.value - ); - - if (isDuplicate) { - toast({ - variant: "destructive", - title: t("rulesErrorDuplicate"), - description: t("rulesErrorDuplicateDescription") - }); - return; - } - - if (data.match === "CIDR" && !isValidCIDR(data.value)) { - toast({ - variant: "destructive", - title: t("rulesErrorInvalidIpAddressRange"), - description: t("rulesErrorInvalidIpAddressRangeDescription") - }); - return; - } - if (data.match === "PATH" && !isValidUrlGlobPattern(data.value)) { - toast({ - variant: "destructive", - title: t("rulesErrorInvalidUrl"), - description: t("rulesErrorInvalidUrlDescription") - }); - return; - } - if (data.match === "IP" && !isValidIP(data.value)) { - toast({ - variant: "destructive", - title: t("rulesErrorInvalidIpAddress"), - description: t("rulesErrorInvalidIpAddressDescription") - }); - return; - } - if ( - data.match === "COUNTRY" && - !COUNTRIES.some((c) => c.code === data.value) - ) { - toast({ - variant: "destructive", - title: t("rulesErrorInvalidCountry"), - description: t("rulesErrorInvalidCountryDescription") || "" - }); - return; - } - - let priority = data.priority; - if (priority === undefined) { - priority = rules.reduce( - (acc, rule) => (rule.priority > acc ? rule.priority : acc), - 0 + const syncFormRules = useCallback( + (updatedRules: LocalRule[]) => { + form.setValue( + "rules", + updatedRules.map( + ({ action, match, value, priority, enabled }) => ({ + action, + match, + value, + priority, + enabled + }) + ) ); - priority++; - } + }, + [form] + ); - const newRule: LocalRule = { - ...data, - ruleId: new Date().getTime(), - new: true, - priority, - enabled: true - }; - - const updatedRules = [...rules, newRule]; - setRules(updatedRules); - form.setValue( - "rules", - updatedRules.map(({ action, match, value, priority, enabled }) => ({ - action, - match, - value, - priority, - enabled - })) - ); - addRuleForm.reset(); - }, [rules, t, form, addRuleForm]); - - const removeRule = useCallback(function removeRule(ruleId: number) { - const updatedRules = rules.filter((rule) => rule.ruleId !== ruleId); - setRules(updatedRules); - form.setValue( - "rules", - updatedRules.map(({ action, match, value, priority, enabled }) => ({ - action, - match, - value, - priority, - enabled - })) - ); - }, [rules, form]); - - const updateRule = useCallback(function updateRule(ruleId: number, data: Partial) { - const updatedRules = rules.map((rule) => - rule.ruleId === ruleId ? { ...rule, ...data, updated: true } : rule - ); - setRules(updatedRules); - form.setValue( - "rules", - updatedRules.map(({ action, match, value, priority, enabled }) => ({ - action, - match, - value, - priority, - enabled - })) - ); - }, [rules, form]); - - const getValueHelpText = useCallback(function getValueHelpText(type: string) { - switch (type) { - case "CIDR": - return t("rulesMatchIpAddressRangeDescription"); - case "IP": - return t("rulesMatchIpAddress"); - case "PATH": - return t("rulesMatchUrl"); - case "COUNTRY": - return t("rulesMatchCountry"); - case "ASN": - return "Enter an Autonomous System Number (e.g., AS15169 or 15169)"; - } - }, [t]); - - const allRoles = useMemo(() => { - return orgRoles - .map((role) => ({ - id: role.roleId.toString(), - text: role.name - })) - .filter((role) => role.text !== "Admin"); - }, [orgRoles]); - - const allUsers = useMemo(() => { - return orgUsers.map((user) => ({ - id: user.id.toString(), - text: `${getUserDisplayName({ - email: user.email, - username: user.username - })}${user.type !== UserType.Internal ? ` (${user.idpName})` : ""}` - })); - }, [orgUsers]); - - const allIdps = useMemo(() => { - if (build === "saas") { - if (isPaidUser(tierMatrix.orgOidc)) { - return orgIdps.map((idp) => ({ - id: idp.idpId, - text: idp.name - })); + const addRule = useCallback( + function addRule(data: z.infer) { + const isDuplicate = rules.some( + (rule) => + rule.action === data.action && + rule.match === data.match && + rule.value === data.value + ); + if (isDuplicate) { + toast({ + variant: "destructive", + title: t("rulesErrorDuplicate"), + description: t("rulesErrorDuplicateDescription") + }); + return; } - } else { - return orgIdps.map((idp) => ({ - id: idp.idpId, - text: idp.name - })); - } - return []; - }, [orgIdps]); + if (data.match === "CIDR" && !isValidCIDR(data.value)) { + toast({ + variant: "destructive", + title: t("rulesErrorInvalidIpAddressRange"), + description: t("rulesErrorInvalidIpAddressRangeDescription") + }); + return; + } + if (data.match === "PATH" && !isValidUrlGlobPattern(data.value)) { + toast({ + variant: "destructive", + title: t("rulesErrorInvalidUrl"), + description: t("rulesErrorInvalidUrlDescription") + }); + return; + } + if (data.match === "IP" && !isValidIP(data.value)) { + toast({ + variant: "destructive", + title: t("rulesErrorInvalidIpAddress"), + description: t("rulesErrorInvalidIpAddressDescription") + }); + return; + } + if ( + data.match === "COUNTRY" && + !COUNTRIES.some((c) => c.code === data.value) + ) { + toast({ + variant: "destructive", + title: t("rulesErrorInvalidCountry"), + description: t("rulesErrorInvalidCountryDescription") || "" + }); + return; + } + + let priority = data.priority; + if (priority === undefined) { + priority = + rules.reduce( + (acc, rule) => + rule.priority > acc ? rule.priority : acc, + 0 + ) + 1; + } + + const updatedRules = [ + ...rules, + { + ...data, + ruleId: new Date().getTime(), + new: true, + priority, + enabled: true + } + ]; + setRules(updatedRules); + syncFormRules(updatedRules); + addRuleForm.reset(); + }, + [rules, t, addRuleForm, syncFormRules] + ); + + const removeRule = useCallback( + function removeRule(ruleId: number) { + const updatedRules = rules.filter((rule) => rule.ruleId !== ruleId); + setRules(updatedRules); + syncFormRules(updatedRules); + }, + [rules, syncFormRules] + ); + + const updateRule = useCallback( + function updateRule(ruleId: number, data: Partial) { + const updatedRules = rules.map((rule) => + rule.ruleId === ruleId + ? { ...rule, ...data, updated: true } + : rule + ); + setRules(updatedRules); + syncFormRules(updatedRules); + }, + [rules, syncFormRules] + ); + + const getValueHelpText = useCallback( + function getValueHelpText(type: string) { + switch (type) { + case "CIDR": + return t("rulesMatchIpAddressRangeDescription"); + case "IP": + return t("rulesMatchIpAddress"); + case "PATH": + return t("rulesMatchUrl"); + case "COUNTRY": + return t("rulesMatchCountry"); + case "ASN": + return "Enter an Autonomous System Number (e.g., AS15169 or 15169)"; + } + }, + [t] + ); const columns: ColumnDef[] = useMemo( () => [ @@ -550,9 +984,8 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) { > {row.original.value ? COUNTRIES.find( - (country) => - country.code === - row.original.value + (c) => + c.code === row.original.value )?.name + " (" + row.original.value + @@ -575,23 +1008,17 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) { { + onSelect={() => updateRule( row.original.ruleId, { value: country.code } - ); - }} + ) + } > {country.name} ( {country.code}) @@ -642,21 +1069,15 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) { " " + asn.code } - onSelect={() => { + onSelect={() => updateRule( row.original.ruleId, { value: asn.code } - ); - }} + ) + } > {asn.name} ({asn.code}) @@ -752,958 +1173,439 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) { getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), - state: { - pagination: { - pageIndex: 0, - pageSize: 1000 - } - } + state: { pagination: { pageIndex: 0, pageSize: 1000 } } }); - const pageLoading = - isLoadingOrgRoles || isLoadingOrgUsers || isLoadingOrgIdps; - - if (pageLoading) { - return <>; - } - return ( -
- - - {/* Name */} - - - - {t("resourcePolicyName")} - - - {t("resourcePolicyNameDescription")} - - - - + + + + {t("rulesResource")} + + + {t("rulesResourceDescription")} + + + +
+
+ { + setRulesEnabled(val); + form.setValue("applyRules", val); + }} + /> +
+ + + +
( - {t("name")} + + {t("rulesAction")} + - + )} /> - - - - - {/* Users & Roles */} - - - - {t("resourceUsersRoles")} - - - {t("resourceUsersRolesDescription")} - - - - - { - setSsoEnabled(val); - form.setValue("sso", val); - }} - /> - - {ssoEnabled && ( - <> - ( - - - {t("roles")} - - - { - form.setValue( - "roles", - newRoles as [ - Tag, - ...Tag[] - ] - ); - }} - enableAutocomplete={ - true - } - autocompleteOptions={ - allRoles - } - allowDuplicates={ - false - } - restrictTagsToAutocompleteOptions={ - true - } - sortTags={true} - /> - - - - {t( - "resourceRoleDescription" - )} - - - )} - /> - ( - - - {t("users")} - - - { - form.setValue( - "users", - newUsers as [ - Tag, - ...Tag[] - ] - ); - }} - enableAutocomplete={ - true - } - autocompleteOptions={ - allUsers - } - allowDuplicates={ - false - } - restrictTagsToAutocompleteOptions={ - true - } - sortTags={true} - /> - - - - )} - /> - - )} - - {ssoEnabled && allIdps.length > 0 && ( -
- - -

- {t( - "defaultIdentityProviderDescription" - )} -

-
- )} -
-
-
- - {/* Auth Methods */} - - - - {t("resourceAuthMethods")} - - - {t("resourceAuthMethodsDescriptions")} - - - - -
-
- - - {t("resourcePasswordProtection", { - status: t("disabled") - })} - -
- -
- -
-
- - - {t("resourcePincodeProtection", { - status: t("disabled") - })} - -
- -
- -
-
- - - {t( - "resourceHeaderAuthProtectionDisabled" - )} - -
- -
-
-
-
- - {/* OTP Email */} - - - - {t("otpEmailTitle")} - - - {t("otpEmailTitleDescription")} - - - - - {!env.email.emailEnabled && ( - - - - {t("otpEmailSmtpRequired")} - - - {t( - "otpEmailSmtpRequiredDescription" - )} - - - )} - { - setWhitelistEnabled(val); - form.setValue( - "emailWhitelistEnabled", - val - ); - }} - disabled={!env.email.emailEnabled} - /> - - {whitelistEnabled && env.email.emailEnabled && ( - ( - - - - - - {/* @ts-ignore */} - { - return z - .email() - .or( - z - .string() - .regex( - /^\*@[\w.-]+\.[a-zA-Z]{2,}$/, - { - message: - t( - "otpEmailErrorInvalid" - ) - } - ) - ) - .safeParse(tag) - .success; - }} - setActiveTagIndex={ - setActiveEmailTagIndex - } - placeholder={t( - "otpEmailEnter" - )} - tags={ - form.getValues() - .emails - } - setTags={( - newEmails - ) => { - form.setValue( - "emails", - newEmails as [ - Tag, - ...Tag[] - ] - ); - }} - allowDuplicates={false} - sortTags={true} - /> - - - {t( - "otpEmailEnterDescription" - )} - - - )} - /> - )} - - - - - {/* Rules */} - - - - {t("rulesResource")} - - - {t("rulesResourceDescription")} - - - -
-
- { - setRulesEnabled(val); - form.setValue("applyRules", val); - }} - /> -
- - - -
- ( - - - {t("rulesAction")} - - - - - - - )} - /> - ( - - - {t( - "rulesMatchType" - )} - - - - - - - )} - /> - ( - - - - {addRuleForm.watch( - "match" - ) === "COUNTRY" ? ( - - - - - - - - - - {t( - "noCountryFound" - )} - - - {COUNTRIES.map( - ( - country - ) => ( - { - field.onChange( - country.code - ); - setOpenAddRuleCountrySelect( - false - ); - }} - > - - { - country.name - }{" "} - ( - { - country.code - } - - ) - - ) - )} - - - - - - ) : addRuleForm.watch( - "match" - ) === "ASN" ? ( - - - - - - - - - - No - ASN - found. - Use - the - custom - input - below. - - - {MAJOR_ASNS.map( - ( - asn - ) => ( - { - field.onChange( - asn.code - ); - setOpenAddRuleAsnSelect( - false - ); - }} - > - - { - asn.name - }{" "} - ( - { - asn.code - } - - ) - - ) - )} - - - -
- { - if ( - e.key === - "Enter" - ) { - const value = - e.currentTarget.value - .toUpperCase() - .replace( - /^AS/, - "" - ); - if ( - /^\d+$/.test( - value - ) - ) { - field.onChange( - "AS" + - value - ); - setOpenAddRuleAsnSelect( - false - ); - } - } - }} - className="text-sm" - /> -
-
-
- ) : ( - - )} -
- -
- )} - /> - -
- - - - - - {table - .getHeaderGroups() - .map((headerGroup) => ( - - {headerGroup.headers.map( - (header) => { - const isActionsColumn = - header.column - .id === - "actions"; - return ( - - {header.isPlaceholder - ? null - : flexRender( - header - .column - .columnDef - .header, - header.getContext() - )} - - ); - } - )} - - ))} - - - {table.getRowModel().rows?.length ? ( - table - .getRowModel() - .rows.map((row) => ( - - {row - .getVisibleCells() - .map((cell) => { - const isActionsColumn = - cell.column - .id === - "actions"; - return ( - - {flexRender( - cell - .column - .columnDef - .cell, - cell.getContext() - )} - - ); - })} - - )) - ) : ( - - ( + + + {t("rulesMatchType")} + + +
-
-
-
- + + + + + + {RuleMatch.PATH} + + + {RuleMatch.IP} + + + {RuleMatch.CIDR} + + {isMaxmindAvailable && ( + + { + RuleMatch.COUNTRY + } + + )} + {isMaxmindAsnAvailable && ( + + {RuleMatch.ASN} + + )} + + + + + + )} + /> + ( + + + + {addRuleForm.watch("match") === + "COUNTRY" ? ( + + + + + + + + + + {t( + "noCountryFound" + )} + + + {COUNTRIES.map( + ( + country + ) => ( + { + field.onChange( + country.code + ); + setOpenAddRuleCountrySelect( + false + ); + }} + > + + { + country.name + }{" "} + ( + { + country.code + } -
- + ) + + ) + )} + + + + + + ) : addRuleForm.watch( + "match" + ) === "ASN" ? ( + + + + + + + + + + No ASN + found. + Use the + custom + input + below. + + + {MAJOR_ASNS.map( + ( + asn + ) => ( + { + field.onChange( + asn.code + ); + setOpenAddRuleAsnSelect( + false + ); + }} + > + + { + asn.name + }{" "} + ( + { + asn.code + } + + ) + + ) + )} + + + +
+ { + if ( + e.key === + "Enter" + ) { + const value = + e.currentTarget.value + .toUpperCase() + .replace( + /^AS/, + "" + ); + if ( + /^\d+$/.test( + value + ) + ) { + field.onChange( + "AS" + + value + ); + setOpenAddRuleAsnSelect( + false + ); + } + } + }} + className="text-sm" + /> +
+
+
+ ) : ( + + )} + + + + )} + /> + +
+ + + + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + const isActionsColumn = + header.column.id === "actions"; + return ( + + {header.isPlaceholder + ? null + : flexRender( + header.column + .columnDef.header, + header.getContext() + )} + + ); + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => { + const isActionsColumn = + cell.column.id === "actions"; + return ( + + {flexRender( + cell.column.columnDef + .cell, + cell.getContext() + )} + + ); + })} + + )) + ) : ( + + + {t("rulesNoOne")} + + + )} + +
- - + + ); }