notes(#454): per-recipient view/edit folder sharing
- Schema: noteFolderShares.permission ('view'|'edit', default 'view').
Project uses drizzle-kit push (no migration files); existing rows
pick up the default automatically on next push.
- Server: resolveFolderEditAccess + emitFolderChanged helpers.
- POST/PATCH/DELETE/checklist now allow folder editors.
- Editors stamp notes with folder owner's userId; labels validated
against owner; PATCH editors blocked from unfile (folderId=null)
and cross-folder moves to non-matching owners.
- emitFolderChanged fires for owner AND editor mutations across
create / patch (old + new folder) / delete / checklist toggle.
- PUT /shares accepts both legacy recipientUserIds and new
recipients:[{userId,permission}]; diffs add/update/remove/perm-flip.
- GET /shares, /shared-with-me, /shared-notes return permission /
myPermission / readOnly.
- Distinct socket events: note-folder-shared (added),
note-folder-share-updated (permission flipped),
note-folder-unshared (removed). Permission events carry the new
permission so clients can react.
- Client:
- notes-api types: FolderSharePermission, myPermission on
SharedFolder/SharedFolderView, permission on FolderShareRecipient,
readOnly:boolean on SharedFolderNote.
- useUpdateFolderShares takes recipients[].
- useCreate/Update/DeleteNote also invalidate ['note-folders'] so
actor's shared-folder rail badge stays fresh.
- FolderShareDialog: per-row checkbox + segmented View/Edit toggle.
- SharedFolderView: editor mode mounts Composer + NoteCard with
full edit/delete/archive affordances; Send hidden in editor
context (Composer + NoteCard hideSend prop) since /send is
owner-only.
- folders-rail: per-folder permission badge.
- socket: handlers for shared / share-updated / unshared all
invalidate the right query keys for live UI flips.
- Locales: shareDescriptionPerm, permissionView/Edit, canEdit
(en + ar).
- Tests: new permission roundtrip test in notes-share.test.mjs covering
view-rejects-write, edit-can-write, editor-cannot-unfile,
editor-create-stamped-to-owner, downgrade/upgrade flips.
- Pre-existing executive-meetings.ts type errors are out of scope.
This commit is contained in:
@@ -343,6 +343,19 @@ export function useNotificationsSocket() {
|
||||
invalidate(["note-folders"]);
|
||||
},
|
||||
);
|
||||
// Task #454: dedicated event for permission-only flips on an
|
||||
// existing share (view ↔ edit). Same invalidation as `shared`,
|
||||
// but kept distinct so the contract is explicit and so future UI
|
||||
// can react with a toast like "Your access changed to Edit".
|
||||
socket.on(
|
||||
"note-folder-share-updated",
|
||||
(payload?: { folderId?: number; permission?: "view" | "edit" }) => {
|
||||
invalidate(["note-folders", "shared-with-me"]);
|
||||
if (typeof payload?.folderId === "number") {
|
||||
invalidate(["notes", "shared-folder", payload.folderId]);
|
||||
}
|
||||
},
|
||||
);
|
||||
socket.on(
|
||||
"note-folder-unshared",
|
||||
(payload?: { folderId?: number }) => {
|
||||
|
||||
Reference in New Issue
Block a user