);
diff --git a/app/views/EditTutorial/ScenarioPageInput/TaskInput/schema.ts b/app/views/EditTutorial/ScenarioPageInput/TaskInput/schema.ts
index da7dc5c..209f211 100644
--- a/app/views/EditTutorial/ScenarioPageInput/TaskInput/schema.ts
+++ b/app/views/EditTutorial/ScenarioPageInput/TaskInput/schema.ts
@@ -18,6 +18,7 @@ import {
import comparePropertyInputSchema from './ComparePropertyInput/schema';
import completenessPropertyInputSchema from './CompletenessPropertyInput/schema';
+import conflationPropertyInputSchema from './ConflationPropertyInput/schema';
import findPropertyInputSchema from './FindPropertyInput/schema';
import streetPropertyInputSchema from './StreetPropertyInput/schema';
import validateImagePropertyInputSchema from './ValidateImagePropertyInput/schema';
@@ -66,6 +67,7 @@ const taskSchema: TaskSchema = {
validate: { forceValue: undefinedValue },
validateImage: { forceValue: undefinedValue },
street: { forceValue: undefinedValue },
+ conflation: { forceValue: undefinedValue },
};
}
@@ -77,6 +79,7 @@ const taskSchema: TaskSchema = {
validate: { forceValue: undefinedValue },
validateImage: { forceValue: undefinedValue },
street: { forceValue: undefinedValue },
+ conflation: { forceValue: undefinedValue },
};
}
@@ -88,6 +91,19 @@ const taskSchema: TaskSchema = {
validate: { forceValue: undefinedValue },
validateImage: { forceValue: undefinedValue },
street: { forceValue: undefinedValue },
+ conflation: { forceValue: undefinedValue },
+ };
+ }
+
+ if (projectType === ProjectTypeEnum.Conflation) {
+ return {
+ validate: { forceValue: undefinedValue },
+ find: { forceValue: undefinedValue },
+ compare: { forceValue: undefinedValue },
+ completeness: { forceValue: undefinedValue },
+ validateImage: { forceValue: undefinedValue },
+ street: { forceValue: undefinedValue },
+ conflation: conflationPropertyInputSchema,
};
}
@@ -99,6 +115,7 @@ const taskSchema: TaskSchema = {
completeness: { forceValue: undefinedValue },
validateImage: { forceValue: undefinedValue },
street: { forceValue: undefinedValue },
+ conflation: { forceValue: undefinedValue },
};
}
@@ -110,6 +127,7 @@ const taskSchema: TaskSchema = {
completeness: { forceValue: undefinedValue },
validate: { forceValue: undefinedValue },
street: { forceValue: undefinedValue },
+ conflation: { forceValue: undefinedValue },
};
}
@@ -121,6 +139,7 @@ const taskSchema: TaskSchema = {
completeness: { forceValue: undefinedValue },
validate: { forceValue: undefinedValue },
validateImage: { forceValue: undefinedValue },
+ conflation: { forceValue: undefinedValue },
};
}
@@ -133,6 +152,7 @@ const taskSchema: TaskSchema = {
validate: { forceValue: undefinedValue },
validateImage: { forceValue: undefinedValue },
street: { forceValue: undefinedValue },
+ conflation: { forceValue: undefinedValue },
};
},
},
diff --git a/app/views/EditTutorial/index.tsx b/app/views/EditTutorial/index.tsx
index 3c9d7a9..5b1414b 100644
--- a/app/views/EditTutorial/index.tsx
+++ b/app/views/EditTutorial/index.tsx
@@ -61,6 +61,7 @@ import { PartialInformationPageInputFields } from './InformationPageInput/schema
import { PartialScenarioPageInputFields } from './ScenarioPageInput/schema';
import { ComparePropertyInputFields } from './ScenarioPageInput/TaskInput/ComparePropertyInput/schema';
import { CompletenessPropertyInputFields } from './ScenarioPageInput/TaskInput/CompletenessPropertyInput/schema';
+import { ConflationPropertyInputFields } from './ScenarioPageInput/TaskInput/ConflationPropertyInput/schema';
import { FindPropertyInputFields } from './ScenarioPageInput/TaskInput/FindPropertyInput/schema';
import { StreetPropertyInputFields } from './ScenarioPageInput/TaskInput/StreetPropertyInput/schema';
import { ValidatePropertyInputFields } from './ScenarioPageInput/TaskInput/ValidatePropertyInput/schema';
@@ -146,6 +147,15 @@ const StreetFeaturePropertyType = type({
id: 'string',
});
+const ConflationFeaturePropertyType = type.merge(
+ CommonFeaturePropertyType,
+ {
+ // This is not used anymore
+ // id: '"string" | "number"',
+ id: type.number,
+ },
+);
+
const ValidateTutorialGeoJsonType = type({
type: '"FeatureCollection"',
features: type({
@@ -154,6 +164,14 @@ const ValidateTutorialGeoJsonType = type({
}).array(),
});
+const ConflationTutorialGeoJsonType = type({
+ type: '"FeatureCollection"',
+ features: type({
+ geometry: PolygonType.or(MultiPolygonType),
+ properties: ConflationFeaturePropertyType,
+ }).array(),
+});
+
const FindTutorialGeoJsonType = type({
type: '"FeatureCollection"',
features: type({
@@ -385,6 +403,16 @@ function NewTutorial() {
};
}
+ // eslint-disable-next-line no-underscore-dangle
+ if (task.projectTypeSpecifics?.__typename === 'ConflationTutorialTaskPropertyType') {
+ return {
+ ...task,
+ projectTypeSpecifics: {
+ conflation: task.projectTypeSpecifics,
+ },
+ };
+ }
+
task.projectTypeSpecifics satisfies undefined;
return { ...task };
@@ -665,6 +693,42 @@ function NewTutorial() {
],
}));
+ setFieldValue(
+ scenarioPages.toSorted((a, b) => (
+ compareNumber(a.scenarioPageNumber, b.scenarioPageNumber)
+ )),
+ 'scenarios',
+ );
+ }
+ } else if (projectType === ProjectTypeEnum.Conflation) {
+ const result = ConflationTutorialGeoJsonType(geoJson);
+ if (result instanceof type.errors) {
+ setError({
+ scenarios: {
+ [nonFieldError]: result.summary,
+ },
+ });
+ } else {
+ const scenarioPages = result.features.map((feature, i) => ({
+ clientId: ulid(),
+ scenarioPageNumber: isDefined(feature.properties.screen)
+ ? feature.properties.screen
+ : i + 1,
+ tasks: [
+ {
+ clientId: ulid(),
+ reference: feature.properties.reference,
+ projectTypeSpecifics: {
+ // FIXME: Why objectGeometry is string?
+ conflation: {
+ identifier: feature.properties.id,
+ objectGeometry: JSON.stringify(feature.geometry, null, 4),
+ } satisfies ConflationPropertyInputFields,
+ },
+ },
+ ],
+ }));
+
setFieldValue(
scenarioPages.toSorted((a, b) => (
compareNumber(a.scenarioPageNumber, b.scenarioPageNumber)
diff --git a/app/views/NewProject/ProjectGeneralInputs/index.tsx b/app/views/NewProject/ProjectGeneralInputs/index.tsx
index 8111eea..70dab65 100644
--- a/app/views/NewProject/ProjectGeneralInputs/index.tsx
+++ b/app/views/NewProject/ProjectGeneralInputs/index.tsx
@@ -60,6 +60,7 @@ const hintText: Record<
[ProjectTypeEnum.ValidateImage]: 'Enter the description for your project. (markdown syntax is supported)',
[ProjectTypeEnum.Completeness]: 'Enter the description for your project. (markdown syntax is supported)',
[ProjectTypeEnum.Street]: 'Enter the description for your project. (markdown syntax is supported)',
+ [ProjectTypeEnum.Conflation]: 'Enter the description for your project. (markdown syntax is supported)',
},
topic: {
[ProjectTypeEnum.Find]: 'Enter the title of your project.',
@@ -68,6 +69,7 @@ const hintText: Record<
[ProjectTypeEnum.ValidateImage]: 'Enter the title of your project.',
[ProjectTypeEnum.Completeness]: 'Enter the title of your project.',
[ProjectTypeEnum.Street]: 'Enter the title of your project.',
+ [ProjectTypeEnum.Conflation]: 'Enter the title of your project.',
},
projectInstruction: {
[ProjectTypeEnum.Find]: 'What should the users look for (e.g. You are looking for: buildings, destroyed buildings, cars, trees, etc.)',
@@ -76,6 +78,7 @@ const hintText: Record<
[ProjectTypeEnum.ValidateImage]: 'What should the users look to assess? (e.g., You are looking for trees)',
[ProjectTypeEnum.Completeness]: undefined,
[ProjectTypeEnum.Street]: undefined,
+ [ProjectTypeEnum.Conflation]: undefined,
},
lookFor: {
[ProjectTypeEnum.Find]: '[This field is used only for legacy app!] What should the users look for? (e.g., buildings, cars, trees)',
@@ -84,6 +87,7 @@ const hintText: Record<
[ProjectTypeEnum.ValidateImage]: '[This field is used only for legacy app!] What should the users look for? (e.g., buildings, cars, trees)',
[ProjectTypeEnum.Completeness]: '[This field is used only for legacy app!] What should the users look for? (e.g., buildings, cars, trees)',
[ProjectTypeEnum.Street]: '[This field is used only for legacy app!] What should the users look for? (e.g., buildings, cars, trees)',
+ [ProjectTypeEnum.Conflation]: '[This field is used only for legacy app!] What should the users look for? (e.g., buildings, cars, trees)',
},
additionalInfoUrl: {
[ProjectTypeEnum.Find]: 'Provide an optional link to a resource with additional information on the project (only visible in the MapSwipe web app)',
@@ -92,6 +96,7 @@ const hintText: Record<
[ProjectTypeEnum.ValidateImage]: 'Provide an optional link to a resource with additional information on the project (only visible in the MapSwipe web app)',
[ProjectTypeEnum.Completeness]: 'Provide an optional link to a resource with additional information on the project (only visible in the MapSwipe web app)',
[ProjectTypeEnum.Street]: 'Provide an optional link to a resource with additional information on the project (only visible in the MapSwipe web app)',
+ [ProjectTypeEnum.Conflation]: 'Provide an optional link to a resource with additional information on the project (only visible in the MapSwipe web app)',
},
projectNumber: {
[ProjectTypeEnum.Find]: 'Is this project part of a bigger campaign with multiple projects? If so, increment this number up by one each time you create a new project in the series. ',
@@ -100,6 +105,7 @@ const hintText: Record<
[ProjectTypeEnum.ValidateImage]: 'Is this project part of a bigger campaign with multiple projects? If so, increment this number up by one each time you create a new project in the series. ',
[ProjectTypeEnum.Completeness]: 'Is this project part of a bigger campaign with multiple projects? If so, increment this number up by one each time you create a new project in the series. ',
[ProjectTypeEnum.Street]: 'Is this project part of a bigger campaign with multiple projects? If so, increment this number up by one each time you create a new project in the series. ',
+ [ProjectTypeEnum.Conflation]: 'Is this project part of a bigger campaign with multiple projects? If so, increment this number up by one each time you create a new project in the series. ',
},
region: {
[ProjectTypeEnum.Find]: 'Enter the region/location of your project (eg: City, Country)',
@@ -108,6 +114,7 @@ const hintText: Record<
[ProjectTypeEnum.ValidateImage]: 'Enter the region/location of your project (eg: City, Country)',
[ProjectTypeEnum.Completeness]: 'Enter the region/location of your project (eg: City, Country)',
[ProjectTypeEnum.Street]: 'Enter the region/location of your project (eg: City, Country)',
+ [ProjectTypeEnum.Conflation]: 'Enter the region/location of your project (eg: City, Country)',
},
requestingOrganization: {
[ProjectTypeEnum.Find]: 'Which group, institution or community is requesting this project?',
@@ -116,6 +123,7 @@ const hintText: Record<
[ProjectTypeEnum.ValidateImage]: 'Which group, institution or community is requesting this project?',
[ProjectTypeEnum.Completeness]: 'Which group, institution or community is requesting this project?',
[ProjectTypeEnum.Street]: 'Which group, institution or community is requesting this project?',
+ [ProjectTypeEnum.Conflation]: 'Which group, institution or community is requesting this project?',
},
team: {
[ProjectTypeEnum.Find]: 'Please note that if \'private\', this project will only be visible to the assigned team members. Data results will still be public.',
@@ -124,6 +132,7 @@ const hintText: Record<
[ProjectTypeEnum.ValidateImage]: 'Please note that if \'private\', this project will only be visible to the assigned team members. Data results will still be public.',
[ProjectTypeEnum.Completeness]: 'Please note that if \'private\', this project will only be visible to the assigned team members. Data results will still be public.',
[ProjectTypeEnum.Street]: 'Please note that if \'private\', this project will only be visible to the assigned team members. Data results will still be public.',
+ [ProjectTypeEnum.Conflation]: 'Please note that if \'private\', this project will only be visible to the selected team members. Data results will still be public.',
},
};
@@ -265,24 +274,32 @@ function ProjectGeneralInputs(props: Props) {
layout="grid"
spacing="lg"
>
-
-
+ {/*
+ Remove instruction and lookFor inputs if project type is conflation,
+ as values are hard-coded on form submission
+ */}
+ {projectType !== ProjectTypeEnum.Conflation && (
+ <>
+
+
+ >
+ )}
(form.projectType !== ProjectTypeEnum.Conflation
+ ? requiredStringCondition(value)
+ : undefined),
},
lookFor: {
- required: true,
- requiredValidation: requiredStringCondition,
+ requiredValidation: (value, form) => (form.projectType !== ProjectTypeEnum.Conflation
+ ? requiredStringCondition(value)
+ : undefined),
},
description: {},
team: {},
@@ -156,7 +158,23 @@ const projectTypeDescriptions: Record = {
name="street-alert"
title="MapSwipe Web only"
type="warning"
- description="Street project are currently only available in the MapSwipe web app."
+ description="Street projects are currently only available in the MapSwipe web app."
+ fullWidth
+ withoutShadow
+ />
+
+ ),
+ [ProjectTypeEnum.Conflation]: (
+
+