surface errors in UI

This commit is contained in:
Johannes
2025-11-26 16:27:19 +01:00
parent dfa1c3e375
commit a384743751
3 changed files with 43 additions and 14 deletions

View File

@@ -323,7 +323,10 @@ export const validateSurveyImportAction = authenticatedActionClient
if ("error" in parseResult) {
return {
valid: false,
errors: [parseResult.error],
errors:
parseResult.details && parseResult.details.length > 0
? [parseResult.error, ...parseResult.details]
: [parseResult.error],
warnings: [],
infos: [],
surveyName: parsedInput.surveyData.name || "",
@@ -428,9 +431,10 @@ export const importSurveyAction = authenticatedActionClient
// Step 1: Parse and validate survey payload
const parseResult = parseSurveyPayload(parsedInput.surveyData);
if ("error" in parseResult) {
const errorMessage = parseResult.details
? `${parseResult.error}:\n${parseResult.details.join("\n")}`
: parseResult.error;
const errorMessage =
parseResult.details && parseResult.details.length > 0
? `${parseResult.error}:\n${parseResult.details.join("\n")}`
: parseResult.error;
throw new Error(`Validation failed: ${errorMessage}`);
}
const { surveyInput, exportedLanguages, triggers } = parseResult;

View File

@@ -244,11 +244,27 @@ export const ImportSurveyModal = ({ environmentId, open, setOpen }: ImportSurvey
{validationErrors.length > 0 && (
<Alert variant="error">
<AlertTitle>{t("environments.surveys.import_survey_errors")}</AlertTitle>
<AlertDescription>
<ul className="list-disc pl-4 text-sm">
{validationErrors.map((error, i) => (
<li key={i}>{error}</li>
))}
<AlertDescription className="max-h-60 overflow-y-auto">
<ul className="space-y-2 text-sm">
{validationErrors.map((error, i) => {
// Check if the error contains a field path (format: 'Field "path":')
const fieldMatch = error.match(/^Field "([^"]+)": (.+)$/);
if (fieldMatch) {
return (
<li key={i} className="flex flex-col gap-1">
<code className="rounded bg-red-50 px-1.5 py-0.5 font-mono text-xs text-red-800">
{fieldMatch[1]}
</code>
<span className="text-slate-700">{fieldMatch[2]}</span>
</li>
);
}
return (
<li key={i} className="text-slate-700">
{error}
</li>
);
})}
</ul>
</AlertDescription>
</Alert>
@@ -257,7 +273,7 @@ export const ImportSurveyModal = ({ environmentId, open, setOpen }: ImportSurvey
{validationWarnings.length > 0 && (
<Alert variant="warning">
<AlertTitle>{t("environments.surveys.import_survey_warnings")}</AlertTitle>
<AlertDescription>
<AlertDescription className="max-h-60 overflow-y-auto">
<ul className="list-disc pl-4 text-sm">
{validationWarnings.map((warningKey, i) => (
<li key={i}>{t(`environments.surveys.${warningKey}`)}</li>
@@ -269,7 +285,7 @@ export const ImportSurveyModal = ({ environmentId, open, setOpen }: ImportSurvey
{validationInfos.length > 0 && (
<Alert variant="info">
<AlertDescription>
<AlertDescription className="max-h-60 overflow-y-auto">
<ul className="list-disc pl-4 text-sm">
{validationInfos.map((infoKey, i) => (
<li key={i}>{t(`environments.surveys.${infoKey}`)}</li>

View File

@@ -30,7 +30,10 @@ export const parseSurveyPayload = (surveyData: unknown): TParsedPayload | TParse
if (!languagesResult.success) {
return {
error: "Invalid languages format",
details: languagesResult.error.errors.map((e) => `${e.path.join(".")}: ${e.message}`),
details: languagesResult.error.errors.map((e) => {
const path = e.path.length > 0 ? `languages.${e.path.join(".")}` : "languages";
return `Field "${path}": ${e.message}`;
}),
};
}
const exportedLanguages = languagesResult.data;
@@ -40,7 +43,10 @@ export const parseSurveyPayload = (surveyData: unknown): TParsedPayload | TParse
if (!triggersResult.success) {
return {
error: "Invalid triggers format",
details: triggersResult.error.errors.map((e) => `${e.path.join(".")}: ${e.message}`),
details: triggersResult.error.errors.map((e) => {
const path = e.path.length > 0 ? `triggers.${e.path.join(".")}` : "triggers";
return `Field "${path}": ${e.message}`;
}),
};
}
const triggers = triggersResult.data;
@@ -54,7 +60,10 @@ export const parseSurveyPayload = (surveyData: unknown): TParsedPayload | TParse
if (!surveyResult.success) {
return {
error: "Invalid survey format",
details: surveyResult.error.errors.map((e) => `${e.path.join(".")}: ${e.message}`),
details: surveyResult.error.errors.map((e) => {
const path = e.path.length > 0 ? e.path.join(".") : "root";
return `Field "${path}": ${e.message}`;
}),
};
}