mirror of
https://github.com/nextcloud/server.git
synced 2026-04-27 17:18:48 -04:00
fix(settings): Allow searching for groups in user row
Signed-off-by: Christopher Ng <chrng8@gmail.com>
This commit is contained in:
parent
f664eb8313
commit
86e521d032
4 changed files with 81 additions and 60 deletions
|
|
@ -34,8 +34,6 @@
|
|||
users,
|
||||
settings,
|
||||
hasObfuscated,
|
||||
groups,
|
||||
subAdminsGroups,
|
||||
quotaOptions,
|
||||
languages,
|
||||
externalActions,
|
||||
|
|
@ -179,11 +177,6 @@ export default {
|
|||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
},
|
||||
|
||||
subAdminsGroups() {
|
||||
// data provided php side
|
||||
return this.$store.getters.getSubadminGroups
|
||||
},
|
||||
|
||||
quotaOptions() {
|
||||
// convert the preset array into objects
|
||||
const quotaPreset = this.settings.quotaPreset.reduce((acc, cur) => acc.concat({
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@
|
|||
label="name"
|
||||
:no-wrap="true"
|
||||
:create-option="(value) => ({ name: value, isCreating: true })"
|
||||
@open="loadGroupDetails"
|
||||
@search="searchGroups"
|
||||
@option:created="createGroup"
|
||||
@option:selected="options => addUserGroup(options.at(-1))"
|
||||
@option:deselected="removeUserGroup" />
|
||||
|
|
@ -127,10 +129,10 @@
|
|||
</span>
|
||||
</td>
|
||||
|
||||
<td v-if="subAdminsGroups.length > 0 && (settings.isAdmin || settings.isDelegatedAdmin)"
|
||||
<td v-if="userSubAdminGroups.length > 0 && (settings.isAdmin || settings.isDelegatedAdmin)"
|
||||
data-cy-user-list-cell-subadmins
|
||||
class="row__cell row__cell--large row__cell--multiline">
|
||||
<template v-if="editing && (settings.isAdmin || settings.isDelegatedAdmin) && subAdminsGroups.length > 0">
|
||||
<template v-if="editing && (settings.isAdmin || settings.isDelegatedAdmin) && userSubAdminGroups.length > 0">
|
||||
<label class="hidden-visually"
|
||||
:for="'subadmins' + uniqueId">
|
||||
{{ t('settings', 'Set account as admin for') }}
|
||||
|
|
@ -145,15 +147,17 @@
|
|||
:append-to-body="false"
|
||||
:multiple="true"
|
||||
:no-wrap="true"
|
||||
:options="subAdminsGroups"
|
||||
:options="availableSubAdminGroups"
|
||||
:placeholder="t('settings', 'Set account as admin for')"
|
||||
:value="userSubAdminsGroups"
|
||||
:value="userSubAdminGroups"
|
||||
@open="loadGroupDetails"
|
||||
@search="searchGroups"
|
||||
@option:deselected="removeUserSubAdmin"
|
||||
@option:selected="options => addUserSubAdmin(options.at(-1))" />
|
||||
</template>
|
||||
<span v-else-if="!isObfuscated"
|
||||
:title="userSubAdminsGroupsLabels?.length > 40 ? userSubAdminsGroupsLabels : null">
|
||||
{{ userSubAdminsGroupsLabels }}
|
||||
:title="userSubAdminGroupsLabels?.length > 40 ? userSubAdminGroupsLabels : null">
|
||||
{{ userSubAdminGroupsLabels }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
|
|
@ -290,6 +294,8 @@ import UserRowActions from './UserRowActions.vue'
|
|||
|
||||
import UserRowMixin from '../../mixins/UserRowMixin.js'
|
||||
import { isObfuscated, unlimitedQuota } from '../../utils/userUtils.ts'
|
||||
import { formatGroup } from '../../utils/groups.ts'
|
||||
import logger from '../../logger.ts'
|
||||
|
||||
export default {
|
||||
name: 'UserRow',
|
||||
|
|
@ -324,14 +330,6 @@ export default {
|
|||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
groups: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
subAdminsGroups: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
quotaOptions: {
|
||||
type: Array,
|
||||
required: true,
|
||||
|
|
@ -375,6 +373,8 @@ export default {
|
|||
editedDisplayName: this.user.displayname,
|
||||
editedPassword: '',
|
||||
editedMail: this.user.email ?? '',
|
||||
// Cancelable promise for search groups request
|
||||
promise: null,
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -406,13 +406,13 @@ export default {
|
|||
|
||||
userGroupsLabels() {
|
||||
return this.userGroups
|
||||
.map(group => group.name)
|
||||
.map(group => group.name ?? group.id)
|
||||
.join(', ')
|
||||
},
|
||||
|
||||
userSubAdminsGroupsLabels() {
|
||||
return this.userSubAdminsGroups
|
||||
.map(group => group.name)
|
||||
userSubAdminGroupsLabels() {
|
||||
return this.userSubAdminGroups
|
||||
.map(group => group.name ?? group.id)
|
||||
.join(', ')
|
||||
},
|
||||
|
||||
|
|
@ -548,6 +548,46 @@ export default {
|
|||
this.loadingPossibleManagers = false
|
||||
},
|
||||
|
||||
async loadGroupDetails() {
|
||||
this.loading.groups = true
|
||||
try {
|
||||
const { data } = await this.$store.dispatch('getUserGroups', {
|
||||
userId: this.user.id,
|
||||
})
|
||||
const groups = data.ocs?.data?.groups
|
||||
if (!groups) {
|
||||
logger.error(t('settings', 'Failed to load groups with details'))
|
||||
return
|
||||
}
|
||||
this.availableGroups = this.availableGroups.map(availableGroup => groups.find(group => group.id === availableGroup.id) ?? availableGroup)
|
||||
} catch (error) {
|
||||
logger.error(t('settings', 'Failed to load groups with details'), { error })
|
||||
}
|
||||
this.loading.groups = false
|
||||
},
|
||||
|
||||
async searchGroups(query, toggleLoading) {
|
||||
if (this.promise) {
|
||||
this.promise.cancel()
|
||||
}
|
||||
this.loading.groups = true
|
||||
toggleLoading(true)
|
||||
try {
|
||||
this.promise = await searchGroups({
|
||||
search: query,
|
||||
offset: 0,
|
||||
limit: 25,
|
||||
})
|
||||
const groups = (await this.promise).data.ocs?.data?.groups ?? []
|
||||
this.availableGroups = groups.map(formatGroup)
|
||||
} catch (error) {
|
||||
logger.error(t('settings', 'Failed to search groups'), { error })
|
||||
}
|
||||
this.promise = null
|
||||
this.loading.groups = false
|
||||
toggleLoading(false)
|
||||
},
|
||||
|
||||
async searchUserManager(query) {
|
||||
await this.$store.dispatch('searchUsers', { offset: 0, limit: 10, search: query }).then(response => {
|
||||
const users = response?.data ? this.filterManagers(Object.values(response?.data.ocs.data.users)) : []
|
||||
|
|
@ -703,6 +743,7 @@ export default {
|
|||
this.loading = { groups: true, subadmins: true }
|
||||
try {
|
||||
await this.$store.dispatch('addGroup', gid)
|
||||
this.availableGroups.push({ id: gid, name: gid })
|
||||
const userid = this.user.id
|
||||
await this.$store.dispatch('addUserGroup', { userid, gid })
|
||||
} catch (error) {
|
||||
|
|
@ -732,6 +773,7 @@ export default {
|
|||
}
|
||||
try {
|
||||
await this.$store.dispatch('addUserGroup', { userid, gid })
|
||||
this.userGroups.push({ id: group.id, name: group.id })
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
|
|
@ -756,6 +798,7 @@ export default {
|
|||
userid,
|
||||
gid,
|
||||
})
|
||||
this.userGroups = this.userGroups.filter(group => group.id !== gid)
|
||||
this.loading.groups = false
|
||||
// remove user from current list if current list is the removed group
|
||||
if (this.$route.params.selectedGroup === gid) {
|
||||
|
|
@ -780,6 +823,7 @@ export default {
|
|||
userid,
|
||||
gid,
|
||||
})
|
||||
this.userSubAdminGroups.push({ id: group.id, name: group.id })
|
||||
this.loading.subadmins = false
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
|
@ -801,6 +845,7 @@ export default {
|
|||
userid,
|
||||
gid,
|
||||
})
|
||||
this.userSubAdminGroups = this.userSubAdminGroups.filter(group => group.id !== gid)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -13,14 +13,6 @@ export default {
|
|||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
groups: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
subAdminsGroups: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
quotaOptions: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
|
|
@ -39,33 +31,6 @@ export default {
|
|||
return this.$store.getters.getShowConfig
|
||||
},
|
||||
|
||||
/* GROUPS MANAGEMENT */
|
||||
userGroups() {
|
||||
const userGroups = this.groups.filter(group => this.user.groups.includes(group.id))
|
||||
return userGroups
|
||||
},
|
||||
userSubAdminsGroups() {
|
||||
const userSubAdminsGroups = this.subAdminsGroups.filter(group => this.user.subadmin.includes(group.id))
|
||||
return userSubAdminsGroups
|
||||
},
|
||||
availableGroups() {
|
||||
return this.groups.map((group) => {
|
||||
// clone object because we don't want
|
||||
// to edit the original groups
|
||||
const groupClone = Object.assign({}, group)
|
||||
|
||||
// two settings here:
|
||||
// 1. user NOT in group but no permission to add
|
||||
// 2. user is in group but no permission to remove
|
||||
groupClone.$isDisabled
|
||||
= (group.canAdd === false
|
||||
&& !this.user.groups.includes(group.id))
|
||||
|| (group.canRemove === false
|
||||
&& this.user.groups.includes(group.id))
|
||||
return groupClone
|
||||
})
|
||||
},
|
||||
|
||||
/* QUOTA MANAGEMENT */
|
||||
usedSpace() {
|
||||
if (this.user.quota.used) {
|
||||
|
|
|
|||
|
|
@ -463,6 +463,24 @@ const actions = {
|
|||
.catch((error) => context.commit('API_FAILURE', error))
|
||||
},
|
||||
|
||||
/**
|
||||
* Get user groups
|
||||
*
|
||||
* @param {object} context store context
|
||||
* @param {object} options destructuring object
|
||||
* @param {number} options.userId User id
|
||||
* @return {Promise}
|
||||
*/
|
||||
async getUserGroups(context, { userId }) {
|
||||
const url = generateOcsUrl('cloud/users/{userId}/groups/details', { userId })
|
||||
try {
|
||||
const response = await api.get(url)
|
||||
return response
|
||||
} catch (error) {
|
||||
context.commit('API_FAILURE', error)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all users with full details
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue