Skip to content

Commit

Permalink
chore: xml conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
jeafreezy committed Nov 28, 2024
1 parent 27b3d67 commit b0dfe2c
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 48 deletions.
32 changes: 23 additions & 9 deletions frontend/src/app/routes/start-mapping.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,22 +135,36 @@ export const StartMappingPage = () => {
};
}, [query, map, currentZoom, trainingDataset, modelId, data]);

const renderModelHeader = useMemo(() => {
return (
<ModelHeader
data={data}
trainingDatasetIsPending={trainingDatasetIsPending}
modelPredictionsExist={modelPredictionsExist}
trainingDatasetIsError={trainingDatasetIsError}
modelPredictions={modelPredictions}
trainingDataset={trainingDataset}
oamTileJSON={oamTileJSON}
/>
);
}, [
data,
trainingDatasetIsPending,
modelPredictionsExist,
trainingDatasetIsError,
modelPredictions,
trainingDataset,
oamTileJSON,
]);

return (
<>
<Head title={APPLICATION_CONTENTS.START_MAPPING.pageTitle(data?.name)} />
<BackButton />

<div className="min-h-screen md:h-[90vh] flex mt-8 flex-col mb-20">
<div>
<ModelHeader
data={data}
trainingDatasetIsPending={trainingDatasetIsPending}
modelPredictionsExist={modelPredictionsExist}
trainingDatasetIsError={trainingDatasetIsError}
modelPredictions={modelPredictions}
trainingDataset={trainingDataset}
oamTileJSON={oamTileJSON}
/>
{renderModelHeader}
<div className="hidden md:block w-full">
<Divider />
</div>
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/contents/start-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ export const START_MAPPING_CONTENT = {
label: "download",
options: {
allFeatures: "All Features as GeoJSON",
acceptedFeatures: "Accepted Features Only",
openAllFeaturesInJOSM: "Open All Features in JOSM",
openAcceptedFeaturesInJOSM: "Open All Features in JOSM",
acceptedFeatures: "Accepted Features as GeoJSON",
openAllFeaturesInJOSM: "All Features to JOSM",
openAcceptedFeaturesInJOSM: "Accepted Features to JOSM",
},
},
predictionInProgress: "running",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/contents/toast-notifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export const TOAST_NOTIFICATIONS = {
modelUpdateSuccess: "Model updated successfully.",

// JOSM

errorLoadingData: "An error occurred while loading data",
dataLoadingSuccess: "Data loaded successfully",
josmOpenSuccess: "Map view opened in JOSM successfully!",
josmBBOXZoomFailed: "Failed to zoom to the bounding box in JOSM.",
josmImageryLoadFailed: "Failed to load imagery in JOSM.",
Expand Down
42 changes: 23 additions & 19 deletions frontend/src/features/start-mapping/components/model-action.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TModelPredictions } from "@/types";
import { Feature, TModelPredictions } from "@/types";
import {
MIN_ZOOM_LEVEL_FOR_PREDICTION,
showErrorToast,
Expand Down Expand Up @@ -34,32 +34,36 @@ const ModelAction = ({
);

/**
* When a prediction is retrived from the backend and it hasn't been interacted with (i.e in the `all` array),
* When a prediction is retrieved from the backend and it hasn't been interacted with (i.e in the `all` array),
* override it. But if it has been interacted with (i.e in either `rejected` or `accepted` array, leave it.)
*/

const nonIntersectingFeatures = data.features.filter((newFeature) => {
return (
!modelPredictions.accepted.some((acceptedFeature) =>
booleanIntersects(acceptedFeature, newFeature),
) &&
!modelPredictions.rejected.some((rejectedFeature) =>
booleanIntersects(rejectedFeature, newFeature),
)
const doesNotIntersectAccepted = modelPredictions.accepted.every(
(acceptedFeature) => {
const intersects = booleanIntersects(newFeature, acceptedFeature);
return !intersects;
},
);

const doesNotIntersectRejected = modelPredictions.rejected.every(
(rejectedFeature) => {
const intersects = booleanIntersects(newFeature, rejectedFeature);
return !intersects;
},
);

return doesNotIntersectAccepted && doesNotIntersectRejected;
});

setModelPredictions((prev) => ({
...prev,
all: [
...nonIntersectingFeatures.map((feature) => ({
...feature,
properties: {
...feature.properties,
id: uuid4(), // Add unique ID for tracking
},
})),
],
all: nonIntersectingFeatures.map((feature) => ({
...feature,
properties: {
...feature.properties,
id: uuid4(), // Add unique ID for tracking
},
})),
}));
},
onError: (error) => showErrorToast(error),
Expand Down
42 changes: 32 additions & 10 deletions frontend/src/features/start-mapping/components/model-header.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useMap } from "@/app/providers/map-provider";
import { ButtonWithIcon } from "@/components/ui/button";
import { Divider } from "@/components/ui/divider";
import { DropDown } from "@/components/ui/dropdown";
Expand All @@ -7,7 +8,7 @@ import { APPLICATION_CONTENTS, TOAST_NOTIFICATIONS } from "@/contents";
import { ModelDetailsPopUp } from "@/features/models/components";
import { useDropdownMenu } from "@/hooks/use-dropdown-menu";
import {
BBOX,
Feature,
TileJSON,
TModel,
TModelPredictions,
Expand Down Expand Up @@ -40,6 +41,7 @@ const ModelHeader = ({
}) => {
const { onDropdownHide, onDropdownShow, dropdownIsOpened } =
useDropdownMenu();
const { map } = useMap();
const [showModelDetails, setShowModelDetails] = useState<boolean>(false);

const popupAnchorId = "model-details";
Expand Down Expand Up @@ -67,13 +69,33 @@ const ModelHeader = ({
showSuccessToast(TOAST_NOTIFICATIONS.startMapping.fileDownloadSuccess);
}, [modelPredictions]);

const handleOpenInJOSM = useCallback(() => {
openInJOSM(
oamTileJSON?.name as string,
trainingDataset?.source_imagery as string,
oamTileJSON?.bounds as BBOX,
);
}, [oamTileJSON, trainingDataset]);
const handleFeaturesDownloadToJOSM = useCallback(
(features: Feature[]) => {
if (!map || !oamTileJSON?.name || !trainingDataset?.source_imagery)
return;

const bounds = [
...map.getBounds().toArray()[0],
...map.getBounds().toArray()[1],
];
openInJOSM(
oamTileJSON.name,
trainingDataset.source_imagery,
//@ts-expect-error bad type definition
bounds,
features,
);
},
[map, oamTileJSON, trainingDataset],
);

const handleAllFeaturesDownloadToJOSM = useCallback(() => {
handleFeaturesDownloadToJOSM(modelPredictions.all);
}, [handleFeaturesDownloadToJOSM, modelPredictions.all]);

const handleAcceptedFeaturesDownloadToJOSM = useCallback(() => {
handleFeaturesDownloadToJOSM(modelPredictions.accepted);
}, [handleFeaturesDownloadToJOSM, modelPredictions.accepted]);

const downloadButtonDropdownOptions = [
{
Expand All @@ -97,15 +119,15 @@ const ModelHeader = ({
value:
APPLICATION_CONTENTS.START_MAPPING.buttons.download.options
.openAllFeaturesInJOSM,
onClick: handleOpenInJOSM,
onClick: handleAllFeaturesDownloadToJOSM,
},
{
name: APPLICATION_CONTENTS.START_MAPPING.buttons.download.options
.openAcceptedFeaturesInJOSM,
value:
APPLICATION_CONTENTS.START_MAPPING.buttons.download.options
.openAcceptedFeaturesInJOSM,
onClick: handleOpenInJOSM,
onClick: handleAcceptedFeaturesDownloadToJOSM,
},
];
return (
Expand Down
1 change: 1 addition & 0 deletions frontend/src/features/start-mapping/components/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const PredictedFeatureActionPopup = ({

useEffect(() => {
if (!map || !popupRef.current) return;
// reset if in comment mode
setShowComment(false);
const _popup = new maplibregl.Popup({ closeButton: false })
.setLngLat(event.lngLat)
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/services/api-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export const API_ENDPOINTS = {
// KPIs
GET_KPI_STATS: "kpi/stats/ ",

// GeoJSON to OSM

GEOJSON_TO_OSM: "geojson2osm/",

// Banner

GET_BANNER: "banner",
Expand Down
47 changes: 41 additions & 6 deletions frontend/src/utils/general-utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { API_ENDPOINTS, BASE_API_URL } from "@/services";
import { API_ENDPOINTS, apiClient, BASE_API_URL } from "@/services";
import { BBOX, Feature, FeatureCollection } from "@/types";
import {
FAIR_VERSION,
Expand Down Expand Up @@ -158,7 +158,8 @@ export const uuid4 = function (): string {
export const openInJOSM = async (
oamTileName: string,
tmsURL: string,
oamBounds: BBOX,
bounds: BBOX,
data: Feature[],
) => {
try {
const imgURL = new URL("http://127.0.0.1:8111/imagery");
Expand All @@ -174,12 +175,46 @@ export const openInJOSM = async (
}

const loadurl = new URL("http://127.0.0.1:8111/load_and_zoom");
loadurl.searchParams.set("bottom", String(oamBounds[1]));
loadurl.searchParams.set("top", String(oamBounds[3]));
loadurl.searchParams.set("left", String(oamBounds[0]));
loadurl.searchParams.set("right", String(oamBounds[2]));
loadurl.searchParams.set("bottom", String(bounds[1]));
loadurl.searchParams.set("top", String(bounds[3]));
loadurl.searchParams.set("left", String(bounds[0]));
loadurl.searchParams.set("right", String(bounds[2]));

const zoomResponse = await fetch(loadurl);
// XML Conversion
if (data) {
try {
const res = await apiClient.post(API_ENDPOINTS.GEOJSON_TO_OSM, {
geojson: {
type: "FeatureCollection",
// Remove the id properties, otherwise it'll throw server error.
features: data.map((feature) => ({
...feature,
properties: {
...Object.fromEntries(
Object.entries(feature.properties).filter(
([key]) => key !== "id",
),
),
},
})),
name: "prediction",
},
});
const _data = await res.data;
const loadData = new URL("http://127.0.0.1:8111/load_data");
loadData.searchParams.set("new_layer", "true");
loadData.searchParams.set("data", _data);
const response = await fetch(loadData);
// No need to show success toast since there'll be a success toast later on
// This is to avoid multiple toasts showing up at once.
if (!response.ok) {
showErrorToast(undefined, TOAST_NOTIFICATIONS.errorLoadingData);
}
} catch (error) {
showErrorToast(error);
}
}

if (zoomResponse.ok) {
showSuccessToast(TOAST_NOTIFICATIONS.josmOpenSuccess);
Expand Down

0 comments on commit b0dfe2c

Please sign in to comment.