notes(folders): allow drag-drop of notes onto shared folders (edit perm)
User report (AR): "shared folders also appear here — the user should
be able to move notes wherever they want." The folders rail already
lists shared-with-me folders, but only OWN folder rows registered as
@dnd-kit drop targets. Recipients with edit permission could see a
shared folder but couldn't drop a note onto it.
Changes:
- folders-rail.tsx: extend the inline `DroppableRow` to accept an
optional `ownerId`. Wrap each shared-folder row in a DroppableRow
when `sf.myPermission === "edit"`, passing the owning user's id;
read-only viewers stay non-droppable. The droppable id is namespaced
with `-shared-<ownerId>` so it never collides with the owner-side
row for the same folder id.
- notes.tsx: extend `sharedFolderBucketRef` to carry the bucket's
`ownerId` (sourced from `data.folder.ownerId`). In `handleDragEnd`,
read `o.ownerId` from the drop data:
• undefined → own folder / Unfiled. Allow only own notes.
• number → shared folder. Allow only when the source note
came from sharedBucket and `sharedBucket.ownerId
=== o.ownerId`.
This mirrors the server-side rule that an editor may move notes
only between folders owned by the same owner — cross-owner drops
are blocked client-side so we never round-trip a 400.
Out of scope:
- Cross-owner moves (would require a copy/share flow, not supported
by the server today).
- Drop targets on shared folders inside the FoldersBrowser tile grid
(the rail covers the user's reported screenshot; tiles can follow).
This commit is contained in:
@@ -84,10 +84,8 @@ function DroppableRow({
|
||||
children,
|
||||
}: {
|
||||
target: "unfiled" | number;
|
||||
// When set, the drop target belongs to a shared folder owned by this
|
||||
// user id. handleDragEnd uses this to enforce the "same-owner only"
|
||||
// rule the server applies to editors. Leave undefined for own folders
|
||||
// and the Unfiled bucket.
|
||||
// Set only for shared-folder rows, so handleDragEnd can enforce the
|
||||
// server's same-owner rule for editors.
|
||||
ownerId?: number;
|
||||
className?: string;
|
||||
testId?: string;
|
||||
@@ -515,9 +513,6 @@ export function FoldersRail({
|
||||
},
|
||||
lang,
|
||||
);
|
||||
// Editors can drop notes from this owner's namespace into
|
||||
// any of their shared folders (server enforces same-owner).
|
||||
// Read-only viewers stay non-droppable.
|
||||
const canDrop = sf.myPermission === "edit";
|
||||
const rowInner = (
|
||||
<div
|
||||
|
||||
@@ -349,9 +349,6 @@ export default function NotesPage() {
|
||||
| {
|
||||
type?: string;
|
||||
target?: "unfiled" | number;
|
||||
// Owner of the target droppable. Set ONLY for shared-folder
|
||||
// rows; absent (undefined) on own folders + the Unfiled bucket
|
||||
// — those targets implicitly belong to the current user.
|
||||
ownerId?: number;
|
||||
noteId?: number;
|
||||
folderId?: number | null;
|
||||
@@ -370,14 +367,7 @@ export default function NotesPage() {
|
||||
if (!isOwn && !isEditableShared) return;
|
||||
|
||||
if (o?.type === "folder-drop" && o.target !== undefined) {
|
||||
// The server enforces: an editor may only move a note BETWEEN
|
||||
// folders owned by the same owner. Mirror that constraint
|
||||
// client-side so cross-owner drops never round-trip:
|
||||
// • Target with no ownerId = own folder / Unfiled. Allow only
|
||||
// for the user's OWN notes.
|
||||
// • Target with ownerId = a shared folder we can edit.
|
||||
// Allow only when the source note also lives in that owner's
|
||||
// namespace (i.e. came from sharedBucket with the same owner).
|
||||
// Enforce same-owner rule client-side (server also validates).
|
||||
if (o.ownerId === undefined) {
|
||||
if (!isOwn) return;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user