mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add form_type error (#18067)
Normally parameters had red text for error diagnostics. The goal here is to make errors more obvious when the form_type is error meaning the parameter could not be processed correctly. <img width="543" alt="Screenshot 2025-05-27 at 18 35 50" src="https://github.com/user-attachments/assets/2265553e-34a3-4526-8209-6253d541f784" />
This commit is contained in:
@@ -156,6 +156,32 @@ export const Slider: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const ErrorFormType: Story = {
|
||||
args: {
|
||||
parameter: {
|
||||
...MockPreviewParameter,
|
||||
form_type: "error",
|
||||
type: "string",
|
||||
diagnostics: [
|
||||
{
|
||||
severity: "error",
|
||||
summary: "This is an error",
|
||||
detail:
|
||||
"This is a longer error message. This is a longer error message. This is a longer error message. This is a longer error message. This is a longer error message. This is a longer error message.",
|
||||
extra: { code: "" },
|
||||
},
|
||||
{
|
||||
severity: "error",
|
||||
summary: "This is an error",
|
||||
detail:
|
||||
"This is a longer error message. This is a longer error message. This is a longer error message. This is a longer error message. This is a longer error message. This is a longer error message.",
|
||||
extra: { code: "" },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
parameter: {
|
||||
|
||||
@@ -34,7 +34,13 @@ import {
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { useDebouncedValue } from "hooks/debounce";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { Info, LinkIcon, Settings, TriangleAlert } from "lucide-react";
|
||||
import {
|
||||
CircleAlert,
|
||||
Info,
|
||||
LinkIcon,
|
||||
Settings,
|
||||
TriangleAlert,
|
||||
} from "lucide-react";
|
||||
import { type FC, useEffect, useId, useRef, useState } from "react";
|
||||
import type { AutofillBuildParameter } from "utils/richParameters";
|
||||
import * as Yup from "yup";
|
||||
@@ -89,7 +95,9 @@ export const DynamicParameter: FC<DynamicParameterProps> = ({
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<ParameterDiagnostics diagnostics={parameter.diagnostics} />
|
||||
{parameter.form_type !== "error" && (
|
||||
<ParameterDiagnostics diagnostics={parameter.diagnostics} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -508,6 +516,8 @@ const ParameterField: FC<ParameterFieldProps> = ({
|
||||
<span className="w-4 font-medium">{parameter.value.value}</span>
|
||||
</div>
|
||||
);
|
||||
case "error":
|
||||
return <Diagnostics diagnostics={parameter.diagnostics} />;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -832,3 +842,45 @@ const parameterError = (
|
||||
(match) => r.get(match) || "",
|
||||
);
|
||||
};
|
||||
|
||||
interface DiagnosticsProps {
|
||||
diagnostics: PreviewParameter["diagnostics"];
|
||||
}
|
||||
|
||||
// Displays a diagnostic with a border, icon and background color
|
||||
export const Diagnostics: FC<DiagnosticsProps> = ({ diagnostics }) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
{diagnostics.map((diagnostic, index) => (
|
||||
<div
|
||||
key={`diagnostic-${diagnostic.summary}-${index}`}
|
||||
className={`text-xs font-semibold flex flex-col rounded-md border px-3.5 py-3.5 border-solid
|
||||
${
|
||||
diagnostic.severity === "error"
|
||||
? "text-content-primary border-border-destructive bg-content-destructive/15"
|
||||
: "text-content-primary border-border-warning bg-content-warning/15"
|
||||
}`}
|
||||
>
|
||||
<div className="flex flex-row items-start">
|
||||
{diagnostic.severity === "error" && (
|
||||
<CircleAlert
|
||||
className="me-2 inline-flex shrink-0 text-content-destructive size-icon-sm"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
{diagnostic.severity === "warning" && (
|
||||
<TriangleAlert
|
||||
className="me-2 inline-flex shrink-0 text-content-warning size-icon-sm"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
<div className="flex flex-col gap-3">
|
||||
<p className="m-0">{diagnostic.summary}</p>
|
||||
{diagnostic.detail && <p className="m-0">{diagnostic.detail}</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -26,14 +26,9 @@ import {
|
||||
} from "components/Tooltip/Tooltip";
|
||||
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
|
||||
import { type FormikContextType, useFormik } from "formik";
|
||||
import {
|
||||
ArrowLeft,
|
||||
CircleAlert,
|
||||
CircleHelp,
|
||||
TriangleAlert,
|
||||
Undo2,
|
||||
} from "lucide-react";
|
||||
import { ArrowLeft, CircleHelp, Undo2 } from "lucide-react";
|
||||
import { useSyncFormParameters } from "modules/hooks/useSyncFormParameters";
|
||||
import { Diagnostics } from "modules/workspaces/DynamicParameter/DynamicParameter";
|
||||
import {
|
||||
DynamicParameter,
|
||||
getInitialParameterValues,
|
||||
@@ -665,44 +660,3 @@ export const CreateWorkspacePageViewExperimental: FC<
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
interface DiagnosticsProps {
|
||||
diagnostics: PreviewParameter["diagnostics"];
|
||||
}
|
||||
|
||||
const Diagnostics: FC<DiagnosticsProps> = ({ diagnostics }) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
{diagnostics.map((diagnostic, index) => (
|
||||
<div
|
||||
key={`diagnostic-${diagnostic.summary}-${index}`}
|
||||
className={`text-xs font-semibold flex flex-col rounded-md border px-3.5 py-3.5 border-solid
|
||||
${
|
||||
diagnostic.severity === "error"
|
||||
? "text-content-primary border-border-destructive bg-content-destructive/15"
|
||||
: "text-content-primary border-border-warning bg-content-warning/15"
|
||||
}`}
|
||||
>
|
||||
<div className="flex flex-row items-start">
|
||||
{diagnostic.severity === "error" && (
|
||||
<CircleAlert
|
||||
className="me-2 inline-flex shrink-0 text-content-destructive size-icon-sm"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
{diagnostic.severity === "warning" && (
|
||||
<TriangleAlert
|
||||
className="me-2 inline-flex shrink-0 text-content-warning size-icon-sm"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
<div className="flex flex-col gap-3">
|
||||
<p className="m-0">{diagnostic.summary}</p>
|
||||
{diagnostic.detail && <p className="m-0">{diagnostic.detail}</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user