aboutsummaryrefslogtreecommitdiffstats
path: root/apps/settings
diff options
context:
space:
mode:
authorPytal <24800714+Pytal@users.noreply.github.com>2023-10-11 11:54:15 -0700
committerGitHub <noreply@github.com>2023-10-11 11:54:15 -0700
commit228b21f3fa4a72740c97205147bf40bfe0c3ea30 (patch)
treeb208a9eead213d4a30b76a31fd3a3768ffcabc91 /apps/settings
parent827515d9601e5fe4c4592a3279155e2a403436fa (diff)
parent4386803ae8c385f1c8506a95d953b0168d59731f (diff)
downloadnextcloud-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.vue150
-rw-r--r--apps/settings/src/store/users.js2
-rw-r--r--apps/settings/src/views/Users.vue99
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