X-Git-Url: http://git.scottworley.com/vopamoi/blobdiff_plain/32808c9a5b8154746bf98339e58ed827c399a9d3..68d693148efba8e2ff62bee1b5780d47f4920029:/vopamoi.ts diff --git a/vopamoi.ts b/vopamoi.ts index a114959..f13e579 100644 --- a/vopamoi.ts +++ b/vopamoi.ts @@ -67,7 +67,7 @@ const Model = { return tag; } } - task.appendChild(tag); + task.insertBefore(tag, task.getElementsByClassName("desc")[0]!); return tag; }, @@ -76,7 +76,7 @@ const Model = { if (!target) return null; if (target.hasAttribute("data-description")) { // Oh no: An edit has arrived from a replica while a local edit is in progress. - const input = target.firstChild as HTMLInputElement; + const input = target.getElementsByTagName("input")[0]!; if ( input.value === target.getAttribute("data-description") && input.selectionStart === input.value.length && @@ -120,6 +120,17 @@ const Model = { } }, + insertInPriorityOrder: function (task: Element, dest: Element) { + const priority = this.getPriority(task); + for (const t of dest.children) { + if (t !== task && this.getPriority(t) < priority) { + dest.insertBefore(task, t); + return; + } + } + dest.appendChild(task); + }, + removeTag: function (createTimestamp: string, tagName: string) { const task = this.getTask(createTimestamp); if (!task) return null; @@ -133,13 +144,7 @@ const Model = { const target = this.getTask(createTimestamp); if (!target) return null; target.setAttribute("data-priority", `${priority}`); - for (const task of document.getElementsByClassName("task")) { - if (task !== target && this.getPriority(task) < priority) { - task.parentElement!.insertBefore(target, task); - return target; - } - } - document.getElementById("tasks")!.appendChild(target); + this.insertInPriorityOrder(target, target.parentElement!); return target; }, @@ -276,6 +281,7 @@ function BrowserUI() { todo: "White", waiting: "MediumOrchid", }; + var currentTagView: string | null = null; var currentViewState = "todo"; var taskFocusedBeforeJumpingToInput: HTMLElement | null = null; var lastTagNameEntered = ""; @@ -291,6 +297,9 @@ function BrowserUI() { this.firstVisibleTask()?.focus(); } input.value = ""; + if (currentTagView) { + ui.addTag(task.getAttribute("data-created")!, currentTagView); + } if (event.getModifierState("Control")) { this.makeBottomPriority(task); } @@ -464,8 +473,13 @@ function BrowserUI() { }, resetTagView: function () { - for (const task of document.getElementsByClassName("task")) { + currentTagView = null; + const taskList = document.getElementById("tasks")!; + for (const task of Array.from(document.getElementsByClassName("task"))) { task.classList.remove("hide"); + if (task.parentElement !== taskList) { + Model.insertInPriorityOrder(task, taskList); + } } }, @@ -508,17 +522,51 @@ function BrowserUI() { return ui.setState(createTimestamp, newState, oldState); }, - setTagView: function () { - const target = this.currentTag(); - if (!target) return; - const tag = target.textContent!; + setTagView: function (tag: string | null = null) { + if (tag === null) { + const target = this.currentTag(); + if (!target) return; + tag = target.textContent!; + } + + if (currentTagView !== null) { + this.resetTagView(); + } + + const tasksWithTag = new Map(); for (const task of document.getElementsByClassName("task")) { + if (Model.hasTag(task, tag)) { + tasksWithTag.set(task.getElementsByClassName("desc")[0].textContent, [Model.getPriority(task), task]); + } + } + + function highestPrioritySuperTask(t: Element) { + var maxPriority = -1; + var superTask = null; + for (const child of t.getElementsByClassName("tag")) { + const e = tasksWithTag.get(child.textContent); + if (e !== undefined && e[0] > maxPriority) { + maxPriority = e[0]; + superTask = e[1]; + } + } + return superTask; + } + + for (const task of Array.from(document.getElementsByClassName("task"))) { if (Model.hasTag(task, tag)) { task.classList.remove("hide"); } else { - task.classList.add("hide"); + const superTask = highestPrioritySuperTask(task); + if (superTask !== null) { + Model.insertInPriorityOrder(task, superTask); + } else { + task.classList.add("hide"); + } } } + + currentTagView = tag; }, setView: function (state: string) { @@ -537,6 +585,19 @@ function BrowserUI() { } }, + setUntaggedView: function () { + if (currentTagView !== null) { + this.resetTagView(); + } + for (const task of document.getElementsByClassName("task")) { + if (task.getElementsByClassName("tag").length === 0) { + task.classList.remove("hide"); + } else { + task.classList.add("hide"); + } + } + }, + undo: function () { const ret = ui.undo(); if (ret && ret instanceof HTMLElement) ret.focus(); @@ -613,10 +674,13 @@ function handleKey(event: any) { if (event.key == "a") return browserUI.setView("all"); if (event.key == "c") return browserUI.setView("cancelled"); if (event.key == "d") return browserUI.setView("done"); + if (event.key == "i") return browserUI.setUntaggedView(); + if (event.key == "p") return browserUI.setTagView("Project"); if (event.key == "q") return browserUI.setView("todo"); if (event.key == "s") return (inputState = InputState.VS); if (event.key == "T") return browserUI.resetTagView(); if (event.key == "t") return browserUI.setTagView(); + if (event.key == "u") return browserUI.setUntaggedView(); if (event.key == "v") return browserUI.resetView(); if (event.key == "w") return browserUI.setView("waiting"); if (event.key == "x") return browserUI.setView("deleted");