From 7f2ca53cefcda71c9cc79f6aeeb14d4b9476ca4e Mon Sep 17 00:00:00 2001 From: Norman Niati Date: Mon, 18 May 2026 17:46:22 +0200 Subject: [PATCH] fix(plugin-id/ui): map scope name to Integer ID before save (Company + Group) The backend expects `scope` as an Integer (container scope ID), not as the string name. The frontend v-autocomplete uses the name for display (item-value="name"), so we now resolve the ID from the preloaded scopeAll list at save() time. Unblocks POST /company and POST /group from the UI after the @POST fix in PR norman/fix-container-resource-post. GroupEditView previously stored only the scope names in availableScopes (stripped at load time); add a parallel scopeAll ref holding the full {id, name, ...} objects so save() can resolve the ID. --- ui/src/views/CompanyEditView.vue | 11 ++++++++++- ui/src/views/GroupEditView.vue | 17 ++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/ui/src/views/CompanyEditView.vue b/ui/src/views/CompanyEditView.vue index 02138e2..b2e5fd5 100644 --- a/ui/src/views/CompanyEditView.vue +++ b/ui/src/views/CompanyEditView.vue @@ -242,8 +242,17 @@ async function save() { return } + // Resolve the scope ID from its name. The backend expects an Integer + // ID (container scope), not the string name. scopeAll is preloaded at + // mount() from rest/service/id/container-scope/COMPANY. + const scopeEntry = scopeAll.value.find(s => s.name === form.value.scope) + if (!scopeEntry) { + errorStore.push({ message: `Unknown scope: ${form.value.scope}`, status: 0 }) + return + } + saving.value = true - const payload = { name: form.value.name, scope: form.value.scope } + const payload = { name: form.value.name, scope: scopeEntry.id } if (isEdit.value) { await api.put('rest/service/id/company', payload) diff --git a/ui/src/views/GroupEditView.vue b/ui/src/views/GroupEditView.vue index a660fcf..fe47455 100644 --- a/ui/src/views/GroupEditView.vue +++ b/ui/src/views/GroupEditView.vue @@ -75,6 +75,9 @@ const confirmDelete = ref(false) const demoMode = ref(false) const availableGroups = ref([]) const availableScopes = ref([]) +// Full scope objects ({id, name, ...}) — used at save() to resolve the +// Integer ID expected by the backend from the name held in form.value.scope. +const scopeAll = ref([]) const scopesLoading = ref(false) const isEdit = computed(() => route.params.id && route.params.id !== 'new') @@ -113,11 +116,14 @@ async function loadGroupScopes() { const data = await api.get('rest/service/id/container-scope/group') const rows = Array.isArray(data) ? data : (Array.isArray(data?.data) ? data.data : null) if (rows) { + scopeAll.value = rows availableScopes.value = rows.map((s) => s.name).filter(Boolean) } else { + scopeAll.value = [] availableScopes.value = ['Group', 'Department', 'Team', 'Project'] } } catch { + scopeAll.value = [] availableScopes.value = ['Group', 'Department', 'Team', 'Project'] } finally { scopesLoading.value = false @@ -186,8 +192,17 @@ async function save() { return } + // Resolve the scope ID from its name. The backend expects an Integer + // ID (container scope), not the string name. scopeAll is preloaded at + // mount() from rest/service/id/container-scope/group. + const scopeEntry = scopeAll.value.find(s => s.name === form.value.scope) + if (!scopeEntry) { + errorStore.push({ message: `Unknown scope: ${form.value.scope}`, status: 0 }) + return + } + saving.value = true - const payload = { name: form.value.name, scope: form.value.scope, parent: form.value.parent || null } + const payload = { name: form.value.name, scope: scopeEntry.id, parent: form.value.parent || null } if (isEdit.value) { await api.put('rest/service/id/group', payload)