This commit is contained in:
jpmvaz
2026-09-13 20:03:24 +01:00
commit 0ebb8e7f4b
270 changed files with 23789 additions and 0 deletions
+80
View File
@@ -0,0 +1,80 @@
{% extends "base.html" %}
{% block title %}Request #{{ req.id }} — MartinhalApprovalFlow{% endblock %}
{% block content %}
<p><a href="{{ url_for('admin') }}">&larr; All requests</a></p>
<div class="rowline">
<h1>Request #{{ req.id }}</h1>
<span class="stamp big {{ req.status }}">{{ req.status }}</span>
</div>
<p class="sub">Workflow <b>{{ req.wf_name }}</b> · received {{ req.created_at }}</p>
<div class="card">
<p><b>From:</b> <span class="mono">{{ req.requester }}</span><br>
<b>Subject:</b> {{ req.subject }}</p>
<div class="pre">{{ req.body }}</div>
{% if attachments %}
<p><b>Attachments</b> <span class="muted">(included in every approval mail)</span>:<br>
{% for att in attachments %}
<a class="mono" href="{{ url_for('request_attachment', rid=req.id, idx=loop.index0) }}">{{ att.name }}</a>{% if not loop.last %} · {% endif %}
{% endfor %}
</p>
{% endif %}
{% if req.decided_by %}
<p class="muted">Final decision by <span class="mono">{{ req.decided_by }}</span> at {{ req.decided_at }}</p>
{% endif %}
{% if req.status == 'denied' and req.deny_reason %}
<p><b>Reason for denial:</b></p>
<div class="pre">{{ req.deny_reason }}</div>
{% endif %}
{% if req.status == 'pending' %}
<form method="post">
<div class="rowline">
<button class="btn approve small" name="action" value="approve">Approve this step</button>
<span class="muted">Same effect as the current approver's email links.</span>
</div>
</form>
<form method="post" style="margin-top:.8rem">
<label for="rr" style="margin-top:0">Reason for denial <small>(required to deny)</small></label>
<textarea id="rr" name="reason" required style="min-height:70px"></textarea>
<button class="btn deny small" name="action" value="deny" style="margin-top:.6rem">Deny &amp; stop workflow</button>
</form>
{% endif %}
</div>
<h2>Approval chain</h2>
<div class="card">
<ul class="ledger">
{% for a in chain %}
<li>
<span class="t mono">step {{ loop.index }} / {{ chain | length }}</span>
<span class="e mono">{{ a }}</span>
<span>
{% if req.status == 'denied' and loop.index0 == req.current_step %}<span class="stamp denied">denied here</span>
{% elif loop.index0 < req.current_step or req.status == 'approved' %}<span class="stamp approved">approved</span>
{% elif loop.index0 == req.current_step and req.status == 'pending' %}<span class="stamp pending">waiting</span>
{% elif req.status == 'denied' %}<span class="muted">never reached — workflow stopped</span>
{% else %}<span class="muted">not yet reached</span>{% endif %}
</span>
</li>
{% endfor %}
</ul>
</div>
<h2>People involved so far</h2>
<div class="card">
{% for p in participants %}<span class="chip">{{ p }}</span> {% else %}<span class="muted">None recorded.</span>{% endfor %}
</div>
<h2>Full log</h2>
<div class="card">
<ul class="ledger">
{% for l in logs %}
<li><span class="t">{{ l.at }}</span><span class="e">{{ l.event }}</span><span>{{ l.detail }}</span></li>
{% endfor %}
</ul>
<form method="post" action="{{ url_for('send_request_log', rid=req.id) }}" class="rowline" style="margin-top:1rem">
<input type="email" name="email" placeholder="name@example.com" required style="max-width:280px">
<button class="small" type="submit">Email this full log</button>
</form>
</div>
{% endblock %}