diff options
Diffstat (limited to 'apps/settings/src/components/Users/NewUserDialog.vue')
-rw-r--r-- | apps/settings/src/components/Users/NewUserDialog.vue | 116 |
1 files changed, 72 insertions, 44 deletions
diff --git a/apps/settings/src/components/Users/NewUserDialog.vue b/apps/settings/src/components/Users/NewUserDialog.vue index 26e4afbd924..ef401b565fa 100644 --- a/apps/settings/src/components/Users/NewUserDialog.vue +++ b/apps/settings/src/components/Users/NewUserDialog.vue @@ -61,32 +61,36 @@ :required="newUser.password === '' || settings.newUserRequireEmail" /> <div class="dialog__item"> <NcSelect class="dialog__select" + data-test="groups" :input-label="!settings.isAdmin && !settings.isDelegatedAdmin ? t('settings', 'Member of the following groups (required)') : t('settings', 'Member of the following groups')" :placeholder="t('settings', 'Set account groups')" :disabled="loading.groups || loading.all" - :options="canAddGroups" + :options="availableGroups" :value="newUser.groups" label="name" :close-on-select="false" :multiple="true" - :taggable="true" + :taggable="settings.isAdmin || settings.isDelegatedAdmin" :required="!settings.isAdmin && !settings.isDelegatedAdmin" - @input="handleGroupInput" - @option:created="createGroup" /> + :create-option="(value) => ({ id: value, name: value, isCreating: true })" + @search="searchGroups" + @option:created="createGroup" + @option:selected="options => addGroup(options.at(-1))" /> <!-- If user is not admin, they are a subadmin. Subadmins can't create users outside their groups Therefore, empty select is forbidden --> </div> - <div v-if="subAdminsGroups.length > 0" - class="dialog__item"> + <div class="dialog__item"> <NcSelect v-model="newUser.subAdminsGroups" class="dialog__select" :input-label="t('settings', 'Admin of the following groups')" :placeholder="t('settings', 'Set account as admin for …')" - :options="subAdminsGroups" + :disabled="loading.groups || loading.all" + :options="availableGroups" :close-on-select="false" :multiple="true" - label="name" /> + label="name" + @search="searchGroups" /> </div> <div class="dialog__item"> <NcSelect v-model="newUser.quota" @@ -136,11 +140,14 @@ <script> import { formatFileSize, parseFileSize } from '@nextcloud/files' -import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' -import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js' -import NcPasswordField from '@nextcloud/vue/dist/Components/NcPasswordField.js' -import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' -import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js' +import NcButton from '@nextcloud/vue/components/NcButton' +import NcDialog from '@nextcloud/vue/components/NcDialog' +import NcPasswordField from '@nextcloud/vue/components/NcPasswordField' +import NcSelect from '@nextcloud/vue/components/NcSelect' +import NcTextField from '@nextcloud/vue/components/NcTextField' + +import { searchGroups } from '../../service/groups.ts' +import logger from '../../logger.ts' export default { name: 'NewUserDialog', @@ -177,6 +184,8 @@ export default { managerInputLabel: t('settings', 'Manager'), // TRANSLATORS This string describes a manager in the context of an organization managerLabel: t('settings', 'Set line manager'), + // Cancelable promise for search groups request + promise: null, } }, @@ -200,27 +209,12 @@ export default { return this.$store.getters.getPasswordPolicyMinLength }, - groups() { - // data provided php side + remove the recent and disabled groups - return this.$store.getters.getGroups - .filter(group => group.id !== '__nc_internal_recent' && group.id !== 'disabled') - .sort((a, b) => a.name.localeCompare(b.name)) - }, - - subAdminsGroups() { - // data provided php side - return this.$store.getters.getSubadminGroups - }, + availableGroups() { + const groups = (this.settings.isAdmin || this.settings.isDelegatedAdmin) + ? this.$store.getters.getSortedGroups + : this.$store.getters.getSubAdminGroups - canAddGroups() { - // disabled if no permission to add new users to group - return this.groups.map(group => { - // clone object because we don't want - // to edit the original groups - group = Object.assign({}, group) - group.$isDisabled = group.canAdd === false - return group - }) + return groups.filter(group => group.id !== '__nc_internal_recent' && group.id !== 'disabled') }, languages() { @@ -281,13 +275,32 @@ export default { } }, - handleGroupInput(groups) { - /** - * Filter out groups with no id to prevent duplicate selected options - * - * Created groups are added programmatically by `createGroup()` - */ - this.newUser.groups = groups.filter(group => Boolean(group.id)) + async searchGroups(query, toggleLoading) { + if (!this.settings.isAdmin && !this.settings.isDelegatedAdmin) { + // managers cannot search for groups + return + } + + if (this.promise) { + this.promise.cancel() + } + toggleLoading(true) + try { + this.promise = searchGroups({ + search: query, + offset: 0, + limit: 25, + }) + const groups = await this.promise + // Populate store from server request + for (const group of groups) { + this.$store.commit('addGroup', group) + } + } catch (error) { + logger.error(t('settings', 'Failed to search groups'), { error }) + } + this.promise = null + toggleLoading(false) }, /** @@ -300,11 +313,26 @@ export default { this.loading.groups = true try { await this.$store.dispatch('addGroup', gid) - this.newUser.groups.push(this.groups.find(group => group.id === gid)) - this.loading.groups = false + this.newUser.groups.push({ id: gid, name: gid }) } catch (error) { - this.loading.groups = false + logger.error(t('settings', 'Failed to create group'), { error }) + } + this.loading.groups = false + }, + + /** + * Add user to group + * + * @param {object} group Group object + */ + async addGroup(group) { + if (group.isCreating) { + return + } + if (group.canAdd === false) { + return } + this.newUser.groups.push(group) }, /** @@ -318,7 +346,7 @@ export default { const validQuota = OC.Util.computerFileSize(quota) if (validQuota !== null && validQuota >= 0) { // unify format output - quota = formatFileSize(parseFileSize(quota)) + quota = formatFileSize(parseFileSize(quota, true)) this.newUser.quota = { id: quota, label: quota } return this.newUser.quota } |