forked from MapComplete/MapComplete
		
	
		
			
	
	
		
			184 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			184 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 
								 | 
							
								import {UIEventSource} from "../../Logic/UIEventSource";
							 | 
						||
| 
								 | 
							
								import {OsmConnection} from "../../Logic/Osm/OsmConnection";
							 | 
						||
| 
								 | 
							
								import FeaturePipeline from "../../Logic/FeatureSource/FeaturePipeline";
							 | 
						||
| 
								 | 
							
								import BaseUIElement from "../BaseUIElement";
							 | 
						||
| 
								 | 
							
								import LocationInput from "../Input/LocationInput";
							 | 
						||
| 
								 | 
							
								import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers";
							 | 
						||
| 
								 | 
							
								import {BBox} from "../../Logic/BBox";
							 | 
						||
| 
								 | 
							
								import {TagUtils} from "../../Logic/Tags/TagUtils";
							 | 
						||
| 
								 | 
							
								import {SubtleButton} from "../Base/SubtleButton";
							 | 
						||
| 
								 | 
							
								import Combine from "../Base/Combine";
							 | 
						||
| 
								 | 
							
								import Translations from "../i18n/Translations";
							 | 
						||
| 
								 | 
							
								import Svg from "../../Svg";
							 | 
						||
| 
								 | 
							
								import Toggle from "../Input/Toggle";
							 | 
						||
| 
								 | 
							
								import SimpleAddUI, {PresetInfo} from "../BigComponents/SimpleAddUI";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export default class ConfirmLocationOfPoint extends Combine {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    constructor(
							 | 
						||
| 
								 | 
							
								        state: {
							 | 
						||
| 
								 | 
							
								            osmConnection: OsmConnection,
							 | 
						||
| 
								 | 
							
								            featurePipeline: FeaturePipeline
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        filterViewIsOpened: UIEventSource<boolean>,
							 | 
						||
| 
								 | 
							
								        preset: PresetInfo,
							 | 
						||
| 
								 | 
							
								        confirmText: BaseUIElement,
							 | 
						||
| 
								 | 
							
								        loc: { lon: number, lat: number },
							 | 
						||
| 
								 | 
							
								        confirm: (tags: any[], location: { lat: number, lon: number }, snapOntoWayId: string) => void,
							 | 
						||
| 
								 | 
							
								        cancel: () => void,
							 | 
						||
| 
								 | 
							
								    ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        let preciseInput: LocationInput = undefined
							 | 
						||
| 
								 | 
							
								        if (preset.preciseInput !== undefined) {
							 | 
						||
| 
								 | 
							
								            // We uncouple the event source
							 | 
						||
| 
								 | 
							
								            const zloc = {...loc, zoom: 19}
							 | 
						||
| 
								 | 
							
								            const locationSrc = new UIEventSource(zloc);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            let backgroundLayer = undefined;
							 | 
						||
| 
								 | 
							
								            if (preset.preciseInput.preferredBackground) {
							 | 
						||
| 
								 | 
							
								                backgroundLayer = AvailableBaseLayers.SelectBestLayerAccordingTo(locationSrc, new UIEventSource<string | string[]>(preset.preciseInput.preferredBackground))
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            let snapToFeatures: UIEventSource<{ feature: any }[]> = undefined
							 | 
						||
| 
								 | 
							
								            let mapBounds: UIEventSource<BBox> = undefined
							 | 
						||
| 
								 | 
							
								            if (preset.preciseInput.snapToLayers && preset.preciseInput.snapToLayers.length > 0) {
							 | 
						||
| 
								 | 
							
								                snapToFeatures = new UIEventSource<{ feature: any }[]>([])
							 | 
						||
| 
								 | 
							
								                mapBounds = new UIEventSource<BBox>(undefined)
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            const tags = TagUtils.KVtoProperties(preset.tags ?? []);
							 | 
						||
| 
								 | 
							
								            preciseInput = new LocationInput({
							 | 
						||
| 
								 | 
							
								                mapBackground: backgroundLayer,
							 | 
						||
| 
								 | 
							
								                centerLocation: locationSrc,
							 | 
						||
| 
								 | 
							
								                snapTo: snapToFeatures,
							 | 
						||
| 
								 | 
							
								                snappedPointTags: tags,
							 | 
						||
| 
								 | 
							
								                maxSnapDistance: preset.preciseInput.maxSnapDistance,
							 | 
						||
| 
								 | 
							
								                bounds: mapBounds
							 | 
						||
| 
								 | 
							
								            })
							 | 
						||
| 
								 | 
							
								            preciseInput.installBounds(0.15, true)
							 | 
						||
| 
								 | 
							
								            preciseInput.SetClass("h-32 rounded-xl overflow-hidden border border-gray").SetStyle("height: 12rem;")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (preset.preciseInput.snapToLayers && preset.preciseInput.snapToLayers.length > 0) {
							 | 
						||
| 
								 | 
							
								                // We have to snap to certain layers.
							 | 
						||
| 
								 | 
							
								                // Lets fetch them
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                let loadedBbox: BBox = undefined
							 | 
						||
| 
								 | 
							
								                mapBounds?.addCallbackAndRunD(bbox => {
							 | 
						||
| 
								 | 
							
								                    if (loadedBbox !== undefined && bbox.isContainedIn(loadedBbox)) {
							 | 
						||
| 
								 | 
							
								                        // All is already there
							 | 
						||
| 
								 | 
							
								                        // return;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    bbox = bbox.pad(2);
							 | 
						||
| 
								 | 
							
								                    loadedBbox = bbox;
							 | 
						||
| 
								 | 
							
								                    const allFeatures: { feature: any }[] = []
							 | 
						||
| 
								 | 
							
								                    preset.preciseInput.snapToLayers.forEach(layerId => {
							 | 
						||
| 
								 | 
							
								                        console.log("Snapping to", layerId)
							 | 
						||
| 
								 | 
							
								                        state.featurePipeline.GetFeaturesWithin(layerId, bbox)?.forEach(feats => allFeatures.push(...feats.map(f => ({feature: f}))))
							 | 
						||
| 
								 | 
							
								                    })
							 | 
						||
| 
								 | 
							
								                    console.log("Snapping to", allFeatures)
							 | 
						||
| 
								 | 
							
								                    snapToFeatures.setData(allFeatures)
							 | 
						||
| 
								 | 
							
								                })
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        let confirmButton: BaseUIElement = new SubtleButton(preset.icon(),
							 | 
						||
| 
								 | 
							
								            new Combine([
							 | 
						||
| 
								 | 
							
								                confirmText,
							 | 
						||
| 
								 | 
							
								                Translations.t.general.add.warnVisibleForEveryone.Clone().SetClass("alert")
							 | 
						||
| 
								 | 
							
								            ]).SetClass("flex flex-col")
							 | 
						||
| 
								 | 
							
								        ).SetClass("font-bold break-words")
							 | 
						||
| 
								 | 
							
								            .onClick(() => {
							 | 
						||
| 
								 | 
							
								                confirm(preset.tags, (preciseInput?.GetValue()?.data ?? loc), preciseInput?.snappedOnto?.data?.properties?.id);
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (preciseInput !== undefined) {
							 | 
						||
| 
								 | 
							
								            confirmButton = new Combine([preciseInput, confirmButton])
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const openLayerControl =
							 | 
						||
| 
								 | 
							
								            new SubtleButton(
							 | 
						||
| 
								 | 
							
								                Svg.layers_ui(),
							 | 
						||
| 
								 | 
							
								                new Combine([
							 | 
						||
| 
								 | 
							
								                    Translations.t.general.add.layerNotEnabled
							 | 
						||
| 
								 | 
							
								                        .Subs({layer: preset.layerToAddTo.layerDef.name})
							 | 
						||
| 
								 | 
							
								                        .SetClass("alert"),
							 | 
						||
| 
								 | 
							
								                    Translations.t.general.add.openLayerControl
							 | 
						||
| 
								 | 
							
								                ])
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								                .onClick(() => filterViewIsOpened.setData(true))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const openLayerOrConfirm = new Toggle(
							 | 
						||
| 
								 | 
							
								            confirmButton,
							 | 
						||
| 
								 | 
							
								            openLayerControl,
							 | 
						||
| 
								 | 
							
								            preset.layerToAddTo.isDisplayed
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const disableFilter = new SubtleButton(
							 | 
						||
| 
								 | 
							
								            new Combine([
							 | 
						||
| 
								 | 
							
								                Svg.filter_ui().SetClass("absolute w-full"),
							 | 
						||
| 
								 | 
							
								                Svg.cross_bottom_right_svg().SetClass("absolute red-svg")
							 | 
						||
| 
								 | 
							
								            ]).SetClass("relative"),
							 | 
						||
| 
								 | 
							
								            new Combine(
							 | 
						||
| 
								 | 
							
								                [
							 | 
						||
| 
								 | 
							
								                    Translations.t.general.add.disableFiltersExplanation.Clone(),
							 | 
						||
| 
								 | 
							
								                    Translations.t.general.add.disableFilters.Clone().SetClass("text-xl")
							 | 
						||
| 
								 | 
							
								                ]
							 | 
						||
| 
								 | 
							
								            ).SetClass("flex flex-col")
							 | 
						||
| 
								 | 
							
								        ).onClick(() => {
							 | 
						||
| 
								 | 
							
								            preset.layerToAddTo.appliedFilters.setData([])
							 | 
						||
| 
								 | 
							
								            cancel()
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const disableFiltersOrConfirm = new Toggle(
							 | 
						||
| 
								 | 
							
								            openLayerOrConfirm,
							 | 
						||
| 
								 | 
							
								            disableFilter,
							 | 
						||
| 
								 | 
							
								            preset.layerToAddTo.appliedFilters.map(filters => {
							 | 
						||
| 
								 | 
							
								                if (filters === undefined || filters.length === 0) {
							 | 
						||
| 
								 | 
							
								                    return true;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                for (const filter of filters) {
							 | 
						||
| 
								 | 
							
								                    if (filter.selected === 0 && filter.filter.options.length === 1) {
							 | 
						||
| 
								 | 
							
								                        return false;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    if (filter.selected !== undefined) {
							 | 
						||
| 
								 | 
							
								                        const tags = filter.filter.options[filter.selected].osmTags
							 | 
						||
| 
								 | 
							
								                        if (tags !== undefined && tags["and"]?.length !== 0) {
							 | 
						||
| 
								 | 
							
								                            // This actually doesn't filter anything at all
							 | 
						||
| 
								 | 
							
								                            return false;
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                return true
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            })
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const tagInfo = SimpleAddUI.CreateTagInfoFor(preset, state.osmConnection);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const cancelButton = new SubtleButton(Svg.close_ui(),
							 | 
						||
| 
								 | 
							
								            Translations.t.general.cancel
							 | 
						||
| 
								 | 
							
								        ).onClick(cancel)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        super([
							 | 
						||
| 
								 | 
							
								            state.osmConnection.userDetails.data.dryRun ?
							 | 
						||
| 
								 | 
							
								                Translations.t.general.testing.Clone().SetClass("alert") : undefined,
							 | 
						||
| 
								 | 
							
								            disableFiltersOrConfirm,
							 | 
						||
| 
								 | 
							
								            cancelButton,
							 | 
						||
| 
								 | 
							
								            preset.description,
							 | 
						||
| 
								 | 
							
								            tagInfo
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        ])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        this.SetClass("flex flex-col")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 |