07 — Component Library (RBAC Module)
- 1.
PermissionMatrix(hero component) - 2.
PermissionGroupSection - 3.
PermissionChip - 4.
RoleRow - 5.
RoleBadge/SystemRoleBadge - 6.
MemberTile - 7.
MemberStatusBadge - 8.
RolePickerChips - 9.
UserSearchPicker - 10.
AuditRow/AuditFilterBar - 11.
PermissionSummary(read-mode group list) - 12. Shared-component reuse map
Module-specific components. All base widgets (cards, lists, chips, dialogs, sheets, menus, skeletons, states) come from 00-shared/03; this file adds the RBAC layer. Every component is derived from schema fields (
role.schema.ts,organization-member.schema.ts) and the guard model (rbac.guard.ts).
1. PermissionMatrix (hero component)
- Purpose: render + edit the full permission catalog for one role (S3).
- Props:
permissions(catalog fromGET /rbac/permissions),selected(Set of granted perm strings),onChanged(Set<String>),searchQuery,readOnly,compact. - Structure: 26
PermissionGroupSections (grouping table in 06 §3), each with tri-stateCheckbox(none/some/all) +WrapofPermissionChips; optionalAppSearchBar(owned by parent); live countAppBadge "{sel} of 95". - Behaviour: chip tap → toggle; group checkbox → toggle all; search → filter
sections (0-match sections collapse);
readOnly→ chips render as plain labels withSemantics(label: "granted"); no server calls until save (single PATCH,rbac.service.ts:96). - Flutter: stateful widget owning
Set<String> selected+Map<String,bool> groupState; sections =ListView.builderchildren (lazy); chips =FilterChipwithvisualDensity: compact;RepaintBoundaryper section (see 15 §2). - Golden: phone/tablet/desktop × light/dark × readOnly/editable.
2. PermissionGroupSection
- Header row: group label (
titleSmall), tri-stateCheckbox,"{k}/{n}"counter (labelSmall); bodyWrap(spacing:8, runSpacing:8)of chips. Semantics(headers:)on header; tri-state announced.
3. PermissionChip
FilterChip-like; label = full permission string (bodySmall,monofeel), selected =primaryContainer/onPrimaryContainer; unselected =surfaceVariant.- Tooltip: humanized name
(proposed), e.g.payments.reconcile→ "Reconcile payments" (i18n keyperm.payments.reconcile); falls back to raw string. - A11y:
Semantics(checked: selected, label: '<perm>').
4. RoleRow
AppListTile-based list row:AppAvatar(initials,primaryContainer), title = role name, subtitle = slug (mono) + description ellipsized, trailing =AppBadge"System"/"{n} perms" +AppMenu(Edit/Delete for custom; disabled for system).- Sort:
priority desc(rbac.service.ts:76) — provided pre-sorted by parent.
5. RoleBadge / SystemRoleBadge
AppBadgevariants:System(outlined, tooltip "Locked — can't be edited"),Custom, and permission-count badge"{n} perms". System badge always onisSystem:trueroles (role.schema.ts:78-79).
6. MemberTile
AppListTile:AppAvatar48 (photo/initials from merged user profile, OQ-R7), title displayName (fallbackuserIdmono), subtitle = email + "Joined {date}" (organization-member.schema.ts:30-31), trailing = role chips +AppMenu(Edit roles / Remove — admin only).- Role chips = read-only
AppChips(tap no-op, tooltip "Managed in role editor"); unknown slug renders raw.
7. MemberStatusBadge
AppBadgefromMemberStatus(organization-member.schema.ts:7-11):active→ success (secondary),invited→tertiary(info),suspended→error. Render-only: server produces onlyactivetoday (OQ-R3).
8. RolePickerChips
- Multi-select
FilterChipwrap fromGET /rbac/roles(priority order); used in S5 (add/edit member). Props:roles,selected,onChanged. System roles get a tiny lock glyph (still selectable — e.g. assigningteacher).
9. UserSearchPicker
AppSearchBar-driven result list (user.read),AppListTilerows (avatar, name, email); single-select with check; props:onPicked(User),preselected?.
10. AuditRow / AuditFilterBar
AuditRow: action (labelLarge), entityType · actorId (monobodySmall), timestamp (relative,bodySmall); tap → copies requestId(proposed).AuditFilterBar: threeAppDropdowns (action, entityType, actorId) + clear button; map toaudit.controller.ts:20-25query params; RBAC presets(proposed)(OQ-R8).
11. PermissionSummary (read-mode group list)
- Compact read-only block for S2: group label + granted
PermissionChips (or "None in this group"). ReusesPermissionGroupSectioninreadOnly.
12. Shared-component reuse map
| Need | Shared component (00-shared/03) |
|---|---|
| Loading | AppSkeleton (list/card), AppProgress |
| Empty / error / offline | AppEmptyState, AppErrorState, AppOfflineBanner |
| Feedback | AppSnackbar, AppBanner (system-role info, 409 conflict) |
| Inputs | AppTextField, AppDropdown, AppSearchBar, AppCheckbox |
| Display | AppCard, AppAvatar, AppBadge, AppSectionHeader, AppInfoRow |
| Actions | AppFAB (Roles/Members lists), AppButton, AppDialog (delete/self-removal confirm), AppBottomSheet (S5), AppMenu (row actions) |