avo 2.7.0 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of avo might be problematic. Click here for more details.

Files changed (174) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +6 -4
  4. data/README.md +11 -0
  5. data/app/assets/stylesheets/avo.css +4 -4
  6. data/app/assets/stylesheets/css/{components → fields}/code.css +0 -0
  7. data/app/assets/stylesheets/css/{components → fields}/progress.css +0 -0
  8. data/app/assets/stylesheets/css/{components → fields}/status.css +0 -0
  9. data/app/assets/stylesheets/css/fields/trix.css +17 -0
  10. data/app/assets/svgs/download-solid-reversed.svg +2 -2
  11. data/app/components/avo/actions_component.html.erb +5 -13
  12. data/app/components/avo/actions_component.rb +39 -1
  13. data/app/components/avo/alert_component.rb +6 -0
  14. data/app/components/avo/card_component.html.erb +2 -2
  15. data/app/components/avo/common_field_wrapper_component.html.erb +11 -4
  16. data/app/components/avo/common_field_wrapper_component.rb +27 -1
  17. data/app/components/avo/edit/field_wrapper_component.html.erb +1 -1
  18. data/app/components/avo/fields/badge_field/index_component.html.erb +1 -1
  19. data/app/components/avo/fields/badge_field/show_component.html.erb +1 -1
  20. data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +21 -10
  21. data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +7 -1
  22. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +27 -15
  23. data/app/components/avo/fields/belongs_to_field/edit_component.rb +4 -0
  24. data/app/components/avo/fields/belongs_to_field/index_component.html.erb +1 -1
  25. data/app/components/avo/fields/belongs_to_field/show_component.html.erb +1 -1
  26. data/app/components/avo/fields/boolean_field/edit_component.html.erb +4 -2
  27. data/app/components/avo/fields/boolean_field/index_component.html.erb +1 -1
  28. data/app/components/avo/fields/boolean_field/show_component.html.erb +1 -1
  29. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +7 -1
  30. data/app/components/avo/fields/boolean_group_field/index_component.html.erb +1 -1
  31. data/app/components/avo/fields/boolean_group_field/show_component.html.erb +1 -1
  32. data/app/components/avo/fields/code_field/edit_component.html.erb +7 -5
  33. data/app/components/avo/fields/code_field/show_component.html.erb +2 -2
  34. data/app/components/avo/fields/common/key_value_component.html.erb +10 -4
  35. data/app/components/avo/fields/common/key_value_component.rb +2 -0
  36. data/app/components/avo/fields/country_field/edit_component.html.erb +4 -2
  37. data/app/components/avo/fields/country_field/index_component.html.erb +1 -1
  38. data/app/components/avo/fields/country_field/show_component.html.erb +1 -1
  39. data/app/components/avo/fields/date_field/edit_component.html.erb +6 -4
  40. data/app/components/avo/fields/date_field/index_component.html.erb +1 -1
  41. data/app/components/avo/fields/date_field/show_component.html.erb +1 -1
  42. data/app/components/avo/fields/date_time_field/edit_component.html.erb +6 -4
  43. data/app/components/avo/fields/date_time_field/index_component.html.erb +1 -1
  44. data/app/components/avo/fields/date_time_field/show_component.html.erb +1 -1
  45. data/app/components/avo/fields/edit_component.rb +7 -0
  46. data/app/components/avo/fields/external_image_field/edit_component.html.erb +5 -2
  47. data/app/components/avo/fields/external_image_field/index_component.html.erb +6 -4
  48. data/app/components/avo/fields/external_image_field/show_component.html.erb +1 -1
  49. data/app/components/avo/fields/file_field/edit_component.html.erb +6 -1
  50. data/app/components/avo/fields/file_field/index_component.html.erb +1 -1
  51. data/app/components/avo/fields/file_field/show_component.html.erb +1 -1
  52. data/app/components/avo/fields/files_field/edit_component.html.erb +7 -1
  53. data/app/components/avo/fields/files_field/index_component.html.erb +1 -1
  54. data/app/components/avo/fields/files_field/show_component.html.erb +1 -1
  55. data/app/components/avo/fields/gravatar_field/index_component.html.erb +1 -1
  56. data/app/components/avo/fields/gravatar_field/show_component.html.erb +1 -1
  57. data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
  58. data/app/components/avo/fields/hidden_field/edit_component.html.erb +5 -1
  59. data/app/components/avo/fields/id_field/edit_component.html.erb +1 -1
  60. data/app/components/avo/fields/id_field/index_component.html.erb +1 -1
  61. data/app/components/avo/fields/id_field/show_component.html.erb +1 -1
  62. data/app/components/avo/fields/index_component.rb +3 -0
  63. data/app/components/avo/fields/key_value_field/edit_component.html.erb +1 -1
  64. data/app/components/avo/fields/key_value_field/show_component.html.erb +1 -1
  65. data/app/components/avo/fields/markdown_field/edit_component.html.erb +8 -5
  66. data/app/components/avo/fields/markdown_field/show_component.html.erb +1 -1
  67. data/app/components/avo/fields/number_field/edit_component.html.erb +7 -4
  68. data/app/components/avo/fields/number_field/index_component.html.erb +1 -1
  69. data/app/components/avo/fields/number_field/show_component.html.erb +1 -1
  70. data/app/components/avo/fields/password_field/edit_component.html.erb +4 -2
  71. data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +7 -4
  72. data/app/components/avo/fields/progress_bar_field/index_component.html.erb +1 -1
  73. data/app/components/avo/fields/progress_bar_field/show_component.html.erb +1 -1
  74. data/app/components/avo/fields/select_field/edit_component.html.erb +9 -3
  75. data/app/components/avo/fields/select_field/index_component.html.erb +1 -1
  76. data/app/components/avo/fields/select_field/show_component.html.erb +1 -1
  77. data/app/components/avo/fields/show_component.rb +3 -0
  78. data/app/components/avo/fields/status_field/edit_component.html.erb +6 -3
  79. data/app/components/avo/fields/status_field/index_component.html.erb +1 -1
  80. data/app/components/avo/fields/status_field/show_component.html.erb +1 -1
  81. data/app/components/avo/fields/tags_field/edit_component.html.erb +19 -11
  82. data/app/components/avo/fields/tags_field/index_component.html.erb +1 -1
  83. data/app/components/avo/fields/tags_field/show_component.html.erb +1 -1
  84. data/app/components/avo/fields/text_field/edit_component.html.erb +5 -2
  85. data/app/components/avo/fields/text_field/index_component.html.erb +1 -1
  86. data/app/components/avo/fields/text_field/show_component.html.erb +1 -1
  87. data/app/components/avo/fields/textarea_field/edit_component.html.erb +6 -3
  88. data/app/components/avo/fields/textarea_field/show_component.html.erb +1 -1
  89. data/app/components/avo/fields/trix_field/edit_component.html.erb +14 -4
  90. data/app/components/avo/fields/trix_field/edit_component.rb +3 -0
  91. data/app/components/avo/fields/trix_field/show_component.html.erb +2 -2
  92. data/app/components/avo/index/field_wrapper_component.html.erb +12 -5
  93. data/app/components/avo/index/field_wrapper_component.rb +27 -3
  94. data/app/components/avo/panel_component.rb +4 -3
  95. data/app/components/avo/resource_component.rb +1 -0
  96. data/app/components/avo/show/field_wrapper_component.html.erb +1 -1
  97. data/app/components/avo/show/field_wrapper_component.rb +2 -1
  98. data/app/components/avo/sidebar/item_switcher_component.html.erb +2 -2
  99. data/app/components/avo/views/resource_edit_component.html.erb +13 -8
  100. data/app/components/avo/views/resource_edit_component.rb +32 -3
  101. data/app/components/avo/views/resource_index_component.html.erb +7 -4
  102. data/app/components/avo/views/resource_index_component.rb +7 -1
  103. data/app/components/avo/views/resource_show_component.html.erb +11 -9
  104. data/app/components/avo/views/resource_show_component.rb +1 -0
  105. data/app/controllers/avo/actions_controller.rb +4 -1
  106. data/app/controllers/avo/base_controller.rb +24 -13
  107. data/app/controllers/avo/cards_controller.rb +25 -0
  108. data/app/controllers/avo/dashboards_controller.rb +2 -8
  109. data/app/controllers/avo/home_controller.rb +8 -1
  110. data/app/controllers/avo/search_controller.rb +7 -1
  111. data/app/helpers/avo/url_helpers.rb +8 -9
  112. data/app/javascript/js/controllers/fields/code_field_controller.js +7 -1
  113. data/app/javascript/js/controllers/fields/key_value_controller.js +1 -0
  114. data/app/javascript/js/controllers/fields/tags_field_controller.js +0 -1
  115. data/app/javascript/js/controllers/menu_controller.js +4 -3
  116. data/app/javascript/js/controllers/resource_edit_controller.js +72 -0
  117. data/app/javascript/js/controllers/resource_index_controller.js +4 -0
  118. data/app/javascript/js/controllers/resource_show_controller.js +4 -0
  119. data/app/javascript/js/controllers/search_controller.js +28 -5
  120. data/app/javascript/js/controllers.js +8 -0
  121. data/app/views/avo/associations/new.html.erb +2 -1
  122. data/app/views/avo/base/_select_filter.html.erb +1 -1
  123. data/app/views/avo/base/_text_filter.html.erb +1 -0
  124. data/app/views/avo/base/edit.html.erb +2 -1
  125. data/app/views/avo/base/new.html.erb +1 -1
  126. data/app/views/avo/{dashboards → cards}/_chartkick_card.html.erb +0 -0
  127. data/app/views/avo/{dashboards → cards}/_metric_card.html.erb +0 -0
  128. data/app/views/avo/{dashboards/card.html.erb → cards/show.html.erb} +0 -0
  129. data/app/views/avo/partials/_custom_tools_alert.html.erb +21 -7
  130. data/app/views/avo/partials/_logo.html.erb +3 -2
  131. data/app/views/avo/partials/_navbar.html.erb +1 -1
  132. data/app/views/avo/partials/_table_header.html.erb +9 -1
  133. data/bin/test +1 -0
  134. data/config/routes.rb +7 -4
  135. data/db/factories.rb +1 -0
  136. data/lib/avo/app.rb +18 -1
  137. data/lib/avo/base_action.rb +16 -4
  138. data/lib/avo/base_card.rb +0 -23
  139. data/lib/avo/base_resource.rb +23 -16
  140. data/lib/avo/concerns/fetches_things.rb +19 -12
  141. data/lib/avo/concerns/has_fields.rb +93 -0
  142. data/lib/avo/concerns/has_html_attributes.rb +110 -0
  143. data/lib/avo/concerns/has_model.rb +11 -0
  144. data/lib/avo/concerns/has_stimulus_controllers.rb +42 -0
  145. data/lib/avo/dynamic_router.rb +1 -1
  146. data/lib/avo/engine.rb +1 -3
  147. data/lib/avo/fields/base_field.rb +24 -13
  148. data/lib/avo/fields/concerns/is_required.rb +17 -0
  149. data/lib/avo/fields/select_field.rb +1 -1
  150. data/lib/avo/grid_collector.rb +4 -4
  151. data/lib/avo/hosts/view_record_host.rb +7 -0
  152. data/lib/avo/html/builder.rb +117 -0
  153. data/lib/avo/licensing/pro_license.rb +1 -0
  154. data/lib/avo/menu/base_item.rb +4 -0
  155. data/lib/avo/menu/dashboard.rb +5 -0
  156. data/lib/avo/menu/resource.rb +5 -0
  157. data/lib/avo/version.rb +1 -1
  158. data/lib/avo.rb +5 -0
  159. data/lib/generators/avo/install_generator.rb +1 -4
  160. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +11 -1
  161. data/lib/generators/avo/templates/cards/metric_card_sample.tt +11 -1
  162. data/lib/generators/avo/templates/field/components/edit_component.html.erb.tt +1 -1
  163. data/lib/generators/avo/templates/field/components/index_component.html.erb.tt +1 -1
  164. data/lib/generators/avo/templates/field/components/show_component.html.erb.tt +1 -1
  165. data/lib/generators/avo/templates/initializer/avo.tt +1 -1
  166. data/lib/generators/avo/templates/locales/avo.en.yml +3 -3
  167. data/public/avo-assets/avo.css +473 -1055
  168. data/public/avo-assets/avo.js +147 -147
  169. data/public/avo-assets/avo.js.map +3 -3
  170. data/public/avo-assets/logomark.png +0 -0
  171. metadata +21 -11
  172. data/app/components/avo/views/resource_new_component.html.erb +0 -55
  173. data/app/components/avo/views/resource_new_component.rb +0 -38
  174. data/lib/avo/fields_collector.rb +0 -70
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c49705a72c31381fe9a133a58b1953d56513fda407157b4c92a17f933424b3e5
4
- data.tar.gz: 6680ac6be68f89e9ecdbce81f3ee2ecd18915369509c27914835f824f8da550e
3
+ metadata.gz: 7a1d99b5007b69c25b8eb7b426fd8881d9baacc700d4f14c0ed8dfeac81c7004
4
+ data.tar.gz: bb18e3d2d52f500c3d73ae8f29bf0165ea560905c848388bfeef127850cc5e79
5
5
  SHA512:
6
- metadata.gz: b34915f9540a2e057df9cde8c228077eec22bafee204cb076399a1eb2b3ee36834aff7fb50b9fb57060c3271cb31387d7fcbd27642fca8222a245db04cc70182
7
- data.tar.gz: 0a3ce0cad78f3fd6b3cde3534d879e9729569e3e3ac8ea595fd4266c77b6025227bad0154a2f69263c1e8858337906c788d63f635976e2678a94f95d5419d72b
6
+ metadata.gz: 516b6413536158cd998e3addbb3b327f3fbdbdec504a9f1502aaadc5f52925490966c22a5d67f161933e08e5c5c0f4c0a0bf1e3a207216297dd65e50966569b9
7
+ data.tar.gz: 5474fa61b0268b691865abc602271828c49500612bbe22617a2bf117fc1c2cc05ab0568ba78ea917ff021bf63bfd63ad9d728868d723e9684dc9c7c38e636615
data/Gemfile CHANGED
@@ -152,3 +152,5 @@ gem 'acts_as_list'
152
152
  gem 'acts-as-taggable-on', '~> 9.0'
153
153
 
154
154
  gem "bundler-integrity", "~> 1.0"
155
+
156
+ gem 'erb-formatter'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (2.7.0)
4
+ avo (2.9.0)
5
5
  active_link_to
6
6
  addressable
7
7
  breadcrumbs_on_rails
@@ -136,7 +136,7 @@ GEM
136
136
  rack-test (>= 0.6.3)
137
137
  regexp_parser (>= 1.5, < 3.0)
138
138
  xpath (~> 3.2)
139
- chartkick (4.1.3)
139
+ chartkick (4.2.0)
140
140
  childprocess (4.1.0)
141
141
  concurrent-ruby (1.1.9)
142
142
  countries (4.2.1)
@@ -167,6 +167,7 @@ GEM
167
167
  dotenv (= 2.7.6)
168
168
  railties (>= 3.2)
169
169
  dry-initializer (3.1.1)
170
+ erb-formatter (0.3.0)
170
171
  erubi (1.10.0)
171
172
  factory_bot (6.2.0)
172
173
  activesupport (>= 5.0.0)
@@ -210,7 +211,7 @@ GEM
210
211
  io-wait (0.2.1)
211
212
  iso (0.4.0)
212
213
  i18n
213
- jmespath (1.5.0)
214
+ jmespath (1.6.1)
214
215
  jsbundling-rails (1.0.0)
215
216
  railties (>= 6.0.0)
216
217
  launchy (2.5.0)
@@ -264,7 +265,7 @@ GEM
264
265
  pundit (2.2.0)
265
266
  activesupport (>= 3.0.0)
266
267
  racc (1.6.0)
267
- rack (2.2.3)
268
+ rack (2.2.3.1)
268
269
  rack-test (1.1.0)
269
270
  rack (>= 1.0, < 3)
270
271
  rails (6.1.4.6)
@@ -441,6 +442,7 @@ DEPENDENCIES
441
442
  database_cleaner
442
443
  devise
443
444
  dotenv-rails
445
+ erb-formatter
444
446
  factory_bot_rails
445
447
  faker
446
448
  friendly_id (~> 5.4.0)
data/README.md CHANGED
@@ -76,6 +76,17 @@ Please read the [UPGRADE_GUIDE.MD](https://docs.avohq.io/2.0/upgrade.html)
76
76
  </a>
77
77
  <!-- https://contrib.rocks -->
78
78
 
79
+ # 🥇 Business & Agency Sponsors
80
+
81
+ <a href="https://equipetechnique.com/?utm_source=github&utm_medium=link&utm_campaign=avo_code_without_borders" target="_blank">
82
+ <picture>
83
+ <source media="(prefers-color-scheme: dark)" srcset="https://avohq.io/img/sponsors/ET-dark.jpeg">
84
+ <img alt="Equipe Technique Busines Sponsor" src="https://avohq.io/img/sponsors/ET-light.jpeg" width="240px">
85
+ </picture>
86
+ </a>
87
+
88
+ [Become a sponsor ](https://github.com/sponsors/adrianthedev)
89
+
79
90
 
80
91
  ![Alt](https://repobeats.axiom.co/api/embed/1481a6a259064f02a7936470d12a50802a9c98a4.svg "Repobeats analytics image")
81
92
 
@@ -1,7 +1,6 @@
1
1
  @import './../../../node_modules/simplemde/dist/simplemde.min.css';
2
2
  @import './../../../node_modules/tippy.js/dist/tippy.css';
3
3
  @import './../../../node_modules/tippy.js/themes/light.css';
4
- @import './../../../node_modules/trix/dist/trix.css';
5
4
  @import './../../../node_modules/flatpickr/dist/flatpickr.css';
6
5
  @import './../../../node_modules/@algolia/autocomplete-theme-classic/dist/theme.css';
7
6
  @import './../../../node_modules/@yaireo/tagify/dist/tagify.css';
@@ -20,9 +19,10 @@
20
19
  @import './css/spinner.css';
21
20
  @import './css/tags.css';
22
21
 
23
- @import './css/components/status.css';
24
- @import './css/components/code.css';
25
- @import './css/components/progress.css';
22
+ @import './css/fields/status.css';
23
+ @import './css/fields/code.css';
24
+ @import './css/fields/progress.css';
25
+ @import './css/fields/trix.css';
26
26
 
27
27
  @import 'tailwindcss/components';
28
28
 
@@ -0,0 +1,17 @@
1
+ @import './../../../../../node_modules/trix/dist/trix.css';
2
+
3
+ .trix-content h1 {
4
+ @apply text-xl font-bold mb-2;
5
+ }
6
+
7
+ .trix-content ul {
8
+ @apply list-disc;
9
+ }
10
+
11
+ .trix-content pre {
12
+ @apply text-base;
13
+ }
14
+
15
+ .trix-content ol {
16
+ @apply list-decimal;
17
+ }
@@ -1,3 +1,3 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" transform="rotate(-180)">
2
- <path fill-rule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" />
1
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
2
+ <path fill-rule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" transform="rotate(-180 10 10)" />
3
3
  </svg>
@@ -4,6 +4,7 @@
4
4
  data-actions-picker-disabled-class="cursor-wait text-gray-500"
5
5
  >
6
6
  <%= a_button style: :outline,
7
+ type: :button,
7
8
  color: :primary,
8
9
  class: "focus:outline-none",
9
10
  icon: 'arrow-circle-right',
@@ -18,24 +19,15 @@
18
19
  >
19
20
  <div class="w-full space divide-y">
20
21
  <% @actions.each_with_index do |action, index| %>
21
- <%
22
- path = action_name == 'show' ?
23
- "#{@resource.record_path}/actions/#{action.param_id}" :
24
- "#{@resource.records_path}/actions/#{action.param_id}"
25
- if action_name == 'show' || action.standalone
26
- disabled = false
27
- else
28
- disabled = true
29
- end
30
- %>
31
- <%= link_to path,
22
+ <%= link_to action_path(action.param_id),
32
23
  data: {
33
24
  'turbo-frame': 'actions_show',
34
25
  'action': 'click->actions-picker#visitAction',
35
26
  'actions-picker-target': action.standalone ? 'standaloneAction' : 'resourceAction',
36
- 'disabled': disabled,
27
+ 'disabled': is_disabled?(action),
37
28
  },
38
- class: "flex items-center px-4 py-3 w-full font-semibold text-sm #{disabled ? 'text-gray-500' : 'text-black hover:bg-blue-500 hover:text-white'}" do %>
29
+ title: action.action_name,
30
+ class: "flex items-center px-4 py-3 w-full font-semibold text-sm #{is_disabled?(action) ? 'text-gray-500' : 'text-black hover:bg-blue-500 hover:text-white'}" do %>
39
31
  <%= svg 'play', class: 'h-5 mr-1 inline' %> <%= action.action_name %>
40
32
  <% end %>
41
33
  <% end %>
@@ -3,12 +3,50 @@
3
3
  class Avo::ActionsComponent < ViewComponent::Base
4
4
  include Avo::ApplicationHelper
5
5
 
6
- def initialize(actions: [], resource: nil)
6
+ def initialize(actions: [], resource: nil, view: nil)
7
7
  @actions = actions
8
8
  @resource = resource
9
+ @view = view
9
10
  end
10
11
 
11
12
  def render?
12
13
  @actions.present?
13
14
  end
15
+
16
+ # When running an action for one record we should do it on a special path.
17
+ # We do that so we get the `model` param inside the action so we can prefill fields.
18
+ def action_path(id)
19
+ return many_records_path(id) unless @resource.has_model_id?
20
+
21
+ if on_record_page?
22
+ single_record_path id
23
+ else
24
+ many_records_path id
25
+ end
26
+ end
27
+
28
+ # How should the action be displayed by default
29
+ def is_disabled?(action)
30
+ return false if action.standalone
31
+
32
+ on_index_page?
33
+ end
34
+
35
+ private
36
+
37
+ def on_record_page?
38
+ @view.in?([:show, :edit, :new])
39
+ end
40
+
41
+ def on_index_page?
42
+ !on_record_page?
43
+ end
44
+
45
+ def single_record_path(id)
46
+ "#{@resource.record_path}/actions/#{id}"
47
+ end
48
+
49
+ def many_records_path(id)
50
+ "#{@resource.records_path}/actions/#{id}"
51
+ end
14
52
  end
@@ -21,6 +21,8 @@ class Avo::AlertComponent < ViewComponent::Base
21
21
  end
22
22
 
23
23
  def classes
24
+ return "hidden" if is_empty?
25
+
24
26
  result = "max-w-lg w-full shadow-lg rounded px-4 py-3 rounded relative border text-white pointer-events-auto"
25
27
 
26
28
  result += if is_error?
@@ -51,4 +53,8 @@ class Avo::AlertComponent < ViewComponent::Base
51
53
  def is_warning?
52
54
  type.to_sym == :warning
53
55
  end
56
+
57
+ def is_empty?
58
+ message.nil?
59
+ end
54
60
  end
@@ -11,8 +11,8 @@
11
11
  <%= @card.label %>
12
12
  </div>
13
13
  <div data-controller="select">
14
- <% if @card.type == :metric && @card.parsed_ranges.present? %>
15
- <%= select_tag "#{@card.id}_#{@card.index}_range", options_for_select(@card.parsed_ranges, @card.range),
14
+ <% if @card.type.in?([:metric, :chartkick, :partial]) && @card.ranges.present? %>
15
+ <%= select_tag "#{@card.id}_#{@card.index}_range", options_for_select(@card.ranges, @card.range),
16
16
  class: 'appearance-none inline-flex bg-blue-gray-100 disabled:bg-blue-gray-300 disabled:cursor-not-allowed focus:bg-white text-sm text-blue-gray-700 disabled:text-blue-gray-700 leading-none rounded-md py-px px-2 leading-tight border outline-none outline w-24',
17
17
  data: {
18
18
  target: 'select',
@@ -1,15 +1,22 @@
1
- <div class="flex flex-col md:flex-row md:items-center pb-2 md:pb-0 leading-tight <%= @classes %> min-h-14" data-field-id="<%= @field.id %>" data-field-type="<%= @field.type %>">
2
- <div class="pt-4 md:pt-0 md:h-14 flex self-start items-center text-slate-800">
1
+ <%= content_tag :div,
2
+ class: classes("relative flex flex-col md:flex-row md:items-center pb-2 md:pb-0 leading-tight min-h-14"),
3
+ style: style,
4
+ data: {
5
+ field_id: @field.id,
6
+ field_type: @field.type,
7
+ **stimulus_attributes,
8
+ } do %>
9
+ <div class="h-full pt-4 md:pt-0 md:h-14 flex self-start items-center text-slate-800">
3
10
  <div class="<% if @displayed_in_modal %> md:w-48 <% else %> md:w-64 px-6 md:px-6 <% end %> w-48 flex uppercase font-semibold text-gray-500 text-sm" data-slot="label">
4
11
  <% if @form.present? %>
5
12
  <%= @form.label @field.id, label %>
6
13
  <% else %>
7
14
  <%= @field.name %>
8
15
  <% end %>
9
- <% if @field.required %> <span class="text-red-600 ml-1">*</span> <% end %>
16
+ <% if @field.is_required? %> <span class="text-red-600 ml-1">*</span> <% end %>
10
17
  </div>
11
18
  </div>
12
19
  <div class="flex-1 flex flex-row md:min-h-inherit py-2 <% unless @displayed_in_modal %> px-6 <% end %>">
13
20
  <%= content %>
14
21
  </div>
15
- </div>
22
+ <% end %>
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::CommonFieldWrapperComponent < ViewComponent::Base
4
- def initialize(field: nil, dash_if_blank: true, full_width: false, displayed_in_modal: false, form: nil, resource: {}, label: nil, **args)
4
+ attr_reader :view
5
+
6
+ def initialize(field: nil, dash_if_blank: true, full_width: false, displayed_in_modal: false, form: nil, resource: nil, label: nil, view: nil, **args)
5
7
  @field = field
6
8
  @dash_if_blank = dash_if_blank
7
9
  @classes = args[:class].present? ? args[:class] : ""
@@ -12,9 +14,33 @@ class Avo::CommonFieldWrapperComponent < ViewComponent::Base
12
14
  @model = resource.present? ? resource.model : nil
13
15
  @full_width = full_width
14
16
  @label = label
17
+ @view = view
18
+ end
19
+
20
+ def classes(extra_classes = "")
21
+ "#{@classes || ""} #{extra_classes || ""} #{@field.get_html(:classes, view: view, element: :wrapper)}"
22
+ end
23
+
24
+ def style
25
+ @field.get_html(:style, view: view, element: :wrapper)
15
26
  end
16
27
 
17
28
  def label
18
29
  @label || @field.name
19
30
  end
31
+
32
+ def stimulus_attributes
33
+ attributes = {}
34
+
35
+ @resource.get_stimulus_controllers.split(" ").each do |controller|
36
+ attributes["#{controller}-target"] = "#{@field.id.to_s.underscore}_#{@field.type.to_s.underscore}_wrapper".camelize(:lower)
37
+ end
38
+
39
+ wrapper_data_attributes = @field.get_html :data, view: view, element: :wrapper
40
+ if wrapper_data_attributes.present?
41
+ attributes.merge! wrapper_data_attributes
42
+ end
43
+
44
+ attributes
45
+ end
20
46
  end
@@ -1,4 +1,4 @@
1
- <%= render Avo::CommonFieldWrapperComponent.new(field: @field, resource: @resource, index: @index, form: @form, displayed_in_modal: @displayed_in_modal, label: @label) do %>
1
+ <%= render Avo::CommonFieldWrapperComponent.new(field: @field, resource: @resource, index: @index, form: @form, displayed_in_modal: @displayed_in_modal, label: @label, view: @resource.view, class: @classes) do %>
2
2
  <div class="self-center <% if @displayed_in_modal or @full_width %> w-full <% else %> w-full md:w-8/12 <% end %>" data-slot="value">
3
3
  <%= content %>
4
4
  <% if @model.present? and @model.errors.include? @field.id %>
@@ -1,3 +1,3 @@
1
- <%= index_field_wrapper field: @field, flush: true do %>
1
+ <%= index_field_wrapper field: @field, resource: @resource, flush: true do %>
2
2
  <%= render Avo::Fields::Common::BadgeViewerComponent.new value: @field.value, options: @field.options %>
3
3
  <% end %>
@@ -1,3 +1,3 @@
1
- <%= show_field_wrapper field: @field, index: @index do %>
1
+ <%= show_field_wrapper field: @field, resource: @resource, index: @index do %>
2
2
  <%= render Avo::Fields::Common::BadgeViewerComponent.new value: @field.value, options: @field.options %>
3
3
  <% end %>
@@ -13,24 +13,35 @@
13
13
  ></div>
14
14
  <div class="relative w-full" autocomplete="off">
15
15
  <%= @form.text_field @foreign_key,
16
- type: :text,
17
- value: field_label,
18
- class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
19
- placeholder: @field.placeholder,
20
- 'data-search-target': 'button clearValue',
16
+ class: classes,
21
17
  # This instructs the search_controller if it should enable/disabled this field when the user switches polymorphic associations
22
18
  # It should not enable the field if the record is being created through an association
23
- 'data-should-be-disabled': @disabled,
24
- disabled: true %>
19
+ data: {
20
+ 'search-target': 'button clearValue',
21
+ 'should-be-disabled': @disabled,
22
+ **@field.get_html(:data, view: view, element: :input)
23
+ },
24
+ disabled: true,
25
+ placeholder: @field.placeholder,
26
+ style: @field.get_html(:style, view: view, element: :input),
27
+ type: :text,
28
+ value: field_label %>
25
29
  <% unless @disabled %>
26
- <div class="absolute top-1/2 left-auto right-3 mr-px -mt-2 cursor-pointer hidden text-gray-500"
30
+ <button class="absolute top-1/2 left-auto right-3 mr-px -mt-2 cursor-pointer hidden text-gray-500"
31
+ type="button"
27
32
  data-tippy="tooltip"
28
33
  data-search-target="clearButton"
29
34
  title="<%= I18n.translate 'avo.clear_value' %>"
30
35
  data-action="click->search#clearValue"
31
36
  ><%= helpers.svg 'x', class: 'h-4' %>
32
- </div>
37
+ </button>
33
38
  <% end %>
34
39
  </div>
35
- <%= @form.hidden_field @foreign_key, value: field_value, 'data-search-target': 'hiddenId clearValue' %>
40
+ <%= @form.hidden_field @foreign_key,
41
+ value: field_value,
42
+ data: {
43
+ 'search-target': 'hiddenId clearValue',
44
+ **@field.get_html(:data, view: view, element: :input)
45
+ }
46
+ %>
36
47
  </div>
@@ -1,14 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Fields::BelongsToField::AutocompleteComponent < ViewComponent::Base
4
- def initialize(form:, field:, model_key:, foreign_key:, disabled: false, type: nil, resource: nil, polymorphic_record: nil)
4
+ attr_reader :classes
5
+ attr_reader :view
6
+
7
+ def initialize(form:, field:, model_key:, foreign_key:, disabled: false, type: nil, resource: nil, polymorphic_record: nil, view: nil, style: nil, classes: nil)
5
8
  @form = form
6
9
  @field = field
7
10
  @type = type
11
+ @view = view
8
12
  @model_key = model_key
9
13
  @foreign_key = foreign_key
10
14
  @resource = resource
11
15
  @disabled = disabled
16
+ @style = style
17
+ @classes = classes
12
18
  @polymorphic_record = polymorphic_record
13
19
  end
14
20
 
@@ -19,10 +19,13 @@
19
19
  include_blank: @field.placeholder,
20
20
  },
21
21
  {
22
- class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
23
- disabled: disabled,
24
- 'data-belongs-to-field-target': "select",
25
- 'data-action': 'change->belongs-to-field#changeType'
22
+ class: classes("w-full"),
23
+ data: {
24
+ **@field.get_html(:data, view: view, element: :input),
25
+ action: "change->belongs-to-field#changeType #{field_html_action}",
26
+ 'belongs-to-field-target': "select",
27
+ },
28
+ disabled: disabled
26
29
  }
27
30
  %>
28
31
  <%
@@ -40,13 +43,16 @@
40
43
  <%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal, label: type.to_s.underscore.humanize do %>
41
44
  <% if @field.searchable %>
42
45
  <%= render Avo::Fields::BelongsToField::AutocompleteComponent.new form: @form,
43
- field: @field,
44
- type: type,
45
- model_key: model_keys[type.to_s],
46
- foreign_key: @field.id_input_foreign_key,
47
- resource: @resource,
48
- disabled: disabled,
49
- polymorphic_record: polymorphic_record
46
+ disabled: disabled,
47
+ field: @field,
48
+ foreign_key: @field.id_input_foreign_key,
49
+ model_key: model_keys[type.to_s],
50
+ polymorphic_record: polymorphic_record,
51
+ resource: @resource,
52
+ style: @field.get_html(:style, view: view, element: :input),
53
+ type: type,
54
+ classes: classes("w-full"),
55
+ view: @resource.view
50
56
  %>
51
57
  <% else %>
52
58
  <%= @form.select @field.id_input_foreign_key,
@@ -56,7 +62,8 @@
56
62
  include_blank: @field.placeholder,
57
63
  },
58
64
  {
59
- class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
65
+ class: classes("w-full"),
66
+ data: @field.get_html(:data, view: view, element: :input),
60
67
  disabled: disabled
61
68
  }
62
69
  %>
@@ -79,7 +86,10 @@
79
86
  model_key: @field.target_resource&.model_key,
80
87
  foreign_key: @field.id_input_foreign_key,
81
88
  resource: @resource,
82
- disabled: disabled
89
+ disabled: disabled,
90
+ classes: classes("w-full"),
91
+ view: @resource.view,
92
+ style: @field.get_html(:style, view: view, element: :input)
83
93
  %>
84
94
  <% else %>
85
95
  <%= @form.select @field.id_input_foreign_key, @field.options,
@@ -88,8 +98,10 @@
88
98
  value: @field.value
89
99
  },
90
100
  {
91
- class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
92
- disabled: disabled
101
+ class: classes("w-full"),
102
+ data: @field.get_html(:data, view: view, element: :input),
103
+ disabled: disabled,
104
+ style: @field.get_html(:style, view: view, element: :input)
93
105
  }
94
106
  %>
95
107
  <%
@@ -48,4 +48,8 @@ class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
48
48
 
49
49
  @polymorphic_record
50
50
  end
51
+
52
+ def field_html_action
53
+ @field.get_html(:data, view: @resource.view, element: :input).fetch(:action, nil)
54
+ end
51
55
  end
@@ -1,3 +1,3 @@
1
- <%= index_field_wrapper field: @field do %>
1
+ <%= index_field_wrapper field: @field, resource: @resource do %>
2
2
  <%= link_to @field.label, helpers.resource_path(model: @field.value, resource: @field.target_resource) %>
3
3
  <% end %>
@@ -1,3 +1,3 @@
1
- <%= show_field_wrapper field: @field, index: @index do %>
1
+ <%= show_field_wrapper field: @field, resource: @resource, index: @index do %>
2
2
  <%= link_to @field.label, helpers.resource_path(model: @field.value, resource: @field.target_resource, via_resource_class: @resource.model_class, via_resource_id: @resource.model.id) %>
3
3
  <% end %>
@@ -1,9 +1,11 @@
1
1
  <%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, dash_if_blank: false, displayed_in_modal: @displayed_in_modal do %>
2
2
  <div class="h-8 flex items-center">
3
3
  <%= @form.check_box @field.id,
4
- class: 'text-lg h-4 w-4',
4
+ checked: @field.value,
5
+ class: "text-lg h-4 w-4 #{@field.get_html(:classes, view: view, element: :input)}",
6
+ data: @field.get_html(:data, view: view, element: :input),
5
7
  disabled: @field.readonly,
6
- checked: @field.value
8
+ style: @field.get_html(:style, view: view, element: :input)
7
9
  %>
8
10
  </div>
9
11
  <% end %>
@@ -1,3 +1,3 @@
1
- <%= index_field_wrapper field: @field, dash_if_blank: false, center_content: true, flush: true do %>
1
+ <%= index_field_wrapper field: @field, resource: @resource, dash_if_blank: false, center_content: true, flush: true do %>
2
2
  <%= render Avo::Fields::Common::BooleanCheckComponent.new checked: @field.value %>
3
3
  <% end %>
@@ -1,3 +1,3 @@
1
- <%= show_field_wrapper field: @field, index: @index, dash_if_blank: false do %>
1
+ <%= show_field_wrapper field: @field, resource: @resource, index: @index, dash_if_blank: false do %>
2
2
  <%= render Avo::Fields::Common::BooleanCheckComponent.new checked: @field.value %>
3
3
  <% end %>
@@ -17,7 +17,13 @@
17
17
  end
18
18
  %>
19
19
  <label class="block">
20
- <%= check_box_tag "#{model_param_key}[#{@field.id}][]", id, checked, { class: "w-4 h-4", disabled: @field.readonly, id: "#{model_param_key}_#{@field.id}_#{id}" } %> <%= label %>
20
+ <%= check_box_tag "#{model_param_key}[#{@field.id}][]", id, checked, {
21
+ class: "w-4 h-4 #{@field.get_html(:classes, view: view, element: :input)}",
22
+ data: @field.get_html(:data, view: view, element: :input),
23
+ disabled: @field.readonly,
24
+ id: "#{model_param_key}_#{@field.id}_#{id}",
25
+ style: @field.get_html(:style, view: view, element: :input)
26
+ } %> <%= label %>
21
27
  </label>
22
28
  <% end %>
23
29
  </div>
@@ -1,3 +1,3 @@
1
- <%= index_field_wrapper field: @field, dash_if_blank: false do %>
1
+ <%= index_field_wrapper field: @field, resource: @resource, dash_if_blank: false do %>
2
2
  <%= render Avo::Fields::Common::BooleanGroupComponent.new options: @field.options, value: @field.value %>
3
3
  <% end %>
@@ -1,3 +1,3 @@
1
- <%= show_field_wrapper field: @field, index: @index, dash_if_blank: false do %>
1
+ <%= show_field_wrapper field: @field, resource: @resource, index: @index, dash_if_blank: false do %>
2
2
  <%= render Avo::Fields::Common::BooleanGroupComponent.new options: @field.options, value: @field.value %>
3
3
  <% end %>
@@ -1,19 +1,21 @@
1
1
  <%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal, full_width: true do %>
2
2
  <div data-controller="code-field">
3
3
  <%= @form.text_area @field.id,
4
- class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
5
- placeholder: @field.placeholder,
6
- disabled: @field.readonly,
4
+ class: classes("w-full"),
7
5
  data: {
8
6
  'code-field-target': 'element',
9
- view: :edit,
7
+ view: @resource.view,
10
8
  language: @field.language,
11
9
  theme: @field.theme,
12
10
  'tab-size': @field.tab_size,
13
11
  'read-only': @field.readonly,
14
12
  'indent-with-tabs': @field.indent_with_tabs,
15
13
  'line-wrapping': @field.line_wrapping,
16
- }
14
+ **@field.get_html(:data, view: view, element: :input),
15
+ },
16
+ disabled: @field.readonly,
17
+ placeholder: @field.placeholder,
18
+ style: @field.get_html(:style, view: view, element: :input)
17
19
  %>
18
20
  </div>
19
21
  <% end %>
@@ -1,4 +1,4 @@
1
- <%= show_field_wrapper field: @field, index: @index, full_width: true do %>
1
+ <%= show_field_wrapper field: @field, resource: @resource, index: @index, full_width: true do %>
2
2
  <div data-controller="code-field" style="--height: <%= @field.height %>">
3
3
  <%= text_area_tag @field.id, @field.value,
4
4
  class: helpers.input_classes('w-full'),
@@ -6,7 +6,7 @@
6
6
  disabled: true,
7
7
  data: {
8
8
  'code-field-target': 'element',
9
- view: :edit,
9
+ view: @resource.view,
10
10
  language: @field.language,
11
11
  theme: @field.theme,
12
12
  'tab-size': @field.tab_size,