avo 3.0.0.beta1 → 3.0.0.pre1

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 (215) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -5
  3. data/Gemfile.lock +81 -92
  4. data/{public/avo-assets/avo.css → app/assets/builds/avo.base.css} +686 -728
  5. data/app/assets/builds/avo.base.js +93804 -0
  6. data/app/assets/builds/avo.base.js.map +7 -0
  7. data/app/assets/stylesheets/avo.base.css +2 -1
  8. data/app/assets/svgs/failed_to_load.svg +1 -0
  9. data/app/assets/svgs/grid-empty-state.svg +1 -0
  10. data/app/assets/svgs/table-empty-state.svg +1 -0
  11. data/app/assets/svgs/triangle-up.svg +1 -1
  12. data/app/components/avo/actions_component.html.erb +1 -1
  13. data/app/components/avo/actions_component.rb +16 -42
  14. data/app/components/avo/alert_component.html.erb +1 -1
  15. data/app/components/avo/base_component.rb +7 -7
  16. data/app/components/avo/field_wrapper_component.html.erb +4 -4
  17. data/app/components/avo/field_wrapper_component.rb +1 -1
  18. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +5 -5
  19. data/app/components/avo/fields/belongs_to_field/edit_component.rb +4 -8
  20. data/app/components/avo/fields/boolean_field/edit_component.html.erb +0 -1
  21. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
  22. data/app/components/avo/fields/code_field/edit_component.html.erb +0 -1
  23. data/app/components/avo/fields/common/files_list_viewer_component.html.erb +5 -0
  24. data/app/components/avo/fields/common/files_list_viewer_component.rb +8 -0
  25. data/app/components/avo/fields/common/heading_component.html.erb +1 -1
  26. data/app/components/avo/fields/common/single_file_viewer_component.html.erb +56 -0
  27. data/app/components/avo/fields/common/single_file_viewer_component.rb +55 -0
  28. data/app/components/avo/fields/country_field/edit_component.html.erb +1 -3
  29. data/app/components/avo/fields/file_field/edit_component.html.erb +2 -4
  30. data/app/components/avo/fields/file_field/edit_component.rb +0 -1
  31. data/app/components/avo/fields/file_field/index_component.rb +2 -2
  32. data/app/components/avo/fields/file_field/show_component.html.erb +1 -1
  33. data/app/components/avo/fields/files_field/edit_component.html.erb +2 -4
  34. data/app/components/avo/fields/files_field/edit_component.rb +0 -1
  35. data/app/components/avo/fields/files_field/show_component.html.erb +1 -1
  36. data/app/components/avo/fields/has_many_field/show_component.html.erb +1 -1
  37. data/app/components/avo/fields/has_one_field/show_component.html.erb +4 -5
  38. data/app/components/avo/fields/has_one_field/show_component.rb +2 -6
  39. data/app/components/avo/fields/index_component.rb +0 -1
  40. data/app/components/avo/fields/markdown_field/edit_component.html.erb +3 -4
  41. data/app/components/avo/fields/markdown_field/show_component.html.erb +3 -3
  42. data/app/components/avo/fields/number_field/edit_component.html.erb +1 -3
  43. data/app/components/avo/fields/password_field/edit_component.html.erb +1 -3
  44. data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +0 -1
  45. data/app/components/avo/fields/select_field/edit_component.html.erb +1 -2
  46. data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
  47. data/app/components/avo/fields/text_field/edit_component.html.erb +2 -3
  48. data/app/components/avo/fields/textarea_field/edit_component.html.erb +0 -1
  49. data/app/components/avo/fields/trix_field/edit_component.html.erb +1 -2
  50. data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
  51. data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
  52. data/app/components/avo/index/field_wrapper_component.rb +12 -0
  53. data/app/components/avo/index/grid_item_component.html.erb +35 -9
  54. data/app/components/avo/index/grid_item_component.rb +10 -36
  55. data/app/components/avo/index/resource_controls_component.rb +11 -8
  56. data/app/components/avo/index/resource_table_component.rb +1 -1
  57. data/app/components/avo/item_switcher_component.html.erb +5 -10
  58. data/app/components/avo/item_switcher_component.rb +1 -2
  59. data/app/components/avo/modal_component.html.erb +1 -1
  60. data/app/components/avo/panel_component.html.erb +1 -6
  61. data/app/components/avo/panel_component.rb +0 -1
  62. data/app/components/avo/profile_item_component.html.erb +2 -17
  63. data/app/components/avo/profile_item_component.rb +1 -13
  64. data/app/components/avo/referrer_params_component.html.erb +0 -2
  65. data/app/components/avo/resource_component.rb +6 -69
  66. data/app/components/avo/resource_sidebar_component.rb +1 -1
  67. data/app/components/avo/sidebar/link_component.html.erb +0 -2
  68. data/app/components/avo/sidebar/link_component.rb +3 -5
  69. data/app/components/avo/sidebar_component.html.erb +3 -3
  70. data/app/components/avo/sidebar_component.rb +4 -4
  71. data/app/components/avo/sidebar_profile_component.html.erb +27 -27
  72. data/app/components/avo/views/resource_edit_component.html.erb +5 -5
  73. data/app/components/avo/views/resource_edit_component.rb +1 -1
  74. data/app/components/avo/views/resource_index_component.html.erb +10 -19
  75. data/app/components/avo/views/resource_index_component.rb +16 -22
  76. data/app/components/avo/views/resource_show_component.html.erb +4 -4
  77. data/app/controllers/avo/actions_controller.rb +20 -20
  78. data/app/controllers/avo/application_controller.rb +67 -90
  79. data/app/controllers/avo/associations_controller.rb +7 -5
  80. data/app/controllers/avo/attachments_controller.rb +7 -22
  81. data/app/controllers/avo/base_controller.rb +35 -47
  82. data/app/controllers/avo/home_controller.rb +1 -1
  83. data/app/controllers/avo/search_controller.rb +16 -20
  84. data/app/controllers/concerns/avo/initializes_avo.rb +8 -3
  85. data/app/helpers/avo/application_helper.rb +6 -13
  86. data/app/javascript/js/application.js +0 -2
  87. data/app/javascript/js/controllers/fields/{easy_mde_controller.js → simple_mde_controller.js} +3 -4
  88. data/app/javascript/js/controllers/search_controller.js +1 -3
  89. data/app/javascript/js/controllers.js +2 -2
  90. data/app/views/avo/actions/show.html.erb +3 -5
  91. data/app/views/avo/associations/new.html.erb +3 -3
  92. data/app/views/avo/debug/status.html.erb +5 -6
  93. data/app/views/avo/home/index.html.erb +1 -1
  94. data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
  95. data/app/views/avo/partials/_footer.html.erb +1 -1
  96. data/app/views/avo/partials/_javascript.html.erb +1 -1
  97. data/app/views/avo/partials/_navbar.html.erb +1 -1
  98. data/app/views/avo/partials/_table_header.html.erb +8 -0
  99. data/app/views/avo/partials/_view_toggle_button.html.erb +0 -9
  100. data/app/views/avo/private/design.html.erb +2 -2
  101. data/app/views/layouts/avo/application.html.erb +3 -2
  102. data/avo.gemspec +1 -2
  103. data/config/initializers/pagy.rb +10 -12
  104. data/config/routes.rb +5 -5
  105. data/db/factories.rb +0 -17
  106. data/lib/avo/app.rb +165 -0
  107. data/lib/avo/base_action.rb +18 -31
  108. data/lib/avo/base_resource.rb +213 -238
  109. data/lib/avo/concerns/breadcrumbs.rb +2 -2
  110. data/lib/avo/concerns/can_replace_items.rb +7 -3
  111. data/lib/avo/concerns/filters_session_handler.rb +4 -5
  112. data/lib/avo/concerns/has_item_type.rb +0 -4
  113. data/lib/avo/concerns/has_items.rb +115 -93
  114. data/lib/avo/concerns/is_visible.rb +1 -1
  115. data/lib/avo/concerns/model_class_constantized.rb +2 -0
  116. data/lib/avo/configuration.rb +8 -9
  117. data/lib/avo/current.rb +1 -35
  118. data/lib/avo/dsl/field_parser.rb +1 -1
  119. data/lib/avo/dynamic_router.rb +2 -13
  120. data/lib/avo/engine.rb +13 -11
  121. data/lib/avo/execution_context.rb +2 -4
  122. data/lib/avo/fields/base_field.rb +14 -51
  123. data/lib/avo/fields/belongs_to_field.rb +13 -20
  124. data/lib/avo/fields/concerns/is_searchable.rb +1 -1
  125. data/lib/avo/fields/concerns/use_resource.rb +1 -1
  126. data/lib/avo/fields/date_field.rb +3 -16
  127. data/lib/avo/fields/field_manager.rb +3 -13
  128. data/lib/avo/fields/file_field.rb +0 -2
  129. data/lib/avo/fields/files_field.rb +0 -6
  130. data/lib/avo/fields/has_base_field.rb +5 -5
  131. data/lib/avo/fields/has_one_field.rb +1 -2
  132. data/lib/avo/fields/id_field.rb +1 -2
  133. data/lib/avo/filters/base_filter.rb +0 -9
  134. data/lib/avo/grid_collector.rb +40 -0
  135. data/lib/avo/html/builder.rb +1 -3
  136. data/lib/avo/licensing/h_q.rb +6 -11
  137. data/lib/avo/licensing/license.rb +1 -1
  138. data/lib/avo/licensing/license_manager.rb +1 -1
  139. data/lib/avo/licensing/{nil_license.rb → null_license.rb} +1 -1
  140. data/lib/avo/loaders/fields_loader.rb +1 -7
  141. data/lib/avo/plugin.rb +0 -10
  142. data/lib/avo/plugin_manager.rb +4 -2
  143. data/lib/avo/reloader.rb +1 -1
  144. data/lib/avo/resources/controls/actions_list.rb +1 -2
  145. data/lib/avo/resources/controls/create_button.rb +1 -1
  146. data/lib/avo/resources/controls/delete_button.rb +1 -1
  147. data/lib/avo/resources/controls/detach_button.rb +1 -1
  148. data/lib/avo/resources/controls/edit_button.rb +1 -1
  149. data/lib/avo/resources/controls/show_button.rb +1 -1
  150. data/lib/avo/resources/items/holder.rb +5 -13
  151. data/lib/avo/resources/items/item_group.rb +0 -1
  152. data/lib/avo/resources/resource_manager.rb +18 -11
  153. data/lib/avo/services/debug_service.rb +5 -6
  154. data/lib/avo/services/telemetry_service.rb +2 -3
  155. data/lib/avo/version.rb +1 -1
  156. data/lib/avo.rb +25 -109
  157. data/lib/generators/avo/action_generator.rb +8 -8
  158. data/lib/generators/avo/card/chartkick_generator.rb +18 -0
  159. data/lib/generators/avo/card/metric_generator.rb +18 -0
  160. data/lib/generators/avo/card/partial_generator.rb +19 -0
  161. data/lib/generators/avo/eject_generator.rb +0 -1
  162. data/lib/generators/avo/filter_generator.rb +8 -8
  163. data/lib/generators/avo/install_generator.rb +1 -11
  164. data/lib/generators/avo/resource_generator.rb +4 -22
  165. data/lib/generators/avo/tailwindcss/install_generator.rb +1 -4
  166. data/lib/generators/avo/templates/action.tt +5 -7
  167. data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
  168. data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
  169. data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
  170. data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
  171. data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
  172. data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
  173. data/lib/generators/avo/templates/dashboards/dashboard.tt +3 -5
  174. data/lib/generators/avo/templates/initializer/avo.tt +2 -4
  175. data/lib/generators/avo/templates/resource/resource.tt +6 -6
  176. data/lib/generators/avo/templates/scope.tt +1 -1
  177. data/lib/generators/avo/templates/standalone_action.tt +8 -0
  178. data/lib/generators/avo/templates/tailwindcss/Procfile.dev +1 -1
  179. data/lib/tasks/avo_tasks.rake +0 -5
  180. metadata +19 -56
  181. data/app/assets/svgs/map-empty-state.svg +0 -35
  182. data/app/assets/svgs/map-view-type.svg +0 -3
  183. data/app/components/avo/fields/area_field/edit_component.html.erb +0 -7
  184. data/app/components/avo/fields/area_field/edit_component.rb +0 -4
  185. data/app/components/avo/fields/area_field/show_component.html.erb +0 -8
  186. data/app/components/avo/fields/area_field/show_component.rb +0 -4
  187. data/app/components/avo/fields/common/files/controls_component.html.erb +0 -29
  188. data/app/components/avo/fields/common/files/controls_component.rb +0 -19
  189. data/app/components/avo/fields/common/files/list_viewer_component.html.erb +0 -20
  190. data/app/components/avo/fields/common/files/list_viewer_component.rb +0 -41
  191. data/app/components/avo/fields/common/files/view_type/grid_component.html.erb +0 -27
  192. data/app/components/avo/fields/common/files/view_type/grid_component.rb +0 -51
  193. data/app/components/avo/fields/common/files/view_type/list_component.html.erb +0 -22
  194. data/app/components/avo/fields/common/files/view_type/list_component.rb +0 -15
  195. data/app/components/avo/fields/location_field/edit_component.html.erb +0 -22
  196. data/app/components/avo/fields/location_field/edit_component.rb +0 -4
  197. data/app/components/avo/fields/location_field/show_component.html.erb +0 -7
  198. data/app/components/avo/fields/location_field/show_component.rb +0 -4
  199. data/app/components/avo/index/resource_map_component.html.erb +0 -16
  200. data/app/components/avo/index/resource_map_component.rb +0 -109
  201. data/app/components/avo/row_component.html.erb +0 -3
  202. data/app/components/avo/row_component.rb +0 -12
  203. data/app/views/avo/attachments/destroy.turbo_stream.erb +0 -7
  204. data/app/views/avo/partials/_profile_menu_extra.html.erb +0 -2
  205. data/lib/avo/concerns/has_description.rb +0 -23
  206. data/lib/avo/fields/area_field.rb +0 -39
  207. data/lib/avo/fields/concerns/file_authorization.rb +0 -31
  208. data/lib/avo/fields/location_field.rb +0 -86
  209. data/lib/avo/resources/items/row.rb +0 -54
  210. data/lib/generators/avo/card_generator.rb +0 -27
  211. data/public/avo-assets/avo.base.css +0 -10542
  212. data/public/avo-assets/avo.base.js +0 -949
  213. data/public/avo-assets/avo.base.js.map +0 -7
  214. data/public/avo-assets/avo.js +0 -513
  215. data/public/avo-assets/avo.js.map +0 -7
@@ -97,23 +97,16 @@ module Avo
97
97
  end
98
98
 
99
99
  def root_path_without_url
100
- "#{Avo.configuration.prefix_path}#{mount_path}"
100
+ Avo::App.root_path
101
+ .to_s
102
+ .delete_prefix(request.base_url.to_s)
103
+ .delete_suffix("/")
104
+ .gsub("/?", "?")
105
+ .query = ""
101
106
  rescue
102
107
  Avo.configuration.root_path
103
108
  end
104
109
 
105
- def mount_path
106
- Avo::Engine.routes.find_script_name(params.permit!.to_h.symbolize_keys)
107
- end
108
-
109
- def decode_filter_params(encoded_params)
110
- Avo::Filters::BaseFilter.decode_filters(encoded_params)
111
- end
112
-
113
- def encode_filter_params(filter_params)
114
- Avo::Filters::BaseFilter.encode_filters(filter_params)
115
- end
116
-
117
110
  def number_to_social(number, start_at: 10_000)
118
111
  return number_with_delimiter(number) if number < start_at
119
112
 
@@ -1,5 +1,3 @@
1
- import 'mapkick/bundle'
2
-
3
1
  import { Alert, Popover } from 'tailwindcss-stimulus-components'
4
2
  import { Application } from '@hotwired/stimulus'
5
3
 
@@ -1,5 +1,5 @@
1
1
  import { Controller } from '@hotwired/stimulus'
2
- import EasyMDE from 'easymde'
2
+ import SimpleMDE from 'simplemde'
3
3
 
4
4
  export default class extends Controller {
5
5
  static targets = ['element']
@@ -20,7 +20,6 @@ export default class extends Controller {
20
20
  const options = {
21
21
  element: this.elementTarget,
22
22
  spellChecker: this.componentOptions.spell_checker,
23
- autoRefresh: { delay: 500},
24
23
  }
25
24
 
26
25
  if (this.view === 'show') {
@@ -28,9 +27,9 @@ export default class extends Controller {
28
27
  options.status = false
29
28
  }
30
29
 
31
- const easyMde = new EasyMDE(options)
30
+ const simpleMde = new SimpleMDE(options)
32
31
  if (this.view === 'show') {
33
- easyMde.codemirror.options.readOnly = true
32
+ simpleMde.codemirror.options.readOnly = true
34
33
  }
35
34
  }
36
35
  }
@@ -211,9 +211,7 @@ export default class extends Controller {
211
211
  searchUrl(query) {
212
212
  const url = URI()
213
213
 
214
- return url.segment([window.Avo.configuration.root_path, ...this.searchSegments()])
215
- .search(this.searchParams(encodeURIComponent(query)))
216
- .readable().toString()
214
+ return url.segment([window.Avo.configuration.root_path, ...this.searchSegments()]).search(this.searchParams(query)).readable().toString()
217
215
  }
218
216
 
219
217
  searchSegments() {
@@ -10,7 +10,6 @@ import CodeFieldController from './controllers/fields/code_field_controller'
10
10
  import CopyToClipboardController from './controllers/copy_to_clipboard_controller'
11
11
  import DashboardCardController from './controllers/dashboard_card_controller'
12
12
  import DateFieldController from './controllers/fields/date_field_controller'
13
- import EasyMdeController from './controllers/fields/easy_mde_controller'
14
13
  import FilterController from './controllers/filter_controller'
15
14
  import HiddenInputController from './controllers/hidden_input_controller'
16
15
  import InputAutofocusController from './controllers/input_autofocus_controller'
@@ -32,6 +31,7 @@ import SelectController from './controllers/select_controller'
32
31
  import SelectFilterController from './controllers/select_filter_controller'
33
32
  import SelfDestroyController from './controllers/self_destroy_controller'
34
33
  import SidebarController from './controllers/sidebar_controller'
34
+ import SimpleMdeController from './controllers/fields/simple_mde_controller'
35
35
  import TabsController from './controllers/tabs_controller'
36
36
  import TextFilterController from './controllers/text_filter_controller'
37
37
  import TippyController from './controllers/tippy_controller'
@@ -73,9 +73,9 @@ application.register('toggle', ToggleController)
73
73
  application.register('belongs-to-field', BelongsToFieldController)
74
74
  application.register('code-field', CodeFieldController)
75
75
  application.register('date-field', DateFieldController)
76
- application.register('easy-mde', EasyMdeController)
77
76
  application.register('key-value', KeyValueController)
78
77
  application.register('progress-bar-field', ProgressBarFieldController)
78
+ application.register('simple-mde', SimpleMdeController)
79
79
  application.register('trix-field', TrixFieldController)
80
80
 
81
81
  // Custom controllers
@@ -9,21 +9,19 @@
9
9
  >
10
10
  <%= form_with model: @record,
11
11
  scope: 'fields',
12
- url: Avo::Services::URIService.parse(@resource.records_path).append_paths("actions").to_s,
12
+ url: "#{@resource.records_path}/actions/#{@action.param_id}",
13
13
  local: true,
14
14
  data: @action.class.form_data_attributes do |form|
15
15
  %>
16
16
  <%= render Avo::ModalComponent.new do |c| %>
17
- <% c.with_heading do %>
17
+ <% c.heading do %>
18
18
  <%= @action.action_name %>
19
19
  <% end %>
20
20
  <div class="flex-1 flex">
21
21
  <%= @action.get_message %>
22
22
  </div>
23
- <%= hidden_field_tag :action_id, @action.param_id %>
24
23
  <%= form.hidden_field :avo_resource_ids, value: params[:id] || params[:resource_ids], 'data-action-target': 'resourceIds' %>
25
24
  <%= form.hidden_field :avo_selected_query, 'data-action-target': 'selectedAllQuery' %>
26
- <%= form.hidden_field :arguments, value: params[:arguments] %>
27
25
  <% if @action.get_fields.present? %>
28
26
  <div class="my-4 -mx-6">
29
27
  <% @action.get_fields.each_with_index do |field, index| %>
@@ -35,7 +33,7 @@
35
33
  <% end %>
36
34
  </div>
37
35
  <% end %>
38
- <% c.with_controls do %>
36
+ <% c.controls do %>
39
37
  <%= a_button type: :button,
40
38
  data: { action: 'click->modal#close' },
41
39
  size: :sm,
@@ -11,13 +11,13 @@
11
11
  'turbo-frame': '_top'
12
12
  } do |form| %>
13
13
  <%= render Avo::ModalComponent.new do |c| %>
14
- <% c.with_heading do %>
14
+ <% c.heading do %>
15
15
  <%= t 'avo.choose_item', item: @related_resource.name.downcase %>
16
16
  <% end %>
17
17
 
18
18
  <div class="flex-1 flex items-center justify-center px-0 lg:px-8 text-lg mt-8 mb-12">
19
19
  <% if @field.is_searchable? %>
20
- <%= render Avo::Pro::SearchableAssociations::AutocompleteComponent.new form: form,
20
+ <%= render AvoPro::SearchableAssociations::AutocompleteComponent.new form: form,
21
21
  classes: input_classes("w-full"),
22
22
  field: @field,
23
23
  model_key: @field.target_resource&.model_key,
@@ -39,7 +39,7 @@
39
39
  <% end %>
40
40
  </div>
41
41
 
42
- <% c.with_controls do %>
42
+ <% c.controls do %>
43
43
  <%= a_button 'data-action': 'click->modal#close', size: :sm, style: :outline, color: :gray do %>
44
44
  <%= t('avo.cancel') %>
45
45
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <%
2
- license = Avo.license
2
+ license = Avo::App.license
3
3
  information_items = [
4
4
  'license_key',
5
5
  'ruby_version',
@@ -14,9 +14,9 @@
14
14
  %>
15
15
  <div class="flex flex-col">
16
16
  <%= render Avo::PanelComponent.new(name: 'Avo Status', description: 'Use this page to debug your Avo instance.') do |c| %>
17
- <% c.with_tools do %>
17
+ <% c.tools do %>
18
18
  <% end %>
19
- <% c.with_bare_content do %>
19
+ <% c.bare_content do %>
20
20
  <div class="grid gap-4 grid-cols-2">
21
21
  <div class="relative flex flex-col bg-white rounded shadow-panel p-4 space-y-4 h-full">
22
22
  <div class="flex justify-between w-full">
@@ -74,16 +74,15 @@
74
74
  <div class="flex flex-col flex-1">
75
75
  <div>
76
76
  <ul>
77
- <li>Avo <%= Avo::VERSION %></li>
78
77
  <% Avo.plugin_manager.plugins.each do |plugin| %>
79
- <li><%= plugin.klass.to_s.split("::").first %> <%= plugin.klass.version %></li>
78
+ <li><%= plugin.klass.to_s.split("::").first %></li>
80
79
  <% end %>
81
80
  </ul>
82
81
  </div>
83
82
  </div>
84
83
  </div>
85
84
  <%= render Avo::PanelComponent.new(title: "Report") do |c| %>
86
- <% c.with_body do %>
85
+ <% c.body do %>
87
86
  <div class="p-4">
88
87
  <turbo-frame id="debug-report" src="<%= root_path %>avo_private/debug/report" target="_top" class="block">
89
88
  Loading...
@@ -1,6 +1,6 @@
1
1
  <div class="flex flex-col">
2
2
  <%= render Avo::PanelComponent.new(name: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
3
- <% c.with_body do %>
3
+ <% c.body do %>
4
4
  <div class="flex flex-col justify-between py-6 min-h-24">
5
5
  <div class="px-6 space-y-4">
6
6
  <h3>About</h3>
@@ -5,8 +5,8 @@
5
5
  </a>
6
6
  </div>
7
7
  <% end %>
8
- <% if Avo.error_manager.has_errors?.present? %>
9
- <% Avo.error_manager.all.each do |error| %>
8
+ <% if Avo::App.errors.has_errors?.present? %>
9
+ <% Avo::App.errors.all.each do |error| %>
10
10
  <% if error.is_a? Hash %>
11
11
  <%
12
12
  url, message, target = error.values_at :url, :message, :target
@@ -1,3 +1,3 @@
1
1
  <div class="text-center text-sm text-gray-700 <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>">
2
- <a href="https://avohq.io/" target="_blank">Avo</a> · &copy; <%= Date.today.year %> AvoHQ · <span title="<%= Avo.license.valid ? 'valid' : 'invalid'%> <%= Avo.license.id %> license">v<%= Avo::VERSION %></span>
2
+ <a href="https://avohq.io/" target="_blank">Avo</a> · &copy; <%= Date.today.year %> AvoHQ · <span title="<%= Avo::App.license.valid ? 'valid' : 'invalid'%> <%= Avo::App.license.id %> license">v<%= Avo::VERSION %></span>
3
3
  </div>
@@ -6,7 +6,7 @@
6
6
  Avo.configuration.cookies_key = '<%= Avo::COOKIES_KEY %>'
7
7
  <% if Avo.avo_filters_installed? %>
8
8
  Avo.configuration.avo_filters = {
9
- param_key: '<%= Avo::DynamicFilters.configuration.param_key %>'
9
+ param_key: '<%= AvoFilters.configuration.param_key %>'
10
10
  }
11
11
  <% end %>
12
12
  <% end %>
@@ -10,7 +10,7 @@
10
10
  <%= render partial: "avo/partials/logo" %>
11
11
  </div>
12
12
  <div class="flex-1 flex items-center justify-between lg:justify-start space-x-2 sm:space-x-8 lg:px-2">
13
- <%= render Avo::Pro::GlobalSearchComponent.new rescue nil %>
13
+ <%= render AvoPro::GlobalSearchComponent.new rescue nil %>
14
14
  <div class="m-0">
15
15
  <%= render partial: "avo/partials/header" %>
16
16
  </div>
@@ -37,6 +37,14 @@
37
37
  sort_direction = 'desc'
38
38
  end
39
39
  classes = "text-gray-500 tracking-tight leading-tight text-xs font-semibold"
40
+ classes += case field.index_text_align.to_sym
41
+ when :right
42
+ " text-right"
43
+ when :center
44
+ " text-center"
45
+ else
46
+ ""
47
+ end
40
48
  %>
41
49
  <%= content_tag :th,
42
50
  class: "text-left uppercase px-3 py-3 whitespace-nowrap rounded-l",
@@ -11,15 +11,6 @@
11
11
  new_icon: 'grid-view-type',
12
12
  translation_key: 'avo.grid_view',
13
13
  },
14
- list: {
15
- new_view_type: 'list',
16
- new_icon: 'queue-list',
17
- },
18
- map: {
19
- new_view_type: 'map',
20
- new_icon: 'map-view-type',
21
- translation_key: 'avo.map_view',
22
- },
23
14
  }
24
15
  %>
25
16
  <div class="flex">
@@ -1,6 +1,6 @@
1
1
  <div class="flex flex-col">
2
2
  <%= render Avo::PanelComponent.new(name: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
3
- <% c.with_tools do %>
3
+ <% c.tools do %>
4
4
  <%= a_link('/admin', icon: 'arrow-left', color: :green, style: :primary, is_link: true) do %>
5
5
  Primary
6
6
  <% end %>
@@ -18,7 +18,7 @@
18
18
  <% end %>
19
19
  <% end %>
20
20
 
21
- <% c.with_body do %>
21
+ <% c.body do %>
22
22
  <div class="flex flex-col justify-between py-6 min-h-24">
23
23
  <%= render 'links_and_buttons' %>
24
24
  </div>
@@ -48,6 +48,7 @@
48
48
  </div>
49
49
  <%= turbo_frame_tag 'actions_show' %>
50
50
  <%= turbo_frame_tag 'attach_modal' %>
51
+ <%= turbo_frame_tag 'destroy_attachment_form' %>
51
52
  <%= turbo_frame_tag 'alerts', class: "fixed inset-0 bottom-0 flex flex-col space-y-4 items-end justify-right px-4 py-6 sm:p-6 justify-end z-[100] pointer-events-none" do %>
52
53
  <%= render Avo::FlashAlertsComponent.new flashes: flash %>
53
54
  <% # In case we have other general error messages %>
@@ -60,8 +61,8 @@
60
61
  <%= render partial: "avo/partials/scripts" %>
61
62
  <!-- Avo version: <%= Avo::VERSION %> -->
62
63
  <!-- Environment: <%= Rails.env %> -->
63
- <!-- License ID: <%= Avo.license.id %> -->
64
- <!-- License valid?: <%= Avo.license.valid ? "valid" : "invalid" %> -->
64
+ <!-- License ID: <%= Avo::App.license.id %> -->
65
+ <!-- License valid?: <%= Avo::App.license.valid ? "valid" : "invalid" %> -->
65
66
  </body>
66
67
  </html>
67
68
  <!-- ✨ Built with Avo • https://www.avohq.io/ -->
data/avo.gemspec CHANGED
@@ -33,13 +33,12 @@ Gem::Specification.new do |spec|
33
33
  spec.files = Dir["{bin,app,config,db,lib,public}/**/*", "MIT-LICENSE", "Rakefile", "README.md", "avo.gemspec", "Gemfile", "Gemfile.lock"]
34
34
 
35
35
  spec.add_dependency "activerecord", ">= 6.1"
36
- spec.add_dependency "activesupport", ">= 6.1"
37
36
  spec.add_dependency "actionview", ">= 6.1"
38
37
  spec.add_dependency "pagy"
39
38
  spec.add_dependency "zeitwerk", ">= 2.6.2"
40
39
  spec.add_dependency "httparty"
41
40
  spec.add_dependency "active_link_to"
42
- spec.add_dependency "view_component", ">= 3.0.0"
41
+ spec.add_dependency "view_component"
43
42
  spec.add_dependency "turbo-rails"
44
43
  spec.add_dependency "addressable"
45
44
  spec.add_dependency "meta-tags"
@@ -5,15 +5,13 @@ def pagy_locale_path(file_name)
5
5
  Avo::Engine.root.join("lib", "generators", "avo", "templates", "locales", "pagy", file_name)
6
6
  end
7
7
 
8
- extra_locales = [
9
- {locale: "en"},
10
- {locale: "fr"},
11
- {locale: "nb"},
12
- {locale: "pt-BR"},
13
- {locale: "pt"},
14
- {locale: "tr"},
15
- {locale: "nn", filepath: pagy_locale_path("nn.yml")},
16
- {locale: "ro", filepath: pagy_locale_path("ro.yml")}
17
- ]
18
-
19
- Pagy::I18n.send(:build, *extra_locales)
8
+ Pagy::I18n.load(
9
+ { locale: 'en' },
10
+ { locale: 'fr' },
11
+ { locale: 'nb' },
12
+ { locale: 'pt-BR' },
13
+ { locale: 'pt' },
14
+ { locale: 'tr' },
15
+ { locale: 'nn', filepath: pagy_locale_path("nn.yml") },
16
+ { locale: 'ro', filepath: pagy_locale_path("ro.yml") },
17
+ )
data/config/routes.rb CHANGED
@@ -4,9 +4,9 @@ Avo::Engine.routes.draw do
4
4
  get "resources", to: redirect(Avo.configuration.root_path)
5
5
  get "dashboards", to: redirect(Avo.configuration.root_path)
6
6
 
7
- mount Avo::DynamicFilters::Engine, at: "/avo-dynamic_filters" if defined?(Avo::DynamicFilters::Engine)
8
- mount Avo::Dashboards::Engine, at: "/dashboards" if defined?(Avo::Dashboards::Engine)
9
- mount Avo::Pro::Engine, at: "/avo/avo-pro" if defined?(Avo::Pro::Engine)
7
+ mount AvoFilters::Engine, at: "/avo_filters" if defined?(AvoFilters)
8
+ mount AvoDashboards::Engine, at: "/dashboards" if defined?(AvoDashboards::Engine)
9
+ mount AvoPro::Engine, at: "/avo_pro" if defined?(AvoPro)
10
10
 
11
11
  post "/rails/active_storage/direct_uploads", to: "/active_storage/direct_uploads#create"
12
12
 
@@ -23,8 +23,8 @@ Avo::Engine.routes.draw do
23
23
  delete "/:resource_name/:id/active_storage_attachments/:attachment_name/:attachment_id", to: "attachments#destroy"
24
24
 
25
25
  # Actions
26
- get "/:resource_name(/:id)/actions/(:action_id)", to: "actions#show"
27
- post "/:resource_name(/:id)/actions/(:action_id)", to: "actions#handle"
26
+ get "/:resource_name(/:id)/actions/:action_id", to: "actions#show"
27
+ post "/:resource_name(/:id)/actions/:action_id", to: "actions#handle"
28
28
 
29
29
  # Generate resource routes as below:
30
30
  # resources :posts
data/db/factories.rb CHANGED
@@ -48,20 +48,6 @@ FactoryBot.define do
48
48
  progress { Faker::Number.between(from: 0, to: 100) }
49
49
  end
50
50
 
51
- trait :with_files do
52
- after(:create) do |project|
53
- ["watch.jpg", "dummy-video.mp4"].each do |filename|
54
- file = Rails.root.join("db", "seed_files", filename)
55
- project.files.attach(io: file.open, filename: filename)
56
- end
57
-
58
- ["dummy-file.txt", "dummy-audio.mp3"].each do |filename|
59
- file = Avo::Engine.root.join("spec", "dummy", filename)
60
- project.files.attach(io: file.open, filename: filename)
61
- end
62
- end
63
- end
64
-
65
51
  factory :comment do
66
52
  body { Faker::Lorem.paragraphs(number: rand(4...10)).join(" ") }
67
53
  posted_at { Time.now - rand(10...365).days }
@@ -110,8 +96,6 @@ FactoryBot.define do
110
96
  factory :city do
111
97
  name { Faker::Address.city }
112
98
  population { rand(10000..999000) }
113
- latitude { Faker::Address.latitude }
114
- longitude { Faker::Address.longitude }
115
99
  is_capital { [true, false].sample }
116
100
  features { Faker::Address.community }
117
101
  metadata { Faker::Address.community }
@@ -119,7 +103,6 @@ FactoryBot.define do
119
103
  description { Faker::Address.community }
120
104
  status { ["open", "closed"].sample }
121
105
  tiny_description { Faker::Address.community }
122
- city_center_area { [[[10.0, 11.2], [10.5, 11.9], [10.8, 12.0], [10.0, 11.2]]].to_json }
123
106
  end
124
107
 
125
108
  factory :product do
data/lib/avo/app.rb ADDED
@@ -0,0 +1,165 @@
1
+ module Avo
2
+ class App
3
+ class_attribute :field_manager
4
+ class_attribute :cache_store, default: nil
5
+ class_attribute :logger
6
+
7
+ include ActiveModel::Model
8
+
9
+ attr_accessor :request, :context, :current_user, :view_context
10
+ attr_accessor :cache_store
11
+ attr_accessor :resource_manager
12
+ attr_accessor :dashboard_manager
13
+ attr_accessor :tool_manager
14
+ attr_accessor :error_manager
15
+
16
+ delegate :params, to: :request
17
+
18
+ class << self
19
+ def eager_load(entity)
20
+ paths = Avo::ENTITIES.fetch entity
21
+
22
+ return unless paths.present?
23
+
24
+ pathname = Rails.root.join(*paths)
25
+ if pathname.directory?
26
+ Rails.autoloaders.main.eager_load_dir(pathname.to_s)
27
+ end
28
+ end
29
+
30
+ def boot
31
+ init_logger
32
+ init_fields
33
+ init_cache_store
34
+ end
35
+
36
+ def init_cache_store
37
+ # The cache store should be set when the app boots up.
38
+ if Rails.cache.instance_of?(ActiveSupport::Cache::NullStore)
39
+ self.cache_store ||= ActiveSupport::Cache::MemoryStore.new
40
+ else
41
+ self.cache_store = Rails.cache
42
+ end
43
+ end
44
+
45
+ def init_logger
46
+ file_logger = ActiveSupport::Logger.new(Rails.root.join("log", "avo.log"))
47
+
48
+ file_logger.datetime_format = "%Y-%m-%d %H:%M:%S"
49
+ file_logger.formatter = proc do |severity, time, progname, msg|
50
+ "[Avo] #{time}: #{msg}\n".tap do |i|
51
+ puts i
52
+ end
53
+ end
54
+
55
+ self.logger = file_logger
56
+ end
57
+
58
+ def init_fields
59
+ self.field_manager = Avo::Fields::FieldManager.build
60
+ end
61
+
62
+ def fields
63
+ field_manager
64
+ end
65
+
66
+ def build(request:, context:, current_user:, view_context:)
67
+ @app || new(request: request, context: context, current_user: current_user, view_context: view_context)
68
+ end
69
+
70
+ def license
71
+ Current.license
72
+ end
73
+
74
+ def instance
75
+ Current.app
76
+ end
77
+
78
+ def resources
79
+ Current.app.resource_manager
80
+ end
81
+
82
+ def dashboards
83
+ Current.app.dashboard_manager
84
+ end
85
+
86
+ def tools
87
+ Current.app.tool_manager
88
+ end
89
+
90
+ def errors
91
+ Current.app.error_manager
92
+ end
93
+
94
+ # Renerate a dynamic root path using the URIService
95
+ def root_path(paths: [], query: {}, **args)
96
+ Avo::Services::URIService.parse(Avo::Current.view_context.avo.root_url.to_s)
97
+ .append_paths(paths)
98
+ .append_query(query)
99
+ .to_s
100
+ end
101
+
102
+ def mount_path
103
+ Avo::Engine.routes.find_script_name({})
104
+ end
105
+
106
+ def has_main_menu?
107
+ return false if Avo::App.license.lacks_with_trial(:menu_editor)
108
+ return false if Avo.configuration.main_menu.nil?
109
+
110
+ true
111
+ end
112
+
113
+ def has_profile_menu?
114
+ return false if Avo::App.license.lacks_with_trial(:menu_editor)
115
+ return false if Avo.configuration.profile_menu.nil?
116
+
117
+ true
118
+ end
119
+
120
+ def main_menu
121
+ return unless Avo.plugin_manager.installed?(:avo_menu)
122
+
123
+ # Return empty menu if the app doesn't have the profile menu configured
124
+ return AvoMenu::Builder.new.build unless has_main_menu?
125
+
126
+ AvoMenu::Builder.parse_menu(&Avo.configuration.main_menu)
127
+ end
128
+
129
+ def profile_menu
130
+ return unless Avo.plugin_manager.installed?(:avo_menu)
131
+
132
+ # Return empty menu if the app doesn't have the profile menu configured
133
+ return AvoMenu::Builder.new.build unless has_profile_menu?
134
+
135
+ AvoMenu::Builder.parse_menu(&Avo.configuration.profile_menu)
136
+ end
137
+ end
138
+
139
+ def init
140
+ self.error_manager = Avo::ErrorManager.build
141
+ self.resource_manager = Avo::Resources::ResourceManager.build
142
+ self.tool_manager = Avo::Tools::ToolManager.build
143
+ end
144
+
145
+ # Renerate a dynamic root path using the URIService
146
+ def root_path(paths: [], query: {}, **args)
147
+ Avo::Services::URIService.parse(view_context.avo.root_url.to_s)
148
+ .append_paths(paths)
149
+ .append_query(query)
150
+ .to_s
151
+ end
152
+
153
+ def mount_path
154
+ Avo::Engine.routes.find_script_name({})
155
+ end
156
+
157
+ def app_status
158
+ Current.license.valid?
159
+ end
160
+ end
161
+
162
+ def self.logger
163
+ Avo::App.logger
164
+ end
165
+ end