diff options
author | Christopher Ng <chrng8@gmail.com> | 2024-08-30 16:29:57 -0700 |
---|---|---|
committer | Christopher Ng <chrng8@gmail.com> | 2024-08-30 16:29:57 -0700 |
commit | fb5dd8a25942de1884fb9c5af2109e5e3098ad43 (patch) | |
tree | 8852f308a92eb5018e9ae4e8f3dcbe54b798a31d | |
parent | 558fbcda7255602fa44e3096a12ea9d9d7e113f1 (diff) | |
download | nextcloud-server-feat/namespace-group-route.tar.gz nextcloud-server-feat/namespace-group-route.zip |
feat(settings): Namespace group routesfeat/namespace-group-route
Signed-off-by: Christopher Ng <chrng8@gmail.com>
-rw-r--r-- | apps/settings/lib/Controller/UsersController.php | 5 | ||||
-rw-r--r-- | apps/settings/src/components/GroupListItem.vue | 6 | ||||
-rw-r--r-- | apps/settings/src/components/UserList.vue | 32 | ||||
-rw-r--r-- | apps/settings/src/components/Users/NewUserDialog.vue | 4 | ||||
-rw-r--r-- | apps/settings/src/composables/useGroupsNavigation.ts | 10 | ||||
-rw-r--r-- | apps/settings/src/router/routes.ts | 19 | ||||
-rw-r--r-- | apps/settings/src/store/users.js | 14 | ||||
-rw-r--r-- | apps/settings/src/views/UserManagement.vue | 27 | ||||
-rw-r--r-- | apps/settings/src/views/UserManagementNavigation.vue | 27 |
9 files changed, 104 insertions, 40 deletions
diff --git a/apps/settings/lib/Controller/UsersController.php b/apps/settings/lib/Controller/UsersController.php index 4ee359b6fe9..8b153a86ca8 100644 --- a/apps/settings/lib/Controller/UsersController.php +++ b/apps/settings/lib/Controller/UsersController.php @@ -170,7 +170,7 @@ class UsersController extends Controller { } $recentUsersGroup = [ - 'id' => '__nc_internal_recent', + 'id' => 'recent', 'name' => $this->l10n->t('Recently active'), 'usercount' => $userCount, ]; @@ -203,7 +203,8 @@ class UsersController extends Controller { /* FINAL DATA */ $serverData = []; // groups - $serverData['groups'] = array_merge_recursive($adminGroup, [$recentUsersGroup, $disabledUsersGroup], $groups); + $serverData['sectionGroups'] = [$recentUsersGroup, $disabledUsersGroup]; + $serverData['groups'] = array_merge($adminGroup, $groups); // Various data $serverData['isAdmin'] = $isAdmin; $serverData['isDelegatedAdmin'] = $isDelegatedAdmin; diff --git a/apps/settings/src/components/GroupListItem.vue b/apps/settings/src/components/GroupListItem.vue index 44b0605c9de..ec5295b82d0 100644 --- a/apps/settings/src/components/GroupListItem.vue +++ b/apps/settings/src/components/GroupListItem.vue @@ -31,7 +31,7 @@ <NcAppNavigationItem :key="id" :exact="true" :name="name" - :to="{ name: 'group', params: { selectedGroup: encodeURIComponent(id) } }" + :to="{ name: 'group', params: { group: encodeURIComponent(id) } }" :loading="loadingRenameGroup" :menu-open="openGroupMenu" @update:menuOpen="handleGroupMenuOpen"> @@ -45,7 +45,7 @@ </NcCounterBubble> </template> <template #actions> - <NcActionInput v-if="id !== 'admin' && id !== 'disabled' && (settings.isAdmin || settings.isDelegatedAdmin)" + <NcActionInput v-if="id !== 'admin' && (settings.isAdmin || settings.isDelegatedAdmin)" ref="displayNameInput" :trailing-button-label="t('settings', 'Submit')" type="text" @@ -56,7 +56,7 @@ <Pencil :size="20" /> </template> </NcActionInput> - <NcActionButton v-if="id !== 'admin' && id !== 'disabled' && (settings.isAdmin || settings.isDelegatedAdmin)" + <NcActionButton v-if="id !== 'admin' && (settings.isAdmin || settings.isDelegatedAdmin)" @click="showRemoveGroupModal = true"> <template #icon> <Delete :size="20" /> diff --git a/apps/settings/src/components/UserList.vue b/apps/settings/src/components/UserList.vue index 228ead554e2..c7dc03526de 100644 --- a/apps/settings/src/components/UserList.vue +++ b/apps/settings/src/components/UserList.vue @@ -113,6 +113,10 @@ export default { type: String, default: null, }, + selectedSection: { + type: String, + default: null, + }, externalActions: { type: Array, default: () => [], @@ -166,17 +170,15 @@ export default { }, filteredUsers() { - if (this.selectedGroup === 'disabled') { + if (this.selectedSection === 'disabled') { return this.users.filter(user => user.enabled === false) } return this.users.filter(user => user.enabled !== false) }, 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)) + .toSorted((a, b) => a.name.localeCompare(b.name)) }, subAdminsGroups() { @@ -234,8 +236,8 @@ export default { }, watch: { - // watch url change and group select - async selectedGroup(val) { + // watch url change and section select + async selectedSection(val) { this.isInitialLoad = true // if selected is the disabled group but it's empty await this.redirectIfDisabled() @@ -244,6 +246,14 @@ export default { this.setNewUserDefaultGroup(val) }, + // watch url change and group select + async selectedGroup(val) { + this.isInitialLoad = true + this.$store.commit('resetUsers') + await this.loadUsers() + this.setNewUserDefaultGroup(val) + }, + filteredUsers(filteredUsers) { logger.debug(`${filteredUsers.length} filtered user(s)`) }, @@ -288,13 +298,13 @@ export default { async loadUsers() { this.loading.users = true try { - if (this.selectedGroup === 'disabled') { + if (this.selectedSection === 'disabled') { await this.$store.dispatch('getDisabledUsers', { offset: this.disabledUsersOffset, limit: this.disabledUsersLimit, search: this.searchQuery, }) - } else if (this.selectedGroup === '__nc_internal_recent') { + } else if (this.selectedSection === 'recent') { await this.$store.dispatch('getRecentUsers', { offset: this.usersOffset, limit: this.usersLimit, @@ -385,9 +395,9 @@ export default { * and we therefore set the usercount to -1 in this specific case */ async redirectIfDisabled() { - const allGroups = this.$store.getters.getGroups - if (this.selectedGroup === 'disabled' - && allGroups.findIndex(group => group.id === 'disabled' && group.usercount === 0) > -1) { + const sectionGroups = this.$store.getters.getSectionGroups + if (this.selectedSection === 'disabled' + && sectionGroups.find(group => group.id === 'disabled' && group.usercount === 0) !== undefined) { // disabled group is empty, redirection to all users this.$router.push({ name: 'users' }) await this.loadUsers() diff --git a/apps/settings/src/components/Users/NewUserDialog.vue b/apps/settings/src/components/Users/NewUserDialog.vue index 2240e75f1d8..40597611f01 100644 --- a/apps/settings/src/components/Users/NewUserDialog.vue +++ b/apps/settings/src/components/Users/NewUserDialog.vue @@ -200,10 +200,8 @@ export default { }, 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)) + .toSorted((a, b) => a.name.localeCompare(b.name)) }, subAdminsGroups() { diff --git a/apps/settings/src/composables/useGroupsNavigation.ts b/apps/settings/src/composables/useGroupsNavigation.ts index 6235088f944..3cad2403ed7 100644 --- a/apps/settings/src/composables/useGroupsNavigation.ts +++ b/apps/settings/src/composables/useGroupsNavigation.ts @@ -27,14 +27,14 @@ function formatGroupMenu(group?: IGroup) { return item } -export const useFormatGroups = (groups: Ref<IGroup[]>|ComputedRef<IGroup[]>) => { +export const useFormatGroups = (sectionGroups: Ref<IGroup[]>|ComputedRef<IGroup[]>, groups: Ref<IGroup[]>|ComputedRef<IGroup[]>) => { /** * All non-disabled non-admin groups */ const userGroups = computed(() => { const formatted = groups.value - // filter out disabled and admin - .filter(group => group.id !== 'disabled' && group.id !== '__nc_internal_recent' && group.id !== 'admin') + // filter out admin group + .filter(group => group.id !== 'admin') // format group .map(group => formatGroupMenu(group)) // remove invalid @@ -50,12 +50,12 @@ export const useFormatGroups = (groups: Ref<IGroup[]>|ComputedRef<IGroup[]>) => /** * The group of disabled users */ - const disabledGroup = computed(() => formatGroupMenu(groups.value.find(group => group.id === 'disabled'))) + const disabledGroup = computed(() => formatGroupMenu(sectionGroups.value.find(group => group.id === 'disabled'))) /** * The group of recent users */ - const recentGroup = computed(() => formatGroupMenu(groups.value.find(group => group.id === '__nc_internal_recent'))) + const recentGroup = computed(() => formatGroupMenu(sectionGroups.value.find(group => group.id === 'recent'))) return { adminGroup, recentGroup, disabledGroup, userGroups } } diff --git a/apps/settings/src/router/routes.ts b/apps/settings/src/router/routes.ts index 7182a606309..ffcd689986d 100644 --- a/apps/settings/src/router/routes.ts +++ b/apps/settings/src/router/routes.ts @@ -20,11 +20,26 @@ const routes: RouteConfig[] = [ default: UserManagement, navigation: UserManagementNavigation, }, - props: true, + props: { + default: true, + navigation: true, + }, children: [ { - path: ':selectedGroup', + path: 'group/:group', name: 'group', + props: { + default: true, + navigation: true, + }, + }, + { + path: ':sectionGroup', + name: 'section', + props: { + default: true, + navigation: true, + }, }, ], }, diff --git a/apps/settings/src/store/users.js b/apps/settings/src/store/users.js index 15c40d77072..9f0f71e69f4 100644 --- a/apps/settings/src/store/users.js +++ b/apps/settings/src/store/users.js @@ -29,6 +29,7 @@ const defaults = { const state = { users: [], + sectionGroups: [], groups: [], orderBy: GroupSorting.UserCount, minPasswordLength: 0, @@ -62,6 +63,9 @@ const mutations = { setPasswordPolicyMinLength(state, length) { state.minPasswordLength = length !== '' ? length : 0 }, + initSectionGroups(state, { sectionGroups }) { + state.sectionGroups = sectionGroups.map(group => Object.assign({}, defaults.group, group)) + }, initGroups(state, { groups, orderBy, userCount }) { state.groups = groups.map(group => Object.assign({}, defaults.group, group)) state.orderBy = orderBy @@ -146,8 +150,8 @@ const mutations = { return } - const recentGroup = state.groups.find(group => group.id === '__nc_internal_recent') - const disabledGroup = state.groups.find(group => group.id === 'disabled') + const recentGroup = state.sectionGroups.find(group => group.id === 'recent') + const disabledGroup = state.sectionGroups.find(group => group.id === 'disabled') switch (actionType) { case 'enable': case 'disable': @@ -241,12 +245,14 @@ const getters = { getUsers(state) { return state.users }, + getSectionGroups(state) { + return state.sectionGroups + }, getGroups(state) { return state.groups }, getSubadminGroups(state) { - // Can't be subadmin of admin, recent, or disabled - return state.groups.filter(group => group.id !== 'admin' && group.id !== '__nc_internal_recent' && group.id !== 'disabled') + return state.groups.filter(group => group.id !== 'admin') }, getSortedGroups(state) { const groups = [...state.groups] diff --git a/apps/settings/src/views/UserManagement.vue b/apps/settings/src/views/UserManagement.vue index d6a681649b8..74d9e647309 100644 --- a/apps/settings/src/views/UserManagement.vue +++ b/apps/settings/src/views/UserManagement.vue @@ -6,6 +6,7 @@ <template> <NcAppContent :page-heading="pageHeading"> <UserList :selected-group="selectedGroupDecoded" + :selected-section="selectedSection" :external-actions="externalActions" /> </NcAppContent> </template> @@ -26,6 +27,17 @@ export default defineComponent({ UserList, }, + props: { + group: { + type: String, + default: null, + }, + sectionGroup: { + type: String, + default: null, + }, + }, + data() { return { // temporary value used for multiselect change @@ -46,15 +58,28 @@ export default defineComponent({ }, selectedGroup() { - return this.$route.params.selectedGroup + if (this.sectionGroup === 'admin') { + return this.sectionGroup + } + return this.group }, selectedGroupDecoded() { return this.selectedGroup ? decodeURIComponent(this.selectedGroup) : null }, + + selectedSection() { + if (this.sectionGroup === 'admin') { + return null + } + return this.sectionGroup + }, }, beforeMount() { + this.$store.commit('initSectionGroups', { + sectionGroups: this.$store.getters.getServerData.sectionGroups, + }) this.$store.commit('initGroups', { groups: this.$store.getters.getServerData.groups, orderBy: this.$store.getters.getServerData.sortGroups, diff --git a/apps/settings/src/views/UserManagementNavigation.vue b/apps/settings/src/views/UserManagementNavigation.vue index 47ecf877589..752339f5283 100644 --- a/apps/settings/src/views/UserManagementNavigation.vue +++ b/apps/settings/src/views/UserManagementNavigation.vue @@ -34,7 +34,8 @@ id="admin" :exact="true" :name="t('settings', 'Admins')" - :to="{ name: 'group', params: { selectedGroup: 'admin' } }"> + :to="{ name: 'section', params: { sectionGroup: 'admin' } }"> + <!-- This is a group but it should be routed to as a section --> <template #icon> <NcIconSvgWrapper :path="mdiShieldAccount" /> </template> @@ -50,13 +51,13 @@ id="recent" :exact="true" :name="t('settings', 'Recently active')" - :to="{ name: 'group', params: { selectedGroup: '__nc_internal_recent' } }"> + :to="{ name: 'section', params: { sectionGroup: 'recent' } }"> <template #icon> <NcIconSvgWrapper :path="mdiHistory" /> </template> <template #counter> <NcCounterBubble v-if="recentGroup?.usercount" - :type="selectedGroupDecoded === '__nc_internal_recent' ? 'highlighted' : undefined"> + :type="selectedSectionGroup === 'recent' ? 'highlighted' : undefined"> {{ recentGroup.usercount }} </NcCounterBubble> </template> @@ -67,12 +68,12 @@ id="disabled" :exact="true" :name="t('settings', 'Disabled accounts')" - :to="{ name: 'group', params: { selectedGroup: 'disabled' } }"> + :to="{ name: 'section', params: { sectionGroup: 'disabled' } }"> <template #icon> <NcIconSvgWrapper :path="mdiAccountOff" /> </template> <template v-if="disabledGroup.usercount > 0" #counter> - <NcCounterBubble :type="selectedGroupDecoded === 'disabled' ? 'highlighted' : undefined"> + <NcCounterBubble :type="selectedSectionGroup === 'disabled' ? 'highlighted' : undefined"> {{ disabledGroup.usercount }} </NcCounterBubble> </template> @@ -151,10 +152,14 @@ import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js' import GroupListItem from '../components/GroupListItem.vue' import UserSettingsDialog from '../components/Users/UserSettingsDialog.vue' import { useStore } from '../store' -import { useRoute, useRouter } from 'vue-router/composables' +import { useRouter } from 'vue-router/composables' import { useFormatGroups } from '../composables/useGroupsNavigation' -const route = useRoute() +const props = defineProps<{ + group?: string, + sectionGroup?: string, +}>() + const router = useRouter() const store = useStore() @@ -162,15 +167,19 @@ const store = useStore() const isDialogOpen = ref(false) /** Current active group in the view - this is URL encoded */ -const selectedGroup = computed(() => route.params?.selectedGroup) +const selectedGroup = computed(() => props.group) /** Current active group - URL decoded */ const selectedGroupDecoded = computed(() => selectedGroup.value ? decodeURIComponent(selectedGroup.value) : null) +/** Current active section in the view */ +const selectedSectionGroup = computed(() => props.sectionGroup) /** Overall user count */ const userCount = computed(() => store.getters.getUserCount) +/** All available sections */ +const sectionGroups = computed(() => store.getters.getSectionGroups) /** All available groups */ const groups = computed(() => store.getters.getSortedGroups) -const { adminGroup, recentGroup, disabledGroup, userGroups } = useFormatGroups(groups) +const { adminGroup, recentGroup, disabledGroup, userGroups } = useFormatGroups(sectionGroups, groups) /** Server settings for current user */ const settings = computed(() => store.getters.getServerData) |