Files
FabledSteward/steward/templates/settings/_ansible_sources.html
T
bvandeusenandClaude Opus 5.5 5ec930bf76
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 53s
CI / unit (push) Successful in 1m14s
CI / publish (push) Successful in 1m10s
feat(ui): Disk, Traefik, UniFi and Settings say things plainly (#5212)
#5212 "Plain labels: no raw ids, scopes, metric keys or unexplained jargon",
batch 3:

- Disk page: each tile says what it holds. "Writable layers" becomes
  "Container files" and Build cache says it is safe to clear. Shared is
  "Shared with other images" with a tooltip, and "dangling" is gone.
  Untagged images show by id instead of "<none>", a capped list says
  "The 50 largest of N images", and each host shows "as of" its report.
- Traefik: an expired certificate reads "expired 12 days ago", not "-12
  days" (cert_left). The Traffic empty state knows whether the access log
  is on: off points to Settings → Plugins → Traefik; on says to check the
  mounted log path.
- Moments use |ago with an exact UTC tooltip: UniFi last seen, alarms,
  events, speed test and DPI; AI token last used.
- Settings: the Auth tab is "Authentication" like its breadcrumb, plugin
  fields read "Metrics URL" not metrics_url (field_label), a source's pull
  interval is "every 1h", and the last report time drops the ISO "T".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:29:30 -04:00

222 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{# settings/_ansible_sources.html — HTMX partial for Ansible source management #}
<div id="ansible-sources">
{% if sources %}
<div style="display:grid;gap:0.75rem;margin-bottom:0.75rem;">
{% for src in sources %}
{% set idx = loop.index0 %}
<div class="card" style="padding:0;overflow:visible;">
{# ── View row ──────────────────────────────────────────────────────── #}
<div id="ansible-source-view-{{ idx }}"
style="display:flex;align-items:center;gap:0.75rem;padding:0.85rem 1rem;">
<span style="flex-shrink:0;font-size:0.7rem;font-weight:500;text-transform:uppercase;
letter-spacing:0.06em;padding:0.15em 0.5em;border-radius:3px;
background:{% if src.type == 'git' %}var(--fs-accent-faint){% else %}var(--bg-elevated){% endif %};
color:{% if src.type == 'git' %}var(--accent){% else %}var(--text-muted){% endif %};">
{{ src.type }}
</span>
<div style="flex:1;min-width:0;">
<div style="font-weight:500;font-size:0.9rem;">{{ src.name }}</div>
<div style="font-size:0.78rem;color:var(--text-muted);margin-top:0.1rem;
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
{% if src.type == 'git' %}
{{ src.url or '(no URL)' }}
<span style="color:var(--text-dim);margin-left:0.5rem;">branch: {{ src.branch or 'main' }}</span>
{% if src.pull_interval_seconds %}<span style="color:var(--text-dim);margin-left:0.5rem;">· pulled every {{ src.pull_interval_seconds|duration }}</span>{% endif %}
{% else %}
{{ src.path or '(no path)' }}
{% endif %}
</div>
</div>
<div style="display:flex;gap:0.4rem;flex-shrink:0;align-items:center;">
<a href="/ansible/browse" class="btn btn-ghost btn-sm" style="font-size:0.78rem;">Browse</a>
{% if src.type == 'git' %}
<span id="ansible-sync-status-{{ idx }}"></span>
<button class="btn btn-ghost btn-sm" style="font-size:0.78rem;"
hx-post="/settings/ansible/sources/{{ idx }}/sync"
hx-target="#ansible-sync-status-{{ idx }}"
hx-swap="innerHTML"
hx-indicator="#ansible-sync-status-{{ idx }}">Sync</button>
{% endif %}
<button class="btn btn-ghost btn-sm" style="font-size:0.78rem;"
onclick="toggleAnsibleEdit({{ idx|int }})">Edit</button>
<button class="btn btn-danger btn-sm" style="font-size:0.78rem;"
hx-post="/settings/ansible/sources/{{ idx }}/remove"
hx-target="#ansible-sources"
hx-swap="outerHTML"
hx-confirm="Remove source '{{ src.name }}'?">×</button>
</div>
</div>
{# ── Inline edit form ──────────────────────────────────────────────── #}
<div id="ansible-source-edit-{{ idx }}" style="display:none;
border-top:1px solid var(--border);padding:1rem;">
<form hx-post="/settings/ansible/sources/{{ idx }}/save"
hx-target="#ansible-sources"
hx-swap="outerHTML">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:0.6rem;">
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">Name</label>
<input type="text" name="name" value="{{ src.name }}" required>
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">Type</label>
<select name="type" id="ansible-edit-type-{{ idx }}"
onchange="updateAnsibleEditFields({{ idx|int }})">
<option value="local" {% if src.type == 'local' %}selected{% endif %}>local</option>
<option value="git" {% if src.type == 'git' %}selected{% endif %}>git</option>
</select>
</div>
<div id="ansible-edit-git-fields-{{ idx }}"
style="display:{% if src.type == 'git' %}contents{% else %}none{% endif %};
grid-column:1/-1;display:{% if src.type == 'git' %}grid{% else %}none{% endif %};
grid-template-columns:1fr 1fr;gap:0.6rem;grid-column:1/-1;">
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">URL</label>
<input type="url" name="url" value="{{ src.url or '' }}" placeholder="https://github.com/org/repo.git">
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">Branch</label>
<input type="text" name="branch" value="{{ src.branch or 'main' }}" placeholder="main">
</div>
<div class="form-group" style="margin:0;grid-column:1/-1;">
<label style="font-size:0.8rem;">Pull interval (seconds)</label>
<input type="number" name="pull_interval_seconds" value="{{ src.pull_interval_seconds or 3600 }}" min="60">
</div>
<div class="form-group" style="margin:0;grid-column:1/-1;">
<label style="font-size:0.8rem;">
HTTP Token
<span style="color:var(--text-muted);font-weight:normal;">(optional — Gitea PAT for private repos)</span>
</label>
<input type="password" name="http_token"
placeholder="{% if src.http_token %}token saved — enter new to replace{% endif %}"
autocomplete="new-password">
</div>
</div>
<div id="ansible-edit-local-fields-{{ idx }}"
style="display:{% if src.type == 'local' %}grid{% else %}none{% endif %};
grid-template-columns:1fr;gap:0.6rem;grid-column:1/-1;">
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">Path</label>
<input type="text" name="path" value="{{ src.path or '' }}" placeholder="/opt/playbooks">
</div>
</div>
</div>
<div style="display:flex;gap:0.5rem;margin-top:0.75rem;">
<button type="submit" class="btn btn-sm">Save</button>
<button type="button" class="btn btn-ghost btn-sm"
onclick="toggleAnsibleEdit({{ idx|int }})">Cancel</button>
</div>
</form>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="card" style="color:var(--text-muted);font-size:0.9rem;text-align:center;padding:2rem;">
No sources mustered. Add one below.
</div>
{% endif %}
{# ── Add source ────────────────────────────────────────────────────────── #}
<details class="card" style="padding:0;overflow:hidden;">
<summary style="display:flex;align-items:center;gap:0.75rem;padding:0.85rem 1rem;
cursor:pointer;list-style:none;user-select:none;">
<span style="flex:1;font-weight:500;font-size:0.875rem;color:var(--text);">Add Source</span>
<span class="btn btn-sm" style="pointer-events:none;">New ▾</span>
</summary>
<form hx-post="/settings/ansible/sources/add"
hx-target="#ansible-sources"
hx-swap="outerHTML"
style="padding:1rem;padding-top:0;border-top:1px solid var(--border);">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:0.6rem;padding-top:1rem;">
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">Name</label>
<input type="text" name="name" placeholder="my-playbooks" required>
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">Type</label>
<select name="type" id="ansible-add-type"
onchange="updateAnsibleAddFields()">
<option value="local">local</option>
<option value="git">git</option>
</select>
</div>
<div id="ansible-add-git-fields"
style="display:none;grid-template-columns:1fr 1fr;gap:0.6rem;grid-column:1/-1;">
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">URL</label>
<input type="url" name="url" placeholder="https://github.com/org/repo.git">
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">Branch</label>
<input type="text" name="branch" placeholder="main" value="main">
</div>
<div class="form-group" style="margin:0;grid-column:1/-1;">
<label style="font-size:0.8rem;">Pull interval (seconds)</label>
<input type="number" name="pull_interval_seconds" value="3600" min="60">
</div>
<div class="form-group" style="margin:0;grid-column:1/-1;">
<label style="font-size:0.8rem;">HTTP Token
<span style="color:var(--text-muted);font-weight:normal;">(optional)</span>
</label>
<input type="password" name="http_token" autocomplete="new-password">
</div>
</div>
<div id="ansible-add-local-fields"
style="display:grid;grid-template-columns:1fr;gap:0.6rem;grid-column:1/-1;">
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">Path</label>
<input type="text" name="path" placeholder="/opt/playbooks">
</div>
</div>
</div>
<button type="submit" class="btn btn-sm" style="margin-top:0.75rem;width:100%;">
Add Source
</button>
</form>
</details>
</div>
<script>
function toggleAnsibleEdit(idx) {
var view = document.getElementById('ansible-source-view-' + idx);
var edit = document.getElementById('ansible-source-edit-' + idx);
var showingEdit = edit.style.display !== 'none';
edit.style.display = showingEdit ? 'none' : 'block';
}
function updateAnsibleEditFields(idx) {
var t = document.getElementById('ansible-edit-type-' + idx).value;
document.getElementById('ansible-edit-git-fields-' + idx).style.display = t === 'git' ? 'grid' : 'none';
document.getElementById('ansible-edit-local-fields-' + idx).style.display = t === 'local' ? 'grid' : 'none';
}
function updateAnsibleAddFields() {
var t = document.getElementById('ansible-add-type').value;
document.getElementById('ansible-add-git-fields').style.display = t === 'git' ? 'grid' : 'none';
document.getElementById('ansible-add-local-fields').style.display = t === 'local' ? 'grid' : 'none';
}
</script>