feat(host-agent): add Console task submission with Host self-submission client

Adds a CSRF-protected task submission form to the local Console Tasks page
This commit is contained in:
2026-07-14 17:02:41 +08:00
parent 99bde4febb
commit fb09924835
9 changed files with 1158 additions and 33 deletions
@@ -1,20 +1,52 @@
{% extends "base.html" %}
{% block body %}
<h1>Tasks</h1>
{% if not tasks %}
<p>No tasks recorded.</p>
{% else %}
<table>
<thead><tr><th>Task ID</th><th>Status</th><th>Device</th><th>Created</th><th>Updated</th></tr></thead>
<tbody>{% for task in tasks %}
<tr>
<td><a href="/tasks/{{ task["id"] }}">{{ task["id"] }}</a></td>
<td>{{ task.get("status") or "" }}</td>
<td>{{ task.get("device_id") or "" }}</td>
<td>{{ task.get("created_at") or "" }}</td>
<td>{{ task.get("updated_at") or "" }}</td>
</tr>
{% endfor %}</tbody>
</table>
{% endif %}
{% endblock %}
<section id="task-submission">
<h2>Submit task to current Host</h2>
{% if submission_available %}
<form method="post" action="/tasks/submit">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<p>
<label for="goal">Goal</label><br>
<textarea id="goal" name="goal" rows="4" cols="60" required>{{ goal_value }}</textarea>
</p>
<p>
<label for="device_id">Target device</label><br>
<select id="device_id" name="device_id">
<option value="{{ automatic_device_value }}"{% if selected_device == automatic_device_value %} selected{% endif %}>Automatic (let Host choose an eligible device)</option>
{% for device in devices %}<option value="{{ device.id }}"{% if selected_device == device.id %} selected{% endif %}>{{ device.label }}</option>{% endfor %}
</select>
</p>
{% if submission_error %}<p class="error" id="submission-error">{{ submission_error }}</p>{% endif %}
{% if submission_unknown %}<p class="error" id="submission-unknown">Submission outcome is unknown. The task may have been queued. Check the Cloud console before submitting again.</p>{% endif %}
{% if submission_notice %}<p class="notice" id="submission-notice">{{ submission_notice }}</p>{% endif %}
<p><button type="submit">Submit task</button></p>
</form>
{% else %}
<p class="error" id="submission-unavailable">Host submission client is not available yet. Wait for Host enrollment to complete, then refresh.</p>
{% endif %}
</section>
<section id="local-tasks">
<h2>Local Runtime tasks</h2>
{% if metadata_store_missing %}
<p class="error">Task metadata store is not configured.</p>
{% elif not tasks %}
<p>No tasks recorded.</p>
{% else %}
<table>
<thead><tr><th>Task ID</th><th>Status</th><th>Device</th><th>Created</th><th>Updated</th></tr></thead>
<tbody>{% for task in tasks %}
<tr>
<td><a href="/tasks/{{ task["id"] }}">{{ task["id"] }}</a></td>
<td>{{ task.get("status") or "" }}</td>
<td>{{ task.get("device_id") or "" }}</td>
<td>{{ task.get("created_at") or "" }}</td>
<td>{{ task.get("updated_at") or "" }}</td>
</tr>
{% endfor %}</tbody>
</table>
{% endif %}
</section>
{% endblock %}