diff --git a/frontends/mdr-frontend/src/components/Dialog/Dialog.tsx b/frontends/mdr-frontend/src/components/Dialog/Dialog.tsx index 3893f71..af9f920 100644 --- a/frontends/mdr-frontend/src/components/Dialog/Dialog.tsx +++ b/frontends/mdr-frontend/src/components/Dialog/Dialog.tsx @@ -45,6 +45,7 @@ export interface DialogField { accept?: string; inputMode?: InputMode; pattern?: string; + patternErr?: string; } export interface DialogItem { @@ -92,6 +93,10 @@ export const CrudDialog: React.FC = ({ nextParams.BaseDataModelId = null; } } + // # Disabled pattern validation here; now handled on handleCreateOrEdit + // if (field.pattern && createParams[field.name] && !new RegExp(field.pattern).test(createParams[field.name])) { + // setCreateError(`The following fields have invalid values:\n > ${field.patternErr}`); + // } return nextParams; }); }; @@ -111,6 +116,12 @@ export const CrudDialog: React.FC = ({ setCreateError(`Please complete all required fields: ${missingFields.join(", ")}`); return; } + + const regexFields = fields.filter((f) => f.pattern && createParams[f.name] && !new RegExp(f.pattern).test(createParams[f.name])); + if (regexFields.length) { + setCreateError(`The following fields have invalid values:\n > ${regexFields.map(f => f.patternErr).join("\n > ")}`); + return; + } setDisableSubmitForm(true); if (isEditMode && itemToEdit) { @@ -228,7 +239,7 @@ export const CrudDialog: React.FC = ({ {createError && ( <>

- + {createError} @@ -298,6 +309,7 @@ export const CrudDialog: React.FC = ({ onChange={(e) => handleFieldValueChange(field, e.target.value) } inputMode={field.inputMode} pattern={field.pattern} + title={field.patternErr ?? ""} readOnly={field.readOnly || (isEditMode && field.name === "CreationDate")} /> )} diff --git a/frontends/mdr-frontend/src/components/ModelExplorer/CreateOptFields.tsx b/frontends/mdr-frontend/src/components/ModelExplorer/CreateOptFields.tsx index 9d60f66..afa127a 100644 --- a/frontends/mdr-frontend/src/components/ModelExplorer/CreateOptFields.tsx +++ b/frontends/mdr-frontend/src/components/ModelExplorer/CreateOptFields.tsx @@ -1,5 +1,8 @@ import { DialogField } from "../Dialog/Dialog"; + +const PatternRegex = "^[A-Za-z][A-Za-z0-9_./-]*$"; +const PatternErrStr = " must start with a letter and contain only letters, numbers, underscores, periods, hyphens, and forward slashes."; const capitalize = (s: string): string => { return s?.length ? s.charAt(0).toUpperCase() + s.slice(1) : ""; } /** Dev Note: Once we get actual user data we should use that for Contributor and ContributorOrganization */ @@ -13,12 +16,21 @@ export const entityCreateFields = (model: any): DialogField[] => { hidden: true, defaultValue: model?.Id, }, - { name: "Name", type: "text" as const, label: "Name", required: true }, + { + name: "Name", + type: "text" as const, + label: "Name", + required: true, + pattern: PatternRegex, + patternErr: "Name" + PatternErrStr, + }, { name: "UniqueName", type: "text" as const, label: "Unique Name", required: true, + pattern: PatternRegex, + patternErr: "Unique Name" + PatternErrStr, }, { name: "Description", type: "text" as const, label: "Description" }, { @@ -90,12 +102,21 @@ export const attributeCreateFields = (model: any, valueSetId: string | number | hidden: true, defaultValue: valueSetId?.toString(), }, - { name: "Name", type: "text" as const, label: "Name", required: true }, + { + name: "Name", + type: "text" as const, + label: "Name", + required: true, + pattern: PatternRegex, + patternErr: "Name" + PatternErrStr, + }, { name: "UniqueName", type: "text" as const, label: "Unique Name", required: true, + pattern: PatternRegex, + patternErr: "Unique Name" + PatternErrStr, }, { name: "DataType", @@ -173,7 +194,14 @@ export const valueSetCreateFields = (model: any): DialogField[] => { hidden: true, defaultValue: model?.Id, }, - { name: "Name", type: "text" as const, label: "Name", required: true }, + { + name: "Name", + type: "text" as const, + label: "Name", + required: true, + pattern: PatternRegex, + patternErr: "Name" + PatternErrStr, + }, { name: "Description", type: "text" as const, label: "Description" }, { name: "Use Considerations", @@ -223,6 +251,8 @@ export const valueCreateFields = (model: any): DialogField[] => { type: "text" as const, label: "Value Name", required: true, + pattern: PatternRegex, + patternErr: "Value Name" + PatternErrStr, }, { name: "Description", type: "text" as const, label: "Description" }, {