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

Replace Select2 with SlimSelect #448

Merged
merged 23 commits into from
Mar 17, 2023
Merged

Replace Select2 with SlimSelect #448

merged 23 commits into from
Mar 17, 2023

Conversation

gmq
Copy link
Member

@gmq gmq commented Mar 6, 2023

Context

Select2 is difficult to configure and use with newer bundlers based on esbuild. Rather than attempting to make it work, this pull request replaces the library with a more up-to-date alternative while attempting to maintain similar usage.

Breaking Changes

This implementation replaces ActiveAdmin's jQuery events with a MutationObserver. Instead of listening to has_many_* events, the MutationObserver watches for new elements and initializes slim-select where necessary. It covers most typical use cases, but there may be scenarios that I have not taken into account.

Changes

I added our standard ESLint configuration to accommodate the use of ES6 syntax in newer files. This may result in a lot of red lines in older files, but since they are not touched often, it shouldn't be a major issue.

Possible Issues

It may be necessary to fork slim-select to fix outstanding issues since the author of the library works sporadically on it. This is alleviated in part by the fact that we don't really need any new features. Once we get it working with no issues, there won't be a need for continued development, and we can contribute the fixes to upstream.

@@ -4,7 +4,7 @@ module ActiveadminAddons
attr_writer :default_select, :datetime_picker_default_options, :datetime_picker_input_format

def default_select
return "select2" unless @default_select
return "slim-select" unless @default_select
Copy link

Choose a reason for hiding this comment

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

[rubocop] reported by reviewdog 🐶
Add empty line after guard clause.

on_input_ctx("invoice_region_id") { select2_options_container.click }
on_input_ctx("invoice_city_id") { open_select2_options }
expect_select2_result_text_to_eq(1, msg)
msg = "Input is too short"
Copy link

Choose a reason for hiding this comment

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

⚠️ [rubocop] reported by reviewdog 🐶
Useless assignment to variable - msg.

end
end

context "when default config is Active Admin's default and select control has select 2 class" do
context "when default config is Active Admin's default and select control has slim-select class" do
Copy link

Choose a reason for hiding this comment

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

[rubocop] reported by reviewdog 🐶
Line is too long. [101/100]

fill_select2_input_and_press_return("Not preloaded item")
expect_select2_choices_count_to_eq(1)
expect_slimselect_options_count_to_eq(3)
expect { add_slimselect_option("Not preloaded item") }.to raise_error(Capybara::ElementNotFound)
Copy link

Choose a reason for hiding this comment

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

[rubocop] reported by reviewdog 🐶
Line is too long. [104/100]

end

def select2_input
find(".select2-search__field")
def expect_slimselect_options_count_to_eq(count, id=nil)
Copy link

Choose a reason for hiding this comment

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

[rubocop] reported by reviewdog 🐶
Surrounding space missing in default value assignment.

def select2_input
find(".select2-search__field")
def expect_slimselect_options_count_to_eq(count, id=nil)
id = slimselect_original_select_id unless id
Copy link

Choose a reason for hiding this comment

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

[rubocop] reported by reviewdog 🐶
Use the double pipe equals operator ||= instead.

def expect_select2_options_count_to_eq(count)
expect(page).to have_css("select.select2-hidden-accessible option", count: count)
def pick_slimselect_entered_option(item_text, display_name = nil)
display_name = item_text unless display_name
Copy link

Choose a reason for hiding this comment

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

[rubocop] reported by reviewdog 🐶
Use the double pipe equals operator ||= instead.

end

def expect_slimselect_popover_is_closed(id = nil)
expect(page.document).not_to have_css(".ss-content[data-id=#{id || slimselect_original_select_id}]")
Copy link

Choose a reason for hiding this comment

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

[rubocop] reported by reviewdog 🐶
Line is too long. [104/100]

Copy link
Contributor

@difernandez difernandez left a comment

Choose a reason for hiding this comment

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

Nice! Like how the js of different slim select input types is organized 💯. I leave some comments, let me know what you think. I only reviewed the code, when I have some time I'll do some testing in local and I'll come back if I find something

package.json Outdated
Comment on lines 28 to 29
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-platanus": "^0.1.0",
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should also go in devDependencies

@@ -1,6 +1,10 @@
class ActiveAdmin::Inputs::SelectInput < Formtastic::Inputs::SelectInput
def input_html_options
super.merge(data: { tags: @options[:tags].present? })
if @options[:tags].present?
super.deep_merge(data: { tags: true }, class: 'simple-tags-input')
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 data: { tags: true } necessary now? It was added in this PR because select2 received options via data-* attributes, not sure if slim select needs it

}

function setupSelect(el) {
// eslint-disable-next-line no-new
Copy link
Contributor

Choose a reason for hiding this comment

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

there's no new in the next line, don't think this is necessary

@@ -2,11 +2,10 @@
/**
* Warning: This file is auto-generated, do not modify. Instead, make your changes in 'app/javascript/activeadmin_addons/' and run `yarn build`
*/
//= require select2.full
Copy link
Contributor

Choose a reason for hiding this comment

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

we have a select2.full.js and select2.css in our vendor, should we also remove it?

// eslint-disable-next-line max-statements
newVal.forEach((data) => {
const itemId = `${prefix}_${data.value}`;
if (document.querySelectorAll(`#${itemId}`).length > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

we could use querySelector to not gather all of them

!!document.querySelector(`#${itemId}`)

// eslint-disable-next-line no-unused-vars
const { id, ...rest } = item;

return { ...rest, value: item.id, selected: !!item.selected };
Copy link
Contributor

Choose a reason for hiding this comment

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

you could use id instead of item.id, and avoid the eslint-disable a couple lines before

hiddenInput.name = itemName;
hiddenInput.value = data.value;
hiddenInput.type = 'hidden';
hiddenInput.textContent = data.text;
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure, but is it okay for the input to have textContent?

Copy link
Member Author

Choose a reason for hiding this comment

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

It appends the text next to the input, but I can't remember why I added it so I removed it.

return queryArray.join('&');
}

// eslint-disable-next-line import/prefer-default-export
Copy link
Contributor

Choose a reason for hiding this comment

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

We recently changed this rule to prefer named exports in Potassium, maybe we should update it here too

Copy link
Member

@ldlsegovia ldlsegovia left a comment

Choose a reason for hiding this comment

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

I have manually tested the functionality in the Dummy app and I found these details:

  1. Indentation:
    before:
    image

    after:
    image

  2. Cleaning button
    before:
    image
    after:
    image

  3. Red border:
    before:
    image
    after:
    image

  4. Clean value after selecting
    before:
    image
    after:
    image

app/inputs/nested_level_input.rb Show resolved Hide resolved
Copy link
Contributor

@difernandez difernandez left a comment

Choose a reason for hiding this comment

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

One small detail, otherwise it's looking pretty good to me 👌I'll try the branch later today to see if there's anything else. One other thing I just remembered: we should update the docs, there are various mentions of select2 in there, as well as filenames like select2_search.md

spec/features/inputs/tags_input_spec.rb Outdated Show resolved Hide resolved
@gmq gmq requested a review from difernandez March 13, 2023 19:34
@gmq gmq changed the base branch from v2 to master March 14, 2023 14:00
Copy link
Contributor

@difernandez difernandez left a comment

Choose a reason for hiding this comment

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

Found a couple things while testing this:

  • Display text is being interpreted as html. The part between <> dissapears and is an html tag in devtools
Screen.Recording.2023-03-16.at.11.49.57.mov

image

  • Interactive tag is not working for me 🤔 select appears and disappears immediately
Screen.Recording.2023-03-16.at.11.56.42.mov

Copy link
Member

@ldlsegovia ldlsegovia left a comment

Choose a reason for hiding this comment

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

Excellent! The only issue that remains is the indentation problem. Could you review that please? :)

Copy link
Contributor

@difernandez difernandez left a comment

Choose a reason for hiding this comment

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

excellent! 👏 🚀

Copy link
Member

@ldlsegovia ldlsegovia left a comment

Choose a reason for hiding this comment

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

👏🏻

@gmq gmq merged commit 7614d15 into master Mar 17, 2023
@gmq gmq deleted the remove-select2 branch March 17, 2023 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants