Files
member-console/internal/embeds/templates/partials/operator_grants.html
T
cgalo5758 71818de0bd Add setup checklist and empty-state guidance
Implement the ux-first-run change: a state-derived setup checklist on
/operator/setup with a landing region that recedes once required steps
are done, and empty states that distinguish blocked from empty across
operator and member surfaces. Also add production deployment and
environment reference docs, plus a config-key completeness test.
2026-08-23 03:06:11 -05:00

80 lines
3.4 KiB
HTML

<!-- Grants management partial for operator — READ-ONLY.
Per operator-mpa-conversion D8, Issue/Extend/Revoke and CreateGrant
are exposed only on /operator/organizations/{orgID}. This view is
browse/audit only.
Delivery renders the derived state from the shared
ListGrantsWithDelivery query (ux-honest-surfaces design decision 1) —
the same vocabulary and badge treatment the org-detail composite's
Grants table uses, so the two surfaces can never disagree. Ledger
(grants.status) is issuance history and is deliberately NOT a colored
state badge — see the explanation below. -->
<h1 class="h2 mb-3">Grants</h1>
{{ if .Error }}
<div class="alert alert-danger" role="alert">
<strong>Error:</strong> {{ .Error }}
</div>
{{ else }}
{{ if eq (len .Grants) 0 }}
<div class="text-center py-4">
<p class="text-muted mb-2">No grants found.</p>
{{ if eq (len .Products) 0 }}
<p class="text-muted small mb-0">A grant delivers a published product to an organization, but no product has been published yet. <a href="/operator/products">Go to Products</a> to publish one.</p>
{{ else }}
<p class="text-muted small mb-0">Grants are issued from each organization's detail page, not from here.</p>
{{ end }}
</div>
{{ else }}
<p class="text-muted small mb-2">
Grants are the issuance ledger, not the delivery record: Ledger is when
and why a grant was recorded (and whether it was later revoked or
expired). Delivery is derived by joining each grant to its pool
provision — at most one grant per ladder position is
<span class="badge text-bg-success">Live</span> at a time; the rest are
history.
</p>
<div class="table-responsive">
<table class="table table-hover table-sm">
<thead>
<tr>
<th>Organization</th>
<th>Grant Target</th>
<th>Qty</th>
<th>Reason</th>
<th>Ledger</th>
<th>Delivery</th>
<th>Created</th>
</tr>
</thead>
<tbody>
{{ range .Grants }}
<tr{{ if ne .DeliveryState "live" }} class="text-muted"{{ end }}>
<td>{{ .OrgName }}</td>
<td>{{ if .ProductName }}{{ .ProductName }} <span class="badge bg-secondary">product</span>{{ else }}{{ .EntitlementSetName }} <span class="badge text-bg-info">set</span>{{ end }}</td>
<td>{{ .Quantity }}</td>
<td>{{ .GrantReason }}</td>
<td><small>{{ .Status }}</small></td>
<td>
{{ if eq .DeliveryState "live" }}
<span class="badge text-bg-success">Live</span>
{{ if .ExtendsLabel }}<br><small class="text-muted">extends {{ .ExtendsLabel }}</small>{{ end }}
{{ else if eq .DeliveryState "superseded" }}
<span class="badge text-bg-secondary">Superseded</span>
{{ if .ReplacedByLabel }}<br><small class="text-muted">replaced by {{ .ReplacedByLabel }}</small>{{ end }}
{{ else }}
<span class="badge text-bg-light border">Inactive</span>
{{ end }}
</td>
<td>{{ .CreatedAt }}</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
<p class="text-muted small mt-2">Total: {{ len .Grants }} grants</p>
{{ end }}
{{ end }}