Skip to content

Commit

Permalink
chore: added aoi area size to file upload modal
Browse files Browse the repository at this point in the history
  • Loading branch information
jeafreezy committed Nov 12, 2024
1 parent 85333f2 commit 6c1cfa2
Show file tree
Hide file tree
Showing 17 changed files with 156 additions and 96 deletions.
3 changes: 2 additions & 1 deletion frontend/src/components/map/draw-control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { PenIcon } from "@/components/ui/icons";
import { Map, MapMouseEvent } from "maplibre-gl";
import {
calculateGeoJSONArea,
formatAreaInAppropriateUnit,
MAX_TRAINING_AREA_SIZE,
MIN_TRAINING_AREA_SIZE,
} from "@/utils";
Expand Down Expand Up @@ -158,7 +159,7 @@ const DrawControl = ({
<p>
{mode === DrawingModes.RECTANGLE && featureArea === 0
? "Click and drag to draw a rectangle."
: `Current area: ${featureArea.toFixed(2)}`}
: `Current area: ${formatAreaInAppropriateUnit(featureArea)}`}
</p>
<p>{getFeedbackMessage()}</p>
</div>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ui/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import "./button.css";
import { Spinner } from "@/components/ui/spinner";
import { cn } from "@/utils";
import { ButtonSize, ButtonVariant } from "@/types";
import useDevice from "@/hooks/use-device";
import useScreenSize from "@/hooks/use-screen-size";

type ButtonProps = {
children: React.ReactNode;
Expand All @@ -29,7 +29,7 @@ const Button: React.FC<ButtonProps> = ({
}) => {
const spinnerColor = variant === "primary" ? "white" : "red";
const trackColor = variant === "primary" ? "red" : "white";
const isMobile = useDevice();
const { isMobile } = useScreenSize();
return (
<SlButton
//@ts-expect-error bad type definition
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ui/form/input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styles from "./input.module.css";
import { CalenderIcon } from "@/components/ui/icons";
import useBrowserType from "@/hooks/use-browser-type";
import { useRef } from "react";
import useDevice from "@/hooks/use-device";
import useScreenSize from "@/hooks/use-screen-size";
import { HelpText, FormLabel } from "@/components/ui/form";
import CheckIcon from "@/components/ui/icons/check-icon";
import { INPUT_TYPES, SHOELACE_SIZES } from "@/enums";
Expand Down Expand Up @@ -63,7 +63,7 @@ const Input: React.FC<InputProps> = ({
};

const inputRef = useRef<HTMLInputElement | null>(null);
const isMobile = useDevice();
const { isMobile } = useScreenSize();;

return (
<SlInput
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ui/form/select/select.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SlOption, SlSelect } from "@shoelace-style/shoelace/dist/react";
import useDevice from "@/hooks/use-device";
import useScreenSize from "@/hooks/use-screen-size";
import { HelpText, FormLabel } from "@/components/ui/form";
import "./select.css";

Expand Down Expand Up @@ -30,7 +30,7 @@ const Select: React.FC<SelectProps> = ({
handleChange,
required,
}) => {
const isMobile = useDevice();
const { isMobile } = useScreenSize();;
return (
<SlSelect
placeholder={placeholder}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/enums/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ export enum SHOELACE_SIZES {
SMALL = "small",
MEDIUM = "medium",
LARGE = "large",
EXTRA_LARGE = 'extra-large'
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { useCallback, useState } from "react";
import { FileWithPath, useDropzone } from "react-dropzone";
import { useCreateTrainingArea } from "@/features/model-creation/hooks/use-training-areas";
import { geojsonToWKT } from "@terraformer/wkt";
import useDevice from "@/hooks/use-device";
import useScreenSize from "@/hooks/use-screen-size";

type FileUploadDialogProps = DialogProps & {
datasetId: string;
Expand All @@ -48,28 +48,44 @@ const FileUploadDialog: React.FC<FileUploadDialogProps> = ({
});

const onDrop = useCallback((files: FileWithPath[]) => {
const validFiles = files.filter((file) => {
if (file.size > MAX_TRAINING_AREA_UPLOAD_FILE_SIZE) {
showErrorToast(undefined, `File ${file.name} is too large (max 5MB)`);

const initialValidFiles = files.filter((file) => {
if (!file.name.endsWith(".geojson") && !file.name.endsWith(".json")) {
showErrorToast(undefined, `File ${file.name} is not a supported format`);
return false;
}
if (!file.name.endsWith(".geojson") && !file.name.endsWith(".json")) {
showErrorToast(
undefined,
`File ${file.name} is not a supported format`,
);
if (file.size > MAX_TRAINING_AREA_UPLOAD_FILE_SIZE) {
showErrorToast(undefined, `File ${file.name} is too large (max 5MB)`);
return false;
}
return true;
});

const newFiles = validFiles.map((file) => ({
file,
id: generateUniqueId(),
}));
setAcceptedFiles((prev) => [...prev, ...newFiles]);

const validateFiles = async () => {
const validFiles: { file: FileWithPath; id: string }[] = [];

for (const file of initialValidFiles) {
const text = await file.text();
try {
const geojson: FeatureCollection | Feature = JSON.parse(text);
if (validateGeoJSONArea(geojson as Feature)) {
showErrorToast(undefined, `File area for ${file.name} exceeds area limit.`);
} else {
validFiles.push({ file, id: generateUniqueId() });
}
} catch (error) {
showErrorToast(error);
}
}

setAcceptedFiles((prev) => [...prev, ...validFiles]);
};

validateFiles();
}, []);


const clearAcceptedFiles = () => {
setAcceptedFiles([]);
};
Expand Down Expand Up @@ -176,7 +192,7 @@ const FileUploadDialog: React.FC<FileUploadDialogProps> = ({
</button>
</li>
));
const isMobile = useDevice();
const { isMobile } = useScreenSize();;
return (
<Dialog
isOpened={isOpened}
Expand Down Expand Up @@ -205,7 +221,13 @@ const FileUploadDialog: React.FC<FileUploadDialogProps> = ({
<small>
{
MODEL_CREATION_CONTENT.trainingArea.fileUploadDialog
.subInstruction
.fleSizeInstruction
}
</small>
<small>
{
MODEL_CREATION_CONTENT.trainingArea.fileUploadDialog
.aoiAreaInstruction
}
</small>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { useDropdownMenu } from "@/hooks/use-dropdown-menu";
import {
calculateGeoJSONArea,
formatAreaInAppropriateUnit,
formatDuration,
geoJSONDowloader,
getGeoJSONFeatureBounds,
Expand All @@ -31,7 +32,7 @@ import {
} from "@/features/model-creation/hooks/use-training-areas";
import { useMap } from "@/app/providers/map-provider";
import { useModelsContext } from "@/app/providers/models-provider";
import { useCallback, useEffect, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";

const TrainingAreaItem: React.FC<
TTrainingAreaFeature & { datasetId: number; offset: number }
Expand Down Expand Up @@ -200,10 +201,12 @@ const TrainingAreaItem: React.FC<

return () => clearInterval(intervalId);
}, [trainingArea?.properties?.label_fetched]);
const trainingAreaSize = roundNumber(
calculateGeoJSONArea(trainingArea),
2,
).toLocaleString();


const trainingAreaSize = useMemo(() => {
return formatAreaInAppropriateUnit(calculateGeoJSONArea(trainingArea))
}, [trainingArea]);

return (
<>
<div className="flex items-center justify-between w-full gap-x-4">
Expand All @@ -213,10 +216,9 @@ const TrainingAreaItem: React.FC<
</p>
<p
className="text-body-4 text-dark"
title={`${trainingAreaSize} sqm`}
title={`${trainingAreaSize}`}
>
{trainingArea.geometry ? truncateString(trainingAreaSize, 15) : 0}
sqm
</p>
<p className="text-body-4 text-dark">
{trainingAreaLabelsMutation.isPending
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Dialog } from "@/components/ui/dialog";
import useDevice from "@/hooks/use-device";
import useScreenSize from "@/hooks/use-screen-size";
import {
CategoryFilter,
DateRangeFilter,
Expand Down Expand Up @@ -36,7 +36,7 @@ const MobileModelFiltersDialog: React.FC<TrainingAreaDialogProps> = ({
updateQuery,
disabled,
}) => {
const isMobile = useDevice();
const { isMobile } = useScreenSize();;
return (
<Dialog
isOpened={isOpened}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dialog } from "@/components/ui/dialog";
import { SHOELACE_SIZES } from "@/enums";
import DirectoryTree from "@/features/models/components/directory-tree";
import useDevice from "@/hooks/use-device";
import useScreenSize from "@/hooks/use-screen-size";
import { DialogProps } from "@/types";
import { APP_CONTENT } from "@/utils";

Expand All @@ -15,13 +16,13 @@ const ModelFilesDialog: React.FC<TrainingAreaDialogProps> = ({
datasetId,
trainingId,
}) => {
const isMobile = useDevice();
const { isMobile, isLaptop, isTablet } = useScreenSize();;
return (
<Dialog
isOpened={isOpened}
closeDialog={closeDialog}
label={APP_CONTENT.models.modelsDetailsCard.modelFilesDialog.dialogTitle}
size={isMobile ? "extra-large" : "medium"}
size={isMobile || isTablet ? SHOELACE_SIZES.EXTRA_LARGE : isLaptop ? SHOELACE_SIZES.LARGE : SHOELACE_SIZES.MEDIUM}
>
<DirectoryTree trainingId={trainingId} datasetId={datasetId} />
</Dialog>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Dialog } from "@/components/ui/dialog";
import useDevice from "@/hooks/use-device";
import useScreenSize from "@/hooks/use-screen-size";
import { MapComponent } from "@/components/map";
import { cn } from "@/utils";
import { DialogProps } from "@/types";
Expand All @@ -10,7 +10,7 @@ const TrainingAreaDialog: React.FC<TrainingAreaDialogProps> = ({
isOpened,
closeDialog,
}) => {
const isMobile = useDevice();
const { isMobile } = useScreenSize();;

return (
<Dialog
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Dialog } from "@/components/ui/dialog";
import useDevice from "@/hooks/use-device";
import useScreenSize from "@/hooks/use-screen-size";
import ModelProperties from "@/features/models/components/model-details-properties";
import { DialogProps } from "@/types";
import { SHOELACE_SIZES } from "@/enums";

type TrainingDetailsDialogProps = DialogProps & {
trainingId: number;
Expand All @@ -16,14 +17,14 @@ const TrainingDetailsDialog: React.FC<TrainingDetailsDialogProps> = ({
datasetId,
baseModel,
}) => {
const isMobile = useDevice();
const { isMobile, isTablet, isLaptop } = useScreenSize();;

return (
<Dialog
isOpened={isOpened}
closeDialog={closeDialog}
label={`Training ${trainingId}`}
size={isMobile ? "extra-large" : "medium"}
size={isMobile || isTablet ? SHOELACE_SIZES.EXTRA_LARGE : isLaptop ? SHOELACE_SIZES.LARGE : SHOELACE_SIZES.MEDIUM}
>
<ModelProperties
trainingId={trainingId}
Expand Down
30 changes: 15 additions & 15 deletions frontend/src/features/models/components/directory-tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,20 +125,20 @@ const DirectoryTree: React.FC<DirectoryTreeProps> = ({
const { dir, file } = data;
const subdirectories = dir
? await Promise.all(
Object.keys(dir).map(async (key: string) => {
const fullPath = currentDirectory
? `${currentDirectory}/${key}`
: key;
const subDirData = await fetchDirectoryRecursive(fullPath);
return {
[key]: {
...subDirData,
size: dir[key]?.size || 0,
length: dir[key]?.len || 0,
},
};
}),
)
Object.keys(dir).map(async (key: string) => {
const fullPath = currentDirectory
? `${currentDirectory}/${key}`
: key;
const subDirData = await fetchDirectoryRecursive(fullPath);
return {
[key]: {
...subDirData,
size: dir[key]?.size || 0,
length: dir[key]?.len || 0,
},
};
}),
)
: [];

return {
Expand Down Expand Up @@ -227,7 +227,7 @@ const DirectoryTree: React.FC<DirectoryTreeProps> = ({
if (isLoading) return <DirectoryLoadingSkeleton />;
if (hasError)
return (
<div>{APP_CONTENT.models.modelsDetailsCard.modelFilesDialog.error}.</div>
<div>{APP_CONTENT.models.modelsDetailsCard.modelFilesDialog.error}</div>
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ const ModelProperties: React.FC<ModelPropertiesProps> = ({
return <ModelPropertiesSkeleton isTrainingDetailsDialog />;
}


return (
<>
<ModelFilesDialog
Expand Down Expand Up @@ -272,9 +273,9 @@ const ModelProperties: React.FC<ModelPropertiesProps> = ({
</div>
)}

{/* Show logs only in modal and when status failed */}
{/* Show logs only in modal and when status failed or running */}
{isTrainingDetailsDialog &&
data?.status !== TrainingStatus.SUCCESS && (
(data?.status === TrainingStatus.FAILED || data?.status === TrainingStatus.RUNNING) && (
<FailedTrainingTraceBack taskId={data?.task_id ?? ""} />
)}
</div>
Expand Down Expand Up @@ -304,23 +305,22 @@ export default ModelProperties;

const FailedTrainingTraceBack = ({ taskId }: { taskId: string }) => {
const { data, isPending } = useTrainingStatus(taskId);
const [showLogs, setShowLogs] = useState(false);
const [showLogs, setShowLogs] = useState<boolean>(false);

if (isPending) {
return (
<div className="h-40 col-span-5 w-full animate-pulse bg-light-gray"></div>
<div className="h-80 col-span-5 w-full animate-pulse bg-light-gray"></div>
);
}
return (
<div className="col-span-5 flex flex-col gap-y-4">
<div
<div className="col-span-5 flex flex-col gap-y-4 w-full h-20">
<button
onClick={() => setShowLogs(!showLogs)}
role="button"
className="flex items-center gap-x-2"
>
<p>{APP_CONTENT.models.modelsDetailsCard.trainingInfoDialog.logs}</p>
<ChevronDownIcon className={`icon ${showLogs && "rotate-180"}`} />
</div>
</button>
{showLogs && <CodeBlock content={data?.traceback as string} />}
</div>
);
Expand Down
Loading

0 comments on commit 6c1cfa2

Please sign in to comment.