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/go back in history #344

Merged
merged 8 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
8 changes: 6 additions & 2 deletions frontend/src/app/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ const router = createBrowserRouter([
*/

/**
* Auth route
* Auth route starts.
*/
{
path: APPLICATION_ROUTES.AUTH_CALLBACK,
Expand All @@ -333,7 +333,11 @@ const router = createBrowserRouter([
return { Component: AuthenticationCallbackPage };
},
},


/**
* Auth route ends.
*/

/**
* 404 route
*/
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/app/routes/models/model-details-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ export const ModelDetailsPage = () => {
trainingId={data?.published_training as number}
datasetId={data?.dataset as number}
/>

<BackButton className="mt-6" />
<BackButton className="mt-6" route={APPLICATION_ROUTES.MODELS} />
<div className="my-12 flex flex-col gap-y-20">
<ModelDetailsInfo
data={data as TModelDetails}
Expand Down
65 changes: 25 additions & 40 deletions frontend/src/app/routes/start-mapping.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
START_MAPPING_PAGE_CONTENT,
TOAST_NOTIFICATIONS,
} from "@/constants";
import { BASE_MODELS } from "@/enums";
import { FitToBounds, LayerControl, ZoomLevel } from "@/components/map";
import { Head } from "@/components/seo";
import { LngLatBoundsLike } from "maplibre-gl";
Expand All @@ -18,11 +17,10 @@ import { useModelDetails } from "@/features/models/hooks/use-models";
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
import { UserProfile } from "@/components/layout";
import {
BBOX,
Feature,
TileJSON,
TModelPredictions,
TModelPredictionsConfig,
TTrainingDataset,
} from "@/types";
import {
BrandLogoWithDropDown,
Expand All @@ -38,7 +36,6 @@ import {
showSuccessToast,
} from "@/utils";
import {
PREDICTION_API_FILE_EXTENSIONS,
REJECTED_MODEL_PREDICTIONS_FILL_LAYER_ID,
REJECTED_MODEL_PREDICTIONS_OUTLINE_LAYER_ID,
MIN_ZOOM_LEVEL_FOR_START_MAPPING_PREDICTION,
Expand Down Expand Up @@ -70,22 +67,24 @@ export const StartMappingPage = () => {
const { map, mapContainerRef, currentZoom } = useMapInstance();
const { isSmallViewport } = useScreenSize();
const navigate = useNavigate();
const bounds = map?.getBounds();

const [showModelDetailsPopup, setShowModelDetailsPopup] =
useState<boolean>(false);
const { dropdownIsOpened, onDropdownHide, onDropdownShow } =
useDropdownMenu();

const { isError, isPending, data, error } = useModelDetails(
modelId as string,
!!modelId,
);
const {
isError,
isPending,
data: modelInfo,
error,
} = useModelDetails(modelId as string, !!modelId);

const {
data: trainingDataset,
isPending: trainingDatasetIsPending,
isError: trainingDatasetIsError,
} = useGetTrainingDataset(data?.dataset as number, !isPending);
} = useGetTrainingDataset(modelInfo?.dataset as number, !isPending);

const tileJSONURL = extractTileJSONURL(trainingDataset?.source_imagery ?? "");

Expand Down Expand Up @@ -119,6 +118,7 @@ export const StartMappingPage = () => {
};
});

// Todo - move to local storage
const [modelPredictions, setModelPredictions] = useState<TModelPredictions>({
all: [],
accepted: [],
Expand Down Expand Up @@ -149,25 +149,6 @@ export const StartMappingPage = () => {
[searchParams, setSearchParams],
);

const trainingConfig: TModelPredictionsConfig = {
tolerance: query[SEARCH_PARAMS.tolerance] as number,
area_threshold: query[SEARCH_PARAMS.area] as number,
use_josm_q: query[SEARCH_PARAMS.useJOSMQ] as boolean,
confidence: query[SEARCH_PARAMS.confidenceLevel] as number,
checkpoint: `/mnt/efsmount/data/trainings/dataset_${data?.dataset}/output/training_${data?.published_training}/checkpoint${PREDICTION_API_FILE_EXTENSIONS[data?.base_model as BASE_MODELS]}`,
max_angle_change: 15,
model_id: modelId as string,
skew_tolerance: 15,
source: trainingDataset?.source_imagery as string,
zoom_level: currentZoom,
bbox: [
bounds?.getWest(),
bounds?.getSouth(),
bounds?.getEast(),
bounds?.getNorth(),
] as BBOX,
};

const disablePrediction =
currentZoom < MIN_ZOOM_LEVEL_FOR_START_MAPPING_PREDICTION;

Expand Down Expand Up @@ -225,18 +206,18 @@ export const StartMappingPage = () => {
...modelPredictions.all,
],
},
`all_predictions_${data.dataset}`,
`all_predictions_${modelInfo.dataset}`,
);
showSuccessToast(TOAST_NOTIFICATIONS.startMapping.fileDownloadSuccess);
}, [modelPredictions]);
}, [modelPredictions, modelInfo]);

const handleAcceptedFeaturesDownload = useCallback(async () => {
geoJSONDowloader(
{ type: "FeatureCollection", features: modelPredictions.accepted },
`accepted_predictions_${data.dataset}`,
`accepted_predictions_${modelInfo.dataset}`,
);
showSuccessToast(TOAST_NOTIFICATIONS.startMapping.fileDownloadSuccess);
}, [modelPredictions]);
}, [modelPredictions, modelInfo]);

const handleFeaturesDownloadToJOSM = useCallback(
(features: Feature[]) => {
Expand Down Expand Up @@ -316,13 +297,12 @@ export const StartMappingPage = () => {

return (
<>
<Head title={START_MAPPING_PAGE_CONTENT.pageTitle(data?.name)} />
<Head title={START_MAPPING_PAGE_CONTENT.pageTitle(modelInfo?.name)} />
{/* Mobile dialog */}
<div className="h-screen flex flex-col fullscreen">
<StartMappingMobileDrawer
isOpen={isSmallViewport}
disablePrediction={disablePrediction}
trainingConfig={trainingConfig}
setModelPredictions={setModelPredictions}
modelPredictions={modelPredictions}
map={map}
Expand All @@ -332,31 +312,33 @@ export const StartMappingPage = () => {
updateQuery={updateQuery}
modelDetailsPopupIsActive={showModelDetailsPopup}
clearPredictions={clearPredictions}
trainingDataset={trainingDataset as TTrainingDataset}
currentZoom={currentZoom}
modelInfo={modelInfo}
/>
<div className="sticky top-0 bg-white z-10 px-4 xl:px-large py-1 hidden md:block">
{/* Model Details Popup */}
{data && (
{modelInfo && (
<ModelDetailsPopUp
showPopup={showModelDetailsPopup}
handlePopup={handleModelDetailsPopup}
closeMobileDrawer={() => setShowModelDetailsPopup(false)}
anchor={popupAnchorId}
model={data}
model={modelInfo}
trainingDataset={trainingDataset}
trainingDatasetIsPending={trainingDatasetIsPending}
trainingDatasetIsError={trainingDatasetIsError}
/>
)}
{/* Web Header */}
<StartMappingHeader
data={data}
modelInfo={modelInfo}
trainingDatasetIsPending={trainingDatasetIsPending}
modelPredictionsExist={modelPredictionsExist}
trainingDatasetIsError={trainingDatasetIsError}
modelPredictions={modelPredictions}
query={query}
updateQuery={updateQuery}
trainingConfig={trainingConfig}
setModelPredictions={setModelPredictions}
map={map}
disablePrediction={disablePrediction}
Expand All @@ -365,6 +347,8 @@ export const StartMappingPage = () => {
handleModelDetailsPopup={handleModelDetailsPopup}
downloadOptions={downloadOptions}
clearPredictions={clearPredictions}
trainingDataset={trainingDataset as TTrainingDataset}
currentZoom={currentZoom}
/>
</div>
<div className="col-span-12 h-[70vh] md:h-full md:border-8 md:border-off-white flex-grow relative map-elements-z-index">
Expand All @@ -378,6 +362,7 @@ export const StartMappingPage = () => {
onClose={onDropdownHide}
onShow={onDropdownShow}
isOpened={dropdownIsOpened}
modelId={modelInfo?.id}
/>
</div>
<div className="absolute top-[10vh] right-4 z-[2] flex flex-col gap-y-4 items-end">
Expand Down Expand Up @@ -408,7 +393,7 @@ export const StartMappingPage = () => {
currentZoom={currentZoom}
layers={mapLayers}
tmsBounds={oamTileJSON?.bounds as LngLatBoundsLike}
trainingId={data?.published_training}
trainingId={modelInfo?.published_training}
/>
</div>
</div>
Expand Down
16 changes: 14 additions & 2 deletions frontend/src/components/ui/button/back-button.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import { ArrowBackIcon } from "@/components/ui/icons";
import { useNavigate } from "react-router-dom";

const BackButton = ({ className }: { className?: string }) => {
const BackButton = ({
className,
route,
}: {
className?: string;
route?: string;
}) => {
const navigate = useNavigate();
return (
<button
className={`flex items-center gap-x-2 ${className}`}
onClick={() => navigate(-1)}
onClick={() => {
if (route) {
navigate(route);
} else {
navigate(-1);
}
}}
title="Go back"
>
<ArrowBackIcon className="icon md:icon-lg" />
Expand Down
22 changes: 14 additions & 8 deletions frontend/src/features/start-mapping/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,20 @@ import { ModelPredictionsTracker } from "@/features/start-mapping/components/mod
import { ModelSettings } from "@/features/start-mapping/components/model-settings";
import { SkeletonWrapper } from "@/components/ui/skeleton";
import { TDownloadOptions, TQueryParams } from "@/app/routes/start-mapping";
import { TModel, TModelPredictions, TModelPredictionsConfig } from "@/types";
import { TModel, TModelPredictions, TTrainingDataset } from "@/types";
import { ToolTip } from "@/components/ui/tooltip";
import { useDropdownMenu } from "@/hooks/use-dropdown-menu";
import { UserProfile } from "@/components/layout";
import { START_MAPPING_PAGE_CONTENT } from "@/constants";

const StartMappingHeader = ({
data,
modelInfo,
modelPredictions,
modelPredictionsExist,
trainingDatasetIsPending,
trainingDatasetIsError,
query,
updateQuery,
trainingConfig,
setModelPredictions,
disablePrediction,
map,
Expand All @@ -34,15 +33,16 @@ const StartMappingHeader = ({
modelDetailsPopupIsActive,
downloadOptions,
clearPredictions,
trainingDataset,
currentZoom,
}: {
modelPredictionsExist: boolean;
trainingDatasetIsPending: boolean;
trainingDatasetIsError: boolean;
data: TModel;
modelInfo: TModel;
modelPredictions: TModelPredictions;
query: TQueryParams;
updateQuery: (newParams: TQueryParams) => void;
trainingConfig: TModelPredictionsConfig;
setModelPredictions: React.Dispatch<React.SetStateAction<TModelPredictions>>;
map: Map | null;
disablePrediction: boolean;
Expand All @@ -51,6 +51,8 @@ const StartMappingHeader = ({
modelDetailsPopupIsActive: boolean;
downloadOptions: TDownloadOptions;
clearPredictions: () => void;
trainingDataset: TTrainingDataset;
currentZoom: number;
}) => {
const { onDropdownHide, onDropdownShow, dropdownIsOpened } =
useDropdownMenu();
Expand All @@ -72,13 +74,14 @@ const StartMappingHeader = ({
onClose={onFAIRLogoDropdownHide}
onShow={onFAIRLogoDropdownShow}
isOpened={FAIRLogoDropdownIsOpened}
modelId={modelInfo?.id}
/>
<div className="flex flex-col md:flex-row md:items-center gap-x-4 z-10">
<p
title={data?.name}
title={modelInfo?.name}
className="text-dark text-body-2base text-nowrap truncate md:max-w-[20px] lg:max-w-[300px] xl:max-w-[400px]"
>
{data?.name ?? "N/A"}
{modelInfo?.name ?? "N/A"}
</p>
<ModelDetailsButton
onClick={handleModelDetailsPopup}
Expand Down Expand Up @@ -132,9 +135,12 @@ const StartMappingHeader = ({
<ModelAction
modelPredictions={modelPredictions}
setModelPredictions={setModelPredictions}
trainingConfig={trainingConfig}
map={map}
disablePrediction={disablePrediction}
query={query}
trainingDataset={trainingDataset}
currentZoom={currentZoom}
modelInfo={modelInfo}
/>
<UserProfile hideFullName smallerSize />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@ import { Link } from "@/components/ui/link";
import { navLinks } from "@/constants/general";
import { NavLogo } from "@/components/layout";
import { useNavigate } from "react-router-dom";
import { APPLICATION_ROUTES } from "@/constants";

type BrandLogoWithDropDownProps = {
isOpened: boolean;
onClose: () => void;
onShow: () => void;
modelId?: string;
};

export const BrandLogoWithDropDown = function BrandLogoWithDropDown({
export const BrandLogoWithDropDown = ({
isOpened,
onClose,
onShow,
}: BrandLogoWithDropDownProps) {
modelId,
}: BrandLogoWithDropDownProps) => {
const navigate = useNavigate();
const navItems = navLinks.map((link, id) => (
<li key={`${link.title}-${id}`}>
<Link
Expand All @@ -31,8 +35,6 @@ export const BrandLogoWithDropDown = function BrandLogoWithDropDown({
</Link>
</li>
));

const navigate = useNavigate();
return (
<DropDown
placement={DropdownPlacement.BOTTOM_START}
Expand All @@ -48,7 +50,13 @@ export const BrandLogoWithDropDown = function BrandLogoWithDropDown({
<Divider />
<button
className="text-body-3 block w-full px-4 py-2 text-start hover:bg-off-white hover:rounded-b-xl text-primary"
onClick={() => navigate(-1)}
onClick={() => {
/**
* Since this is on the start-mapping page, when they click on stop mapping, regardless of how they got here,
* they will be redirected to the model card/details page.
*/
navigate(`${APPLICATION_ROUTES.MODELS}/${modelId}`);
}}
>
Stop Mapping
</button>
Expand Down
Loading
Loading