feat: user invite flow, deactivate/delete, favicon, dashboard loading fix, admin full-width
- Invite flow: admin can invite users by email with role selection; accept-invite page sets password and creates the account; 72-hour token expiry; E2E tests - User deactivate/reactivate/delete: new tRPC procedures + UI buttons; deactivation revokes all active sessions immediately; delete cascades vacation/broadcast records; isActive field added via migration 20260402000000_user_isactive - Auth: block login for inactive users with audit entry - Favicon: SVG favicon + ICO/PNG fallbacks (16, 32, 180, 192, 512px); manifest updated - Dashboard: GridLayout dynamic-import loading skeleton prevents blank dark area on first login before react-grid-layout chunk is cached - Admin users: remove max-w-5xl constraint so table uses full page width - Dev: docker container restart workflow documented in LEARNINGS.md; Prisma generate must run inside the container after schema changes (named node_modules volume) Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -23,10 +23,21 @@ function WidgetFallback() {
|
||||
);
|
||||
}
|
||||
|
||||
function GridLayoutSkeleton() {
|
||||
return (
|
||||
<div className="grid grid-cols-2 gap-3 p-3">
|
||||
{Array.from({ length: 4 }).map((_, i) => (
|
||||
<div key={i} className="h-48 shimmer-skeleton rounded-2xl" />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Dynamic import — no WidthProvider (uses findDOMNode, broken in React 18 strict mode).
|
||||
// We measure container width ourselves via ResizeObserver and pass it as a prop.
|
||||
const GridLayout = dynamic(() => import("react-grid-layout").then((m) => m.Responsive), {
|
||||
ssr: false,
|
||||
loading: () => <GridLayoutSkeleton />,
|
||||
});
|
||||
|
||||
function renderWidget(
|
||||
|
||||
Reference in New Issue
Block a user