bootstrap-cells 0.1.5

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.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.gitlab-ci.yml +13 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +27 -0
  6. data/CHANGELOG +29 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.lock +200 -0
  9. data/Rakefile +8 -0
  10. data/app/assets/javascripts/bootstrap-cells/add_many_event_listeners.js +11 -0
  11. data/app/assets/javascripts/bootstrap-cells/index.js +3 -0
  12. data/app/assets/stylesheets/_bootstrap-cells.scss +7 -0
  13. data/app/views/kaminari/bootstrap/_first_page.html.erb +15 -0
  14. data/app/views/kaminari/bootstrap/_gap.html.erb +12 -0
  15. data/app/views/kaminari/bootstrap/_last_page.html.erb +16 -0
  16. data/app/views/kaminari/bootstrap/_next_page.html.erb +16 -0
  17. data/app/views/kaminari/bootstrap/_page.html.erb +17 -0
  18. data/app/views/kaminari/bootstrap/_paginator.html.erb +32 -0
  19. data/app/views/kaminari/bootstrap/_prev_page.html.erb +16 -0
  20. data/bin/console +15 -0
  21. data/bin/setup +8 -0
  22. data/bootstrap-cells.gemspec +36 -0
  23. data/lib/bootstrap-cells.rb +16 -0
  24. data/lib/bootstrap-cells/cells/alert/body.erb +7 -0
  25. data/lib/bootstrap-cells/cells/alert/show.erb +7 -0
  26. data/lib/bootstrap-cells/cells/alert/title.erb +9 -0
  27. data/lib/bootstrap-cells/cells/alert_cell.rb +39 -0
  28. data/lib/bootstrap-cells/cells/base_cell.rb +43 -0
  29. data/lib/bootstrap-cells/cells/button/show.erb +17 -0
  30. data/lib/bootstrap-cells/cells/button_cell.rb +41 -0
  31. data/lib/bootstrap-cells/cells/card/block.erb +14 -0
  32. data/lib/bootstrap-cells/cells/card/block_body.erb +5 -0
  33. data/lib/bootstrap-cells/cells/card/block_subtitle.erb +5 -0
  34. data/lib/bootstrap-cells/cells/card/block_text.erb +5 -0
  35. data/lib/bootstrap-cells/cells/card/block_title.erb +5 -0
  36. data/lib/bootstrap-cells/cells/card/footer.erb +9 -0
  37. data/lib/bootstrap-cells/cells/card/header.erb +9 -0
  38. data/lib/bootstrap-cells/cells/card/img_bottom.erb +9 -0
  39. data/lib/bootstrap-cells/cells/card/img_top.erb +9 -0
  40. data/lib/bootstrap-cells/cells/card/list_group.erb +9 -0
  41. data/lib/bootstrap-cells/cells/card/show.erb +9 -0
  42. data/lib/bootstrap-cells/cells/card/table.erb +9 -0
  43. data/lib/bootstrap-cells/cells/card_cell.rb +152 -0
  44. data/lib/bootstrap-cells/cells/column/td.erb +1 -0
  45. data/lib/bootstrap-cells/cells/column/th.erb +9 -0
  46. data/lib/bootstrap-cells/cells/column_cell.rb +49 -0
  47. data/lib/bootstrap-cells/cells/field/required_field.scss +5 -0
  48. data/lib/bootstrap-cells/cells/field/show.erb +15 -0
  49. data/lib/bootstrap-cells/cells/field_cell.rb +96 -0
  50. data/lib/bootstrap-cells/cells/fields_for/form.scss +12 -0
  51. data/lib/bootstrap-cells/cells/fields_for/form_horizontal.scss +33 -0
  52. data/lib/bootstrap-cells/cells/fields_for/show.erb +3 -0
  53. data/lib/bootstrap-cells/cells/fields_for_cell.rb +15 -0
  54. data/lib/bootstrap-cells/cells/kv_horizontal/show.erb +17 -0
  55. data/lib/bootstrap-cells/cells/kv_horizontal_cell.rb +34 -0
  56. data/lib/bootstrap-cells/cells/kv_vertical/show.erb +17 -0
  57. data/lib/bootstrap-cells/cells/kv_vertical_cell.rb +32 -0
  58. data/lib/bootstrap-cells/cells/modal/body.erb +9 -0
  59. data/lib/bootstrap-cells/cells/modal/button.erb +9 -0
  60. data/lib/bootstrap-cells/cells/modal/content.erb +12 -0
  61. data/lib/bootstrap-cells/cells/modal/footer.erb +10 -0
  62. data/lib/bootstrap-cells/cells/modal/header.erb +12 -0
  63. data/lib/bootstrap-cells/cells/modal/modal.js +15 -0
  64. data/lib/bootstrap-cells/cells/modal/show.erb +9 -0
  65. data/lib/bootstrap-cells/cells/modal_cell.rb +64 -0
  66. data/lib/bootstrap-cells/cells/pages/pages.scss +4 -0
  67. data/lib/bootstrap-cells/cells/pages/show.erb +3 -0
  68. data/lib/bootstrap-cells/cells/pages_cell.rb +16 -0
  69. data/lib/bootstrap-cells/cells/table/nubbin.scss +40 -0
  70. data/lib/bootstrap-cells/cells/table/show.erb +7 -0
  71. data/lib/bootstrap-cells/cells/table/table_sort.scss +17 -0
  72. data/lib/bootstrap-cells/cells/table/table_striped_nested.scss +8 -0
  73. data/lib/bootstrap-cells/cells/table/tbody.erb +3 -0
  74. data/lib/bootstrap-cells/cells/table/tbody_button_for_nested_row.erb +9 -0
  75. data/lib/bootstrap-cells/cells/table/tbody_final_row.erb +9 -0
  76. data/lib/bootstrap-cells/cells/table/tbody_first_row.erb +9 -0
  77. data/lib/bootstrap-cells/cells/table/tbody_nested_row.erb +6 -0
  78. data/lib/bootstrap-cells/cells/table/tbody_rows.erb +35 -0
  79. data/lib/bootstrap-cells/cells/table/thead.erb +11 -0
  80. data/lib/bootstrap-cells/cells/table_cell.rb +68 -0
  81. data/lib/bootstrap-cells/cells/tabs/show.erb +19 -0
  82. data/lib/bootstrap-cells/cells/tabs_cell.rb +40 -0
  83. data/lib/bootstrap-cells/engine.rb +9 -0
  84. metadata +307 -0
@@ -0,0 +1 @@
1
+ <%= content_tag(:td, cell_text, **td_props) %>
@@ -0,0 +1,9 @@
1
+ <%= content_tag(:th, **th_props) do %>
2
+ <% if options[:sort] %>
3
+ <%= content_tag(:div, class: 'flex items-center justify-between') do %>
4
+ <%= content_tag(:span, header_text) %>
5
+ <% end %>
6
+ <% else %>
7
+ <%= header_text %>
8
+ <% end %>
9
+ <% end %>
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ColumnCell < BaseCell
4
+ def th
5
+ render
6
+ end
7
+
8
+ def td
9
+ render
10
+ end
11
+
12
+ private
13
+
14
+ def th_props
15
+ defaults = {
16
+ class: c(('sort' if options[:sort]),
17
+ ("col-xs-#{options[:columns]}" if options[:columns]),
18
+ ('text-center' if options[:center])),
19
+ data: { sort: options[:attribute] },
20
+ }
21
+ merge_props(from: defaults, to: options.dig(:props, :th))
22
+ end
23
+
24
+ def td_props
25
+ defaults = {
26
+ class: c(options[:attribute],
27
+ ('truncate' if options[:truncate]),
28
+ ('text-center' if options[:center])),
29
+ }
30
+ merge_props(from: defaults, to: options.dig(:props, :td))
31
+ end
32
+
33
+ def header_text
34
+ return options[:header] if options[:header]
35
+ return nil unless options[:attribute]
36
+ return options[:model].human_attribute_name(
37
+ options[:attribute],
38
+ default: I18n.t(options[:attribute],
39
+ scope: :attributes,
40
+ default: titleized_attribute_path(options[:attribute]))
41
+ ) if options[:model].respond_to?(:human_attribute_name)
42
+ titleized_attribute_path(options[:attribute])
43
+ end
44
+
45
+ def cell_text
46
+ return '—' unless options[:cell] || options[:attribute]
47
+ options[:cell]&.call(model, options[:index]) || render_attribute_path(options[:attribute], model)
48
+ end
49
+ end
@@ -0,0 +1,5 @@
1
+ .required label:before {
2
+ content: "*";
3
+ color: #d82c2c;
4
+ padding-right: 2px;
5
+ }
@@ -0,0 +1,15 @@
1
+ <% if field[:hidden] %>
2
+ <%= hidden_field(field_input_name, field_input_attribute, value: field_input_value) %>
3
+ <% else %>
4
+ <%= content_tag(:div, **container_props) do %>
5
+ <% unless field[:label] == false %>
6
+ <%= content_tag(:label, label_text, **label_props) %>
7
+ <% end %>
8
+ <%= content_tag(:div, **value_props) do %>
9
+ <%= value_text %>
10
+ <% end %>
11
+ <% if field[:errors] && field[:errors].present? %>
12
+ <span class="help-block"><%= field[:errors] %></span>
13
+ <% end %>
14
+ <% end %>
15
+ <% end %>
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FieldCell < BaseCell
4
+ private
5
+
6
+ def field
7
+ @field ||= field_props
8
+ end
9
+
10
+ def field_props
11
+ attribute = @options[:attribute]
12
+ defaults = {
13
+ attribute: attribute,
14
+ required: false,
15
+ hidden: false,
16
+ readonly: false,
17
+ props: {
18
+ container: {},
19
+ label: {},
20
+ value: {},
21
+ input: {},
22
+ },
23
+ }
24
+
25
+ params = merge_props(from: defaults, to: @options)
26
+ params[:required] = 'required' if params[:required]
27
+ params[:errors] ||= fetch_errors(model, attribute) if model
28
+ params
29
+ end
30
+
31
+ def attribute
32
+ field[:attribute].to_s
33
+ end
34
+
35
+ def container_props
36
+ defaults = {
37
+ class: %w[form-group px-0],
38
+ }
39
+ defaults[:class] << %w[has-error] if field[:errors]
40
+ defaults[:class] << %w[required] if field[:required]
41
+ merge_props(from: defaults, to: field.dig(:props, :container))
42
+ end
43
+
44
+ def label_props
45
+ defaults = {
46
+ class: %w[control-label],
47
+ }
48
+ merge_props(from: defaults, to: field.dig(:props, :label))
49
+ end
50
+
51
+ def label_text
52
+ return field[:label] if field[:label].is_a?(String)
53
+ return nil if field[:label] == false || !model
54
+ return model.class.human_attribute_name(
55
+ attribute,
56
+ default: I18n.t(attribute,
57
+ scope: :attributes,
58
+ default: titleized_attribute_path(attribute))
59
+ ) if model.class.respond_to?(:human_attribute_name)
60
+ titleized_attribute_path(attribute)
61
+ end
62
+
63
+ def value_props
64
+ defaults = {
65
+ class: %w[control-value],
66
+ }
67
+ defaults[:class] << %w[form-control-static] if field[:readonly]
68
+ merge_props(from: defaults, to: field.dig(:props, :value))
69
+ end
70
+
71
+ def value_text
72
+ return field[:output] if field[:output]
73
+ return render_attribute_path(attribute, model) if field[:readonly]
74
+ text_field(field_input_name,
75
+ field_input_attribute,
76
+ value: field_input_value,
77
+ class: c(field.dig(:props, :input, :class), 'form-control px-2'),
78
+ placeholder: field[:placeholder] || titleized_attribute_path(attribute),
79
+ **field.dig(:props, :input).except(:class))
80
+ end
81
+
82
+ def field_input_name
83
+ return nil unless model
84
+ param_name = (model.try(:model_name) || model.class.name.remove('Filterer').constantize.new.model_name)&.param_key
85
+ param_name.to_s + attribute.split('.')[0..-2].map { |a| '[' + a + ']' }.join
86
+ end
87
+
88
+ def field_input_attribute
89
+ attribute.split('.').last
90
+ end
91
+
92
+ def field_input_value
93
+ return field[:output] if field[:output]
94
+ render_attribute_path(attribute, model)
95
+ end
96
+ end
@@ -0,0 +1,12 @@
1
+ .form {
2
+ .form-group {
3
+ margin-bottom: 2rem;
4
+ }
5
+ .help-block {
6
+ margin-bottom: 0;
7
+ }
8
+ }
9
+
10
+ .form-group {
11
+ width: 100%;
12
+ }
@@ -0,0 +1,33 @@
1
+ .form-horizontal {
2
+ .form-group {
3
+ display: flex;
4
+ flex-wrap: wrap;
5
+ align-items: center;
6
+ margin-left: 0;
7
+ margin-right: 0;
8
+
9
+ .control-label, .sr-only {
10
+ flex-basis: 20%;
11
+ width: 20%;
12
+ text-align: right;
13
+ padding: 0;
14
+ }
15
+ > .control-value,
16
+ > .help-block {
17
+ flex-basis: 75%;
18
+ width: 75%;
19
+ margin-left: 2%;
20
+ }
21
+ > .control-value:only-child {
22
+ flex-basis: 100%;
23
+ width: 100%;
24
+ margin-left: 0;
25
+ }
26
+ .sr-only + .control-value {
27
+ margin-left: 22%;
28
+ }
29
+ > .help-block {
30
+ margin-left: 22%;
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,3 @@
1
+ <% fields.each do |field| %>
2
+ <%= cell(:field, model, options_for(field: field)).() %>
3
+ <% end %>
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bootstrap-cells/cells/field_cell'
4
+
5
+ class FieldsForCell < BaseCell
6
+ private
7
+
8
+ def fields
9
+ (options[:fields] || []).compact
10
+ end
11
+
12
+ def options_for(field:)
13
+ options.slice(:required, :hidden, :readonly).merge(field)
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ <%= content_tag(:dl, **item_props) do %>
2
+ <%= content_tag(:dt, **key_props) do %>
3
+ <% if renderable?(:key) %>
4
+ <%= render_option(:key) %>
5
+ <% else %>
6
+ <%= key_text %>
7
+ <% end %>
8
+ <% end %>
9
+
10
+ <%= content_tag(:dd, **value_props) do %>
11
+ <% if renderable?(:value) %>
12
+ <%= render_option(:value) %>
13
+ <% else %>
14
+ <%= value_text %>
15
+ <% end %>
16
+ <% end %>
17
+ <% end %>
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ class KvHorizontalCell < BaseCell
4
+ private
5
+
6
+ def item_props
7
+ defaults = {
8
+ class: 'col-xs-12 my-0 mr-auto',
9
+ }
10
+ merge_props(from: defaults, to: options.dig(:props, :item))
11
+ end
12
+
13
+ def key_props
14
+ defaults = {
15
+ class: 'col-xs-3 right-align pr-2',
16
+ }
17
+ merge_props(from: defaults, to: options.dig(:props, :key))
18
+ end
19
+
20
+ def key_text
21
+ options[:key]
22
+ end
23
+
24
+ def value_props
25
+ defaults = {
26
+ class: 'col-xs-9',
27
+ }
28
+ merge_props(from: defaults, to: options.dig(:props, :value))
29
+ end
30
+
31
+ def value_text
32
+ options[:value] || '—'
33
+ end
34
+ end
@@ -0,0 +1,17 @@
1
+ <%= content_tag(:dl, **item_props) do %>
2
+ <%= content_tag(:dt, **key_props) do %>
3
+ <% if renderable?(:key) %>
4
+ <%= render_option(:key) %>
5
+ <% else %>
6
+ <%= key_text %>
7
+ <% end %>
8
+ <% end %>
9
+
10
+ <%= content_tag(:dd, **value_props) do %>
11
+ <% if renderable?(:value) %>
12
+ <%= render_option(:value) %>
13
+ <% else %>
14
+ <%= value_text %>
15
+ <% end %>
16
+ <% end %>
17
+ <% end %>
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class KvVerticalCell < BaseCell
4
+ private
5
+
6
+ def item_props
7
+ defaults = {
8
+ class: 'my-0',
9
+ }
10
+ merge_props(from: defaults, to: options.dig(:props, :item))
11
+ end
12
+
13
+ def key_props
14
+ defaults = {
15
+ }
16
+ merge_props(from: defaults, to: options.dig(:props, :key))
17
+ end
18
+
19
+ def key_text
20
+ options[:key]
21
+ end
22
+
23
+ def value_props
24
+ defaults = {
25
+ }
26
+ merge_props(from: defaults, to: options.dig(:props, :value))
27
+ end
28
+
29
+ def value_text
30
+ options[:value] || '—'
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ <div class="modal-body">
2
+ <% if renderable?(:body) %>
3
+ <%= render_option(:body) %>
4
+ <% else %>
5
+ <%= content_tag(:div, **body_props) do %>
6
+ <%= body_text %>
7
+ <% end %>
8
+ <% end %>
9
+ </div>
@@ -0,0 +1,9 @@
1
+ <span data-toggle="modal" style="cursor:pointer;">
2
+ <% if renderable?(:button) %>
3
+ <%= render_option(:button) %>
4
+ <% else %>
5
+ <%= content_tag(:button, **button_props) do %>
6
+ <%= button_text %>
7
+ <% end %>
8
+ <% end %>
9
+ </span>
@@ -0,0 +1,12 @@
1
+ <div class="modal-content">
2
+ <%= render :header %>
3
+
4
+ <% if renderable?(:content) %>
5
+ <%= render_option(:content) %>
6
+ <% else %>
7
+ <%= content_tag(:div, **content_props) do %>
8
+ <%= render :body %>
9
+ <%= render :footer %>
10
+ <% end %>
11
+ <% end %>
12
+ </div>
@@ -0,0 +1,10 @@
1
+ <div class="modal-footer">
2
+ <% if renderable?(:footer) %>
3
+ <%= render_option(:footer) %>
4
+ <% else %>
5
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
6
+ <%= content_tag(:span, **footer_props) do %>
7
+ <%= footer_text %>
8
+ <% end %>
9
+ <% end %>
10
+ </div>
@@ -0,0 +1,12 @@
1
+ <div class="modal-header">
2
+ <% if renderable?(:header) %>
3
+ <%= render_option(:header) %>
4
+ <% else %>
5
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
6
+ <span aria-hidden="true">&times;</span>
7
+ </button>
8
+ <%= content_tag(header_props[:tag], **header_props.except(:tag)) do %>
9
+ <%= header_text %>
10
+ <% end %>
11
+ <% end %>
12
+ </div>
@@ -0,0 +1,15 @@
1
+ var handleModals = function handleModals() {
2
+ document.querySelectorAll('.bootstrap-modal [data-toggle="modal"]').forEach(function(modalButton) {
3
+ var modal = modalButton.parentNode.querySelector('.modal');
4
+ var randomId = Math.random().toString().substr(-10);
5
+
6
+ modal.setAttribute('id', randomId);
7
+ modalButton.setAttribute('data-target', '#' + randomId);
8
+
9
+ document.querySelector('body').appendChild( modal )
10
+ });
11
+ }
12
+
13
+ addManyEventListeners(document,
14
+ "page:change turbolinks:load ajax:complete",
15
+ handleModals);
@@ -0,0 +1,9 @@
1
+ <%= content_tag(:div, **wrapper_props) do %>
2
+ <%= render :button %>
3
+
4
+ <div class="modal fade" tabindex="-1" role="dialog">
5
+ <div class="modal-dialog" role="document">
6
+ <%= render :content %>
7
+ </div>
8
+ </div>
9
+ <% end %>