diff options
Diffstat (limited to 'apps/settings/src/components')
5 files changed, 42 insertions, 12 deletions
diff --git a/apps/settings/src/components/AppNavigationGroupList.vue b/apps/settings/src/components/AppNavigationGroupList.vue index b32a07bc9b8..5c648a17098 100644 --- a/apps/settings/src/components/AppNavigationGroupList.vue +++ b/apps/settings/src/components/AppNavigationGroupList.vue @@ -57,12 +57,16 @@ </template> <script setup lang="ts"> +import type CancelablePromise from 'cancelable-promise' +import type { IGroup } from '../views/user-types.d.ts' + +import { mdiAccountGroup, mdiPlus } from '@mdi/js' +import { showError } from '@nextcloud/dialogs' +import { t } from '@nextcloud/l10n' +import { useElementVisibility } from '@vueuse/core' import { computed, ref, watch, onBeforeMount } from 'vue' import { Fragment } from 'vue-frag' import { useRoute, useRouter } from 'vue-router/composables' -import { useElementVisibility } from '@vueuse/core' -import { showError } from '@nextcloud/dialogs' -import { mdiAccountGroup, mdiPlus } from '@mdi/js' import NcActionInput from '@nextcloud/vue/components/NcActionInput' import NcActionText from '@nextcloud/vue/components/NcActionText' @@ -137,12 +141,16 @@ watch(groupsSearchQuery, async () => { }) /** Cancelable promise for search groups request */ -const promise = ref(null) +const promise = ref<CancelablePromise<IGroup[]>>() /** * Load groups */ async function loadGroups() { + if (!isAdminOrDelegatedAdmin.value) { + return + } + if (promise.value) { promise.value.cancel() } @@ -163,7 +171,7 @@ async function loadGroups() { } catch (error) { logger.error(t('settings', 'Failed to load groups'), { error }) } - promise.value = null + promise.value = undefined loadingGroups.value = false } diff --git a/apps/settings/src/components/PersonalInfo/FediverseSection.vue b/apps/settings/src/components/PersonalInfo/FediverseSection.vue index 65400ce0e45..043fa6e64b9 100644 --- a/apps/settings/src/components/PersonalInfo/FediverseSection.vue +++ b/apps/settings/src/components/PersonalInfo/FediverseSection.vue @@ -19,7 +19,7 @@ import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.js' import AccountPropertySection from './shared/AccountPropertySection.vue' -const { fediverse } = loadState<AccountProperties>('settings', 'personalInfoParameters', {}) +const { fediverse } = loadState<AccountProperties>('settings', 'personalInfoParameters') const value = ref({ ...fediverse }) const readable = NAME_READABLE_ENUM[fediverse.name] @@ -29,11 +29,18 @@ const readable = NAME_READABLE_ENUM[fediverse.name] * @param text The potential fediverse handle */ function onValidate(text: string): boolean { + // allow to clear the value + if (text === '') { + return true + } + + // check its in valid format const result = text.match(/^@?([^@/]+)@([^@/]+)$/) if (result === null) { return false } + // check its a valid URL try { return URL.parse(`https://${result[2]}/`) !== null } catch { diff --git a/apps/settings/src/components/PersonalInfo/TwitterSection.vue b/apps/settings/src/components/PersonalInfo/TwitterSection.vue index 802f96087c2..43d08f81e3f 100644 --- a/apps/settings/src/components/PersonalInfo/TwitterSection.vue +++ b/apps/settings/src/components/PersonalInfo/TwitterSection.vue @@ -19,7 +19,7 @@ import { ref } from 'vue' import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.ts' import AccountPropertySection from './shared/AccountPropertySection.vue' -const { twitter } = loadState<AccountProperties>('settings', 'personalInfoParameters', {}) +const { twitter } = loadState<AccountProperties>('settings', 'personalInfoParameters') const value = ref({ ...twitter }) const readable = NAME_READABLE_ENUM[twitter.name] @@ -29,6 +29,6 @@ const readable = NAME_READABLE_ENUM[twitter.name] * @param text The potential twitter handle */ function onValidate(text: string): boolean { - return text.match(/^@?([a-zA-Z0-9_]{2,15})$/) !== null + return text === '' || text.match(/^@?([a-zA-Z0-9_]{2,15})$/) !== null } </script> diff --git a/apps/settings/src/components/UserList.vue b/apps/settings/src/components/UserList.vue index 5d6bd5f04ee..84c204805cc 100644 --- a/apps/settings/src/components/UserList.vue +++ b/apps/settings/src/components/UserList.vue @@ -350,11 +350,13 @@ export default { setNewUserDefaultGroup(value) { // Is no value set, but user is a line manager we set their group as this is a requirement for line manager if (!value && !this.settings.isAdmin && !this.settings.isDelegatedAdmin) { + const groups = this.$store.getters.getSubAdminGroups // if there are multiple groups we do not know which to add, // so we cannot make the managers life easier by preselecting it. - if (this.groups.length === 1) { - value = this.groups[0].id + if (groups.length === 1) { + this.newUser.groups = [...groups] } + return } if (value) { diff --git a/apps/settings/src/components/Users/NewUserDialog.vue b/apps/settings/src/components/Users/NewUserDialog.vue index 3e50efc2072..19445bc187e 100644 --- a/apps/settings/src/components/Users/NewUserDialog.vue +++ b/apps/settings/src/components/Users/NewUserDialog.vue @@ -61,6 +61,7 @@ :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" @@ -69,7 +70,7 @@ label="name" :close-on-select="false" :multiple="true" - :taggable="true" + :taggable="settings.isAdmin || settings.isDelegatedAdmin" :required="!settings.isAdmin && !settings.isDelegatedAdmin" :create-option="(value) => ({ id: value, name: value, isCreating: true })" @search="searchGroups" @@ -178,7 +179,7 @@ export default { data() { return { - availableGroups: this.$store.getters.getSortedGroups.filter(group => group.id !== '__nc_internal_recent' && group.id !== 'disabled'), + availableGroups: [], possibleManagers: [], // TRANSLATORS This string describes a manager in the context of an organization managerInputLabel: t('settings', 'Manager'), @@ -235,6 +236,13 @@ export default { }, mounted() { + // admins also can assign the system groups + if (this.isAdmin || this.isDelegatedAdmin) { + this.availableGroups = this.$store.getters.getSortedGroups.filter(group => group.id !== '__nc_internal_recent' && group.id !== 'disabled') + } else { + this.availableGroups = [...this.$store.getters.getSubAdminGroups] + } + this.$refs.username?.focus?.() }, @@ -273,6 +281,11 @@ export default { }, async searchGroups(query, toggleLoading) { + if (!this.isAdmin && !this.isDelegatedAdmin) { + // managers cannot search for groups + return + } + if (this.promise) { this.promise.cancel() } |