forked from github/plane
chore: input character limit error message improvement (#4271)
This commit is contained in:
parent
fc1cffd524
commit
87737dbfbe
@ -27,9 +27,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => {
|
||||
: mode === "true-transparent"
|
||||
? "rounded border-none bg-transparent ring-0"
|
||||
: ""
|
||||
} ${hasError ? "border-red-500" : ""} ${hasError && mode === "primary" ? "bg-red-500/20" : ""} ${
|
||||
inputSize === "sm" ? "px-3 py-2" : inputSize === "md" ? "p-3" : ""
|
||||
}`,
|
||||
} ${hasError ? "border-red-500" : ""} ${inputSize === "sm" ? "px-3 py-2" : inputSize === "md" ? "p-3" : ""}`,
|
||||
className
|
||||
)}
|
||||
{...rest}
|
||||
|
@ -77,7 +77,7 @@ export const CycleForm: React.FC<Props> = (props) => {
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<div className="mt-2 space-y-3">
|
||||
<div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
@ -85,7 +85,7 @@ export const CycleForm: React.FC<Props> = (props) => {
|
||||
required: "Name is required",
|
||||
maxLength: {
|
||||
value: 255,
|
||||
message: "Name should be less than 255 characters",
|
||||
message: "Title should be less than 255 characters",
|
||||
},
|
||||
}}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
@ -103,6 +103,7 @@ export const CycleForm: React.FC<Props> = (props) => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<span className="text-xs text-red-500">{errors?.name?.message}</span>
|
||||
</div>
|
||||
<div>
|
||||
<Controller
|
||||
|
@ -116,10 +116,16 @@ export const InboxIssueCreateRoot: FC<TInboxIssueCreateRoot> = observer((props)
|
||||
setFormSubmitting(false);
|
||||
};
|
||||
|
||||
const isTitleLengthMoreThan255Character = formData?.name ? formData.name.length > 255 : false;
|
||||
|
||||
if (!workspaceSlug || !projectId || !workspaceId) return <></>;
|
||||
return (
|
||||
<form className="relative space-y-4" onSubmit={handleFormSubmit}>
|
||||
<InboxIssueTitle data={formData} handleData={handleFormData} />
|
||||
<InboxIssueTitle
|
||||
data={formData}
|
||||
handleData={handleFormData}
|
||||
isTitleLengthMoreThan255Character={isTitleLengthMoreThan255Character}
|
||||
/>
|
||||
<InboxIssueDescription
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
@ -138,7 +144,13 @@ export const InboxIssueCreateRoot: FC<TInboxIssueCreateRoot> = observer((props)
|
||||
<Button variant="neutral-primary" size="sm" type="button" onClick={handleModalClose}>
|
||||
Discard
|
||||
</Button>
|
||||
<Button variant="primary" size="sm" type="submit" loading={formSubmitting}>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
type="submit"
|
||||
loading={formSubmitting}
|
||||
disabled={isTitleLengthMoreThan255Character}
|
||||
>
|
||||
{formSubmitting ? "Adding Issue..." : "Add Issue"}
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -121,10 +121,16 @@ export const InboxIssueEditRoot: FC<TInboxIssueEditRoot> = observer((props) => {
|
||||
setFormSubmitting(false);
|
||||
};
|
||||
|
||||
const isTitleLengthMoreThan255Character = formData?.name ? formData.name.length > 255 : false;
|
||||
|
||||
if (!workspaceSlug || !projectId || !workspaceId || !formData) return <></>;
|
||||
return (
|
||||
<div className="relative space-y-4">
|
||||
<InboxIssueTitle data={formData} handleData={handleFormData} />
|
||||
<InboxIssueTitle
|
||||
data={formData}
|
||||
handleData={handleFormData}
|
||||
isTitleLengthMoreThan255Character={isTitleLengthMoreThan255Character}
|
||||
/>
|
||||
<InboxIssueDescription
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
@ -138,7 +144,14 @@ export const InboxIssueEditRoot: FC<TInboxIssueEditRoot> = observer((props) => {
|
||||
<Button variant="neutral-primary" size="sm" type="button" onClick={handleModalClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="primary" size="sm" type="button" loading={formSubmitting} onClick={handleFormSubmit}>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
type="button"
|
||||
loading={formSubmitting}
|
||||
disabled={isTitleLengthMoreThan255Character}
|
||||
onClick={handleFormSubmit}
|
||||
>
|
||||
{formSubmitting ? "Adding..." : "Add to project"}
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -6,10 +6,11 @@ import { Input } from "@plane/ui";
|
||||
type TInboxIssueTitle = {
|
||||
data: Partial<TIssue>;
|
||||
handleData: (issueKey: keyof Partial<TIssue>, issueValue: Partial<TIssue>[keyof Partial<TIssue>]) => void;
|
||||
isTitleLengthMoreThan255Character?: boolean;
|
||||
};
|
||||
|
||||
export const InboxIssueTitle: FC<TInboxIssueTitle> = observer((props) => {
|
||||
const { data, handleData } = props;
|
||||
const { data, handleData, isTitleLengthMoreThan255Character } = props;
|
||||
|
||||
return (
|
||||
<div className="relative flex flex-wrap gap-2 items-center">
|
||||
@ -21,9 +22,11 @@ export const InboxIssueTitle: FC<TInboxIssueTitle> = observer((props) => {
|
||||
onChange={(e) => handleData("name", e.target.value)}
|
||||
placeholder="Title"
|
||||
className="w-full resize-none text-xl"
|
||||
maxLength={255}
|
||||
required
|
||||
/>
|
||||
{isTitleLengthMoreThan255Character && (
|
||||
<span className="text-xs text-red-500">Title should be less than 255 characters</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
@ -391,6 +391,8 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<span className="text-xs text-red-500">{errors?.name?.message}</span>
|
||||
|
||||
<div className="relative">
|
||||
{data?.description_html === undefined ? (
|
||||
<Loader className="min-h-[7rem] space-y-2 overflow-hidden rounded-md border border-custom-border-200 p-2 py-2">
|
||||
|
@ -90,7 +90,7 @@ export const ModuleForm: React.FC<Props> = (props) => {
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
@ -109,13 +109,14 @@ export const ModuleForm: React.FC<Props> = (props) => {
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
ref={ref}
|
||||
hasError={Boolean(errors.name)}
|
||||
hasError={Boolean(errors?.name)}
|
||||
placeholder="Module Title"
|
||||
className="w-full resize-none placeholder:text-sm placeholder:font-medium focus:border-blue-400"
|
||||
tabIndex={1}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<span className="text-xs text-red-500">{errors?.name?.message}</span>
|
||||
</div>
|
||||
<div>
|
||||
<Controller
|
||||
|
@ -216,6 +216,10 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
|
||||
name="name"
|
||||
rules={{
|
||||
required: "Name is required",
|
||||
maxLength: {
|
||||
value: 255,
|
||||
message: "Project name should be less than 255 characters",
|
||||
},
|
||||
}}
|
||||
render={({ field: { value, onChange, ref } }) => (
|
||||
<Input
|
||||
@ -232,9 +236,7 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<span className="text-xs text-red-500">
|
||||
<>{errors?.name?.message}</>
|
||||
</span>
|
||||
<span className="text-xs text-red-500">{errors?.name?.message}</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<h4 className="text-sm">Description</h4>
|
||||
|
@ -112,7 +112,7 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
|
||||
<div className="space-y-5">
|
||||
<h3 className="text-lg font-medium leading-6 text-custom-text-100">{data ? "Update" : "Create"} View</h3>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
@ -137,6 +137,7 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<span className="text-xs text-red-500">{errors?.name?.message}</span>
|
||||
</div>
|
||||
<div>
|
||||
<Controller
|
||||
@ -215,8 +216,8 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
|
||||
? "Updating View..."
|
||||
: "Update View"
|
||||
: isSubmitting
|
||||
? "Creating View..."
|
||||
: "Create View"}
|
||||
? "Creating View..."
|
||||
: "Create View"}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -125,35 +125,38 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
|
||||
Workspace Name
|
||||
<span className="ml-0.5 text-red-500">*</span>
|
||||
</label>
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
rules={{
|
||||
required: "Workspace name is required",
|
||||
validate: (value) =>
|
||||
/^[\w\s-]*$/.test(value) || `Name can only contain (" "), ( - ), ( _ ) & alphanumeric characters.`,
|
||||
maxLength: {
|
||||
value: 80,
|
||||
message: "Workspace name should not exceed 80 characters",
|
||||
},
|
||||
}}
|
||||
render={({ field: { value, ref, onChange } }) => (
|
||||
<Input
|
||||
id="workspaceName"
|
||||
type="text"
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.value);
|
||||
setValue("name", e.target.value);
|
||||
setValue("slug", e.target.value.toLocaleLowerCase().trim().replace(/ /g, "-"));
|
||||
}}
|
||||
ref={ref}
|
||||
hasError={Boolean(errors.name)}
|
||||
placeholder="Enter workspace name..."
|
||||
className="w-full"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<div className="flex flex-col gap-1">
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
rules={{
|
||||
required: "Workspace name is required",
|
||||
validate: (value) =>
|
||||
/^[\w\s-]*$/.test(value) || `Name can only contain (" "), ( - ), ( _ ) & alphanumeric characters.`,
|
||||
maxLength: {
|
||||
value: 80,
|
||||
message: "Workspace name should not exceed 80 characters",
|
||||
},
|
||||
}}
|
||||
render={({ field: { value, ref, onChange } }) => (
|
||||
<Input
|
||||
id="workspaceName"
|
||||
type="text"
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.value);
|
||||
setValue("name", e.target.value);
|
||||
setValue("slug", e.target.value.toLocaleLowerCase().trim().replace(/ /g, "-"));
|
||||
}}
|
||||
ref={ref}
|
||||
hasError={Boolean(errors.name)}
|
||||
placeholder="Enter workspace name..."
|
||||
className="w-full"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<span className="text-xs text-red-500">{errors?.name?.message}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1 text-sm">
|
||||
<label htmlFor="workspaceUrl">
|
||||
|
Loading…
Reference in New Issue
Block a user