Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEP Replace react-dnd with dnd-kit #1527

Open
wants to merge 1 commit into
base: 3.0
Choose a base branch
from

Conversation

GuySartorelli
Copy link
Member

@GuySartorelli GuySartorelli commented Dec 17, 2024

This PR replaces the react-dnd with dnd-kit with like-for-like functionality, except:

  • Dragged file is the wrong size #1016 has been fixed - I had to alter the styling anyway because of the way dragging the GalleryItemDragLayer works now. The changes aren't fully compatible with CMS 5 so I won't be backporting the changes there, so #1016 needs to remain open.
  • When dragging an item on top of a droppable zone, the cursor doesn't update. The one used by react-dnd is actually coming from the browser itself with default HTML5 drag-and-drop functionality (see https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/dropEffect). That cursor is not selectable with CSS as far as I can tell.
    • We could use the no-drop cursor when dragging anywhere else, and only use grabbing for when we're over a valid drop target - but that wouldn't be consistent with cursors used in other drag-and-drop scenarios in the CMS. I'd recommend if we want to do that, it's handled in a wider-reaching card that standardises this approach.

Ran yarn upgrade to get silverstripe/eslint-config#29

Issue

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that I didn't split converting this or other components to functional as its own PR or commit because the lifycycle functions needed to be removed anyway. Converting it with the lifecycle events in-tact and then removing them separately would have been more work.

<div className={classnames(className, { 'gallery__main--dragging': this.state.dragging })}>
return (
<div className={classnames(className, { 'gallery__main--dragging': dragging })}>
<DndContext sensors={sensors} onDragStart={handleDragStart} onDragEnd={handleDragEnd} modifiers={[snapCenterToCursor]}>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried using built-in modifiers (including restrictToWindowEdges) to restrict where we can drag the files, but none of them worked how I'd expect them to, so I opted to go without. The end result is the same unbound dragging as the old approach so it's not worse than it was before, at least.

Comment on lines +138 to +140
if (this.props.item.type === 'folder') {
thumbnailClassNames.push('gallery-item__thumbnail--folder');
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed for styling the draglayer for folders

background: $white url("../../images/icon_archive.png") center center no-repeat;
background: transparent url("../../images/icon_archive.png") center center no-repeat;
Copy link
Member Author

@GuySartorelli GuySartorelli Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes were required to fix a problem where the background was being drawn over top of the border of the drag layer.
Note that I can't just use background-image because that seems to be overridden by something elseand results in no thumbnail being displayed

Comment on lines -8 to -16
getOffset() {
const {
offset,
dragged,
} = this.props;
return {
transform: offset && `translate(${offset.x + dragged.x}px, ${offset.y + dragged.y}px)`,
};
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset stuff is handled by the snapCenterToCursor modifier now

Comment on lines -7 to +8
<GalleryItem item={{id: 2}} selectable={true} />
<GalleryItem item={{id: 2, exists: true, type: 'file', category: 'document'}} selectable={true} />
<GalleryItem item={{id: 2, exists: true, type: 'folder', category: 'folder'}} selectable={true} />
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While updating styling, I had to render out these directly so I could mess with css in the browser.
I found that just an ID wasn't enough, so I've updated for an example for a file and for a folder, for future reference.

Comment on lines -8 to -28
canDrag(props) {
return props.canDrag;
},
beginDrag(props) {
const { id } = props.item;
if (typeof props.onDrag === 'function') {
props.onDrag(true, id);
}
const selected = props.selectedFiles.concat([]);
if (!selected.includes(id)) {
selected.push(id);
}

return { selected, props };
},
endDrag(props) {
const { id } = props.item;
if (typeof props.onDrag === 'function') {
props.onDrag(false, id);
}
},
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handling what happens on drag/drop is done inside GalleryDND instead.

@@ -952,7 +950,12 @@ class Gallery extends Component {
ref={gallery => { this.gallery = gallery; }}
>
{this.renderTransitionBulkActions()}
<GalleryDND className={galleryClasses.join(' ')}>
<GalleryDND
onDragStartEnd={(dragging) => this.handleEnableDropzone(!dragging)}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaces handleDrag in ThumbnailView

@GuySartorelli GuySartorelli force-pushed the pulls/3.0/dnd-kit branch 5 times, most recently from 4728667 to 2c975bc Compare December 19, 2024 20:54
@GuySartorelli GuySartorelli marked this pull request as ready for review December 19, 2024 21:03
Comment on lines +508 to +515
public function stepDragTheFileToTheFolder(string $fileName, string $folderName): void
{
$file = $this->getGalleryItem($fileName)->find('xpath', "/ancestor-or-self::div[contains(@class, 'gallery-item__draggable')]");
Assert::assertNotNull($file, "File named {$fileName} could not be found or isn't draggable");
$folder = $this->getGalleryItem($folderName)->find('xpath', "/ancestor-or-self::div[contains(@class, 'gallery-item__droppable')]");
Assert::assertNotNull($folder, "Folder named {$folderName} could not be found or isn't droppable");
$file->dragTo($folder);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't use the existing I drag the "some element" element to the "some other element" element method, because the only selectors available rely on fixed IDs which works locally but fails in CI.

Copy link
Member

@emteknetnz emteknetnz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of weird things happening when I tested locally in firefox, neither of which happen in CMS 5

  • After moving, the thumbnail animates back to its original location
  • There's a red toast error when attempting to move to the parent folder. Only happens with moving files, not moving folders.

https://www.youtube.com/watch?v=vnHESa15Q8g

@@ -0,0 +1,34 @@
@javascript @assets @retry @job3 @gsat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@javascript @assets @retry @job3 @gsat
@javascript @assets @retry @job3

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@GuySartorelli
Copy link
Member Author

There's a server error when attempting to move to the parent folder. Only happens with moving files, not moving folders.

If the parent folder is the root, this is a known regression that was already linked in the issue description.

@emteknetnz
Copy link
Member

Server error still happens when trying to move files to the parent folder in deeply nested folders

@GuySartorelli
Copy link
Member Author

Can't reproduce. Please:

  1. Compare against the 3.0 branch without this PR to rule out an existing regression
  2. If it is an existing regression, open a new card about it
  3. If it is not an existing regression, please provide server error message and stack trace - I may even ask for a copy of your DB and assets since as I said I can't reproduce.

@GuySartorelli
Copy link
Member Author

After moving, the thumbnail animates back to its original location

Good spot. Fixed.

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.

2 participants