forked from MapComplete/MapComplete
		
	Finish import_viewer gui
This commit is contained in:
		
							parent
							
								
									cd09efca94
								
							
						
					
					
						commit
						33ef83c4a9
					
				
					 14 changed files with 198 additions and 103 deletions
				
			
		|  | @ -197,10 +197,7 @@ export class TagUtils { | ||||||
|                         } |                         } | ||||||
|                         let b = Number(value?.trim()) |                         let b = Number(value?.trim()) | ||||||
|                         if (isNaN(b)) { |                         if (isNaN(b)) { | ||||||
|                             if (value.endsWith(" UTC")) { |                             b = Utils.ParseDate(value).getTime() | ||||||
|                                 value = value.replace(" UTC", "+00") |  | ||||||
|                             } |  | ||||||
|                             b = new Date(value).getTime() |  | ||||||
|                             if (isNaN(b)) { |                             if (isNaN(b)) { | ||||||
|                                 return false |                                 return false | ||||||
|                             } |                             } | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								UI/Base/LeftIndex.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								UI/Base/LeftIndex.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | import BaseUIElement from "../BaseUIElement"; | ||||||
|  | import Combine from "./Combine"; | ||||||
|  | import BackToIndex from "../BigComponents/BackToIndex"; | ||||||
|  | 
 | ||||||
|  | export default class LeftIndex extends Combine{ | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     constructor(leftContents: BaseUIElement[], mainContent: BaseUIElement, options?:{ | ||||||
|  |         hideBackButton : false | boolean | ||||||
|  |     } ) { | ||||||
|  |          | ||||||
|  |         let back : BaseUIElement = undefined; | ||||||
|  |         if(options?.hideBackButton ?? true){ | ||||||
|  |             back = new BackToIndex() | ||||||
|  |         } | ||||||
|  |         super([ | ||||||
|  |             new Combine([ | ||||||
|  |                 new Combine([back, ...leftContents]).SetClass("sticky top-4"), | ||||||
|  |             ]).SetClass("ml-4 block w-full md:w-2/6 lg:w-1/6"), | ||||||
|  |             mainContent.SetClass("m-8 w-full mb-24") | ||||||
|  |         ]) | ||||||
|  |         this.SetClass("h-full block md:flex") | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
|  | @ -53,7 +53,7 @@ export default class Toggleable extends Combine { | ||||||
| 
 | 
 | ||||||
|         this.isVisible.addCallbackAndRun(isVisible => { |         this.isVisible.addCallbackAndRun(isVisible => { | ||||||
|             if (isVisible) { |             if (isVisible) { | ||||||
|                 contentElement.style.maxHeight = "8gs0vh" |                 contentElement.style.maxHeight = "50vh" | ||||||
|                 contentElement.style.overflowY = "auto" |                 contentElement.style.overflowY = "auto" | ||||||
|                 contentElement.style["-webkit-mask-image"] = "unset" |                 contentElement.style["-webkit-mask-image"] = "unset" | ||||||
|             } else { |             } else { | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ export default class BackToIndex extends SubtleButton { | ||||||
|             Svg.back_svg().SetStyle("height: 1.5rem;"), |             Svg.back_svg().SetStyle("height: 1.5rem;"), | ||||||
|            message ?? Translations.t.general.backToMapcomplete, |            message ?? Translations.t.general.backToMapcomplete, | ||||||
|             { |             { | ||||||
|                 url: "./index.html" |                 url: "index.html" | ||||||
|             } |             } | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -6,7 +6,8 @@ import Toggle from "../Input/Toggle"; | ||||||
| import Loading from "../Base/Loading"; | import Loading from "../Base/Loading"; | ||||||
| import {VariableUiElement} from "../Base/VariableUIElement"; | import {VariableUiElement} from "../Base/VariableUIElement"; | ||||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | import {FixedUiElement} from "../Base/FixedUiElement"; | ||||||
| import Link from "../Base/Link"; | import {SubtleButton} from "../Base/SubtleButton"; | ||||||
|  | import Svg from "../../Svg"; | ||||||
| 
 | 
 | ||||||
| export class CreateNotes extends Combine { | export class CreateNotes extends Combine { | ||||||
| 
 | 
 | ||||||
|  | @ -24,7 +25,7 @@ export class CreateNotes extends Combine { | ||||||
| 
 | 
 | ||||||
|             const tags: string [] = [] |             const tags: string [] = [] | ||||||
|             for (const key in f.properties) { |             for (const key in f.properties) { | ||||||
|                 if(f.properties[key] === ""){ |                 if (f.properties[key] === "") { | ||||||
|                     continue |                     continue | ||||||
|                 } |                 } | ||||||
|                 tags.push(key + "=" + f.properties[key].replace(/=/, "\\=").replace(/;/g, "\\;").replace(/\n/g, "\\n")) |                 tags.push(key + "=" + f.properties[key].replace(/=/, "\\=").replace(/;/g, "\\;").replace(/\n/g, "\\n")) | ||||||
|  | @ -56,7 +57,13 @@ export class CreateNotes extends Combine { | ||||||
|             "Hang on while we are importing...", |             "Hang on while we are importing...", | ||||||
|             new Toggle( |             new Toggle( | ||||||
|                 new Loading(new VariableUiElement(currentNote.map(count => new FixedUiElement("Imported <b>" + count + "</b> out of " + v.features.length + " notes")))), |                 new Loading(new VariableUiElement(currentNote.map(count => new FixedUiElement("Imported <b>" + count + "</b> out of " + v.features.length + " notes")))), | ||||||
|                 new FixedUiElement("All done!"), |                 new Combine([ | ||||||
|  |                         new FixedUiElement("All done!").SetClass("thanks"), | ||||||
|  |                         new SubtleButton(Svg.note_svg(), "Inspect the progress of your notes in the 'import_viewer'", { | ||||||
|  |                             url: "import_viewer.html" | ||||||
|  |                         }) | ||||||
|  |                     ] | ||||||
|  |                 ), | ||||||
|                 currentNote.map(count => count < v.features.length) |                 currentNote.map(count => count < v.features.length) | ||||||
|             ), |             ), | ||||||
|             new VariableUiElement(failed.map(failed => { |             new VariableUiElement(failed.map(failed => { | ||||||
|  | @ -69,11 +76,6 @@ export class CreateNotes extends Combine { | ||||||
|                     ...failed |                     ...failed | ||||||
|                 ]).SetClass("flex flex-col") |                 ]).SetClass("flex flex-col") | ||||||
| 
 | 
 | ||||||
|             })), |  | ||||||
|             new VariableUiElement(createdNotes.map(notes => { |  | ||||||
|                 const links = notes.map(n => |  | ||||||
|                     new Link(new FixedUiElement("https://openstreetmap.org/note/" + n), "https://openstreetmap.org/note/" + n, true)); |  | ||||||
|                 return new Combine(links).SetClass("flex flex-col"); |  | ||||||
|             })) |             })) | ||||||
|         ]) |         ]) | ||||||
|         this.SetClass("flex flex-col"); |         this.SetClass("flex flex-col"); | ||||||
|  |  | ||||||
|  | @ -1,7 +1,6 @@ | ||||||
| import Combine from "../Base/Combine"; | import Combine from "../Base/Combine"; | ||||||
| import Toggle from "../Input/Toggle"; | import Toggle from "../Input/Toggle"; | ||||||
| import LanguagePicker from "../LanguagePicker"; | import LanguagePicker from "../LanguagePicker"; | ||||||
| import BackToIndex from "../BigComponents/BackToIndex"; |  | ||||||
| import UserRelatedState from "../../Logic/State/UserRelatedState"; | import UserRelatedState from "../../Logic/State/UserRelatedState"; | ||||||
| import BaseUIElement from "../BaseUIElement"; | import BaseUIElement from "../BaseUIElement"; | ||||||
| import MinimapImplementation from "../Base/MinimapImplementation"; | import MinimapImplementation from "../Base/MinimapImplementation"; | ||||||
|  | @ -21,11 +20,11 @@ import {CompareToAlreadyExistingNotes} from "./CompareToAlreadyExistingNotes"; | ||||||
| import Introdution from "./Introdution"; | import Introdution from "./Introdution"; | ||||||
| import LoginToImport from "./LoginToImport"; | import LoginToImport from "./LoginToImport"; | ||||||
| import {MapPreview} from "./MapPreview"; | import {MapPreview} from "./MapPreview"; | ||||||
|  | import LeftIndex from "../Base/LeftIndex"; | ||||||
|  | import {SubtleButton} from "../Base/SubtleButton"; | ||||||
| 
 | 
 | ||||||
| export default class ImportHelperGui extends Combine { | export default class ImportHelperGui extends LeftIndex { | ||||||
|     constructor() { |     constructor() { | ||||||
|         const t = Translations.t.importHelper; |  | ||||||
| 
 |  | ||||||
|         const state = new UserRelatedState(undefined) |         const state = new UserRelatedState(undefined) | ||||||
| 
 | 
 | ||||||
|         // We disable the userbadge, as various 'showData'-layers will give a read-only view in this case
 |         // We disable the userbadge, as various 'showData'-layers will give a read-only view in this case
 | ||||||
|  | @ -61,24 +60,17 @@ export default class ImportHelperGui extends Combine { | ||||||
|             , true) |             , true) | ||||||
|          |          | ||||||
|         const leftContents: BaseUIElement[] = [ |         const leftContents: BaseUIElement[] = [ | ||||||
|             new BackToIndex().SetClass("block pl-4"), |             new SubtleButton(undefined,"Inspect your preview imports", { | ||||||
|  |                 url:"import_viewer.html" | ||||||
|  |             }), | ||||||
|             toc, |             toc, | ||||||
|             new Toggle(new FixedUiElement("Testmode - won't actually import notes").SetClass("alert"), undefined, state.featureSwitchIsTesting), |             new Toggle(new FixedUiElement("Testmode - won't actually import notes").SetClass("alert"), undefined, state.featureSwitchIsTesting), | ||||||
|             LanguagePicker.CreateLanguagePicker(Translations.t.importHelper.title.SupportedLanguages())?.SetClass("mt-4 self-end flex-col"), |             LanguagePicker.CreateLanguagePicker(Translations.t.importHelper.title.SupportedLanguages())?.SetClass("mt-4 self-end flex-col"), | ||||||
|         ].map(el => el?.SetClass("pl-4")) |         ].map(el => el?.SetClass("pl-4")) | ||||||
| 
 | 
 | ||||||
|         const leftBar = new Combine([ |         super( | ||||||
|             new Combine(leftContents).SetClass("sticky top-4 m-4"), |             leftContents, | ||||||
|           ]).SetClass("block w-full md:w-2/6 lg:w-1/6") |             flow) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         super([ |  | ||||||
|                 new Combine([ |  | ||||||
|                     leftBar, |  | ||||||
|                     flow.SetClass("m-8 w-full mb-24") |  | ||||||
|                 ]).SetClass("h-full block md:flex")]) |  | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,8 +8,6 @@ import Title from "../Base/Title"; | ||||||
| import Translations from "../i18n/Translations"; | import Translations from "../i18n/Translations"; | ||||||
| import Loading from "../Base/Loading"; | import Loading from "../Base/Loading"; | ||||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | import {FixedUiElement} from "../Base/FixedUiElement"; | ||||||
| import Toggleable from "../Base/Toggleable"; |  | ||||||
| import List from "../Base/List"; |  | ||||||
| import Link from "../Base/Link"; | import Link from "../Base/Link"; | ||||||
| import {DropDown} from "../Input/DropDown"; | import {DropDown} from "../Input/DropDown"; | ||||||
| import BaseUIElement from "../BaseUIElement"; | import BaseUIElement from "../BaseUIElement"; | ||||||
|  | @ -17,11 +15,18 @@ import ValidatedTextField from "../Input/ValidatedTextField"; | ||||||
| import {SubtleButton} from "../Base/SubtleButton"; | import {SubtleButton} from "../Base/SubtleButton"; | ||||||
| import Svg from "../../Svg"; | import Svg from "../../Svg"; | ||||||
| import Toggle from "../Input/Toggle"; | import Toggle from "../Input/Toggle"; | ||||||
|  | import Table from "../Base/Table"; | ||||||
|  | import LeftIndex from "../Base/LeftIndex"; | ||||||
|  | import Toggleable, {Accordeon} from "../Base/Toggleable"; | ||||||
|  | import TableOfContents from "../Base/TableOfContents"; | ||||||
|  | import LoginButton from "../Popup/LoginButton"; | ||||||
|  | import BackToIndex from "../BigComponents/BackToIndex"; | ||||||
| 
 | 
 | ||||||
| interface NoteProperties { | interface NoteProperties { | ||||||
|     "id": number, |     "id": number, | ||||||
|     "url": string, |     "url": string, | ||||||
|     "date_created": string |     "date_created": string, | ||||||
|  |     closed_at?: string, | ||||||
|     "status": "open" | "closed", |     "status": "open" | "closed", | ||||||
|     "comments": { |     "comments": { | ||||||
|         date: string, |         date: string, | ||||||
|  | @ -31,9 +36,15 @@ interface NoteProperties { | ||||||
|     }[] |     }[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | interface NoteState { | ||||||
|  |     props: NoteProperties, | ||||||
|  |     theme: string, | ||||||
|  |     intro: string, | ||||||
|  |     dateStr: string, | ||||||
|  |     status: "imported" | "already_mapped" | "invalid" | "closed" | "not_found" | "open" | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class MassAction extends Combine { | class MassAction extends Combine { | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     constructor(state: UserRelatedState, props: NoteProperties[]) { |     constructor(state: UserRelatedState, props: NoteProperties[]) { | ||||||
|         const textField = ValidatedTextField.InputForType("text") |         const textField = ValidatedTextField.InputForType("text") | ||||||
| 
 | 
 | ||||||
|  | @ -54,6 +65,16 @@ class MassAction extends Combine { | ||||||
|                     } |                     } | ||||||
|                 }, |                 }, | ||||||
|                 shown: "Add comment to every open note and close all notes" |                 shown: "Add comment to every open note and close all notes" | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 value: { | ||||||
|  |                     predicate: p => p.status === "open", | ||||||
|  |                     action: async p => { | ||||||
|  |                         const txt = textField.GetValue().data | ||||||
|  |                         state.osmConnection.addCommentToNode(p.id, txt) | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 shown: "Add comment to every open note" | ||||||
|             } |             } | ||||||
|         ]) |         ]) | ||||||
| 
 | 
 | ||||||
|  | @ -96,7 +117,7 @@ class MassAction extends Combine { | ||||||
|                 actions.GetValue().map(v => v !== undefined && textField.GetValue()?.data?.length > 15, [textField.GetValue()]) |                 actions.GetValue().map(v => v !== undefined && textField.GetValue()?.data?.length > 15, [textField.GetValue()]) | ||||||
|             ), |             ), | ||||||
|             new Toggle( |             new Toggle( | ||||||
|             new FixedUiElement   ( "Testmode enable").SetClass("alert"), undefined, |                 new FixedUiElement("Testmode enable").SetClass("alert"), undefined, | ||||||
|                 state.featureSwitchIsTesting |                 state.featureSwitchIsTesting | ||||||
|             ) |             ) | ||||||
|         ]); |         ]); | ||||||
|  | @ -104,6 +125,36 @@ class MassAction extends Combine { | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | class BatchView extends Toggleable { | ||||||
|  |     constructor(state: UserRelatedState, noteStates: NoteState[]) { | ||||||
|  |         const {theme, intro, dateStr} = noteStates[0] | ||||||
|  |         console.log("Creating a batchview for ", noteStates) | ||||||
|  |         super( | ||||||
|  |             new Title(theme + ": " + intro, 2), | ||||||
|  |             new Combine([ | ||||||
|  |                 new FixedUiElement(dateStr), | ||||||
|  |                 new FixedUiElement("Click to expand/collapse table"), | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                 new Table( | ||||||
|  |                     ["id", "status", "last comment"], | ||||||
|  |                     noteStates.map(ns => { | ||||||
|  |                         const link = new Link( | ||||||
|  |                             "" + ns.props.id, | ||||||
|  |                             "https://openstreetmap.org/note/" + ns.props.id, true | ||||||
|  |                         ) | ||||||
|  |                         const last_comment = ns.props.comments[ns.props.comments.length - 1].text | ||||||
|  |                         return [link, ns.status, last_comment] | ||||||
|  |                     }) | ||||||
|  |                 ).SetClass("zebra-table link-underline"), | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                 new Title("Mass apply an action"), | ||||||
|  |                 new MassAction(state, noteStates.map(ns => ns.props)).SetClass("block")]).SetClass("flex flex-col")) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class ImportInspector extends VariableUiElement { | class ImportInspector extends VariableUiElement { | ||||||
| 
 | 
 | ||||||
|     constructor(userDetails: UserDetails, state: UserRelatedState) { |     constructor(userDetails: UserDetails, state: UserRelatedState) { | ||||||
|  | @ -122,61 +173,86 @@ class ImportInspector extends VariableUiElement { | ||||||
|                 return new FixedUiElement("Something went wrong: " + notes["error"]).SetClass("alert") |                 return new FixedUiElement("Something went wrong: " + notes["error"]).SetClass("alert") | ||||||
|             } |             } | ||||||
|             // We only care about the properties here
 |             // We only care about the properties here
 | ||||||
|             const props = notes["success"].features.map(f => f.properties) |             const props: NoteProperties[] = notes["success"].features.map(f => f.properties) | ||||||
|  |             const perBatch: NoteState[][] = Array.from(ImportInspector.SplitNotesIntoBatches(props).values()); | ||||||
|  |             const els: Toggleable[] = perBatch.map(noteStates => new BatchView(state, noteStates)) | ||||||
| 
 | 
 | ||||||
|             const perBatch = new Map<string, { props: NoteProperties[], theme: string }>() |             const accordeon = new Accordeon(els) | ||||||
|             const prefix = "https://mapcomplete.osm.be/" |             const content = new Combine([ | ||||||
|             for (const prop of props) { |                 new Title(Translations.t.importInspector.title, 1), | ||||||
|                 const lines = prop.comments[0].text.split("\n") |                 new SubtleButton(undefined, "Create a new batch of imports",{url:'import_helper.html'}), | ||||||
|                 const trigger = lines.findIndex(l => l.startsWith(prefix) && l.endsWith("#import")) |                 accordeon]) | ||||||
|                 if (trigger < 0) { |             return new LeftIndex( | ||||||
|                     continue |                 [new TableOfContents(content, {noTopLevel: true, maxDepth: 1}).SetClass("subtle")], | ||||||
|                 } |                 content | ||||||
|                 let theme = lines[trigger].substr(prefix.length) |             ) | ||||||
|                 theme = theme.substr(0, theme.indexOf(".")) |  | ||||||
|                 const key = lines[0] |  | ||||||
|                 if (!perBatch.has(key)) { |  | ||||||
|                     perBatch.set(key, {props: [], theme}) |  | ||||||
|                 } |  | ||||||
|                 perBatch.get(key).props.push(prop) |  | ||||||
|             } |  | ||||||
|             const els = [] |  | ||||||
|             perBatch.forEach(({props, theme}, intro) => { |  | ||||||
|                 els.push(new Combine([ |  | ||||||
|                     new Title(theme + ": " + intro + " (" + props.length + " features)", 2), |  | ||||||
|                     new Toggleable(new FixedUiElement("Notes"), |  | ||||||
|                         new List(props.map(prop => new Link( |  | ||||||
|                             "" + prop.id, |  | ||||||
|                             "https://openstreetmap.org/note/" + prop.id, true |  | ||||||
|                         )))), |  | ||||||
|                     new Title("Mass apply an action"), |  | ||||||
|                     new MassAction(state, props).SetClass("block") |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|                 ])) |  | ||||||
|             }) |  | ||||||
|             return new Combine(els) |  | ||||||
| 
 | 
 | ||||||
|         })); |         })); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates distinct batches of note, where 'date', 'intro' and 'theme' are identical | ||||||
|  |      */ | ||||||
|  |     private static SplitNotesIntoBatches(props: NoteProperties[]): Map<string, NoteState[]> { | ||||||
|  |         const perBatch = new Map<string, NoteState[]>() | ||||||
|  |         const prefix = "https://mapcomplete.osm.be/" | ||||||
|  |         for (const prop of props) { | ||||||
|  |             const lines = prop.comments[0].text.split("\n") | ||||||
|  |             const trigger = lines.findIndex(l => l.startsWith(prefix) && l.endsWith("#import")) | ||||||
|  |             if (trigger < 0) { | ||||||
|  |                 continue | ||||||
|  |             } | ||||||
|  |             let theme = lines[trigger].substr(prefix.length) | ||||||
|  |             theme = theme.substr(0, theme.indexOf(".")) | ||||||
|  |             const date = Utils.ParseDate(prop.date_created) | ||||||
|  |             const dateStr = date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate() | ||||||
|  |             const key = theme + lines[0] + dateStr | ||||||
|  |             if (!perBatch.has(key)) { | ||||||
|  |                 perBatch.set(key, []) | ||||||
|  |             } | ||||||
|  |             let status: "open" | "closed" | "imported" | "invalid" | "already_mapped" | "not_found" = "open" | ||||||
|  |             if (prop.closed_at !== undefined) { | ||||||
|  |                 const lastComment = prop.comments[prop.comments.length - 1].text.toLowerCase() | ||||||
|  |                 if (lastComment.indexOf("does not exist") >= 0) { | ||||||
|  |                     status = "not_found" | ||||||
|  |                 } else if (lastComment.indexOf("already mapped") >= 0) { | ||||||
|  |                     status = "already_mapped" | ||||||
|  |                 } else if (lastComment.indexOf("invalid") >= 0 || lastComment.indexOf("incorrecto") >= 0) { | ||||||
|  |                     status = "invalid" | ||||||
|  |                 } else if (lastComment.indexOf("imported") >= 0) { | ||||||
|  |                     status = "imported" | ||||||
|  |                 } else { | ||||||
|  |                     status = "closed" | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             perBatch.get(key).push({ | ||||||
|  |                 props: prop, | ||||||
|  |                 intro: lines[0], | ||||||
|  |                 theme, | ||||||
|  |                 dateStr, | ||||||
|  |                 status | ||||||
|  |             }) | ||||||
|  |         } | ||||||
|  |         return perBatch; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default class ImportInspectorGui extends Combine { | class ImportViewerGui extends Combine { | ||||||
| 
 | 
 | ||||||
|     constructor() { |     constructor() { | ||||||
|         const state = new UserRelatedState(undefined) |         const state = new UserRelatedState(undefined) | ||||||
|         const t = Translations.t.importInspector; |  | ||||||
|         super([ |         super([ | ||||||
|             new Title(t.title, 1), |  | ||||||
|             new VariableUiElement(state.osmConnection.userDetails.map(ud => { |             new VariableUiElement(state.osmConnection.userDetails.map(ud => { | ||||||
|                 if (ud === undefined || ud.loggedIn === false) { |                 if (ud === undefined || ud.loggedIn === false) { | ||||||
|                     return undefined |                     return new Combine([new LoginButton("Login to inspect your import flows", state), | ||||||
|  |                     new BackToIndex() | ||||||
|  |                     ]) | ||||||
|                 } |                 } | ||||||
|                 return new ImportInspector(ud, state); |                 return new ImportInspector(ud, state); | ||||||
|             })) |             })) | ||||||
|         ]); |         ]); | ||||||
|     } |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 
 | new ImportViewerGui().AttachTo("main") | ||||||
| } |  | ||||||
|  | @ -8,6 +8,7 @@ import BaseUIElement from "./BaseUIElement"; | ||||||
| import LanguagePicker from "./LanguagePicker"; | import LanguagePicker from "./LanguagePicker"; | ||||||
| import TableOfContents from "./Base/TableOfContents"; | import TableOfContents from "./Base/TableOfContents"; | ||||||
| import BackToIndex from "./BigComponents/BackToIndex"; | import BackToIndex from "./BigComponents/BackToIndex"; | ||||||
|  | import LeftIndex from "./Base/LeftIndex"; | ||||||
| 
 | 
 | ||||||
| class Snippet extends Toggleable { | class Snippet extends Toggleable { | ||||||
|     constructor(translations, ...extraContent: BaseUIElement[]) { |     constructor(translations, ...extraContent: BaseUIElement[]) { | ||||||
|  | @ -39,7 +40,7 @@ class SnippetContent extends Combine { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class ProfessionalGui { | class ProfessionalGui extends LeftIndex{ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     constructor() { |     constructor() { | ||||||
|  | @ -93,7 +94,6 @@ class ProfessionalGui { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         const leftContents: BaseUIElement[] = [ |         const leftContents: BaseUIElement[] = [ | ||||||
|             new BackToIndex().SetClass("block"), |  | ||||||
|             new TableOfContents(content, { |             new TableOfContents(content, { | ||||||
|                 noTopLevel: true, |                 noTopLevel: true, | ||||||
|                 maxDepth: 2 |                 maxDepth: 2 | ||||||
|  | @ -102,10 +102,7 @@ class ProfessionalGui { | ||||||
|             LanguagePicker.CreateLanguagePicker(Translations.t.professional.title.SupportedLanguages())?.SetClass("mt-4 self-end flex-col"), |             LanguagePicker.CreateLanguagePicker(Translations.t.professional.title.SupportedLanguages())?.SetClass("mt-4 self-end flex-col"), | ||||||
|         ].map(el => el?.SetClass("pl-4")) |         ].map(el => el?.SetClass("pl-4")) | ||||||
|          |          | ||||||
|         const leftBar = new Combine([ |         super(leftContents, content) | ||||||
|             new Combine(leftContents).SetClass("sticky top-4 m-4") |  | ||||||
|         ]).SetClass("block w-full md:w-2/6 lg:w-1/6") |  | ||||||
|         new Combine([leftBar, content]).SetClass("block md:flex").AttachTo("main") |  | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -113,4 +110,4 @@ class ProfessionalGui { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| new FixedUiElement("").AttachTo("decoration-desktop") | new FixedUiElement("").AttachTo("decoration-desktop") | ||||||
| new ProfessionalGui() | new ProfessionalGui().AttachTo("main") | ||||||
							
								
								
									
										7
									
								
								Utils.ts
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								Utils.ts
									
										
									
									
									
								
							|  | @ -625,6 +625,13 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be | ||||||
|         } |         } | ||||||
|         return JSON.parse(JSON.stringify(x)); |         return JSON.parse(JSON.stringify(x)); | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |     public static ParseDate(str: string): Date{ | ||||||
|  |         if (str.endsWith(" UTC")) { | ||||||
|  |             str = str.replace(" UTC", "+00") | ||||||
|  |         } | ||||||
|  |         return new Date(str) | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     private static colorDiff(c0: { r: number, g: number, b: number }, c1: { r: number, g: number, b: number }) { |     private static colorDiff(c0: { r: number, g: number, b: number }, c1: { r: number, g: number, b: number }) { | ||||||
|         return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b); |         return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b); | ||||||
|  |  | ||||||
|  | @ -752,14 +752,14 @@ video { | ||||||
|   bottom: 0px; |   bottom: 0px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .top-4 { |  | ||||||
|   top: 1rem; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .right-1\/3 { | .right-1\/3 { | ||||||
|   right: 33.333333%; |   right: 33.333333%; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .top-4 { | ||||||
|  |   top: 1rem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .top-0 { | .top-0 { | ||||||
|   top: 0px; |   top: 0px; | ||||||
| } | } | ||||||
|  | @ -872,6 +872,14 @@ video { | ||||||
|   margin-top: 0.25rem; |   margin-top: 0.25rem; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .ml-4 { | ||||||
|  |   margin-left: 1rem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .mb-24 { | ||||||
|  |   margin-bottom: 6rem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .mr-4 { | .mr-4 { | ||||||
|   margin-right: 1rem; |   margin-right: 1rem; | ||||||
| } | } | ||||||
|  | @ -912,10 +920,6 @@ video { | ||||||
|   margin-left: 0.25rem; |   margin-left: 0.25rem; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .mb-24 { |  | ||||||
|   margin-bottom: 6rem; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .mr-0 { | .mr-0 { | ||||||
|   margin-right: 0px; |   margin-right: 0px; | ||||||
| } | } | ||||||
|  | @ -1182,10 +1186,6 @@ video { | ||||||
|   flex-grow: 1; |   flex-grow: 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .table-auto { |  | ||||||
|   table-layout: auto; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .border-collapse { | .border-collapse { | ||||||
|   border-collapse: collapse; |   border-collapse: collapse; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -319,7 +319,10 @@ | ||||||
|         "layerName": "Hier is misschien een {title}", |         "layerName": "Hier is misschien een {title}", | ||||||
|         "description": "Deze laag toont kaart-nota's die wijzen op een {title}", |         "description": "Deze laag toont kaart-nota's die wijzen op een {title}", | ||||||
|         "popupTitle": "Mogelijkse {title}", |         "popupTitle": "Mogelijkse {title}", | ||||||
|         "importButton": "import_button({layerId}, _tags, Hier is een {title}, voeg toe...,./assets/svg/addSmall.svg,,,id)", |         "importButton": "import_button({layerId}, _tags, Ik heb hier een {title} gevonden - voeg deze toe aan de kaart...,./assets/svg/addSmall.svg,,,id)", | ||||||
|         "importHandled": "<div class='thanks'>Dit punt is afgehandeld. Bedankt om mee te helpen!</div>" |         "importHandled": "<div class='thanks'>Dit punt is afgehandeld. Bedankt om mee te helpen!</div>", | ||||||
|  | 
 | ||||||
|  |         "notFound": "Ik kon geen {title} vinden hier - verwijder deze van de kaart", | ||||||
|  |         "alreadyMapped": "Er staat hier reeds een {title} op de kaart; dit punt is een duplicaat. Verwijder deze van de kaart" | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ | ||||||
|     "prepare-deploy": "./scripts/build.sh", |     "prepare-deploy": "./scripts/build.sh", | ||||||
|     "gittag": "ts-node scripts/printVersion.ts | bash", |     "gittag": "ts-node scripts/printVersion.ts | bash", | ||||||
|     "lint": "tslint --project . -c tslint.json '**.ts' ", |     "lint": "tslint --project . -c tslint.json '**.ts' ", | ||||||
|     "clean": "rm -rf .cache/ && (find *.html | grep -v \"\\(404\\|index\\|land\\|test\\|preferences\\|customGenerator\\|professional\\|automaton\\|import_helper\\|theme\\).html\" | xargs rm) && (ls | grep \"^index_[a-zA-Z_]\\+\\.ts$\" | xargs rm) && (ls | grep \".*.webmanifest$\" | xargs rm)", |     "clean": "rm -rf .cache/ && (find *.html | grep -v \"\\(404\\|index\\|land\\|test\\|preferences\\|customGenerator\\|professional\\|automaton\\|import_helper\\|import_viewer\\|theme\\).html\" | xargs rm) && (ls | grep \"^index_[a-zA-Z_]\\+\\.ts$\" | xargs rm) && (ls | grep \".*.webmanifest$\" | xargs rm)", | ||||||
|     "generate:dependency-graph": "node_modules/.bin/depcruise --exclude \"^node_modules\" --output-type dot Logic/State/MapState.ts > dependencies.dot && dot dependencies.dot -T svg -o dependencies.svg && rm dependencies.dot", |     "generate:dependency-graph": "node_modules/.bin/depcruise --exclude \"^node_modules\" --output-type dot Logic/State/MapState.ts > dependencies.dot && dot dependencies.dot -T svg -o dependencies.svg && rm dependencies.dot", | ||||||
|     "bicycle_rental": "ts-node ./scripts/extractBikeRental.ts" |     "bicycle_rental": "ts-node ./scripts/extractBikeRental.ts" | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ fi | ||||||
| 
 | 
 | ||||||
| echo -e "\n\n   Building non-theme pages" | echo -e "\n\n   Building non-theme pages" | ||||||
| echo -e "  ==========================\n\n" | echo -e "  ==========================\n\n" | ||||||
| parcel build --public-url "./" $SRC_MAPS "index.html" "404.html" "professional.html" "automaton.html" "import_helper.html" "land.html" "customGenerator.html" "theme.html" vendor | parcel build --public-url "./" $SRC_MAPS "index.html" "404.html" "professional.html" "automaton.html" "import_helper.html" "import_viewer.html" "land.html" "customGenerator.html" "theme.html" vendor | ||||||
| echo -e "\n\n   Building theme pages" | echo -e "\n\n   Building theme pages" | ||||||
| echo -e "  ======================\n\n" | echo -e "  ======================\n\n" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								test.ts
									
										
									
									
									
								
							|  | @ -1,4 +0,0 @@ | ||||||
| import ImportInspectorGui from "./UI/ImportFlow/ImportInspector"; |  | ||||||
| 
 |  | ||||||
| new ImportInspectorGui().AttachTo("maindiv") |  | ||||||
| 
 |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue