Files
member-console/internal/embeds/templates/partials/operator_integrations.html
T
cgalo5758 408fa6f5a6 Add page anatomy parts and UI quality gate
- Add shared ui_*.html parts (pageHeader, sectionHeader, statusBadge,
  emptyState) parsed into every template set
- Add anatomy lint rules with a shrinking allowlist and screen-coverage
  check
- Add make screens capture harness with contact sheets and baseline diff
- Compose member and FedWiki regions server-side so pages arrive
  complete
- Rebuild Domains and Integrations on the parts as pilots
2026-08-30 04:05:31 -05:00

100 lines
5.9 KiB
HTML

<!-- Integrations landing — registry-driven list of every registered
integration (all provider kinds, so payments integrations appear
alongside provisioning ones). Adding a conforming integration
populates this with no edit here. Browse-only except the
unrecognized-override cleanup, which is confirm-modal-gated. Built
from the page-anatomy parts (docs/design-system.md §6): the header,
badges, section header, and empty state come from ui_*.html; the
values from IntegrationsData's methods. -->
{{ template "pageHeader" .Header }}
{{ if .Error }}
<div class="alert alert-danger" role="alert"><strong>Error:</strong> {{ .Error }}</div>
{{ else if eq (len .Integrations) 0 }}
{{ template "emptyState" .Empty }}
{{ else }}
<div class="table-responsive">
<table class="table table-hover table-sm align-middle">
<thead>
<tr>
<th>Integration</th>
<th>Registry status<span title="An operator-managed record, not a live health or connectivity check."><svg class="form-help-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span></th>
<th>Configuration<span title="Whether the integration's required keys actually resolve to a value."><svg class="form-help-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span></th>
<th>Kind<span title="What the integration does for members: a provisioning integration creates and manages member resources; a payment integration handles billing."><svg class="form-help-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span></th>
<th>Operations</th>
<th>Resource keys</th>
<th></th>
</tr>
</thead>
<tbody>
{{ range .Integrations }}
<tr>
<td>
<span class="fw-semibold">{{ .DisplayName }}</span>
<span class="text-muted small ms-1">{{ .Key }}</span>
</td>
<td>{{ template "statusBadge" .StatusBadge }}</td>
<td>
{{ if not .Configured }}{{ template "statusBadge" .ConfigurationBadge }}
{{ else }}<span class="text-muted small">&mdash;</span>{{ end }}
</td>
<td><span class="text-capitalize">{{ .Kind }}</span></td>
<td>
<!-- Operation names are identifiers, not states: muted code, like
the resource keys beside them. -->
{{ range .Operations }}<code class="small me-1">{{ . }}</code>{{ end }}
{{ if eq (len .Operations) 0 }}<span class="text-muted small"></span>{{ end }}
</td>
<td>
{{ range .ResourceKeys }}<span class="d-block">{{ if .DisplayName }}{{ .DisplayName }} <span class="text-muted small">({{ .ResourceKey }})</span>{{ else }}<code class="small">{{ .ResourceKey }}</code>{{ end }}</span>{{ end }}
{{ if eq (len .ResourceKeys) 0 }}<span class="text-muted small"></span>{{ end }}
</td>
<td class="text-end text-nowrap">
{{ if .SurfacePath }}
<a href="{{ .SurfacePath }}" class="btn btn-sm btn-outline-primary">Manage</a>
{{ end }}
{{ if .SettingsPath }}
<a href="{{ .SettingsPath }}" class="btn btn-sm btn-outline-secondary">Settings</a>
{{ end }}
{{ if and (not .SurfacePath) (not .SettingsPath) }}
<span class="text-muted small"></span>
{{ end }}
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
{{ end }}
{{ if .Orphans }}
{{ template "sectionHeader" .OrphansHeader }}
<p class="text-muted small">Stored configuration overrides whose key matches no installed integration, left behind by a removed integration or a retired key. They have no effect; remove them when convenient.</p>
<div class="table-responsive">
<table class="table table-hover table-sm align-middle">
<thead><tr><th>Key</th><th>Value</th><th></th></tr></thead>
<tbody>
{{ range .Orphans }}
<tr>
<td><code>{{ .Key }}</code></td>
<td><code>{{ .Value }}</code></td>
<td class="text-end">
<button type="button" class="btn btn-sm btn-outline-danger"
data-bs-toggle="modal"
data-bs-target="#confirmActionModal"
data-action-url="{{ routeURL "/operator/integrations/config-orphans/{key}" .Key }}"
data-action-method="delete"
data-action-target="#operator-body"
data-action-title="Delete stored override"
data-action-body="Delete the stored override for {{ .Key }}? It has no effect; this only removes the leftover row."
data-action-confirm-label="Delete override">
Delete
</button>
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
{{ end }}