diff --git a/client/components/tables/UsersTable.vue b/client/components/tables/UsersTable.vue index 88323a74..cfcf3f47 100644 --- a/client/components/tables/UsersTable.vue +++ b/client/components/tables/UsersTable.vue @@ -19,9 +19,13 @@ {{ user.type }} -
-

Listening: {{ usersOnline[user.id].session.libraryItem.media.metadata.title || '' }}

-

Last: {{ usersOnline[user.id].mostRecent.media.metadata.title }}

+
+

Listening: {{ usersOnline[user.id].session.displayTitle || '' }}

+

{{ getDeviceInfoString(usersOnline[user.id].session.deviceInfo) }}

+
+
+

Last: {{ user.latestSession.displayTitle || '' }}

+

{{ getDeviceInfoString(user.latestSession.deviceInfo) }}

@@ -83,6 +87,12 @@ export default { } }, methods: { + getDeviceInfoString(deviceInfo) { + if (!deviceInfo) return '' + if (deviceInfo.manufacturer && deviceInfo.model) return `${deviceInfo.manufacturer} ${deviceInfo.model}` + + return `${deviceInfo.osName || 'Unknown'} ${deviceInfo.osVersion || ''} ${deviceInfo.browserName || ''}` + }, deleteUserClick(user) { if (this.isDeletingUser) return if (confirm(this.$getString('MessageRemoveUserWarning', [user.username]))) { @@ -114,11 +124,12 @@ export default { }, loadUsers() { this.$axios - .$get('/api/users') + .$get('/api/users?include=latestSession') .then((res) => { this.users = res.users.sort((a, b) => { return a.createdAt - b.createdAt }) + console.log('Loaded users', this.users) }) .catch((error) => { console.error('Failed', error) diff --git a/server/controllers/UserController.js b/server/controllers/UserController.js index 14635bb1..97c08cea 100644 --- a/server/controllers/UserController.js +++ b/server/controllers/UserController.js @@ -8,12 +8,24 @@ const { getId, toNumber } = require('../utils/index') class UserController { constructor() { } - findAll(req, res) { + async findAll(req, res) { if (!req.user.isAdminOrUp) return res.sendStatus(403) const hideRootToken = !req.user.isRoot + + const includes = (req.query.include || '').split(',').map(i => i.trim()) + + // Minimal toJSONForBrowser does not include mediaProgress and bookmarks + const users = this.db.users.map(u => u.toJSONForBrowser(hideRootToken, true)) + + if (includes.includes('latestSession')) { + for (const user of users) { + const userSessions = await this.db.selectUserSessions(user.id) + user.latestSession = userSessions.sort((a, b) => b.updatedAt - a.updatedAt).shift() || null + } + } + res.json({ - // Minimal toJSONForBrowser does not include mediaProgress and bookmarks - users: this.db.users.map(u => u.toJSONForBrowser(hideRootToken, true)) + users }) } diff --git a/server/objects/PlaybackSession.js b/server/objects/PlaybackSession.js index 232487f4..db4ebb61 100644 --- a/server/objects/PlaybackSession.js +++ b/server/objects/PlaybackSession.js @@ -1,6 +1,5 @@ const date = require('../libs/dateAndTime') const { getId } = require('../utils/index') -const { PlayMethod } = require('../utils/constants') const BookMetadata = require('./metadata/BookMetadata') const PodcastMetadata = require('./metadata/PodcastMetadata') const DeviceInfo = require('./DeviceInfo')