From 7fbaf5fe2dbc97e5e9e4b02a840b0f8d529a8d16 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 17 May 2026 07:52:24 +0200 Subject: [PATCH] fix(clients): expose Attached inbounds in edit mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The multi-select was gated on add-only, so editing a client had no way to change which inbounds it belonged to. The picker now shows in both modes, and on submit the modal diffs the picked set against the original attachedIds — additions go through the /attach endpoint, removals through /detach, both after the field update lands so the new attachments get the latest values. Co-Authored-By: Claude Opus 4.7 --- .../src/pages/clients/ClientFormModal.vue | 14 ++++++++++++-- frontend/src/pages/clients/ClientsPage.vue | 19 ++++++++++++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/frontend/src/pages/clients/ClientFormModal.vue b/frontend/src/pages/clients/ClientFormModal.vue index fca8a8ab..725e3521 100644 --- a/frontend/src/pages/clients/ClientFormModal.vue +++ b/frontend/src/pages/clients/ClientFormModal.vue @@ -128,7 +128,16 @@ async function onSubmit() { try { let msg; if (isEdit.value) { - msg = await props.save(clientPayload, { isEdit: true, id: props.client.id }); + const original = new Set(props.attachedIds || []); + const next = new Set(form.inboundIds || []); + const toAttach = [...next].filter((id) => !original.has(id)); + const toDetach = [...original].filter((id) => !next.has(id)); + msg = await props.save(clientPayload, { + isEdit: true, + id: props.client.id, + attach: toAttach, + detach: toDetach, + }); } else { msg = await props.save( { client: clientPayload, inboundIds: form.inboundIds }, @@ -215,7 +224,8 @@ async function onSubmit() { - + diff --git a/frontend/src/pages/clients/ClientsPage.vue b/frontend/src/pages/clients/ClientsPage.vue index 8569056e..1b221ae7 100644 --- a/frontend/src/pages/clients/ClientsPage.vue +++ b/frontend/src/pages/clients/ClientsPage.vue @@ -32,6 +32,8 @@ const { create, update, remove, + attach, + detach, resetTraffic, } = useClients(); @@ -125,10 +127,21 @@ function onShowQr(row) { } async function onSave(payload, meta) { - if (meta?.isEdit) { - return update(meta.id, payload); + if (!meta?.isEdit) { + return create(payload); } - return create(payload); + const id = meta.id; + const updateMsg = await update(id, payload); + if (!updateMsg?.success) return updateMsg; + if (Array.isArray(meta.attach) && meta.attach.length > 0) { + const r = await attach(id, meta.attach); + if (!r?.success) return r; + } + if (Array.isArray(meta.detach) && meta.detach.length > 0) { + const r = await detach(id, meta.detach); + if (!r?.success) return r; + } + return updateMsg; } function trafficLabel(row) {