From f55c67fe2e89d125b81e3f1b44e1dbc2626b1d3d Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Wed, 6 Sep 2023 12:20:10 +0200 Subject: [PATCH] 1-1334: show short error message when validation fails (#4617) The error message only tells the user that the name doesn't match the pattern. Because we already show the pattern above the input, we don't need to repeat it in the error message. This makes for a shorter and more concise message and better UX. At the same time, for API users, we can keep the more detailed message that includes info about the pattern, the example, and the description. ![image](https://github.com/Unleash/unleash/assets/17786332/0492f2ad-810d-435e-bfe6-785afee96892) --- src/lib/error/pattern-error.ts | 17 ++++++++++------- src/lib/services/feature-toggle-service.ts | 12 +++++++++--- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/lib/error/pattern-error.ts b/src/lib/error/pattern-error.ts index 53da023a16..2f24f6e6d1 100644 --- a/src/lib/error/pattern-error.ts +++ b/src/lib/error/pattern-error.ts @@ -1,18 +1,21 @@ -import BadDataError from './bad-data-error'; -import { ApiErrorSchema } from './unleash-error'; +import { ApiErrorSchema, UnleashError } from './unleash-error'; -class PatternError extends BadDataError { - pattern: string; +class PatternError extends UnleashError { + statusCode = 400; - constructor(message: string, pattern: string) { + details?: { message: string }[]; + + constructor(message: string, details?: string[]) { super(message); - this.pattern = pattern; + this.details = details?.map((description) => ({ + message: description, + })); } toJSON(): ApiErrorSchema { return { ...super.toJSON(), - pattern: this.pattern, + details: this.details, }; } } diff --git a/src/lib/services/feature-toggle-service.ts b/src/lib/services/feature-toggle-service.ts index 26828e0482..0c1c30667f 100644 --- a/src/lib/services/feature-toggle-service.ts +++ b/src/lib/services/feature-toggle-service.ts @@ -1099,16 +1099,22 @@ class FeatureToggleService { const project = await this.projectStore.get(projectId); const namingPattern = project.featureNaming?.pattern; const namingExample = project.featureNaming?.example; + const namingDescription = project.featureNaming?.description; if ( namingPattern && !featureName.match(new RegExp(namingPattern)) ) { - const error = `The feature flag name "${featureName}" does not match the project's naming pattern: "${namingPattern}.`; + const error = `The feature flag name "${featureName}" does not match the project's naming pattern: "${namingPattern}".`; const example = namingExample - ? ` Here's an example of a name that does match the pattern: "${namingExample}. Try something like that instead."` + ? ` Here's an example of a name that does match the pattern: "${namingExample}"."` : ''; - throw new PatternError(`${error}${example}`, namingPattern); + const description = namingDescription + ? ` The pattern's description is: "${namingDescription}"` + : ''; + throw new PatternError(`${error}${example}${description}`, [ + `The flag name does not match the pattern.`, + ]); } } }