+9
-7
atproto-notifications/src/pages/Admin.tsx
+9
-7
atproto-notifications/src/pages/Admin.tsx
···
127
127
credentials
128
128
ok={accounts => accounts.length > 0 ? (
129
129
<ul>
130
-
{accounts.map(({ did, first_seen, role }) => (
131
-
<li key={did}>
132
-
<Account did={did} firstSeen={first_seen} role={role} />
130
+
{accounts.map(info => (
131
+
<li key={info.did}>
132
+
<Account {...info} />
133
133
</li>
134
134
))}
135
135
</ul>
···
141
141
);
142
142
}
143
143
144
-
function Account({ did, firstSeen, role }) {
144
+
function Account({ did, first_seen, role, active_subs, total_pushes, last_push }) {
145
145
return (
146
146
<p>
147
147
<Handle did={did} />
148
-
{', '}
149
-
"{role}"
148
+
{' '}
149
+
({active_subs} subs, {total_pushes} pushes, latest <ReactTimeAgo date={new Date(last_push)} locale="en-US" />)
150
+
<br/>
151
+
joined <ReactTimeAgo date={new Date(first_seen)} locale="en-US" />
150
152
{', '}
151
-
<ReactTimeAgo date={new Date(firstSeen)} locale="en-US" />
153
+
role: <code>{role}</code>
152
154
</p>
153
155
);
154
156
}
+6
-1
server/db.js
+6
-1
server/db.js
···
131
131
this.#stmt_admin_secret_accounts = db.prepare(
132
132
`select did,
133
133
unixepoch(first_seen) * 1000 as 'first_seen',
134
-
role
134
+
role,
135
+
count(*) as 'active_subs',
136
+
sum(p.total_pushes) as 'total_pushes',
137
+
unixepoch(max(p.last_push)) * 1000 as 'last_push'
135
138
from accounts
139
+
join push_subs p on (p.account_did = did)
136
140
where secret_password = ?
141
+
group by did
137
142
order by first_seen desc`);
138
143
139
144
this.#transactionally = t => db.transaction(t).immediate();