#238 [admin] optimise the list of users, pagination and all

This commit is contained in:
Avris 2021-11-26 17:08:10 +01:00
parent 846ddfeea0
commit b9a9524f1d
2 changed files with 43 additions and 37 deletions

View File

@ -48,8 +48,7 @@
<template v-slot:row="s">
<td>
<Avatar :user="s.el" dsize="2rem"/>
{{s.el.username}}
<a :href="'https://pronouns.page/@ + s.el.username'">@{{s.el.username}}</a>
</td>
<td>
<p>
@ -57,11 +56,13 @@
{{s.el.email}}
</a>
</p>
<!--
<ul v-if="s.el.socialConnections.length" class="list-inline">
<li v-for="conn in s.el.socialConnections" class="list-inline-item">
<Icon :v="socialProviders[conn].icon || conn" set="b"/>
</li>
</ul>
-->
</td>
<td>
<Roles :user="s.el"/>
@ -201,9 +202,12 @@
return {
socialProviders,
userFilter: '',
userFilterDelayed: '',
userFilterDelayHandle: undefined,
localeFilter: true,
adminsFilter: false,
users: undefined,
visibleUsers: [],
}
},
async asyncData({ app, store }) {
@ -225,7 +229,10 @@
methods: {
async loadUsers() {
if (this.users === undefined) {
this.users = await this.$axios.$get(`/admin/users`);
this.users = (await this.$axios.$get(`/admin/users`)).map(u => {
u.profiles = u.profiles ? u.profiles.split(',') : [];
return u;
});
}
},
async handleReport(id) {
@ -236,18 +243,18 @@
return r;
});
},
},
computed: {
visibleUsers() {
calcVisibleUsers() {
if (this.users === undefined) {
return [];
}
return Object.values(this.users).filter(u =>
u.username.toLowerCase().includes(this.userFilter.toLowerCase())
return this.users.filter(u =>
u.username.toLowerCase().includes(this.userFilterDelayed.toLowerCase())
&& (!this.adminsFilter || u.roles !== '')
&& (!this.localeFilter || u.profiles.includes(this.config.locale))
);
},
},
computed: {
profilesByLocale() {
const r = {};
for (let locale of Object.values(this.stats.locales).sort((a, b) => b.profiles - a.profiles)) {
@ -256,6 +263,29 @@
return r;
},
},
watch: {
userFilter() {
if (this.userFilterDelayHandle !== undefined) {
clearInterval(this.userFilterDelayHandle);
}
this.userFilterDelayHandle = setTimeout(() => {
this.userFilterDelayed = this.userFilter;
}, 500);
},
userFilterDelayed() {
this.visibleUsers = this.calcVisibleUsers();
},
localeFilter() {
this.visibleUsers = this.calcVisibleUsers();
},
adminsFilter() {
this.visibleUsers = this.calcVisibleUsers();
},
users() {
this.visibleUsers = this.calcVisibleUsers();
},
},
head() {
return head({
title: this.$t('admin.header'),

View File

@ -74,38 +74,14 @@ router.get('/admin/users', handleErrorAsync(async (req, res) => {
}
const users = await req.db.all(SQL`
SELECT u.id, u.username, u.email, u.roles, u.avatarSource, p.locale
SELECT u.id, u.username, u.email, u.roles, u.avatarSource, group_concat(p.locale) AS profiles
FROM users u
LEFT JOIN profiles p ON p.userId = u.id
GROUP BY u.id
ORDER BY u.id DESC
`);
const authenticators = await req.db.all(SQL`
SELECT userId, type FROM authenticators
WHERE type IN (`.append(Object.keys(socialLoginConfig).map(k => `'${k}'`).join(',')).append(SQL`)
AND (validUntil IS NULL OR validUntil > ${now()})
`));
const groupedUsers = {};
for (let user of users) {
if (groupedUsers[user.id] === undefined) {
groupedUsers[user.id] = {
...user,
locale: undefined,
profiles: user.locale ? [user.locale] : [],
avatar: await avatar(req.db, user),
socialConnections: [],
}
} else {
groupedUsers[user.id].profiles.push(user.locale);
}
}
for (let auth of authenticators) {
groupedUsers[auth.userId].socialConnections.push(auth.type);
}
return res.json(groupedUsers);
return res.json(users);
}));
router.get('/admin/stats', handleErrorAsync(async (req, res) => {