feat(sessions): add detail page, Notification component, and session API improvements

- add SessionDetailPage with breadcrumbs, DescriptionList, status badge, masked token
- add Notification component (info/success/error/warning/note variants) for contextual messages
- use Notification for 404 errors on session and environment detail pages
- add GET /sessions/:id endpoint; sanitize token (head…tail) and strip cookies/localStorage
- change DELETE /sessions/:id to return 204 No Content so client redirect works correctly
- add onRowClick prop to Table for clickable rows; stop propagation on actions column
- update status badges: open=success (green), closed=error (red) on both list and detail
This commit is contained in:
2026-04-09 19:00:16 +03:00
parent 097c747993
commit d342637eb6
14 changed files with 290 additions and 11 deletions
+8 -2
View File
@@ -21,8 +21,11 @@ async function request<T>(path: string, init?: RequestInit): Promise<T> {
const text = await res.text().catch(() => res.statusText);
throw new Error(`${res.status} ${text}`);
}
if (res.status === 204) return undefined as T;
return res.json() as Promise<T>;
const contentLength = res.headers.get('content-length');
if (res.status === 204 || contentLength === '0') return undefined as T;
const text = await res.text();
if (!text) return undefined as T;
return JSON.parse(text) as T;
}
// ── Environments ──────────────────────────────────────────────────────────────
@@ -65,6 +68,9 @@ export const sessions = {
list(page = 1, limit = 50): Promise<PaginatedResponse<Session>> {
return request(`/sessions?page=${page}&limit=${limit}`);
},
get(id: number): Promise<Session> {
return request(`/sessions/${id}`);
},
remove(id: number): Promise<void> {
return request(`/sessions/${id}`, { method: 'DELETE' });
},