Implemented Task Manager

This commit is contained in:
2026-04-13 14:25:53 -05:00
parent 1aadf40164
commit d2604b5c10
9 changed files with 234 additions and 6 deletions

62
app.py
View File

@@ -28,6 +28,14 @@ with open("./config.json", "r", encoding="utf-8") as file:
db = mongo.db
def partition(predicate, iterable):
trues = []
falses = []
for item in iterable:
(trues if predicate(item) else falses).append(item)
return falses, trues
@app.context_processor
def inject_data():
ddata = db.domains.find_one({"id": request.endpoint})
@@ -190,3 +198,57 @@ def database_edit(collection, oid):
name=name,
document=document,
)
@app.route("/tasks", methods=["GET", "POST"])
def tasks():
print(request.form, request.method)
if request.method == "POST":
act = request.form.get("action", "save")
match act:
case "save":
oid = request.form.get("oid")
if oid:
db.tasks.update_one(
{"_id": ObjectId(oid)},
{
"$set": {
"id": request.form.get("tid") or "000",
"txt": request.form.get("content", ""),
"pre": request.form.get("pre", "").split(),
}
},
)
else:
db.tasks.insert_one(
{
"id": request.form.get("tid") or "000",
"txt": request.form.get("content", ""),
"pre": request.form.get("pre", "").split(),
"done": False,
}
)
case "delete":
oid = request.form.get("oid")
db.tasks.delete_one({"_id": ObjectId(oid)})
case "mark":
oid = request.form.get("oid")
db.tasks.update_one(
{"_id": ObjectId(oid)},
{"$set": {"done": request.form.get("done") == "False"}},
)
tasks = sorted(db.tasks.find(), key=lambda task: task["id"])
other_tasks, complete_tasks = partition(lambda task: task["done"], tasks)
active_tasks, blocked_tasks = partition(
lambda task: any(
any(not ot["done"] for ot in tasks if ot["id"] == pre)
for pre in task["pre"]
),
other_tasks,
)
return render_template(
"tasks.html",
active_tasks=active_tasks,
blocked_tasks=blocked_tasks,
complete_tasks=complete_tasks,
)

View File

@@ -8,7 +8,8 @@ hr {
width: 100%;
}
form {
#db-form,
#edit-form {
display: flex;
flex-direction: row;
gap: 0.25em;

View File

@@ -112,6 +112,15 @@ hr#sectorbar {
ul {
margin: 0.5em 0;
}
li {
color: var(--color);
}
a {
color: var(--color);
text-decoration: none;
}
}
#other>div {

View File

@@ -86,6 +86,10 @@ hr {
border-bottom: 1px dashed var(--color);
}
label {
color: var(--color);
}
header {
display: flex;
flex-direction: row;

39
static/tasks.css Normal file
View File

@@ -0,0 +1,39 @@
ul {
margin: 1em;
padding: 0;
display: flex;
flex-direction: column;
gap: 0.5em;
}
li {
list-style: none;
margin: 0;
padding: 0.5em;
background-color: var(--color-bg2);
border: 1px solid var(--color);
span {
flex-direction: row;
gap: 0.5em;
}
}
.task-value,
.task-value-editor {
flex-grow: 1;
}
output.task-value {
border: none;
text-decoration: 1px dotted underline var(--color);
}
.view-box {
display: flex;
}
.edit-box {
display: none;
}

46
static/tasks.js Normal file
View File

@@ -0,0 +1,46 @@
function getFirst(item, className) {
return item.getElementsByClassName(className)[0]
}
for (elem of document.getElementsByTagName("li")) {
var editBtn = getFirst(elem, "task-value")
if (editBtn) {
editBtn.onclick = (event) => {
event.preventDefault(true);
var item = event.target.parentNode.parentNode;
getFirst(item, "view-box").style.display = "none";
getFirst(item, "edit-box").style.display = "flex";
}
}
var cancelBtn = getFirst(elem, "btn-cancel")
if (cancelBtn) {
cancelBtn.onclick = (event) => {
event.preventDefault(true);
var item = event.target.parentNode.parentNode;
getFirst(item, "edit-box").style.display = "none";
getFirst(item, "view-box").style.display = "flex";
}
}
var markBtn = getFirst(elem, "task-id")
if (markBtn) {
markBtn.onclick = (event) => {
event.target.type = "submit";
event.target.click();
}
}
}
var newBtn = document.getElementById("btn-new")
newBtn.onclick = (event) => {
event.preventDefault(true);
var item = event.target.parentNode.parentNode;
getFirst(item, "view-box").style.display = "none";
getFirst(item, "edit-box").style.display = "flex";
}
var cancelBtn = document.getElementById("btn-cancel")
cancelBtn.onclick = (event) => {
event.preventDefault(true);
var item = event.target.parentNode.parentNode;
getFirst(item, "edit-box").style.display = "none";
getFirst(item, "view-box").style.display = "flex";
}

View File

@@ -6,7 +6,7 @@
{% block content %}
<main>
<form method="post">
<form method="post" id="db-form">
<div>
<label for="collection">Collection:</label>
<input id="collection" name="collection" list="cnames">

View File

@@ -68,11 +68,11 @@
</div>
<div id="news">
<h2>News</h2>
<h3>Test1</h3>
<p>Foo, Bar, Baz</p>
<h3>Error: Not Implemented</h3>
<p>Unable to connect to Index Feed.</p>
<hr>
<h3>Test2</h3>
<p>Quux, Quuux, Quuuux</p>
<h3>Example Text</h3>
<p>Foo, Bar, Baz, Quux</p>
</div>
</div>
</div>

67
templates/tasks.html Normal file
View File

@@ -0,0 +1,67 @@
{% extends "base.html" %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='tasks.css') }}">
<script src="{{ url_for('static', filename='tasks.js') }}" defer></script>
{% endblock %}
{% macro make_task(task) %}
<li>
<form method="post">
<span class="view-box">
<button class="task-id" name="action" value="mark" type="button">{{ task["id"] }}</button>
<output class="task-value">{{ task["txt"] }}</output>
{% for pre in task["pre"] %}
<output class="task-pre">{{ pre }}</output>
{% endfor %}
</span>
<span class="edit-box">
<input class="task-id-editor" name="tid" size="3" placeholder="000" value="{{ task['id'] }}">
<input class="task-value-editor" name="content" value="{{ task['txt'] }}">
<input class="task-pre-editor" name="pre" value="{{ ','.join(task['pre']) }}">
<button class="btn-save" name="action" value="save" type="submit">Save</button>
<button class="btn-cancel" type="button">Cancel</button>
<button class="btn-delete" name="action" value="delete" type="submit">Delete</button>
</span>
<input type="hidden" name="oid" value="{{ task['_id'] }}">
<input type="hidden" name="done" value="{{ task['done'] }}">
</form>
</li>
{% endmacro %}
{% block content %}
<main>
<h2>Active Tasks:</h2>
<ul>
{% for task in active_tasks %}
{{ make_task(task) }}
{% endfor %}
<li>
<form method="post">
<span class="view-box">
<button id="btn-new" type="button">New Task</button>
</span>
<span class="edit-box">
<input class="task-id-editor" name="tid" size="3" placeholder="000">
<input class="task-value-editor" name="content">
<input class="task-pre-editor" name="pre">
<button id="btn-make" name="action" value="save" type="submit">Create Task</button>
<button id="btn-cancel" type="button">Cancel</button>
</span>
</form>
</li>
</ul>
<h2>Blocked Tasks:</h2>
<ul>
{% for task in blocked_tasks %}
{{ make_task(task) }}
{% endfor %}
</ul>
<h2>Complete Tasks:</h2>
<ul>
{% for task in complete_tasks %}
{{ make_task(task) }}
{% endfor %}
</ul>
</main>
{% endblock %}