aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Ng <chrng8@gmail.com>2024-08-30 16:29:57 -0700
committerChristopher Ng <chrng8@gmail.com>2024-08-30 16:29:57 -0700
commitfb5dd8a25942de1884fb9c5af2109e5e3098ad43 (patch)
tree8852f308a92eb5018e9ae4e8f3dcbe54b798a31d
parent558fbcda7255602fa44e3096a12ea9d9d7e113f1 (diff)
downloadnextcloud-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.php5
-rw-r--r--apps/settings/src/components/GroupListItem.vue6
-rw-r--r--apps/settings/src/components/UserList.vue32
-rw-r--r--apps/settings/src/components/Users/NewUserDialog.vue4
-rw-r--r--apps/settings/src/composables/useGroupsNavigation.ts10
-rw-r--r--apps/settings/src/router/routes.ts19
-rw-r--r--apps/settings/src/store/users.js14
-rw-r--r--apps/settings/src/views/UserManagement.vue27
-rw-r--r--apps/settings/src/views/UserManagementNavigation.vue27
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)