From dedd45506f38bfcf96f7c50ee314180778284fe8 Mon Sep 17 00:00:00 2001 From: Oliver Fritz Date: Thu, 6 Feb 2025 16:07:14 +0100 Subject: [PATCH 1/7] feat(manager-dashboard): show custom options input for street tutorials --- manager-dashboard/app/views/NewTutorial/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/manager-dashboard/app/views/NewTutorial/index.tsx b/manager-dashboard/app/views/NewTutorial/index.tsx index 76f238066..a6fc640ce 100644 --- a/manager-dashboard/app/views/NewTutorial/index.tsx +++ b/manager-dashboard/app/views/NewTutorial/index.tsx @@ -69,6 +69,7 @@ import { PROJECT_TYPE_COMPLETENESS, PROJECT_TYPE_CHANGE_DETECTION, PROJECT_TYPE_FOOTPRINT, + PROJECT_TYPE_STREET, ProjectType, projectTypeLabelMap, } from '#utils/common'; @@ -761,7 +762,10 @@ function NewTutorial(props: Props) { autoFocus /> - {value.projectType === PROJECT_TYPE_FOOTPRINT && ( + {( + value.projectType === PROJECT_TYPE_FOOTPRINT + || value.projectType === PROJECT_TYPE_STREET + ) && ( Date: Thu, 6 Feb 2025 16:58:11 +0100 Subject: [PATCH 2/7] feat(manager-dashboard): handle default custom options on project type change --- .../app/views/NewTutorial/index.tsx | 4 +- .../app/views/NewTutorial/utils.ts | 40 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/manager-dashboard/app/views/NewTutorial/index.tsx b/manager-dashboard/app/views/NewTutorial/index.tsx index a6fc640ce..9ce9d4b67 100644 --- a/manager-dashboard/app/views/NewTutorial/index.tsx +++ b/manager-dashboard/app/views/NewTutorial/index.tsx @@ -77,7 +77,7 @@ import { import { tileServerUrls, tutorialFormSchema, - defaultFootprintCustomOptions, + getDefaultOptions, TutorialFormType, PartialTutorialFormType, PartialInformationPagesType, @@ -342,7 +342,6 @@ const defaultTutorialFormValue: PartialTutorialFormType = { name: TILE_SERVER_ESRI, credits: tileServerDefaultCredits[TILE_SERVER_ESRI], }, - customOptions: defaultFootprintCustomOptions, }; type SubmissionStatus = 'started' | 'imageUpload' | 'tutorialSubmit' | 'success' | 'failed'; @@ -717,6 +716,7 @@ function NewTutorial(props: Props) { setFieldValue(undefined, 'tutorialTasks'); setFieldValue(undefined, 'scenarioPages'); setFieldValue(newValue, 'projectType'); + setFieldValue(getDefaultOptions(newValue), 'customOptions'); }, [setFieldValue], ); diff --git a/manager-dashboard/app/views/NewTutorial/utils.ts b/manager-dashboard/app/views/NewTutorial/utils.ts index 90b805f5d..4fc6deebf 100644 --- a/manager-dashboard/app/views/NewTutorial/utils.ts +++ b/manager-dashboard/app/views/NewTutorial/utils.ts @@ -26,6 +26,7 @@ import { PROJECT_TYPE_CHANGE_DETECTION, PROJECT_TYPE_COMPLETENESS, PROJECT_TYPE_FOOTPRINT, + PROJECT_TYPE_STREET, IconKey, } from '#utils/common'; @@ -257,6 +258,33 @@ export const defaultFootprintCustomOptions: PartialTutorialFormType['customOptio }, ]; +export const defaultStreetCustomOptions: PartialTutorialFormType['customOptions'] = [ + { + optionId: 1, + value: 1, + title: 'Yes', + icon: 'checkmark-outline', + iconColor: colorKeyToColorMap.green, + description: '', + }, + { + optionId: 2, + value: 0, + title: 'No', + icon: 'close-outline', + iconColor: colorKeyToColorMap.red, + description: '', + }, + { + optionId: 3, + value: 2, + title: 'Not Sure', + icon: 'remove-outline', + iconColor: colorKeyToColorMap.gray, + description: 'if you\'re not sure or there is bad imagery', + }, +]; + export function deleteKey( value: T, key: K, @@ -268,6 +296,18 @@ export function deleteKey( return copy; } +export function getDefaultOptions(projectType: ProjectType | undefined) { + if (projectType === PROJECT_TYPE_FOOTPRINT) { + return defaultFootprintCustomOptions; + } + + if (projectType === PROJECT_TYPE_STREET) { + return defaultStreetCustomOptions; + } + + return undefined; +} + export interface BuildAreaProperties { reference: number; screen: number; From 3826747f7ac486fe3aa64dfdd7dceb7042a3bf50 Mon Sep 17 00:00:00 2001 From: Oliver Fritz Date: Thu, 6 Feb 2025 17:06:50 +0100 Subject: [PATCH 3/7] feat(manager-dashboard): hide tileserver input for street tutorials --- .../app/views/NewTutorial/index.tsx | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/manager-dashboard/app/views/NewTutorial/index.tsx b/manager-dashboard/app/views/NewTutorial/index.tsx index 9ce9d4b67..dccf7f4d6 100644 --- a/manager-dashboard/app/views/NewTutorial/index.tsx +++ b/manager-dashboard/app/views/NewTutorial/index.tsx @@ -646,6 +646,11 @@ function NewTutorial(props: Props) { || tutorialSubmissionStatus === 'tutorialSubmit' ); + const tileServerVisible = value.projectType === PROJECT_TYPE_BUILD_AREA + || value.projectType === PROJECT_TYPE_FOOTPRINT + || value.projectType === PROJECT_TYPE_COMPLETENESS + || value.projectType === PROJECT_TYPE_CHANGE_DETECTION; + const tileServerBVisible = value.projectType === PROJECT_TYPE_CHANGE_DETECTION || value.projectType === PROJECT_TYPE_COMPLETENESS; @@ -900,17 +905,20 @@ function NewTutorial(props: Props) { )} - - - + {tileServerVisible && ( + + + + )} + {tileServerBVisible && ( Date: Wed, 19 Feb 2025 16:28:15 +0100 Subject: [PATCH 4/7] feat(street-tutorials): add street tutorial sample scenario and instructions README --- mapswipe_workers/sample_data/street/README.md | 58 +++++++++++++++++++ .../street_tutorial_sample_scenario.geojson | 17 ++++++ 2 files changed, 75 insertions(+) create mode 100644 mapswipe_workers/sample_data/street/README.md create mode 100644 mapswipe_workers/sample_data/street/street_tutorial_sample_scenario.geojson diff --git a/mapswipe_workers/sample_data/street/README.md b/mapswipe_workers/sample_data/street/README.md new file mode 100644 index 000000000..dfa52293e --- /dev/null +++ b/mapswipe_workers/sample_data/street/README.md @@ -0,0 +1,58 @@ +# Creating a New 'Street' Tutorial +### Useful Links +- MapSwipe Development Server: [https://dev-managers.mapswipe.org] +- MapSwipe Development App Installation Guide: [https://github.com/mapswipe/mapswipe/wiki/How-to-test-the-development-version-of-MapSwipe](https://github.com/mapswipe/mapswipe/wiki/How-to-test-the-development-version-of-MapSwipe) + +## Select appropriate Mapillary imagery for the tutorial (with JOSM and Mapillary plug-in) + +1. Open JOSM. Make sure the [JOSM Mapillary plug-in](https://wiki.openstreetmap.org/wiki/JOSM/Plugins/Mapillary) is installed +2. **File > Download data**. Select an area in which you expect appropriate example imagery available on Mapillary and **Download** +3. **Imagery > Mapillary** to download sequences and images for the current area +4. If helpful, use the Mapillary filter dialog to filter images (for start and end date, user and/or organization) +5. Click **Mapillary** in Layers controls to select the Mapillary layer +6. Zoom in until you can see images location markers (green dots) +7. Click on the dots to view the images +8. Once you have found an image that you would like to use in your tutorial, **File > Export Mapillary images** and select **Export selected images** +9. Click **Explore** +10. Choose a parent folder for all images in this tutorial +11. **OK** +12. Repeat until you have exported all the images that you would like to use in the tutorial. Use the same parent folder for all images. + +## Add exported Mapillary images as geotagged images in QGIS + +1. Open QGIS +2. **Processing Toolbox > Vector creation > Import geotagged photos** +3. Select the folder containing all exported Mapillary images and check **Scan recursively** +4. **Run** +5. **Properties > Display** and add `` to HTML Map Tip to show images on a pop up +6. **View > Show Map Tips** +7. If you keep the mouse tip on the image markers, a pop up with the image will appear + +## Edit geotagged images in QGIS + +1. Right click on layer. +2. **Properties > Field** +3. **Toggle editing mode** +4. Change the name of the `filename` column to `id` +5. Add `Integer (32 bit)` columns titled `screen` and `reference`. +6. Populate the `reference` and `screen` fields. + * `reference` is the value of the correct answer option for the image. + * `screen` determines the order of the images in the tutorial and should start with `1`. +7. Delete any rows representing images that you do not want to use + +## Export as GeoJSON + +1. **Toggle editing mode** +2. **Save** +3. Right click, **Export > Save Features As...** +4. Choose Format GeoJSON, CRS EPSG:4326 - WGS 84 +5. Select only `id`, `reference` and `screen` as fields to export. Deselect all other fields. +6. Choose a file name and location and click OK to save + +## Create tutorial + +1. Go to https://dev-managers.mapswipe.org/ +2. Select **Projects** and then **Add New Tutorial**. +3. Check that **Project Type** is set to **Street**. +4. Fill in all the fields, following the instructions. Upload your `GeoJSON` you just created with the scenarios where it says **Scenario Pages**. +5. Submit diff --git a/mapswipe_workers/sample_data/street/street_tutorial_sample_scenario.geojson b/mapswipe_workers/sample_data/street/street_tutorial_sample_scenario.geojson new file mode 100644 index 000000000..3a56f6d50 --- /dev/null +++ b/mapswipe_workers/sample_data/street/street_tutorial_sample_scenario.geojson @@ -0,0 +1,17 @@ +{ + "type": "FeatureCollection", + "name": "cobblestone-scenario", + "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, + "features": [ + { + "type": "Feature", + "properties": { "id": "378811598610667", "reference": 0, "screen": 2 }, + "geometry": { "type": "Point", "coordinates": [ 13.45285, 52.508467, 0.0 ] } + }, + { + "type": "Feature", + "properties": { "id": "1171343450849316", "reference": 1, "screen": 1 }, + "geometry": { "type": "Point", "coordinates": [ 13.4514123, 52.5103378, 0.0 ] } + } + ] +} From 32ce566d6c31d493de6b5f13dc5faa445ebe9360 Mon Sep 17 00:00:00 2001 From: Oliver Fritz Date: Wed, 19 Feb 2025 16:42:24 +0100 Subject: [PATCH 5/7] feat(street-tutorials): prepare scenario pages input for street tutorial --- .../views/NewTutorial/ScenarioPageInput/index.tsx | 10 +++++++++- manager-dashboard/app/views/NewTutorial/index.tsx | 5 +++++ manager-dashboard/app/views/NewTutorial/utils.ts | 13 ++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/manager-dashboard/app/views/NewTutorial/ScenarioPageInput/index.tsx b/manager-dashboard/app/views/NewTutorial/ScenarioPageInput/index.tsx index 607434590..b309be7ff 100644 --- a/manager-dashboard/app/views/NewTutorial/ScenarioPageInput/index.tsx +++ b/manager-dashboard/app/views/NewTutorial/ScenarioPageInput/index.tsx @@ -17,6 +17,7 @@ import { PROJECT_TYPE_FOOTPRINT, PROJECT_TYPE_CHANGE_DETECTION, PROJECT_TYPE_COMPLETENESS, + PROJECT_TYPE_STREET, } from '#utils/common'; import TextInput from '#components/TextInput'; import Heading from '#components/Heading'; @@ -318,7 +319,14 @@ export default function ScenarioPageInput(props: Props) { lookFor={lookFor} /> )} - {(projectType && projectType !== PROJECT_TYPE_FOOTPRINT) && ( + {projectType === PROJECT_TYPE_STREET && ( +
+ Preview not available. +
+ )} + {(projectType + && projectType !== PROJECT_TYPE_FOOTPRINT + && projectType !== PROJECT_TYPE_STREET) && ( checkSchema( diff --git a/manager-dashboard/app/views/NewTutorial/utils.ts b/manager-dashboard/app/views/NewTutorial/utils.ts index 4fc6deebf..be3a92fa0 100644 --- a/manager-dashboard/app/views/NewTutorial/utils.ts +++ b/manager-dashboard/app/views/NewTutorial/utils.ts @@ -348,6 +348,12 @@ export interface ChangeDetectionProperties { // taskId: string; } +export interface StreetProperties { + id: string; + reference: number; + screen: number; +} + export type BuildAreaGeoJSON = GeoJSON.FeatureCollection< GeoJSON.Geometry, BuildAreaProperties @@ -363,9 +369,14 @@ export type ChangeDetectionGeoJSON = GeoJSON.FeatureCollection< ChangeDetectionProperties >; +export type StreetGeoJSON = GeoJSON.FeatureCollection< + GeoJSON.Geometry, + StreetProperties +>; + export type TutorialTasksGeoJSON = GeoJSON.FeatureCollection< GeoJSON.Geometry, - BuildAreaProperties | FootprintProperties | ChangeDetectionProperties + BuildAreaProperties | FootprintProperties | ChangeDetectionProperties | StreetProperties >; export type CustomOptions = { From f3ae5498d91b79c706227a0646137a836e876d98 Mon Sep 17 00:00:00 2001 From: Oliver Fritz Date: Thu, 20 Feb 2025 14:01:02 +0100 Subject: [PATCH 6/7] feat(street-tutorial): correct reference value in sample data --- .../street/street_tutorial_sample_scenario.geojson | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mapswipe_workers/sample_data/street/street_tutorial_sample_scenario.geojson b/mapswipe_workers/sample_data/street/street_tutorial_sample_scenario.geojson index 3a56f6d50..8f5b236f0 100644 --- a/mapswipe_workers/sample_data/street/street_tutorial_sample_scenario.geojson +++ b/mapswipe_workers/sample_data/street/street_tutorial_sample_scenario.geojson @@ -5,12 +5,12 @@ "features": [ { "type": "Feature", - "properties": { "id": "378811598610667", "reference": 0, "screen": 2 }, + "properties": { "id": "378811598610667", "reference": 1, "screen": 2 }, "geometry": { "type": "Point", "coordinates": [ 13.45285, 52.508467, 0.0 ] } }, { "type": "Feature", - "properties": { "id": "1171343450849316", "reference": 1, "screen": 1 }, + "properties": { "id": "1171343450849316", "reference": 0, "screen": 1 }, "geometry": { "type": "Point", "coordinates": [ 13.4514123, 52.5103378, 0.0 ] } } ] From c27e228588193c0112e30bdea036375ae12c393b Mon Sep 17 00:00:00 2001 From: Oliver Fritz Date: Thu, 20 Feb 2025 15:08:44 +0100 Subject: [PATCH 7/7] feat(street-tutorial): ensure that custom options are written to tutorial and project drafts --- manager-dashboard/app/views/NewProject/utils.ts | 3 ++- manager-dashboard/app/views/NewTutorial/utils.ts | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/manager-dashboard/app/views/NewProject/utils.ts b/manager-dashboard/app/views/NewProject/utils.ts index c410084b0..685ffd39d 100644 --- a/manager-dashboard/app/views/NewProject/utils.ts +++ b/manager-dashboard/app/views/NewProject/utils.ts @@ -324,7 +324,8 @@ export const projectFormSchema: ProjectFormSchema = { ['projectType'], ['customOptions'], (formValues) => { - if (formValues?.projectType === PROJECT_TYPE_FOOTPRINT) { + if (formValues?.projectType === PROJECT_TYPE_FOOTPRINT + || formValues?.projectType === PROJECT_TYPE_STREET) { return { customOptions: { keySelector: (key) => key.value, diff --git a/manager-dashboard/app/views/NewTutorial/utils.ts b/manager-dashboard/app/views/NewTutorial/utils.ts index be3a92fa0..67f5e4af5 100644 --- a/manager-dashboard/app/views/NewTutorial/utils.ts +++ b/manager-dashboard/app/views/NewTutorial/utils.ts @@ -265,7 +265,7 @@ export const defaultStreetCustomOptions: PartialTutorialFormType['customOptions' title: 'Yes', icon: 'checkmark-outline', iconColor: colorKeyToColorMap.green, - description: '', + description: 'the object you are looking for is in the image.', }, { optionId: 2, @@ -273,7 +273,7 @@ export const defaultStreetCustomOptions: PartialTutorialFormType['customOptions' title: 'No', icon: 'close-outline', iconColor: colorKeyToColorMap.red, - description: '', + description: 'the object you are looking for is NOT in the image.', }, { optionId: 3, @@ -775,7 +775,8 @@ export const tutorialFormSchema: TutorialFormSchema = { }), }; - if (formValues?.projectType === PROJECT_TYPE_FOOTPRINT) { + if (formValues?.projectType === PROJECT_TYPE_FOOTPRINT + || formValues?.projectType === PROJECT_TYPE_STREET) { return { customOptions: customOptionField, };