Skip to content

feat(dashboard): role-specific tile filtering + server module order (E11.S03)#15

Open
abdout wants to merge 1 commit into
mainfrom
feat/E11-S03-role-tile-filtering
Open

feat(dashboard): role-specific tile filtering + server module order (E11.S03)#15
abdout wants to merge 1 commit into
mainfrom
feat/E11-S03-role-tile-filtering

Conversation

@abdout
Copy link
Copy Markdown
Contributor

@abdout abdout commented May 25, 2026

Summary

  • Introduces HomeTileId (stable per-tile identifier + server-name mapping) and HomeTileVisibility (role → visible-tile matrix) following the hogwarts platform-sidebar config
  • Adds List<HomeTileSpec>.filterAndOrderForRole(role, enabledModules) — filter by role, then reorder by the server's module manifest (case-insensitive; stable fallback)
  • HomeTileSpec carries id: HomeTileId; DashboardUiState gains enabledModules: List<String> for the server hand-off (E08.S06 dashboard endpoint)
  • 9 unit tests lock in the role matrix and ordering rules

Story

E11.S03 (Phase 1 Pilot v1, Sprint P3, 5 pts).

Atomic / reusability notes

Per the architecture/structure doctrine on ed.databayt.org:

  • HomeTileId + HomeTileVisibility are dashboard-local primitives (encoding a dashboard-specific contract) — not lifted to core/designsystem
  • The filter+order is a pure extension function on List<HomeTileSpec>, composable with any future grid that uses the same spec shape
  • No new design-system atoms added; existing BadgedAppIcon / HomeTileSpec shape unchanged

Test plan

  • ./gradlew :feature:dashboard:testDebugUnitTest --tests \"*HomeTileVisibilityTest*\" green
  • ./gradlew :feature:dashboard:lint green
  • Manual smoke per role (via dev UserRole toggle):
    • STUDENT: no Students roster, no Assignments, no AtomStudio
    • TEACHER: Students roster present, Assignments present, Fees absent, AtomStudio absent
    • GUARDIAN: child-scoped subset only (no roster, no marking, no dev tools)
    • ADMIN: every tile except AtomStudio
    • SUPER_ADMIN: every tile including AtomStudio

Forward-compat

  • UserRole only has 5 values today; server returns 8. Mapping is additive so E02.S01 (8-role expansion) extends without touching existing entries — adds ACCOUNTANT, STAFF, USER, renames SUPER_ADMIN → DEVELOPER
  • enabledModules is empty until E08.S06 ships — role defaults keep the dashboard fully usable in the meantime

Coexistence

Stacks cleanly on PR #13 (E11.S01 tile wiring). Disjoint line edits on home-tile-spec.kt — if E11.S01 merges first, this PR rebases automatically; if this merges first, E11.S01 needs id = HomeTileId.X added to its 4 wired tiles.

Figma verification gate

Per ios-design-doctrine, pixel-level UI work requires opening the Figma frame. This PR adds logic (filter + order) and contracts (enum + map) — no pixel changes. Existing iOS 26 grid visuals are unchanged.

Closes #14

Generated with Claude Code

…E11.S03)

Every role used to see every home-grid tile. STUDENT saw the Students
admin roster + Assignments marking + AtomStudio dev tool; GUARDIAN saw
roster + dev tools; ADMIN saw the dev-only AtomStudio. AC requires
mirroring the hogwarts platform-sidebar matrix.

Introduces two small dashboard-local primitives:

- `HomeTileId`: stable enum identifier per tile + `serverName` that
  mirrors the hogwarts module taxonomy
  (src/components/template/platform-sidebar/config.ts).

- `HomeTileVisibility`: Map<UserRole, Set<HomeTileId>> honouring the AC
  matrix:
    STUDENT     - own academics + comms + profile
    TEACHER     - same + Students roster + Assignments, - Fees
    GUARDIAN    - child-scoped views + payments + comms (no roster /
                  marking / dev tools)
    ADMIN       - all - AtomStudio
    SUPER_ADMIN - all (= server DEVELOPER)

- `List<HomeTileSpec>.filterAndOrderForRole(role, enabledModules)`:
  extension that (1) drops tiles the role can't see, then (2) reorders
  visible tiles by the server `enabledModules` manifest (case-insensitive
  against `HomeTileId.serverName`). Unknown / unlisted tiles keep their
  default `buildHomeTiles` order. Empty manifest = role-default order
  preserved, so the dashboard stays usable before E08.S06 server work
  ships.

Wiring:

- `HomeTileSpec` gains `id: HomeTileId`; all 17 tile definitions carry
  their identifier.
- `buildHomeTiles` ends with `.filterAndOrderForRole(state.userRole,
  state.enabledModules)` so the filter applies at the single emission
  point.
- `DashboardUiState` gains `enabledModules: List<String> = emptyList()`
  as the server hand-off slot.
- 9 unit tests in `HomeTileVisibilityTest` lock in the matrix + ordering
  rules so future tile additions explicitly choose a per-role default.

Forward-compatibility notes:

- The local `UserRole` enum has 5 values today; the server returns 8
  (DEVELOPER, ADMIN, TEACHER, STUDENT, GUARDIAN, ACCOUNTANT, STAFF,
  USER). The mapping is structured additively so E02.S01 (8-role
  expansion) only adds entries; existing entries don't change.

- `enabledModules` flows from /api/mobile/dashboard (E08.S06). Until
  that endpoint exists, the empty-default keeps things working.

Atomic / reusability: `HomeTileId` and `HomeTileVisibility` are
dashboard-specific contracts, intentionally kept in `feature/dashboard`
(not lifted to core/designsystem). The filter+order is a pure extension
on `List<HomeTileSpec>`, composable with any future grid using the same
spec shape.

Closes #14

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(dashboard): role-specific tile filtering + server-driven module ordering (E11.S03)

1 participant