| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <pstm-uri>/tasks</pstm-uri>
- <pstm-template>main</pstm-template>
- <script>
- // The task queue. Plan 12: the filters (status / project / goal)
- // run CLIENT-SIDE — the Statum entrypoint fetch never carries the
- // page's own query string to the server, so selects filter the
- // rendered rows directly (window.taskFilters + taskRowVisible)
- // and survive re-renders; the create form gains the mode select
- // (with descriptions) and the auto-enqueue-after dropdown (the
- // global human-task list; goal tasks are the goal agent's to
- // sequence).
- if (window.statum) {
- (function () {
- 'use strict';
- window.taskFilters = window.taskFilters || {};
- window.taskRowVisible = function (row) {
- var filters = window.taskFilters || {};
- if (filters.status && filters.status !== 'all'
- && row.status !== filters.status) {
- return false;
- }
- if (filters.project && filters.project > 0
- && String(row.project_id) !== String(filters.project)) {
- return false;
- }
- if (filters.goal) {
- if (filters.goal === 'standalone' && row.goal_id > 0) {
- return false;
- }
- if (filters.goal !== 'standalone'
- && String(row.goal_id) !== String(filters.goal)) {
- return false;
- }
- }
- return true;
- };
- window.setTaskFilter = function (name, value) {
- window.taskFilters[name] = value;
- var tasks = statum.read('tasks');
- if (tasks && tasks.refresh) {
- statum.act(tasks.refresh).catch(function () { });
- } else {
- // No sealed refresh on this build: force a render
- // cycle through the pulse listener if present.
- document.body.setAttribute('data-filter-bump', String(Date.now()));
- }
- };
- })();
- }
- </script>
- </head>
- <body>
- <div class="page">
- <h1>Tasks</h1>
- <form class="inline" onsubmit="return false">
- <label for="filter-status">Status</label>
- <select id="filter-status" onchange="window.setTaskFilter('status', this.value)">
- <option value="all">all</option>
- <option value="draft">draft</option>
- <option value="queued">queued</option>
- <option value="assigned">assigned</option>
- <option value="working">working</option>
- <option value="blocked">blocked</option>
- <option value="suspended">suspended</option>
- <option value="done">done</option>
- <option value="failed">failed</option>
- </select>
- <label for="filter-project">Project</label>
- <select id="filter-project" onchange="window.setTaskFilter('project', this.value)">
- <option value="0">all</option>
- <option stm-for-project-in="tasks.projects" stm-attribute.value="project.id"
- stm-text="project.name">project</option>
- </select>
- <label for="filter-goal">Goal</label>
- <select id="filter-goal" onchange="window.setTaskFilter('goal', this.value)">
- <option value="all">all</option>
- <option value="standalone">standalone only</option>
- <option stm-for-goal-in="tasks.goal_options" stm-attribute.value="goal.id"
- stm-text="goal.title">goal</option>
- </select>
- <span class="muted">— filters apply instantly</span>
- </form>
- <details class="history-expander">
- <summary><strong>New task</strong></summary>
- <form stm-action="tasks.create">
- <div class="form-row"><label for="task-project">Project</label>
- <select id="task-project" name="project_id" required>
- <option stm-for-project-in="tasks.projects" stm-attribute.value="project.id"
- stm-text="project.name">project</option>
- </select></div>
- <div class="form-row"><label for="task-title">Title</label>
- <input type="text" id="task-title" name="title" required></div>
- <div class="form-row"><label for="task-mode">Mode</label>
- <select id="task-mode" name="mode">
- <option value="implement" selected>implement — build the change on a task branch</option>
- <option value="investigate">investigate — explore and report, no code changes</option>
- <option value="review">review — read and critique existing work</option>
- <option value="test">test — write and run tests</option>
- </select></div>
- <div class="form-row"><label for="task-description">Mandate</label>
- <textarea id="task-description" name="description" rows="4"
- placeholder="What the agent must accomplish (the mandate)"></textarea></div>
- <div class="form-row"><label for="task-priority">Priority</label>
- <select id="task-priority" name="priority">
- <option value="1">1 — highest</option>
- <option value="2">2</option>
- <option value="3">3</option>
- <option value="4">4</option>
- <option value="5" selected>5 — default</option>
- <option value="6">6</option>
- <option value="7">7</option>
- <option value="8">8</option>
- <option value="9">9 — lowest</option>
- </select></div>
- <div class="form-row"><label for="task-enqueue-after">Auto-enqueue after
- <span class="muted">(optional — enqueues itself when the predecessor is done)</span></label>
- <select id="task-enqueue-after" name="enqueue_after_task_id">
- <option value="">none</option>
- <option stm-for-option-in="tasks.enqueue_after_options"
- stm-attribute.value="option.id" stm-text="option.name">task</option>
- </select></div>
- <div class="form-row" stm-if="tasks.capability_options.length > 0">
- <label for="task-capabilities">Capabilities
- <span class="muted">(the saddle fleet must carry them until assigned)</span></label>
- <select id="task-capabilities" name="required_capabilities" multiple
- size="3">
- <option stm-for-capability-in="tasks.capability_options"
- stm-attribute.value="capability.id"
- stm-text="capability.name">cap</option>
- </select></div>
- <button type="submit" class="primary">Create task</button>
- </form>
- </details>
- <table>
- <thead>
- <tr><th>#</th><th>Title</th><th>Status</th><th>Mode</th><th>Goal</th>
- <th>Priority</th><th>Project</th><th>Capabilities</th></tr>
- </thead>
- <tbody>
- <tr stm-for-task-in="tasks.tasks" stm-if="window.taskRowVisible(task)">
- <td stm-text="task.id">id</td>
- <td>
- <a stm-attribute.href="'/tasks/' + task.id" stm-text="task.title">title</a>
- <span class="badge badge-yeehaw" stm-if="task.has_yeehaw"
- title="The agent celebrated this task (saddle yeehaw)">🤠</span>
- </td>
- <td><span stm-attribute.class="'badge badge-' + task.status" stm-text="task.display">status</span></td>
- <td><span stm-attribute.class="'badge badge-mode-' + task.mode" stm-text="task.mode">mode</span></td>
- <td stm-if="task.goal_id > 0">
- <a stm-attribute.href="'/goals/' + task.goal_id" stm-text="task.goal_title">goal</a>
- <span class="muted" stm-if="task.creator == 'goal'">(agent)</span>
- </td>
- <td stm-if="task.goal_id == 0" class="muted">—</td>
- <td stm-text="task.priority">5</td>
- <td stm-text="task.project_name">project</td>
- <td><span stm-if="task.capabilities.length > 0"
- stm-text="task.capabilities.join(', ')">caps</span>
- <span class="muted" stm-if="task.capabilities.length == 0">—</span></td>
- </tr>
- <tr stm-if="tasks.tasks.length == 0"><td colspan="8" class="muted">No tasks.</td></tr>
- </tbody>
- </table>
- </div>
- </body>
- </html>
|