diff options
author | Pytal <24800714+Pytal@users.noreply.github.com> | 2023-10-11 11:54:15 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-11 11:54:15 -0700 |
commit | 228b21f3fa4a72740c97205147bf40bfe0c3ea30 (patch) | |
tree | b208a9eead213d4a30b76a31fd3a3768ffcabc91 /apps/settings | |
parent | 827515d9601e5fe4c4592a3279155e2a403436fa (diff) | |
parent | 4386803ae8c385f1c8506a95d953b0168d59731f (diff) | |
download | nextcloud-server-228b21f3fa4a72740c97205147bf40bfe0c3ea30.tar.gz nextcloud-server-228b21f3fa4a72740c97205147bf40bfe0c3ea30.zip |
Merge pull request #40110 from nextcloud/enh/a11y/add-group
Diffstat (limited to 'apps/settings')
-rw-r--r-- | apps/settings/src/components/GroupListItem.vue | 150 | ||||
-rw-r--r-- | apps/settings/src/store/users.js | 2 | ||||
-rw-r--r-- | apps/settings/src/views/Users.vue | 99 |
3 files changed, 161 insertions, 90 deletions
diff --git a/apps/settings/src/components/GroupListItem.vue b/apps/settings/src/components/GroupListItem.vue index 239a48a5d5f..cba0b7b3748 100644 --- a/apps/settings/src/components/GroupListItem.vue +++ b/apps/settings/src/components/GroupListItem.vue @@ -21,56 +21,101 @@ --> <template> - <NcAppNavigationItem :key="id" - :exact="true" - :name="name" - :to="{ name: 'group', params: { selectedGroup: encodeURIComponent(id) } }" - :loading="loadingRenameGroup" - :menu-open="openGroupMenu" - @update:menuOpen="handleGroupMenuOpen"> - <template #icon> - <AccountGroup :size="20" /> - </template> - <template #counter> - <NcCounterBubble v-if="count" - :type="active ? 'highlighted' : undefined"> - {{ count }} - </NcCounterBubble> - </template> - <template #actions> - <NcActionInput v-if="id !== 'admin' && id !== 'disabled' && settings.isAdmin" - ref="displayNameInput" - icon="icon-edit" - :trailing-button-label="t('settings', 'Submit')" - type="text" - :value="name" - :label=" t('settings', 'Rename group')" - @submit="renameGroup(id)" /> - <NcActionButton v-if="id !== 'admin' && id !== 'disabled' && settings.isAdmin" - icon="icon-delete" - @click="removeGroup(id)"> - {{ t('settings', 'Remove group') }} - </NcActionButton> - </template> - </NcAppNavigationItem> + <Fragment> + <NcModal v-if="showRemoveGroupModal" + @close="showRemoveGroupModal = false"> + <div class="modal__content"> + <h2 class="modal__header"> + {{ t('settings', 'Please confirm the group removal') }} + </h2> + <NcNoteCard type="warning" + show-alert> + {{ t('settings', 'You are about to remove the group "{group}". The users will NOT be deleted.', { group: name }) }} + </NcNoteCard> + <div class="modal__button-row"> + <NcButton type="secondary" + @click="showRemoveGroupModal = false"> + {{ t('settings', 'Cancel') }} + </NcButton> + <NcButton type="primary" + @click="removeGroup"> + {{ t('settings', 'Confirm') }} + </NcButton> + </div> + </div> + </NcModal> + + <NcAppNavigationItem :key="id" + :exact="true" + :name="name" + :to="{ name: 'group', params: { selectedGroup: encodeURIComponent(id) } }" + :loading="loadingRenameGroup" + :menu-open="openGroupMenu" + @update:menuOpen="handleGroupMenuOpen"> + <template #icon> + <AccountGroup :size="20" /> + </template> + <template #counter> + <NcCounterBubble v-if="count" + :type="active ? 'highlighted' : undefined"> + {{ count }} + </NcCounterBubble> + </template> + <template #actions> + <NcActionInput v-if="id !== 'admin' && id !== 'disabled' && settings.isAdmin" + ref="displayNameInput" + :trailing-button-label="t('settings', 'Submit')" + type="text" + :value="name" + :label=" t('settings', 'Rename group')" + @submit="renameGroup(id)"> + <template #icon> + <Pencil :size="20" /> + </template> + </NcActionInput> + <NcActionButton v-if="id !== 'admin' && id !== 'disabled' && settings.isAdmin" + @click="showRemoveGroupModal = true"> + <template #icon> + <Delete :size="20" /> + </template> + {{ t('settings', 'Remove group') }} + </NcActionButton> + </template> + </NcAppNavigationItem> + </Fragment> </template> <script> +import { Fragment } from 'vue-frag' + import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' import NcActionInput from '@nextcloud/vue/dist/Components/NcActionInput.js' import NcAppNavigationItem from '@nextcloud/vue/dist/Components/NcAppNavigationItem.js' +import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble.js' +import NcModal from '@nextcloud/vue/dist/Components/NcModal.js' +import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js' import AccountGroup from 'vue-material-design-icons/AccountGroup.vue' +import Delete from 'vue-material-design-icons/Delete.vue' +import Pencil from 'vue-material-design-icons/Pencil.vue' + +import { showError } from '@nextcloud/dialogs' export default { name: 'GroupListItem', components: { AccountGroup, + Delete, + Fragment, NcActionButton, NcActionInput, NcAppNavigationItem, + NcButton, NcCounterBubble, + NcModal, + NcNoteCard, + Pencil, }, props: { /** @@ -106,6 +151,7 @@ export default { return { loadingRenameGroup: false, openGroupMenu: false, + showRemoveGroupModal: false, } }, computed: { @@ -144,18 +190,36 @@ export default { this.loadingRenameGroup = false } }, - removeGroup(groupid) { - // TODO migrate to a vue js confirm dialog component - OC.dialogs.confirm( - t('settings', 'You are about to remove the group {group}. The users will NOT be deleted.', { group: groupid }), - t('settings', 'Please confirm the group removal '), - (success) => { - if (success) { - this.$store.dispatch('removeGroup', groupid) - } - }, - ) + async removeGroup() { + try { + await this.$store.dispatch('removeGroup', this.id) + this.showRemoveGroupModal = false + } catch (error) { + showError(t('settings', 'Failed to remove group "{group}"', { group: this.name })) + } }, }, } </script> + +<style lang="scss" scoped> +.modal { + &__header { + margin: 0; + } + + &__content { + display: flex; + flex-direction: column; + align-items: center; + padding: 20px; + gap: 4px 0; + } + + &__button-row { + display: flex; + width: 100%; + justify-content: space-between; + } +} +</style> diff --git a/apps/settings/src/store/users.js b/apps/settings/src/store/users.js index a339ccfdfa2..01e3ab8f04e 100644 --- a/apps/settings/src/store/users.js +++ b/apps/settings/src/store/users.js @@ -101,7 +101,7 @@ const mutations = { id: gid, name: displayName, }) - state.groups.push(group) + state.groups.unshift(group) state.groups = orderGroups(state.groups, state.orderBy) } catch (e) { console.error('Can\'t create group', e) diff --git a/apps/settings/src/views/Users.vue b/apps/settings/src/views/Users.vue index 9a32ca48168..13a7d46d256 100644 --- a/apps/settings/src/views/Users.vue +++ b/apps/settings/src/views/Users.vue @@ -22,7 +22,7 @@ <template> <Fragment> - <NcContent app-name="settings" :navigation-class="{ 'icon-loading': loadingAddGroup }"> + <NcContent app-name="settings"> <NcAppNavigation> <NcAppNavigationNew button-id="new-user-button" :text="t('settings','New user')" @@ -36,18 +36,6 @@ </NcAppNavigationNew> <template #list> - <NcAppNavigationNewItem id="addgroup" - ref="addGroup" - :edit-placeholder="t('settings', 'Enter group name')" - :editable="true" - :loading="loadingAddGroup" - :name="t('settings', 'Add group')" - @click="showAddGroupForm" - @new-item="createGroup"> - <template #icon> - <Plus :size="20" /> - </template> - </NcAppNavigationNewItem> <NcAppNavigationItem id="everyone" :exact="true" :name="t('settings', 'Active users')" @@ -61,6 +49,7 @@ </NcCounterBubble> </template> </NcAppNavigationItem> + <NcAppNavigationItem v-if="settings.isAdmin" id="admin" :exact="true" @@ -92,7 +81,32 @@ </template> </NcAppNavigationItem> - <NcAppNavigationCaption v-if="groupList.length > 0" :name="t('settings', 'Groups')" /> + <NcAppNavigationCaption :name="t('settings', 'Groups')" + :disabled="loadingAddGroup" + :aria-label="loadingAddGroup ? t('settings', 'Creating group …') : t('settings', 'Create group')" + force-menu + :open.sync="isAddGroupOpen"> + <template #actionsTriggerIcon> + <NcLoadingIcon v-if="loadingAddGroup" /> + <Plus v-else :size="20" /> + </template> + <template #actions> + <NcActionText> + <template #icon> + <AccountGroup :size="20" /> + </template> + {{ t('settings', 'Create group') }} + </NcActionText> + <NcActionInput :label="t('settings', 'Group name')" + :label-outside="false" + :disabled="loadingAddGroup" + :value.sync="newGroupName" + :error="hasAddGroupError" + :helper-text="hasAddGroupError ? t('settings', 'Please enter a valid group name') : ''" + @submit="createGroup" /> + </template> + </NcAppNavigationCaption> + <GroupListItem v-for="group in groupList" :id="group.id" :key="group.id" @@ -127,15 +141,19 @@ import Vue from 'vue' import VueLocalStorage from 'vue-localstorage' import { Fragment } from 'vue-frag' +import { translate as t } from '@nextcloud/l10n' +import { showError } from '@nextcloud/dialogs' +import NcActionInput from '@nextcloud/vue/dist/Components/NcActionInput.js' +import NcActionText from '@nextcloud/vue/dist/Components/NcActionText.js' import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent.js' import NcAppNavigation from '@nextcloud/vue/dist/Components/NcAppNavigation.js' import NcAppNavigationCaption from '@nextcloud/vue/dist/Components/NcAppNavigationCaption.js' import NcAppNavigationItem from '@nextcloud/vue/dist/Components/NcAppNavigationItem.js' import NcAppNavigationNew from '@nextcloud/vue/dist/Components/NcAppNavigationNew.js' -import NcAppNavigationNewItem from '@nextcloud/vue/dist/Components/NcAppNavigationNewItem.js' import NcContent from '@nextcloud/vue/dist/Components/NcContent.js' import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble.js' +import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js' import AccountGroup from 'vue-material-design-icons/AccountGroup.vue' import AccountOff from 'vue-material-design-icons/AccountOff.vue' @@ -158,14 +176,16 @@ export default { Cog, Fragment, GroupListItem, + NcActionInput, + NcActionText, NcAppContent, NcAppNavigation, NcAppNavigationCaption, NcAppNavigationItem, NcAppNavigationNew, - NcAppNavigationNewItem, NcContent, NcCounterBubble, + NcLoadingIcon, Plus, ShieldAccount, UserList, @@ -183,7 +203,10 @@ export default { return { // temporary value used for multiselect change externalActions: [], + newGroupName: '', + isAddGroupOpen: false, loadingAddGroup: false, + hasAddGroupError: false, isDialogOpen: false, } }, @@ -261,6 +284,8 @@ export default { }, methods: { + t, + showNewUserMenu() { this.$store.commit('setShowConfig', { key: 'showNewUserForm', @@ -287,43 +312,30 @@ export default { /** * Create a new group - * - * @param {string} gid The group id */ - async createGroup(gid) { - // group is not valid - if (gid.trim() === '') { + async createGroup() { + this.hasAddGroupError = false + const groupId = this.newGroupName.trim() + if (groupId === '') { + this.hasAddGroupError = true return } + this.isAddGroupOpen = false + this.loadingAddGroup = true try { - this.loadingAddGroup = true - await this.$store.dispatch('addGroup', gid.trim()) - - this.hideAddGroupForm() + await this.$store.dispatch('addGroup', groupId) await this.$router.push({ name: 'group', params: { - selectedGroup: encodeURIComponent(gid.trim()), + selectedGroup: encodeURIComponent(groupId), }, }) + this.newGroupName = '' } catch { - this.showAddGroupForm() - } finally { - this.loadingAddGroup = false + showError(t('settings', 'Failed to create group')) } - }, - - showAddGroupForm() { - this.$refs.addGroup.newItemActive = true - this.$nextTick(() => { - this.$refs.addGroup.$refs.newItemInput.focusInput() - }) - }, - - hideAddGroupForm() { - this.$refs.addGroup.newItemActive = false - this.$refs.addGroup.newItemValue = '' + this.loadingAddGroup = false }, /** @@ -362,11 +374,6 @@ export default { max-height: 100%; } -// force hiding the editing action for the add group entry -.app-navigation__list #addgroup::v-deep .app-navigation-entry__utils { - display: none; -} - .app-navigation-entry__settings { height: auto !important; // Prevent shrinking or growing |