docs/plugins/prometheus-widgets.md covers: - where templates live and how to copy one in, duplicate, export and share; - a first template, walked through; - each block (states with its deadlines, values, times, table, info) with an example; - the format reference: keys, units, spans, limits, what the checker refuses; - the Fabled Archives template, block by block, with what it leaves out and why. Linked from the README, the plugin guide, the editor and template_format. tests/plugins/prometheus/test_widget_guide.py checks every YAML example in the guide against the checker, so the guide can't drift from the format. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
93 lines
5.0 KiB
HTML
93 lines
5.0 KiB
HTML
{# plugins/prometheus/templates/prometheus/template.html — one widget
|
|
template (#5692): its YAML beside a live preview over a chosen target,
|
|
drawn as the dashboard widget draws it. An admin edits their own here,
|
|
or starts one by pasting or uploading; a built-in one is read-only and
|
|
can be duplicated. The preview saves nothing. #}
|
|
{% extends "base.html" %}
|
|
{% from "_macros.html" import crumbs, page_header %}
|
|
{% from "prometheus/_tabs.html" import prometheus_tabs %}
|
|
{% block title %}{{ title }} — Widget templates — Steward{% endblock %}
|
|
{% block section_tabs %}{{ prometheus_tabs("templates") }}{% endblock %}
|
|
{% block breadcrumb %}{{ crumbs([("Prometheus", "/plugins/prometheus/"), ("Widget templates", "/plugins/prometheus/templates/"), (title, "")]) }}{% endblock %}
|
|
{% block content %}
|
|
{% set admin = session.user_role == 'admin' %}
|
|
{% call page_header(title, ("Built in, read-only" if entry.bundled else "Your own") if entry else none) %}
|
|
{% if entry %}
|
|
<a class="btn btn-sm btn-ghost" href="/plugins/prometheus/templates/{{ entry.key }}/export">Export</a>
|
|
{% if admin %}<a class="btn btn-sm btn-ghost" href="/plugins/prometheus/templates/new?from={{ entry.key|urlencode }}">Duplicate</a>{% endif %}
|
|
{% endif %}
|
|
{% endcall %}
|
|
|
|
{% if problems %}
|
|
<div class="field-error" role="alert">
|
|
{{ "Not saved. " if saving }}{{ problems|length }} problem{{ "s" if problems|length != 1 }} to fix:
|
|
<ul class="tpl-problems">{% for p in problems %}<li>{{ p }}</li>{% endfor %}</ul>
|
|
</div>
|
|
{% endif %}
|
|
{% if note %}<p class="field-hint">{{ note }}</p>{% endif %}
|
|
{% if entry and entry.bundled %}
|
|
<p class="field-hint">Ships with Steward and changes with it. To change it, duplicate it and edit the copy.</p>
|
|
{% endif %}
|
|
{% if used %}<p class="field-hint">{{ used }} dashboard widget{{ "s draw" if used != 1 else " draws" }} with it{{ "; saving changes them too" if editable }}.</p>{% endif %}
|
|
|
|
<div class="tpl-editor">
|
|
<form method="post" id="tpl-form"
|
|
action="{{ '/plugins/prometheus/templates/custom:' ~ entry.id ~ '/edit' if entry else '/plugins/prometheus/templates/new' }}">{{ csrf_field() }}
|
|
<label class="field-label" for="tpl-text">YAML</label>
|
|
<textarea class="input mono tpl-text" id="tpl-text" name="text" spellcheck="false" wrap="off"
|
|
{%- if not editable %} readonly{% endif %}
|
|
placeholder="Paste a template here, or write one: name, version and blocks. The guide is docs/plugins/prometheus-widgets.md.">{{ text }}</textarea>
|
|
{% if editable %}
|
|
<div class="form-actions">
|
|
<button type="submit" class="btn">{{ "Save" if entry else "Save template" }}</button>
|
|
<a href="{{ '/plugins/prometheus/templates/' ~ entry.key if entry else '/plugins/prometheus/templates/' }}" class="btn btn-ghost">Cancel</a>
|
|
</div>
|
|
{% endif %}
|
|
</form>
|
|
|
|
<section class="card" aria-labelledby="tpl-preview-title">
|
|
<div class="tpl-preview-head">
|
|
<h2 id="tpl-preview-title" class="section-title">Preview</h2>
|
|
{% if targets %}
|
|
<label class="sr-only" for="tpl-target">Target</label>
|
|
<select class="input" id="tpl-target" name="target">
|
|
{% for t in targets %}<option value="{{ t.value }}">{{ t.label }}</option>{% endfor %}
|
|
</select>
|
|
{% endif %}
|
|
</div>
|
|
<div id="tpl-preview" class="dash-cell-body" aria-live="polite"
|
|
hx-post="/plugins/prometheus/templates/preview"
|
|
hx-trigger="load, input changed delay:600ms from:#tpl-text, change from:#tpl-target"
|
|
hx-include="#tpl-text, #tpl-target">
|
|
<p class="field-hint">Loading…</p>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
{% if editable and not entry %}
|
|
<section class="card form-section" aria-labelledby="tpl-upload">
|
|
<h2 id="tpl-upload" class="section-title">Or upload a file</h2>
|
|
<form method="post" action="/plugins/prometheus/templates/upload" enctype="multipart/form-data"
|
|
style="display:flex;gap:0.75rem;align-items:center;flex-wrap:wrap;">{{ csrf_field() }}
|
|
<label class="sr-only" for="tpl-file">Template file</label>
|
|
<input id="tpl-file" type="file" name="file" accept=".yaml,.yml,text/yaml,application/yaml">
|
|
<button type="submit" class="btn btn-sm btn-ghost">Read file</button>
|
|
<span class="field-hint">Opens it here to look over; nothing is saved until you press Save.</span>
|
|
</form>
|
|
</section>
|
|
{% endif %}
|
|
|
|
{% if editable and entry %}
|
|
<section class="card danger-zone" aria-labelledby="tpl-delete">
|
|
<div>
|
|
<h2 id="tpl-delete" class="section-title">Delete this template</h2>
|
|
<p class="field-hint">{% if used %}{{ used }} widget{{ "s" if used != 1 }} using it will say the template is gone.{% else %}No widget uses it.{% endif %} Export it first to keep a copy.</p>
|
|
</div>
|
|
<form method="post" action="/plugins/prometheus/templates/custom:{{ entry.id }}/delete"
|
|
data-confirm="Delete widget template {{ entry.name }}?{% if used %} {{ used }} widget{{ 's' if used != 1 }} use it.{% endif %}">{{ csrf_field() }}
|
|
<button class="btn btn-danger" type="submit">Delete template</button>
|
|
</form>
|
|
</section>
|
|
{% endif %}
|
|
{% endblock %}
|