- /ansible/playbooks lists every playbook across sources: what it says it does, its category and destructive flag, how it last ran; the whole row opens the playbook. A source with none is one quiet line. - /ansible/playbooks/<source>/<path>: the verdict (what it does, flagged destructive, last ran), the run form in place (dry run beside the button, options folded), the schedules that use it, its recent runs, the playbook itself folded. ?from=<run> fills the form from that run: Run again on a run's page. - /ansible/browse, its view page and the /run-form fragment are gone, not redirected (rule 122); every link points at the new pages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
222 lines
11 KiB
HTML
222 lines
11 KiB
HTML
{# 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/playbooks" class="btn btn-ghost btn-sm" style="font-size:0.78rem;">Playbooks</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>
|