forked from MapComplete/MapComplete
		
	First draft of split road
This commit is contained in:
		
							parent
							
								
									f5c7683d9d
								
							
						
					
					
						commit
						ae5325d4d1
					
				
					 4 changed files with 173 additions and 164 deletions
				
			
		
							
								
								
									
										7
									
								
								Svg.ts
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								Svg.ts
									
										
									
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										163
									
								
								UI/Popup/SplitRoadWizard.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								UI/Popup/SplitRoadWizard.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -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<boolean>(false); | ||||||
|  | 
 | ||||||
|  |         const splitButton = new SubtleButton(Svg.scissors_ui(), "Split road"); | ||||||
|  |         splitButton.onClick( | ||||||
|  |             () => { | ||||||
|  |                 splitClicked.setData(true) | ||||||
|  |             } | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         // const isShown = new UIEventSource<boolean>(id.indexOf("-") < 0)
 | ||||||
|  | 
 | ||||||
|  |         const miniMap = new Minimap({background: State.state.backgroundLayer}); | ||||||
|  | 
 | ||||||
|  |         super(miniMap, splitButton, splitClicked); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     private static constructConfirmButton(deleteReasons: UIEventSource<TagsFilter>): 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<TagsFilter>, 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" | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								assets/svg/scissors.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/svg/scissors.svg
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| After Width: | Height: | Size: 5.9 KiB | 
							
								
								
									
										166
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										166
									
								
								test.ts
									
										
									
									
									
								
							|  | @ -1,166 +1,6 @@ | ||||||
| import {OsmObject} from "./Logic/Osm/OsmObject"; | import SplitRoadWizard from "./UI/Popup/SplitRoadWizard"; | ||||||
| import DeleteButton from "./UI/Popup/DeleteWizard"; |  | ||||||
| import Combine from "./UI/Base/Combine"; |  | ||||||
| import State from "./State"; | 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"; | import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; | ||||||
| 
 | 
 | ||||||
| 
 | State.state = new State(AllKnownLayouts.layoutsList[4]); | ||||||
| function TestSlideshow() { | new SplitRoadWizard("way/1234").AttachTo("maindiv") | ||||||
|     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<Loc>({ |  | ||||||
|         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<LayoutConfig>(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<LayoutConfig>(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<any>({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") |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue