forked from github/plane
chore: number field validations
This commit is contained in:
parent
529a286954
commit
fff07a2353
@ -124,14 +124,18 @@ export const AttributeForm: React.FC<Props> = ({
|
||||
)}
|
||||
<div className="mt-8 flex items-center justify-between">
|
||||
<div className="flex-shrink-0 flex items-center gap-2">
|
||||
<Controller
|
||||
control={control}
|
||||
name="is_required"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<ToggleSwitch value={value ?? false} onChange={onChange} />
|
||||
)}
|
||||
/>
|
||||
<span className="text-xs">Mandatory field</span>
|
||||
{data.type !== "checkbox" && (
|
||||
<>
|
||||
<Controller
|
||||
control={control}
|
||||
name="is_required"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<ToggleSwitch value={value ?? false} onChange={onChange} />
|
||||
)}
|
||||
/>
|
||||
<span className="text-xs">Mandatory field</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
|
@ -111,12 +111,12 @@ export const NumberAttributeForm: React.FC<FormComponentProps> = ({ control, wat
|
||||
placeholder="Maximum value"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
className="hide-arrows"
|
||||
min={0}
|
||||
step={1}
|
||||
required
|
||||
/>
|
||||
)}
|
||||
rules={{
|
||||
required: "This field is required",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
@ -125,9 +125,15 @@ export const NumberAttributeForm: React.FC<FormComponentProps> = ({ control, wat
|
||||
<div className="col-span-2">
|
||||
<Controller
|
||||
control={control}
|
||||
name="extra_settings.color"
|
||||
name="color"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input type="text" placeholder="Accent color" value={value} onChange={onChange} />
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Accent color"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
required
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
@ -6,6 +6,7 @@ import { Controller, useForm } from "react-hook-form";
|
||||
import { Props } from "./types";
|
||||
|
||||
export const CustomEmailAttribute: React.FC<Props & { value: string | undefined }> = ({
|
||||
attributeDetails,
|
||||
onChange,
|
||||
value,
|
||||
}) => {
|
||||
@ -57,6 +58,7 @@ export const CustomEmailAttribute: React.FC<Props & { value: string | undefined
|
||||
<input
|
||||
type="email"
|
||||
className="text-xs px-2 py-0.5 bg-custom-background-80 rounded w-full outline-none"
|
||||
required={attributeDetails.is_required}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
|
@ -61,8 +61,8 @@ export const CustomNumberAttribute: React.FC<Props & { value: number | undefined
|
||||
<div
|
||||
className="absolute top-0 left-0 h-full"
|
||||
style={{
|
||||
backgroundColor: extraSettings?.color ?? "rgb(var(--color-primary-100))",
|
||||
width: `${(value / parseInt(extraSettings.divided_by, 10)) * 100}%`,
|
||||
backgroundColor: attributeDetails.color ?? "rgb(var(--color-primary-100))",
|
||||
width: `${(value / parseInt(extraSettings.divided_by ?? 100, 10)) * 100}%`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -73,9 +73,9 @@ export const CustomNumberAttribute: React.FC<Props & { value: number | undefined
|
||||
<span className="flex-shrink-0 font-medium">{value}</span>
|
||||
)}
|
||||
<ProgressBar
|
||||
activeStrokeColor={extraSettings?.color ?? "rgb(var(--color-primary-100))"}
|
||||
activeStrokeColor={attributeDetails.color ?? "rgb(var(--color-primary-100))"}
|
||||
value={value}
|
||||
maxValue={parseInt(extraSettings.divided_by, 10)}
|
||||
maxValue={parseInt(extraSettings.divided_by ?? 100, 10)}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
@ -96,6 +96,10 @@ export const CustomNumberAttribute: React.FC<Props & { value: number | undefined
|
||||
<input
|
||||
type="number"
|
||||
className="hide-arrows text-xs px-2 py-0.5 bg-custom-background-80 rounded w-full outline-none"
|
||||
step={1}
|
||||
min={extraSettings.divided_by ? 0 : undefined}
|
||||
max={extraSettings.divided_by ?? undefined}
|
||||
required={attributeDetails.is_required}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
|
@ -6,6 +6,7 @@ import { Controller, useForm } from "react-hook-form";
|
||||
import { Props } from "./types";
|
||||
|
||||
export const CustomTextAttribute: React.FC<Props & { value: string | undefined }> = ({
|
||||
attributeDetails,
|
||||
onChange,
|
||||
value,
|
||||
}) => {
|
||||
@ -57,6 +58,7 @@ export const CustomTextAttribute: React.FC<Props & { value: string | undefined }
|
||||
<input
|
||||
type="text"
|
||||
className="text-xs px-2 py-0.5 bg-custom-background-80 rounded w-full outline-none"
|
||||
required={attributeDetails.is_required}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
|
@ -6,6 +6,7 @@ import { Controller, useForm } from "react-hook-form";
|
||||
import { Props } from "./types";
|
||||
|
||||
export const CustomUrlAttribute: React.FC<Props & { value: string | undefined }> = ({
|
||||
attributeDetails,
|
||||
onChange,
|
||||
value,
|
||||
}) => {
|
||||
@ -57,6 +58,7 @@ export const CustomUrlAttribute: React.FC<Props & { value: string | undefined }>
|
||||
<input
|
||||
type="url"
|
||||
className="text-xs px-2 py-0.5 bg-custom-background-80 rounded w-full outline-none"
|
||||
required={attributeDetails.is_required}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
|
@ -1,7 +1,6 @@
|
||||
// icons
|
||||
import {
|
||||
AtSign,
|
||||
Baseline,
|
||||
CaseSensitive,
|
||||
CheckCircle,
|
||||
Clock4,
|
||||
@ -91,10 +90,10 @@ export const CUSTOM_ATTRIBUTES_LIST: {
|
||||
},
|
||||
number: {
|
||||
defaultFormValues: {
|
||||
color: "#000000",
|
||||
default_value: "",
|
||||
display_name: "",
|
||||
extra_settings: {
|
||||
color: "Blue",
|
||||
divided_by: 100,
|
||||
representation: "numerical",
|
||||
show_number: true,
|
||||
@ -109,10 +108,6 @@ export const CUSTOM_ATTRIBUTES_LIST: {
|
||||
},
|
||||
},
|
||||
},
|
||||
option: {
|
||||
icon: Baseline,
|
||||
label: "Option",
|
||||
},
|
||||
relation: {
|
||||
defaultFormValues: { display_name: "", is_multi: false, is_required: false, unit: "cycle" },
|
||||
icon: Forward,
|
||||
|
@ -63,7 +63,7 @@ class CustomAttributeValuesStore {
|
||||
|
||||
newChildren.map((child) => {
|
||||
if (attributesToUpdate.includes(child.id) && child)
|
||||
child.prop_value = [{ type: "", value: data.issue_properties[child.id] }];
|
||||
child.prop_value = [{ type: 0, value: data.issue_properties[child.id] }];
|
||||
|
||||
return child;
|
||||
});
|
||||
|
39
web/types/custom-attributes.d.ts
vendored
39
web/types/custom-attributes.d.ts
vendored
@ -14,6 +14,37 @@ export type TCustomAttributeTypes =
|
||||
|
||||
export type TCustomAttributeUnits = "cycle" | "issue" | "module" | "user" | null;
|
||||
|
||||
// export type TCustomAttributeExtraSettings =
|
||||
// | {
|
||||
// type: "checkbox";
|
||||
// extra_settings: {
|
||||
// representation: "check" | "toggle_switch";
|
||||
// };
|
||||
// }
|
||||
// | {
|
||||
// type: "datetime";
|
||||
// extra_settings: {
|
||||
// date_format: "DD-MM-YYYY" | "MM-DD-YYYY" | "YYYY-MM-DD";
|
||||
// hide_date: boolean;
|
||||
// hide_time: boolean;
|
||||
// time_format: "12" | "24";
|
||||
// };
|
||||
// }
|
||||
// | {
|
||||
// type: "files";
|
||||
// extra_settings: {
|
||||
// file_formats: string[];
|
||||
// };
|
||||
// }
|
||||
// | {
|
||||
// type: "number";
|
||||
// extra_settings: {
|
||||
// divided_by: number;
|
||||
// representation: "numerical" | "bar" | "ring";
|
||||
// show_number: boolean;
|
||||
// };
|
||||
// };
|
||||
|
||||
export interface ICustomAttribute {
|
||||
children: ICustomAttribute[];
|
||||
color: string;
|
||||
@ -40,10 +71,16 @@ export interface ICustomAttributeValue {
|
||||
name: string;
|
||||
prop_value:
|
||||
| {
|
||||
type: string;
|
||||
type: 0 | 1;
|
||||
value: string;
|
||||
}[]
|
||||
| null;
|
||||
prop_extra:
|
||||
| {
|
||||
id: string;
|
||||
name: string;
|
||||
}[]
|
||||
| null;
|
||||
type: TCustomAttributeTypes;
|
||||
unit: TCustomAttributeUnits;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user