diff --git a/app/components/domain/ConflationOptionSelectInput/index.tsx b/app/components/domain/ConflationOptionSelectInput/index.tsx new file mode 100644 index 0000000..e3147ef --- /dev/null +++ b/app/components/domain/ConflationOptionSelectInput/index.tsx @@ -0,0 +1,95 @@ +import { + isDefined, + listToMap, +} from '@togglecorp/fujs'; + +import InlineLayout from '#components/InlineLayout'; +import SelectInput from '#components/SelectInput'; +import { SearchSelectInputProps } from '#components/SelectInput/SearchSelectInput'; +import { + conflationTileOptions, + labelSelector, + OPACITY_TILE_SELECTED, + TileSelectOption, + valueSelector, +} from '#utils/common'; + +interface ColorPreviewProps { + value: string | undefined | null; +} + +function ColorPreview(props: ColorPreviewProps) { + const { + value, + } = props; + + return ( +
+ ); +} + +function iconOptionLabelSelector(option: TileSelectOption) { + return ( + } + > + {option.label} + + ); +} + +type Def = { containerClassName?: string }; + +type Props = SearchSelectInputProps< +number, +NAME, +TileSelectOption, +Def, +'onSearchValueChange' +| 'searchOptions' +| 'onShowDropdownChange' +| 'totalOptionsCount' +| 'value' +| 'options' +| 'keySelector' +| 'labelSelector' +| 'optionLabelSelector' +| 'icons' +> & { value: number | undefined | null}; + +function TileOptionSelectInput(props: Props) { + const { + value, + ...otherProps + } = props; + + const optionToColorMapping = listToMap( + conflationTileOptions, + (option) => option.value, + (option) => option.color, + ); + + return ( + + )} + /> + ); +} + +export default TileOptionSelectInput; diff --git a/app/utils/common.ts b/app/utils/common.ts index c6aa428..cb8dd52 100644 --- a/app/utils/common.ts +++ b/app/utils/common.ts @@ -22,6 +22,11 @@ export const COLOR_TILE_OPTION_YES = 'green'; export const COLOR_TILE_OPTION_MAYBE = 'orange'; export const COLOR_TILE_OPTION_BAD_IMAGERY = 'red'; +export const COLOR_CONFLATION_OPTION_NO = 'red'; +export const COLOR_CONFLATION_OPTION_YES = 'green'; +export const COLOR_CONFLATION_OPTION_NOT_SURE = 'grey'; +export const COLOR_CONFLATION_OPTION_SKIP = 'orange'; + export const VALUE_TILE_OPTION_NO = 0; export const VALUE_TILE_OPTION_YES = 1; export const VALUE_TILE_OPTION_MAYBE = 2; @@ -56,6 +61,29 @@ export const defaultTileOptions: TileSelectOption[] = [ }, ]; +export const conflationTileOptions: TileSelectOption[] = [ + { + value: VALUE_TILE_OPTION_NO, + label: 'No | OSM', + color: COLOR_CONFLATION_OPTION_NO, + }, + { + value: VALUE_TILE_OPTION_YES, + label: 'Yes | fAIr', + color: COLOR_CONFLATION_OPTION_YES, + }, + { + value: VALUE_TILE_OPTION_MAYBE, + label: 'Not sure | Neither', + color: COLOR_CONFLATION_OPTION_NOT_SURE, + }, + { + value: VALUE_TILE_OPTION_BAD_IMAGERY, + label: 'Skip', + color: COLOR_CONFLATION_OPTION_SKIP, + }, +]; + export const defaultMarkdownPreviewOptions: MarkdownViewProps['options'] = { simpleLineBreaks: true, headerLevelStart: 3, @@ -156,6 +184,7 @@ export const projectTypeToKeyMap: Record, + setFieldValue: (...entries: EntriesAsList) => void; +} + +function ObjectSourceInput(props: Props) { + const { + value, + error: formError, + setFieldValue, + } = props; + + const error = getErrorObject(formError); + + return ( + + + + ); +} + +export default ObjectSourceInput; diff --git a/app/views/EditProject/UpdateProjectForm/ConflationProjectSpecifics/ObjectSourceInput/schema.ts b/app/views/EditProject/UpdateProjectForm/ConflationProjectSpecifics/ObjectSourceInput/schema.ts new file mode 100644 index 0000000..d0c8907 --- /dev/null +++ b/app/views/EditProject/UpdateProjectForm/ConflationProjectSpecifics/ObjectSourceInput/schema.ts @@ -0,0 +1,34 @@ +import { + ObjectSchema, + PartialForm, +} from '@togglecorp/toggle-form'; + +import { + ConflationObjectSourceConfig, + ConflationObjectSourceConfigInput, +} from '#generated/types/graphql'; +import { DeepNonNullable } from '#utils/types'; + +export type ConflationSourceConfigKeys = Exclude; + +export type PartialConflationObjectSourceInputFields = PartialForm< + DeepNonNullable +>; +type ConflationSourceFormSchema = ObjectSchema; +type ConflationSourceInputFields = ReturnType; + +export const defaultObjectSourceInputFormValue: PartialConflationObjectSourceInputFields = { + objectGeojsonUrl: '', +}; + +const objectSourceFormSchema: ConflationSourceFormSchema = { + fields: (): ConflationSourceInputFields => { + const schema: ConflationSourceInputFields = { + objectGeojsonUrl: { required: true }, + }; + + return schema; + }, +}; + +export default objectSourceFormSchema; diff --git a/app/views/EditProject/UpdateProjectForm/ConflationProjectSpecifics/index.tsx b/app/views/EditProject/UpdateProjectForm/ConflationProjectSpecifics/index.tsx new file mode 100644 index 0000000..bf7d68f --- /dev/null +++ b/app/views/EditProject/UpdateProjectForm/ConflationProjectSpecifics/index.tsx @@ -0,0 +1,69 @@ +import { + EntriesAsList, + getErrorObject, + LeafError, + ObjectError, + useFormObject, +} from '@togglecorp/toggle-form'; + +import RasterTileServerInput from '#components/domain/RasterTileServerInput'; +import { + defaultRasterTileServerInputValue, + type PartialRasterTileServerInputFields, +} from '#components/domain/RasterTileServerInput/schema'; + +import { + defaultObjectSourceInputFormValue, + PartialConflationObjectSourceInputFields, +} from './ObjectSourceInput/schema'; +import ObjectSourceInput from './ObjectSourceInput'; +import { type PartialConflationSpecificFields } from './schema'; + +interface Props { + value: PartialConflationSpecificFields | undefined | null; + error: LeafError | ObjectError; + setFieldValue: (...entries: EntriesAsList) => void; + disabled?: boolean; +} + +function ConflationProjectSpecifics(props: Props) { + const { + value, + error: formError, + setFieldValue, + disabled, + } = props; + + const error = getErrorObject(formError); + + const setTileServerInputFieldValue = useFormObject<'tileServerProperty', PartialRasterTileServerInputFields>( + 'tileServerProperty' as const, + setFieldValue, + defaultRasterTileServerInputValue, + ); + + const setObjectSourceInputFieldValue = useFormObject<'objectSource', PartialConflationObjectSourceInputFields>( + 'objectSource' as const, + setFieldValue, + defaultObjectSourceInputFormValue, + ); + + return ( + <> + + + + ); +} + +export default ConflationProjectSpecifics; diff --git a/app/views/EditProject/UpdateProjectForm/ConflationProjectSpecifics/schema.ts b/app/views/EditProject/UpdateProjectForm/ConflationProjectSpecifics/schema.ts new file mode 100644 index 0000000..97defd4 --- /dev/null +++ b/app/views/EditProject/UpdateProjectForm/ConflationProjectSpecifics/schema.ts @@ -0,0 +1,38 @@ +import { + ObjectSchema, + PartialForm, +} from '@togglecorp/toggle-form'; + +import rasterTileServerFormSchema, { defaultRasterTileServerInputValue } from '#components/domain/RasterTileServerInput/schema'; +import { ConflationProjectPropertyInput } from '#generated/types/graphql'; +import { DeepNonNullable } from '#utils/types'; + +import { + type PartialProjectUpdateInput, + type UpdateProjectContext, +} from '../schema'; +import objectSourceFormSchema, { defaultObjectSourceInputFormValue } from './ObjectSourceInput/schema'; + +export type PartialConflationSpecificFields = PartialForm< + DeepNonNullable, + 'clientId' +>; +type ConflationSpecificFormSchema = ObjectSchema< + PartialConflationSpecificFields, + PartialProjectUpdateInput, + UpdateProjectContext +>; + +export const defaultConflationSpecificFormValue: PartialConflationSpecificFields = { + objectSource: defaultObjectSourceInputFormValue, + tileServerProperty: defaultRasterTileServerInputValue, +}; + +const conflationSpecificFormSchema: ConflationSpecificFormSchema = { + fields: (): ReturnType => ({ + objectSource: objectSourceFormSchema, + tileServerProperty: rasterTileServerFormSchema, + }), +}; + +export default conflationSpecificFormSchema; diff --git a/app/views/EditProject/UpdateProjectForm/index.tsx b/app/views/EditProject/UpdateProjectForm/index.tsx index c327432..fbe7f4d 100644 --- a/app/views/EditProject/UpdateProjectForm/index.tsx +++ b/app/views/EditProject/UpdateProjectForm/index.tsx @@ -55,6 +55,11 @@ import { defaultCompletenessSpecificFormValue, PartialCompletenessSpecificFields, } from './CompletenessProjectSpecifics/schema.ts'; +import ConflationProjectSpecifics from './ConflationProjectSpecifics/index.tsx'; +import { + defaultConflationSpecificFormValue, + PartialConflationSpecificFields, +} from './ConflationProjectSpecifics/schema.ts'; import { defaultFindSpecificFormValue, PartialFindSpecificFields, @@ -134,6 +139,10 @@ function UpdateProjectForm(props: Props) { return defaultFindSpecificFormValue; } + if (projectData.project.projectType === ProjectTypeEnum.Conflation) { + return defaultConflationSpecificFormValue; + } + if (projectData.project.projectType === ProjectTypeEnum.Compare) { return defaultCompareSpecificFormValue; } @@ -373,7 +382,7 @@ function UpdateProjectForm(props: Props) { const setValidateImageProjectSpecificsFieldValue = useFormObject<'validateImage', PartialValidateImageSpecificFields>( 'validateImage', setProjectSpecificFieldValue, - defaultValidateSpecificFormValue, + defaultValidateImageSpecificFormValue, ); const setCompletenessProjectSpecificsFieldValue = useFormObject<'completeness', PartialCompletenessSpecificFields>( @@ -385,7 +394,13 @@ function UpdateProjectForm(props: Props) { const setStreetProjectSpecificsFieldValue = useFormObject<'street', PartialStreetSpecificFields>( 'street', setProjectSpecificFieldValue, - defaultValidateSpecificFormValue, + defaultStreetSpecificFormValue, + ); + + const setConflationSpecificsFieldValue = useFormObject<'conflation', PartialConflationSpecificFields>( + 'conflation', + setProjectSpecificFieldValue, + defaultConflationSpecificFormValue, ); const pending = updateProjectPending; @@ -416,6 +431,8 @@ function UpdateProjectForm(props: Props) { ?.validateImage as PartialValidateSpecificFields | undefined; const streetProjectTypeSpecifics = value.projectTypeSpecifics ?.street as PartialStreetSpecificFields | undefined; + const conflationProjectTypeSpecifics = value.projectTypeSpecifics + ?.conflation as PartialConflationSpecificFields | undefined; return ( )} + {projectContext.projectType === ProjectTypeEnum.Conflation && ( + + )} ); diff --git a/app/views/EditProject/UpdateProjectForm/schema.ts b/app/views/EditProject/UpdateProjectForm/schema.ts index 1004f09..d19facd 100644 --- a/app/views/EditProject/UpdateProjectForm/schema.ts +++ b/app/views/EditProject/UpdateProjectForm/schema.ts @@ -14,6 +14,7 @@ import { DeepNonNullable } from '#utils/types'; import compareSpecificFormSchema from './CompareProjectSpecifics/schema'; import completenessSpecificFormSchema from './CompletenessProjectSpecifics/schema'; +import conflationSpecificFormSchema from './ConflationProjectSpecifics/schema'; import findSpecificFormSchema from './FindProjectSpecifics/schema'; import streetSpecificFormSchema from './StreetProjectSpecifics/schema.ts'; import validateImageSpecificFormSchema from './ValidateImageProjectSpecifics/schema.ts'; @@ -84,6 +85,7 @@ const projectUpdateFormSchema: ProjectUpdateFormSchema = { completeness: { forceValue: undefinedValue }, validate: { forceValue: undefinedValue }, validateImage: { forceValue: undefinedValue }, + conflation: { forceValue: undefinedValue }, }; } @@ -95,6 +97,7 @@ const projectUpdateFormSchema: ProjectUpdateFormSchema = { completeness: { forceValue: undefinedValue }, validate: { forceValue: undefinedValue }, validateImage: { forceValue: undefinedValue }, + conflation: { forceValue: undefinedValue }, }; } @@ -106,6 +109,19 @@ const projectUpdateFormSchema: ProjectUpdateFormSchema = { compare: { forceValue: undefinedValue }, validate: { forceValue: undefinedValue }, validateImage: { forceValue: undefinedValue }, + conflation: { forceValue: undefinedValue }, + }; + } + + if (context?.projectType === ProjectTypeEnum.Conflation) { + return { + street: { forceValue: undefinedValue }, + validate: { forceValue: undefinedValue }, + completeness: { forceValue: undefinedValue }, + find: { forceValue: undefinedValue }, + compare: { forceValue: undefinedValue }, + validateImage: { forceValue: undefinedValue }, + conflation: conflationSpecificFormSchema, }; } @@ -117,6 +133,7 @@ const projectUpdateFormSchema: ProjectUpdateFormSchema = { find: { forceValue: undefinedValue }, compare: { forceValue: undefinedValue }, validateImage: { forceValue: undefinedValue }, + conflation: { forceValue: undefinedValue }, }; } @@ -128,6 +145,7 @@ const projectUpdateFormSchema: ProjectUpdateFormSchema = { find: { forceValue: undefinedValue }, compare: { forceValue: undefinedValue }, validate: { forceValue: undefinedValue }, + conflation: { forceValue: undefinedValue }, }; } @@ -139,6 +157,7 @@ const projectUpdateFormSchema: ProjectUpdateFormSchema = { find: { forceValue: undefinedValue }, compare: { forceValue: undefinedValue }, validate: { forceValue: undefinedValue }, + conflation: { forceValue: undefinedValue }, }; } @@ -151,6 +170,7 @@ const projectUpdateFormSchema: ProjectUpdateFormSchema = { completeness: { forceValue: undefinedValue }, validate: { forceValue: undefinedValue }, validateImage: { forceValue: undefinedValue }, + conflation: { forceValue: undefinedValue }, }; }, }, diff --git a/app/views/EditTutorial/ScenarioPageInput/TaskInput/ConflationPropertyInput/index.tsx b/app/views/EditTutorial/ScenarioPageInput/TaskInput/ConflationPropertyInput/index.tsx new file mode 100644 index 0000000..652a0aa --- /dev/null +++ b/app/views/EditTutorial/ScenarioPageInput/TaskInput/ConflationPropertyInput/index.tsx @@ -0,0 +1,59 @@ +import { _cs } from '@togglecorp/fujs'; +import { + EntriesAsList, + getErrorObject, + LeafError, + ObjectError, +} from '@togglecorp/toggle-form'; + +import NumberInput from '#components/NumberInput'; +import TextArea from '#components/TextArea'; + +import { PartialConflationPropertyInputFields } from './schema.ts'; + +import styles from './styles.module.css'; + +interface Props { + className?: string; + value: PartialConflationPropertyInputFields | undefined; + setFieldValue: (...entries: EntriesAsList) => void; + error: LeafError | ObjectError; + disabled?: boolean; +} + +function ConflationPropertyInput(props: Props) { + const { + className, + value, + setFieldValue, + error: formError, + disabled, + } = props; + + const error = getErrorObject(formError); + + return ( +
+ +