Don't allow # in face name

This commit is contained in:
Nicolas Mowen 2026-01-31 07:21:20 -07:00
parent aaa61ae2e0
commit ac6dda370d
5 changed files with 19 additions and 1 deletions

View File

@ -2,7 +2,8 @@
"description": { "description": {
"addFace": "Add a new collection to the Face Library by uploading your first image.", "addFace": "Add a new collection to the Face Library by uploading your first image.",
"placeholder": "Enter a name for this collection", "placeholder": "Enter a name for this collection",
"invalidName": "Invalid name. Names can only include letters, numbers, spaces, apostrophes, underscores, and hyphens." "invalidName": "Invalid name. Names can only include letters, numbers, spaces, apostrophes, underscores, and hyphens.",
"nameCannotContainHash": "Name cannot contain #."
}, },
"details": { "details": {
"timestamp": "Timestamp", "timestamp": "Timestamp",

View File

@ -20,6 +20,8 @@ type TextEntryProps = {
children?: React.ReactNode; children?: React.ReactNode;
regexPattern?: RegExp; regexPattern?: RegExp;
regexErrorMessage?: string; regexErrorMessage?: string;
forbiddenPattern?: RegExp;
forbiddenErrorMessage?: string;
}; };
export default function TextEntry({ export default function TextEntry({
@ -30,11 +32,16 @@ export default function TextEntry({
children, children,
regexPattern, regexPattern,
regexErrorMessage = "Input does not match the required format", regexErrorMessage = "Input does not match the required format",
forbiddenPattern,
forbiddenErrorMessage = "Input contains invalid characters",
}: TextEntryProps) { }: TextEntryProps) {
const formSchema = z.object({ const formSchema = z.object({
text: z text: z
.string() .string()
.optional() .optional()
.refine((val) => !val || !forbiddenPattern?.test(val), {
message: forbiddenErrorMessage,
})
.refine( .refine(
(val) => { (val) => {
if (!allowEmpty && !val) return false; if (!allowEmpty && !val) return false;

View File

@ -128,6 +128,8 @@ export default function CreateFaceWizardDialog({
}} }}
regexPattern={/^[\p{L}\p{N}\s'_-]{1,50}$/u} regexPattern={/^[\p{L}\p{N}\s'_-]{1,50}$/u}
regexErrorMessage={t("description.invalidName")} regexErrorMessage={t("description.invalidName")}
forbiddenPattern={/#/}
forbiddenErrorMessage={t("description.nameCannotContainHash")}
> >
<div className="flex justify-end py-2"> <div className="flex justify-end py-2">
<Button variant="select" type="submit"> <Button variant="select" type="submit">

View File

@ -22,6 +22,8 @@ type TextEntryDialogProps = {
allowEmpty?: boolean; allowEmpty?: boolean;
regexPattern?: RegExp; regexPattern?: RegExp;
regexErrorMessage?: string; regexErrorMessage?: string;
forbiddenPattern?: RegExp;
forbiddenErrorMessage?: string;
}; };
export default function TextEntryDialog({ export default function TextEntryDialog({
@ -34,6 +36,8 @@ export default function TextEntryDialog({
allowEmpty = false, allowEmpty = false,
regexPattern, regexPattern,
regexErrorMessage, regexErrorMessage,
forbiddenPattern,
forbiddenErrorMessage,
}: TextEntryDialogProps) { }: TextEntryDialogProps) {
const { t } = useTranslation("common"); const { t } = useTranslation("common");
@ -50,6 +54,8 @@ export default function TextEntryDialog({
onSave={onSave} onSave={onSave}
regexPattern={regexPattern} regexPattern={regexPattern}
regexErrorMessage={regexErrorMessage} regexErrorMessage={regexErrorMessage}
forbiddenPattern={forbiddenPattern}
forbiddenErrorMessage={forbiddenErrorMessage}
> >
<DialogFooter className={cn("pt-4", isMobile && "gap-2")}> <DialogFooter className={cn("pt-4", isMobile && "gap-2")}>
<Button type="button" onClick={() => setOpen(false)}> <Button type="button" onClick={() => setOpen(false)}>

View File

@ -560,6 +560,8 @@ function LibrarySelector({
defaultValue={renameFace || ""} defaultValue={renameFace || ""}
regexPattern={/^[\p{L}\p{N}\s'_-]{1,50}$/u} regexPattern={/^[\p{L}\p{N}\s'_-]{1,50}$/u}
regexErrorMessage={t("description.invalidName")} regexErrorMessage={t("description.invalidName")}
forbiddenPattern={/#/}
forbiddenErrorMessage={t("description.nameCannotContainHash")}
/> />
<DropdownMenu modal={false}> <DropdownMenu modal={false}>