From e1cdb75001728e522172efd8b3e9cdbba609db43 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 12 Jan 2023 01:16:22 +0100 Subject: [PATCH] Repair import flow --- UI/Base/DivContainer.ts | 20 +++++ .../CompareToAlreadyExistingNotes.ts | 6 +- UI/ImportFlow/ConflationChecker.ts | 30 ++++---- UI/ImportFlow/ImportUtils.ts | 6 +- UI/ImportFlow/MapPreview.ts | 77 +++++++++---------- UI/ImportFlow/PreviewPanel.ts | 17 ++-- UI/ImportFlow/RequestFile.ts | 3 +- 7 files changed, 85 insertions(+), 74 deletions(-) create mode 100644 UI/Base/DivContainer.ts diff --git a/UI/Base/DivContainer.ts b/UI/Base/DivContainer.ts new file mode 100644 index 0000000000..bc6c9e68e5 --- /dev/null +++ b/UI/Base/DivContainer.ts @@ -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 + } +} diff --git a/UI/ImportFlow/CompareToAlreadyExistingNotes.ts b/UI/ImportFlow/CompareToAlreadyExistingNotes.ts index 128885dab6..37aa64994c 100644 --- a/UI/ImportFlow/CompareToAlreadyExistingNotes.ts +++ b/UI/ImportFlow/CompareToAlreadyExistingNotes.ts @@ -21,6 +21,8 @@ import { VariableUiElement } from "../Base/VariableUIElement" import * as known_layers from "../../assets/generated/known_layers.json" import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson" 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 @@ -105,7 +107,7 @@ export class CompareToAlreadyExistingNotes zoomToFeatures: true, leafletMap: comparisonMap.leafletMap, features: StaticFeatureSource.fromGeojsonStore( - partitionedImportPoints.map((p) => p.hasNearby) + partitionedImportPoints.map((p) => p.hasNearby) ), popup: (tags, layer) => new FeatureInfoBox(tags, layer, state), }) @@ -134,7 +136,7 @@ export class CompareToAlreadyExistingNotes return new Combine([ t.mapExplanation.Subs(params.features), map, - + new DivContainer("fullscreen"), new VariableUiElement( partitionedImportPoints.map(({ noNearby, hasNearby }) => { if (noNearby.length === 0) { diff --git a/UI/ImportFlow/ConflationChecker.ts b/UI/ImportFlow/ConflationChecker.ts index 55ec9c0d9d..517ded7f69 100644 --- a/UI/ImportFlow/ConflationChecker.ts +++ b/UI/ImportFlow/ConflationChecker.ts @@ -27,24 +27,26 @@ import { GeoOperations } from "../../Logic/GeoOperations" import FeatureInfoBox from "../Popup/FeatureInfoBox" import { ImportUtils } from "./ImportUtils" 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 { CheckBox } from "../Input/Checkboxes" 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 */ export default class ConflationChecker extends Combine - implements FlowStep<{ features: any[]; theme: string }> + implements FlowStep<{ features: Feature[]; theme: string }> { public readonly IsValid - public readonly Value: Store<{ features: any[]; theme: string }> + public readonly Value: Store<{ features: Feature[]; theme: string }> - constructor(state, params: { bbox: BBox; layer: LayerConfig; theme: string; features: any[] }) { + constructor( + state, + params: { bbox: BBox; layer: LayerConfig; theme: string; features: Feature[] } + ) { const t = Translations.t.importHelper.conflationChecker const bbox = params.bbox.padAbsolute(0.0001) @@ -175,15 +177,8 @@ export default class ConflationChecker features: StaticFeatureSource.fromGeojson([bbox.asGeoJson({})]), }) - new ShowDataMultiLayer({ - //layerToShow: layer, - layers: new UIEventSource([ - { - layerDef: layer, - isDisplayed: new UIEventSource(true), - appliedFilters: new UIEventSource>(undefined), - }, - ]), + new ShowDataLayer({ + layerToShow: layer, state, leafletMap: osmLiveData.leafletMap, 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 const toImportWithNearby = StaticFeatureSource.fromGeojsonStore( - paritionedImport.map((els) => els?.hasNearby ?? []) + paritionedImport.map((els) => els?.hasNearby ?? []) ) toImportWithNearby.features.addCallback((nearby) => console.log("The following features are near an already existing object:", nearby) @@ -325,6 +320,7 @@ export default class ConflationChecker }) ), ]).SetClass("flex"), + new DivContainer("fullscreen"), new Title(t.titleNearby), new Combine([t.mapShowingNearbyIntro, nearbyCutoff]).SetClass("flex"), new VariableUiElement( @@ -369,7 +365,7 @@ export default class ConflationChecker this.Value = paritionedImport.map((feats) => ({ theme: params.theme, - features: feats?.noNearby, + features: feats?.noNearby, layer: params.layer, })) this.IsValid = this.Value.map((v) => v?.features !== undefined && v.features.length > 0) diff --git a/UI/ImportFlow/ImportUtils.ts b/UI/ImportFlow/ImportUtils.ts index 1622672be0..204a0b47dd 100644 --- a/UI/ImportFlow/ImportUtils.ts +++ b/UI/ImportFlow/ImportUtils.ts @@ -1,10 +1,10 @@ import { Store } from "../../Logic/UIEventSource" import { GeoOperations } from "../../Logic/GeoOperations" -import { Feature, Geometry } from "@turf/turf" +import { Feature, Point } from "geojson" export class ImportUtils { public static partitionFeaturesIfNearby( - toPartitionFeatureCollection: { features: Feature[] }, + toPartitionFeatureCollection: { features: Feature[] }, compareWith: Store<{ features: Feature[] }>, cutoffDistanceInMeters: Store ): Store<{ hasNearby: Feature[]; noNearby: Feature[] }> { @@ -25,7 +25,7 @@ export class ImportUtils { (f) => maxDist >= GeoOperations.distanceBetween( - toImportElement.geometry.coordinates, + (toImportElement.geometry).coordinates, GeoOperations.centerpointCoordinates(f) ) ) diff --git a/UI/ImportFlow/MapPreview.ts b/UI/ImportFlow/MapPreview.ts index ab18813274..23274ae2eb 100644 --- a/UI/ImportFlow/MapPreview.ts +++ b/UI/ImportFlow/MapPreview.ts @@ -25,6 +25,9 @@ import Title from "../Base/Title" import CheckBoxes from "../Input/Checkboxes" import { AllTagsPanel } from "../AllTagsPanel" import BackgroundMapSwitch from "../BigComponents/BackgroundMapSwitch" +import { Feature, Point } from "geojson" +import DivContainer from "../Base/DivContainer" +import ShowDataLayer from "../ShowDataLayer/ShowDataLayer" class PreviewPanel extends ScrollableFullScreen { constructor(tags: UIEventSource) { @@ -41,15 +44,12 @@ class PreviewPanel extends ScrollableFullScreen { */ export class MapPreview extends Combine - implements FlowStep<{ bbox: BBox; layer: LayerConfig; features: any[] }> + implements FlowStep<{ bbox: BBox; layer: LayerConfig; features: Feature[] }> { public readonly IsValid: Store public readonly Value: Store<{ bbox: BBox; layer: LayerConfig; features: any[] }> - constructor( - state: UserRelatedState, - geojson: { features: { properties: any; geometry: { coordinates: [number, number] } }[] } - ) { + constructor(state: UserRelatedState, geojson: { features: Feature[] }) { const t = Translations.t.importHelper.mapPreview const propertyKeys = new Set() @@ -90,22 +90,23 @@ export class MapPreview return copy }) - const matching: Store<{ properties: any; geometry: { coordinates: [number, number] } }[]> = - layerPicker.GetValue().map((layer: LayerConfig) => { - if (layer === undefined) { - return [] - } - const matching: { properties: any; geometry: { coordinates: [number, number] } }[] = - [] + // Create a store which has only features matching the selected layer + const matching: Store = layerPicker.GetValue().map((layer: LayerConfig) => { + if (layer === undefined) { + console.log("No matching layer found") + return [] + } + const matching: Feature[] = [] - for (const feature of withId) { - if (layer.source.osmTags.matchesProperties(feature.properties)) { - matching.push(feature) - } + for (const feature of withId) { + if (layer.source.osmTags.matchesProperties(feature.properties)) { + matching.push(feature) } + } + console.log("Matching features: ", matching) - return matching - }) + return matching + }) const background = new UIEventSource(AvailableBaseLayers.osmCarto) const location = new UIEventSource({ lat: 0, lon: 0, zoom: 1 }) const currentBounds = new UIEventSource(undefined) @@ -130,25 +131,22 @@ export class MapPreview ) map.SetClass("w-full").SetStyle("height: 500px") - new ShowDataMultiLayer({ - layers: new UIEventSource( - AllKnownLayouts.AllPublicLayers() - .filter((l) => l.source.geojsonSource === undefined) - .map((l) => ({ - layerDef: l, - isDisplayed: new UIEventSource(true), - appliedFilters: new UIEventSource>(undefined), - })) - ), - zoomToFeatures: true, - features: StaticFeatureSource.fromDateless( - matching.map((features) => features.map((feature) => ({ feature }))) - ), - leafletMap: map.leafletMap, - popup: (tag) => new PreviewPanel(tag).SetClass("font-lg"), + layerPicker.GetValue().addCallbackAndRunD((layerToShow) => { + new ShowDataLayer({ + layerToShow, + zoomToFeatures: true, + features: StaticFeatureSource.fromDateless( + matching.map((features) => features.map((feature) => ({ feature }))) + ), + leafletMap: map.leafletMap, + 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([(>f).geometry.coordinates])) + ) ) const mismatchIndicator = new VariableUiElement( @@ -171,10 +169,11 @@ export class MapPreview super([ new Title(t.title, 1), layerPicker, - new Toggle(t.autodetected.SetClass("thank"), undefined, autodetected), + new Toggle(t.autodetected.SetClass("thanks"), undefined, autodetected), mismatchIndicator, map, + new DivContainer("fullscreen"), layerControl, confirm, ]) @@ -182,10 +181,10 @@ export class MapPreview this.Value = bbox.map( (bbox) => ({ bbox, - features: geojson.features, + features: matching.data, layer: layerPicker.GetValue().data, }), - [layerPicker.GetValue()] + [layerPicker.GetValue(), matching] ) this.IsValid = matching.map( diff --git a/UI/ImportFlow/PreviewPanel.ts b/UI/ImportFlow/PreviewPanel.ts index 7bfb28533b..fd4a64e5b8 100644 --- a/UI/ImportFlow/PreviewPanel.ts +++ b/UI/ImportFlow/PreviewPanel.ts @@ -10,24 +10,19 @@ import Histogram from "../BigComponents/Histogram" import Toggleable from "../Base/Toggleable" import List from "../Base/List" import CheckBoxes from "../Input/Checkboxes" +import { Feature, Point } from "geojson" /** * Shows the attributes by value, requests to check them of */ export class PreviewAttributesPanel extends Combine - implements - FlowStep<{ features: { properties: any; geometry: { coordinates: [number, number] } }[] }> + implements FlowStep<{ features: Feature[] }> { public readonly IsValid: Store - public readonly Value: Store<{ - features: { properties: any; geometry: { coordinates: [number, number] } }[] - }> + public readonly Value: Store<{ features: Feature[] }> - constructor( - state: UserRelatedState, - geojson: { features: { properties: any; geometry: { coordinates: [number, number] } }[] } - ) { + constructor(state: UserRelatedState, geojson: { features: Feature[] }) { const t = Translations.t.importHelper.previewAttributes const propertyKeys = new Set() @@ -93,9 +88,7 @@ export class PreviewAttributesPanel confirm, ]) - this.Value = new UIEventSource<{ - features: { properties: any; geometry: { coordinates: [number, number] } }[] - }>(geojson) + this.Value = new UIEventSource<{ features: Feature[] }>(geojson) this.IsValid = confirm.GetValue().map((selected) => selected.length == 1) } } diff --git a/UI/ImportFlow/RequestFile.ts b/UI/ImportFlow/RequestFile.ts index b8231a330b..8d550d1bdd 100644 --- a/UI/ImportFlow/RequestFile.ts +++ b/UI/ImportFlow/RequestFile.ts @@ -11,6 +11,7 @@ import { FlowStep } from "./FlowStep" import { parse } from "papaparse" import { FixedUiElement } from "../Base/FixedUiElement" import { TagUtils } from "../../Logic/Tags/TagUtils" +import { Feature, Point } from "geojson" class FileSelector extends InputElementMap }> { constructor(label: BaseUIElement) { @@ -40,7 +41,7 @@ export class RequestFile extends Combine implements FlowStep<{ features: any[] } /** * The loaded GeoJSON */ - public readonly Value: Store<{ features: any[] }> + public readonly Value: Store<{ features: Feature[] }> constructor() { const t = Translations.t.importHelper.selectFile