Sortable Rows in GridField

1,052 views
Skip to first unread message

UndefinedOffset

unread,
May 9, 2012, 1:47:07 PM5/9/12
to silverst...@googlegroups.com
I noticed some discussion on here about having the ability to sort data objects in grid fields, I've been toying around with this a little bit over the day and have come up with something that seems to be working well for me in my testing https://github.com/UndefinedOffset/SortableGridField. Right now I have it as its own module but I'm wondering if it's something better suited to be merged into the core of SS 3.0?

It uses some code based off of UncleCheese's SortableDataObject for managing what classes are sortable. It functions very similar once the component is added to the grid field, it adds a checkbox to the grid field then removes pagination, filtering, and the sortable headers components when the box is checked allowing for the sort order to be easily determined. Sorting is done via drag-n-drop using jQuery ui which seems to be always loaded in the cms anyways.

Sigurd Magnusson

unread,
May 10, 2012, 4:30:31 AM5/10/12
to silverst...@googlegroups.com
Sounds great! "Sortability" seems like a very useful attribute so seems something that should either be in core or at minimum a well supported extension...

Sig


On 10 May 2012 05:47, UndefinedOffset <edch...@gmail.com> wrote:
I noticed some discussion on here about having the ability to sort data objects in grid fields, I've been toying around with this a little bit over the day and have come up with something that seems to be working well for me in my testing https://github.com/UndefinedOffset/SortableGridField. Right now I have it as its own module but I'm wondering if it's something better suited to be merged into the core of SS 3.0?

It uses some code based off of UncleCheese's SortableDataObject for managing what classes are sortable. It functions very similar once the component is added to the grid field, it adds a checkbox to the grid field then removes pagination, filtering, and the sortable headers components when the box is checked allowing for the sort order to be easily determined. Sorting is done via drag-n-drop using jQuery ui which seems to be always loaded in the cms anyways.

--
You received this message because you are subscribed to the Google Groups "SilverStripe Core Development" group.
To view this discussion on the web visit https://groups.google.com/d/msg/silverstripe-dev/-/k_dtb9bCrqMJ.
To post to this group, send email to silverst...@googlegroups.com.
To unsubscribe from this group, send email to silverstripe-d...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/silverstripe-dev?hl=en.

Ingo Schommer

unread,
May 10, 2012, 5:14:53 AM5/10/12
to silverst...@googlegroups.com
We had this feature on our internal project tool for a while.
As SS3 is progressing from team-based feature development to bugfixing, 
we're migrating all storycards which are likely to be actioned
in the next month to our open bugtracker. I've done this for the sortable card:

Had a brief look at Ed's module, looks good in principle.
There's a couple of workarounds to get manymany sorting
going, which should really be integrated into DataObject statics
and RelationList rather than augmentSQL calls on an extension.
From a GridField's perspective, the only additional
data the component should need is the database column
to sort on (either on the record table itself, or the many many join table).

Plus, the module needs unit tests :)

UndefinedOffset

unread,
May 10, 2012, 8:34:17 AM5/10/12
to silverst...@googlegroups.com
I think I can handle the tweaking of the GridField component to account for letting the site dev specify the column to sort on. Which would actually make it a much simpler module. The entire GridFieldSortableObject would really become obsolete. I'll also see what I can do about the Up/Down keyboard sorting, I'm using jQuery UI so I'll do some googling and see what I can come up with. Since like you suggest you would manually setup all of what it does on your DataObject class. Probably by the time you guys are starting your day (and reading this) I will have that done.

In regards to the unit tests, what would you want to see this unit test do Ingo?



On Thursday, May 10, 2012 6:14:53 AM UTC-3, Ingo Schommer wrote:
We had this feature on our internal project tool for a while.
As SS3 is progressing from team-based feature development to bugfixing, 
we're migrating all storycards which are likely to be actioned
in the next month to our open bugtracker. I've done this for the sortable card:

Had a brief look at Ed's module, looks good in principle.
There's a couple of workarounds to get manymany sorting
going, which should really be integrated into DataObject statics
and RelationList rather than augmentSQL calls on an extension.
From a GridField's perspective, the only additional
data the component should need is the database column
to sort on (either on the record table itself, or the many many join table).

Plus, the module needs unit tests :)
On 10/05/2012, at 10:30 AM, Sigurd Magnusson wrote:

Sounds great! "Sortability" seems like a very useful attribute so seems something that should either be in core or at minimum a well supported extension...

Sig


On 10 May 2012 05:47, UndefinedOffset <edch...@gmail.com> wrote:
I noticed some discussion on here about having the ability to sort data objects in grid fields, I've been toying around with this a little bit over the day and have come up with something that seems to be working well for me in my testing https://github.com/UndefinedOffset/SortableGridField. Right now I have it as its own module but I'm wondering if it's something better suited to be merged into the core of SS 3.0?

It uses some code based off of UncleCheese's SortableDataObject for managing what classes are sortable. It functions very similar once the component is added to the grid field, it adds a checkbox to the grid field then removes pagination, filtering, and the sortable headers components when the box is checked allowing for the sort order to be easily determined. Sorting is done via drag-n-drop using jQuery ui which seems to be always loaded in the cms anyways.

--
You received this message because you are subscribed to the Google Groups "SilverStripe Core Development" group.
To view this discussion on the web visit https://groups.google.com/d/msg/silverstripe-dev/-/k_dtb9bCrqMJ.
To post to this group, send email to silverstripe-dev@googlegroups.com.
To unsubscribe from this group, send email to silverstripe-dev+unsubscribe@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/silverstripe-dev?hl=en.


--
You received this message because you are subscribed to the Google Groups "SilverStripe Core Development" group.
To post to this group, send email to silverstripe-dev@googlegroups.com.
To unsubscribe from this group, send email to silverstripe-dev+unsubscribe@googlegroups.com.

UndefinedOffset

unread,
May 10, 2012, 10:55:15 AM5/10/12
to silverst...@googlegroups.com
There I've updated my repo, I removed the GridFieldSortableObject which means the site dev has define the field used for sorting which isn't that big of a deal. I also changed GridFieldSortableRows to also be a data manipulator instead of relying on the data object to specify sorting. It does account for GridFieldSortableHeader, so if you use it to sort the view then GridFieldSortableRows backs off, however when you check the box since GridFieldSortableRows removes pagination, sortable headers and the filter components it accounts for it there as well. I'm still looking into using keyboard controls, I'll push something up if I find a solution.

UndefinedOffset

unread,
May 14, 2012, 8:01:28 PM5/14/12
to silverst...@googlegroups.com
So I've done some looking into keyboard controls to do the sorting, there seems to be some attempts a few years ago but no one solution. I think I've knocked out most of what your asking for Ingo in your ticket, except for items 5 & 8 in your ticket, since as I mentioned prior it removes pagination, sortable headers and the filter components when drag and drop sorting is enabled. Can you have another look and let me know what you think?

Ingo Schommer

unread,
May 15, 2012, 8:53:34 AM5/15/12
to silverst...@googlegroups.com
On 15/05/2012, at 2:01 AM, UndefinedOffset wrote:

So I've done some looking into keyboard controls to do the sorting, there seems to be some attempts a few years ago but no one solution. I think I've knocked out most of what your asking for Ingo in your ticket, except for items 5 & 8 in your ticket, since as I mentioned prior it removes pagination, sortable headers and the filter components when drag and drop sorting is enabled. Can you have another look and let me know what you think?
Hm, item 8 is a tricky one: "Ordering should be changable across pages by hovering over the paging buttons"
That was a suggestion by Hamish originally, and I can see its appeal from a system architecture perspective:
It avoids loading *all* records, which is a memory usage server error waiting to happen, depending on the size of the managed set.
Plus it removes the need for an additional UI element to specifically enable drag'n'drop, can just be enabled by default.
That being said, the UX is not so great if you want to drag over a hundred records on a dozen pages.
Developers can counteract this problem by simply making the default pagination longer.
What do you think, worth implementing the hover solution?

With the hover solution, we'd still need to update all counts on records,
raising the same memory usage concerns as with your current solution.
I think its OK to do this through a raw SQL query rather than instanciating each object.

Also, is there a reason you're triggering a refresh of the whole table on drop?
I think it should save in the background, the refresh disables the field,
making it much more time consuming to drag multiple items in quick succession.
On that note, can you wrap the sort updates in a transaction please?
It sounds like a typical victim of lacking atomicity, with users quickly
firing off multiple actions. 

If we are to consider this component for core, we also need unit tests
(or more functional tests in this case). Could you look into this?
Have a look at the GridFieldDeleteActionTest class to get you started,
and feel free to ping me on IRC (@chillu) for more help on that :)

Thanks!
Ingo




--
You received this message because you are subscribed to the Google Groups "SilverStripe Core Development" group.
To view this discussion on the web visit https://groups.google.com/d/msg/silverstripe-dev/-/AVIZM0Y86NMJ.
To post to this group, send email to silverst...@googlegroups.com.
To unsubscribe from this group, send email to silverstripe-d...@googlegroups.com.

UndefinedOffset

unread,
May 15, 2012, 10:27:59 AM5/15/12
to silverst...@googlegroups.com
Cool, ya I'm working through some of the changes now. However I did run into one thing, you mention using ManyManyList->foreighIDFilter() but the definition of this method has it defined as protected in master and beta 2 so I can't access it.

As for number 8 it makes complete sense to me from a memory/resource prospective but I would agree with you on the user experience issue, I think it maybe a bit confusing for the average user if they have to drag a row over the arrow to sort an item to the previous page. It also poses like you mention the issue that the count is based on the items index in the table being displayed. But I suppose I could just offset the number based on the page length.

I think the core reason I was refreshing the whole table is because I was having a hard time getting the request to properly send. I'll keep digging and see if I can get a better way working, any tips would be awesome ;). The other reason was to prevent users from doing things too fast and causing things to get overwritten but the transaction should help with that one.

I'll see what I can do about a unit test, I'll look at the class you suggested for pointers and poke you on irc if I need help with it.
To post to this group, send email to silverstripe-dev@googlegroups.com.
To unsubscribe from this group, send email to silverstripe-dev+unsubscribe@googlegroups.com.

UndefinedOffset

unread,
May 15, 2012, 11:49:06 AM5/15/12
to silverst...@googlegroups.com
Ok I've managed to get the saving of items working fine without reloading the whole table. Also I've made all but the previously mentioned ManyManList->foreignIDFilter() changes. I've also added a unit test let me know if it is sufficient. If you want me to look into number 8 more just let me know and I'll see what I can come up with later today.

UndefinedOffset

unread,
May 16, 2012, 9:48:39 PM5/16/12
to silverst...@googlegroups.com
Ingo,

I've pushed a change up to the repo (https://github.com/UndefinedOffset/SortableGridField/) that keeps paginator enabled but maintains sorting properly and allows you to sort cross pages. The only thing I'm not happy with is that it currently swaps the item being sorting cross pages with the item closest to the destination (bottom of the list for a previous page, top of the list for a following page) this is done to maintain the order of the other items on the pages.

I think there also needs to be a really good visual cue when you start to drag a row that it can be dropped on the page buttons. But I'm not sure what that would look like, it has to be very clear or users won't understand.

I'm struggling with how to best move the updating of the sort on the current page away from creating every object for a has_many relationship, the problem is I'm not sure how to figure out what table I need to update to ensure that the column exists on the table. I can't guarantee that the sort column exists on the given class name's table since that table may not even exist or if it does it may actually extend another data object that defines the sort column. Can you recommend away to find what table the column exists on, that way I can move way from the heavy way it's doing things now for has_many relationships.

Jakob Kristoferitsch

unread,
May 17, 2012, 5:11:54 AM5/17/12
to silverst...@googlegroups.com
UndefinedOffset wrote:
> I think there also needs to be a really good visual cue when you start
> to drag a row that it can be dropped on the page buttons. But I'm not
> sure what that would look like, it has to be very clear or users won't
> understand.

Hi,
I would suggest highlighting the page buttons, either by giving them a
border with a strong contrast (maybe green?) or by turning them into a
different (darker or lighter) color.
A very nice looking alternative would be to put a shadow mask over the
parts of the page that can not be used as drop targets, but this is
certainly more complex.

Jakob

UndefinedOffset

unread,
May 18, 2012, 9:58:45 AM5/18/12
to silverst...@googlegroups.com
I actually ended up going with a pulsing between the SS logo color and the white. Seems to work, but I'm not sure if its enough or the right fit. Also I've updated the cross page sorting so things are much better it's more of a shifting algorithm now instead of just swapping. Ingo can you have a look again and let me know what you think? I can setup a demo site later on if you want to try it out.

Sigurd Magnusson

unread,
May 18, 2012, 3:16:26 PM5/18/12
to silverst...@googlegroups.com
You wanna throw up a pic of this on skitch? :)

Sig

--
You received this message because you are subscribed to the Google Groups "SilverStripe Core Development" group.
To view this discussion on the web visit https://groups.google.com/d/msg/silverstripe-dev/-/UUvNyqMFo4cJ.

To post to this group, send email to silverst...@googlegroups.com.
To unsubscribe from this group, send email to silverstripe-d...@googlegroups.com.

UndefinedOffset

unread,
May 18, 2012, 6:38:47 PM5/18/12
to silverst...@googlegroups.com
Sig,

Skitch wouldn't let me sign up, yay broken links (redirects back to the home page when you go to the signup). I attached it to this post, not really much to see anyways. The previous page, and next page pulse blue, just fading between the white to blue then back over the course of 1.5s repeating till the row is dropped on the arrows or elsewhere in the list.


On Friday, May 18, 2012 4:16:26 PM UTC-3, Sigurd Magnusson wrote:
You wanna throw up a pic of this on skitch? :)

Sig

On 19 May 2012 01:58, UndefinedOffset wrote:
I actually ended up going with a pulsing between the SS logo color and the white. Seems to work, but I'm not sure if its enough or the right fit. Also I've updated the cross page sorting so things are much better it's more of a shifting algorithm now instead of just swapping. Ingo can you have a look again and let me know what you think? I can setup a demo site later on if you want to try it out.


On Thursday, May 17, 2012 6:11:54 AM UTC-3, Jakob Kristoferitsch wrote:
UndefinedOffset wrote:
> I think there also needs to be a really good visual cue when you start
> to drag a row that it can be dropped on the page buttons. But I'm not
> sure what that would look like, it has to be very clear or users won't
> understand.

Hi,
I would suggest highlighting the page buttons, either by giving them a
border with a strong contrast (maybe green?) or by turning them into a
different (darker or lighter) color.
A very nice looking alternative would be to put a shadow mask over the
parts of the page that can not be used as drop targets, but this is
certainly more complex.

Jakob
--
You received this message because you are subscribed to the Google Groups "SilverStripe Core Development" group.
To view this discussion on the web visit https://groups.google.com/d/msg/silverstripe-dev/-/UUvNyqMFo4cJ.

To post to this group, send email to silverstripe-dev@googlegroups.com.
To unsubscribe from this group, send email to silverstripe-dev+unsubscribe@googlegroups.com.
Grid Field Sortable.jpg

UndefinedOffset

unread,
May 28, 2012, 11:42:54 AM5/28/12
to silverst...@googlegroups.com
Just poking about this, I've updated the JS to work with the changes in 3.0 Beta 3 and things (aside from a super minor style issue) are working fine again.

UndefinedOffset

unread,
Jun 4, 2012, 6:34:17 PM6/4/12
to silverst...@googlegroups.com
Hey Ingo,

Did you still want to try and merge this into the core?

Ingo Schommer

unread,
Jun 5, 2012, 5:50:24 AM6/5/12
to silverst...@googlegroups.com
Hey there, we've missed our window of opportunity for 3.0 I think,
mostly due to us being useless in responding/reviewing rather than your work :)
From what I understand, it serves fine as a module for now, right?
It'll be good to get some real world usage out of it, and we can reconsider for 3.1.

Thanks again for your awesome work!
Ingo

--
You received this message because you are subscribed to the Google Groups "SilverStripe Core Development" group.
To view this discussion on the web visit https://groups.google.com/d/msg/silverstripe-dev/-/yPNdjGhsC-EJ.
To post to this group, send email to silverst...@googlegroups.com.
To unsubscribe from this group, send email to silverstripe-d...@googlegroups.com.

UndefinedOffset

unread,
Jun 5, 2012, 11:36:26 AM6/5/12
to silverst...@googlegroups.com
Oh well it works great as a module :)
To post to this group, send email to silverstripe-dev@googlegroups.com.
To unsubscribe from this group, send email to silverstripe-dev+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages