diff --git a/projects/tentacles/src/python/tentacles/blueprints/job_ui.py b/projects/tentacles/src/python/tentacles/blueprints/job_ui.py index cf282ca..7cd9f85 100644 --- a/projects/tentacles/src/python/tentacles/blueprints/job_ui.py +++ b/projects/tentacles/src/python/tentacles/blueprints/job_ui.py @@ -41,7 +41,7 @@ def manipulate_jobs(): case "cancel": ctx.db.cancel_job(ctx.uid, int(request.form.get("job_id"))) - flash("Cancellation reqiested", category="info") + flash("Cancellation reqested", category="info") case "delete": ctx.db.delete_job(ctx.uid, int(request.form.get("job_id"))) diff --git a/projects/tentacles/src/python/tentacles/schema.sql b/projects/tentacles/src/python/tentacles/schema.sql index 29f6da1..c6c8e9c 100644 --- a/projects/tentacles/src/python/tentacles/schema.sql +++ b/projects/tentacles/src/python/tentacles/schema.sql @@ -49,11 +49,12 @@ CREATE TABLE IF NOT EXISTS printer_statuses ( , UNIQUE(name) ); -INSERT OR IGNORE INTO printer_statuses (id, name) values (-1, 'error'); -INSERT OR IGNORE INTO printer_statuses (id, name) values (0, 'disconnected'); -INSERT OR IGNORE INTO printer_statuses (id, name) values (1, 'connected'); -INSERT OR IGNORE INTO printer_statuses (id, name) values (2, 'idle'); -INSERT OR IGNORE INTO printer_statuses (id, name) values (3, 'running'); +INSERT OR IGNORE INTO printer_statuses (id, name) VALUES (-1, 'error'); +INSERT OR IGNORE INTO printer_statuses (id, name) VALUES (0, 'disconnected'); +INSERT OR IGNORE INTO printer_statuses (id, name) VALUES (2, 'connecting'); +INSERT OR IGNORE INTO printer_statuses (id, name) VALUES (2, 'connected'); +INSERT OR IGNORE INTO printer_statuses (id, name) VALUES (3, 'idle'); +INSERT OR IGNORE INTO printer_statuses (id, name) VALUES (4, 'running'); CREATE TABLE IF NOT EXISTS printers ( id INTEGER PRIMARY KEY AUTOINCREMENT diff --git a/projects/tentacles/src/python/tentacles/static/css/style.scss b/projects/tentacles/src/python/tentacles/static/css/style.scss index aac7309..a48c0ab 100644 --- a/projects/tentacles/src/python/tentacles/static/css/style.scss +++ b/projects/tentacles/src/python/tentacles/static/css/style.scss @@ -8,6 +8,7 @@ @import "tirefire/timers"; @import "tirefire/nav"; @import "tirefire/dots"; +@import "tirefire/tooltips"; .controls a, .controls form { @@ -18,11 +19,16 @@ .printer, .key, .job { - margin-top: 4px; + margin-top: 4px; } -.details { - overflow: hidden; +.file .details, +.printer .details, +.key .details, +.job .details { + div { + margin-right: 10px; + } } // Hide the header name if we're on a mobile device @@ -31,3 +37,7 @@ display: none; } } + +label { + margin-right: 10px; +} diff --git a/projects/tentacles/src/python/tentacles/static/css/tirefire/_dots.scss b/projects/tentacles/src/python/tentacles/static/css/tirefire/_dots.scss index b855021..74b82be 100644 --- a/projects/tentacles/src/python/tentacles/static/css/tirefire/_dots.scss +++ b/projects/tentacles/src/python/tentacles/static/css/tirefire/_dots.scss @@ -13,6 +13,11 @@ border-radius: 50%; } +.dot::before, +.dot::after { + animation: disabled; +} + .dot.success { background-color: $secondary_green; } @@ -25,8 +30,16 @@ background-color: $secondary_green; } -.dot.error, +.dot.cancelling { + background-color: $yellow; +} + + .dot.cancelled { + background-color: $yellow; +} + +.dot.failed { background-color: $red; } diff --git a/projects/tentacles/src/python/tentacles/store.py b/projects/tentacles/src/python/tentacles/store.py index 9ce7b59..d062ae2 100644 --- a/projects/tentacles/src/python/tentacles/store.py +++ b/projects/tentacles/src/python/tentacles/store.py @@ -272,7 +272,8 @@ class Store(object): SELECT p.id FROM printers p LEFT JOIN (SELECT id, printer_id FROM jobs WHERE finished_at IS NULL) j ON p.id = j.printer_id - WHERE j.id IS NULL + INNER JOIN printer_statuses s ON p.status_id = s.id + WHERE j.id IS NULL AND s.name = 'idle' """ ).fetchall() @@ -370,6 +371,19 @@ class Store(object): [], ).fetchall() + @requires_conn + def list_job_history(self, uid: Optional[int] = None): + """Enumerate jobs in priority order. Note: ignores completed jobs.""" + cond = f"user_id = {uid}" if uid else "TRUE" + return self._conn.execute( + f""" + SELECT * FROM jobs + WHERE finished_at IS NOT NULL AND {cond} + ORDER BY datetime(finished_at) DESC + """, + [], + ).fetchall() + @requires_conn def list_mapped_jobs(self): """Scheduler detail. List mapped but not started jobs.""" @@ -406,14 +420,12 @@ class Store(object): @requires_conn def list_cancelled_jobs(self): - """Scheduler detail. List jobs which have been cancelled but are still 'live'.""" + """Scheduler detail. List jobs which have been cancelled but are still 'live' (not finished).""" return self._conn.execute( """ SELECT * FROM jobs - WHERE started_at IS NOT NULL - AND printer_id IS NOT NULL - AND finished_at IS NULL + WHERE finished_at IS NULL AND cancelled_at IS NOT NULL """, [], diff --git a/projects/tentacles/src/python/tentacles/templates/jobs_history.html.j2 b/projects/tentacles/src/python/tentacles/templates/jobs_history.html.j2 index b745a7b..37c2dac 100644 --- a/projects/tentacles/src/python/tentacles/templates/jobs_history.html.j2 +++ b/projects/tentacles/src/python/tentacles/templates/jobs_history.html.j2 @@ -1,18 +1,29 @@ {% import "macros.html.j2" as macros %}