formtastic_grouped_check_boxes 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9f3d955d833d5ceb811a388f7e00ce870f8fa53e8f8c703e49a7e549349f4fa4
4
+ data.tar.gz: 36bf37b3e215387547bd12adb674b13f3a819b42e1b7fd001e82e5967f096ec3
5
+ SHA512:
6
+ metadata.gz: 8f72c14546ae640f567f3144737cc1cc2f54809eb9d20808022d9688f408bdfb6e1f622075b7cfa6f184287857c111ca869094eafd2aa562088a401845ba1681
7
+ data.tar.gz: ade6206ca2f57fad0ebaa83db7516a23fdb847a394720b9a1b8330a21b33e469ac021d116b36ab6248fec0d95827a08a1639282657c0a05d7f0a72857cfa0d1e
data/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ # Changelog
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec # Specify your gem's dependencies in .gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2023 Sergey Pedan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # Formtastic grouped checkboxes
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem "formtastic_grouped_check_boxes"
9
+ ```
10
+
11
+ Import our Sass file “formtastic-grouped-check-boxes.css” in your CSS entrypoint that compiles CSS files:
12
+
13
+ ```sass
14
+ // app/assets/stylesheets/application.sass
15
+
16
+ // Your regular ActiveAdmin files
17
+ @import ...
18
+ @import ...
19
+
20
+ // This gem’s files
21
+ @import "formtastic-grouped-check-boxes"
22
+ ```
23
+
24
+ ## Use
25
+
26
+ This gem adds a new input type `:grouped_check_boxes`.
27
+
28
+ It also adds 3 new input options, 2 of which follow the Rails naming convention from `grouped_collection_select`:
29
+
30
+ - `group_method` — The name of a method which, when called on a member of collection, returns an array of child objects. It can also be any object that responds to call, such as a proc, that will be called for each member of the collection to retrieve the value.
31
+ - `group_label_method` — The name of a method which, when called on a member of collection, returns a string to be used as the label attribute for its <optgroup> tag. It can also be any object that responds to call, such as a proc, that will be called for each member of the collection to retrieve the label.
32
+ - `group_label_parent` — Whether to prepend the fieldset label with the parent input title
33
+
34
+ ```ruby
35
+ ActiveAdmin.register Project do
36
+ permit_params technology_ids: []
37
+
38
+ form do |f|
39
+ f.inputs "Technologies" do
40
+ f.input :technologies,
41
+ as: :grouped_check_boxes, \
42
+ collection: Technology.select(:id, :name, :area_id).includes(:area).order(:name), \
43
+ group_method: :area, \
44
+ group_label_method: :name, \
45
+ group_label_parent: true
46
+ end
47
+ end
48
+ end
49
+ ```
50
+
51
+ Providing that
52
+
53
+ ```ruby
54
+ class Technology < ApplicationRecord
55
+ belongs_to :area, foreign_key: :area_id, class_name: "TechnologyArea", optional: true
56
+ end
57
+ ```
58
+
59
+ ```ruby
60
+ class TechnologyArea < ApplicationRecord
61
+ has_many :technologies
62
+ end
63
+ ```
64
+
65
+ Results in
66
+
67
+ ```html
68
+ <fieldset class="inputs">
69
+ <legend><span>Technologies</span></legend>
70
+ <ol>
71
+ <li class="grouped_check_boxes check_boxes input optional" id="project_technologies_input">
72
+ <input type="hidden" name="project[technology_ids][]" id="project_technologies_none" value="" autocomplete="off">
73
+
74
+ <fieldset class="choices grouped_check_boxes__choices">
75
+ <legend class="label grouped_check_boxes__legend">
76
+ <label class="grouped_check_boxes__legend__label">Technologies / No subgroup</label>
77
+ </legend>
78
+
79
+ <ol class="choices-group grouped_check_boxes__choices-group">
80
+ <li class="choice grouped_check_boxes__choice">
81
+ <label for="project_technology_ids_46">
82
+ <input type="checkbox" name="project[technology_ids][]" id="project_technology_ids_46" value="46">BitBucket
83
+ </label>
84
+ </li>
85
+ <li class="choice grouped_check_boxes__choice">
86
+ <label for="project_technology_ids_138">
87
+ <input type="checkbox" name="project[technology_ids][]" id="project_technology_ids_138" value="138">BrainTree API (Ruby SDK)
88
+ </label>
89
+ </li>
90
+ </ol>
91
+ </fieldset>
92
+
93
+ <fieldset class="choices grouped_check_boxes__choices">
94
+ <legend class="label grouped_check_boxes__legend">
95
+ <label class="grouped_check_boxes__legend__label">Technologies / Marketing</label>
96
+ </legend>
97
+
98
+ <ol class="choices-group grouped_check_boxes__choices-group">
99
+ <li class="choice grouped_check_boxes__choice">
100
+ <label for="project_technology_ids_59">
101
+ <input type="checkbox" name="project[technology_ids][]" id="project_technology_ids_59" value="59">Direct sales
102
+ </label>
103
+ </li>
104
+ <li class="choice grouped_check_boxes__choice">
105
+ <label for="project_technology_ids_89">
106
+ <input type="checkbox" name="project[technology_ids][]" id="project_technology_ids_89" value="89">Google Analytics
107
+ </label>
108
+ </li>
109
+ </ol>
110
+ </fieldset>
111
+ </li>
112
+ </ol>
113
+ </fieldset>
114
+ ```
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+
5
+ # APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
6
+ load "rails/tasks/engine.rake"
7
+ load "rails/tasks/statistics.rake"
8
+
9
+ require "bundler/gem_tasks"
10
+ require "rspec/core/rake_task"
11
+ RSpec::Core::RakeTask.new(:spec)
12
+ task default: :spec
@@ -0,0 +1,19 @@
1
+ .grouped_check_boxes
2
+ &__legend
3
+ margin-left: 0.75rem
4
+ width: max-content
5
+
6
+ &__label
7
+ float: none
8
+ width: 100%
9
+
10
+ &__choices
11
+ border: solid 1px hsla(0, 0%, 50%, 0.2)
12
+ padding-bottom: 1rem
13
+ padding-top: 0.5rem
14
+
15
+ & + &
16
+ margin-top: 1rem
17
+
18
+ &__choices-group
19
+ margin-bottom: 0
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GroupedCheckBoxesInput < Formtastic::Inputs::CheckBoxesInput
4
+
5
+ # => "<li class=\"grouped_check_boxes check_boxes input optional\" >...</li>"
6
+ # we want to reuse existing CSS from regular checkboxes
7
+ #
8
+ def as
9
+ super + " check_boxes"
10
+ end
11
+
12
+
13
+ # input_wrapping # => "<li class=\"grouped_check_boxes input optional\" id=\"project_technologies_input\">\n\n</li>"
14
+ # hidden_field_for_all # => "<input type=\"hidden\" name=\"project[technology_ids][]\" id=\"project_technologies_none\" value=\"\" autocomplete=\"off\" />"
15
+ #
16
+ def to_html
17
+ input_wrapping do
18
+ hidden_field_for_all << fieldsets_for_groups
19
+ end
20
+ end
21
+
22
+
23
+ # legend_html # => "<legend class=\"label\"><label>Technologies</label></legend>"
24
+ # choices_wrapping # => "<fieldset class=\"choices\"></fieldset>"
25
+ #
26
+ def fieldsets_for_groups
27
+ grouped_collection.
28
+ map { |group_method_call_return_value, group_records|
29
+ choices_wrapping do
30
+ legend_html(group_method_call_return_value) << lis_with_checkboxes(group_records)
31
+ end
32
+ }.join("\n").html_safe
33
+ end
34
+
35
+
36
+ def choices_wrapping_html_options
37
+ { class: ["choices", "grouped_check_boxes__choices"] }
38
+ end
39
+
40
+
41
+ def legend_html(group_method_call_return_value)
42
+ template.content_tag :legend, label_html_options.merge(class: ["label", "grouped_check_boxes__legend"]) do
43
+ template.content_tag :label, class: "grouped_check_boxes__legend__label" do
44
+ acc = []
45
+ acc << (label_text + " / ") if input_options[:group_label_parent]
46
+ acc << group_name(group_method_call_return_value)
47
+ acc.join("\n").html_safe
48
+ end
49
+ end
50
+ end
51
+
52
+
53
+ # choices_group_wrapping # => <ol class="choices-group">...</ol>
54
+ #
55
+ def lis_with_checkboxes(records)
56
+ choices_group_wrapping do
57
+ choices_group_contents(records)
58
+ end
59
+ end
60
+
61
+
62
+ def choices_group_wrapping_html_options
63
+ { class: ["choices-group", "grouped_check_boxes__choices-group"] }
64
+ end
65
+
66
+
67
+ # @return [String] of concatenated <li>s
68
+ #
69
+ def choices_group_contents(group_choice_records)
70
+ normalized_collection(collection, group_choice_records).map { |choice|
71
+ choice_wrapping(choice_wrapping_html_options(choice)) { # <li class="choice">
72
+ choice_html(choice) # <label for="project_technology_ids_49">
73
+ # <input type="checkbox" name="project[technology_ids][]" id="project_technology_ids_49" value="49" />AWS Route53
74
+ # </label>
75
+ } # </li>
76
+ }.join("\n").html_safe
77
+ end
78
+
79
+
80
+ def choice_wrapping_html_options(choice)
81
+ classes = ["choice", "grouped_check_boxes__choice"]
82
+ classes << "#{sanitized_method_name.singularize}_#{choice_html_safe_value(choice)}" if value_as_class?
83
+
84
+ { class: classes.join(" ") }
85
+ end
86
+
87
+
88
+ def grouped_collection
89
+ fail "You must provide a `:collection` input option" unless collection_from_options
90
+
91
+ case (predicat = input_options.fetch(:group_method))
92
+ when Proc then collection_from_options.group_by { |record| predicat.call(record) }
93
+ when Symbol then collection_from_options.group_by { |record| record.public_send(predicat) }
94
+ else fail "You must provide either a Proc or a Symbol in the `:group_method` input option"
95
+ end
96
+ end
97
+
98
+
99
+ # `collection` is an Array of [label, value] Arrays, so `arr_el.second` will return the <option value="">
100
+ # `group_records` is an Array of ActiveRecord objects
101
+ # `value_method` is a Symbol of the method name called on each record to get what to insert into the <option value="">
102
+ #
103
+ def normalized_collection(collection, group_records)
104
+ collection.select do |arr_el|
105
+ group_records
106
+ .map(&value_method.to_sym)
107
+ .include?(arr_el.second)
108
+ end
109
+ end
110
+
111
+
112
+ def group_name(group_record_or_label)
113
+ return "No subgroup" unless group_record_or_label
114
+
115
+ if (label_method = input_options[:group_label_method].presence)
116
+ group_record_or_label.public_send(label_method)
117
+ else
118
+ group_record_or_label
119
+ end
120
+ end
121
+
122
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://guides.rubygems.org/name-your-gem/
4
+ # https://bundler.io/guides/creating_gem.html
5
+ # https://guides.rubyonrails.org/engines.html
6
+ # https://guides.rubyonrails.org/plugins.html
7
+
8
+ require_relative "lib/formtastic_grouped_check_boxes/version"
9
+
10
+ Gem::Specification.new do |spec|
11
+ spec.name = "formtastic_grouped_check_boxes"
12
+ spec.version = FormtasticGroupedCheckBoxes::VERSION
13
+ spec.authors = ["Sergey Pedan"]
14
+ spec.email = ["sergey.pedan@gmail.com"]
15
+ spec.license = "MIT"
16
+
17
+ spec.summary = "..."
18
+ spec.description = <<~HEREDOC
19
+ #{spec.summary}. This gem:
20
+ HEREDOC
21
+
22
+ spec.homepage = "https://github.com/sergeypedan/formtastic-grouped-checkboxes"
23
+ spec.extra_rdoc_files = ["README.md", "CHANGELOG.md"]
24
+ spec.rdoc_options = ["--charset=UTF-8"]
25
+ spec.metadata = { "changelog_uri" => "#{spec.homepage}/blob/master/CHANGELOG.md",
26
+ "documentation_uri" => "https://www.rubydoc.info/gems/#{spec.name}",
27
+ "homepage_uri" => spec.homepage,
28
+ "source_code_uri" => spec.homepage }
29
+
30
+ spec.require_paths = ["app/inputs", "lib"]
31
+ spec.bindir = "exe"
32
+ spec.executables = []
33
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
34
+ `git ls-files`.split("\n")
35
+ .reject { |f| %w[bin spec test].any? { |dir| f.start_with? dir } }
36
+ .reject { |f| f.start_with? "." }
37
+ end
38
+
39
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
40
+
41
+ spec.add_dependency "formtastic", ">= 3", "< 5"
42
+ spec.add_dependency "rails", ">= 4", "< 10"
43
+
44
+ spec.add_development_dependency "rspec", "~> 3"
45
+ spec.add_development_dependency "yard", ">= 0.9.20", "< 1"
46
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FormtasticGroupedCheckBoxes
4
+
5
+ # This is standard Rails way to autoload gem’s contents dynamically as an “engine”
6
+ # @see https://guides.rubyonrails.org/engines.html Rails guide on engines
7
+ #
8
+ class Engine < ::Rails::Engine
9
+ end
10
+
11
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FormtasticGroupedCheckBoxes
4
+ VERSION = "0.0.1"
5
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "formtastic_grouped_check_boxes/version"
4
+ require_relative "formtastic_grouped_check_boxes/engine"
5
+ require_relative "../app/inputs/grouped_check_boxes_input"
6
+
7
+ module FormtasticGroupedCheckBoxes
8
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: formtastic_grouped_check_boxes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sergey Pedan
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-07-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: formtastic
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5'
33
+ - !ruby/object:Gem::Dependency
34
+ name: rails
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '4'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '10'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '4'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '10'
53
+ - !ruby/object:Gem::Dependency
54
+ name: rspec
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3'
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '3'
67
+ - !ruby/object:Gem::Dependency
68
+ name: yard
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 0.9.20
74
+ - - "<"
75
+ - !ruby/object:Gem::Version
76
+ version: '1'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 0.9.20
84
+ - - "<"
85
+ - !ruby/object:Gem::Version
86
+ version: '1'
87
+ description: ".... This gem:\n"
88
+ email:
89
+ - sergey.pedan@gmail.com
90
+ executables: []
91
+ extensions: []
92
+ extra_rdoc_files:
93
+ - README.md
94
+ - CHANGELOG.md
95
+ files:
96
+ - CHANGELOG.md
97
+ - Gemfile
98
+ - MIT-LICENSE
99
+ - README.md
100
+ - Rakefile
101
+ - app/assets/stylesheets/formtastic-grouped-check-boxes.sass
102
+ - app/inputs/grouped_check_boxes_input.rb
103
+ - config/routes.rb
104
+ - formtastic_grouped_check_boxes.gemspec
105
+ - lib/formtastic_grouped_check_boxes.rb
106
+ - lib/formtastic_grouped_check_boxes/engine.rb
107
+ - lib/formtastic_grouped_check_boxes/version.rb
108
+ homepage: https://github.com/sergeypedan/formtastic-grouped-checkboxes
109
+ licenses:
110
+ - MIT
111
+ metadata:
112
+ changelog_uri: https://github.com/sergeypedan/formtastic-grouped-checkboxes/blob/master/CHANGELOG.md
113
+ documentation_uri: https://www.rubydoc.info/gems/formtastic_grouped_check_boxes
114
+ homepage_uri: https://github.com/sergeypedan/formtastic-grouped-checkboxes
115
+ source_code_uri: https://github.com/sergeypedan/formtastic-grouped-checkboxes
116
+ post_install_message:
117
+ rdoc_options:
118
+ - "--charset=UTF-8"
119
+ require_paths:
120
+ - app/inputs
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: 2.4.0
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubygems_version: 3.0.3.1
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: "..."
137
+ test_files: []