From 59858bc413af72a76ca63b6f4c3d2efcec2f2b0f Mon Sep 17 00:00:00 2001 From: Oleksii Dolhov Date: Thu, 25 Jun 2026 12:40:25 +0300 Subject: [PATCH 1/4] feat(ui): move channel config into dialogs + VoIP surface (#19) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Builds on the Sharing-tab reframe (#18). Replaces the inline collapsible channel panels with compact summary rows that open the existing config panels in a modal — the tab stays a clean summary instead of a wall of forms. - New ChannelConfigDialog.vue — Teleport modal (backdrop + Esc close, scrollable body) matching the ConfirmDialog idiom. - New ChannelConfigRow.vue — summary row showing connected/off + a brief status (channel/handle/number), a Configure/Manage button that opens the dialog, and a lightweight status fetch (shared `api` client) that refetches on dialog close so the row reflects edits. The 4 channel panels render untouched in the dialog slot — no loss of functionality. - SharingPanel wires Slack/Telegram/WhatsApp/VoIP through ChannelConfigRow with per-channel status derivations. VoIP (previously backend-only) now has its Sharing UI surface, gated on `voip_available`. - Distribution (public links, file sharing) keeps the collapsible disclosure — out of scope for the channel-dialog change. Frontend-only; no API changes. Verified: 3 SFCs compile (vue/compiler-sfc), design-token check passes, and Vite transforms all modules on the live dev server (HTTP 200). Related to abilityai/trinity-enterprise#19 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/components/ChannelConfigDialog.vue | 66 ++++++++++++++ .../src/components/ChannelConfigRow.vue | 88 +++++++++++++++++++ src/frontend/src/components/SharingPanel.vue | 67 +++++++++++--- 3 files changed, 210 insertions(+), 11 deletions(-) create mode 100644 src/frontend/src/components/ChannelConfigDialog.vue create mode 100644 src/frontend/src/components/ChannelConfigRow.vue diff --git a/src/frontend/src/components/ChannelConfigDialog.vue b/src/frontend/src/components/ChannelConfigDialog.vue new file mode 100644 index 000000000..8116bfe39 --- /dev/null +++ b/src/frontend/src/components/ChannelConfigDialog.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/frontend/src/components/ChannelConfigRow.vue b/src/frontend/src/components/ChannelConfigRow.vue new file mode 100644 index 000000000..8ddb1cf49 --- /dev/null +++ b/src/frontend/src/components/ChannelConfigRow.vue @@ -0,0 +1,88 @@ + + + diff --git a/src/frontend/src/components/SharingPanel.vue b/src/frontend/src/components/SharingPanel.vue index 4ea8becd1..379101241 100644 --- a/src/frontend/src/components/SharingPanel.vue +++ b/src/frontend/src/components/SharingPanel.vue @@ -96,33 +96,53 @@ - +

Channels

- Connect this agent to messaging channels. Expand a row to configure it. + Connect this agent to messaging channels. Use Configure to set one up.

- + - + - + - + - + - + - - +
@@ -152,6 +172,7 @@ import { useAuthStore } from '../stores/auth' import { useNotification } from '../composables' import { useSessionsStore } from '../stores/sessions' import ChannelDisclosure from './ChannelDisclosure.vue' +import ChannelConfigRow from './ChannelConfigRow.vue' import PublicLinksPanel from './PublicLinksPanel.vue' import SlackChannelPanel from './SlackChannelPanel.vue' import TelegramChannelPanel from './TelegramChannelPanel.vue' @@ -182,6 +203,30 @@ const loadAgent = () => { emit('agent-updated') } +// --------------------------------------------------------------------------- +// Channel summary-row status derivations (#19). Each maps a channel's GET +// response to { connected, label, warn } for the compact row; the full config +// panel renders in the row's Configure dialog. +// --------------------------------------------------------------------------- +const slackStatus = (d) => ({ + connected: !!d?.bound, + label: d?.bound ? `#${d.channel_name}` : '', +}) +const telegramStatus = (d) => ({ + connected: !!d?.configured, + label: d?.configured && d.bot_username ? `@${d.bot_username}` : '', + warn: !!d?.configured && !d?.webhook_url, +}) +const whatsappStatus = (d) => ({ + connected: !!d?.configured, + label: d?.configured ? (d.from_number || '') : '', +}) +const voipStatus = (d) => ({ + connected: !!d?.configured, + label: d?.configured ? `${d.from_number || ''}${d.enabled ? '' : ' (disabled)'}` : '', + warn: !!d?.configured && !d?.enabled, +}) + // --------------------------------------------------------------------------- // External access policy + pending requests (Issue #311, reframed by #18) // --------------------------------------------------------------------------- From bf5234f7364e29ac0ce24b1c927dc8c55ddb124e Mon Sep 17 00:00:00 2001 From: Oleksii Dolhov Date: Thu, 25 Jun 2026 13:02:19 +0300 Subject: [PATCH 2/4] fix(ui): mount channel config dialog only when open (no row layout collapse) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A closed ChannelConfigDialog should collapse to Teleport comment nodes, but under some dev-server HMR states its slotted panel rendered inline as a flex child of the channel row, squeezing the label (esp. WhatsApp, whose panel is the widest) to zero width. Gate the dialog with v-if="dialogOpen" in ChannelConfigRow so the closed dialog — and its slotted panel — never participates in the row's flex layout, and mount the panel on demand. Make the dialog's Escape handler bind immediately so it still works when mounted already-open. Related to abilityai/trinity-enterprise#19 Co-Authored-By: Claude Opus 4.8 (1M context) --- src/frontend/src/components/ChannelConfigDialog.vue | 5 +++-- src/frontend/src/components/ChannelConfigRow.vue | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/frontend/src/components/ChannelConfigDialog.vue b/src/frontend/src/components/ChannelConfigDialog.vue index 8116bfe39..3967e6fce 100644 --- a/src/frontend/src/components/ChannelConfigDialog.vue +++ b/src/frontend/src/components/ChannelConfigDialog.vue @@ -54,13 +54,14 @@ const props = defineProps({ const emit = defineEmits(['close']) -// Close on Escape while open. +// Close on Escape while open. `immediate` so it also binds when the dialog is +// mounted already-open (parent gates mount with v-if="dialogOpen"). const onKey = (e) => { if (e.key === 'Escape') emit('close') } watch(() => props.open, (isOpen) => { if (isOpen) document.addEventListener('keydown', onKey) else document.removeEventListener('keydown', onKey) -}) +}, { immediate: true }) onUnmounted(() => document.removeEventListener('keydown', onKey)) diff --git a/src/frontend/src/components/ChannelConfigRow.vue b/src/frontend/src/components/ChannelConfigRow.vue index 8ddb1cf49..6c5bca1f4 100644 --- a/src/frontend/src/components/ChannelConfigRow.vue +++ b/src/frontend/src/components/ChannelConfigRow.vue @@ -35,8 +35,10 @@ {{ status.connected ? 'Manage' : 'Configure' }} - - + + From 304c1a1f402fdbaa6571f1311d82a576cf3ac9d9 Mon Sep 17 00:00:00 2001 From: Oleksii Dolhov Date: Thu, 25 Jun 2026 13:15:45 +0300 Subject: [PATCH 3/4] fix(ui): truncate long channel status labels + collapse redundant dialog gating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses code-review findings on PR #1348: - [Medium] The connected-status label was a flex child without `min-w-0`, so a long label (e.g. WhatsApp `whatsapp:+14155238886`) overflowed the row instead of clipping. Add `min-w-0` to the label and `shrink-0` to the status dots and the "· setup needed" span. - [Low] Collapse the redundant triple-gating to a single mechanism: the dialog is mounted only via the parent `v-if="dialogOpen"`, so drop the now always-true `:open` prop and ChannelConfigDialog's internal `v-if="open"` (Escape binds for the component's lifetime via onMounted/onUnmounted). (Skipped the a11y note — focus-trap/scroll-lock would be new behavior beyond the existing ConfirmDialog parity; not a regression.) Related to abilityai/trinity-enterprise#19 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/components/ChannelConfigDialog.vue | 16 ++++++---------- .../src/components/ChannelConfigRow.vue | 18 +++++++++--------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/frontend/src/components/ChannelConfigDialog.vue b/src/frontend/src/components/ChannelConfigDialog.vue index 3967e6fce..da7401e06 100644 --- a/src/frontend/src/components/ChannelConfigDialog.vue +++ b/src/frontend/src/components/ChannelConfigDialog.vue @@ -1,6 +1,6 @@