From 5cd343cb013670d95925dffd95ecd57f5ae1ce78 Mon Sep 17 00:00:00 2001 From: advplyr Date: Sat, 4 Jun 2022 12:44:42 -0500 Subject: [PATCH] Add:All listening sessions config page --- client/components/app/ConfigSideNav.vue | 16 +- client/components/ui/InputDropdown.vue | 4 +- client/pages/config/sessions.vue | 194 +++++++++++++++++++++ client/pages/config/users/_id/sessions.vue | 2 +- server/Db.js | 9 + server/controllers/SessionController.js | 35 ++++ server/routers/ApiRouter.js | 14 ++ 7 files changed, 261 insertions(+), 13 deletions(-) create mode 100644 client/pages/config/sessions.vue diff --git a/client/components/app/ConfigSideNav.vue b/client/components/app/ConfigSideNav.vue index 2321c4a3..09757ecf 100644 --- a/client/components/app/ConfigSideNav.vue +++ b/client/components/app/ConfigSideNav.vue @@ -38,12 +38,6 @@ export default { userIsAdminOrUp() { return this.$store.getters['user/getIsAdminOrUp'] }, - user() { - return this.$store.state.user.user || {} - }, - userId() { - return this.user.id - }, configRoutes() { if (!this.userIsAdminOrUp) { return [ @@ -70,6 +64,11 @@ export default { title: 'Users', path: '/config/users' }, + { + id: 'config-sessions', + title: 'Sessions', + path: '/config/sessions' + }, { id: 'config-backups', title: 'Backups', @@ -93,11 +92,6 @@ export default { title: 'Your Stats', path: '/config/stats' }) - configRoutes.push({ - id: 'config-users-id-sessions', - title: 'Your Sessions', - path: `/config/users/${this.userId}/sessions` - }) } return configRoutes diff --git a/client/components/ui/InputDropdown.vue b/client/components/ui/InputDropdown.vue index 64dba025..3efd2cf5 100644 --- a/client/components/ui/InputDropdown.vue +++ b/client/components/ui/InputDropdown.vue @@ -42,7 +42,8 @@ export default { editable: { type: Boolean, default: true - } + }, + showAllWhenEmpty: Boolean }, data() { return { @@ -72,6 +73,7 @@ export default { itemsToShow() { if (!this.editable) return this.items if (!this.textInput || this.textInput === this.input) { + if (this.showAllWhenEmpty) return this.items return [] } return this.items.filter((i) => { diff --git a/client/pages/config/sessions.vue b/client/pages/config/sessions.vue new file mode 100644 index 00000000..c2dceae6 --- /dev/null +++ b/client/pages/config/sessions.vue @@ -0,0 +1,194 @@ + + + + + \ No newline at end of file diff --git a/client/pages/config/users/_id/sessions.vue b/client/pages/config/users/_id/sessions.vue index 1c56ce98..3098770c 100644 --- a/client/pages/config/users/_id/sessions.vue +++ b/client/pages/config/users/_id/sessions.vue @@ -17,7 +17,7 @@
-

Listening Sessions ({{ listeningSessions.length }})

+

Listening Sessions

diff --git a/server/Db.js b/server/Db.js index 524fd90f..1a2937af 100644 --- a/server/Db.js +++ b/server/Db.js @@ -428,6 +428,15 @@ class Db { }) } + getAllSessions() { + return this.sessionsDb.select(() => true).then((results) => { + return results.data || [] + }).catch((error) => { + Logger.error('[Db] Failed to select sessions', error) + return [] + }) + } + selectUserSessions(userId) { return this.sessionsDb.select((session) => session.userId === userId).then((results) => { return results.data || [] diff --git a/server/controllers/SessionController.js b/server/controllers/SessionController.js index 9b6d5a5c..2a7ff059 100644 --- a/server/controllers/SessionController.js +++ b/server/controllers/SessionController.js @@ -1,4 +1,5 @@ const Logger = require('../Logger') +const { toNumber } = require('../utils/index') class SessionController { constructor() { } @@ -7,6 +8,40 @@ class SessionController { return res.json(req.session) } + async getAllWithUserData(req, res) { + if (!req.user.isAdminOrUp) { + Logger.error(`[SessionController] getAllWithUserData: Non-admin user requested all session data ${req.user.id}/"${req.user.username}"`) + return res.sendStatus(404) + } + + var listeningSessions = [] + if (req.query.user) { + listeningSessions = await this.getUserListeningSessionsHelper(req.query.user) + } else { + listeningSessions = await this.getAllSessionsWithUserData() + } + + const itemsPerPage = toNumber(req.query.itemsPerPage, 10) || 10 + const page = toNumber(req.query.page, 0) + + const start = page * itemsPerPage + const sessions = listeningSessions.slice(start, start + itemsPerPage) + + const payload = { + total: listeningSessions.length, + numPages: Math.ceil(listeningSessions.length / itemsPerPage), + page, + itemsPerPage, + sessions + } + + if (req.query.user) { + payload.userFilter = req.query.user + } + + res.json(payload) + } + getSession(req, res) { var libraryItem = this.db.getLibraryItem(req.session.libraryItemId) var sessionForClient = req.session.toJSONForClient(libraryItem) diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index aec6f3f0..e9b88c8c 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -174,6 +174,7 @@ class ApiRouter { // // Playback Session Routes // + this.router.get('/sessions', SessionController.getAllWithUserData.bind(this)) this.router.get('/session/:id', SessionController.middleware.bind(this), SessionController.getSession.bind(this)) this.router.post('/session/:id/sync', SessionController.middleware.bind(this), SessionController.sync.bind(this)) this.router.post('/session/:id/close', SessionController.middleware.bind(this), SessionController.close.bind(this)) @@ -310,6 +311,19 @@ class ApiRouter { return userSessions.sort((a, b) => b.updatedAt - a.updatedAt) } + async getAllSessionsWithUserData() { + var sessions = await this.db.getAllSessions() + sessions.sort((a, b) => b.updatedAt - a.updatedAt) + return sessions.map(se => { + var user = this.db.users.find(u => u.id === se.userId) + var _se = { + ...se, + user: user ? { id: user.id, username: user.username } : null + } + return _se + }) + } + async getUserListeningStatsHelpers(userId) { const today = date.format(new Date(), 'YYYY-MM-DD')