feat(proxies): per-row Triggers deep-link to /apps/[id]#bindings
The proxies page now exposes the trigger bindings for each routed
workload via a per-row action chip. Resolves the explicit "what's
next" call-out in WORKLOAD_REFACTOR_TODO under Priority 3 polish.
- Added id="bindings" to the existing trigger bindings <section> on
/apps/[id]/+page.svelte so URL fragments resolve to the panel.
- New triggersHref(route) helper in /proxies that builds
/apps/{workload_id}#bindings; code-pointer comment explains the
back-compat naming (ProxyRoute.project_id is actually the workload
ID — see internal/store/models.go:110-113), so a future contributor
doesn't trip on the mismatch and rip the helper out.
- New right-aligned "Actions" column with a button-shaped link;
defensive — falls back to — when project_id is absent.
- Three new i18n keys under proxies.* (actions, viewTriggers,
viewTriggersTitle) mirrored across EN + RU. Key parity now 1512
each.
No backend change needed; ListProxyRoutes already selects w.id into
ProxyRoute.project_id. Workload-aware batch endpoints (showing
trigger counts inline) were deliberately out of scope for this
half-turn — flagged as a future enhancement only if users want
inline counts.
Verification: svelte-check 0 errors + 3 pre-existing warnings in
TagCombobox; go build + go test ./... all green across 20 packages.
This commit is contained in:
@@ -392,7 +392,10 @@
|
|||||||
"noMatch": "No routes match your search.",
|
"noMatch": "No routes match your search.",
|
||||||
"loadFailed": "Failed to load proxy routes",
|
"loadFailed": "Failed to load proxy routes",
|
||||||
"route": "route",
|
"route": "route",
|
||||||
"routes": "routes"
|
"routes": "routes",
|
||||||
|
"actions": "Actions",
|
||||||
|
"viewTriggers": "Triggers",
|
||||||
|
"viewTriggersTitle": "View trigger bindings for this workload"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
|
|||||||
@@ -392,7 +392,10 @@
|
|||||||
"noMatch": "Нет маршрутов, соответствующих поиску.",
|
"noMatch": "Нет маршрутов, соответствующих поиску.",
|
||||||
"loadFailed": "Не удалось загрузить прокси-маршруты",
|
"loadFailed": "Не удалось загрузить прокси-маршруты",
|
||||||
"route": "маршрут",
|
"route": "маршрут",
|
||||||
"routes": "маршрутов"
|
"routes": "маршрутов",
|
||||||
|
"actions": "Действия",
|
||||||
|
"viewTriggers": "Триггеры",
|
||||||
|
"viewTriggersTitle": "Посмотреть привязки триггеров для этой нагрузки"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"cancel": "Отмена",
|
"cancel": "Отмена",
|
||||||
|
|||||||
@@ -2168,7 +2168,7 @@
|
|||||||
"Add trigger" opens a modal with two tabs: inline-create
|
"Add trigger" opens a modal with two tabs: inline-create
|
||||||
a new trigger record, or pick an existing one. -->
|
a new trigger record, or pick an existing one. -->
|
||||||
{#if !editing}
|
{#if !editing}
|
||||||
<section class="panel" aria-labelledby="trig-bindings-heading">
|
<section id="bindings" class="panel" aria-labelledby="trig-bindings-heading">
|
||||||
<header class="panel-head split bindings-head">
|
<header class="panel-head split bindings-head">
|
||||||
<div class="bindings-head-left">
|
<div class="bindings-head-left">
|
||||||
<h2 class="panel-title" id="trig-bindings-heading">
|
<h2 class="panel-title" id="trig-bindings-heading">
|
||||||
|
|||||||
@@ -57,6 +57,14 @@
|
|||||||
return q ? `/containers?q=${q}` : '/containers';
|
return q ? `/containers?q=${q}` : '/containers';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `project_id` on a ProxyRoute is actually the workload ID
|
||||||
|
// (back-compat naming — see internal/store/models.go:110-113). Anchor
|
||||||
|
// at the bindings section on /apps/[id] so the operator lands directly
|
||||||
|
// on the trigger list for this workload.
|
||||||
|
function triggersHref(route: ProxyRoute): string {
|
||||||
|
return route.project_id ? `/apps/${route.project_id}#bindings` : '/triggers';
|
||||||
|
}
|
||||||
|
|
||||||
async function loadRoutes() {
|
async function loadRoutes() {
|
||||||
loading = true;
|
loading = true;
|
||||||
try {
|
try {
|
||||||
@@ -136,6 +144,7 @@
|
|||||||
<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.tag')}</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.tag')}</th>
|
||||||
<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.port')}</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.port')}</th>
|
||||||
<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.status')}</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.status')}</th>
|
||||||
|
<th class="px-4 py-3 text-right text-xs font-medium text-[var(--text-tertiary)] uppercase">{$t('proxies.actions')}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-[var(--border-secondary)]">
|
<tbody class="divide-y divide-[var(--border-secondary)]">
|
||||||
@@ -172,6 +181,19 @@
|
|||||||
<td class="px-4 py-3">
|
<td class="px-4 py-3">
|
||||||
<StatusBadge status={route.status} />
|
<StatusBadge status={route.status} />
|
||||||
</td>
|
</td>
|
||||||
|
<td class="px-4 py-3 text-right">
|
||||||
|
{#if route.project_id}
|
||||||
|
<a
|
||||||
|
href={triggersHref(route)}
|
||||||
|
title={$t('proxies.viewTriggersTitle')}
|
||||||
|
class="inline-flex items-center rounded-md border border-[var(--border-primary)] bg-[var(--surface-card)] px-2.5 py-1 text-xs font-medium text-[var(--text-secondary)] transition-colors hover:border-[var(--color-brand-500)] hover:text-[var(--text-primary)]"
|
||||||
|
>
|
||||||
|
{$t('proxies.viewTriggers')}
|
||||||
|
</a>
|
||||||
|
{:else}
|
||||||
|
<span class="text-xs text-[var(--text-tertiary)]">—</span>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
Reference in New Issue
Block a user