Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(settings): Namespace group routes #47652

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions apps/settings/lib/Controller/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public function usersList(): TemplateResponse {
}

$recentUsersGroup = [
'id' => '__nc_internal_recent',
'id' => 'recent',
'name' => $this->l10n->t('Recently active'),
'usercount' => $userCount,
];
Expand Down Expand Up @@ -203,7 +203,8 @@ public function usersList(): TemplateResponse {
/* 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;
Expand Down
6 changes: 3 additions & 3 deletions apps/settings/src/components/GroupListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand All @@ -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"
Expand All @@ -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" />
Expand Down
32 changes: 21 additions & 11 deletions apps/settings/src/components/UserList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ export default {
type: String,
default: null,
},
selectedSection: {
type: String,
default: null,
},
externalActions: {
type: Array,
default: () => [],
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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()
Expand All @@ -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)`)
},
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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()
Expand Down
4 changes: 1 addition & 3 deletions apps/settings/src/components/Users/NewUserDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
10 changes: 5 additions & 5 deletions apps/settings/src/composables/useGroupsNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 }
}
19 changes: 17 additions & 2 deletions apps/settings/src/router/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
],
},
Expand Down
14 changes: 10 additions & 4 deletions apps/settings/src/store/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const defaults = {

const state = {
users: [],
sectionGroups: [],
groups: [],
orderBy: GroupSorting.UserCount,
minPasswordLength: 0,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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':
Expand Down Expand Up @@ -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]
Expand Down
27 changes: 26 additions & 1 deletion apps/settings/src/views/UserManagement.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<template>
<NcAppContent :page-heading="pageHeading">
<UserList :selected-group="selectedGroupDecoded"
:selected-section="selectedSection"
:external-actions="externalActions" />
</NcAppContent>
</template>
Expand All @@ -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
Expand All @@ -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,
Expand Down
27 changes: 18 additions & 9 deletions apps/settings/src/views/UserManagementNavigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
Expand All @@ -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>
Expand Down Expand Up @@ -151,26 +152,34 @@ 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()

/** State of the 'new-account' dialog */
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)
Expand Down
Loading