| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  | import Combine from "../Base/Combine"; | 
					
						
							|  |  |  | import {UIEventSource} from "../../Logic/UIEventSource"; | 
					
						
							|  |  |  | import {BBox} from "../../Logic/BBox"; | 
					
						
							|  |  |  | import UserRelatedState from "../../Logic/State/UserRelatedState"; | 
					
						
							|  |  |  | import Translations from "../i18n/Translations"; | 
					
						
							|  |  |  | import {AllKnownLayouts} from "../../Customizations/AllKnownLayouts"; | 
					
						
							|  |  |  | import Constants from "../../Models/Constants"; | 
					
						
							|  |  |  | import {DropDown} from "../Input/DropDown"; | 
					
						
							|  |  |  | import {Utils} from "../../Utils"; | 
					
						
							|  |  |  | import LayerConfig from "../../Models/ThemeConfig/LayerConfig"; | 
					
						
							|  |  |  | import BaseLayer from "../../Models/BaseLayer"; | 
					
						
							|  |  |  | import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers"; | 
					
						
							|  |  |  | import Loc from "../../Models/Loc"; | 
					
						
							|  |  |  | import Minimap from "../Base/Minimap"; | 
					
						
							|  |  |  | import Attribution from "../BigComponents/Attribution"; | 
					
						
							|  |  |  | import ShowDataMultiLayer from "../ShowDataLayer/ShowDataMultiLayer"; | 
					
						
							|  |  |  | import FilteredLayer, {FilterState} from "../../Models/FilteredLayer"; | 
					
						
							|  |  |  | import StaticFeatureSource from "../../Logic/FeatureSource/Sources/StaticFeatureSource"; | 
					
						
							|  |  |  | import Toggle from "../Input/Toggle"; | 
					
						
							|  |  |  | import {VariableUiElement} from "../Base/VariableUIElement"; | 
					
						
							|  |  |  | import {FixedUiElement} from "../Base/FixedUiElement"; | 
					
						
							|  |  |  | import {FlowStep} from "./FlowStep"; | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  | import ScrollableFullScreen from "../Base/ScrollableFullScreen"; | 
					
						
							|  |  |  | import {AllTagsPanel} from "../SpecialVisualizations"; | 
					
						
							|  |  |  | import Title from "../Base/Title"; | 
					
						
							| 
									
										
										
										
											2022-01-22 02:56:35 +01:00
										 |  |  | import CheckBoxes from "../Input/Checkboxes"; | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | class PreviewPanel extends ScrollableFullScreen { | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     constructor(tags, layer) { | 
					
						
							|  |  |  |         super( | 
					
						
							|  |  |  |             _ => new FixedUiElement("Element to import"), | 
					
						
							|  |  |  |             _ => new Combine(["The tags are:",  | 
					
						
							|  |  |  |                 new AllTagsPanel(tags) | 
					
						
							|  |  |  |             ]).SetClass("flex flex-col"), | 
					
						
							|  |  |  |             "element" | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Shows the data to import on a map, asks for the correct layer to be selected | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-01-22 02:56:35 +01:00
										 |  |  | export class MapPreview extends Combine implements FlowStep<{ bbox: BBox, layer: LayerConfig, geojson: any }>{ | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |     public readonly IsValid: UIEventSource<boolean>; | 
					
						
							|  |  |  |     public readonly Value: UIEventSource<{ bbox: BBox, layer: LayerConfig, geojson: any }> | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     constructor( | 
					
						
							|  |  |  |         state: UserRelatedState, | 
					
						
							|  |  |  |         geojson: { features: { properties: any, geometry: { coordinates: [number, number] } }[] }) { | 
					
						
							| 
									
										
										
										
											2022-01-22 02:56:35 +01:00
										 |  |  |         const t = Translations.t.importHelper.mapPreview; | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const propertyKeys = new Set<string>() | 
					
						
							|  |  |  |         for (const f of geojson.features) { | 
					
						
							|  |  |  |             Object.keys(f.properties).forEach(key => propertyKeys.add(key)) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const availableLayers = AllKnownLayouts.AllPublicLayers().filter(l => l.name !== undefined && Constants.priviliged_layers.indexOf(l.id) < 0) | 
					
						
							| 
									
										
										
										
											2022-01-22 02:56:35 +01:00
										 |  |  |         const layerPicker = new DropDown(t.selectLayer, | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |             [{shown: t.selectLayer, value: undefined}].concat(availableLayers.map(l => ({ | 
					
						
							|  |  |  |                 shown: l.name, | 
					
						
							|  |  |  |                 value: l | 
					
						
							|  |  |  |             }))) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let autodetected = new UIEventSource(false) | 
					
						
							|  |  |  |         for (const layer of availableLayers) { | 
					
						
							|  |  |  |             const mismatched = geojson.features.some(f => | 
					
						
							|  |  |  |                 !layer.source.osmTags.matchesProperties(f.properties) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             if (!mismatched) { | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  |                 console.log("Autodected layer", layer.id) | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |                 layerPicker.GetValue().setData(layer); | 
					
						
							|  |  |  |                 layerPicker.GetValue().addCallback(_ => autodetected.setData(false)) | 
					
						
							|  |  |  |                 autodetected.setData(true) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const withId = geojson.features.map((f, i) => { | 
					
						
							|  |  |  |             const copy = Utils.Clone(f) | 
					
						
							|  |  |  |             copy.properties.id = "to-import/" + i | 
					
						
							|  |  |  |             return copy | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const matching: UIEventSource<{ properties: any, geometry: { coordinates: [number, number] } }[]> = layerPicker.GetValue().map((layer: LayerConfig) => { | 
					
						
							|  |  |  |             if (layer === undefined) { | 
					
						
							|  |  |  |                 return undefined; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             const matching: { properties: any, geometry: { coordinates: [number, number] } }[] = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (const feature of withId) { | 
					
						
							|  |  |  |                 if (layer.source.osmTags.matchesProperties(feature.properties)) { | 
					
						
							|  |  |  |                     matching.push(feature) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return matching | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         const background = new UIEventSource<BaseLayer>(AvailableBaseLayers.osmCarto) | 
					
						
							|  |  |  |         const location = new UIEventSource<Loc>({lat: 0, lon: 0, zoom: 1}) | 
					
						
							|  |  |  |         const currentBounds = new UIEventSource<BBox>(undefined) | 
					
						
							|  |  |  |         const map = Minimap.createMiniMap({ | 
					
						
							|  |  |  |             allowMoving: true, | 
					
						
							|  |  |  |             location, | 
					
						
							|  |  |  |             background, | 
					
						
							|  |  |  |             bounds: currentBounds, | 
					
						
							|  |  |  |             attribution: new Attribution(location, state.osmConnection.userDetails, undefined, currentBounds) | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         map.SetClass("w-full").SetStyle("height: 500px") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         new ShowDataMultiLayer({ | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  |             layers: new UIEventSource<FilteredLayer[]>(AllKnownLayouts.AllPublicLayers() | 
					
						
							|  |  |  |                 .filter(l => l.source.geojsonSource === undefined) | 
					
						
							|  |  |  |                 .map(l => ({ | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |                 layerDef: l, | 
					
						
							|  |  |  |                 isDisplayed: new UIEventSource<boolean>(true), | 
					
						
							|  |  |  |                 appliedFilters: new UIEventSource<Map<string, FilterState>>(undefined) | 
					
						
							|  |  |  |             }))), | 
					
						
							|  |  |  |             zoomToFeatures: true, | 
					
						
							|  |  |  |             features: new StaticFeatureSource(matching, false), | 
					
						
							|  |  |  |             leafletMap: map.leafletMap, | 
					
						
							| 
									
										
										
										
											2022-01-21 01:57:16 +01:00
										 |  |  |             popup: (tag, layer) => new PreviewPanel(tag, layer).SetClass("font-lg") | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |         }) | 
					
						
							|  |  |  |         var bbox = matching.map(feats => BBox.bboxAroundAll(feats.map(f => new BBox([f.geometry.coordinates])))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-22 02:56:35 +01:00
										 |  |  |          | 
					
						
							|  |  |  |         const mismatchIndicator =   new VariableUiElement(matching.map(matching => { | 
					
						
							|  |  |  |             if (matching === undefined) { | 
					
						
							|  |  |  |                 return undefined | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             const diff = geojson.features.length - matching.length; | 
					
						
							|  |  |  |             if (diff === 0) { | 
					
						
							|  |  |  |                 return undefined | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             const obligatory = layerPicker.GetValue().data?.source?.osmTags?.asHumanString(false, false, {}); | 
					
						
							|  |  |  |             return t.mismatch.Subs({count: diff, tags: obligatory}).SetClass("alert") | 
					
						
							|  |  |  |         })) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         const confirm = new CheckBoxes([t.confirm]); | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |         super([ | 
					
						
							| 
									
										
										
										
											2022-01-22 02:56:35 +01:00
										 |  |  |             new Title(t.title, 1), | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |             layerPicker, | 
					
						
							| 
									
										
										
										
											2022-01-22 02:56:35 +01:00
										 |  |  |             new Toggle(t.autodetected.SetClass("thank"), undefined, autodetected), | 
					
						
							|  |  |  |            | 
					
						
							|  |  |  |         mismatchIndicator  , | 
					
						
							|  |  |  |             map, | 
					
						
							|  |  |  |             confirm | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |         ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.Value = bbox.map(bbox => | 
					
						
							|  |  |  |             ({ | 
					
						
							|  |  |  |                 bbox, | 
					
						
							|  |  |  |                 geojson, | 
					
						
							|  |  |  |                 layer: layerPicker.GetValue().data | 
					
						
							|  |  |  |             }), [layerPicker.GetValue()]) | 
					
						
							| 
									
										
										
										
											2022-01-22 02:56:35 +01:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |         this.IsValid = matching.map(matching => { | 
					
						
							|  |  |  |             if (matching === undefined) { | 
					
						
							|  |  |  |                 return false | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-01-22 02:56:35 +01:00
										 |  |  |             if(confirm.GetValue().data.length !== 1){ | 
					
						
							|  |  |  |                 return false | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |             const diff = geojson.features.length - matching.length; | 
					
						
							|  |  |  |             return diff === 0; | 
					
						
							| 
									
										
										
										
											2022-01-22 02:56:35 +01:00
										 |  |  |         }, [confirm.GetValue()]) | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  |          | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |