forked from MapComplete/MapComplete
		
	Repair import flow
This commit is contained in:
		
							parent
							
								
									8c7bb92f8a
								
							
						
					
					
						commit
						e1cdb75001
					
				
					 7 changed files with 85 additions and 74 deletions
				
			
		
							
								
								
									
										20
									
								
								UI/Base/DivContainer.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								UI/Base/DivContainer.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | ||||||
|  | import { UIElement } from "../UIElement" | ||||||
|  | import BaseUIElement from "../BaseUIElement" | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Introduces a new element which has an ID | ||||||
|  |  * Mostly a workaround for the import viewer | ||||||
|  |  */ | ||||||
|  | export default class DivContainer extends BaseUIElement { | ||||||
|  |     private readonly _id: string | ||||||
|  | 
 | ||||||
|  |     constructor(id: string) { | ||||||
|  |         super() | ||||||
|  |         this._id = id | ||||||
|  |     } | ||||||
|  |     protected InnerConstructElement(): HTMLElement { | ||||||
|  |         const e = document.createElement("div") | ||||||
|  |         e.id = this._id | ||||||
|  |         return e | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -21,6 +21,8 @@ import { VariableUiElement } from "../Base/VariableUIElement" | ||||||
| import * as known_layers from "../../assets/generated/known_layers.json" | import * as known_layers from "../../assets/generated/known_layers.json" | ||||||
| import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson" | import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson" | ||||||
| import Translations from "../i18n/Translations" | import Translations from "../i18n/Translations" | ||||||
|  | import { Feature } from "geojson" | ||||||
|  | import DivContainer from "../Base/DivContainer" | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Filters out points for which the import-note already exists, to prevent duplicates |  * Filters out points for which the import-note already exists, to prevent duplicates | ||||||
|  | @ -105,7 +107,7 @@ export class CompareToAlreadyExistingNotes | ||||||
|             zoomToFeatures: true, |             zoomToFeatures: true, | ||||||
|             leafletMap: comparisonMap.leafletMap, |             leafletMap: comparisonMap.leafletMap, | ||||||
|             features: StaticFeatureSource.fromGeojsonStore( |             features: StaticFeatureSource.fromGeojsonStore( | ||||||
|                 partitionedImportPoints.map((p) => p.hasNearby) |                 partitionedImportPoints.map((p) => <Feature[]>p.hasNearby) | ||||||
|             ), |             ), | ||||||
|             popup: (tags, layer) => new FeatureInfoBox(tags, layer, state), |             popup: (tags, layer) => new FeatureInfoBox(tags, layer, state), | ||||||
|         }) |         }) | ||||||
|  | @ -134,7 +136,7 @@ export class CompareToAlreadyExistingNotes | ||||||
|                         return new Combine([ |                         return new Combine([ | ||||||
|                             t.mapExplanation.Subs(params.features), |                             t.mapExplanation.Subs(params.features), | ||||||
|                             map, |                             map, | ||||||
| 
 |                             new DivContainer("fullscreen"), | ||||||
|                             new VariableUiElement( |                             new VariableUiElement( | ||||||
|                                 partitionedImportPoints.map(({ noNearby, hasNearby }) => { |                                 partitionedImportPoints.map(({ noNearby, hasNearby }) => { | ||||||
|                                     if (noNearby.length === 0) { |                                     if (noNearby.length === 0) { | ||||||
|  |  | ||||||
|  | @ -27,24 +27,26 @@ import { GeoOperations } from "../../Logic/GeoOperations" | ||||||
| import FeatureInfoBox from "../Popup/FeatureInfoBox" | import FeatureInfoBox from "../Popup/FeatureInfoBox" | ||||||
| import { ImportUtils } from "./ImportUtils" | import { ImportUtils } from "./ImportUtils" | ||||||
| import Translations from "../i18n/Translations" | import Translations from "../i18n/Translations" | ||||||
| import ShowDataMultiLayer from "../ShowDataLayer/ShowDataMultiLayer" |  | ||||||
| import FilteredLayer, { FilterState } from "../../Models/FilteredLayer" |  | ||||||
| import { Feature, FeatureCollection } from "@turf/turf" |  | ||||||
| import * as currentview from "../../assets/layers/current_view/current_view.json" | import * as currentview from "../../assets/layers/current_view/current_view.json" | ||||||
| import { CheckBox } from "../Input/Checkboxes" | import { CheckBox } from "../Input/Checkboxes" | ||||||
| import BackgroundMapSwitch from "../BigComponents/BackgroundMapSwitch" | import BackgroundMapSwitch from "../BigComponents/BackgroundMapSwitch" | ||||||
|  | import { Feature, FeatureCollection, Point } from "geojson" | ||||||
|  | import DivContainer from "../Base/DivContainer" | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Given the data to import, the bbox and the layer, will query overpass for similar items |  * Given the data to import, the bbox and the layer, will query overpass for similar items | ||||||
|  */ |  */ | ||||||
| export default class ConflationChecker | export default class ConflationChecker | ||||||
|     extends Combine |     extends Combine | ||||||
|     implements FlowStep<{ features: any[]; theme: string }> |     implements FlowStep<{ features: Feature<Point>[]; theme: string }> | ||||||
| { | { | ||||||
|     public readonly IsValid |     public readonly IsValid | ||||||
|     public readonly Value: Store<{ features: any[]; theme: string }> |     public readonly Value: Store<{ features: Feature<Point>[]; theme: string }> | ||||||
| 
 | 
 | ||||||
|     constructor(state, params: { bbox: BBox; layer: LayerConfig; theme: string; features: any[] }) { |     constructor( | ||||||
|  |         state, | ||||||
|  |         params: { bbox: BBox; layer: LayerConfig; theme: string; features: Feature<Point>[] } | ||||||
|  |     ) { | ||||||
|         const t = Translations.t.importHelper.conflationChecker |         const t = Translations.t.importHelper.conflationChecker | ||||||
| 
 | 
 | ||||||
|         const bbox = params.bbox.padAbsolute(0.0001) |         const bbox = params.bbox.padAbsolute(0.0001) | ||||||
|  | @ -175,15 +177,8 @@ export default class ConflationChecker | ||||||
|             features: StaticFeatureSource.fromGeojson([bbox.asGeoJson({})]), |             features: StaticFeatureSource.fromGeojson([bbox.asGeoJson({})]), | ||||||
|         }) |         }) | ||||||
| 
 | 
 | ||||||
|         new ShowDataMultiLayer({ |         new ShowDataLayer({ | ||||||
|             //layerToShow: layer,
 |             layerToShow: layer, | ||||||
|             layers: new UIEventSource<FilteredLayer[]>([ |  | ||||||
|                 { |  | ||||||
|                     layerDef: layer, |  | ||||||
|                     isDisplayed: new UIEventSource<boolean>(true), |  | ||||||
|                     appliedFilters: new UIEventSource<Map<string, FilterState>>(undefined), |  | ||||||
|                 }, |  | ||||||
|             ]), |  | ||||||
|             state, |             state, | ||||||
|             leafletMap: osmLiveData.leafletMap, |             leafletMap: osmLiveData.leafletMap, | ||||||
|             popup: (tags, layer) => new FeatureInfoBox(tags, layer, state, { setHash: false }), |             popup: (tags, layer) => new FeatureInfoBox(tags, layer, state, { setHash: false }), | ||||||
|  | @ -239,7 +234,7 @@ export default class ConflationChecker | ||||||
| 
 | 
 | ||||||
|         // Featuresource showing OSM-features which are nearby a toImport-feature
 |         // Featuresource showing OSM-features which are nearby a toImport-feature
 | ||||||
|         const toImportWithNearby = StaticFeatureSource.fromGeojsonStore( |         const toImportWithNearby = StaticFeatureSource.fromGeojsonStore( | ||||||
|             paritionedImport.map((els) => els?.hasNearby ?? []) |             paritionedImport.map((els) => <Feature[]>els?.hasNearby ?? []) | ||||||
|         ) |         ) | ||||||
|         toImportWithNearby.features.addCallback((nearby) => |         toImportWithNearby.features.addCallback((nearby) => | ||||||
|             console.log("The following features are near an already existing object:", nearby) |             console.log("The following features are near an already existing object:", nearby) | ||||||
|  | @ -325,6 +320,7 @@ export default class ConflationChecker | ||||||
|                     }) |                     }) | ||||||
|                 ), |                 ), | ||||||
|             ]).SetClass("flex"), |             ]).SetClass("flex"), | ||||||
|  |             new DivContainer("fullscreen"), | ||||||
|             new Title(t.titleNearby), |             new Title(t.titleNearby), | ||||||
|             new Combine([t.mapShowingNearbyIntro, nearbyCutoff]).SetClass("flex"), |             new Combine([t.mapShowingNearbyIntro, nearbyCutoff]).SetClass("flex"), | ||||||
|             new VariableUiElement( |             new VariableUiElement( | ||||||
|  | @ -369,7 +365,7 @@ export default class ConflationChecker | ||||||
| 
 | 
 | ||||||
|         this.Value = paritionedImport.map((feats) => ({ |         this.Value = paritionedImport.map((feats) => ({ | ||||||
|             theme: params.theme, |             theme: params.theme, | ||||||
|             features: feats?.noNearby, |             features: <any>feats?.noNearby, | ||||||
|             layer: params.layer, |             layer: params.layer, | ||||||
|         })) |         })) | ||||||
|         this.IsValid = this.Value.map((v) => v?.features !== undefined && v.features.length > 0) |         this.IsValid = this.Value.map((v) => v?.features !== undefined && v.features.length > 0) | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| import { Store } from "../../Logic/UIEventSource" | import { Store } from "../../Logic/UIEventSource" | ||||||
| import { GeoOperations } from "../../Logic/GeoOperations" | import { GeoOperations } from "../../Logic/GeoOperations" | ||||||
| import { Feature, Geometry } from "@turf/turf" | import { Feature, Point } from "geojson" | ||||||
| 
 | 
 | ||||||
| export class ImportUtils { | export class ImportUtils { | ||||||
|     public static partitionFeaturesIfNearby( |     public static partitionFeaturesIfNearby( | ||||||
|         toPartitionFeatureCollection: { features: Feature<Geometry>[] }, |         toPartitionFeatureCollection: { features: Feature[] }, | ||||||
|         compareWith: Store<{ features: Feature[] }>, |         compareWith: Store<{ features: Feature[] }>, | ||||||
|         cutoffDistanceInMeters: Store<number> |         cutoffDistanceInMeters: Store<number> | ||||||
|     ): Store<{ hasNearby: Feature[]; noNearby: Feature[] }> { |     ): Store<{ hasNearby: Feature[]; noNearby: Feature[] }> { | ||||||
|  | @ -25,7 +25,7 @@ export class ImportUtils { | ||||||
|                         (f) => |                         (f) => | ||||||
|                             maxDist >= |                             maxDist >= | ||||||
|                             GeoOperations.distanceBetween( |                             GeoOperations.distanceBetween( | ||||||
|                                 <any>toImportElement.geometry.coordinates, |                                 <any>(<Point>toImportElement.geometry).coordinates, | ||||||
|                                 GeoOperations.centerpointCoordinates(f) |                                 GeoOperations.centerpointCoordinates(f) | ||||||
|                             ) |                             ) | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|  | @ -25,6 +25,9 @@ import Title from "../Base/Title" | ||||||
| import CheckBoxes from "../Input/Checkboxes" | import CheckBoxes from "../Input/Checkboxes" | ||||||
| import { AllTagsPanel } from "../AllTagsPanel" | import { AllTagsPanel } from "../AllTagsPanel" | ||||||
| import BackgroundMapSwitch from "../BigComponents/BackgroundMapSwitch" | import BackgroundMapSwitch from "../BigComponents/BackgroundMapSwitch" | ||||||
|  | import { Feature, Point } from "geojson" | ||||||
|  | import DivContainer from "../Base/DivContainer" | ||||||
|  | import ShowDataLayer from "../ShowDataLayer/ShowDataLayer" | ||||||
| 
 | 
 | ||||||
| class PreviewPanel extends ScrollableFullScreen { | class PreviewPanel extends ScrollableFullScreen { | ||||||
|     constructor(tags: UIEventSource<any>) { |     constructor(tags: UIEventSource<any>) { | ||||||
|  | @ -41,15 +44,12 @@ class PreviewPanel extends ScrollableFullScreen { | ||||||
|  */ |  */ | ||||||
| export class MapPreview | export class MapPreview | ||||||
|     extends Combine |     extends Combine | ||||||
|     implements FlowStep<{ bbox: BBox; layer: LayerConfig; features: any[] }> |     implements FlowStep<{ bbox: BBox; layer: LayerConfig; features: Feature<Point>[] }> | ||||||
| { | { | ||||||
|     public readonly IsValid: Store<boolean> |     public readonly IsValid: Store<boolean> | ||||||
|     public readonly Value: Store<{ bbox: BBox; layer: LayerConfig; features: any[] }> |     public readonly Value: Store<{ bbox: BBox; layer: LayerConfig; features: any[] }> | ||||||
| 
 | 
 | ||||||
|     constructor( |     constructor(state: UserRelatedState, geojson: { features: Feature[] }) { | ||||||
|         state: UserRelatedState, |  | ||||||
|         geojson: { features: { properties: any; geometry: { coordinates: [number, number] } }[] } |  | ||||||
|     ) { |  | ||||||
|         const t = Translations.t.importHelper.mapPreview |         const t = Translations.t.importHelper.mapPreview | ||||||
| 
 | 
 | ||||||
|         const propertyKeys = new Set<string>() |         const propertyKeys = new Set<string>() | ||||||
|  | @ -90,19 +90,20 @@ export class MapPreview | ||||||
|             return copy |             return copy | ||||||
|         }) |         }) | ||||||
| 
 | 
 | ||||||
|         const matching: Store<{ properties: any; geometry: { coordinates: [number, number] } }[]> = |         // Create a store which has only features matching the selected layer
 | ||||||
|             layerPicker.GetValue().map((layer: LayerConfig) => { |         const matching: Store<Feature[]> = layerPicker.GetValue().map((layer: LayerConfig) => { | ||||||
|             if (layer === undefined) { |             if (layer === undefined) { | ||||||
|  |                 console.log("No matching layer found") | ||||||
|                 return [] |                 return [] | ||||||
|             } |             } | ||||||
|                 const matching: { properties: any; geometry: { coordinates: [number, number] } }[] = |             const matching: Feature[] = [] | ||||||
|                     [] |  | ||||||
| 
 | 
 | ||||||
|             for (const feature of withId) { |             for (const feature of withId) { | ||||||
|                 if (layer.source.osmTags.matchesProperties(feature.properties)) { |                 if (layer.source.osmTags.matchesProperties(feature.properties)) { | ||||||
|                     matching.push(feature) |                     matching.push(feature) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             console.log("Matching features: ", matching) | ||||||
| 
 | 
 | ||||||
|             return matching |             return matching | ||||||
|         }) |         }) | ||||||
|  | @ -130,25 +131,22 @@ export class MapPreview | ||||||
|         ) |         ) | ||||||
|         map.SetClass("w-full").SetStyle("height: 500px") |         map.SetClass("w-full").SetStyle("height: 500px") | ||||||
| 
 | 
 | ||||||
|         new ShowDataMultiLayer({ |         layerPicker.GetValue().addCallbackAndRunD((layerToShow) => { | ||||||
|             layers: new UIEventSource<FilteredLayer[]>( |             new ShowDataLayer({ | ||||||
|                 AllKnownLayouts.AllPublicLayers() |                 layerToShow, | ||||||
|                     .filter((l) => l.source.geojsonSource === undefined) |  | ||||||
|                     .map((l) => ({ |  | ||||||
|                         layerDef: l, |  | ||||||
|                         isDisplayed: new UIEventSource<boolean>(true), |  | ||||||
|                         appliedFilters: new UIEventSource<Map<string, FilterState>>(undefined), |  | ||||||
|                     })) |  | ||||||
|             ), |  | ||||||
|                 zoomToFeatures: true, |                 zoomToFeatures: true, | ||||||
|                 features: StaticFeatureSource.fromDateless( |                 features: StaticFeatureSource.fromDateless( | ||||||
|                     matching.map((features) => features.map((feature) => ({ feature }))) |                     matching.map((features) => features.map((feature) => ({ feature }))) | ||||||
|                 ), |                 ), | ||||||
|                 leafletMap: map.leafletMap, |                 leafletMap: map.leafletMap, | ||||||
|             popup: (tag) => new PreviewPanel(tag).SetClass("font-lg"), |                 popup: (tag) => new PreviewPanel(tag), | ||||||
|             }) |             }) | ||||||
|         var bbox = matching.map((feats) => |         }) | ||||||
|             BBox.bboxAroundAll(feats.map((f) => new BBox([f.geometry.coordinates]))) | 
 | ||||||
|  |         const bbox = matching.map((feats) => | ||||||
|  |             BBox.bboxAroundAll( | ||||||
|  |                 feats.map((f) => new BBox([(<Feature<Point>>f).geometry.coordinates])) | ||||||
|  |             ) | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         const mismatchIndicator = new VariableUiElement( |         const mismatchIndicator = new VariableUiElement( | ||||||
|  | @ -171,10 +169,11 @@ export class MapPreview | ||||||
|         super([ |         super([ | ||||||
|             new Title(t.title, 1), |             new Title(t.title, 1), | ||||||
|             layerPicker, |             layerPicker, | ||||||
|             new Toggle(t.autodetected.SetClass("thank"), undefined, autodetected), |             new Toggle(t.autodetected.SetClass("thanks"), undefined, autodetected), | ||||||
| 
 | 
 | ||||||
|             mismatchIndicator, |             mismatchIndicator, | ||||||
|             map, |             map, | ||||||
|  |             new DivContainer("fullscreen"), | ||||||
|             layerControl, |             layerControl, | ||||||
|             confirm, |             confirm, | ||||||
|         ]) |         ]) | ||||||
|  | @ -182,10 +181,10 @@ export class MapPreview | ||||||
|         this.Value = bbox.map( |         this.Value = bbox.map( | ||||||
|             (bbox) => ({ |             (bbox) => ({ | ||||||
|                 bbox, |                 bbox, | ||||||
|                 features: geojson.features, |                 features: matching.data, | ||||||
|                 layer: layerPicker.GetValue().data, |                 layer: layerPicker.GetValue().data, | ||||||
|             }), |             }), | ||||||
|             [layerPicker.GetValue()] |             [layerPicker.GetValue(), matching] | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         this.IsValid = matching.map( |         this.IsValid = matching.map( | ||||||
|  |  | ||||||
|  | @ -10,24 +10,19 @@ import Histogram from "../BigComponents/Histogram" | ||||||
| import Toggleable from "../Base/Toggleable" | import Toggleable from "../Base/Toggleable" | ||||||
| import List from "../Base/List" | import List from "../Base/List" | ||||||
| import CheckBoxes from "../Input/Checkboxes" | import CheckBoxes from "../Input/Checkboxes" | ||||||
|  | import { Feature, Point } from "geojson" | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Shows the attributes by value, requests to check them of |  * Shows the attributes by value, requests to check them of | ||||||
|  */ |  */ | ||||||
| export class PreviewAttributesPanel | export class PreviewAttributesPanel | ||||||
|     extends Combine |     extends Combine | ||||||
|     implements |     implements FlowStep<{ features: Feature<Point>[] }> | ||||||
|         FlowStep<{ features: { properties: any; geometry: { coordinates: [number, number] } }[] }> |  | ||||||
| { | { | ||||||
|     public readonly IsValid: Store<boolean> |     public readonly IsValid: Store<boolean> | ||||||
|     public readonly Value: Store<{ |     public readonly Value: Store<{ features: Feature<Point>[] }> | ||||||
|         features: { properties: any; geometry: { coordinates: [number, number] } }[] |  | ||||||
|     }> |  | ||||||
| 
 | 
 | ||||||
|     constructor( |     constructor(state: UserRelatedState, geojson: { features: Feature<Point>[] }) { | ||||||
|         state: UserRelatedState, |  | ||||||
|         geojson: { features: { properties: any; geometry: { coordinates: [number, number] } }[] } |  | ||||||
|     ) { |  | ||||||
|         const t = Translations.t.importHelper.previewAttributes |         const t = Translations.t.importHelper.previewAttributes | ||||||
| 
 | 
 | ||||||
|         const propertyKeys = new Set<string>() |         const propertyKeys = new Set<string>() | ||||||
|  | @ -93,9 +88,7 @@ export class PreviewAttributesPanel | ||||||
|             confirm, |             confirm, | ||||||
|         ]) |         ]) | ||||||
| 
 | 
 | ||||||
|         this.Value = new UIEventSource<{ |         this.Value = new UIEventSource<{ features: Feature<Point>[] }>(geojson) | ||||||
|             features: { properties: any; geometry: { coordinates: [number, number] } }[] |  | ||||||
|         }>(geojson) |  | ||||||
|         this.IsValid = confirm.GetValue().map((selected) => selected.length == 1) |         this.IsValid = confirm.GetValue().map((selected) => selected.length == 1) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ import { FlowStep } from "./FlowStep" | ||||||
| import { parse } from "papaparse" | import { parse } from "papaparse" | ||||||
| import { FixedUiElement } from "../Base/FixedUiElement" | import { FixedUiElement } from "../Base/FixedUiElement" | ||||||
| import { TagUtils } from "../../Logic/Tags/TagUtils" | import { TagUtils } from "../../Logic/Tags/TagUtils" | ||||||
|  | import { Feature, Point } from "geojson" | ||||||
| 
 | 
 | ||||||
| class FileSelector extends InputElementMap<FileList, { name: string; contents: Promise<string> }> { | class FileSelector extends InputElementMap<FileList, { name: string; contents: Promise<string> }> { | ||||||
|     constructor(label: BaseUIElement) { |     constructor(label: BaseUIElement) { | ||||||
|  | @ -40,7 +41,7 @@ export class RequestFile extends Combine implements FlowStep<{ features: any[] } | ||||||
|     /** |     /** | ||||||
|      * The loaded GeoJSON |      * The loaded GeoJSON | ||||||
|      */ |      */ | ||||||
|     public readonly Value: Store<{ features: any[] }> |     public readonly Value: Store<{ features: Feature<Point>[] }> | ||||||
| 
 | 
 | ||||||
|     constructor() { |     constructor() { | ||||||
|         const t = Translations.t.importHelper.selectFile |         const t = Translations.t.importHelper.selectFile | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue