fix(clients): expose Attached inbounds in edit mode

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 <noreply@anthropic.com>
This commit is contained in:
MHSanaei 2026-05-17 07:52:24 +02:00
parent bb5296aa0e
commit 7fbaf5fe2d
No known key found for this signature in database
GPG key ID: 7E4060F2FBE5AB7A
2 changed files with 28 additions and 5 deletions

View file

@ -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() {
<a-input v-model:value="form.comment" />
</a-form-item>
<a-form-item v-if="!isEdit" :label="t('pages.clients.attachedInbounds') || 'Attach to inbounds'" required>
<a-form-item :label="t('pages.clients.attachedInbounds') || 'Attached inbounds'"
:required="!isEdit">
<a-select v-model:value="form.inboundIds" mode="multiple" :options="inboundOptions" :show-search="true"
:placeholder="t('pages.clients.selectInbound') || 'Select one or more inbounds'"
:filter-option="(input, option) => (option.label || '').toLowerCase().includes(input.toLowerCase())" />

View file

@ -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) {