fix(server): dashboard query (#15195)

#### PR Dependency Tree


* **PR #15195** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Admin dashboard storage history now returns a continuous day-by-day
trend, carrying forward the last known workspace and blob storage values
for days without samples.
* Active member counts for workspace analytics were corrected to reflect
active workspace members.
* **New Features**
* Admin workspace member roles are now returned via a dedicated role
enum, serialized as enum name strings (e.g., `Owner`).
* **UI Improvements**
* Renamed key labels to “Active Members” and “Members and Invitations”;
member roles use pill badges and non-accepted statuses are shown.
* **Tests**
* Added E2E coverage for role enum serialization and strengthened
storage history assertions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-07-05 03:04:05 +08:00
committed by GitHub
parent 7cfedbd49d
commit 296a4c2f81
10 changed files with 451 additions and 149 deletions
@@ -390,6 +390,43 @@ e2e(
}
);
e2e('adminWorkspace should serialize member roles as enum names', async t => {
const admin = await app.create(Mockers.User, {
feature: 'administrator',
});
await app.login(admin);
const owner = await app.create(Mockers.User);
const workspace = await app.create(Mockers.Workspace, {
owner: { id: owner.id },
});
const result = await gql(
`
query AdminWorkspace($id: String!) {
adminWorkspace(id: $id) {
id
members(skip: 0, take: 20) {
id
role
status
}
}
}
`,
{ id: workspace.id }
);
t.falsy(result.errors);
t.is(result.data!.adminWorkspace.id, workspace.id);
t.true(
result.data!.adminWorkspace.members.some(
(member: { id: string; role: string }) =>
member.id === owner.id && member.role === 'Owner'
)
);
});
e2e(
'adminDashboard should carry forward missing sync and storage samples',
async t => {
@@ -524,6 +561,36 @@ e2e(
dashboard.workspaceStorageBytes
);
t.is(blobHistory[blobHistory.length - 1], dashboard.blobStorageBytes);
const baselineResult = await gql(
`
query AdminDashboard($input: AdminDashboardInput) {
adminDashboard(input: $input) {
workspaceStorageHistory {
value
}
blobStorageHistory {
value
}
}
}
`,
{
input: {
storageHistoryDays: 2,
},
}
);
t.falsy(baselineResult.errors);
t.is(
baselineResult.data!.adminDashboard.workspaceStorageHistory[0].value,
workspaceHistory[1]
);
t.is(
baselineResult.data!.adminDashboard.blobStorageHistory[0].value,
blobHistory[1]
);
} finally {
clock.restore();
}