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.
- checksums.yaml +4 -4
- data/Gemfile +5 -5
- data/Gemfile.lock +81 -92
- data/{public/avo-assets/avo.css → app/assets/builds/avo.base.css} +686 -728
- data/app/assets/builds/avo.base.js +93804 -0
- data/app/assets/builds/avo.base.js.map +7 -0
- data/app/assets/stylesheets/avo.base.css +2 -1
- data/app/assets/svgs/failed_to_load.svg +1 -0
- data/app/assets/svgs/grid-empty-state.svg +1 -0
- data/app/assets/svgs/table-empty-state.svg +1 -0
- data/app/assets/svgs/triangle-up.svg +1 -1
- data/app/components/avo/actions_component.html.erb +1 -1
- data/app/components/avo/actions_component.rb +16 -42
- data/app/components/avo/alert_component.html.erb +1 -1
- data/app/components/avo/base_component.rb +7 -7
- data/app/components/avo/field_wrapper_component.html.erb +4 -4
- data/app/components/avo/field_wrapper_component.rb +1 -1
- data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +5 -5
- data/app/components/avo/fields/belongs_to_field/edit_component.rb +4 -8
- data/app/components/avo/fields/boolean_field/edit_component.html.erb +0 -1
- data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/code_field/edit_component.html.erb +0 -1
- data/app/components/avo/fields/common/files_list_viewer_component.html.erb +5 -0
- data/app/components/avo/fields/common/files_list_viewer_component.rb +8 -0
- data/app/components/avo/fields/common/heading_component.html.erb +1 -1
- data/app/components/avo/fields/common/single_file_viewer_component.html.erb +56 -0
- data/app/components/avo/fields/common/single_file_viewer_component.rb +55 -0
- data/app/components/avo/fields/country_field/edit_component.html.erb +1 -3
- data/app/components/avo/fields/file_field/edit_component.html.erb +2 -4
- data/app/components/avo/fields/file_field/edit_component.rb +0 -1
- data/app/components/avo/fields/file_field/index_component.rb +2 -2
- data/app/components/avo/fields/file_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/files_field/edit_component.html.erb +2 -4
- data/app/components/avo/fields/files_field/edit_component.rb +0 -1
- data/app/components/avo/fields/files_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/has_many_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/has_one_field/show_component.html.erb +4 -5
- data/app/components/avo/fields/has_one_field/show_component.rb +2 -6
- data/app/components/avo/fields/index_component.rb +0 -1
- data/app/components/avo/fields/markdown_field/edit_component.html.erb +3 -4
- data/app/components/avo/fields/markdown_field/show_component.html.erb +3 -3
- data/app/components/avo/fields/number_field/edit_component.html.erb +1 -3
- data/app/components/avo/fields/password_field/edit_component.html.erb +1 -3
- data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +0 -1
- data/app/components/avo/fields/select_field/edit_component.html.erb +1 -2
- data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/text_field/edit_component.html.erb +2 -3
- data/app/components/avo/fields/textarea_field/edit_component.html.erb +0 -1
- data/app/components/avo/fields/trix_field/edit_component.html.erb +1 -2
- data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
- data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
- data/app/components/avo/index/field_wrapper_component.rb +12 -0
- data/app/components/avo/index/grid_item_component.html.erb +35 -9
- data/app/components/avo/index/grid_item_component.rb +10 -36
- data/app/components/avo/index/resource_controls_component.rb +11 -8
- data/app/components/avo/index/resource_table_component.rb +1 -1
- data/app/components/avo/item_switcher_component.html.erb +5 -10
- data/app/components/avo/item_switcher_component.rb +1 -2
- data/app/components/avo/modal_component.html.erb +1 -1
- data/app/components/avo/panel_component.html.erb +1 -6
- data/app/components/avo/panel_component.rb +0 -1
- data/app/components/avo/profile_item_component.html.erb +2 -17
- data/app/components/avo/profile_item_component.rb +1 -13
- data/app/components/avo/referrer_params_component.html.erb +0 -2
- data/app/components/avo/resource_component.rb +6 -69
- data/app/components/avo/resource_sidebar_component.rb +1 -1
- data/app/components/avo/sidebar/link_component.html.erb +0 -2
- data/app/components/avo/sidebar/link_component.rb +3 -5
- data/app/components/avo/sidebar_component.html.erb +3 -3
- data/app/components/avo/sidebar_component.rb +4 -4
- data/app/components/avo/sidebar_profile_component.html.erb +27 -27
- data/app/components/avo/views/resource_edit_component.html.erb +5 -5
- data/app/components/avo/views/resource_edit_component.rb +1 -1
- data/app/components/avo/views/resource_index_component.html.erb +10 -19
- data/app/components/avo/views/resource_index_component.rb +16 -22
- data/app/components/avo/views/resource_show_component.html.erb +4 -4
- data/app/controllers/avo/actions_controller.rb +20 -20
- data/app/controllers/avo/application_controller.rb +67 -90
- data/app/controllers/avo/associations_controller.rb +7 -5
- data/app/controllers/avo/attachments_controller.rb +7 -22
- data/app/controllers/avo/base_controller.rb +35 -47
- data/app/controllers/avo/home_controller.rb +1 -1
- data/app/controllers/avo/search_controller.rb +16 -20
- data/app/controllers/concerns/avo/initializes_avo.rb +8 -3
- data/app/helpers/avo/application_helper.rb +6 -13
- data/app/javascript/js/application.js +0 -2
- data/app/javascript/js/controllers/fields/{easy_mde_controller.js → simple_mde_controller.js} +3 -4
- data/app/javascript/js/controllers/search_controller.js +1 -3
- data/app/javascript/js/controllers.js +2 -2
- data/app/views/avo/actions/show.html.erb +3 -5
- data/app/views/avo/associations/new.html.erb +3 -3
- data/app/views/avo/debug/status.html.erb +5 -6
- data/app/views/avo/home/index.html.erb +1 -1
- data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
- data/app/views/avo/partials/_footer.html.erb +1 -1
- data/app/views/avo/partials/_javascript.html.erb +1 -1
- data/app/views/avo/partials/_navbar.html.erb +1 -1
- data/app/views/avo/partials/_table_header.html.erb +8 -0
- data/app/views/avo/partials/_view_toggle_button.html.erb +0 -9
- data/app/views/avo/private/design.html.erb +2 -2
- data/app/views/layouts/avo/application.html.erb +3 -2
- data/avo.gemspec +1 -2
- data/config/initializers/pagy.rb +10 -12
- data/config/routes.rb +5 -5
- data/db/factories.rb +0 -17
- data/lib/avo/app.rb +165 -0
- data/lib/avo/base_action.rb +18 -31
- data/lib/avo/base_resource.rb +213 -238
- data/lib/avo/concerns/breadcrumbs.rb +2 -2
- data/lib/avo/concerns/can_replace_items.rb +7 -3
- data/lib/avo/concerns/filters_session_handler.rb +4 -5
- data/lib/avo/concerns/has_item_type.rb +0 -4
- data/lib/avo/concerns/has_items.rb +115 -93
- data/lib/avo/concerns/is_visible.rb +1 -1
- data/lib/avo/concerns/model_class_constantized.rb +2 -0
- data/lib/avo/configuration.rb +8 -9
- data/lib/avo/current.rb +1 -35
- data/lib/avo/dsl/field_parser.rb +1 -1
- data/lib/avo/dynamic_router.rb +2 -13
- data/lib/avo/engine.rb +13 -11
- data/lib/avo/execution_context.rb +2 -4
- data/lib/avo/fields/base_field.rb +14 -51
- data/lib/avo/fields/belongs_to_field.rb +13 -20
- data/lib/avo/fields/concerns/is_searchable.rb +1 -1
- data/lib/avo/fields/concerns/use_resource.rb +1 -1
- data/lib/avo/fields/date_field.rb +3 -16
- data/lib/avo/fields/field_manager.rb +3 -13
- data/lib/avo/fields/file_field.rb +0 -2
- data/lib/avo/fields/files_field.rb +0 -6
- data/lib/avo/fields/has_base_field.rb +5 -5
- data/lib/avo/fields/has_one_field.rb +1 -2
- data/lib/avo/fields/id_field.rb +1 -2
- data/lib/avo/filters/base_filter.rb +0 -9
- data/lib/avo/grid_collector.rb +40 -0
- data/lib/avo/html/builder.rb +1 -3
- data/lib/avo/licensing/h_q.rb +6 -11
- data/lib/avo/licensing/license.rb +1 -1
- data/lib/avo/licensing/license_manager.rb +1 -1
- data/lib/avo/licensing/{nil_license.rb → null_license.rb} +1 -1
- data/lib/avo/loaders/fields_loader.rb +1 -7
- data/lib/avo/plugin.rb +0 -10
- data/lib/avo/plugin_manager.rb +4 -2
- data/lib/avo/reloader.rb +1 -1
- data/lib/avo/resources/controls/actions_list.rb +1 -2
- data/lib/avo/resources/controls/create_button.rb +1 -1
- data/lib/avo/resources/controls/delete_button.rb +1 -1
- data/lib/avo/resources/controls/detach_button.rb +1 -1
- data/lib/avo/resources/controls/edit_button.rb +1 -1
- data/lib/avo/resources/controls/show_button.rb +1 -1
- data/lib/avo/resources/items/holder.rb +5 -13
- data/lib/avo/resources/items/item_group.rb +0 -1
- data/lib/avo/resources/resource_manager.rb +18 -11
- data/lib/avo/services/debug_service.rb +5 -6
- data/lib/avo/services/telemetry_service.rb +2 -3
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +25 -109
- data/lib/generators/avo/action_generator.rb +8 -8
- data/lib/generators/avo/card/chartkick_generator.rb +18 -0
- data/lib/generators/avo/card/metric_generator.rb +18 -0
- data/lib/generators/avo/card/partial_generator.rb +19 -0
- data/lib/generators/avo/eject_generator.rb +0 -1
- data/lib/generators/avo/filter_generator.rb +8 -8
- data/lib/generators/avo/install_generator.rb +1 -11
- data/lib/generators/avo/resource_generator.rb +4 -22
- data/lib/generators/avo/tailwindcss/install_generator.rb +1 -4
- data/lib/generators/avo/templates/action.tt +5 -7
- data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
- data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
- data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
- data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
- data/lib/generators/avo/templates/dashboards/dashboard.tt +3 -5
- data/lib/generators/avo/templates/initializer/avo.tt +2 -4
- data/lib/generators/avo/templates/resource/resource.tt +6 -6
- data/lib/generators/avo/templates/scope.tt +1 -1
- data/lib/generators/avo/templates/standalone_action.tt +8 -0
- data/lib/generators/avo/templates/tailwindcss/Procfile.dev +1 -1
- data/lib/tasks/avo_tasks.rake +0 -5
- metadata +19 -56
- data/app/assets/svgs/map-empty-state.svg +0 -35
- data/app/assets/svgs/map-view-type.svg +0 -3
- data/app/components/avo/fields/area_field/edit_component.html.erb +0 -7
- data/app/components/avo/fields/area_field/edit_component.rb +0 -4
- data/app/components/avo/fields/area_field/show_component.html.erb +0 -8
- data/app/components/avo/fields/area_field/show_component.rb +0 -4
- data/app/components/avo/fields/common/files/controls_component.html.erb +0 -29
- data/app/components/avo/fields/common/files/controls_component.rb +0 -19
- data/app/components/avo/fields/common/files/list_viewer_component.html.erb +0 -20
- data/app/components/avo/fields/common/files/list_viewer_component.rb +0 -41
- data/app/components/avo/fields/common/files/view_type/grid_component.html.erb +0 -27
- data/app/components/avo/fields/common/files/view_type/grid_component.rb +0 -51
- data/app/components/avo/fields/common/files/view_type/list_component.html.erb +0 -22
- data/app/components/avo/fields/common/files/view_type/list_component.rb +0 -15
- data/app/components/avo/fields/location_field/edit_component.html.erb +0 -22
- data/app/components/avo/fields/location_field/edit_component.rb +0 -4
- data/app/components/avo/fields/location_field/show_component.html.erb +0 -7
- data/app/components/avo/fields/location_field/show_component.rb +0 -4
- data/app/components/avo/index/resource_map_component.html.erb +0 -16
- data/app/components/avo/index/resource_map_component.rb +0 -109
- data/app/components/avo/row_component.html.erb +0 -3
- data/app/components/avo/row_component.rb +0 -12
- data/app/views/avo/attachments/destroy.turbo_stream.erb +0 -7
- data/app/views/avo/partials/_profile_menu_extra.html.erb +0 -2
- data/lib/avo/concerns/has_description.rb +0 -23
- data/lib/avo/fields/area_field.rb +0 -39
- data/lib/avo/fields/concerns/file_authorization.rb +0 -31
- data/lib/avo/fields/location_field.rb +0 -86
- data/lib/avo/resources/items/row.rb +0 -54
- data/lib/generators/avo/card_generator.rb +0 -27
- data/public/avo-assets/avo.base.css +0 -10542
- data/public/avo-assets/avo.base.js +0 -949
- data/public/avo-assets/avo.base.js.map +0 -7
- data/public/avo-assets/avo.js +0 -513
- data/public/avo-assets/avo.js.map +0 -7
@@ -1,4 +1,4 @@
|
|
1
|
-
@import './../../../node_modules/
|
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
4
|
@import './../../../node_modules/flatpickr/dist/flatpickr.css';
|
@@ -70,6 +70,7 @@ body {
|
|
70
70
|
@apply opacity-0 translate-y-1;
|
71
71
|
}
|
72
72
|
|
73
|
+
|
73
74
|
.turbo-progress-bar {
|
74
75
|
@apply bg-primary-400;
|
75
76
|
}
|
@@ -22,6 +22,7 @@
|
|
22
22
|
<feColorMatrix type="matrix" values="0 0 0 0 0.788235 0 0 0 0 0.803922 0 0 0 0 0.85098 0 0 0 0.349 0"/>
|
23
23
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_577_1090"/>
|
24
24
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_577_1090" result="shape"/>
|
25
|
+
</filter>
|
25
26
|
<filter id="filter1_d_577_1090" x="38.6401" y="0" width="170.72" height="78.1333" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
26
27
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
27
28
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
@@ -1 +1 @@
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="9" role="presentation"><g fill="none" fill-rule="evenodd"><path fill="#
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="9" role="presentation"><g fill="none" fill-rule="evenodd"><path fill="#8898AA" fill-opacity="0.1" d="M1 9.092h19l-6.402-6.74c-1.717-1.806-4.485-1.8-6.196 0L1 9.093zM20.342 8l-6.02-6.336c-2.108-2.22-5.538-2.218-7.645 0L.658 8h19.684z"></path><path fill="currentcolor" d="M7.402 2.353c1.711-1.801 4.48-1.807 6.196 0L20 9.093H1l6.402-6.74z"></path></g></svg>
|
@@ -32,7 +32,7 @@
|
|
32
32
|
>
|
33
33
|
<div data-target="actions-list" class="w-full space divide-y">
|
34
34
|
<% actions.each_with_index do |action, index| %>
|
35
|
-
<%= link_to action_path(action),
|
35
|
+
<%= link_to action_path(action.param_id),
|
36
36
|
data: {
|
37
37
|
action_name: action.action_name,
|
38
38
|
'turbo-frame': 'actions_show',
|
@@ -4,15 +4,14 @@ class Avo::ActionsComponent < ViewComponent::Base
|
|
4
4
|
include Avo::ApplicationHelper
|
5
5
|
attr_reader :label, :size, :as_row_control
|
6
6
|
|
7
|
-
def initialize(actions: [], resource: nil, view: nil, exclude: [],
|
7
|
+
def initialize(actions: [], resource: nil, view: nil, exclude: [], style: :outline, color: :primary, label: nil, size: :md, as_row_control: false)
|
8
8
|
@actions = actions || []
|
9
9
|
@resource = resource
|
10
10
|
@view = view
|
11
11
|
@exclude = exclude
|
12
|
-
@include = include
|
13
12
|
@color = color
|
14
13
|
@style = style
|
15
|
-
@label = label ||
|
14
|
+
@label = label || t("avo.actions")
|
16
15
|
@size = size
|
17
16
|
@as_row_control = as_row_control
|
18
17
|
end
|
@@ -22,25 +21,19 @@ class Avo::ActionsComponent < ViewComponent::Base
|
|
22
21
|
end
|
23
22
|
|
24
23
|
def actions
|
25
|
-
|
26
|
-
@actions.reject { |action| action.class.in?(@exclude) }
|
27
|
-
elsif @include.present?
|
28
|
-
@actions.select { |action| action.class.in?(@include) }
|
29
|
-
else
|
30
|
-
@actions
|
31
|
-
end
|
24
|
+
@actions.reject { |action| action.class.in?(@exclude) }
|
32
25
|
end
|
33
26
|
|
34
27
|
# When running an action for one record we should do it on a special path.
|
35
28
|
# We do that so we get the `record` param inside the action so we can prefill fields.
|
36
|
-
def action_path(
|
37
|
-
return single_record_path(
|
38
|
-
return many_records_path(
|
29
|
+
def action_path(id)
|
30
|
+
return single_record_path(id) if as_row_control
|
31
|
+
return many_records_path(id) unless @resource.has_record_id?
|
39
32
|
|
40
33
|
if on_record_page?
|
41
|
-
single_record_path
|
34
|
+
single_record_path id
|
42
35
|
else
|
43
|
-
many_records_path
|
36
|
+
many_records_path id
|
44
37
|
end
|
45
38
|
end
|
46
39
|
|
@@ -61,34 +54,15 @@ class Avo::ActionsComponent < ViewComponent::Base
|
|
61
54
|
!on_record_page?
|
62
55
|
end
|
63
56
|
|
64
|
-
def single_record_path(
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
def many_records_path(action)
|
69
|
-
action_url(action, @resource.records_path)
|
57
|
+
def single_record_path(id)
|
58
|
+
Avo::Services::URIService.parse(@resource.record_path)
|
59
|
+
.append_paths("actions", id)
|
60
|
+
.to_s
|
70
61
|
end
|
71
62
|
|
72
|
-
def
|
73
|
-
Avo::Services::URIService.parse(
|
74
|
-
.append_paths("actions")
|
75
|
-
.
|
76
|
-
{
|
77
|
-
action_id: action.param_id,
|
78
|
-
arguments: encrypted_arguments(action)
|
79
|
-
}.compact
|
80
|
-
).to_s
|
81
|
-
end
|
82
|
-
|
83
|
-
# Encrypt the arguments so we can pass them as a query param.
|
84
|
-
# EncryptionService can generate special characters that can break the URL.
|
85
|
-
# We use Base64 to encode the encrypted string so we can safely pass it as a query param and don't break the URL.
|
86
|
-
def encrypted_arguments(action)
|
87
|
-
return if action.arguments.blank?
|
88
|
-
|
89
|
-
Base64.encode64 Avo::Services::EncryptionService.encrypt(
|
90
|
-
message: action.arguments,
|
91
|
-
purpose: :action_arguments
|
92
|
-
)
|
63
|
+
def many_records_path(id)
|
64
|
+
Avo::Services::URIService.parse(@resource.records_path)
|
65
|
+
.append_paths("actions", id)
|
66
|
+
.to_s
|
93
67
|
end
|
94
68
|
end
|
@@ -4,7 +4,7 @@ class Avo::BaseComponent < ViewComponent::Base
|
|
4
4
|
include Turbo::FramesHelper
|
5
5
|
|
6
6
|
def has_with_trial(ability)
|
7
|
-
Avo.license.has_with_trial(ability)
|
7
|
+
::Avo::App.license.has_with_trial(ability)
|
8
8
|
end
|
9
9
|
|
10
10
|
private
|
@@ -18,7 +18,7 @@ class Avo::BaseComponent < ViewComponent::Base
|
|
18
18
|
|
19
19
|
# Fetch the resource and hydrate it with the record
|
20
20
|
def association_resource
|
21
|
-
resource = Avo.
|
21
|
+
resource = ::Avo::App.resources.get_resource(params[:via_resource_class])
|
22
22
|
|
23
23
|
model_class = if params[:via_relation_class].present?
|
24
24
|
::Avo::BaseResource.get_model_by_name params[:via_relation_class]
|
@@ -26,23 +26,23 @@ class Avo::BaseComponent < ViewComponent::Base
|
|
26
26
|
resource.model_class
|
27
27
|
end
|
28
28
|
|
29
|
-
resource = Avo.
|
29
|
+
resource = ::Avo::App.resources.get_resource_by_model_class model_class if resource.blank?
|
30
30
|
|
31
31
|
record = resource.find_record params[:via_record_id], query: model_class, params: params
|
32
32
|
|
33
|
-
resource.
|
33
|
+
resource.dup.hydrate record: record
|
34
34
|
end
|
35
35
|
|
36
36
|
# Get the resource for the resource using the klass attribute so we get the namespace too
|
37
37
|
def reflection_resource
|
38
|
-
Avo.
|
38
|
+
::Avo::App.resources.get_resource_by_model_class(@reflection.klass.to_s)
|
39
39
|
rescue
|
40
40
|
nil
|
41
41
|
end
|
42
42
|
|
43
43
|
# Get the resource for the resource using the klass attribute so we get the namespace too
|
44
44
|
def reflection_parent_resource
|
45
|
-
Avo.
|
45
|
+
::Avo::App.resources.get_resource_by_model_class(@reflection.active_record.to_s)
|
46
46
|
rescue
|
47
47
|
nil
|
48
48
|
end
|
@@ -51,7 +51,7 @@ class Avo::BaseComponent < ViewComponent::Base
|
|
51
51
|
return @resource unless link_to_child_resource_is_enabled?
|
52
52
|
return @resource if @resource.record.class.base_class == @resource.record.class
|
53
53
|
|
54
|
-
Avo.
|
54
|
+
::Avo::App.resources.get_resource_by_model_class(@resource.record.class).dup || @resource
|
55
55
|
end
|
56
56
|
|
57
57
|
def link_to_child_resource_is_enabled?
|
@@ -2,7 +2,7 @@
|
|
2
2
|
class: classes,
|
3
3
|
style: style,
|
4
4
|
data: data do %>
|
5
|
-
<div class="h-full <% if stacked? %> md:pt-4 <% else %> md:pt-0 <% if short? %> md:h-10 <% else %> md:h-14 <% end %> <% end %> pt-4 flex self-start items-center
|
5
|
+
<div class="h-full <% if stacked? %> md:pt-4 <% else %> md:pt-0 <% if short? %> md:h-10 <% else %> md:h-14 <% end %> <% end %> pt-4 flex self-start items-center <%= @field.get_html(:classes, view: view, element: :label) %> w-48 <% if compact? %> md:w-48 xl:w-64 <% else %> md:w-64 <% end %> px-6 uppercase font-semibold text-gray-500 text-sm" data-slot="label">
|
6
6
|
<% if form.present? %>
|
7
7
|
<%= form.label field.id, label %>
|
8
8
|
<% else %>
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<% if on_edit? && field.is_required? %> <span class="text-red-600 ml-1">*</span> <% end %>
|
12
12
|
</div>
|
13
13
|
<div class="flex-1 flex flex-row md:min-h-inherit py-2 <% if stacked? %> pb-4 <% else %><% end %> px-6 <%= @field.get_html(:classes, view: view, element: :content) %>" data-slot="value">
|
14
|
-
<div class="self-center
|
14
|
+
<div class="self-center <% if full_width? || compact? || stacked? %> w-full <% else %> md:w-8/12 <% end %>">
|
15
15
|
<% if on_show? %>
|
16
16
|
<% if field.value.blank? and dash_if_blank %>
|
17
17
|
—
|
@@ -24,13 +24,13 @@
|
|
24
24
|
<div class="text-red-600 mt-2 text-sm"><%= record.errors.full_messages_for(field.id).to_sentence %></div>
|
25
25
|
<% end %>
|
26
26
|
<% if help.present? %>
|
27
|
-
<div class="text-gray-600 mt-2 text-sm"
|
27
|
+
<div class="text-gray-600 mt-2 text-sm"><%== help %></div>
|
28
28
|
<% end %>
|
29
29
|
<% end %>
|
30
30
|
</div>
|
31
31
|
</div>
|
32
32
|
<% if params[:avo_debug].present? %>
|
33
33
|
<!-- Raw value: -->
|
34
|
-
<!--
|
34
|
+
<!-- <%== field.value.inspect %> -->
|
35
35
|
<% end %>
|
36
36
|
<% end %>
|
@@ -43,7 +43,7 @@ class Avo::FieldWrapperComponent < ViewComponent::Base
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def classes(extra_classes = "")
|
46
|
-
"field-wrapper relative flex flex-col grow pb-2 md:pb-0 leading-tight min-h-14
|
46
|
+
"field-wrapper relative flex flex-col flex-grow pb-2 md:pb-0 leading-tight min-h-14 #{stacked? ? "field-wrapper-layout-stacked" : "field-wrapper-layout-inline md:flex-row md:items-center"} #{compact? ? "field-wrapper-size-compact" : "field-wrapper-size-regular"} #{full_width? ? "field-width-full" : "field-width-regular"} #{@classes || ""} #{extra_classes || ""} #{@field.get_html(:classes, view: view, element: :wrapper)}"
|
47
47
|
end
|
48
48
|
|
49
49
|
def style
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<%
|
3
3
|
# Set the model keys so we can pass them over
|
4
4
|
model_keys = @field.types.map do |type|
|
5
|
-
resource = Avo.
|
5
|
+
resource = Avo::App.resources.get_resource_by_model_class(type.to_s)
|
6
6
|
[type.to_s, resource.model_key]
|
7
7
|
end.to_h
|
8
8
|
%>
|
@@ -13,7 +13,7 @@
|
|
13
13
|
data-association-class="<%= @field&.target_resource&.model_class || nil %>"
|
14
14
|
>
|
15
15
|
<%= field_wrapper **field_wrapper_args, help: @field.polymorphic_help || '' do %>
|
16
|
-
<%= @form.select @field.type_input_foreign_key, @field.types.map { |type| [Avo.
|
16
|
+
<%= @form.select @field.type_input_foreign_key, @field.types.map { |type| [::Avo::App.resources.get_resource_by_model_class(type.to_s).name, type.to_s] },
|
17
17
|
{
|
18
18
|
value: @field.value,
|
19
19
|
include_blank: @field.placeholder,
|
@@ -40,9 +40,9 @@
|
|
40
40
|
data-belongs-to-field-target="type"
|
41
41
|
data-type="<%= type %>"
|
42
42
|
>
|
43
|
-
<%= field_wrapper **field_wrapper_args, label: Avo.
|
43
|
+
<%= field_wrapper **field_wrapper_args, label: ::Avo::App.resources.get_resource_by_model_class(type.to_s).name do %>
|
44
44
|
<% if @field.is_searchable? %>
|
45
|
-
<%= render
|
45
|
+
<%= render AvoPro::SearchableAssociations::AutocompleteComponent.new form: @form,
|
46
46
|
disabled: disabled,
|
47
47
|
field: @field,
|
48
48
|
foreign_key: @field.id_input_foreign_key,
|
@@ -81,7 +81,7 @@
|
|
81
81
|
<% else %>
|
82
82
|
<%= field_wrapper **field_wrapper_args do %>
|
83
83
|
<% if @field.is_searchable? %>
|
84
|
-
<%= render
|
84
|
+
<%= render AvoPro::SearchableAssociations::AutocompleteComponent.new form: @form,
|
85
85
|
field: @field,
|
86
86
|
model_key: @field.target_resource&.model_key,
|
87
87
|
foreign_key: @field.id_input_foreign_key,
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
|
4
|
-
def initialize(
|
5
|
-
super
|
4
|
+
def initialize(field: nil, resource: nil, index: 0, form: nil, compact: false, **args)
|
5
|
+
super field: field, resource: resource, index: index, form: form, compact: compact, **args
|
6
6
|
|
7
7
|
@polymorphic_record = nil
|
8
8
|
end
|
@@ -31,10 +31,6 @@ class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
|
|
31
31
|
@resource.record["#{@field.foreign_key}_type"]
|
32
32
|
end
|
33
33
|
|
34
|
-
def polymorphic_resource
|
35
|
-
Avo.resource_manager.get_resource_by_model_class(polymorphic_class)
|
36
|
-
end
|
37
|
-
|
38
34
|
# Get the polymorphic id
|
39
35
|
def polymorphic_id
|
40
36
|
@resource.record["#{@field.foreign_key}_id"]
|
@@ -48,7 +44,7 @@ class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
|
|
48
44
|
|
49
45
|
return @polymorphic_record if @polymorphic_record.present?
|
50
46
|
|
51
|
-
@polymorphic_record =
|
47
|
+
@polymorphic_record = @resource.find_record polymorphic_id, query: polymorphic_class.safe_constantize, params: params
|
52
48
|
|
53
49
|
@polymorphic_record
|
54
50
|
end
|
@@ -60,6 +56,6 @@ class Avo::Fields::BelongsToField::EditComponent < Avo::Fields::EditComponent
|
|
60
56
|
private
|
61
57
|
|
62
58
|
def visit_through_association?
|
63
|
-
@field.target_resource.to_s == params[:via_resource_class].to_s
|
59
|
+
@field.target_resource.class.to_s == params[:via_resource_class].to_s
|
64
60
|
end
|
65
61
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args, dash_if_blank: false do %>
|
2
2
|
<div class="h-8 flex items-center">
|
3
3
|
<%= @form.check_box @field.id,
|
4
|
-
value: @field.value,
|
5
4
|
checked: @field.value,
|
6
5
|
class: "text-lg h-4 w-4 checked:bg-primary-400 focus:checked:!bg-primary-400 rounded #{@field.get_html(:classes, view: view, element: :input)}",
|
7
6
|
data: @field.get_html(:data, view: view, element: :input),
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<div class="flex items-center">
|
3
3
|
<div class="space-y-2">
|
4
4
|
<% model_param_key = model_name_from_record_or_class(@resource.record).param_key %>
|
5
|
-
<%= check_box_tag "#{
|
5
|
+
<%= check_box_tag "#{model_name_from_record_or_class(@resource.record).param_key}[#{@field.id}][]", '', true, { class: "hidden" } %>
|
6
6
|
<% @field.options.each do |id, label| %>
|
7
7
|
<%
|
8
8
|
checked = false
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<div class="relative py-3 grid xs:grid-cols-2 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-3 rounded-xl">
|
2
|
+
<% @field.value.attachments.each do |file| %>
|
3
|
+
<%= render Avo::Fields::Common::SingleFileViewerComponent.new field: @field, resource: @resource, file: file %>
|
4
|
+
<% end %>
|
5
|
+
</div>
|
@@ -0,0 +1,56 @@
|
|
1
|
+
<div class="relative min-h-full max-w-full flex-1 flex flex-col justify-between space-y-3">
|
2
|
+
<% if file.present? %>
|
3
|
+
<div class="flex flex-col justify-between h-full">
|
4
|
+
<% if file.representable? && is_image? %>
|
5
|
+
<div class="max-h-[42rem] h-full flex">
|
6
|
+
<%= image_tag helpers.main_app.url_for(file), class: 'rounded-lg object-cover' %>
|
7
|
+
</div>
|
8
|
+
<% elsif is_audio? %>
|
9
|
+
<%= audio_tag(helpers.main_app.url_for(file), controls: true, preload: false, class: 'w-full') %>
|
10
|
+
<% elsif is_video? %>
|
11
|
+
<%= video_tag(helpers.main_app.url_for(file), controls: true, preload: false, class: 'w-full') %>
|
12
|
+
<% else %>
|
13
|
+
<div class="relative flex flex-col justify-evenly items-center px-2 rounded-lg border bg-white border-gray-500 min-h-24">
|
14
|
+
<div class="flex flex-col justify-center items-center w-full">
|
15
|
+
<%= helpers.svg 'document-text', class: 'h-10 text-gray-600 mb-2' %>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
19
|
+
<span class="text-gray-500 mt-2 text-sm truncate" title="<%= file.filename %>"><%= file.filename %></span>
|
20
|
+
</div>
|
21
|
+
<div class="flex space-x-2">
|
22
|
+
<div class="flex">
|
23
|
+
<% if @resource.authorization.authorize_action(:download_attachments?, raise_exception: false) %>
|
24
|
+
<%= a_link Rails.application.routes.url_helpers.rails_blob_path(file, only_path: true, disposition: :attachment),
|
25
|
+
icon: 'heroicons/outline/download',
|
26
|
+
color: :primary,
|
27
|
+
download: true,
|
28
|
+
class: 'text-center',
|
29
|
+
title: t('avo.download_file'),
|
30
|
+
data: { tippy: :tooltip },
|
31
|
+
compact: true,
|
32
|
+
size: :xs %>
|
33
|
+
<% end %>
|
34
|
+
</div>
|
35
|
+
<div>
|
36
|
+
<% if @resource.authorization.authorize_action(:delete_attachments?, raise_exception: false) %>
|
37
|
+
<%= a_link destroy_path,
|
38
|
+
icon: 'heroicons/outline/trash',
|
39
|
+
color: :red,
|
40
|
+
compact: true,
|
41
|
+
size: :xs,
|
42
|
+
class: 'text-center',
|
43
|
+
title: t('avo.delete_file', item: file.filename),
|
44
|
+
data: {
|
45
|
+
turbo_method: :delete,
|
46
|
+
turbo_frame: 'destroy_attachment_form',
|
47
|
+
turbo_confirm: t('avo.are_you_sure'),
|
48
|
+
tippy: :tooltip
|
49
|
+
} %>
|
50
|
+
<% end %>
|
51
|
+
</div>
|
52
|
+
</div>
|
53
|
+
<% else %>
|
54
|
+
–
|
55
|
+
<% end %>
|
56
|
+
</div>
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Avo::Fields::Common::SingleFileViewerComponent < ViewComponent::Base
|
4
|
+
include Avo::ApplicationHelper
|
5
|
+
|
6
|
+
def initialize(file: nil, field:, resource:)
|
7
|
+
@file = file
|
8
|
+
@field = field
|
9
|
+
@resource = resource
|
10
|
+
end
|
11
|
+
|
12
|
+
def destroy_path
|
13
|
+
Avo::Services::URIService.parse(@resource.record_path).append_paths("active_storage_attachments", id, file.id).to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def id
|
17
|
+
@field.id
|
18
|
+
end
|
19
|
+
|
20
|
+
def file
|
21
|
+
@file || @field.value.attachment
|
22
|
+
rescue
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def is_image?
|
27
|
+
file.image? || @field.is_image
|
28
|
+
rescue
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_audio?
|
33
|
+
file.audio? || @field.is_audio
|
34
|
+
rescue
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
def is_video?
|
39
|
+
file.video? || @field.is_video
|
40
|
+
rescue
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
def render?
|
45
|
+
record_persisted?
|
46
|
+
end
|
47
|
+
|
48
|
+
# If record is not persistent blob is automatically destroyed otherwise it can be "lost" on storage
|
49
|
+
def record_persisted?
|
50
|
+
return true if @resource.record.persisted?
|
51
|
+
|
52
|
+
ActiveStorage::Blob.destroy(file.blob_id) if file.blob_id.present?
|
53
|
+
false
|
54
|
+
end
|
55
|
+
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args do %>
|
2
2
|
<%= @form.select @field.id, @field.select_options, {
|
3
|
-
value: @field.value,
|
4
3
|
selected: @field.value,
|
5
4
|
include_blank: @field.include_blank
|
6
5
|
},
|
@@ -11,7 +10,6 @@
|
|
11
10
|
data: @field.get_html(:data, view: view, element: :input),
|
12
11
|
disabled: disabled?,
|
13
12
|
style: @field.get_html(:style, view: view, element: :input),
|
14
|
-
placeholder: @field.include_blank.present? ? nil : @field.placeholder
|
15
|
-
autocomplete: @field.autocomplete
|
13
|
+
placeholder: @field.include_blank.present? ? nil : @field.placeholder
|
16
14
|
%>
|
17
15
|
<% end %>
|
@@ -1,11 +1,11 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args do %>
|
2
2
|
<% if @field.value.present? %>
|
3
3
|
<div class="mb-2">
|
4
|
-
<%= render Avo::Fields::Common::
|
4
|
+
<%= render Avo::Fields::Common::SingleFileViewerComponent.new resource: @resource, field: @field %>
|
5
5
|
</div>
|
6
6
|
<% end %>
|
7
7
|
|
8
|
-
<% if
|
8
|
+
<% if @resource.authorization.authorize_action(:upload_attachments?, raise_exception: false) %>
|
9
9
|
<%= @form.file_field @field.id,
|
10
10
|
accept: @field.accept,
|
11
11
|
data: @field.get_html(:data, view: view, element: :input),
|
@@ -14,7 +14,5 @@
|
|
14
14
|
style: @field.get_html(:style, view: view, element: :input),
|
15
15
|
class: "w-full"
|
16
16
|
%>
|
17
|
-
<% else %>
|
18
|
-
—
|
19
17
|
<% end %>
|
20
18
|
<% end %>
|
@@ -6,10 +6,10 @@ class Avo::Fields::FileField::IndexComponent < Avo::Fields::IndexComponent
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def has_image_tag?
|
9
|
-
field.value.
|
9
|
+
@field.value.attached? && @field.value.representable? && @field.is_image
|
10
10
|
end
|
11
11
|
|
12
12
|
def has_audio_tag?
|
13
|
-
field.value.
|
13
|
+
@field.value.attached? && @field.is_audio
|
14
14
|
end
|
15
15
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args, full_width: true do %>
|
2
|
-
<%= render Avo::Fields::Common::
|
2
|
+
<%= render Avo::Fields::Common::FilesListViewerComponent.new(field: @field, resource: @resource) if @field.value.present? %>
|
3
3
|
|
4
|
-
<% if
|
4
|
+
<% if @resource.authorization.authorize_action(:upload_attachments?, raise_exception: false) %>
|
5
5
|
<div class="mt-2">
|
6
6
|
<%= @form.file_field @field.id,
|
7
7
|
accept: @field.accept,
|
@@ -13,7 +13,5 @@
|
|
13
13
|
class: "w-full"
|
14
14
|
%>
|
15
15
|
</div>
|
16
|
-
<% else %>
|
17
|
-
—
|
18
16
|
<% end %>
|
19
17
|
<% end %>
|
@@ -1,3 +1,3 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args, full_width: true do %>
|
2
|
-
<%= render Avo::Fields::Common::
|
2
|
+
<%= render Avo::Fields::Common::FilesListViewerComponent.new(field: @field, resource: @resource) if @field.value.present? %>
|
3
3
|
<% end %>
|
@@ -4,14 +4,13 @@
|
|
4
4
|
</turbo-frame>
|
5
5
|
<% else %>
|
6
6
|
<%= render Avo::PanelComponent.new(name: @field.name) do |c| %>
|
7
|
-
<% c.
|
7
|
+
<% c.tools do %>
|
8
8
|
<% if !@field.is_readonly? && !@field.is_disabled? && can_attach? %>
|
9
9
|
<%= a_link attach_path,
|
10
10
|
icon: 'heroicons/outline/link',
|
11
11
|
color: :primary,
|
12
|
-
style: :text,
|
13
12
|
'data-turbo-frame': 'attach_modal' do %>
|
14
|
-
<%= t('avo.attach_item', item: @field.name.
|
13
|
+
<%= t('avo.attach_item', item: @field.name.downcase) %>
|
15
14
|
<% end %>
|
16
15
|
<% end %>
|
17
16
|
<% if !@field.is_readonly? && !@field.is_disabled? && can_see_the_create_button? %>
|
@@ -21,12 +20,12 @@
|
|
21
20
|
'data-turbo-frame': '_top',
|
22
21
|
style: :primary,
|
23
22
|
color: :primary do %>
|
24
|
-
<%= t('avo.create_new_item', item: @field.name.
|
23
|
+
<%= t('avo.create_new_item', item: @field.name.downcase ) %>
|
25
24
|
<% end %>
|
26
25
|
<% end %>
|
27
26
|
<% end %>
|
28
27
|
|
29
|
-
<% c.
|
28
|
+
<% c.body do %>
|
30
29
|
<div class="py-8 flex justify-center items-center">
|
31
30
|
<%= empty_state by_association: params[:related_name].present? %>
|
32
31
|
</div>
|