Skip to content

Commit

Permalink
Finish import_viewer gui
Browse files Browse the repository at this point in the history
  • Loading branch information
pietervdvn committed Jan 24, 2022
1 parent cd09efc commit 33ef83c
Show file tree
Hide file tree
Showing 14 changed files with 199 additions and 104 deletions.
5 changes: 1 addition & 4 deletions Logic/Tags/TagUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
25 changes: 25 additions & 0 deletions UI/Base/LeftIndex.ts
Original file line number Diff line number Diff line change
@@ -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")
}

}
2 changes: 1 addition & 1 deletion UI/Base/Toggleable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion UI/BigComponents/BackToIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
)
}
Expand Down
18 changes: 10 additions & 8 deletions UI/ImportFlow/CreateNotes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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"))
Expand Down Expand Up @@ -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 => {
Expand All @@ -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");
Expand Down
26 changes: 9 additions & 17 deletions UI/ImportFlow/ImportHelperGui.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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
Expand Down Expand Up @@ -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)

}

Expand Down
168 changes: 122 additions & 46 deletions UI/ImportFlow/ImportInspector.ts → UI/ImportFlow/ImportViewerGui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,25 @@ 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";
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,
Expand All @@ -31,9 +36,15 @@ interface NoteProperties {
}[]
}

class MassAction extends Combine {

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")

Expand All @@ -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"
}
])

Expand Down Expand Up @@ -96,14 +117,44 @@ 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
)
]);
}

}


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) {
Expand All @@ -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 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 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 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")
Loading

0 comments on commit 33ef83c

Please sign in to comment.