avo 1.19.0 → 1.19.1.pre.4

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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -7
  3. data/Gemfile.lock +34 -51
  4. data/README.md +3 -0
  5. data/app/assets/builds/avo.css +8477 -0
  6. data/app/assets/builds/avo.js +87744 -0
  7. data/app/assets/builds/avo.js.map +7 -0
  8. data/app/assets/config/avo_manifest.js +2 -1
  9. data/app/{packs/images → assets/images/avo}/logo.png +0 -0
  10. data/app/{packs/entrypoints/application.css → assets/stylesheets/avo.css} +23 -24
  11. data/app/{packs/stylesheets → assets/stylesheets/css}/active-storage.css +0 -0
  12. data/app/{packs/stylesheets → assets/stylesheets/css}/alerts.css +0 -0
  13. data/app/{packs/stylesheets → assets/stylesheets/css}/breadcrumbs.css +0 -0
  14. data/app/{packs/stylesheets → assets/stylesheets/css}/components/code.css +0 -0
  15. data/app/{packs/stylesheets → assets/stylesheets/css}/components/progress.css +0 -0
  16. data/app/{packs/stylesheets → assets/stylesheets/css}/components/status.css +0 -0
  17. data/app/assets/stylesheets/css/fonts.css +26 -0
  18. data/app/{packs/stylesheets → assets/stylesheets/css}/loader.css +0 -0
  19. data/app/{packs/stylesheets → assets/stylesheets/css}/pagination.css +0 -0
  20. data/app/{packs/stylesheets → assets/stylesheets/css}/search.css +0 -0
  21. data/app/{packs/stylesheets → assets/stylesheets/css}/spinner.css +0 -0
  22. data/app/{packs/stylesheets → assets/stylesheets/css}/tailwindcss/base.css +0 -0
  23. data/app/{packs/stylesheets → assets/stylesheets/css}/tailwindcss/components.css +0 -0
  24. data/app/{packs/stylesheets → assets/stylesheets/css}/tailwindcss/utilities.css +0 -0
  25. data/app/{packs/stylesheets → assets/stylesheets/css}/tooltips.css +0 -0
  26. data/app/{packs/stylesheets → assets/stylesheets/css}/typography.css +0 -0
  27. data/app/{packs → assets}/svgs/arrow-circle-right.svg +0 -0
  28. data/app/{packs → assets}/svgs/arrow-left.svg +0 -0
  29. data/app/{packs → assets}/svgs/avocado.svg +0 -0
  30. data/app/{packs → assets}/svgs/badge-check-sm.svg +0 -0
  31. data/app/{packs → assets}/svgs/check-circle-sm.svg +0 -0
  32. data/app/{packs → assets}/svgs/check-circle.svg +0 -0
  33. data/app/{packs → assets}/svgs/chevron-down.svg +0 -0
  34. data/app/{packs → assets}/svgs/chevron-right.svg +0 -0
  35. data/app/{packs → assets}/svgs/chevron-up.svg +0 -0
  36. data/app/{packs → assets}/svgs/code.svg +0 -0
  37. data/app/{packs → assets}/svgs/color-swatch.svg +0 -0
  38. data/app/{packs → assets}/svgs/document-text.svg +0 -0
  39. data/app/{packs → assets}/svgs/download.svg +0 -0
  40. data/app/{packs → assets}/svgs/edit.svg +0 -0
  41. data/app/{packs → assets}/svgs/exclamation-circle-sm.svg +0 -0
  42. data/app/{packs → assets}/svgs/exclamation-sm.svg +0 -0
  43. data/app/{packs → assets}/svgs/exclamation.svg +0 -0
  44. data/app/{packs → assets}/svgs/eye.svg +0 -0
  45. data/app/{packs → assets}/svgs/filter.svg +0 -0
  46. data/app/{packs → assets}/svgs/fire.svg +0 -0
  47. data/app/{packs → assets}/svgs/game-board.svg +0 -0
  48. data/app/{packs → assets}/svgs/globe.svg +0 -0
  49. data/app/{packs → assets}/svgs/information-circle-sm.svg +0 -0
  50. data/app/{packs → assets}/svgs/information-circle.svg +0 -0
  51. data/app/{packs → assets}/svgs/library.svg +0 -0
  52. data/app/{packs → assets}/svgs/photograph.svg +0 -0
  53. data/app/{packs → assets}/svgs/play.svg +0 -0
  54. data/app/{packs → assets}/svgs/plus-circle.svg +0 -0
  55. data/app/{packs → assets}/svgs/plus.svg +0 -0
  56. data/app/{packs → assets}/svgs/question-mark-circle.svg +0 -0
  57. data/app/{packs → assets}/svgs/save.svg +0 -0
  58. data/app/{packs → assets}/svgs/selector.svg +0 -0
  59. data/app/{packs → assets}/svgs/sort-ascending.svg +0 -0
  60. data/app/{packs → assets}/svgs/sort-descending.svg +0 -0
  61. data/app/{packs → assets}/svgs/switch-horizontal.svg +0 -0
  62. data/app/{packs → assets}/svgs/thumbs-down.svg +0 -0
  63. data/app/{packs → assets}/svgs/thumbs-up.svg +0 -0
  64. data/app/{packs → assets}/svgs/times.svg +0 -0
  65. data/app/{packs → assets}/svgs/trash-sm.svg +0 -0
  66. data/app/{packs → assets}/svgs/trash.svg +0 -0
  67. data/app/{packs → assets}/svgs/view-grid-add.svg +0 -0
  68. data/app/{packs → assets}/svgs/view-grid.svg +0 -0
  69. data/app/{packs → assets}/svgs/view-list.svg +0 -0
  70. data/app/{packs → assets}/svgs/x-circle-sm.svg +0 -0
  71. data/app/{packs → assets}/svgs/x-circle.svg +0 -0
  72. data/app/components/avo/resource_component.rb +0 -4
  73. data/app/components/avo/views/resource_edit_component.html.erb +1 -1
  74. data/app/components/avo/views/resource_edit_component.rb +6 -0
  75. data/app/components/avo/views/resource_index_component.html.erb +1 -1
  76. data/app/components/avo/views/resource_index_component.rb +21 -9
  77. data/app/components/avo/views/resource_new_component.html.erb +6 -4
  78. data/app/components/avo/views/resource_new_component.rb +6 -0
  79. data/app/components/avo/views/resource_show_component.html.erb +2 -2
  80. data/app/components/avo/views/resource_show_component.rb +9 -1
  81. data/app/controllers/avo/application_controller.rb +15 -0
  82. data/app/controllers/avo/base_controller.rb +43 -15
  83. data/app/helpers/avo/application_helper.rb +1 -12
  84. data/app/{packs/entrypoints/application.js → javascript/avo.js} +3 -18
  85. data/{public/avo-packs/media/images/dadf2db36589607d107d.png → app/javascript/images/logo.png} +0 -0
  86. data/app/{packs → javascript}/js/active-storage.js +0 -0
  87. data/app/javascript/js/application.js +9 -0
  88. data/app/{packs → javascript}/js/controllers/action_controller.js +1 -1
  89. data/app/{packs → javascript}/js/controllers/actions_picker_controller.js +0 -0
  90. data/app/{packs → javascript}/js/controllers/alerts_controller.js +0 -0
  91. data/app/{packs → javascript}/js/controllers/attachments_controller.js +0 -0
  92. data/app/{packs → javascript}/js/controllers/boolean_filter_controller.js +0 -0
  93. data/app/{packs → javascript}/js/controllers/fields/belongs_to_field_controller.js +0 -0
  94. data/app/{packs → javascript}/js/controllers/fields/code_field_controller.js +2 -1
  95. data/app/{packs → javascript}/js/controllers/fields/date_field_controller.js +1 -1
  96. data/app/{packs → javascript}/js/controllers/fields/key_value_controller.js +1 -1
  97. data/app/{packs → javascript}/js/controllers/fields/simple_mde_controller.js +0 -0
  98. data/app/{packs → javascript}/js/controllers/fields/trix_field_controller.js +1 -1
  99. data/app/{packs → javascript}/js/controllers/filter_controller.js +0 -0
  100. data/app/{packs → javascript}/js/controllers/hidden_input_controller.js +0 -0
  101. data/app/{packs → javascript}/js/controllers/item_select_all_controller.js +0 -0
  102. data/app/{packs → javascript}/js/controllers/item_selector_controller.js +0 -0
  103. data/app/{packs → javascript}/js/controllers/loading_button_controller.js +0 -0
  104. data/app/{packs → javascript}/js/controllers/modal_controller.js +0 -0
  105. data/app/{packs → javascript}/js/controllers/multiple_select_filter_controller.js +0 -0
  106. data/app/{packs → javascript}/js/controllers/per_page_controller.js +0 -0
  107. data/app/{packs → javascript}/js/controllers/search_controller.js +1 -1
  108. data/app/{packs → javascript}/js/controllers/select_filter_controller.js +0 -0
  109. data/app/{packs → javascript}/js/controllers/text_filter_controller.js +0 -0
  110. data/app/{packs → javascript}/js/controllers/tippy_controller.js +0 -0
  111. data/app/{packs → javascript}/js/controllers/toggle_panel_controller.js +0 -0
  112. data/app/javascript/js/controllers.js +53 -0
  113. data/app/{packs → javascript}/js/helpers/cast_boolean.js +0 -0
  114. data/app/{packs → javascript}/js/helpers/debounce_promise.js +0 -0
  115. data/app/{packs → javascript}/js/toastr.js +0 -0
  116. data/app/views/avo/partials/_logo.html.erb +1 -1
  117. data/app/views/layouts/avo/application.html.erb +7 -2
  118. data/avo.gemspec +1 -2
  119. data/bin/dev +9 -0
  120. data/bin/test +2 -1
  121. data/lib/avo/base_resource.rb +4 -3
  122. data/lib/avo/engine.rb +2 -16
  123. data/lib/avo/fields/base_field.rb +7 -2
  124. data/lib/avo/fields/key_value_field.rb +4 -4
  125. data/lib/avo/version.rb +1 -1
  126. data/lib/avo.rb +0 -18
  127. data/lib/generators/avo/templates/locales/avo.en.yml +10 -3
  128. data/lib/generators/avo/templates/locales/avo.ro.yml +7 -0
  129. data/public/avo-assets/avo.css +8477 -0
  130. data/public/avo-assets/avo.js +87744 -0
  131. data/public/avo-assets/avo.js.map +7 -0
  132. data/{app/packs → public/avo-assets}/fonts/nunito-v16-latin-700.eot +0 -0
  133. data/{app/packs → public/avo-assets}/fonts/nunito-v16-latin-700.svg +0 -0
  134. data/{app/packs → public/avo-assets}/fonts/nunito-v16-latin-700.ttf +0 -0
  135. data/{app/packs → public/avo-assets}/fonts/nunito-v16-latin-700.woff +0 -0
  136. data/{app/packs → public/avo-assets}/fonts/nunito-v16-latin-700.woff2 +0 -0
  137. data/{app/packs → public/avo-assets}/fonts/nunito-v16-latin-regular.eot +0 -0
  138. data/{app/packs → public/avo-assets}/fonts/nunito-v16-latin-regular.svg +0 -0
  139. data/{app/packs → public/avo-assets}/fonts/nunito-v16-latin-regular.ttf +0 -0
  140. data/{app/packs → public/avo-assets}/fonts/nunito-v16-latin-regular.woff +0 -0
  141. data/{app/packs → public/avo-assets}/fonts/nunito-v16-latin-regular.woff2 +0 -0
  142. metadata +117 -170
  143. data/app/assets/stylesheets/avo/application.css +0 -15
  144. data/app/packs/importmap.json.erb +0 -5
  145. data/app/packs/stylesheets/fonts.css +0 -26
  146. data/bin/webpack +0 -20
  147. data/bin/webpack-dev-server +0 -18
  148. data/config/webpack/aliases.js +0 -10
  149. data/config/webpack/base.js +0 -14
  150. data/config/webpack/development.js +0 -5
  151. data/config/webpack/production.js +0 -5
  152. data/config/webpack/test.js +0 -5
  153. data/config/webpacker.yml +0 -79
  154. data/public/avo-packs/css/application-c3b50b28.css +0 -6329
  155. data/public/avo-packs/css/application-c3b50b28.css.br +0 -0
  156. data/public/avo-packs/css/application-c3b50b28.css.gz +0 -0
  157. data/public/avo-packs/css/application-c3b50b28.css.map +0 -1
  158. data/public/avo-packs/css/application-c3b50b28.css.map.br +0 -0
  159. data/public/avo-packs/css/application-c3b50b28.css.map.gz +0 -0
  160. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js +0 -2
  161. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.br +0 -0
  162. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.gz +0 -0
  163. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map +0 -1
  164. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map.br +0 -0
  165. data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map.gz +0 -0
  166. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js +0 -26
  167. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.LICENSE.txt +0 -77
  168. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.br +0 -0
  169. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.gz +0 -0
  170. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map +0 -1
  171. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map.br +0 -0
  172. data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map.gz +0 -0
  173. data/public/avo-packs/manifest.json +0 -52
  174. data/public/avo-packs/media/images/13ae283c0d7cc04efe7e.svg +0 -380
  175. data/public/avo-packs/media/images/13ae283c0d7cc04efe7e.svg.br +0 -0
  176. data/public/avo-packs/media/images/13ae283c0d7cc04efe7e.svg.gz +0 -0
  177. data/public/avo-packs/media/images/195026a50008c53526ef.svg +0 -388
  178. data/public/avo-packs/media/images/195026a50008c53526ef.svg.br +0 -0
  179. data/public/avo-packs/media/images/195026a50008c53526ef.svg.gz +0 -0
  180. data/public/avo-packs/media/images/1f30e08faa7c60d1f7ac.woff +0 -0
  181. data/public/avo-packs/media/images/1fd17dabf6b7d2b15348.ttf +0 -0
  182. data/public/avo-packs/media/images/1fd17dabf6b7d2b15348.ttf.br +0 -0
  183. data/public/avo-packs/media/images/1fd17dabf6b7d2b15348.ttf.gz +0 -0
  184. data/public/avo-packs/media/images/39a18f443d434999b89b.woff2 +0 -0
  185. data/public/avo-packs/media/images/4ad349571e28bb59c5a5.woff2 +0 -0
  186. data/public/avo-packs/media/images/57a5470848663767abbf.eot +0 -0
  187. data/public/avo-packs/media/images/b2e4cf0fab6c8ca66b7f.ttf +0 -0
  188. data/public/avo-packs/media/images/b2e4cf0fab6c8ca66b7f.ttf.br +0 -0
  189. data/public/avo-packs/media/images/b2e4cf0fab6c8ca66b7f.ttf.gz +0 -0
  190. data/public/avo-packs/media/images/b78d61ab7e046de8c156.eot +0 -0
  191. data/public/avo-packs/media/images/c9ab29becb76ddab01d0.woff +0 -0
@@ -1 +1,2 @@
1
- //= link_directory ../stylesheets/avo .css
1
+ //= link_directory ../images/avo
2
+ //= link_tree ../builds
File without changes
@@ -6,25 +6,26 @@
6
6
  @import './../../../node_modules/flatpickr/dist/flatpickr.css';
7
7
  @import './../../../node_modules/@algolia/autocomplete-theme-classic/dist/theme.css';
8
8
 
9
- @import './../stylesheets/tailwindcss/base.css';
10
-
11
- @import './../stylesheets/fonts.css';
12
- @import './../stylesheets/typography.css';
13
- @import './../stylesheets/tooltips.css';
14
- @import './../stylesheets/alerts.css';
15
- @import './../stylesheets/loader.css';
16
- @import './../stylesheets/pagination.css';
17
- @import './../stylesheets/breadcrumbs.css';
18
- @import './../stylesheets/search.css';
19
- @import './../stylesheets/active-storage.css';
20
- @import './../stylesheets/spinner.css';
21
-
22
- @import './../stylesheets/components/status.css';
23
- @import './../stylesheets/components/code.css';
24
- @import './../stylesheets/components/progress.css';
25
- @import './../stylesheets/tailwindcss/components.css';
26
-
27
- @import './../stylesheets/tailwindcss/utilities.css';
9
+ @import 'tailwindcss/base';
10
+
11
+ @import './css/fonts.css';
12
+ @import './css/typography.css';
13
+ @import './css/tooltips.css';
14
+ @import './css/alerts.css';
15
+ @import './css/loader.css';
16
+ @import './css/pagination.css';
17
+ @import './css/breadcrumbs.css';
18
+ @import './css/search.css';
19
+ @import './css/active-storage.css';
20
+ @import './css/spinner.css';
21
+
22
+ @import './css/components/status.css';
23
+ @import './css/components/code.css';
24
+ @import './css/components/progress.css';
25
+
26
+ @import 'tailwindcss/components';
27
+
28
+ @import 'tailwindcss/utilities';
28
29
 
29
30
  html,
30
31
  body {
@@ -67,11 +68,9 @@ body {
67
68
  @apply opacity-0 translate-y-1;
68
69
  }
69
70
 
70
- .application-sidebar {
71
- .active:hover,
72
- .active {
73
- @apply bg-gray-200;
74
- }
71
+ .application-sidebar .active:hover,
72
+ .application-sidebar .active {
73
+ @apply bg-gray-200;
75
74
  }
76
75
 
77
76
  .turbo-progress-bar {
@@ -0,0 +1,26 @@
1
+ /* nunito-regular - latin */
2
+ @font-face {
3
+ font-family: 'Nunito';
4
+ font-style: normal;
5
+ font-weight: 400;
6
+ src: url('/avo-assets/fonts/nunito-v16-latin-regular.eot'); /* IE9 Compat Modes */
7
+ src: local(''),
8
+ url('/avo-assets/fonts/nunito-v16-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
9
+ url('/avo-assets/fonts/nunito-v16-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
10
+ url('/avo-assets/fonts/nunito-v16-latin-regular.woff') format('woff'), /* Modern Browsers */
11
+ url('/avo-assets/fonts/nunito-v16-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
12
+ url('/avo-assets/fonts/nunito-v16-latin-regular.svg#Nunito') format('svg'); /* Legacy iOS */
13
+ }
14
+ /* nunito-700 - latin */
15
+ @font-face {
16
+ font-family: 'Nunito';
17
+ font-style: normal;
18
+ font-weight: 700;
19
+ src: url('/avo-assets/fonts/nunito-v16-latin-700.eot'); /* IE9 Compat Modes */
20
+ src: local(''),
21
+ url('/avo-assets/fonts/nunito-v16-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
22
+ url('/avo-assets/fonts/nunito-v16-latin-700.woff2') format('woff2'), /* Super Modern Browsers */
23
+ url('/avo-assets/fonts/nunito-v16-latin-700.woff') format('woff'), /* Modern Browsers */
24
+ url('/avo-assets/fonts/nunito-v16-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */
25
+ url('/avo-assets/fonts/nunito-v16-latin-700.svg#Nunito') format('svg'); /* Legacy iOS */
26
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -25,10 +25,6 @@ class Avo::ResourceComponent < ViewComponent::Base
25
25
 
26
26
  private
27
27
 
28
- def simple_relation?
29
- @reflection.is_a? ::ActiveRecord::Reflection::HasManyReflection
30
- end
31
-
32
28
  def relation_resource
33
29
  ::Avo::App.get_resource_by_model_name params[:via_resource_class].safe_constantize
34
30
  end
@@ -10,7 +10,7 @@
10
10
  <%= helpers.svg 'arrow-left' %> <%= t('avo.cancel').capitalize %>
11
11
  <% end %>
12
12
 
13
- <% if @resource.authorization.authorize_action :update, raise_exception: false %>
13
+ <% if can_see_the_save_button? %>
14
14
  <%= a_button color: 'green', variant: 'outlined', spinner: true, type: :submit do %>
15
15
  <%= helpers.svg 'save' %> <%= t('avo.save').capitalize %>
16
16
  <% end %>
@@ -16,6 +16,12 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
16
16
  end
17
17
  end
18
18
 
19
+ # The save button is dependent on the edit? policy method.
20
+ # The update? method should be called only when the user clicks the Save button so the developer gets access to the params from the form.
21
+ def can_see_the_save_button?
22
+ @resource.authorization.authorize_action :edit, raise_exception: false
23
+ end
24
+
19
25
  private
20
26
 
21
27
  def via_resource?
@@ -3,7 +3,7 @@
3
3
  <% c.tools do %>
4
4
  <%= render 'actions' if @actions.present? %>
5
5
 
6
- <% if can_create? %>
6
+ <% if can_see_the_create_button? %>
7
7
  <%= a_link create_path do %>
8
8
  <%= svg 'plus' %> <%= t('avo.create_new_item', item: singular_resource_name.downcase ) %>
9
9
  <% end %>
@@ -44,8 +44,10 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
44
44
  @index_params[:available_view_types]
45
45
  end
46
46
 
47
- def can_create?
48
- @resource.authorization.authorize_action(:create, raise_exception: false) && simple_relation? && !has_reflection_and_is_read_only
47
+ # The Create button is dependent on the new? policy method.
48
+ # The create? should be called only when the user clicks the Save button so the developers gets access to the params from the form.
49
+ def can_see_the_create_button?
50
+ @resource.authorization.authorize_action(:new, raise_exception: false) && !has_reflection_and_is_read_only
49
51
  end
50
52
 
51
53
  def can_attach?
@@ -58,7 +60,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
58
60
  def has_reflection_and_is_read_only
59
61
  if @reflection.present? && @reflection.active_record.name && @reflection.name
60
62
  fields = ::Avo::App.get_resource_by_model_name(@reflection.active_record.name).get_field_definitions
61
- filtered_fields = fields.filter{ |f| f.id == @reflection.name}
63
+ filtered_fields = fields.filter { |f| f.id == @reflection.name }
62
64
  else
63
65
  return false
64
66
  end
@@ -75,10 +77,22 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
75
77
 
76
78
  if @reflection.present?
77
79
  args = {
78
- via_relation_class: @parent_model.model_name,
79
- via_resource_id: @parent_model.id
80
+ via_relation_class: reflection_model_class,
81
+ via_resource_id: @parent_model.id,
80
82
  }
81
83
 
84
+ if @reflection.is_a? ActiveRecord::Reflection::ThroughReflection
85
+ args[:via_relation] = params[:resource_name]
86
+ end
87
+
88
+ if @reflection.is_a? ActiveRecord::Reflection::HasManyReflection
89
+ args[:via_relation] = @reflection.name
90
+ end
91
+
92
+ if @reflection.parent_reflection.present? && @reflection.parent_reflection.inverse_of.present?
93
+ args[:via_relation] = @reflection.parent_reflection.inverse_of.name
94
+ end
95
+
82
96
  if @reflection.inverse_of.present?
83
97
  args[:via_relation] = @reflection.inverse_of.name
84
98
  end
@@ -101,9 +115,7 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
101
115
 
102
116
  private
103
117
 
104
- def simple_relation?
105
- return @reflection.is_a? ::ActiveRecord::Reflection::HasManyReflection if @reflection.present?
106
-
107
- true
118
+ def reflection_model_class
119
+ @reflection.active_record.to_s
108
120
  end
109
121
  end
@@ -1,6 +1,6 @@
1
1
  <div>
2
2
  <% @resource.panels.each do |resource_panel| %>
3
- <%= form_with model: @resource.model, url: helpers.resources_path(resource: @resource, via_relation_class: params[:via_relation_class], via_resource_id: params[:via_resource_id]), local: true, multipart: true do |form| %>
3
+ <%= form_with model: @resource.model, url: helpers.resources_path(resource: @resource, via_relation_class: params[:via_relation_class], via_relation: params[:via_relation], via_resource_id: params[:via_resource_id]), local: true, multipart: true do |form| %>
4
4
  <%= render Avo::PanelComponent.new(title: resource_panel[:name], display_breadcrumbs: true) do |c| %>
5
5
  <% c.tools do %>
6
6
  <div class="flex justify-end space-x-2">
@@ -8,9 +8,11 @@
8
8
  <%= svg 'arrow-left' %> <%= t('avo.cancel').capitalize %>
9
9
  <% end %>
10
10
 
11
- <%= a_button color: 'green', spinner: true, type: :submit do %>
12
- <%= svg 'save' %> <%= t('avo.save').capitalize %>
13
- <% end if @resource.authorization.authorize_action :create, raise_exception: false %>
11
+ <% if can_see_the_save_button? %>
12
+ <%= a_button color: 'green', spinner: true, type: :submit do %>
13
+ <%= svg 'save' %> <%= t('avo.save').capitalize %>
14
+ <% end %>
15
+ <% end %>
14
16
  </div>
15
17
  <% end %>
16
18
 
@@ -20,6 +20,12 @@ class Avo::Views::ResourceNewComponent < ViewComponent::Base
20
20
  end
21
21
  end
22
22
 
23
+ # The create button is dependent on the new? policy method.
24
+ # The create? should be called only when the user clicks the Save button so the developers gets access to the params from the form.
25
+ def can_see_the_save_button?
26
+ @resource.authorization.authorize_action :new, raise_exception: false
27
+ end
28
+
23
29
  private
24
30
 
25
31
  def via_resource?
@@ -14,7 +14,7 @@
14
14
  <%= svg 'trash' %> <%= t('avo.detach_item', item: @reflection.name.to_s).capitalize %>
15
15
  <% end %>
16
16
  <% end %>
17
- <% if @resource.authorization.authorize_action(:edit, raise_exception: false) %>
17
+ <% if can_see_the_edit_button? %>
18
18
  <%= a_link edit_path, color: 'indigo' do %>
19
19
  <%= svg 'edit' %> <%= t('avo.edit').capitalize %>
20
20
  <% end %>
@@ -24,7 +24,7 @@
24
24
  <%= svg 'arrow-left' %> <%= t('avo.go_back') %>
25
25
  <% end %>
26
26
 
27
- <% if @resource.authorization.authorize_action(:destroy, raise_exception: false) %>
27
+ <% if can_see_the_destroy_button? %>
28
28
  <%= form_with url: helpers.resource_path(model: @resource.model, resource: @resource), method: :delete, html: { 'data-turbo-frame': params[:turbo_frame] } do |form| %>
29
29
  <%= a_button title: t('avo.delete_item', item: @resource.model.model_name.name.downcase).capitalize,
30
30
  spinner: true,
@@ -43,7 +43,15 @@ class Avo::Views::ResourceShowComponent < Avo::ResourceComponent
43
43
  end
44
44
 
45
45
  def can_detach?
46
- authorize_association_for('detach')
46
+ authorize_association_for("detach")
47
+ end
48
+
49
+ def can_see_the_edit_button?
50
+ @resource.authorization.authorize_action(:edit, raise_exception: false)
51
+ end
52
+
53
+ def can_see_the_destroy_button?
54
+ @resource.authorization.authorize_action(:destroy, raise_exception: false)
47
55
  end
48
56
 
49
57
  private
@@ -12,6 +12,8 @@ module Avo
12
12
  before_action :_authenticate!
13
13
  before_action :set_container_classes
14
14
  before_action :add_initial_breadcrumbs
15
+ before_action :set_view
16
+ before_action :set_model_to_fill
15
17
 
16
18
  rescue_from Pundit::NotAuthorizedError, with: :render_unauthorized
17
19
  rescue_from ActiveRecord::RecordInvalid, with: :exception_logger
@@ -99,6 +101,19 @@ module Avo
99
101
  @related_model = eager_load_files(@related_resource, @related_resource.class.find_scope).find params[:related_id]
100
102
  end
101
103
 
104
+ def set_view
105
+ @view = action_name.to_sym
106
+ end
107
+
108
+ def set_model_to_fill
109
+ @model_to_fill = @resource.model_class.new if @view == :create
110
+ @model_to_fill = @model if @view == :update
111
+ end
112
+
113
+ def fill_model
114
+ @model = @resource.fill_model(@model_to_fill, cast_nullable(model_params))
115
+ end
116
+
102
117
  def hydrate_resource
103
118
  @resource.hydrate(view: action_name.to_sym, user: _current_user)
104
119
  end
@@ -5,13 +5,13 @@ module Avo
5
5
  before_action :set_resource_name
6
6
  before_action :set_resource
7
7
  before_action :hydrate_resource
8
- before_action :authorize_action
9
8
  before_action :set_model, only: [:show, :edit, :destroy, :update]
9
+ before_action :set_model_to_fill
10
+ before_action :authorize_action
10
11
  before_action :reset_pagination_if_filters_changed, only: :index
11
12
  before_action :cache_applied_filters, only: :index
12
13
 
13
14
  def index
14
- @view = :index
15
15
  @page_title = resource_name.humanize
16
16
  add_breadcrumb resource_name.humanize
17
17
 
@@ -24,8 +24,8 @@ module Avo
24
24
  @query = @resource.class.query_scope
25
25
  end
26
26
 
27
- # Remove default_scope for index view
28
- if @resource.unscoped_queries_on_index
27
+ # Remove default_scope for index view if no parent_resource present
28
+ if @resource.unscoped_queries_on_index && @parent_resource.blank?
29
29
  @query = @query.unscoped
30
30
  end
31
31
 
@@ -59,7 +59,6 @@ module Avo
59
59
  end
60
60
 
61
61
  def show
62
- @view = :show
63
62
  set_actions
64
63
 
65
64
  @resource = @resource.hydrate(model: @model, view: :show, user: _current_user, params: params)
@@ -82,7 +81,6 @@ module Avo
82
81
  end
83
82
 
84
83
  def new
85
- @view = :new
86
84
  @model = @resource.model_class.new
87
85
  @resource = @resource.hydrate(model: @model, view: :new, user: _current_user)
88
86
 
@@ -92,7 +90,6 @@ module Avo
92
90
  end
93
91
 
94
92
  def edit
95
- @view = :edit
96
93
  @resource = @resource.hydrate(model: @model, view: :edit, user: _current_user)
97
94
 
98
95
  @page_title = @resource.default_panel_name
@@ -114,20 +111,50 @@ module Avo
114
111
  end
115
112
 
116
113
  def create
117
- @model = @resource.fill_model(@resource.model_class.new, cast_nullable(model_params))
114
+ # model gets instantiated and filled in the fill_model method
115
+ fill_model
118
116
  saved = @model.save
119
117
  @resource.hydrate(model: @model, view: :new, user: _current_user)
120
118
 
119
+ # This means that the record has been created through another parent record and we need to attach it somehow.
120
+ if params[:via_resource_id].present?
121
+ @reflection = @model._reflections[params[:via_relation]]
122
+ # Figure out what kind of association does the record have with the parent record
123
+
124
+ # belongs_to
125
+ # has_many
126
+ # Get the foreign key and set it to the id we received in the params
127
+ if @reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection) || @reflection.is_a?(ActiveRecord::Reflection::HasManyReflection)
128
+ foreign_key = @reflection.foreign_key
129
+ @model.send("#{foreign_key}=", params[:via_resource_id])
130
+ @model.save
131
+ end
132
+
133
+ # has_one
134
+ # has_one_through
135
+
136
+ # has_many_through
137
+ # has_and_belongs_to_many
138
+ # polymorphic
139
+ if @reflection.is_a? ActiveRecord::Reflection::ThroughReflection
140
+ # find the record
141
+ via_resource = ::Avo::App.get_resource_by_model_name params[:via_relation_class]
142
+ @related_record = via_resource.model_class.find params[:via_resource_id]
143
+
144
+ @model.send(params[:via_relation]) << @related_record
145
+ end
146
+ end
147
+
121
148
  respond_to do |format|
122
149
  if saved
123
- redirect_path = if params[:via_relation_class].present? && params[:via_resource_id].present?
150
+ redirect_path = resource_path(model: @model, resource: @resource)
151
+
152
+ if params[:via_relation_class].present? && params[:via_resource_id].present?
124
153
  parent_resource = ::Avo::App.get_resource_by_model_name params[:via_relation_class].safe_constantize
125
- resource_path(model: params[:via_relation_class].safe_constantize, resource: parent_resource, resource_id: params[:via_resource_id])
126
- else
127
- resource_path(model: @model, resource: @resource)
154
+ redirect_path = resource_path(model: params[:via_relation_class].safe_constantize, resource: parent_resource, resource_id: params[:via_resource_id])
128
155
  end
129
156
 
130
- format.html { redirect_to redirect_path, notice: "#{@model.class.name} was successfully created." }
157
+ format.html { redirect_to redirect_path, notice: "#{@model.class.name} #{t("avo.was_successfully_created")}." }
131
158
  format.json { render :show, status: :created, location: @model }
132
159
  else
133
160
  flash[:error] = t "avo.you_missed_something_check_form"
@@ -138,13 +165,14 @@ module Avo
138
165
  end
139
166
 
140
167
  def update
141
- @model = @resource.fill_model(@model, cast_nullable(model_params))
168
+ # model gets instantiated and filled in the fill_model method
169
+ fill_model
142
170
  saved = @model.save
143
171
  @resource = @resource.hydrate(model: @model, view: :edit, user: _current_user)
144
172
 
145
173
  respond_to do |format|
146
174
  if saved
147
- format.html { redirect_to params[:referrer] || resource_path(model: @model, resource: @resource), notice: "#{@model.class.name} was successfully updated." }
175
+ format.html { redirect_to params[:referrer] || resource_path(model: @model, resource: @resource), notice: "#{@model.class.name} #{t("avo.was_successfully_updated")}." }
148
176
  format.json { render :show, status: :ok, location: @model }
149
177
  else
150
178
  flash[:error] = t "avo.you_missed_something_check_form"
@@ -1,18 +1,7 @@
1
1
  module Avo
2
2
  module ApplicationHelper
3
- include ::Manifester::Helper
4
3
  include ::Pagy::Frontend
5
4
 
6
- def current_webpacker_instance
7
- return Avo.webpacker if Avo::IN_DEVELOPMENT
8
-
9
- super
10
- end
11
-
12
- def current_manifester_instance
13
- Avo.manifester
14
- end
15
-
16
5
  def render_license_warnings
17
6
  render partial: "avo/sidebar/license_warnings", locals: {
18
7
  license: Avo::App.license.properties
@@ -116,7 +105,7 @@ module Avo
116
105
  options[:class] += args[:extra_class].present? ? " #{args[:extra_class]}" : ""
117
106
 
118
107
  # Create the path to the svgs directory
119
- file_path = "#{Avo::Engine.root}/app/packs/svgs/#{file_name}"
108
+ file_path = "#{Avo::Engine.root}/app/assets/svgs/#{file_name}"
120
109
  file_path = "#{file_path}.svg" unless file_path.end_with? ".svg"
121
110
 
122
111
  # Create a cache hash