diff --git a/apps/settings/src/components/Users/UserRow.vue b/apps/settings/src/components/Users/UserRow.vue index d5ecff42384..b6af13c7300 100644 --- a/apps/settings/src/components/Users/UserRow.vue +++ b/apps/settings/src/components/Users/UserRow.vue @@ -262,6 +262,7 @@ label="displayname" :options="possibleManagers" :placeholder="managerLabel" + clearable @open="searchInitialUserManager" @search="searchUserManager" @option:selected="updateUserManager" /> @@ -636,20 +637,25 @@ export default { }, async updateUserManager(manager) { - if (manager === null) { - this.currentManager = '' - } + // Update the local state immediately for better UX + const previousManager = this.currentManager + this.currentManager = manager || '' this.loading.manager = true + try { await this.$store.dispatch('setUserData', { userid: this.user.id, key: 'manager', - value: this.currentManager ? this.currentManager.id : '', + value: manager ? manager.id : '', }) + } catch (error) { // TRANSLATORS This string describes a line manager in the context of an organization showError(t('settings', 'Failed to update line manager')) - console.error(error) + console.error('Failed to update manager:', error) + + // Revert to the previous manager in the UI on error + this.currentManager = previousManager } finally { this.loading.manager = false } diff --git a/apps/settings/src/store/users.js b/apps/settings/src/store/users.js index 3734b7008df..39ff43346d8 100644 --- a/apps/settings/src/store/users.js +++ b/apps/settings/src/store/users.js @@ -767,23 +767,27 @@ const actions = { */ async setUserData(context, { userid, key, value }) { const allowedEmpty = ['email', 'displayname', 'manager'] - if (['email', 'language', 'quota', 'displayname', 'password', 'manager'].indexOf(key) !== -1) { - // We allow empty email or displayname - if (typeof value === 'string' - && ( - (allowedEmpty.indexOf(key) === -1 && value.length > 0) - || allowedEmpty.indexOf(key) !== -1 - ) - ) { - try { - await api.requireAdmin() - await api.put(generateOcsUrl('cloud/users/{userid}', { userid }), { key, value }) - return context.commit('setUserData', { userid, key, value }) - } catch (error) { - context.commit('API_FAILURE', { userid, error }) - } - } + const validKeys = ['email', 'language', 'quota', 'displayname', 'password', 'manager'] + if (!validKeys.includes(key)) { + return Promise.reject(new Error('Invalid request data')) } + + try { + await api.requireAdmin() + if (typeof value === 'string' && value.length === 0 && allowedEmpty.includes(key)) { + // If value is empty and allowed to be empty, send DELETE request + await api.delete(generateOcsUrl('cloud/users/{userid}', { userid }), { key }) + return context.commit('setUserData', { userid, key, value: '' }) + } + + if (typeof value === 'string' && (value.length > 0 || allowedEmpty.includes(key))) { + await api.put(generateOcsUrl('cloud/users/{userid}', { userid }), { key, value }) + return context.commit('setUserData', { userid, key, value }) + } + } catch (error) { + context.commit('API_FAILURE', { userid, error }) + } + return Promise.reject(new Error('Invalid request data')) },