Skip to content
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
3 changes: 2 additions & 1 deletion manager-dashboard/app/views/NewProject/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -318,7 +319,14 @@ export default function ScenarioPageInput(props: Props) {
lookFor={lookFor}
/>
)}
{(projectType && projectType !== PROJECT_TYPE_FOOTPRINT) && (
{projectType === PROJECT_TYPE_STREET && (
<div>
Preview not available.
</div>
)}
{(projectType
&& projectType !== PROJECT_TYPE_FOOTPRINT
&& projectType !== PROJECT_TYPE_STREET) && (
<SegmentInput
name={undefined}
value={activeSegmentInput}
Expand Down
45 changes: 31 additions & 14 deletions manager-dashboard/app/views/NewTutorial/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,15 @@ import {
PROJECT_TYPE_COMPLETENESS,
PROJECT_TYPE_CHANGE_DETECTION,
PROJECT_TYPE_FOOTPRINT,
PROJECT_TYPE_STREET,
ProjectType,
projectTypeLabelMap,
} from '#utils/common';

import {
tileServerUrls,
tutorialFormSchema,
defaultFootprintCustomOptions,
getDefaultOptions,
TutorialFormType,
PartialTutorialFormType,
PartialInformationPagesType,
Expand Down Expand Up @@ -189,6 +190,11 @@ function getGeoJSONError(
tile_y: 'number',
tile_z: 'number',
},
[PROJECT_TYPE_STREET]: {
id: ['string', 'number'],
reference: 'number',
screen: 'number',
},
};
const schemaErrors = tutorialTasks.features.map(
(feature) => checkSchema(
Expand Down Expand Up @@ -341,7 +347,6 @@ const defaultTutorialFormValue: PartialTutorialFormType = {
name: TILE_SERVER_ESRI,
credits: tileServerDefaultCredits[TILE_SERVER_ESRI],
},
customOptions: defaultFootprintCustomOptions,
};

type SubmissionStatus = 'started' | 'imageUpload' | 'tutorialSubmit' | 'success' | 'failed';
Expand Down Expand Up @@ -646,6 +651,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;

Expand Down Expand Up @@ -716,6 +726,7 @@ function NewTutorial(props: Props) {
setFieldValue(undefined, 'tutorialTasks');
setFieldValue(undefined, 'scenarioPages');
setFieldValue(newValue, 'projectType');
setFieldValue(getDefaultOptions(newValue), 'customOptions');
},
[setFieldValue],
);
Expand Down Expand Up @@ -761,7 +772,10 @@ function NewTutorial(props: Props) {
autoFocus
/>
</InputSection>
{value.projectType === PROJECT_TYPE_FOOTPRINT && (
{(
value.projectType === PROJECT_TYPE_FOOTPRINT
|| value.projectType === PROJECT_TYPE_STREET
) && (
<InputSection
heading="Custom Options"
actions={(
Expand Down Expand Up @@ -896,17 +910,20 @@ function NewTutorial(props: Props) {
)}
</div>
</InputSection>
<InputSection
heading={tileServerBVisible ? 'Tile Server A' : 'Tile Server'}
>
<TileServerInput
name={'tileServer' as const}
value={value.tileServer}
error={error?.tileServer}
onChange={setFieldValue}
disabled={submissionPending || projectTypeEmpty}
/>
</InputSection>
{tileServerVisible && (
<InputSection
heading={tileServerBVisible ? 'Tile Server A' : 'Tile Server'}
>
<TileServerInput
name={'tileServer' as const}
value={value.tileServer}
error={error?.tileServer}
onChange={setFieldValue}
disabled={submissionPending || projectTypeEmpty}
/>
</InputSection>
)}

{tileServerBVisible && (
<InputSection
heading="Tile Server B"
Expand Down
56 changes: 54 additions & 2 deletions manager-dashboard/app/views/NewTutorial/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
PROJECT_TYPE_CHANGE_DETECTION,
PROJECT_TYPE_COMPLETENESS,
PROJECT_TYPE_FOOTPRINT,
PROJECT_TYPE_STREET,
IconKey,
} from '#utils/common';

Expand Down Expand Up @@ -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: 'the object you are looking for is in the image.',
},
{
optionId: 2,
value: 0,
title: 'No',
icon: 'close-outline',
iconColor: colorKeyToColorMap.red,
description: 'the object you are looking for is NOT in the image.',
},
{
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<T extends object, K extends keyof T>(
value: T,
key: K,
Expand All @@ -268,6 +296,18 @@ export function deleteKey<T extends object, K extends keyof T>(
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;
Expand Down Expand Up @@ -308,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
Expand All @@ -323,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 = {
Expand Down Expand Up @@ -724,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,
};
Expand Down
58 changes: 58 additions & 0 deletions mapswipe_workers/sample_data/street/README.md
Original file line number Diff line number Diff line change
@@ -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 `<img src="file:///[% photo %]" width="350" height="250">` 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
Original file line number Diff line number Diff line change
@@ -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": 1, "screen": 2 },
"geometry": { "type": "Point", "coordinates": [ 13.45285, 52.508467, 0.0 ] }
},
{
"type": "Feature",
"properties": { "id": "1171343450849316", "reference": 0, "screen": 1 },
"geometry": { "type": "Point", "coordinates": [ 13.4514123, 52.5103378, 0.0 ] }
}
]
}