import Toggle from "../Input/Toggle" import Svg from "../../Svg" import { UIEventSource } from "../../Logic/UIEventSource" import { SubtleButton } from "../Base/SubtleButton" import Combine from "../Base/Combine" import { Button } from "../Base/Button" import Translations from "../i18n/Translations" import SplitAction from "../../Logic/Osm/Actions/SplitAction" import Title from "../Base/Title" import BaseUIElement from "../BaseUIElement" import { VariableUiElement } from "../Base/VariableUIElement" import { LoginToggle } from "./LoginButton" import SvelteUIElement from "../Base/SvelteUIElement" import WaySplitMap from "../BigComponents/WaySplitMap.svelte" import { Feature, Point } from "geojson" import { WayId } from "../../Models/OsmFeature" import { OsmConnection } from "../../Logic/Osm/OsmConnection" import { Changes } from "../../Logic/Osm/Changes" import { IndexedFeatureSource } from "../../Logic/FeatureSource/FeatureSource" import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" import OsmObjectDownloader from "../../Logic/Osm/OsmObjectDownloader" export default class SplitRoadWizard extends Combine { public dialogIsOpened: UIEventSource /** * A UI Element used for splitting roads * * @param id: The id of the road to remove * @param state: the state of the application */ constructor( id: WayId, state: { layout?: LayoutConfig osmConnection?: OsmConnection osmObjectDownloader?: OsmObjectDownloader changes?: Changes indexedFeatures?: IndexedFeatureSource selectedElement?: UIEventSource } ) { const t = Translations.t.split // Contains the points on the road that are selected to split on - contains geojson points with extra properties such as 'location' with the distance along the linestring const splitPoints = new UIEventSource[]>([]) const hasBeenSplit = new UIEventSource(false) // Toggle variable between show split button and map const splitClicked = new UIEventSource(false) const leafletMap = new UIEventSource(undefined) function initMap() { ;(async function ( id: WayId, splitPoints: UIEventSource ): Promise { return new SvelteUIElement(WaySplitMap, { osmWay: await state.osmObjectDownloader.DownloadObjectAsync(id), splitPoints, }) })(id, splitPoints).then((mapComponent) => leafletMap.setData(mapComponent.SetClass("w-full h-80")) ) } // Toggle between splitmap const splitButton = new SubtleButton( Svg.scissors_svg().SetStyle("height: 1.5rem; width: auto"), new Toggle( t.splitAgain.Clone().SetClass("text-lg font-bold"), t.inviteToSplit.Clone().SetClass("text-lg font-bold"), hasBeenSplit ) ) const splitToggle = new LoginToggle(splitButton, t.loginToSplit.Clone(), state) // Save button const saveButton = new Button(t.split.Clone(), async () => { hasBeenSplit.setData(true) splitClicked.setData(false) const splitAction = new SplitAction( id, splitPoints.data.map((ff) => <[number, number]>(ff.geometry).coordinates), { theme: state?.layout?.id, }, 5 ) await state.changes?.applyAction(splitAction) // We throw away the old map and splitpoints, and create a new map from scratch splitPoints.setData([]) // Close the popup. The contributor has to select a segment again to make sure they continue editing the correct segment; see #1219 state.selectedElement?.setData(undefined) }) saveButton.SetClass("btn btn-primary mr-3") const disabledSaveButton = new Button(t.split.Clone(), undefined) disabledSaveButton.SetClass("btn btn-disabled mr-3") // Only show the save button if there are split points defined const saveToggle = new Toggle( disabledSaveButton, saveButton, splitPoints.map((data) => data.length === 0) ) const cancelButton = Translations.t.general.cancel .Clone() // Not using Button() element to prevent full width button .SetClass("btn btn-secondary mr-3") .onClick(() => { splitPoints.setData([]) splitClicked.setData(false) }) cancelButton.SetClass("btn btn-secondary block") const splitTitle = new Title(t.splitTitle) const mapView = new Combine([ splitTitle, new VariableUiElement(leafletMap), new Combine([cancelButton, saveToggle]).SetClass("flex flex-row"), ]) mapView.SetClass("question") super([ Toggle.If(hasBeenSplit, () => t.hasBeenSplit.Clone().SetClass("font-bold thanks block w-full") ), new Toggle(mapView, splitToggle, splitClicked), ]) splitClicked.addCallback((view) => { if (view) { initMap() } }) this.dialogIsOpened = splitClicked const self = this splitButton.onClick(() => { splitClicked.setData(true) self.ScrollIntoView() }) } }