Problem/Motivation
Drag and drop is limited and challenging in the current UI.
We want to expand drag and drop across fields, but still forms are very long and collapse / expand behavior with children is a UX problem.
See #2658694: Move a nested Paragraph across fields and nesting
Proposed resolution
Switching the UI into a special Drag and Drop mode can be very helpful.
The mode needs to be terminated with a dedicated button, back to regular editing.
This also will allow us to remove drag handles from the regular UI.
It also could allow us to flatten the UI completely, removing indentation. But that will be a separate issue.
Remaining tasks
Frontend
Add handles
Style dragging
Update weight when reordering
Update parent entity id when reordering
Validation
Indentation when dragging is disabled
Fix dragging on iOS
Backend
Save weights
Handle parent entity id changes
Nice to have
Drop zone valitdity indication
User interface changes


API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #155 | meta_introduce_a_drag-2825575-154.patch | 76.47 KB | berdir |
| #153 | meta_introduce_a_drag-2825575-153-interdiff.txt | 1.17 KB | berdir |
| #153 | meta_introduce_a_drag-2825575-153.patch | 86.48 KB | berdir |
| #152 | meta_introduce_a_drag-2825575-151-interdiff.txt | 1.92 KB | berdir |
| #152 | meta_introduce_a_drag-2825575-151.patch | 76.36 KB | berdir |
Comments
Comment #2
drobnjak commentedComment #3
drobnjak commentedComment #4
miro_dietikerWhat is unclear here is how to enter the drag and drop mode. This is through the perspective action button - v expand item - Drag & Drop.
Comment #5
pixelmord commentedWe are currently reviewing authoring UX for the thunder distribution that makes heavy use of paragraphs and came up with a different sorting mode that uses the concept of cut and paste which is especially good for long flat lists of paragraphs. See an early wireframe in https://www.drupal.org/node/2828106#comment-11791272
This solution described here is especially for dragging and dropping across fields and entities? I am not entirely sure that I understand the workflow here, may be because I am missing the context of how the hierarchy looks like before you started the special drag n drop mode...
Comment #6
yobottehg commentedI would like to point out this issue here [https://www.drupal.org/node/2264739] for allowing multi value fields without tabledrag
Comment #7
yobottehg commentedComment #8
yobottehg commentedi will work on this.
Comment #9
yobottehg commentedThis patch will disable core drag and drop on the paragraphs multi value fields
Comment #10
yobottehg commentedtriggering testbot
Comment #12
yobottehg commentedremoved the reorder tests from IEF integration because we do not want to reorder paragraphs.
Comment #13
yobottehg commentedadded initial switcher for drag and drop mode
Comment #15
yobottehg commentedUpdated the naming, render the switcher as form element and take it in the header in a preprocess function.
Ignore the button at validation like the add_more button.
Comment #16
yobottehg commentedworking switcher button for form view modes
Comment #17
yobottehg commentedfloat the button to the right, do not show remove button in reorder mode, display all childs in reorder mode
Comment #18
jeroen.b commentedThis patch extends #17 to rewrite the table into a list and add the sortable library on it.
Comment #19
luksakUpdating the IS with the remaining tasks
Comment #20
luksakFixing dragging on iOS
Comment #21
luksakComment #22
johnchqueLet's change the css indentation to two spaces.
!important is quite tricky, can we avoid using it? :)
Missing empty line.
Missing doc.
Missing doc.
Screenshots would be really helpful.
Indentation of the sortable library needs to be fixed too.
Comment #23
yobottehg commentedComment #24
luksakFixing CSS and JS indentation and adding handles for dragging.
Comment #25
luksakAdding indentation when dragging is disabled and fixing typo.
Comment #26
jeroen.b commentedWorking nested paragraphs, fixed issue with empty field, removed add button in reorder mode.
Comment #27
luksakUpdating IS
Comment #28
luksakI refactored the CSS and improved indents and general margins.
Comment #29
luksakFixed the duplicate field wrappers and added rtl support for reorder mode.
Comment #30
jenteralex commentedAdded drop zone validation
Comment #31
luksakUpdating remaining tasks.
Comment #32
yobottehg commentedfixed restoring initial behaviour of paragraphs after switiching to drag an drop mode
Comment #33
yobottehg commentedcorrect patch
Comment #34
jeroen.b commentedFixed a weird reference issue that caused the list to be rendered wrong.
Also made sure the prefix and suffix are appended correctly.
Comment #35
johnchqueJust tested. Wondering if:
- The submission when changing positions doesn't work right? I mean, it is not saved.
- we will need a more core-ish css for this being committed.
- Are behavior plugins not hidden in the reorder mode?
Comment #36
jeroen.b commented@yongt9412 we keep posting patches so we can work on it together, this is nowhere near finished yet.
Comment #37
johnchqueOops, I see, then can you also provide interdiff please? :)
Comment #38
luksakAdding JS logic for setting correct paths and weights when reordering.
Comment #39
luksakHiding the form elements which are now updated using JS.
Comment #40
luksakAdding new ghost item styling which is more compact to be able to sort easier an more granuarly. It is indicated by a black line now. Also improving general margins and font stlyes.
Comment #41
luksakCurrently there is an UX issue when starting to drag. If the user drags a big element, the list collapses and the user can loose context where the paragraph was initially. Maybe we should a placeholder where the paragraph was initially?
Comment #42
luksakFixing indentation in normal edit mode and improving typography of field labels in reorder mode.
Comment #43
luksakCSS cleanup and attaching screenshots of the current solution. Sadly I am unable to take a screenshot while dragging...
Comment #44
luksakComment #45
miro_dietiker@jeroen.b I think you had an improved version of this patch to make the storage work? Can you provide us the WIP so someone else can look into it too?
Comment #46
jeroen.b commentedHere is the WIP. The logic for restructuring is in the processRestructure function.
Comment #47
johnchqueAdded extra check for making it work switching the modes.
I actually think that we should move this patch to a new issue, working in a Meta is not the best thing.
BTW I just tested the patch and it works when you move a paragraph out of its parent, it creates some weird duplicates. The patch doesn't work for moving a paragraph inside another one.
Comment #48
johnchqueFor the ones who want to test this:
When changing the mode to drag and drop, it will allow changing the position of the paragraphs, by now, it support more or less moving a paragraph out of its parent and the other way round. It create some weird duplicates but works.
If you wanna test this, don't forget to use the Experimental widget in all paragraphs fields, also in the nested fields.
Comment #49
miro_dietikerMultiple parties already spent a lot of time in manual testing and debugging. In order to allow us solving this problem we will need to create a step by step test coverage next and fake the move submission and test for the expected storage updates with multiple cases (weight, nesting, ..)
Comment #50
luksakComment #51
drobnjak commentedPromoting and starting to work on tests. Still, patch needs to be moved to another issue. I will add it here once I have the first patch with tests.
Comment #52
ginovski commentedRerolled, tested in the UI, doesn't work when moving a paragraph out of its parent or when moving a paragraph inside another one.
Comment #53
ginovski commentedAdded test for changing the parent. (setting the path to the node parent).
Creates duplicate, fails.
Comment #54
ginovski commentedComment #86
ginovski commentedAdded test cases:
1. Changing the parent
2. Changing the weight (this can't be done with the path, because the assertion would be the same for both text paragraphs.
3. Moving to a different tree (from 1 nested paragraph to another).
Comment #88
miro_dietikerThe patch contains reverts for recent commits. Please pull, rebase, and upload again.
Comment #89
berdiradding an external library to the source code is *not* an option.
If we need something like that then we have to let it be downloaded separtely, which is painful for users. So, it would be better if we could avoid it, actually.
this function needs a lot of coding style cleanup.
this needs to be a class property, I guess static but we could also track this through $form_state.
Comment #90
miro_dietiker@Berdir The sprint team did reasonable research in identifying a sort js library that supports what is needed. Sortability with drag & drop events is not something to easily implement without a library.
Re painful - the drag & drop mode can be an optional feature that simply only is offered if the library is detected.
Comment #91
ginovski commented1. Rerolled patch
2. Cleaned up paragraphs_form_language_content_settings_form_alter
3. Using class property instead of the global $parent_paragraph_in_reorder_mode
Comment #93
miro_dietikersemicolon or not?
space
if we touch lines or write new code, array() => []
Use @todo like the coding standard requests.
https://www.drupal.org/docs/develop/coding-standards/api-documentation-a...
Comment #94
luksakI added some @TODOs in the code. During the sprint we agreed that fixibg them doesn't make sense while we are not sure if we willbe able to store the data at all.
Comment #95
ginovski commented1. Addressed comment #93.
2. Some code style fixes.
Comment #97
berdirComment #98
berdirWork in progress. Single movements seem to working quite fine now, but there is a bug when you don't disable the reorder mode before saving. I'll look into that. It seems to duplicate the paragraph in that case.
Where it starts to fall apart is if you make multiple
I changed one test to disable reorder,that then passes after fixing it. The others will still fail. I also fixed bunch of notices so there should be a lot less fails now.
I also added the summary to the re-order mode as you have no idea what you are moving around otherwise.
TODO:
* Fix immediate saving
* Fix multiple changes. Might actually require that we completely refactor how this works.
* Clean up rendering of the reorder mode. Using a different template should be a lot easier than messing with the table in the standard field multiple template should make things a lot cleaner
* Many more tests. Specifically for multiple changes, but also adding actual content to the paragraphs.
Comment #100
ginovski commentedExtended test with some multiple changes and added an isset for the widget in massageFormValues().
Comment #101
damienmckennaComment #103
anton-staroverov commentedI just implemented drag & drop UI as a small separate module for 8.x:
https://www.drupal.org/project/bricks
It provides a re-usable Entity Reference Widget => compatible with Paragraph entities as well.
So, probably we can re-use some code. Any thoughts?
Comment #104
caldenjacobs commentedThis is brilliant, @tonystar.
Any progress on integrating with Entity Reference Revisions?
Comment #105
jeroen.b commented@tonystar looks very cool!
But when looking at the code I see that it's not very flexible and it probably only works with 2 levels?
Can you explain a bit how it works internally?
Comment #106
anton-staroverov commented@caldenjacobs, currently I'm considedring the options, any thoughts regarding https://www.drupal.org/node/2859679#comment-11983114?
@jeroen.b, this is early implementation, but actually pretty stable and flexible. And no limitations for levels! Internally it extends db scheme to store depth for each ER field item. Simple. And perfomant.
Comment #107
jeroen.b commented@tonystar So internally all references are actually attached to the main entity (probably a node) and the formatter/widget processes the tree?
Comment #108
anton-staroverov commented@jeroen.b exactly! This also allows to re-use the same entities in different tree structures and attach different css classes and view modes to the same entities.
Holding entities one "inside" another supported as well (w/o any code actually).
Comment #109
caldenjacobs commentedIt looks like @tonystar has added Entity Reference Revisions support to Bricks, and the thread to Collaborate with Paragraphs is alive and well!
Comment #110
ginovski commentedUploading rerolled patch (doesn't work properly atm, need some fixes).
Comment #112
berdirThis is a restart that uses a completely different approach to display the re-order mode, does everything in the main widget and doesn't rely on global statics and rewriting everything in preprocess.
Way too many changes for an interdiff, so didn't bother with that.
Displaying seems to be working fairly well, but the saving isn't implemented yet, so don't bother testing this. The JS part with updating the fields also doesn't seem to be working anymore.
Comment #114
berdirStarted implementing the saving/updating but turns out the the JS was not working for many more complex moves as the path wasn't properly updated for complex/nested structures. So worked quite a bit on that, that was before and now even more a mess of jquery non-jquery code. Not sure sure yet in which direction to unify.
On purpose made the weight and path visible elements now for testing, as this allows to easily verify that the data being sent is valid.
Comment #116
berdirRemoved the unused underscore reference, wasn't used anyway.
Comment #118
berdirThings are starting to work...
Comment #120
berdirNoticed two problems while starting to test this in a real project.
1. The button didn't use the field id prefix, broke in fun ways with multiple paragraph fields.
2. It initially didn't work at all in our project, which took me a while to track down. Turns out that the jquery binding conflicts with jQuery UI sortable as it uses the same function name. I copied the binding into our own JS file with a custom name.
Some operations aren't working yet, still working on tracking that down. Also didn't update the tests yet.
Comment #122
berdirFixing a number if nasty bugs and updating /extending tests.
Comment #123
berdirComment #124
berdirThis now requires that the library is downloaded separately and put into /libraries. I have not yet added libraries.module integration to support different locations and I also need to figure out a way to check for existence of the library and handle that.
The main problem there is that if we hide the feature then we won't be able to test it on testbot as it doesn't have it.. but we also don't actually need it, as it is not a JS tests.
Tests are passing for me locally.
Use bower install Sortable to get the JS library, make sure it is in libraries/Sortable.
Comment #125
berdirThis should apply.
Comment #126
miro_dietikerI think the button to enter the drag and drop mode should go to the same location as #2738645: Add a collapse / edit all button
Comment #127
berdirYes it should, but that location doesn't exist yet ;)
No point in spending time here on that, can be updated once one of those issues lands. And as I mentioned before, we will need to rework it again and replace the standard field multiple template with something similar to how I'm already shortcutting that here so it doesn't get in our way.
Comment #128
steniya commentedComment #129
miro_dietikerOne important thing we want to investigate in a follow-up is how we can bring layout (from plugins) to the drag & drop display.
In contrast to the edit more, there is enough compactness and room in the collapsed situation to apply a grid layout to the UI - at least in drag & drop mode. One idea was to add a setting to only have one paragraph in edit mode and display all collapsed. That would then bring the compactness to the whole Paragraphs UI and we could discuss applying certain layout in the regular summary too... A long way. ;-)
Comment #130
toncic commentedNeed to rebase, refactor and fix test failing.
Comment #131
toncic commentedRebased, refactored a bit. There is a problem with 'Confirm order changes', will take a look tomorrow.
Comment #132
miro_dietikerStrange this didn't go back to needs work?
BTW issue summary needs update, right? It's no more a META plan... ;-)
Comment #133
berdirImproved a few things, still various things left to do:
* Fix save while in reorder mode. This partially works now, but only for top-level.
* libraries module integration
* check for existence of library, hide button, probably with a test override so we can still do the tests without the library as it is not a JS test anyway.
* test and likely fix multiple paragraph fields.
* Convert css to scss?
* ...
Comment #134
berdirGetting close.
Tests completely rewritten to use BrowserTestBase, avoding demo and so on, made them multiple times faster. Complex changes as well as multiple fields are now tested, also directly saving, correct handling of summary and doing it all in collapsed widgets.
Comment #135
miro_dietikerFound a bug:
If i first change the position of a container while editing, then switch into reorder mode and drag and drop elements into that container, Fatal error.
UX feedback from testing, might go into follow-ups:
When i start to drag, i have zero indication where i can drop it. We should indicate the drop'able area with some 2px+ horizontal lines. My original proposal was to display them yellow. Yes, takes more vertical space, but worth it. This is also important since now we have 1px moving effects and it's sometimes hard to hit a droppable area at all when nested elements jump back and forth.
The field label for children can be removed if it is only one.
Everything is about drag & drop. I should be able to drag an item wherever i click. Not just the handle.
Everything is grey'ish. That's a bit odd, but dunno if black is better. We might want to apply some hover effect (grey background?) on elements.
Comment #136
miro_dietikerAh and the drag handle is vertically off from the summary line.
Comment #137
berdirFixed bug with moving before starting reorder, also added another test for deleting a paragraph.
Made some visual changes, removed single children paragraph label, added some ugly yellow background thingy, someone will have to make that nicer ;) But it does already help with knowing where you can put stuff. Also fixed the padding of summary to have it on same line as drag handle, that used to be padded through another class is no longer there. Did not change the grey color, summary is always that gray in paragraps UI, so the type is the same and macking it black is then *very* black.
Comment #138
berdirThis fixes the missing top-level field label and with also the overlapping disable button.
Comment #139
luksakSaving the data works perfect so far on a existing site with data.
I have two issues.
Comment #140
berdir1. Make sure you use the latest dev version. We introduce the concept of header actions in the collapse all issue, that takes care of the button display, it's now an option in the dropbutton there. That said, this patch wouldn't apply if you didn't have that, so not sure.
This is how it should look like:

2. Making the client side interaction itself better is probably outside of my very basic JS skills. You're very welcome to give it a try :) We also noticed a problem that the validation of allowed times sometimes doesn't work. That's something I want to look into.
Comment #141
berdirThis at least prevents the fatal error when you manage to put a paragraph into a not-allowed position.
Comment #142
berdirRenamed reorder mode in the ui to "Drag & drop", added libraries module support and hiding the feature if the library is not present, including an override for tests. Also added a bit of documentation to the README.
Comment #144
berdirRebased.
Comment #145
johnchqueFew nitpicks that don't alter the behavior.
Commented. :)
dot at the end.
more than 80 chars.
parameter type missing.
todo.
Let's remove the slash next to "not".
Comment #146
primsi commentedA few more nitpicks. Might overlap with the review above, because I did this before holidays and didn't post :|
Is this left intentionally?
Follow-ups to add documentation and perhaps some kind of graceful handling if lib doesn't exist?
Needs method doc update.
Leftover code.
Nitpick: order of params is wrong.
This comment needs some work: missing description and perhaps explain return a bit.
Comment #147
miro_dietikerTested. In fact we discovered some crazy bug with most recent Sortable.js, but it works perfectly with 1.4.0 Sortable.js.
Let's get this in after nitfixing and work in follow-ups. :-)
Comment #148
miro_dietikerClear follow-ups are:
- The "Complete drag & drop" button should be blue IMHO. The button also has some small indentation problem.
- The paragraph should be draggable as a whole (fully clickable) and not just the drag handle.
- The dragged element shoudl receive some grey background and be less transparent. Thunder does this pretty nicely with its specific drag behavior.
- The grey text color has a contrast ratio that is too low.
- Let's trigger the behavior plugins that introduce layout so they can apply something like a grid layout to the drag & drop. That would create awesome layout awareness. In fact, we could even ship drag and drop on steroids for our rendered frontend... :-) (might need an ajax refresh for the draggable element after drop though..)
- And we should improve UX / design for the drag & drop UI.
And likely many more things once people work with it. :-)
Comment #149
berdirOk, lots of changes again.
Thanks for the reviews, specific replies:
#145.5 todo is now gone, we have this option now and it works well. Still shows summary of e.g. behaviors but not the children.
#146.1 Not sure, removed for now.
#146.2 Graceful disabling of the feature was already in a previous patch after you wrote you review. I also updated and improved the README in general and specifically for this.
#146.4 was already removed in previous patch but is now back as non-commented out code.
Other changes:
* Weight is now a hidden field, updated JS and tests for that.
* Renamed more sortable to dragdrop
* Improved and documented JS
* Complete is now a primary action.
Comment #150
berdirDebug left-over cleaned up and rebased.
Comment #151
berdirThe last non-broken version that I now tested is 1.5.1. That also can be installed with bower, 1.4.0 has a broken bower.json.
Can be fixed on commit in README if that's the only change.
Comment #152
berdirRenaming all the things broke all the things.
This should fix the JS. Also updated the README.
Too bad, Patch -150 would have been a nice one to commit :)
Comment #153
berdirThis should fix the problem where it doesn't work with hidden fields path/weight fields.
Comment #155
berdirAnd wrong patch.
Comment #157
miro_dietikerYay! Committed...
Back to needs-work so someone can create all the follow-ups and close.
Comment #158
luksakI am going to test on some existing projects with serious paragraphs stuff going on :)
Thank you for getting this done!
Comment #159
luksakI created a few follow ups.
Besides that the data saved when properly rearranging paragraphs looks good.
Comment #160
luksakHere are some small improvements to the UI:
Comment #161
luksakI created a separate issue for the UI improvements: #2901582: Drag and drop mode: UI improvements
Comment #162
miro_dietikerCreated last follow-up that i found.
Comment #163
luksakAnother one.
Comment #164
luksak