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