formtastic_grouped_check_boxes 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []