feats(domain): configurable limit configs
This commit is contained in:
@@ -80,6 +80,9 @@ export function DomainForm({
|
||||
cf_record_types: initData?.cf_record_types || "CNAME,A,TXT",
|
||||
cf_api_key_encrypted: initData?.cf_api_key_encrypted || false,
|
||||
resend_api_key: initData?.resend_api_key || "",
|
||||
min_url_length: initData?.min_url_length,
|
||||
min_email_length: initData?.min_email_length,
|
||||
min_record_length: initData?.min_record_length,
|
||||
max_short_links: initData?.max_short_links || 0,
|
||||
max_email_forwards: initData?.max_email_forwards || 0,
|
||||
max_dns_records: initData?.max_dns_records || 0,
|
||||
@@ -549,6 +552,64 @@ export function DomainForm({
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
|
||||
<Collapsible className="relative mt-2 rounded-md bg-neutral-100 p-4 dark:bg-neutral-800">
|
||||
<CollapsibleTrigger className="flex w-full items-center justify-between">
|
||||
<h2 className="absolute left-2 top-4 flex gap-2 text-xs font-semibold text-neutral-400">
|
||||
{t("Limit Configs")} ({t("Optional")})
|
||||
</h2>
|
||||
<Icons.chevronDown className="ml-auto size-4" />
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent className="mt-3 space-y-2">
|
||||
<div className="flex w-full items-center justify-between gap-2">
|
||||
<Label className="cursor-pointer" htmlFor="min_url_length">
|
||||
{t("Min URL Length")}:
|
||||
</Label>
|
||||
<Input
|
||||
id="target"
|
||||
className="max-w-20 flex-1 bg-neutral-50 shadow-inner"
|
||||
size={32}
|
||||
type="number"
|
||||
defaultValue={initData?.min_url_length ?? 3}
|
||||
{...register("min_url_length", {
|
||||
valueAsNumber: true,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex w-full items-center justify-between gap-2">
|
||||
<Label className="cursor-pointer" htmlFor="min_email_length">
|
||||
{t("Min Email Length")}:
|
||||
</Label>
|
||||
<Input
|
||||
id="target"
|
||||
className="max-w-20 flex-1 bg-neutral-50 shadow-inner"
|
||||
size={32}
|
||||
type="number"
|
||||
defaultValue={initData?.min_email_length ?? 3}
|
||||
{...register("min_email_length", {
|
||||
valueAsNumber: true,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex w-full items-center justify-between gap-2">
|
||||
<Label className="cursor-pointer" htmlFor="min_subdomain_length">
|
||||
{t("Min Subdomain Length")}:
|
||||
</Label>
|
||||
<Input
|
||||
id="target"
|
||||
className="max-w-20 flex-1 bg-neutral-50 shadow-inner"
|
||||
size={32}
|
||||
type="number"
|
||||
defaultValue={initData?.min_record_length ?? 3}
|
||||
{...register("min_record_length", {
|
||||
valueAsNumber: true,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
|
||||
{/* Action buttons */}
|
||||
<div className="mt-3 flex justify-end gap-3">
|
||||
{type === "edit" && (
|
||||
|
||||
@@ -66,6 +66,7 @@ export function RecordForm({
|
||||
initData?.type || "CNAME",
|
||||
);
|
||||
const [currentZoneName, setCurrentZoneName] = useState(initData?.zone_name);
|
||||
const [limitLen, setLimitLen] = useState(3);
|
||||
const [email, setEmail] = useState(initData?.user.email || user.email);
|
||||
const [allowedRecordTypes, setAllowedRecordTypes] = useState<string[]>([]);
|
||||
const isAdmin = action.indexOf("admin") > -1;
|
||||
@@ -93,7 +94,11 @@ export function RecordForm({
|
||||
|
||||
// Fetch the record domains
|
||||
const { data: recordDomains, isLoading } = useSWR<
|
||||
{ domain_name: string; cf_record_types: string }[]
|
||||
{
|
||||
domain_name: string;
|
||||
cf_record_types: string;
|
||||
min_record_length: number;
|
||||
}[]
|
||||
>("/api/domain?feature=record", fetcher, {
|
||||
revalidateOnFocus: false,
|
||||
dedupingInterval: 10000,
|
||||
@@ -131,6 +136,10 @@ export function RecordForm({
|
||||
.find((d) => d.domain_name === validDefaultDomain)!
|
||||
.cf_record_types.split(","),
|
||||
);
|
||||
setLimitLen(
|
||||
recordDomains.find((d) => d.domain_name === currentZoneName)
|
||||
?.min_record_length || 3,
|
||||
);
|
||||
}
|
||||
}, [currentZoneName, recordDomains, validDefaultDomain]);
|
||||
|
||||
@@ -413,6 +422,7 @@ export function RecordForm({
|
||||
id="name"
|
||||
className="flex-1 shadow-inner"
|
||||
size={32}
|
||||
minLength={limitLen}
|
||||
{...register("name")}
|
||||
/>
|
||||
{["CNAME", "A", "AAAA"].includes(currentRecordType) && (
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
SetStateAction,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
useTransition,
|
||||
} from "react";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@@ -58,6 +59,8 @@ export function UrlForm({
|
||||
}: RecordFormProps) {
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const [isDeleting, startDeleteTransition] = useTransition();
|
||||
const [currentPrefix, setCurrentPrefix] = useState(initData?.prefix || "");
|
||||
const [limitLen, setLimitLen] = useState(3);
|
||||
const t = useTranslations("List");
|
||||
|
||||
const {
|
||||
@@ -79,14 +82,12 @@ export function UrlForm({
|
||||
},
|
||||
});
|
||||
|
||||
const { data: shortDomains, isLoading } = useSWR<{ domain_name: string }[]>(
|
||||
"/api/domain?feature=short",
|
||||
fetcher,
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
dedupingInterval: 10000,
|
||||
},
|
||||
);
|
||||
const { data: shortDomains, isLoading } = useSWR<
|
||||
{ domain_name: string; min_url_length: number }[]
|
||||
>("/api/domain?feature=short", fetcher, {
|
||||
revalidateOnFocus: false,
|
||||
dedupingInterval: 10000,
|
||||
});
|
||||
|
||||
const validDefaultDomain = useMemo(() => {
|
||||
if (!shortDomains?.length) return undefined;
|
||||
@@ -104,9 +105,17 @@ export function UrlForm({
|
||||
useEffect(() => {
|
||||
if (validDefaultDomain) {
|
||||
setValue("prefix", validDefaultDomain);
|
||||
setCurrentPrefix(validDefaultDomain);
|
||||
}
|
||||
}, [validDefaultDomain]);
|
||||
|
||||
useEffect(() => {
|
||||
setLimitLen(
|
||||
shortDomains?.find((d) => d.domain_name === currentPrefix)
|
||||
?.min_url_length || 3,
|
||||
);
|
||||
}, [currentPrefix]);
|
||||
|
||||
const onSubmit = handleSubmit((data) => {
|
||||
if (type === "add") {
|
||||
handleCreateUrl(data);
|
||||
@@ -233,6 +242,7 @@ export function UrlForm({
|
||||
<Select
|
||||
onValueChange={(value: string) => {
|
||||
setValue("prefix", value);
|
||||
setCurrentPrefix(value);
|
||||
}}
|
||||
name="prefix"
|
||||
defaultValue={validDefaultDomain}
|
||||
@@ -260,6 +270,7 @@ export function UrlForm({
|
||||
id="url"
|
||||
className="w-full rounded-none pl-[8px] shadow-inner"
|
||||
size={20}
|
||||
minLength={limitLen}
|
||||
{...register("url")}
|
||||
disabled={type === "edit"}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user