Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/localstorage persists #353

Merged
merged 6 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 38 additions & 22 deletions frontend/src/app/providers/models-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ export const ModelsProvider: React.FC<{
}
}, [isError, error, navigate]);

// Fetch and prefill model details and training dataset
// Prefill formData with model details in edit mode.
useEffect(() => {
if (!isEditMode || isPending || !data || isError) return;

Expand Down Expand Up @@ -380,6 +380,19 @@ export const ModelsProvider: React.FC<{
};
}, []);

useEffect(() => {
/**
* During model creation, don't reset the state on unmount to keep track of the users progress and to persist the data during page refresh.
* But during edit mode, clean it up on unmount to ensure the forms are on a clean slate.
* Given that there is already an effect that prefills the form above in edit mode, this won't affect edit mode state.
*/
if (!isEditMode) return;
// Cleanup the state on component unmount
return () => {
resetState();
};
}, []);

const createNewTrainingRequestMutation = useCreateModelTrainingRequest({
mutationConfig: {
onSuccess: () => {
Expand Down Expand Up @@ -411,29 +424,30 @@ export const ModelsProvider: React.FC<{
},
});

const submitTrainingRequest = useCallback(() => {
createNewTrainingRequestMutation.mutate({
model: modelId as string,
input_boundary_width: formData.boundaryWidth,
input_contact_spacing: formData.contactSpacing,
epochs: formData.epoch,
batch_size: formData.batchSize,
zoom_level: formData.zoomLevels,
});
}, [formData, modelId]);

const handleModelCreationOrUpdateSuccess = (id?: string) => {
if (isModelOwner) {
showSuccessToast(
isEditMode
? TOAST_NOTIFICATIONS.modelUpdateSuccess
: TOAST_NOTIFICATIONS.modelCreationSuccess,
);
const submitTrainingRequest = useCallback(
(id: string) => {
createNewTrainingRequestMutation.mutate({
model: id,
input_boundary_width: formData.boundaryWidth,
input_contact_spacing: formData.contactSpacing,
epochs: formData.epoch,
batch_size: formData.batchSize,
zoom_level: formData.zoomLevels,
});
},
[formData, modelId],
);

const handleModelCreationOrUpdateSuccess = (id: string) => {
if (isEditMode && isModelOwner) {
showSuccessToast(TOAST_NOTIFICATIONS.modelUpdateSuccess);
} else if (!isEditMode) {
showSuccessToast(TOAST_NOTIFICATIONS.modelCreationSuccess);
}

navigate(`${getFullPath(MODELS_ROUTES.CONFIRMATION)}?id=${id ?? modelId}`);
navigate(`${getFullPath(MODELS_ROUTES.CONFIRMATION)}?id=${id}`);
// Submit the model for training request
submitTrainingRequest();
submitTrainingRequest(id);
};

const modelCreateMutation = useCreateModel({
Expand Down Expand Up @@ -462,6 +476,7 @@ export const ModelsProvider: React.FC<{
// Confirm that all the training areas labels have been fetched.
const hasLabeledTrainingAreas = useMemo(
() =>
formData.trainingAreas.length > 0 &&
formData.trainingAreas.every(
(aoi: TTrainingAreaFeature) => aoi.properties.label_fetched !== null,
),
Expand All @@ -471,6 +486,7 @@ export const ModelsProvider: React.FC<{
// Confirm that all of the training areas have a geometry.
const hasAOIsWithGeometry = useMemo(
() =>
formData.trainingAreas.length > 0 &&
formData.trainingAreas.every(
(aoi: TTrainingAreaFeature) => aoi.geometry !== null,
),
Expand Down Expand Up @@ -500,7 +516,7 @@ export const ModelsProvider: React.FC<{
// The user is trying to edit another users model training area and settings.
// In this case, directly submit a training request.
} else if (isEditMode && !isModelOwner) {
handleModelCreationOrUpdateSuccess();
handleModelCreationOrUpdateSuccess(modelId as string);
} else {
modelCreateMutation.mutate({
dataset: formData.selectedTrainingDatasetId,
Expand Down
18 changes: 9 additions & 9 deletions frontend/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,26 +229,26 @@ export const MAP_STYLES: Record<string, string | StyleSpecification> = {
OSM: {
version: 8,
// "glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
glyphs: 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf',
glyphs: "https://fonts.openmaptiles.org/{fontstack}/{range}.pbf",
sources: {
'raster-tiles': {
type: 'raster',
tiles: ['https://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png'],
"raster-tiles": {
type: "raster",
tiles: ["https://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png"],
tileSize: 128,
attribution:
'© <a href="https://www.openstreetmap.org/copyright/">OpenStreetMap</a> contributors',
},
},
layers: [
{
id: 'simple-tiles',
type: 'raster',
source: 'raster-tiles',
id: "simple-tiles",
type: "raster",
source: "raster-tiles",
minzoom: 0,
maxzoom: 22,
},
],
}
},
};

// ==============================================================================================================================
Expand Down Expand Up @@ -403,7 +403,7 @@ const REFRESH_BUFFER_MS: number = 1000;
*/
export const KPI_STATS_CACHE_TIME_MS: number =
parseIntEnv(ENVS.KPI_STATS_CACHE_TIME, DEFAULT_KPI_STATS_CACHE_TIME_SECONDS) *
1000 +
1000 +
REFRESH_BUFFER_MS;

// ==============================================================================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const ProgressBar: React.FC<ProgressBarProps> = ({
pages,
}) => {
const navigate = useNavigate();
const { getFullPath, isModelOwner } = useModelsContext();
const { getFullPath, isModelOwner, isEditMode } = useModelsContext();
const activeStepRef = useRef<HTMLButtonElement | null>(null);
const containerRef = useRef<HTMLDivElement | null>(null);

Expand Down Expand Up @@ -50,11 +50,11 @@ const ProgressBar: React.FC<ProgressBarProps> = ({
const isConfirmationPage = currentPath.includes(
MODELS_ROUTES.CONFIRMATION,
);
// Disable the model details and training dataset if the user is not the owner of the model
// Disable the model details and training dataset if the user is not the owner of the model and if in edit mode.
const disableButton =
isLastPage ||
isConfirmationPage ||
(!isModelOwner && [0, 1].includes(index));
(!isModelOwner && [0, 1].includes(index) && isEditMode);
return (
<button
key={`current-form-progress-${step.id}`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const OpenAerialMap = ({
}, [map, fitToTMSBounds]);

return (
<div className="flex w-full flex-col gap-y-2 border-b-8 border-off-white py-2 px-4 pb-4">
<div className="flex w-full flex-col gap-y-2 border-b-8 border-off-white py-2 px-4 pb-2">
<p className="text-body-2 md:text-body-1 font-medium">
{MODELS_CONTENT.modelCreation.trainingArea.form.openAerialMap}
</p>
Expand All @@ -66,7 +66,7 @@ const OpenAerialMap = ({
}
</p>
) : isPending ? (
<div className="w-full h-20 bg-gray-border animate-pulse"></div>
<div className="w-full h-16 bg-gray-border animate-pulse"></div>
) : (
<>
<div className="flex gap-x-3 justify-between w-full">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ const TrainingAreaList = ({
});

return (
<div className="flex max-h-[60%] flex-col gap-y-4 justify-between p-2 lg:p-4">
<div className="flex items-start w-full flex-col gap-y-4">
<div className="flex flex-col overflow-y-auto flex-1 h-full gap-y-2 justify-between p-2 lg:p-4">
<div className="flex items-start w-full flex-col gap-y-2">
<p className="text-body-2">
{MODELS_CONTENT.modelCreation.trainingArea.form.trainingArea}
{`${data && data.count > 1 ? "s" : ""}`}{" "}
Expand Down Expand Up @@ -81,7 +81,7 @@ const TrainingAreaList = ({
/>
</div>
</div>
<div className="flex items-center justify-center h-full">
<div className="flex items-center justify-center h-full flex-1 overflow-y-auto">
{data?.count === 0 ? (
<div className="flex items-center justify-center flex-col gap-y-10 text-center">
<NoTrainingAreaIcon />
Expand All @@ -93,7 +93,7 @@ const TrainingAreaList = ({
) : isPending ? (
<div className="w-full h-full animate-pulse bg-light-gray"></div>
) : (
<div className="h-full overflow-y-auto flex flex-col gap-y-4 w-full">
<div className="h-full flex flex-col gap-y-4 w-full">
{data?.results.features
.sort((a, b) => b.id - a.id)
.map((ta) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const TrainingAreaForm = () => {
successToast={TOAST_NOTIFICATIONS.trainingAreasFileUploadSuccess}
disabled={createTrainingArea.isPending}
/>
<div className="md:h-screen min-h-screen flex flex-col mb-40">
<div className="lg:h-screen min-h-screen flex flex-col mb-40">
<div className="flex md:justify-between md:items-center flex-col md:flex-row gap-y-4 mb-10">
<div className="basis-2/3">
<StepHeading
Expand All @@ -104,15 +104,15 @@ const TrainingAreaForm = () => {
</div>
</div>

<div className="border-t-8 border-x-8 border-off-white mb-10 fullscreen md:no-fullscreen md:hidden">
<div className="border-t-8 border-x-8 border-off-white fullscreen lg:no-fullscreen lg:hidden">
<OpenAerialMap
tileJSONURL={tileJSONURL}
map={map}
trainingDatasetId={Number(formData.selectedTrainingDatasetId)}
/>
</div>
<div className="h-full grid grid-cols-12 md:grid-cols-9 border-8 border-off-white fullscreen md:no-fullscreen">
<div className="w-full h-[90vh] col-span-12 md:col-span-6 2xl:col-span-7">
<div className="h-full grid grid-cols-12 lg:grid-cols-9 border-8 border-off-white fullscreen xl:no-fullscreen">
<div className="w-full h-[90vh] col-span-12 lg:col-span-6 2xl:col-span-7">
<TrainingAreaMap
tileJSONURL={tileJSONURL}
data={trainingAreasData}
Expand All @@ -126,7 +126,7 @@ const TrainingAreaForm = () => {
currentZoom={currentZoom}
/>
</div>
<div className="hidden md:flex h-[90vh] max-h-screen col-span-12 md:col-span-3 2xl:col-span-2 flex-col w-full border-l-8 border-off-white gap-y-6 py-4 ">
<div className="hidden lg:flex h-[90vh] max-h-screen col-span-12 lg:col-span-3 2xl:col-span-2 flex-col w-full border-l-8 border-off-white gap-y-6 py-4 ">
<OpenAerialMap
tileJSONURL={tileJSONURL}
map={map}
Expand All @@ -149,25 +149,22 @@ const TrainingAreaForm = () => {
</div>
</div>

<div className="md:hidden fullscreen md:no-fullscreen border-8 border-off-white py-2">
<div className="h-[60vh] overflow-y-auto ">
<TrainingAreaList
offset={offset}
setOffset={setOffset}
isPlaceholderData={isPlaceholderData}
data={trainingAreasData}
isPending={trainingAreaIsPending}
datasetId={Number(formData.selectedTrainingDatasetId)}
map={map}
/>
</div>
<div className="py-2">
<ActionButtons
toggle={toggle}
trainingAreasDataCount={trainingAreasData?.count}
setDrawingMode={setDrawingMode}
/>
</div>
<div className="flex flex-col lg:hidden h-[90vh] max-h-screen fullscreen lg:no-fullscreen border-8 border-off-white py-2">
<TrainingAreaList
offset={offset}
setOffset={setOffset}
isPlaceholderData={isPlaceholderData}
data={trainingAreasData}
isPending={trainingAreaIsPending}
datasetId={Number(formData.selectedTrainingDatasetId)}
map={map}
/>

<ActionButtons
toggle={toggle}
trainingAreasDataCount={trainingAreasData?.count}
setDrawingMode={setDrawingMode}
/>
</div>
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useMapInstance } from "@/hooks/use-map-instance";

const mapSourceName = "models";
// Font from OpenFreeMap
const licensedFonts = ['Open Sans Semibold'];
const licensedFonts = ["Open Sans Semibold"];

let markerIcon = new Image(17, 20);
markerIcon.src = MapMarkerIcon;
Expand Down
Loading