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())
 | 
			
		||||
                        if (isNaN(b)) {
 | 
			
		||||
                            if (value.endsWith(" UTC")) {
 | 
			
		||||
                                value = value.replace(" UTC", "+00")
 | 
			
		||||
                            }
 | 
			
		||||
                            b = new Date(value).getTime()
 | 
			
		||||
                            b = Utils.ParseDate(value).getTime()
 | 
			
		||||
                            if (isNaN(b)) {
 | 
			
		||||
                                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 => {
 | 
			
		||||
            if (isVisible) {
 | 
			
		||||
                contentElement.style.maxHeight = "8gs0vh"
 | 
			
		||||
                contentElement.style.maxHeight = "50vh"
 | 
			
		||||
                contentElement.style.overflowY = "auto"
 | 
			
		||||
                contentElement.style["-webkit-mask-image"] = "unset"
 | 
			
		||||
            } else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ export default class BackToIndex extends SubtleButton {
 | 
			
		|||
            Svg.back_svg().SetStyle("height: 1.5rem;"),
 | 
			
		||||
           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 {VariableUiElement} from "../Base/VariableUIElement";
 | 
			
		||||
import {FixedUiElement} from "../Base/FixedUiElement";
 | 
			
		||||
import Link from "../Base/Link";
 | 
			
		||||
import {SubtleButton} from "../Base/SubtleButton";
 | 
			
		||||
import Svg from "../../Svg";
 | 
			
		||||
 | 
			
		||||
export class CreateNotes extends Combine {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +25,7 @@ export class CreateNotes extends Combine {
 | 
			
		|||
 | 
			
		||||
            const tags: string [] = []
 | 
			
		||||
            for (const key in f.properties) {
 | 
			
		||||
                if(f.properties[key] === ""){
 | 
			
		||||
                if (f.properties[key] === "") {
 | 
			
		||||
                    continue
 | 
			
		||||
                }
 | 
			
		||||
                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...",
 | 
			
		||||
            new Toggle(
 | 
			
		||||
                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)
 | 
			
		||||
            ),
 | 
			
		||||
            new VariableUiElement(failed.map(failed => {
 | 
			
		||||
| 
						 | 
				
			
			@ -69,11 +76,6 @@ export class CreateNotes extends Combine {
 | 
			
		|||
                    ...failed
 | 
			
		||||
                ]).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");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
import Combine from "../Base/Combine";
 | 
			
		||||
import Toggle from "../Input/Toggle";
 | 
			
		||||
import LanguagePicker from "../LanguagePicker";
 | 
			
		||||
import BackToIndex from "../BigComponents/BackToIndex";
 | 
			
		||||
import UserRelatedState from "../../Logic/State/UserRelatedState";
 | 
			
		||||
import BaseUIElement from "../BaseUIElement";
 | 
			
		||||
import MinimapImplementation from "../Base/MinimapImplementation";
 | 
			
		||||
| 
						 | 
				
			
			@ -21,11 +20,11 @@ import {CompareToAlreadyExistingNotes} from "./CompareToAlreadyExistingNotes";
 | 
			
		|||
import Introdution from "./Introdution";
 | 
			
		||||
import LoginToImport from "./LoginToImport";
 | 
			
		||||
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() {
 | 
			
		||||
        const t = Translations.t.importHelper;
 | 
			
		||||
 | 
			
		||||
        const state = new UserRelatedState(undefined)
 | 
			
		||||
 | 
			
		||||
        // 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)
 | 
			
		||||
        
 | 
			
		||||
        const leftContents: BaseUIElement[] = [
 | 
			
		||||
            new BackToIndex().SetClass("block pl-4"),
 | 
			
		||||
            new SubtleButton(undefined,"Inspect your preview imports", {
 | 
			
		||||
                url:"import_viewer.html"
 | 
			
		||||
            }),
 | 
			
		||||
            toc,
 | 
			
		||||
            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"),
 | 
			
		||||
        ].map(el => el?.SetClass("pl-4"))
 | 
			
		||||
 | 
			
		||||
        const leftBar = new Combine([
 | 
			
		||||
            new Combine(leftContents).SetClass("sticky top-4 m-4"),
 | 
			
		||||
          ]).SetClass("block w-full md:w-2/6 lg:w-1/6")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        super([
 | 
			
		||||
                new Combine([
 | 
			
		||||
                    leftBar,
 | 
			
		||||
                    flow.SetClass("m-8 w-full mb-24")
 | 
			
		||||
                ]).SetClass("h-full block md:flex")])
 | 
			
		||||
        super(
 | 
			
		||||
            leftContents,
 | 
			
		||||
            flow)
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,8 +8,6 @@ import Title from "../Base/Title";
 | 
			
		|||
import Translations from "../i18n/Translations";
 | 
			
		||||
import Loading from "../Base/Loading";
 | 
			
		||||
import {FixedUiElement} from "../Base/FixedUiElement";
 | 
			
		||||
import Toggleable from "../Base/Toggleable";
 | 
			
		||||
import List from "../Base/List";
 | 
			
		||||
import Link from "../Base/Link";
 | 
			
		||||
import {DropDown} from "../Input/DropDown";
 | 
			
		||||
import BaseUIElement from "../BaseUIElement";
 | 
			
		||||
| 
						 | 
				
			
			@ -17,11 +15,18 @@ import ValidatedTextField from "../Input/ValidatedTextField";
 | 
			
		|||
import {SubtleButton} from "../Base/SubtleButton";
 | 
			
		||||
import Svg from "../../Svg";
 | 
			
		||||
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 {
 | 
			
		||||
    "id": number,
 | 
			
		||||
    "url": string,
 | 
			
		||||
    "date_created": string
 | 
			
		||||
    "date_created": string,
 | 
			
		||||
    closed_at?: string,
 | 
			
		||||
    "status": "open" | "closed",
 | 
			
		||||
    "comments": {
 | 
			
		||||
        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 {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    constructor(state: UserRelatedState, props: NoteProperties[]) {
 | 
			
		||||
        const textField = ValidatedTextField.InputForType("text")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +65,16 @@ class MassAction extends Combine {
 | 
			
		|||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                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()])
 | 
			
		||||
            ),
 | 
			
		||||
            new Toggle(
 | 
			
		||||
            new FixedUiElement   ( "Testmode enable").SetClass("alert"), undefined,
 | 
			
		||||
                new FixedUiElement("Testmode enable").SetClass("alert"), undefined,
 | 
			
		||||
                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 {
 | 
			
		||||
 | 
			
		||||
    constructor(userDetails: UserDetails, state: UserRelatedState) {
 | 
			
		||||
| 
						 | 
				
			
			@ -122,61 +173,86 @@ class ImportInspector extends VariableUiElement {
 | 
			
		|||
                return new FixedUiElement("Something went wrong: " + notes["error"]).SetClass("alert")
 | 
			
		||||
            }
 | 
			
		||||
            // 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 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 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)
 | 
			
		||||
            const accordeon = new Accordeon(els)
 | 
			
		||||
            const content = new Combine([
 | 
			
		||||
                new Title(Translations.t.importInspector.title, 1),
 | 
			
		||||
                new SubtleButton(undefined, "Create a new batch of imports",{url:'import_helper.html'}),
 | 
			
		||||
                accordeon])
 | 
			
		||||
            return new LeftIndex(
 | 
			
		||||
                [new TableOfContents(content, {noTopLevel: true, maxDepth: 1}).SetClass("subtle")],
 | 
			
		||||
                content
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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() {
 | 
			
		||||
        const state = new UserRelatedState(undefined)
 | 
			
		||||
        const t = Translations.t.importInspector;
 | 
			
		||||
        super([
 | 
			
		||||
            new Title(t.title, 1),
 | 
			
		||||
            new VariableUiElement(state.osmConnection.userDetails.map(ud => {
 | 
			
		||||
                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);
 | 
			
		||||
            }))
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
new ImportViewerGui().AttachTo("main")
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ import BaseUIElement from "./BaseUIElement";
 | 
			
		|||
import LanguagePicker from "./LanguagePicker";
 | 
			
		||||
import TableOfContents from "./Base/TableOfContents";
 | 
			
		||||
import BackToIndex from "./BigComponents/BackToIndex";
 | 
			
		||||
import LeftIndex from "./Base/LeftIndex";
 | 
			
		||||
 | 
			
		||||
class Snippet extends Toggleable {
 | 
			
		||||
    constructor(translations, ...extraContent: BaseUIElement[]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +40,7 @@ class SnippetContent extends Combine {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ProfessionalGui {
 | 
			
		||||
class ProfessionalGui extends LeftIndex{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +94,6 @@ class ProfessionalGui {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
        const leftContents: BaseUIElement[] = [
 | 
			
		||||
            new BackToIndex().SetClass("block"),
 | 
			
		||||
            new TableOfContents(content, {
 | 
			
		||||
                noTopLevel: true,
 | 
			
		||||
                maxDepth: 2
 | 
			
		||||
| 
						 | 
				
			
			@ -102,10 +102,7 @@ class ProfessionalGui {
 | 
			
		|||
            LanguagePicker.CreateLanguagePicker(Translations.t.professional.title.SupportedLanguages())?.SetClass("mt-4 self-end flex-col"),
 | 
			
		||||
        ].map(el => el?.SetClass("pl-4"))
 | 
			
		||||
        
 | 
			
		||||
        const leftBar = new Combine([
 | 
			
		||||
            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")
 | 
			
		||||
        super(leftContents, content)
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -113,4 +110,4 @@ class ProfessionalGui {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
new FixedUiElement("").AttachTo("decoration-desktop")
 | 
			
		||||
new ProfessionalGui()
 | 
			
		||||
new ProfessionalGui().AttachTo("main")
 | 
			
		||||
							
								
								
									
										7
									
								
								Utils.ts
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								Utils.ts
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -626,6 +626,13 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
 | 
			
		|||
        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 }) {
 | 
			
		||||
        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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.top-4 {
 | 
			
		||||
  top: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.right-1\/3 {
 | 
			
		||||
  right: 33.333333%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.top-4 {
 | 
			
		||||
  top: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.top-0 {
 | 
			
		||||
  top: 0px;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -872,6 +872,14 @@ video {
 | 
			
		|||
  margin-top: 0.25rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ml-4 {
 | 
			
		||||
  margin-left: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mb-24 {
 | 
			
		||||
  margin-bottom: 6rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mr-4 {
 | 
			
		||||
  margin-right: 1rem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -912,10 +920,6 @@ video {
 | 
			
		|||
  margin-left: 0.25rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mb-24 {
 | 
			
		||||
  margin-bottom: 6rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mr-0 {
 | 
			
		||||
  margin-right: 0px;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1182,10 +1186,6 @@ video {
 | 
			
		|||
  flex-grow: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.table-auto {
 | 
			
		||||
  table-layout: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.border-collapse {
 | 
			
		||||
  border-collapse: collapse;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -319,7 +319,10 @@
 | 
			
		|||
        "layerName": "Hier is misschien een {title}",
 | 
			
		||||
        "description": "Deze laag toont kaart-nota's die wijzen op een {title}",
 | 
			
		||||
        "popupTitle": "Mogelijkse {title}",
 | 
			
		||||
        "importButton": "import_button({layerId}, _tags, Hier is een {title}, voeg toe...,./assets/svg/addSmall.svg,,,id)",
 | 
			
		||||
        "importHandled": "<div class='thanks'>Dit punt is afgehandeld. Bedankt om mee te helpen!</div>"
 | 
			
		||||
        "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>",
 | 
			
		||||
 | 
			
		||||
        "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",
 | 
			
		||||
    "gittag": "ts-node scripts/printVersion.ts | bash",
 | 
			
		||||
    "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",
 | 
			
		||||
    "bicycle_rental": "ts-node ./scripts/extractBikeRental.ts"
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ fi
 | 
			
		|||
 | 
			
		||||
echo -e "\n\n   Building non-theme pages"
 | 
			
		||||
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"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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