Sharing UI: invite by email, role management, read-only viewer mode #17

Closed
opened 2026-07-18 18:19:19 +00:00 by steve · 0 comments
Owner

Part of epic #20 · Design: DESIGN.md

Context

Frontend for garden sharing: owners invite existing users by email as viewer or editor, and the whole app respects the actor's role — most visibly a read-only editor mode for viewers, where the garden renders beautifully but nothing can be changed.

Scope

  • Share dialog (owner only), reachable from the garden card and the editor: list current shares (name/email + role), invite by email with a viewer/editor select, change a share's role, remove a share. Friendly "no account with that email" error.
  • /gardens list: role badge on shared gardens ("shared · viewer" / "shared · editor"); owned gardens unbadged. Data comes from my_role in the list payload (#16).
  • Role-aware UI gating driven by my_role from /full/list responses (never guessed client-side): viewers get no palette, no handles, no inspector edit fields (read-only inspector is fine), no plant-placement action, plus a subtle "view only" indicator in the editor; editors get everything except the share dialog and garden meta edit/delete; owners get it all.
  • Defense in depth: mutations are also disabled at the mutation-hook level for viewers, so a missed UI gate can't fire a request that would 403.
  • A recipient can remove themselves from a shared garden ("leave garden" on the card).

Out of scope

  • Backend (#16). Real-time presence/updates (out of scope for v1 by design — a viewer sees changes on reload/refetch).

Key files & patterns

  • API from #16; editor gating touches #11/#15 components — keep the gate a single canEdit derived flag, not scattered conditionals.

Dependencies

Blocked by #8 and #16 (full read-only coverage also assumes #11/#15 are in place; if picked up before #15, gate what exists).

Acceptance criteria

  • Two-browser flow: A shares with B as viewer → B sees the badge, opens the garden, canvas renders, pan/zoom works, nothing is editable, no mutation requests fire; A upgrades B to editor → after refetch B can move objects and place plops; A removes the share → the garden leaves B's list.
  • Owner sees the share dialog; editor doesn't; viewer doesn't.
  • npx tsc --noEmit clean.
Part of epic #20 · Design: [DESIGN.md](https://gitea.stevedudenhoeffer.com/steve/pansy/src/branch/main/DESIGN.md) ## Context Frontend for garden sharing: owners invite existing users by email as viewer or editor, and the whole app respects the actor's role — most visibly a **read-only editor mode** for viewers, where the garden renders beautifully but nothing can be changed. ## Scope - [ ] Share dialog (owner only), reachable from the garden card and the editor: list current shares (name/email + role), invite by email with a viewer/editor select, change a share's role, remove a share. Friendly "no account with that email" error. - [ ] `/gardens` list: role badge on shared gardens ("shared · viewer" / "shared · editor"); owned gardens unbadged. Data comes from `my_role` in the list payload (#16). - [ ] Role-aware UI gating driven by `my_role` from `/full`/list responses (never guessed client-side): viewers get no palette, no handles, no inspector edit fields (read-only inspector is fine), no plant-placement action, plus a subtle "view only" indicator in the editor; editors get everything except the share dialog and garden meta edit/delete; owners get it all. - [ ] Defense in depth: mutations are also disabled at the mutation-hook level for viewers, so a missed UI gate can't fire a request that would 403. - [ ] A recipient can remove themselves from a shared garden ("leave garden" on the card). ## Out of scope - Backend (#16). Real-time presence/updates (out of scope for v1 by design — a viewer sees changes on reload/refetch). ## Key files & patterns - API from #16; editor gating touches #11/#15 components — keep the gate a single `canEdit` derived flag, not scattered conditionals. ## Dependencies Blocked by #8 and #16 (full read-only coverage also assumes #11/#15 are in place; if picked up before #15, gate what exists). ## Acceptance criteria - Two-browser flow: A shares with B as viewer → B sees the badge, opens the garden, canvas renders, pan/zoom works, nothing is editable, no mutation requests fire; A upgrades B to editor → after refetch B can move objects and place plops; A removes the share → the garden leaves B's list. - Owner sees the share dialog; editor doesn't; viewer doesn't. - `npx tsc --noEmit` clean.
steve added the frontendsharing labels 2026-07-18 18:19:19 +00:00
steve closed this issue 2026-07-19 04:14:31 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: steve/pansy#17