diff --git a/Svg.ts b/Svg.ts
index 9a5c94b8f..d24c1072a 100644
--- a/Svg.ts
+++ b/Svg.ts
@@ -264,6 +264,11 @@ export default class Svg {
public static ring_svg() { return new Img(Svg.ring, true);}
public static ring_ui() { return new FixedUiElement(Svg.ring_img);}
+ public static scissors = ""
+ public static scissors_img = Img.AsImageElement(Svg.scissors)
+ public static scissors_svg() { return new Img(Svg.scissors, true);}
+ public static scissors_ui() { return new FixedUiElement(Svg.scissors_img);}
+
public static search = " "
public static search_img = Img.AsImageElement(Svg.search)
public static search_svg() { return new Img(Svg.search, true);}
@@ -334,4 +339,4 @@ export default class Svg {
public static wikipedia_svg() { return new Img(Svg.wikipedia, true);}
public static wikipedia_ui() { return new FixedUiElement(Svg.wikipedia_img);}
-public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"direction_masked.svg": Svg.direction_masked,"direction_outline.svg": Svg.direction_outline,"direction_stroke.svg": Svg.direction_stroke,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};}
+public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"direction_masked.svg": Svg.direction_masked,"direction_outline.svg": Svg.direction_outline,"direction_stroke.svg": Svg.direction_stroke,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"scissors.svg": Svg.scissors,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};}
diff --git a/UI/Popup/SplitRoadWizard.ts b/UI/Popup/SplitRoadWizard.ts
new file mode 100644
index 000000000..5caf0ec61
--- /dev/null
+++ b/UI/Popup/SplitRoadWizard.ts
@@ -0,0 +1,163 @@
+import {VariableUiElement} from "../Base/VariableUIElement";
+import Toggle from "../Input/Toggle";
+import Translations from "../i18n/Translations";
+import Svg from "../../Svg";
+import {UIEventSource} from "../../Logic/UIEventSource";
+import {TagsFilter} from "../../Logic/Tags/TagsFilter";
+import TagRenderingConfig from "../../Customizations/JSON/TagRenderingConfig";
+import Combine from "../Base/Combine";
+import {SubtleButton} from "../Base/SubtleButton";
+import {FixedUiElement} from "../Base/FixedUiElement";
+import {Translation} from "../i18n/Translation";
+import {AndOrTagConfigJson} from "../../Customizations/JSON/TagConfigJson";
+import BaseUIElement from "../BaseUIElement";
+import SplitRoadAction from "../../Logic/Osm/SplitRoadAction";
+import Minimap from "../Base/Minimap";
+import State from "../../State";
+
+export default class SplitRoadWizard extends Toggle {
+ /**
+ * A UI Element used for splitting roads
+ *
+ * @param id: The id of the road to remove
+ */
+ constructor(id: string) {
+
+
+ const splitClicked = new UIEventSource(false);
+
+ const splitButton = new SubtleButton(Svg.scissors_ui(), "Split road");
+ splitButton.onClick(
+ () => {
+ splitClicked.setData(true)
+ }
+ )
+
+ // const isShown = new UIEventSource(id.indexOf("-") < 0)
+
+ const miniMap = new Minimap({background: State.state.backgroundLayer});
+
+ super(miniMap, splitButton, splitClicked);
+
+ }
+
+
+ private static constructConfirmButton(deleteReasons: UIEventSource): BaseUIElement {
+ const t = Translations.t.delete;
+ const btn = new Combine([
+ Svg.delete_icon_ui().SetClass("w-6 h-6 mr-3 block"),
+ t.delete.Clone()
+ ]).SetClass("flex btn bg-red-500")
+
+
+ const btnNonActive = new Combine([
+ Svg.delete_icon_ui().SetClass("w-6 h-6 mr-3 block"),
+ t.delete.Clone()
+ ]).SetClass("flex btn btn-disabled bg-red-200")
+
+ return new Toggle(
+ btn,
+ btnNonActive,
+ deleteReasons.map(reason => reason !== undefined)
+ )
+
+ }
+
+
+ private static constructExplanation(tags: UIEventSource, deleteAction: SplitRoadAction) {
+ const t = Translations.t.delete;
+ return new VariableUiElement(tags.map(
+ currentTags => {
+ const cbd = deleteAction.canBeDeleted.data;
+ if (currentTags === undefined) {
+ return t.explanations.selectReason.Clone().SetClass("subtle");
+ }
+
+ const hasDeletionTag = currentTags.asChange(currentTags).some(kv => kv.k === "_delete_reason")
+
+ if (cbd.canBeDeleted && hasDeletionTag) {
+ return t.explanations.hardDelete.Clone()
+ }
+ return new Combine([t.explanations.softDelete.Subs({reason: cbd.reason}),
+ new FixedUiElement(currentTags.asHumanString(false, true, currentTags)).SetClass("subtle")
+ ]).SetClass("flex flex-col")
+
+
+ }
+ , [deleteAction.canBeDeleted]
+ )).SetClass("block")
+ }
+
+ private static generateDeleteTagRenderingConfig(softDeletionTags: TagsFilter,
+ nonDeleteOptions: { if: TagsFilter; then: Translation }[],
+ extraDeleteReasons: { explanation: Translation; changesetMessage: string }[],
+ currentTags: any) {
+ const t = Translations.t.delete
+ nonDeleteOptions = nonDeleteOptions ?? []
+ const softDeletionTagsStr = []
+ if (softDeletionTags !== undefined) {
+ softDeletionTags.asChange(currentTags)
+ }
+ const extraOptionsStr: { if: AndOrTagConfigJson, then: any }[] = []
+ for (const nonDeleteOption of nonDeleteOptions) {
+ const newIf: string[] = nonDeleteOption.if.asChange({}).map(kv => kv.k + "=" + kv.v)
+
+ extraOptionsStr.push({
+ if: {and: newIf},
+ then: nonDeleteOption.then
+ })
+ }
+
+ for (const extraDeleteReason of (extraDeleteReasons ?? [])) {
+ extraOptionsStr.push({
+ if: {and: ["_delete_reason=" + extraDeleteReason.changesetMessage]},
+ then: extraDeleteReason.explanation
+ })
+ }
+ return new TagRenderingConfig(
+ {
+ question: t.whyDelete,
+ render: "Deleted because {_delete_reason}",
+ freeform: {
+ key: "_delete_reason",
+ addExtraTags: softDeletionTagsStr
+ },
+ mappings: [
+
+ ...extraOptionsStr,
+
+ {
+ if: {
+ and: [
+ "_delete_reason=testing point",
+ ...softDeletionTagsStr
+ ]
+ },
+ then: t.reasons.test
+ },
+ {
+ if: {
+ and: [
+ "_delete_reason=disused",
+ ...softDeletionTagsStr
+ ]
+ },
+ then: t.reasons.disused
+ },
+ {
+ if: {
+ and: [
+ "_delete_reason=not found",
+ ...softDeletionTagsStr
+ ]
+ },
+ then: t.reasons.notFound
+ }
+ ]
+
+
+ }, undefined, "Delete wizard"
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/assets/svg/scissors.svg b/assets/svg/scissors.svg
new file mode 100644
index 000000000..be55cb476
--- /dev/null
+++ b/assets/svg/scissors.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test.ts b/test.ts
index eb29b9921..630d0a7dc 100644
--- a/test.ts
+++ b/test.ts
@@ -1,166 +1,6 @@
-import {OsmObject} from "./Logic/Osm/OsmObject";
-import DeleteButton from "./UI/Popup/DeleteWizard";
-import Combine from "./UI/Base/Combine";
+import SplitRoadWizard from "./UI/Popup/SplitRoadWizard";
import State from "./State";
-import DeleteWizard from "./UI/Popup/DeleteWizard";
-import {UIEventSource} from "./Logic/UIEventSource";
-import {Tag} from "./Logic/Tags/Tag";
-import {QueryParameters} from "./Logic/Web/QueryParameters";
-import {Translation} from "./UI/i18n/Translation";
-/*import ValidatedTextField from "./UI/Input/ValidatedTextField";
-import Combine from "./UI/Base/Combine";
-import {VariableUiElement} from "./UI/Base/VariableUIElement";
-import {UIEventSource} from "./Logic/UIEventSource";
-import TagRenderingConfig from "./Customizations/JSON/TagRenderingConfig";
-import State from "./State";
-import TagRenderingQuestion from "./UI/Popup/TagRenderingQuestion";
-import {SlideShow} from "./UI/Image/SlideShow";
-import {FixedUiElement} from "./UI/Base/FixedUiElement";
-import Img from "./UI/Base/Img";
-import {AttributedImage} from "./UI/Image/AttributedImage";
-import {Imgur} from "./Logic/ImageProviders/Imgur";
-import Minimap from "./UI/Base/Minimap";
-import Loc from "./Models/Loc";
-import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers";
-import ShowDataLayer from "./UI/ShowDataLayer";
-import LayoutConfig from "./Customizations/JSON/LayoutConfig";
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
-
-function TestSlideshow() {
- const elems = new UIEventSource([
- new FixedUiElement("A"),
- new FixedUiElement("qmsldkfjqmlsdkjfmqlskdjfmqlksdf").SetClass("text-xl"),
- new Img("https://i.imgur.com/8lIQ5Hv.jpg"),
- new AttributedImage("https://i.imgur.com/y5XudzW.jpg", Imgur.singleton),
- new Img("https://www.grunge.com/img/gallery/the-real-reason-your-cat-sleeps-so-much/intro-1601496900.webp")
- ])
- new SlideShow(elems).AttachTo("maindiv")
-}
-
-function TestTagRendering() {
- State.state = new State(undefined)
- const tagsSource = new UIEventSource({
- id: "node/1"
- })
- new TagRenderingQuestion(
- tagsSource,
- new TagRenderingConfig({
- multiAnswer: false,
- freeform: {
- key: "valve"
- },
- question: "What valves are supported?",
- render: "This pump supports {valve}",
- mappings: [
- {
- if: "valve=dunlop",
- then: "This pump supports dunlop"
- },
- {
- if: "valve=shrader",
- then: "shrader is supported",
- }
- ],
-
- }, undefined, "test"),
- []
- ).AttachTo("maindiv")
- new VariableUiElement(tagsSource.map(tags => tags["valves"])).SetClass("alert").AttachTo("extradiv")
-}
-
-function TestAllInputMethods() {
-
- new Combine(ValidatedTextField.tpList.map(tp => {
- const tf = ValidatedTextField.InputForType(tp.name);
-
- return new Combine([tf, new VariableUiElement(tf.GetValue()).SetClass("alert")]);
- })).AttachTo("maindiv")
-}
-
-function TestMiniMap() {
-
- const location = new UIEventSource({
- lon: 4.84771728515625,
- lat: 51.17920846421931,
- zoom: 14
- })
- const map0 = new Minimap({
- location: location,
- allowMoving: true,
- background: new AvailableBaseLayers(location).availableEditorLayers.map(layers => layers[2])
- })
- map0.SetStyle("width: 500px; height: 250px; overflow: hidden; border: 2px solid red")
- .AttachTo("maindiv")
-
- const layout = AllKnownLayouts.layoutsList[1]
- State.state = new State(layout)
- console.log("LAYOUT is", layout.id)
-
- const feature = {
- "type": "Feature",
- _matching_layer_id: "bike_repair_station",
- "properties": {
- id: "node/-1",
- "amenity": "bicycle_repair_station"
- },
- "geometry": {
- "type": "Point",
- "coordinates": [
- 4.84771728515625,
- 51.17920846421931
- ]
- }
- }
-
- ;
-
- State.state.allElements.addOrGetElement(feature)
-
- const featureSource = new UIEventSource([{
- freshness: new Date(),
- feature: feature
- }])
-
- new ShowDataLayer(
- featureSource,
- map0.leafletMap,
- new UIEventSource(layout)
- )
-
- const map1 = new Minimap({
- location: location,
- allowMoving: true,
- background: new AvailableBaseLayers(location).availableEditorLayers.map(layers => layers[5])
- },
- )
-
- map1.SetStyle("width: 500px; height: 250px; overflow: hidden; border : 2px solid black")
- .AttachTo("extradiv")
-
-
- new ShowDataLayer(
- featureSource,
- map1.leafletMap,
- new UIEventSource(layout)
- )
-
- featureSource.ping()
-}
-//*/
-QueryParameters.GetQueryParameter("test", "true").setData("true")
-State.state= new State(undefined)
-const id = "node/5414688303"
-State.state.allElements.addElementById(id, new UIEventSource({id: id}))
-new Combine([
- new DeleteWizard(id, {
- noDeleteOptions: [
- {
- if:[ new Tag("access","private")],
- then: new Translation({
- en: "Very private! Delete now or me send lawfull lawyer"
- })
- }
- ]
- }),
-]).AttachTo("maindiv")
+State.state = new State(AllKnownLayouts.layoutsList[4]);
+new SplitRoadWizard("way/1234").AttachTo("maindiv")
\ No newline at end of file