headmin 0.4.2 → 0.5.2

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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -3
  3. data/Gemfile +14 -0
  4. data/Gemfile.lock +78 -1
  5. data/app/assets/javascripts/headmin/controllers/date_range_controller.js +12 -6
  6. data/app/assets/javascripts/headmin/controllers/filter_controller.js +61 -11
  7. data/app/assets/javascripts/headmin/controllers/filter_row_controller.js +50 -0
  8. data/app/assets/javascripts/headmin/controllers/flatpickr_controller.js +2 -6
  9. data/app/assets/javascripts/headmin/controllers/media_controller.js +237 -0
  10. data/app/assets/javascripts/headmin/controllers/media_modal_controller.js +110 -0
  11. data/app/assets/javascripts/headmin/controllers/popup_controller.js +3 -1
  12. data/app/assets/javascripts/headmin/controllers/remote_modal_controller.js +10 -0
  13. data/app/assets/javascripts/headmin/controllers/table_actions_controller.js +16 -21
  14. data/app/assets/javascripts/headmin/controllers/textarea_controller.js +34 -0
  15. data/app/assets/javascripts/headmin/index.js +10 -0
  16. data/app/assets/javascripts/headmin.js +413 -38
  17. data/app/assets/stylesheets/headmin/filter.scss +74 -0
  18. data/app/assets/stylesheets/headmin/forms/file.scss +40 -5
  19. data/app/assets/stylesheets/headmin/forms/media.scss +10 -0
  20. data/app/assets/stylesheets/headmin/forms/repeater.scss +4 -0
  21. data/app/assets/stylesheets/headmin/forms.scss +7 -0
  22. data/app/assets/stylesheets/headmin/general.scss +0 -1
  23. data/app/assets/stylesheets/headmin/layout/body.scss +5 -0
  24. data/app/assets/stylesheets/headmin/layout/sidebar.scss +0 -1
  25. data/app/assets/stylesheets/headmin/media/index.scss +9 -0
  26. data/app/assets/stylesheets/headmin/media.scss +1 -0
  27. data/app/assets/stylesheets/headmin/popup.scss +0 -1
  28. data/app/assets/stylesheets/headmin/table.scss +15 -0
  29. data/app/assets/stylesheets/headmin.css +137 -9
  30. data/app/assets/stylesheets/headmin.scss +1 -0
  31. data/app/controllers/concerns/headmin/filterable.rb +27 -0
  32. data/app/controllers/headmin/media_controller.rb +52 -0
  33. data/app/controllers/headmin_controller.rb +2 -0
  34. data/app/models/concerns/headmin/field.rb +0 -1
  35. data/app/models/concerns/headmin/fieldable.rb +10 -1
  36. data/app/models/concerns/headmin/form/hintable.rb +6 -1
  37. data/app/models/headmin/blocks_view.rb +1 -1
  38. data/app/models/headmin/filter/base.rb +238 -0
  39. data/app/models/headmin/filter/base_view.rb +64 -0
  40. data/app/models/headmin/filter/boolean.rb +15 -0
  41. data/app/models/headmin/filter/boolean_view.rb +61 -0
  42. data/app/models/headmin/filter/button_view.rb +25 -0
  43. data/app/models/headmin/filter/conditional_view.rb +16 -0
  44. data/app/models/headmin/filter/date.rb +67 -0
  45. data/app/models/headmin/filter/date_view.rb +52 -0
  46. data/app/models/headmin/filter/flatpickr_view.rb +54 -0
  47. data/app/models/headmin/filter/menu_item_view.rb +6 -0
  48. data/app/models/headmin/filter/money.rb +13 -0
  49. data/app/models/headmin/filter/number.rb +27 -0
  50. data/app/models/headmin/filter/number_view.rb +54 -0
  51. data/app/models/headmin/filter/operator_view.rb +30 -0
  52. data/app/models/headmin/filter/options_view.rb +61 -0
  53. data/app/models/headmin/filter/row_view.rb +13 -0
  54. data/app/models/headmin/filter/search.rb +18 -0
  55. data/app/models/headmin/filter/search_view.rb +31 -0
  56. data/app/models/headmin/filter/text.rb +25 -0
  57. data/app/models/headmin/filter/text_view.rb +53 -0
  58. data/app/models/headmin/filters.rb +29 -0
  59. data/app/models/headmin/form/color_view.rb +48 -0
  60. data/app/models/headmin/form/datetime_range_view.rb +25 -0
  61. data/app/models/headmin/form/datetime_view.rb +45 -0
  62. data/app/models/headmin/form/flatpickr_range_view.rb +4 -15
  63. data/app/models/headmin/form/flatpickr_view.rb +3 -12
  64. data/app/models/headmin/form/media_view.rb +113 -0
  65. data/app/models/headmin/form/textarea_view.rb +6 -1
  66. data/app/models/view_model.rb +1 -1
  67. data/app/views/headmin/_blocks.html.erb +3 -3
  68. data/app/views/headmin/_breadcrumbs.html.erb +1 -1
  69. data/app/views/headmin/_dropdown.html.erb +1 -1
  70. data/app/views/headmin/_filters.html.erb +9 -9
  71. data/app/views/headmin/_heading.html.erb +1 -1
  72. data/app/views/headmin/_notifications.html.erb +1 -1
  73. data/app/views/headmin/_pagination.html.erb +2 -2
  74. data/app/views/headmin/dropdown/_devise.html.erb +7 -7
  75. data/app/views/headmin/dropdown/_list.html.erb +1 -1
  76. data/app/views/headmin/filters/_base.html.erb +95 -0
  77. data/app/views/headmin/filters/_boolean.html.erb +23 -0
  78. data/app/views/headmin/filters/_date.html.erb +14 -38
  79. data/app/views/headmin/filters/_flatpickr.html.erb +15 -48
  80. data/app/views/headmin/filters/_number.html.erb +23 -0
  81. data/app/views/headmin/filters/_options.html.erb +24 -0
  82. data/app/views/headmin/filters/_search.html.erb +14 -12
  83. data/app/views/headmin/filters/_text.html.erb +23 -0
  84. data/app/views/headmin/filters/filter/_button.html.erb +9 -10
  85. data/app/views/headmin/filters/filter/_conditional.html.erb +18 -0
  86. data/app/views/headmin/filters/filter/_menu_item.html.erb +5 -2
  87. data/app/views/headmin/filters/filter/_null_select.html.erb +8 -0
  88. data/app/views/headmin/filters/filter/_operator.html.erb +16 -0
  89. data/app/views/headmin/filters/filter/_row.html.erb +11 -0
  90. data/app/views/headmin/forms/_autocomplete.html.erb +2 -2
  91. data/app/views/headmin/forms/_blocks.html.erb +3 -3
  92. data/app/views/headmin/forms/_checkbox.html.erb +5 -5
  93. data/app/views/headmin/forms/_color.html.erb +32 -0
  94. data/app/views/headmin/forms/_date.html.erb +8 -8
  95. data/app/views/headmin/forms/_datetime.html.erb +41 -0
  96. data/app/views/headmin/forms/_datetime_range.html.erb +40 -0
  97. data/app/views/headmin/forms/_email.html.erb +9 -9
  98. data/app/views/headmin/forms/_file.html.erb +9 -9
  99. data/app/views/headmin/forms/_flatpickr.html.erb +1 -1
  100. data/app/views/headmin/forms/_flatpickr_range.html.erb +9 -10
  101. data/app/views/headmin/forms/_hidden.html.erb +1 -1
  102. data/app/views/headmin/forms/_hint.html.erb +7 -2
  103. data/app/views/headmin/forms/_media.html.erb +58 -0
  104. data/app/views/headmin/forms/_number.html.erb +8 -8
  105. data/app/views/headmin/forms/_password.html.erb +7 -7
  106. data/app/views/headmin/forms/_redactorx.html.erb +2 -2
  107. data/app/views/headmin/forms/_search.html.erb +9 -9
  108. data/app/views/headmin/forms/_select.html.erb +8 -8
  109. data/app/views/headmin/forms/_switch.html.erb +2 -2
  110. data/app/views/headmin/forms/_text.html.erb +9 -9
  111. data/app/views/headmin/forms/_textarea.html.erb +7 -7
  112. data/app/views/headmin/forms/_url.html.erb +9 -9
  113. data/app/views/headmin/forms/_validation.html.erb +1 -1
  114. data/app/views/headmin/forms/_wysiwyg.html.erb +2 -2
  115. data/app/views/headmin/forms/fields/_base.html.erb +1 -1
  116. data/app/views/headmin/forms/fields/_file.html.erb +1 -1
  117. data/app/views/headmin/forms/fields/_files.html.erb +1 -1
  118. data/app/views/headmin/forms/fields/_group.html.erb +2 -2
  119. data/app/views/headmin/forms/fields/_list.html.erb +1 -1
  120. data/app/views/headmin/forms/fields/_text.html.erb +1 -1
  121. data/app/views/headmin/forms/media/_item.html.erb +32 -0
  122. data/app/views/headmin/forms/media/_validation.html.erb +10 -0
  123. data/app/views/headmin/forms/repeater/_row.html.erb +12 -11
  124. data/app/views/headmin/layout/_footer.html.erb +1 -1
  125. data/app/views/headmin/layout/_main.html.erb +2 -0
  126. data/app/views/headmin/layout/_remote_modal.html.erb +1 -0
  127. data/app/views/headmin/layout/_sidebar.html.erb +1 -1
  128. data/app/views/headmin/media/_item.html.erb +17 -0
  129. data/app/views/headmin/media/_media_item_modal.html.erb +51 -0
  130. data/app/views/headmin/media/_modal.html.erb +35 -0
  131. data/app/views/headmin/media/create.turbo_stream.erb +5 -0
  132. data/app/views/headmin/media/index.html.erb +3 -0
  133. data/app/views/headmin/media/show.html.erb +9 -0
  134. data/app/views/headmin/media/update.turbo_stream.erb +3 -0
  135. data/app/views/headmin/nav/item/_devise.html.erb +7 -7
  136. data/app/views/headmin/table/_actions.html.erb +1 -4
  137. data/app/views/headmin/table/actions/_action.html.erb +3 -3
  138. data/app/views/headmin/table/actions/_delete.html.erb +2 -2
  139. data/app/views/headmin/table/actions/_export.html.erb +1 -1
  140. data/app/views/headmin/table/body/_color.html.erb +10 -0
  141. data/app/views/headmin/table/body/_image.html.erb +18 -0
  142. data/app/views/headmin/table/foot/_cell.html.erb +1 -1
  143. data/app/views/headmin/table/foot/_id.html.erb +1 -1
  144. data/app/views/headmin/views/devise/confirmations/_new.html.erb +2 -2
  145. data/app/views/headmin/views/devise/passwords/_edit.html.erb +2 -2
  146. data/app/views/headmin/views/devise/passwords/_new.html.erb +2 -2
  147. data/app/views/headmin/views/devise/registrations/_edit.html.erb +1 -1
  148. data/app/views/headmin/views/devise/registrations/_new.html.erb +2 -2
  149. data/app/views/headmin/views/devise/sessions/_new.html.erb +1 -1
  150. data/app/views/headmin/views/devise/unlocks/_new.html.erb +2 -2
  151. data/config/locales/devise/nl.yml +1 -1
  152. data/config/locales/en.yml +4 -0
  153. data/config/locales/headmin/dropdown/en.yml +6 -0
  154. data/config/locales/headmin/dropdown/nl.yml +6 -0
  155. data/config/locales/headmin/filters/en.yml +26 -1
  156. data/config/locales/headmin/filters/nl.yml +26 -1
  157. data/config/locales/headmin/forms/en.yml +8 -0
  158. data/config/locales/headmin/forms/nl.yml +8 -0
  159. data/config/locales/headmin/layout/en.yml +0 -9
  160. data/config/locales/headmin/layout/nl.yml +0 -9
  161. data/config/locales/headmin/media/en.yml +23 -0
  162. data/config/locales/headmin/media/nl.yml +22 -0
  163. data/config/locales/headmin/nav/en.yml +7 -0
  164. data/config/locales/headmin/nav/nl.yml +7 -0
  165. data/config/locales/headmin/table/en.yml +2 -0
  166. data/config/locales/headmin/table/nl.yml +2 -0
  167. data/config/locales/nl.yml +4 -0
  168. data/config/routes.rb +10 -0
  169. data/lib/generators/templates/views/auth/confirmations/new.html.erb +1 -1
  170. data/lib/generators/templates/views/auth/mailer/confirmation_instructions.html.erb +1 -1
  171. data/lib/generators/templates/views/auth/mailer/email_changed.html.erb +1 -1
  172. data/lib/generators/templates/views/auth/mailer/password_change.html.erb +1 -1
  173. data/lib/generators/templates/views/auth/mailer/reset_password_instructions.html.erb +1 -1
  174. data/lib/generators/templates/views/auth/mailer/unlock_instructions.html.erb +1 -1
  175. data/lib/generators/templates/views/auth/passwords/edit.html.erb +1 -1
  176. data/lib/generators/templates/views/auth/passwords/new.html.erb +1 -1
  177. data/lib/generators/templates/views/auth/registrations/edit.html.erb +1 -1
  178. data/lib/generators/templates/views/auth/registrations/new.html.erb +1 -1
  179. data/lib/generators/templates/views/auth/sessions/new.html.erb +1 -1
  180. data/lib/generators/templates/views/auth/unlocks/new.html.erb +1 -1
  181. data/lib/headmin/version.rb +1 -1
  182. data/package.json +1 -1
  183. metadata +70 -7
  184. data/.lock-487e157d270f3062a98b7b2a012753708-1272821827 +0 -0
  185. data/app/controllers/concerns/headmin/filter.rb +0 -5
  186. data/app/controllers/concerns/headmin/searchable.rb +0 -15
  187. data/app/views/headmin/filters/_select.html.erb +0 -45
  188. data/app/views/headmin/filters/filter/_template.html.erb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2df34e0f6abc35cd855cab3059a40f7716b336df77abdbd4ea9609fc3cf6e5e
4
- data.tar.gz: 2c2c5953560f608e6d479bcb7de506ce8da701be8d56b5fbf72cfcaf3a9478ad
3
+ metadata.gz: f50bfc69af544486c0d0bc963a61dc0eb489b4522fb17454c4371238e12afbc5
4
+ data.tar.gz: 75b003602ff5c8b67db4c23eb84010d6417d008b36a979acfe6f5c06f46bda5c
5
5
  SHA512:
6
- metadata.gz: 17a7d48956fb48e286cd0fd2ac043741256c2e573ffb024cc4ae7fffb2e39c54d4db380efb4308f6816649f43e3fde68fabda7d104211cbcdf8f387d6c7d384b
7
- data.tar.gz: 33afd17085196473000927125f9186e5b5703575373cdee9be982e6ca32db31ce09aef1fdf3ebf65b2efb9e31b16595fb6b5076ea65e7872f2ecaf49f260ea12
6
+ metadata.gz: 227586c0581a6e7aaab79975b7ff5f7484a46af5e9e5f05e336234aa748e63eba6d1afddbf19d5f1a4cd4bbb77e9901a5ef24dae10681a3e89ecd9765572c60a
7
+ data.tar.gz: 016e43a680a555f38905eea53dc44c76f1286606ae99401979ca71a76e7b3c4a8eb0f61286f843a12d5bcb74708d61e2fa363c86de02463fbe845efd1ac0f34b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Headmin Changelog
2
2
 
3
+ ## 0.5
4
+ - FEATURE: Filters now have support for operators and conditionals
5
+ - BREAK: `headmin/filters` now return a form object that is required for each individual form
6
+ - DEPRECATED: `Headmin::Searchable` is replaced with `Headmin::Filterable`.
7
+ - A `filter(params, types)` method is available and accepts an optional types argument.
8
+ - The `search()` method is now deprecated and no longer required
9
+
3
10
  ## 0.4.2
4
11
  - FEATURE: New field type "files" to allow simple gallery creation
5
12
  - FIX: Fields hash with duplicate keys no longer mix up
@@ -22,13 +29,13 @@
22
29
  - BREAK: `headmin/forms/actions` and all of its child components have been removed
23
30
  - BREAK: `$font-weight-medium` has been removed from headmin overrides variables. We don't want to introduce new variable names that look like they are part of Bootstrap.
24
31
  - BREAK: `headmin/forms/date_range` has a different way of setting attribute specific values. We now have a `:start` and `:end` attribute that accept all possible input options for their respective inputs. Both have a required `:attribute` parameter now.
25
-
32
+ - BREAK: filter concern (controllers) has been renamed to filterable
26
33
  ```erb
27
34
  # Old
28
- <%= render "headmin/forms/date_range", form: form, start_attribute: :start_date, end_attribute: :end_date %>
35
+ <%= render 'headmin/forms/date_range', form: form, start_attribute: :start_date, end_attribute: :end_date %>
29
36
 
30
37
  # New
31
- <%= render "headmin/forms/date_range", form: form, start: {attribute: :start_date}, end: {attribute: :end_date} %>
38
+ <%= render 'headmin/forms/date_range', form: form, start: {attribute: :start_date}, end: {attribute: :end_date} %>
32
39
  ```
33
40
 
34
41
  ## 0.3
data/Gemfile CHANGED
@@ -6,9 +6,23 @@ gemspec
6
6
  gem "capybara", ">= 3.26"
7
7
  gem "minitest", "~> 5.0"
8
8
  gem "minitest-spec-rails", "~> 6.1"
9
+ gem "puma", "~> 5.2"
9
10
  gem "rails", "~> 7.0"
10
11
  gem "rake", "~> 13.0"
11
12
  gem "sprockets-rails", "~> 3.4"
12
13
  gem "sqlite3", "~> 1.4"
13
14
  gem "standard", "~> 1.7"
14
15
  gem "debug"
16
+
17
+ # Dummy app
18
+ gem "devise", "~> 4.8"
19
+ gem "enumerize", "~> 2.3"
20
+ gem "sassc-rails", "~> 2.1"
21
+ gem "image_processing", "~> 1.2"
22
+ gem "inline_svg", "~> 1.7"
23
+ gem "kaminari", "~> 1.2"
24
+ gem "route_translator", "~> 12.0"
25
+ gem "acts_as_list", "~> 1.0"
26
+ gem "breadcrumbs_on_rails", "~> 4.1"
27
+ gem "importmap-rails", "~> 1.0"
28
+ gem "hotwire-rails", "~> 0.1"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- headmin (0.4.1)
4
+ headmin (0.5.1)
5
5
  closure_tree (~> 7.4)
6
6
  inline_svg (~> 1.7)
7
7
  redcarpet (~> 3.5)
@@ -75,9 +75,14 @@ GEM
75
75
  i18n (>= 1.6, < 2)
76
76
  minitest (>= 5.1)
77
77
  tzinfo (~> 2.0)
78
+ acts_as_list (1.0.4)
79
+ activerecord (>= 4.2)
78
80
  addressable (2.8.0)
79
81
  public_suffix (>= 2.0.2, < 5.0)
80
82
  ast (2.4.2)
83
+ bcrypt (3.1.18)
84
+ breadcrumbs_on_rails (4.1.0)
85
+ railties (>= 5.0)
81
86
  builder (3.2.4)
82
87
  capybara (3.36.0)
83
88
  addressable
@@ -96,18 +101,49 @@ GEM
96
101
  debug (1.5.0)
97
102
  irb (>= 1.3.6)
98
103
  reline (>= 0.2.7)
104
+ devise (4.8.1)
105
+ bcrypt (~> 3.0)
106
+ orm_adapter (~> 0.1)
107
+ railties (>= 4.1.0)
108
+ responders
109
+ warden (~> 1.2.3)
99
110
  digest (3.1.0)
111
+ enumerize (2.5.0)
112
+ activesupport (>= 3.2)
100
113
  erubi (1.10.0)
114
+ ffi (1.15.5)
101
115
  globalid (1.0.0)
102
116
  activesupport (>= 5.0)
117
+ hotwire-rails (0.1.3)
118
+ rails (>= 6.0.0)
119
+ stimulus-rails
120
+ turbo-rails
103
121
  i18n (1.10.0)
104
122
  concurrent-ruby (~> 1.0)
123
+ image_processing (1.12.2)
124
+ mini_magick (>= 4.9.5, < 5)
125
+ ruby-vips (>= 2.0.17, < 3)
126
+ importmap-rails (1.0.3)
127
+ actionpack (>= 6.0.0)
128
+ railties (>= 6.0.0)
105
129
  inline_svg (1.8.0)
106
130
  activesupport (>= 3.0)
107
131
  nokogiri (>= 1.6)
108
132
  io-console (0.5.11)
109
133
  irb (1.4.1)
110
134
  reline (>= 0.3.0)
135
+ kaminari (1.2.2)
136
+ activesupport (>= 4.1.0)
137
+ kaminari-actionview (= 1.2.2)
138
+ kaminari-activerecord (= 1.2.2)
139
+ kaminari-core (= 1.2.2)
140
+ kaminari-actionview (1.2.2)
141
+ actionview
142
+ kaminari-core (= 1.2.2)
143
+ kaminari-activerecord (1.2.2)
144
+ activerecord
145
+ kaminari-core (= 1.2.2)
146
+ kaminari-core (1.2.2)
111
147
  loofah (2.16.0)
112
148
  crass (~> 1.0.2)
113
149
  nokogiri (>= 1.5.9)
@@ -116,6 +152,7 @@ GEM
116
152
  marcel (1.0.2)
117
153
  matrix (0.4.2)
118
154
  method_source (1.0.0)
155
+ mini_magick (4.11.0)
119
156
  mini_mime (1.1.2)
120
157
  minitest (5.15.0)
121
158
  minitest-spec-rails (6.1.0)
@@ -142,10 +179,13 @@ GEM
142
179
  racc (~> 1.4)
143
180
  nokogiri (1.13.4-x86_64-linux)
144
181
  racc (~> 1.4)
182
+ orm_adapter (0.5.0)
145
183
  parallel (1.22.1)
146
184
  parser (3.1.2.0)
147
185
  ast (~> 2.4.1)
148
186
  public_suffix (4.0.7)
187
+ puma (5.6.4)
188
+ nio4r (~> 2.0)
149
189
  racc (1.6.0)
150
190
  rack (2.2.3)
151
191
  rack-test (1.1.0)
@@ -182,8 +222,15 @@ GEM
182
222
  regexp_parser (2.3.1)
183
223
  reline (0.3.1)
184
224
  io-console (~> 0.5)
225
+ responders (3.0.1)
226
+ actionpack (>= 5.0)
227
+ railties (>= 5.0)
185
228
  rexml (3.2.5)
186
229
  rouge (3.28.0)
230
+ route_translator (12.1.0)
231
+ actionpack (>= 5.2, < 7.1)
232
+ activesupport (>= 5.2, < 7.1)
233
+ addressable (~> 2.7)
187
234
  rubocop (1.28.2)
188
235
  parallel (~> 1.10)
189
236
  parser (>= 3.1.0.0)
@@ -199,6 +246,16 @@ GEM
199
246
  rubocop (>= 1.7.0, < 2.0)
200
247
  rubocop-ast (>= 0.4.0)
201
248
  ruby-progressbar (1.11.0)
249
+ ruby-vips (2.1.4)
250
+ ffi (~> 1.12)
251
+ sassc (2.4.0)
252
+ ffi (~> 1.9)
253
+ sassc-rails (2.1.2)
254
+ railties (>= 4.0.0)
255
+ sassc (>= 2.0)
256
+ sprockets (> 3.0)
257
+ sprockets-rails
258
+ tilt
202
259
  sprockets (4.0.3)
203
260
  concurrent-ruby (~> 1.0)
204
261
  rack (> 1, < 3)
@@ -210,12 +267,20 @@ GEM
210
267
  standard (1.11.0)
211
268
  rubocop (= 1.28.2)
212
269
  rubocop-performance (= 1.13.3)
270
+ stimulus-rails (1.0.4)
271
+ railties (>= 6.0.0)
213
272
  strscan (3.0.1)
214
273
  thor (1.2.1)
274
+ tilt (2.0.10)
215
275
  timeout (0.2.0)
276
+ turbo-rails (1.0.1)
277
+ actionpack (>= 6.0.0)
278
+ railties (>= 6.0.0)
216
279
  tzinfo (2.0.4)
217
280
  concurrent-ruby (~> 1.0)
218
281
  unicode-display_width (2.1.0)
282
+ warden (1.2.9)
283
+ rack (>= 2.0.9)
219
284
  websocket-driver (0.7.5)
220
285
  websocket-extensions (>= 0.1.0)
221
286
  websocket-extensions (0.1.5)
@@ -231,13 +296,25 @@ PLATFORMS
231
296
  x86_64-linux
232
297
 
233
298
  DEPENDENCIES
299
+ acts_as_list (~> 1.0)
300
+ breadcrumbs_on_rails (~> 4.1)
234
301
  capybara (>= 3.26)
235
302
  debug
303
+ devise (~> 4.8)
304
+ enumerize (~> 2.3)
236
305
  headmin!
306
+ hotwire-rails (~> 0.1)
307
+ image_processing (~> 1.2)
308
+ importmap-rails (~> 1.0)
309
+ inline_svg (~> 1.7)
310
+ kaminari (~> 1.2)
237
311
  minitest (~> 5.0)
238
312
  minitest-spec-rails (~> 6.1)
313
+ puma (~> 5.2)
239
314
  rails (~> 7.0)
240
315
  rake (~> 13.0)
316
+ route_translator (~> 12.0)
317
+ sassc-rails (~> 2.1)
241
318
  sprockets-rails (~> 3.4)
242
319
  sqlite3 (~> 1.4)
243
320
  standard (~> 1.7)
@@ -1,10 +1,6 @@
1
1
  import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  export default class extends Controller {
4
- static get targets () {
5
- return ['dateInput', 'startDateInput', 'endDateInput']
6
- }
7
-
8
4
  update (event) {
9
5
  const flatpickr = event.target._flatpickr
10
6
  const startDate = flatpickr.selectedDates[0]
@@ -15,11 +11,21 @@ export default class extends Controller {
15
11
  }
16
12
 
17
13
  setStartDateInputValue (value) {
18
- this.startDateInputTarget.value = value
14
+ const startDateInput = this.startDateInput()
15
+ startDateInput.value = value
19
16
  }
20
17
 
21
18
  setEndDateInputValue (value) {
22
- this.endDateInputTarget.value = value
19
+ const endDateInput = this.endDateInput()
20
+ endDateInput.value = value
21
+ }
22
+
23
+ startDateInput () {
24
+ return this.element.nextElementSibling
25
+ }
26
+
27
+ endDateInput () {
28
+ return this.startDateInput().nextElementSibling
23
29
  }
24
30
 
25
31
  formatDate (date) {
@@ -2,7 +2,13 @@ import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  export default class extends Controller {
4
4
  static get targets () {
5
- return ['button', 'popup']
5
+ return ['button', 'popup', 'conditional', 'operator', 'value', 'hidden', 'wrapper', 'template', 'row']
6
+ }
7
+
8
+ static get values () {
9
+ return {
10
+ name: String
11
+ }
6
12
  }
7
13
 
8
14
  // Attaches controller logic to the element itself
@@ -10,16 +16,7 @@ export default class extends Controller {
10
16
  connect () {
11
17
  this.element.controller = this
12
18
 
13
- // Clicked outside popup
14
- document.addEventListener('click', (event) => {
15
- this.handleOutsideClick(event)
16
- })
17
- }
18
-
19
- handleOutsideClick (event) {
20
- if (!this.isClickedInside(event)) {
21
- this.close()
22
- }
19
+ this.updateHiddenValue()
23
20
  }
24
21
 
25
22
  toggle (event) {
@@ -41,6 +38,38 @@ export default class extends Controller {
41
38
  this.popupTarget.classList.add('closed')
42
39
  }
43
40
 
41
+ add (event) {
42
+ event.preventDefault()
43
+ const html = this.getTemplateHTML()
44
+ this.wrapperTarget.insertAdjacentHTML('beforeend', html)
45
+ }
46
+
47
+ remove (event) {
48
+ event.preventDefault()
49
+ const inputGroup = event.currentTarget.closest('[data-filter-target="row"]')
50
+ // Check if there is a previous element (the conditional select). If no element (first inputGroup), take the next element.
51
+ const conditional = inputGroup.previousElementSibling != null ? inputGroup.previousElementSibling : inputGroup.nextElementSibling
52
+
53
+ inputGroup.remove()
54
+ // If there is only one inputGroup, the conditional is null, so do not attempt to remove it
55
+ if (conditional != null) conditional.remove()
56
+
57
+ // After we remove the UI, run update to also remove filter from the hidden input
58
+ this.updateHiddenValue()
59
+
60
+ // Check if there are still inputs left, else remove filter
61
+ if (this.valueTargets.length === 0) {
62
+ this.removeFilter()
63
+ }
64
+ }
65
+
66
+ removeFilter () {
67
+ const form = this.buttonTarget.closest('form')
68
+ this.buttonTarget.remove()
69
+ this.popupTarget.remove()
70
+ form.submit()
71
+ }
72
+
44
73
  isClickedInside (event) {
45
74
  if (!event) {
46
75
  return false
@@ -50,4 +79,25 @@ export default class extends Controller {
50
79
  const inAddButton = event.target.dataset.action === 'click->filters#add'
51
80
  return (inPopup || inButton || inAddButton)
52
81
  }
82
+
83
+ updateHiddenValue () {
84
+ this.hiddenTarget.value = this.buildInstructionString()
85
+ }
86
+
87
+ buildInstructionString () {
88
+ let string = ''
89
+ for (const row of this.rowTargets) {
90
+ const conditional = row.previousElementSibling ? row.previousElementSibling.querySelector('[data-filter-target="conditional"]').value : null
91
+ const operator = row.querySelector('[data-filter-target="operator"]').value
92
+ const value = row.querySelector('[data-filter-target="value"]').value
93
+ string += `${conditional || ''}${operator}:${value}`
94
+ }
95
+
96
+ return string
97
+ }
98
+
99
+ getTemplateHTML () {
100
+ const template = this.templateTarget
101
+ return template.innerHTML
102
+ }
53
103
  }
@@ -0,0 +1,50 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+
3
+ export default class extends Controller {
4
+ static get targets () {
5
+ return ['original', 'operator', 'null']
6
+ }
7
+
8
+ connect () {
9
+ this.operatorTarget.addEventListener('change', () => this.handleOperatorChange())
10
+ this.handleOperatorChange()
11
+ }
12
+
13
+ handleOperatorChange () {
14
+ if (this.operatorTarget.value === 'is_null' || this.operatorTarget.value === 'is_not_null') {
15
+ this.toggleNullInput()
16
+ } else {
17
+ this.toggleOriginalInput()
18
+ }
19
+ }
20
+
21
+ toggleNullInput () {
22
+ this.hideOriginal()
23
+ this.showNull()
24
+ }
25
+
26
+ toggleOriginalInput () {
27
+ this.showOriginal()
28
+ this.hideNull()
29
+ }
30
+
31
+ hideOriginal () {
32
+ this.originalTarget.style.display = 'none'
33
+ this.originalTarget.setAttribute('data-filter-target', 'value_original')
34
+ }
35
+
36
+ showOriginal () {
37
+ this.originalTarget.style.display = 'block'
38
+ this.originalTarget.setAttribute('data-filter-target', 'value')
39
+ }
40
+
41
+ hideNull () {
42
+ this.nullTarget.style.display = 'none'
43
+ this.nullTarget.setAttribute('data-filter-target', 'value_null')
44
+ }
45
+
46
+ showNull () {
47
+ this.nullTarget.style.display = 'block'
48
+ this.nullTarget.setAttribute('data-filter-target', 'value')
49
+ }
50
+ }
@@ -4,17 +4,13 @@ import { Dutch } from 'flatpickr/dist/esm/l10n/nl.js'
4
4
  import I18n from '../config/i18n'
5
5
 
6
6
  export default class extends Controller {
7
- static get targets () {
8
- return ['input']
9
- }
10
-
11
7
  connect () {
12
8
  const options = { ...this.defaultOptions(), ...this.options() }
13
- flatpickr(this.inputTarget, options)
9
+ flatpickr(this.element, options)
14
10
  }
15
11
 
16
12
  options () {
17
- return JSON.parse(this.inputTarget.getAttribute('data-flatpickr'))
13
+ return JSON.parse(this.element.getAttribute('data-flatpickr'))
18
14
  }
19
15
 
20
16
  defaultOptions () {
@@ -0,0 +1,237 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+ import Sortable from 'sortablejs'
3
+
4
+ export default class extends Controller {
5
+ static get targets () {
6
+ return ['item', 'template', 'thumbnails', 'modalButton', 'placeholder', 'validationInput', 'count', 'editButton']
7
+ }
8
+
9
+ connect () {
10
+ document.addEventListener('mediaSelectionSubmitted', (event) => {
11
+ if (event.detail.name === this.element.dataset.name) {
12
+ this.selectItems(event.detail.items)
13
+ }
14
+ })
15
+
16
+ // Init sorting
17
+ if(this.hasSorting()) {
18
+ this.initSortable()
19
+ }
20
+
21
+ this.validate()
22
+ }
23
+
24
+ // Actions
25
+ destroy (event) {
26
+ const item = event.currentTarget.closest('[data-media-target=\'item\']')
27
+ this.destroyItem(item)
28
+ }
29
+
30
+ syncIds () {
31
+ const ids = this.activeIds()
32
+
33
+ this.modalButtonTargets.forEach((button) => {
34
+ const url = new URL(button.getAttribute('href'))
35
+
36
+ // Remove all ids[]
37
+ url.searchParams.delete('ids[]')
38
+
39
+ // Add new ids
40
+ ids.forEach((id) => {
41
+ url.searchParams.append('ids[]', id)
42
+ })
43
+
44
+ button.setAttribute('href', url.toString())
45
+ })
46
+ }
47
+
48
+ // Methods
49
+ initSortable() {
50
+ Sortable.create(this.thumbnailsTarget, {
51
+ handle: '.media-drag-sort-handle',
52
+ onEnd: (event) => {
53
+ this.resetPositions()
54
+ }
55
+ })
56
+ }
57
+
58
+ hasSorting() {
59
+ return this.element.dataset.sort === "true"
60
+ }
61
+
62
+ destroyItem (item) {
63
+ this.removeItem(item)
64
+ this.postProcess()
65
+ }
66
+
67
+ selectItems (items) {
68
+ // Destroy all deselected items
69
+ this.removeAllItems()
70
+
71
+ // Add all selected items
72
+ this.addItems(items)
73
+
74
+ this.postProcess()
75
+ }
76
+
77
+ postProcess () {
78
+ // Reset positions
79
+ this.resetPositions()
80
+
81
+ // Sync Ids
82
+ this.syncIds()
83
+
84
+ // Toggle placeholder
85
+ this.togglePlaceholder()
86
+
87
+ // Validate
88
+ this.validate()
89
+ }
90
+
91
+ validate () {
92
+ this.clearValidation()
93
+ if (this.element.dataset.required === "0") return
94
+ this.validateMinimum()
95
+ this.validateMaximum()
96
+ }
97
+
98
+ clearValidation () {
99
+ this.validationInputTarget.setCustomValidity('')
100
+ }
101
+
102
+ validateMinimum () {
103
+ const count = this.activeItems().length
104
+ if (count < this.minActiveItems()) {
105
+ this.validationInputTarget.setCustomValidity(this.validationInputTarget.dataset.minMessage)
106
+ }
107
+ }
108
+
109
+ validateMaximum () {
110
+ const count = this.activeItems().length
111
+ if (count > this.maxActiveItems()) {
112
+ this.validationInputTarget.setCustomValidity(this.validationInputTarget.dataset.maxMessage)
113
+ }
114
+ }
115
+
116
+ minActiveItems () {
117
+ return parseInt(this.element.dataset.min, 10) || 0
118
+ }
119
+
120
+ maxActiveItems () {
121
+ return parseInt(this.element.dataset.max, 10) || Infinity
122
+ }
123
+
124
+ resetPositions () {
125
+ this.activeItems().forEach((item, index) => {
126
+ const positionInput = item.querySelector('input[name*=\'position\']')
127
+ if (positionInput) {
128
+ positionInput.value = index
129
+ }
130
+ })
131
+ }
132
+
133
+ addItems (items) {
134
+ items.forEach((item) => this.addItem(item))
135
+ }
136
+
137
+ addItem (item) {
138
+ const currentItem = this.itemByBlobId(item.blobId)
139
+ if (currentItem) {
140
+ // (re-)enable if already exists
141
+ this.enableItem(currentItem)
142
+ } else {
143
+ // Create if item doesn't exist yet
144
+ this.createItem(item)
145
+ }
146
+ }
147
+
148
+ togglePlaceholder () {
149
+ if (this.activeItems().length > 0) {
150
+ this.hidePlaceholder()
151
+ } else {
152
+ this.showPlaceholder()
153
+ }
154
+ }
155
+
156
+ showPlaceholder () {
157
+ this.placeholderTarget.classList.remove('d-none')
158
+ }
159
+
160
+ hidePlaceholder () {
161
+ this.placeholderTarget.classList.add('d-none')
162
+ }
163
+
164
+ enableItem (item) {
165
+ item.querySelector(`input[name*='_destroy']`).value = false
166
+ item.classList.remove('d-none')
167
+ }
168
+
169
+ createItem (item) {
170
+ // Copy template
171
+ const template = this.templateTarget
172
+ const html = this.randomizeIds(template)
173
+ this.thumbnailsTarget.insertAdjacentHTML('beforeend', html)
174
+
175
+ // Set new values
176
+ const newItem = this.itemTargets.pop()
177
+ newItem.querySelector(`input[name*="[blob_id]"]`).value = item.blobId
178
+ newItem.querySelector(`input[name*="[_destroy]"]`).value = false
179
+
180
+ // Update edit button url
181
+ const editButton = newItem.querySelector(`[data-media-target="editButton"]`)
182
+ editButton.setAttribute('href', editButton.getAttribute('href').replace('$1', item.blobId))
183
+
184
+ // Copy thumbnail
185
+ const oldThumbnail = newItem.querySelector('.h-thumbnail')
186
+ const newThumbnail = item.thumbnail.cloneNode(true)
187
+ oldThumbnail.parentNode.replaceChild(newThumbnail, oldThumbnail)
188
+ }
189
+
190
+ randomizeIds (template) {
191
+ const regex = new RegExp(template.dataset.templateIdRegex, 'g')
192
+ const randomNumber = Math.floor(100000000 + Math.random() * 900000000)
193
+ return template.innerHTML.replace(regex, randomNumber)
194
+ }
195
+
196
+ removeAllItems () {
197
+ this.removeItems(this.itemTargets)
198
+ }
199
+
200
+ removeItems (items) {
201
+ items.forEach((item) => {
202
+ this.removeItem(item)
203
+ })
204
+ }
205
+
206
+ removeItem (item) {
207
+ item.querySelector(`input[name*='_destroy']`).value = 1
208
+ item.classList.add('d-none')
209
+
210
+ // Reset positions
211
+ this.resetPositions()
212
+
213
+ // Sync ids
214
+ this.syncIds()
215
+
216
+ // Toggle placeholder
217
+ this.togglePlaceholder()
218
+ }
219
+
220
+ itemByBlobId (blobId) {
221
+ return this.itemTargets.find((item) => {
222
+ return item.querySelector(`input[name*='blob_id']`).value === blobId
223
+ })
224
+ }
225
+
226
+ activeItems () {
227
+ return this.itemTargets.filter((item) => {
228
+ return item.querySelector(`input[name$='[_destroy]']`).value === 'false'
229
+ })
230
+ }
231
+
232
+ activeIds () {
233
+ return this.activeItems().map((item) => {
234
+ return item.querySelector(`input[name$='[blob_id]']`).value
235
+ })
236
+ }
237
+ }