Skip to content

Commit

Permalink
chore: validations
Browse files Browse the repository at this point in the history
  • Loading branch information
jeafreezy committed Oct 31, 2024
1 parent e294a1e commit b076646
Show file tree
Hide file tree
Showing 17 changed files with 323 additions and 138 deletions.
65 changes: 60 additions & 5 deletions frontend/src/app/providers/model-creation-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,92 @@
import { BASE_MODEL } from "@/enums";
import { BASE_MODEL, TrainingType } from "@/enums";
import { TrainingDatasetOption } from "@/features/model-creation/components/training-dataset";
import { useLocalStorage } from "@/hooks/use-storage";
import { HOT_FAIR_MODEL_CREATION_LOCAL_STORAGE_KEY } from "@/utils";
import {
HOT_FAIR_MODEL_CREATION_LOCAL_STORAGE_KEY,
URL_REGEX_PATTERN,
} from "@/utils";
import React, { createContext, useContext, useEffect, useState } from "react";

// The names here is the same with the initialFormState object keys as well as the form validation config
export enum MODEL_CREATION_FORM_NAME {
MODEL_NAME = "modelName",
DATASET_NAME = "datasetName",
MODEL_DESCRIPTION = "modelDescription",
BASE_MODEL = "baseModel",
TRAINING_DATASET_OPTION = "trainingDatasetOption",
ZOOM_LEVELS = "zoomLevels",
TRAINING_TYPE = "trainingType",
EPOCH = "epoch",
CONTACT_SPACING = "contactSpacing",
BATCH_SIZE = "batchSize",
BOUNDARY_WIDTH = "boundaryWidth",
TMS_URL = "tmsURL",
TMS_URL_VALIDITY = "tmsURLValidation",
SELECTED_TRAINING_DATASET_ID = "selectedTrainingDatasetId",
}

export const FORM_VALIDATION_CONFIG = {
modelName: {
maxLength: 40,
minLength: 10,
},
tmsURL: {
pattern: URL_REGEX_PATTERN,
},
modelDescription: {
maxLength: 500,
minLength: 10,
},
datasetName: {
maxLength: 40,
minLength: 10,
},
epoch: {
max: 30,
min: 1,
},
contactSpacing: {
max: 8,
min: 1,
},
batchSize: {
max: 12,
min: 1,
},
boundaryWidth: {
max: 8,
min: 1,
},
};

const initialFormState = {
modelName: "",
modelDescription: "",
datasetName: "",

baseModel: BASE_MODEL.RAMP.toLowerCase(),
trainingDatasetOption: TrainingDatasetOption.NONE,
// create new form
datasetName: "",
tmsURL: "",
tmsURLValidation: {
valid: false,
message: "",
},
// training dataset selection
selectedTrainingDatasetId: "",
zoomLevels: [20, 21],
// Defaults to basic configurations
trainingType: TrainingType.BASIC,
epoch: 2,
contactSpacing: 4,
batchSize: 8,
boundaryWidth: 3,
};

const ModelCreationFormContext = createContext<{
formData: typeof initialFormState;
setFormData: React.Dispatch<React.SetStateAction<typeof initialFormState>>;
handleChange: (field: string, value: string) => void;
handleChange: (field: string, value: string | boolean | number) => void;
}>({
formData: initialFormState,
setFormData: () => {},
Expand All @@ -48,7 +103,7 @@ export const ModelCreationFormProvider: React.FC<{
return savedData ? JSON.parse(savedData) : initialFormState;
});

const handleChange = (field: string, value: string) => {
const handleChange = (field: string, value: string | boolean | number) => {
setFormData((prev) => ({ ...prev, [field]: value }));
};

Expand Down
12 changes: 2 additions & 10 deletions frontend/src/app/routes/models/new/training-dataset.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import { TrainingDatasetForm } from "@/features/model-creation/components";
import { TrainingDatasetOption } from "@/features/model-creation/components/training-dataset";
import { useState } from "react";

export const CreateNewModelTrainingDatasetPage = () => {
const [selectedTrainingDatasetOption, setSelectedTrainingDatasetOption] =
useState<TrainingDatasetOption>(TrainingDatasetOption.NONE);

return (
<div className={"col-start-3 col-span-8 flex flex-col gap-y-10"}>
<TrainingDatasetForm
setSelectedTrainingDatasetOption={setSelectedTrainingDatasetOption}
selectedTrainingDatasetOption={selectedTrainingDatasetOption}
/>
<div className={"col-start-4 col-span-6"}>
<TrainingDatasetForm />
</div>
);
};
2 changes: 1 addition & 1 deletion frontend/src/components/map/draw-control.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Map } from "maplibre-gl";

// @ts-expect-error bad type definition
// @ts-expect-error bad type definition
const DrawControl = ({ map }: { map: Map | null }) => {
const handleDraw = () => {};

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ui/button/icon-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type ButtonWithIconProps = {
className?: string;
iconClassName?: string;
disabled?: boolean;
size?:ButtonSize
size?: ButtonSize;
};
const ButtonWithIcon: React.FC<ButtonWithIconProps> = ({
onClick,
Expand All @@ -24,7 +24,7 @@ const ButtonWithIcon: React.FC<ButtonWithIconProps> = ({
className,
iconClassName,
disabled,
size
size,
}) => {
return (
<div role="button">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type CheckboxGroupProps = {
apiValue?: string;
}[];
disabled?: boolean;
defaultSelectedOption?: string | string[];
defaultSelectedOption?: string | string[] | number[];
onCheck: (selectedOptions: string[]) => void;
className?: string;
multiple?: boolean;
Expand Down
51 changes: 43 additions & 8 deletions frontend/src/components/ui/form/input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import useBrowserType from "@/hooks/use-browser-type";
import { useRef } from "react";
import useDevice from "@/hooks/use-device";
import { HelpText, FormLabel } from "@/components/ui/form";
import CheckIcon from "@/components/ui/icons/check-icon";

type InputProps = {
handleInput: (arg: React.ChangeEvent<HTMLInputElement>) => void;
Expand All @@ -13,7 +14,7 @@ type InputProps = {
placeholder?: string;
clearable?: boolean;
disabled?: boolean;
type?: "date" | "text" | "number";
type?: "date" | "text" | "number" | "url";
showBorder?: boolean;
label?: string;
size?: "small" | "medium" | "large";
Expand All @@ -23,6 +24,11 @@ type InputProps = {
required?: boolean;
maxLength?: number;
minLength?: number;
pattern?: RegExp | string;
validationStateUpdateCallback?: (validity: boolean) => void;
isValid?: boolean;
min?: number;
max?: number;
};

const Input: React.FC<InputProps> = ({
Expand All @@ -42,33 +48,53 @@ const Input: React.FC<InputProps> = ({
required = false,
maxLength,
minLength,
pattern,
validationStateUpdateCallback,
isValid = false,
min,
max,
}) => {
const { isChrome } = useBrowserType();

const openNativeDatePicker = () => {
dateInputRef.current?.focus();
dateInputRef.current?.showPicker();
inputRef.current?.focus();
inputRef.current?.showPicker();
};

const dateInputRef = useRef<HTMLInputElement | null>(null);
const inputRef = useRef<HTMLInputElement | null>(null);
const isMobile = useDevice();

return (
<SlInput
// @ts-expect-error bad type definition
onSlInput={handleInput}
onSlInput={(e) => {
validationStateUpdateCallback &&
validationStateUpdateCallback?.(
// @ts-expect-error bad type definition
{
valid: inputRef.current?.validity?.valid,
message: inputRef.current?.validationMessage,
},
);
// @ts-expect-error bad type definition
handleInput(e);
}}
// @ts-expect-error bad type definition
value={value}
className={`${className} ${styles.customInput} ${showBorder && styles.showBorder}`}
placeholder={placeholder}
clearable={clearable}
disabled={disabled}
type={type}
//@ts-expect-error bad type definition
ref={dateInputRef}
// @ts-expect-error bad type definition
ref={inputRef}
label={label}
size={size ? size : isMobile ? "medium" : "large"}
minlength={minLength}
maxlength={maxLength}
pattern={`${pattern}`}
min={min}
max={max}
step={1}
>
{label && (
<FormLabel
Expand Down Expand Up @@ -97,6 +123,15 @@ const Input: React.FC<InputProps> = ({
onClick={openNativeDatePicker}
/>
)}

{isValid && (
<span
className="icon rounded-full p-1 bg-green-primary flex items-center justify-center"
slot="suffix"
>
<CheckIcon className=" text-white" />
</span>
)}
</SlInput>
);
};
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ui/icons/check-icon.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IconProps } from "@/types";
import { IconProps, ShoelaceSlotProps } from "@/types";
import React from "react";

const CheckIcon: React.FC<IconProps> = (props) => (
const CheckIcon: React.FC<ShoelaceSlotProps & IconProps> = (props) => (
<svg
{...props}
viewBox="0 0 14 10"
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/enums/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,9 @@ export enum BASE_MODEL {
RAMP = "RAMP",
YOLOV8 = "YOLOv8",
}

export enum TrainingType {
BASIC = "Basic",
INTERMEDIATE = "Intermediate",
ADVANCED = "Advanced",
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const ModelDetailsForm = () => {
showBorder
helpText="Model name should be at least 10 characters and at most 40 characters."
required
className="text-sm"
maxLength={
FORM_VALIDATION_CONFIG[MODEL_CREATION_FORM_NAME.MODEL_NAME]
.maxLength
Expand All @@ -68,11 +67,11 @@ const ModelDetailsForm = () => {
value={formData.modelDescription}
required
maxLength={
FORM_VALIDATION_CONFIG[MODEL_CREATION_FORM_NAME.MODEL_NAME]
FORM_VALIDATION_CONFIG[MODEL_CREATION_FORM_NAME.MODEL_DESCRIPTION]
.maxLength
}
minLength={
FORM_VALIDATION_CONFIG[MODEL_CREATION_FORM_NAME.MODEL_NAME]
FORM_VALIDATION_CONFIG[MODEL_CREATION_FORM_NAME.MODEL_DESCRIPTION]
.minLength
}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import CheckIcon from "@/components/ui/icons/check-icon";
import { APPLICATION_ROUTES, cn } from "@/utils";
import { useNavigate } from "react-router-dom";

type ProgressBarProps = {
currentPath: string;
Expand All @@ -13,8 +12,6 @@ const ProgressBar: React.FC<ProgressBarProps> = ({
currentPageIndex,
pages,
}) => {
const navigate = useNavigate();

return (
<div className="flex items-center justify-between px-10">
{pages.map((step) => {
Expand All @@ -26,7 +23,6 @@ const ProgressBar: React.FC<ProgressBarProps> = ({
disabled={
step.path === APPLICATION_ROUTES.CREATE_NEW_MODEL_CONFIRMATION
}
onClick={() => navigate(step.path)}
>
{step.id < currentPageIndex + 1 ? (
<span className="rounded-full bg-primary flex items-center justify-center w-9 h-9">
Expand Down
Loading

0 comments on commit b076646

Please sign in to comment.