From 94d7b76c525612a6a5d3d61ec8f359c7a7ec66ed Mon Sep 17 00:00:00 2001 From: Kostas Drakontidis Date: Sat, 30 May 2026 05:48:58 +0300 Subject: [PATCH] adminjs session map component --- .../src/api/management/components.ts | 11 ++ .../api/management/components/Dashboard.tsx | 121 ++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 src/officesense_pi/src/api/management/components.ts create mode 100644 src/officesense_pi/src/api/management/components/Dashboard.tsx diff --git a/src/officesense_pi/src/api/management/components.ts b/src/officesense_pi/src/api/management/components.ts new file mode 100644 index 0000000..e2efd62 --- /dev/null +++ b/src/officesense_pi/src/api/management/components.ts @@ -0,0 +1,11 @@ +import { ComponentLoader } from 'adminjs' +import { fileURLToPath } from 'url' +import path from 'path' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +export const componentLoader = new ComponentLoader() + +export const Components = { + Dashboard: componentLoader.add('Dashboard', path.join(__dirname, './components/Dashboard.tsx'), 'components'), +} \ No newline at end of file diff --git a/src/officesense_pi/src/api/management/components/Dashboard.tsx b/src/officesense_pi/src/api/management/components/Dashboard.tsx new file mode 100644 index 0000000..2f9cb18 --- /dev/null +++ b/src/officesense_pi/src/api/management/components/Dashboard.tsx @@ -0,0 +1,121 @@ +import React, { useEffect, useState } from 'react' +import { Box, H2, Text, Loader } from '@adminjs/design-system' +import { ApiClient } from 'adminjs' + +type Session = { + realUserId: string + firstName: string + lastName: string + pseudoId: string + pseudoName: string +} + +const Dashboard = () => { + const [sessions, setSessions] = useState([]) + const [loading, setLoading] = useState(true) + const [updated, setUpdated] = useState('') + + const load = async () => { + try { + const res = await fetch('/admin/map', { credentials: 'include' }) + const data = await res.json() + setSessions(data) + setUpdated(new Date().toLocaleTimeString()) + } catch (e) { + console.error(e) + } finally { + setLoading(false) + } + } + + useEffect(() => { + load() + const interval = setInterval(load, 10000) + return () => clearInterval(interval) + }, []) + + const initials = (first: string, last: string) => + ((first?.[0] ?? '') + (last?.[0] ?? '')).toUpperCase() || '?' + + return ( + + + +

OfficeSense Admin Dashboard

+ Live Redis sessions mapped to registered users +
+ + Updated {updated} + + Refresh + + +
+ + {loading ? ( + + ) : sessions.length === 0 ? ( + No active sessions. + ) : ( + + + + + {['User', 'Real UUID', 'Pseudo UUID', 'Pseudo name'].map(h => ( + + ))} + + + + {sessions.map(s => ( + + + + + + + ))} + +
{h}
+
+
+ {initials(s.firstName, s.lastName)} +
+ {s.firstName} {s.lastName} +
+
{s.realUserId}{s.pseudoId}{s.pseudoName ?? '—'}
+
+ )} +
+ ) +} + +export default Dashboard \ No newline at end of file