Skip to content

Conversation

igorbernstein
Copy link
Contributor

This is a revival of #2614, #881, #2117, #880
Its a still a work in progress, but I wanted to post this early on to make sure I'm on the right path and this doesn't slip through the cracks.

TODO:

@igorbernstein
Copy link
Contributor Author

@seanlinsley, are the jasmine tests used? or should I implement cucumber/capybara tests?

@seanlinsley
Copy link
Contributor

We have Jasmine, but have never actually used it. I'd very much like to have JS tests, but for some reason Jasmine is throwing an error when I try running it.

@igorbernstein
Copy link
Contributor Author

This only thing thats missing here are tests. But the jasmine tests are broken & there doesn't appear to be any js tests implemented via cucumber/capybara. Unfortunately I don't have time to open up that can of worms (figuring out why jasmine is broken and then fixing all the existing tests because they haven't been run in awhile).

@seanlinsley Would you merge this w/o js tests? or should I spin this off into a separate gem?

@seanlinsley
Copy link
Contributor

Would you merge this w/o js tests?

I'll answer your question with a question: is there anything I can do to get you to write tests? Any way I can accommodate your skills and schedule?

or should I spin this off into a separate gem?

I'd hope not! IMO the whole create "spin-off gems extending AA" thing was just a way for the previous maintainers to be lazy. We don't need more fragmentation.

@igorbernstein
Copy link
Contributor Author

I have a couple of competing goals:

  1. I want to make some meaningful contributions to open source software (i.e. View layer overhaul #2689)
  2. I need to implement a couple of admin interfaces for a couple of clients

One of the admin interfaces that a client signed off on was a sortable has_many UI, which was implemented in my fork, but was antiquated by the changes in #2679. Hence this PR, which rebases that functionality on current FormBuilder structure.

My client's next priority is to get an autocomplete widget for selecting editions for their homepage. Since they will need both functionalities, I will need to have one of these features merged in master or available in a gem or living in my own fork of active admin.

I don't have a problem with writing tests for this functionality, but I'm concerned about the amount of work necessary to get my tests running along side the existing js tests & passing again, so I can't commit to working on that until december. The path of least resistance for me would be: to get this merged into master, open up a PR for the autocomplete feature, base my client's admin off that PR, then deal with jasmine tests as a whole in december.

@shekibobo
Copy link
Contributor

@igorbernstein Just FYI, Select2 is actually pretty simple to integrate in ActiveAdmin on its own. In my apps, I simply add select2 to all select fields. Then for other types of fields, like tags and tokenizable fields, I just write a new Formtastic input and JS to get the behavior I need. While I think it would be great to have these features integrated fully into ActiveAdmin, it is by no means a requirement to have these features integrated within an application instance.

@seanlinsley
Copy link
Contributor

@igorbernstein if you're going to be around for the long haul then I think we can forgo the tests for now. Later this month I'll try tackling the JS testing issue so we have a framework that is actually operational.

Is this PR fully functional? I'll try it out locally and we can hopefully get it merged tonight.

parent.children('fieldset').each ->
fieldset = $(@)
destroy = fieldset.find ':input[name$="[_destroy]"]'
sortable_input = fieldset.find ":input[name$='[#{input_name}]']:eq(0)"
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the :eq(0) necessary? Are there going to be multiple inputs with the same name?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm kinda hair-splitting here but line 7 uses " '' " while line 8 uses ' "" '. One way or another, I think they should be consistent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the eq(0) is necessary in the nested has_many case
sorry about the inconsistency, i'll switch it to " ' ' " because I need to interpolate the input_name

Copy link
Contributor

Choose a reason for hiding this comment

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

In that case wouldn't it make more sense to have a direct descendent CSS rule?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its a little ugly:

    sortable_input = fieldset.find ">  ol > li > :input[name$='[#{input_name}]']"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

also the _destroy finder has the same issues

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added the correct but ugly selectors for the time being

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, so the simplest ideas I have are:

  1. the closestDescendant plugin
  2. or just to localize the crazy in a helper:
recompute_positions = (parent)->
    ....
    destroy = find_fieldset_input fieldset, "_destroy"
    sortable_input = find_fieldset_input fieldset, input_name

find_fieldset_input = (parent, name)->
  parent.find "> ol > .input > :input[name$='[#{name}]']"

edit: i prefer no. 2

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally I prefer it like it is, with long but obvious CSS selectors. As the behavior grows it might be worth it to abstract things some more, but for now I think what you already have in the PR is appropriate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm cool with that, I added a comment to avoid future head scratching

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.18%) when pulling 3e6d51e on igorbernstein:has_many-sortable into 12b19a7 on gregbell:master.

f.inputs :taggings, sortable: :position do |t|
t.input :tag
t.input :position
end
Copy link
Contributor

Choose a reason for hiding this comment

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

This would be has_many, not inputs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sorry that was sloppy. fixed now

@seanlinsley
Copy link
Contributor

One problem I noticed is that if there's another f.inputs block on the page, the arrows on the right side don't scope to just the f.has_many area

@igorbernstein
Copy link
Contributor Author

Not sure what you mean about arrows not scoping to just the .has_many area...but maybe I accidentally fixed it in the other changes?

  • I moved the arrows to the top right corner instead of right center, to avoid losing them on longer forms and mixing them up with other arrows from nested has_many fieldsets
  • I'm trying out @shekibobo original approach of just making the arrows draggable
  • I fixed the invalid mark up ol > span.handle to ol > li.handle

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.21%) when pulling 77ceec9 on igorbernstein:has_many-sortable into 12b19a7 on gregbell:master.

@seanlinsley
Copy link
Contributor

This is a screenshot I took earlier today illustrating the problem. Haven't tried your updated code yet.

screen shot 2013-11-13 at 11 41 55 am

@igorbernstein
Copy link
Contributor Author

Can you post the form definition code for that screenshot?

On Wed, Nov 13, 2013 at 7:33 PM, Sean Linsley notifications@github.comwrote:

This is a screenshot I took earlier today illustrating the problem.
Haven't tried your updated code yet.

[image: screen shot 2013-11-13 at 11 41 55 am]https://f.cloud.github.com/assets/688886/1537367/56fa0bb2-4cc4-11e3-95b6-ba3024977824.png


Reply to this email directly or view it on GitHubhttps://github.com//pull/2656#issuecomment-28449254
.

@seanlinsley
Copy link
Contributor

It was a f.inputs block, followed by a f.has_many block. Let's see if I still have the code around...

@seanlinsley
Copy link
Contributor

Here it is:

  form do |f|
    f.inputs :body
    f.has_many :taggings, sortable: :position do |t|
      t.input :tag
      t.input :position
    end
    f.actions
  end

@igorbernstein
Copy link
Contributor Author

thanks! just pushed a fix

On Wed, Nov 13, 2013 at 7:41 PM, Sean Linsley notifications@github.comwrote:

Here it is:

form do |f|
f.inputs :body
f.has_many :taggings, sortable: :position do |t|
t.input :tag
t.input :position
end
f.actions
end


Reply to this email directly or view it on GitHubhttps://github.com//pull/2656#issuecomment-28449785
.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.18%) when pulling 5ec157c on igorbernstein:has_many-sortable into 12b19a7 on gregbell:master.

@seanlinsley
Copy link
Contributor

screen shot 2013-11-13 at 7 53 03 pm

Cool.

What about centering the handle vertically to the fieldset? With this CSS:

.has_many_container .handle {
  top: calc(50% - 3em / 2);
}

You get a nicely centered handle:

screen shot 2013-11-13 at 7 59 45 pm

Also, it'd be great if the developer didn't have to manually build the input for the sortable attribute, and it was built automatically.

@igorbernstein
Copy link
Contributor Author

never ran across calc before...its pretty cool
the original css was vertically centering the arrows with:

    margin-top: -1.5em;
    top: 50%;

But I changed it because the arrows gets lost on longer fieldsets
Also, with nested sortable is complete confusion:

overlapping arrows

@igorbernstein
Copy link
Contributor Author

👍 👍 on auto generating sortable input

@seanlinsley
Copy link
Contributor

the problem with the image you attached is that the nested has_many fieldsets don't have a big enough margin on the right to give room for the parent's handle

@igorbernstein
Copy link
Contributor Author

i moved the arrows back to the vertical center, but could use some help making the margins look ok...ui & css aren't not a strong suit of mine

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.21%) when pulling aa24c69 on igorbernstein:has_many-sortable into 12b19a7 on gregbell:master.

@seanlinsley
Copy link
Contributor

Could you use the calc setting I gave earlier? That will get it exactly in the middle, accounting for the height of the icons.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.21%) when pulling bd5279b on igorbernstein:has_many-sortable into 12b19a7 on gregbell:master.

@igorbernstein
Copy link
Contributor Author

pushed, though for personal curiosity, I don't understand why the negative margin gives different results from the calc

ie. why is calculation of:

calc(50% - HEIGHT / 2);

different from

top: 50%;
margin-top:- HEIGHT/2;

@seanlinsley
Copy link
Contributor

In my browser these both have the same effect:

top: calc(50% - 3em / 2);

/* and */

top: 50%;
margin-top: -1.5em;

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.21%) when pulling bd5279b on igorbernstein:has_many-sortable into 12b19a7 on gregbell:master.

@igorbernstein
Copy link
Contributor Author

I guess we had a miscommunication somewhere around commit aa24c69 & your 'Could you use the calc setting I gave earlier? That will get it exactly in the middle, accounting for the height of the icons.' comment.

But I don't think it really matters.

When you have a free moment, would you mind suggesting how I can improve the right margins to avoid arrow soup when nesting sortables?

@@ -64,6 +64,12 @@ ActiveAdmin.register Post do
end
end
f.inputs do
f.has_many :taggings, sortable: :position do |t|
t.input :tag
t.input :position
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you update this since the t.input :position part is no longer needed?

Copy link
Contributor

Choose a reason for hiding this comment

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

This still needs to be updated

@seanlinsley
Copy link
Contributor

I just noticed an interesting bug. Given this form:

  form do |f|
    f.semantic_errors *f.object.errors.keys
    f.inputs
    f.has_many :posts, allow_destroy: true do |o|
      o.input :title
      o.has_many :taggings, sortable: :position do |t|
        t.input :tag
      end
    end
    f.actions
  end

A just-added post's taggings aren't sortable.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.21%) when pulling a44c440 on igorbernstein:has_many-sortable into 12b19a7 on gregbell:master.

@igorbernstein
Copy link
Contributor Author

I cherry picked the css changes from your PR.

Good catch on b8bba4b , but I think we should generalize your solution a bit.
How would you feel about generalized initialize_content, teardown_content events? The idea being that dynamic overlays & has_many widgets can generate the same events & all widgets will just work™.

# application
$ ->
  $(document).trigger('initialize_content')

# datepicker
$(document).on('initialize_content', (e) ->
  $(@).find('.datepicker').datepicker()

$(document).on('teardown_content', (e) ->
  $(@).find('.datepicker').datepicker('destroy')

# has_many (in addition to the existing  has_many_*:* events)
$(document).on 'click', 'a.button.has_many_add', (e)->
  # ..
  fieldset.trigger('initialize_content')

# sortable
$(document).on 'initialize_content' (e)->
  $('.has_many_container[data-sortable]').sortable()

@seanlinsley
Copy link
Contributor

How about we get this PR merged first, in a state where it's fully functional? In general I'm all for standardizing the way our JavaScript works.

@igorbernstein
Copy link
Contributor Author

I think you can merge this, I'll open up a separate PR to deal with the generalized widget initialization I mentioned earlier.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.33%) when pulling b59e82c8dfdb2dd3888419a7a7aed8876a3ddd1a on igorbernstein:has_many-sortable into 12b19a7 on gregbell:master.

@seanlinsley
Copy link
Contributor

Hmm, 21 commits for 100 changes... Would you mind squashing this either into one commit or a handful of commits?

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.21%) when pulling 7cbcf32 on igorbernstein:has_many-sortable into 131c3a4 on gregbell:master.

@seanlinsley
Copy link
Contributor

Awesome. Thanks for working on this! 💙

seanlinsley added a commit that referenced this pull request Nov 17, 2013
@seanlinsley seanlinsley merged commit 00f97ac into activeadmin:master Nov 17, 2013
@igorbernstein
Copy link
Contributor Author

Thanks for helping :)

@coveralls
Copy link

Coverage Status

Coverage remained the same when pulling 7cbcf32 on igorbernstein:has_many-sortable into 131c3a4 on gregbell:master.

parent.trigger 'has_many_add:after', [ fieldset ]

$(document).on 'change','.has_many_container[data-sortable] :input[name$="[_destroy]"]', ->
recompute_positions $(@).closest '.has_many'
Copy link
Contributor

Choose a reason for hiding this comment

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

Wait, what exactly is the purpose of this? Why would you need to recompute positions when the user clicks a checkbox?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

because we don't want to include the ones marked for destruction to be included in the count...

item0
position: 0

item1
position: ''
_destroy: true

item2
position: 1

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh I see. Ignore me :)

@igorbernstein igorbernstein deleted the has_many-sortable branch November 17, 2013 20:23
@Babbz75
Copy link

Babbz75 commented Nov 22, 2016

@kirel Thank you!

For acts_as_list people wondering why the list is rotating you need to start the sort at 1. i.e. sortable_start: 1 otherwise it bumps the zero to one and then with two positions at 1 it will bump the first one to the bottom. At least I believe that's what was happening to me

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.

6 participants