avo 2.11.1 → 2.11.2.pre.1
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.lock +1 -1
- data/app/assets/stylesheets/avo.css +1 -4
- data/app/assets/stylesheets/css/sidebar.css +18 -0
- data/app/assets/svgs/failed_to_load.svg +15 -0
- data/app/components/avo/common_field_wrapper_component.html.erb +4 -0
- data/app/components/avo/fields/has_one_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/has_one_field/show_component.rb +7 -6
- data/app/components/avo/fields/text_field/index_component.html.erb +2 -0
- data/app/components/avo/fields/text_field/show_component.html.erb +2 -0
- data/app/components/avo/fields/trix_field/edit_component.rb +1 -1
- data/app/components/avo/index/field_wrapper_component.html.erb +4 -0
- data/app/components/avo/index/resource_controls_component.html.erb +3 -0
- data/app/components/avo/index/resource_controls_component.rb +7 -5
- data/app/components/avo/index/resource_table_component.html.erb +1 -1
- data/app/components/avo/index/resource_table_component.rb +2 -1
- data/app/components/avo/index/table_row_component.html.erb +14 -5
- data/app/components/avo/index/table_row_component.rb +2 -1
- data/app/components/avo/item_switcher_component.html.erb +1 -1
- data/app/components/avo/resource_component.rb +11 -5
- data/app/components/avo/sidebar_component.html.erb +8 -2
- data/app/components/avo/sidebar_component.rb +9 -0
- data/app/components/avo/tab_switcher_component.rb +4 -0
- data/app/components/avo/views/resource_edit_component.rb +4 -6
- data/app/components/avo/views/resource_index_component.html.erb +1 -1
- data/app/components/avo/views/resource_index_component.rb +5 -3
- data/app/components/avo/views/resource_show_component.html.erb +1 -1
- data/app/components/avo/views/resource_show_component.rb +3 -1
- data/app/controllers/avo/application_controller.rb +25 -10
- data/app/controllers/avo/associations_controller.rb +38 -12
- data/app/controllers/avo/base_controller.rb +7 -2
- data/app/javascript/js/controllers/fields/key_value_controller.js +3 -1
- data/app/javascript/js/controllers/sidebar_controller.js +49 -0
- data/app/javascript/js/controllers.js +2 -2
- data/app/views/avo/base/index.html.erb +1 -0
- data/app/views/avo/base/show.html.erb +7 -1
- data/app/views/avo/home/failed_to_load.html copy.erb +23 -0
- data/app/views/avo/home/failed_to_load.html.erb +9 -15
- data/app/views/avo/partials/_javascript.html.erb +1 -0
- data/app/views/avo/partials/_navbar.html.erb +5 -2
- data/app/views/avo/partials/_table_header.html.erb +12 -5
- data/app/views/layouts/avo/application.html.erb +9 -4
- data/bin/init +5 -0
- data/lib/avo/base_resource.rb +16 -1
- data/lib/avo/concerns/has_fields.rb +12 -3
- data/lib/avo/concerns/has_html_attributes.rb +1 -1
- data/lib/avo/concerns/model_class_constantized.rb +1 -1
- data/lib/avo/configuration/resource_configuration.rb +21 -0
- data/lib/avo/configuration.rb +2 -0
- data/lib/avo/fields/has_base_field.rb +11 -0
- data/lib/avo/fields/text_field.rb +4 -2
- data/lib/avo/items_holder.rb +6 -0
- data/lib/avo/panel_builder.rb +1 -0
- data/lib/avo/services/authorization_service.rb +41 -37
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +1 -0
- data/public/avo-assets/avo.css +78 -16
- data/public/avo-assets/avo.js +70 -69
- data/public/avo-assets/avo.js.map +3 -3
- metadata +9 -5
- data/app/javascript/js/controllers/mobile_controller.js +0 -9
@@ -5,12 +5,16 @@ module Avo
|
|
5
5
|
before_action :set_model, only: [:show, :index, :new, :create, :destroy, :order]
|
6
6
|
before_action :set_related_resource_name
|
7
7
|
before_action :set_related_resource, only: [:show, :index, :new, :create, :destroy, :order]
|
8
|
-
before_action :
|
8
|
+
before_action :set_reflection_field
|
9
|
+
before_action :hydrate_related_resource, only: [:show, :index, :create, :destroy, :order]
|
9
10
|
before_action :set_related_model, only: [:show, :order]
|
11
|
+
before_action :set_reflection
|
10
12
|
before_action :set_attachment_class, only: [:show, :index, :new, :create, :destroy, :order]
|
11
13
|
before_action :set_attachment_resource, only: [:show, :index, :new, :create, :destroy, :order]
|
12
14
|
before_action :set_attachment_model, only: [:create, :destroy, :order]
|
13
|
-
before_action :
|
15
|
+
before_action :authorize_index_action, only: :index
|
16
|
+
before_action :authorize_attach_action, only: :new
|
17
|
+
before_action :authorize_detach_action, only: :destroy
|
14
18
|
|
15
19
|
def index
|
16
20
|
@parent_resource = @resource.dup
|
@@ -28,6 +32,8 @@ module Avo
|
|
28
32
|
end
|
29
33
|
|
30
34
|
def show
|
35
|
+
@parent_resource, @parent_model = @resource, @model
|
36
|
+
|
31
37
|
@resource, @model = @related_resource, @related_model
|
32
38
|
|
33
39
|
super
|
@@ -36,12 +42,6 @@ module Avo
|
|
36
42
|
def new
|
37
43
|
@resource.hydrate(model: @model)
|
38
44
|
|
39
|
-
begin
|
40
|
-
@field = @resource.get_field_definitions.find { |f| f.id == @related_resource_name.to_sym }
|
41
|
-
@field.hydrate(resource: @resource, model: @model, view: :new)
|
42
|
-
rescue
|
43
|
-
end
|
44
|
-
|
45
45
|
if @field.present? && !@field.searchable
|
46
46
|
query = @authorization.apply_policy @attachment_class
|
47
47
|
|
@@ -93,8 +93,12 @@ module Avo
|
|
93
93
|
|
94
94
|
private
|
95
95
|
|
96
|
+
def set_reflection
|
97
|
+
@reflection = @model._reflections[params[:related_name].to_s]
|
98
|
+
end
|
99
|
+
|
96
100
|
def set_attachment_class
|
97
|
-
@attachment_class = @
|
101
|
+
@attachment_class = @reflection.klass
|
98
102
|
end
|
99
103
|
|
100
104
|
def set_attachment_resource
|
@@ -102,11 +106,13 @@ module Avo
|
|
102
106
|
end
|
103
107
|
|
104
108
|
def set_attachment_model
|
105
|
-
@attachment_model = @
|
109
|
+
@attachment_model = @attachment_class.find attachment_id
|
106
110
|
end
|
107
111
|
|
108
|
-
def
|
109
|
-
@
|
112
|
+
def set_reflection_field
|
113
|
+
@field = @resource.get_field_definitions.find { |f| f.id == @related_resource_name.to_sym }
|
114
|
+
@field.hydrate(resource: @resource, model: @model, view: :new)
|
115
|
+
rescue
|
110
116
|
end
|
111
117
|
|
112
118
|
def attachment_id
|
@@ -121,5 +127,25 @@ module Avo
|
|
121
127
|
|
122
128
|
klass
|
123
129
|
end
|
130
|
+
|
131
|
+
def authorize_if_defined(method)
|
132
|
+
@authorization.set_record(@model)
|
133
|
+
|
134
|
+
if @authorization.has_method?(method.to_sym)
|
135
|
+
@authorization.authorize_action method.to_sym
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def authorize_index_action
|
140
|
+
authorize_if_defined "view_#{@field.id}?"
|
141
|
+
end
|
142
|
+
|
143
|
+
def authorize_attach_action
|
144
|
+
authorize_if_defined "attach_#{@field.id}?"
|
145
|
+
end
|
146
|
+
|
147
|
+
def authorize_detach_action
|
148
|
+
authorize_if_defined "detach_#{@field.id}?"
|
149
|
+
end
|
124
150
|
end
|
125
151
|
end
|
@@ -10,7 +10,8 @@ module Avo
|
|
10
10
|
before_action :set_model_to_fill
|
11
11
|
before_action :set_edit_title_and_breadcrumbs, only: [:edit, :update]
|
12
12
|
before_action :fill_model, only: [:create, :update]
|
13
|
-
|
13
|
+
# Don't run base authorizations for associations
|
14
|
+
before_action :authorize_base_action, if: -> {controller_name != "associations"}
|
14
15
|
|
15
16
|
def index
|
16
17
|
@page_title = @resource.plural_name.humanize
|
@@ -247,7 +248,11 @@ module Avo
|
|
247
248
|
end
|
248
249
|
|
249
250
|
def permitted_params
|
250
|
-
@resource.get_field_definitions.select(&:updatable).map(&:to_permitted_param)
|
251
|
+
@resource.get_field_definitions.select(&:updatable).map(&:to_permitted_param).concat extra_params
|
252
|
+
end
|
253
|
+
|
254
|
+
def extra_params
|
255
|
+
@resource.class.extra_params || []
|
251
256
|
end
|
252
257
|
|
253
258
|
def cast_nullable(params)
|
@@ -110,13 +110,15 @@ export default class extends Controller {
|
|
110
110
|
}
|
111
111
|
|
112
112
|
inputField(id = 'key', index, key, value) {
|
113
|
+
const inputValue = id === 'key' ? key : value
|
114
|
+
|
113
115
|
return `<input
|
114
116
|
class="${this.options.inputClasses} focus:bg-gray-100 !rounded-none border-gray-600 border-r border-l-0 border-b-0 border-t-0 focus:border-gray-300 w-1/2 focus:outline-none outline-none key-value-input-${id}"
|
115
117
|
data-action="input->key-value#${id}FieldUpdated"
|
116
118
|
placeholder="${this.options[`${id}_label`]}"
|
117
119
|
data-index="${index}"
|
118
120
|
${this[`${id}InputDisabled`] ? "disabled='disabled'" : ''}
|
119
|
-
value="${
|
121
|
+
value="${typeof inputValue === 'undefined' || inputValue === null ? '' : inputValue}"
|
120
122
|
/>`
|
121
123
|
}
|
122
124
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
2
|
+
import { enter, leave, toggle } from 'el-transition'
|
3
|
+
import Cookies from 'js-cookie'
|
4
|
+
|
5
|
+
export default class extends Controller {
|
6
|
+
static targets = ['sidebar', 'mobileSidebar', 'mainArea']
|
7
|
+
|
8
|
+
static values = {
|
9
|
+
open: Boolean,
|
10
|
+
}
|
11
|
+
|
12
|
+
get cookieKey() {
|
13
|
+
return `${window.Avo.configuration.cookies_key}.sidebar.open`
|
14
|
+
}
|
15
|
+
|
16
|
+
get sidebarOpen() {
|
17
|
+
return Cookies.get(this.cookieKey) === '1'
|
18
|
+
}
|
19
|
+
|
20
|
+
set cookie(state) {
|
21
|
+
Cookies.set(this.cookieKey, state === true ? 1 : 0)
|
22
|
+
}
|
23
|
+
|
24
|
+
markSidebarClosed() {
|
25
|
+
Cookies.set(this.cookieKey, '0')
|
26
|
+
this.openValue = false
|
27
|
+
leave(this.sidebarTarget)
|
28
|
+
this.mainAreaTarget.classList.remove('sidebar-open')
|
29
|
+
}
|
30
|
+
|
31
|
+
markSidebarOpen() {
|
32
|
+
Cookies.set(this.cookieKey, '1')
|
33
|
+
this.openValue = true
|
34
|
+
enter(this.sidebarTarget)
|
35
|
+
this.mainAreaTarget.classList.add('sidebar-open')
|
36
|
+
}
|
37
|
+
|
38
|
+
toggleSidebar() {
|
39
|
+
if (this.openValue) {
|
40
|
+
this.markSidebarClosed()
|
41
|
+
} else {
|
42
|
+
this.markSidebarOpen()
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
toggleSidebarOnMobile() {
|
47
|
+
toggle(this.mobileSidebarTarget)
|
48
|
+
}
|
49
|
+
}
|
@@ -16,7 +16,6 @@ import ItemSelectorController from './controllers/item_selector_controller'
|
|
16
16
|
import KeyValueController from './controllers/fields/key_value_controller'
|
17
17
|
import LoadingButtonController from './controllers/loading_button_controller'
|
18
18
|
import MenuController from './controllers/menu_controller'
|
19
|
-
import MobileController from './controllers/mobile_controller'
|
20
19
|
import ModalController from './controllers/modal_controller'
|
21
20
|
import MultipleSelectFilterController from './controllers/multiple_select_filter_controller'
|
22
21
|
import PerPageController from './controllers/per_page_controller'
|
@@ -26,6 +25,7 @@ import ResourceShowController from './controllers/resource_show_controller'
|
|
26
25
|
import SearchController from './controllers/search_controller'
|
27
26
|
import SelectController from './controllers/select_controller'
|
28
27
|
import SelectFilterController from './controllers/select_filter_controller'
|
28
|
+
import SidebarController from './controllers/sidebar_controller'
|
29
29
|
import SimpleMdeController from './controllers/fields/simple_mde_controller'
|
30
30
|
import TabsController from './controllers/tabs_controller'
|
31
31
|
import TagsFieldController from './controllers/fields/tags_field_controller'
|
@@ -46,7 +46,6 @@ application.register('item-select-all', ItemSelectAllController)
|
|
46
46
|
application.register('item-selector', ItemSelectorController)
|
47
47
|
application.register('loading-button', LoadingButtonController)
|
48
48
|
application.register('menu', MenuController)
|
49
|
-
application.register('mobile', MobileController)
|
50
49
|
application.register('modal', ModalController)
|
51
50
|
application.register('multiple-select-filter', MultipleSelectFilterController)
|
52
51
|
application.register('per-page', PerPageController)
|
@@ -56,6 +55,7 @@ application.register('resource-show', ResourceShowController)
|
|
56
55
|
application.register('search', SearchController)
|
57
56
|
application.register('select', SelectController)
|
58
57
|
application.register('select-filter', SelectFilterController)
|
58
|
+
application.register('sidebar', SidebarController)
|
59
59
|
application.register('tabs', TabsController)
|
60
60
|
application.register('tags-field', TagsFieldController)
|
61
61
|
application.register('text-filter', TextFilterController)
|
@@ -1,3 +1,9 @@
|
|
1
1
|
<%= render Avo::TurboFrameWrapperComponent.new(params[:turbo_frame]) do %>
|
2
|
-
<%= render Avo::Views::ResourceShowComponent.new(
|
2
|
+
<%= render Avo::Views::ResourceShowComponent.new(
|
3
|
+
resource: @resource,
|
4
|
+
reflection: @reflection,
|
5
|
+
actions: @actions,
|
6
|
+
parent_model: @parent_model,
|
7
|
+
parent_resource: @parent_resource,
|
8
|
+
) %>
|
3
9
|
<% end %>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<%= render Avo::TurboFrameWrapperComponent.new(params[:turbo_frame]) do %>
|
2
|
+
<%
|
3
|
+
classes = 'absolute inset-auto left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2'
|
4
|
+
label = t 'avo.failed_to_load'
|
5
|
+
%>
|
6
|
+
<div class="relative flex-1 py-12">
|
7
|
+
<div class="relative block text-gray-300 h-40 w-full">
|
8
|
+
<%= svg 'avocado', class: "#{classes} h-20 text-gray-400" %>
|
9
|
+
<%= svg 'code', class: "#{classes} h-8 -ml-20 -mt-12" %>
|
10
|
+
<%= svg 'fire', class: "#{classes} h-8 -ml-10 -mt-24" %>
|
11
|
+
<%= svg 'color-swatch', class: "#{classes} h-8 ml-8 -mt-24" %>
|
12
|
+
<%= svg 'globe', class: "#{classes} h-8 ml-20 -mt-12" %>
|
13
|
+
<%= svg 'library', class: "#{classes} h-8 -ml-20 mt-4" %>
|
14
|
+
<%= svg 'photograph', class: "#{classes} h-8 ml-20 mt-4" %>
|
15
|
+
</div>
|
16
|
+
<div class="relative block text-center text-lg text-gray-400 font-semibold -mt-10"><%= label %> <span class="border-b-2 border-dashed"><%= params[:turbo_frame].to_s.humanize.downcase if params[:turbo_frame].present? %></span> frame</div>
|
17
|
+
</div>
|
18
|
+
<% if Rails.env.development? %>
|
19
|
+
<div class="text-center text-sm w-full">
|
20
|
+
This is not an issue with Avo. Click <%= link_to 'this link', params[:src], target: :_blank %> to see why this frame failed to load.
|
21
|
+
</div>
|
22
|
+
<% end %>
|
23
|
+
<% end %>
|
@@ -3,21 +3,15 @@
|
|
3
3
|
classes = 'absolute inset-auto left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2'
|
4
4
|
label = t 'avo.failed_to_load'
|
5
5
|
%>
|
6
|
-
<div class="relative flex-1 py-
|
7
|
-
<div class="relative block text-gray-300 h-
|
8
|
-
<%= svg '
|
9
|
-
<%= svg 'code', class: "#{classes} h-8 -ml-20 -mt-12" %>
|
10
|
-
<%= svg 'fire', class: "#{classes} h-8 -ml-10 -mt-24" %>
|
11
|
-
<%= svg 'color-swatch', class: "#{classes} h-8 ml-8 -mt-24" %>
|
12
|
-
<%= svg 'globe', class: "#{classes} h-8 ml-20 -mt-12" %>
|
13
|
-
<%= svg 'library', class: "#{classes} h-8 -ml-20 mt-4" %>
|
14
|
-
<%= svg 'photograph', class: "#{classes} h-8 ml-20 mt-4" %>
|
6
|
+
<div class="relative flex-1 py-4">
|
7
|
+
<div class="relative block text-gray-300 h-64 w-full">
|
8
|
+
<%= svg 'failed_to_load', class: "#{classes} h-52 text-gray-400" %>
|
15
9
|
</div>
|
16
|
-
<div class="relative block text-center text-lg text-gray-400 font-semibold -
|
10
|
+
<div class="relative block text-center text-lg text-gray-400 font-semibold pb-6"><%= label %> <span class="border-b-2 border-dashed"><%= params[:turbo_frame].to_s.humanize.downcase if params[:turbo_frame].present? %></span> frame</div>
|
11
|
+
<% if Rails.env.development? %>
|
12
|
+
<div class="text-center text-sm w-full pb-3">
|
13
|
+
This is not an issue with Avo. Use <%= link_to 'this page', params[:src], target: :_blank %> to see why this frame failed to load.
|
14
|
+
</div>
|
15
|
+
<% end %>
|
17
16
|
</div>
|
18
|
-
<% if Rails.env.development? %>
|
19
|
-
<div class="text-center text-sm w-full">
|
20
|
-
This is not an issue with Avo. Click <%= link_to 'this link', params[:src], target: :_blank %> to see why this frame failed to load.
|
21
|
-
</div>
|
22
|
-
<% end %>
|
23
17
|
<% end %>
|
@@ -3,4 +3,5 @@
|
|
3
3
|
Avo.configuration.timezone = '<%= Avo.configuration.timezone %>'
|
4
4
|
Avo.configuration.root_path = '<%= root_path_without_url %>'
|
5
5
|
Avo.configuration.search_debounce = '<%= Avo.configuration.search_debounce %>'
|
6
|
+
Avo.configuration.cookies_key = '<%= Avo::COOKIES_KEY %>'
|
6
7
|
<% end %>
|
@@ -2,8 +2,11 @@
|
|
2
2
|
class="fixed bg-white p-2 w-full flex flex-shrink-0 items-center z-50 px-4 lg:px-4 border-b space-x-4 lg:space-x-0 h-16 <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>"
|
3
3
|
v-if="layout !== 'blank'"
|
4
4
|
>
|
5
|
-
<div class="flex items-center space-x-2
|
6
|
-
|
5
|
+
<div class="flex items-center space-x-2 w-auto lg:w-64 flex-shrink-0 h-full">
|
6
|
+
<div>
|
7
|
+
<%= a_button class: 'lg:hidden', icon: 'menu', size: :xs, compact: true, style: :text, data: { action: 'click->sidebar#toggleSidebarOnMobile' } %>
|
8
|
+
<%= a_button class: 'hidden lg:block', icon: 'menu', size: :xs, compact: true, style: :text, data: { action: 'click->sidebar#toggleSidebar' } %>
|
9
|
+
</div>
|
7
10
|
<%= render partial: "avo/partials/logo" %>
|
8
11
|
</div>
|
9
12
|
<div class="flex-1 flex items-center justify-between lg:justify-start space-x-2 sm:space-x-8 lg:pl-4">
|
@@ -1,9 +1,14 @@
|
|
1
1
|
<thead class="bg-white border-b border-gray-200 pb-1">
|
2
2
|
<% if @resource.record_selector %>
|
3
|
-
<th class="rounded-lg">
|
3
|
+
<th class="rounded-lg" data-control="item-select-th">
|
4
4
|
<%== item_select_all_input %>
|
5
5
|
</th>
|
6
6
|
<% end %>
|
7
|
+
<% if Avo.configuration.resource_controls_on_the_left? %>
|
8
|
+
<th class="w-24" data-control="resource-controls-th">
|
9
|
+
<!-- Item controls cell -->
|
10
|
+
</th>
|
11
|
+
<% end %>
|
7
12
|
<% fields.each_with_index do |field, index| %>
|
8
13
|
<%
|
9
14
|
if params[:sort_by] == field.id.to_s
|
@@ -39,7 +44,7 @@
|
|
39
44
|
""
|
40
45
|
end
|
41
46
|
%>
|
42
|
-
<th class="text-left uppercase px-3 py-2 whitespace-nowrap rounded-l">
|
47
|
+
<th class="text-left uppercase px-3 py-2 whitespace-nowrap rounded-l" data-control="resource-field-th">
|
43
48
|
<% if field.sortable %>
|
44
49
|
<%= link_to params.permit!.merge(sort_by: sort_by, sort_direction: sort_direction), class: "flex items-center #{classes} #{'cursor-pointer' if field.sortable}", 'data-turbo-frame': params[:turbo_frame] do %>
|
45
50
|
<%= field.name %>
|
@@ -52,7 +57,9 @@
|
|
52
57
|
<% end %>
|
53
58
|
</th>
|
54
59
|
<% end %>
|
55
|
-
|
56
|
-
|
57
|
-
|
60
|
+
<% if Avo.configuration.resource_controls_on_the_right? %>
|
61
|
+
<th class="w-24" data-control="resource-controls-th">
|
62
|
+
<!-- Item controls cell -->
|
63
|
+
</th>
|
64
|
+
<% end %>
|
58
65
|
</thead>
|
@@ -19,12 +19,17 @@
|
|
19
19
|
<% end %>
|
20
20
|
</head>
|
21
21
|
<body class="bg-gray-25 os-mac">
|
22
|
-
<div class="relative flex flex-1 w-full min-h-full" data-controller="
|
22
|
+
<div class="relative flex flex-1 w-full min-h-full" data-controller="sidebar" data-sidebar-open-value="<%= @sidebar_open %>">
|
23
23
|
<div class="flex-1 flex flex-col max-w-full">
|
24
24
|
<%= render partial: "avo/partials/navbar" %>
|
25
|
-
<div class="flex-1 flex pt-16 relative">
|
26
|
-
|
27
|
-
|
25
|
+
<div data-sidebar-target="mainArea" class="content-area flex-1 flex pt-16 relative <%= 'sidebar-open' if @sidebar_open %>">
|
26
|
+
<div class="hidden lg:flex">
|
27
|
+
<%= render Avo::SidebarComponent.new sidebar_open: @sidebar_open %>
|
28
|
+
</div>
|
29
|
+
<div class="flex lg:hidden">
|
30
|
+
<%= render Avo::SidebarComponent.new sidebar_open: false, for_mobile: true %>
|
31
|
+
</div>
|
32
|
+
<div class="main-content-area flex-1 flex flex-col min-h-full max-w-full">
|
28
33
|
<div class="content p-4 lg:p-6 flex-1 flex flex-col justify-between items-stretch <%= @container_classes %>">
|
29
34
|
<%= render partial: "avo/partials/custom_tools_alert" %>
|
30
35
|
<div class="flex flex-1 flex-col justify-between items-stretch space-y-8">
|
data/bin/init
CHANGED
@@ -28,6 +28,11 @@ app_root do
|
|
28
28
|
header 'Preparing the database'
|
29
29
|
run! 'bin/rails db:setup'
|
30
30
|
|
31
|
+
header 'Building assets'
|
32
|
+
run! 'yarn build:js'
|
33
|
+
run! 'yarn build:custom-js'
|
34
|
+
run! 'yarn build:css'
|
35
|
+
|
31
36
|
if use_docker == 'y'
|
32
37
|
header 'Stopping the Docker image'
|
33
38
|
run! 'docker-compose stop'
|
data/lib/avo/base_resource.rb
CHANGED
@@ -47,6 +47,7 @@ module Avo
|
|
47
47
|
class_attribute :after_update_path, default: :show
|
48
48
|
class_attribute :record_selector, default: true
|
49
49
|
class_attribute :keep_filters_panel_open, default: false
|
50
|
+
class_attribute :extra_params
|
50
51
|
|
51
52
|
class << self
|
52
53
|
delegate :t, to: ::I18n
|
@@ -251,7 +252,7 @@ module Avo
|
|
251
252
|
end
|
252
253
|
end
|
253
254
|
|
254
|
-
def fill_model(model, params)
|
255
|
+
def fill_model(model, params, extra_params: [])
|
255
256
|
# Map the received params to their actual fields
|
256
257
|
fields_by_database_id = get_field_definitions
|
257
258
|
.reject do |field|
|
@@ -262,6 +263,7 @@ module Avo
|
|
262
263
|
end
|
263
264
|
.to_h
|
264
265
|
|
266
|
+
# Write the field values
|
265
267
|
params.each do |key, value|
|
266
268
|
field = fields_by_database_id[key]
|
267
269
|
|
@@ -270,6 +272,19 @@ module Avo
|
|
270
272
|
model = field.fill_field model, key, value, params
|
271
273
|
end
|
272
274
|
|
275
|
+
# Write the user configured extra params to the model
|
276
|
+
if extra_params.present?
|
277
|
+
extra_params.each do |param_id|
|
278
|
+
# if it's a nested array, use the key
|
279
|
+
param_id = param_id.first.first if param_id.is_a? Hash
|
280
|
+
|
281
|
+
next unless @model.respond_to? "#{param_id}="
|
282
|
+
|
283
|
+
param_value = params[param_id]
|
284
|
+
@model.send("#{param_id}=", param_value)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
273
288
|
model
|
274
289
|
end
|
275
290
|
|
@@ -13,8 +13,6 @@ module Avo
|
|
13
13
|
end
|
14
14
|
|
15
15
|
class_methods do
|
16
|
-
delegate :tool, to: :items_holder
|
17
|
-
|
18
16
|
# DSL methods
|
19
17
|
def field(name, **args, &block)
|
20
18
|
ensure_items_holder_initialized
|
@@ -34,8 +32,14 @@ module Avo
|
|
34
32
|
self.items_holder.tabs Avo::TabGroupBuilder.parse_block(&block)
|
35
33
|
end
|
36
34
|
|
35
|
+
def tool(klass, **args)
|
36
|
+
ensure_items_holder_initialized
|
37
|
+
|
38
|
+
items_holder.tool klass, **args
|
39
|
+
end
|
40
|
+
|
37
41
|
def heading(body, **args)
|
38
|
-
self.items_holder.
|
42
|
+
self.items_holder.heading body, **args
|
39
43
|
end
|
40
44
|
# END DSL methods
|
41
45
|
|
@@ -252,9 +256,14 @@ module Avo
|
|
252
256
|
if item.respond_to? :visible_on?
|
253
257
|
next unless item.visible_on?(view)
|
254
258
|
end
|
259
|
+
# each field has it's own visibility checker
|
255
260
|
if item.respond_to? :visible?
|
256
261
|
next unless item.visible?
|
257
262
|
end
|
263
|
+
# check if the user is authorized to view it
|
264
|
+
if item.respond_to? :authorized?
|
265
|
+
next unless item.hydrate(model: @model).authorized?
|
266
|
+
end
|
258
267
|
|
259
268
|
if item.is_field?
|
260
269
|
if item.has_own_panel?
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Avo
|
2
|
+
class Configuration
|
3
|
+
module ResourceConfiguration
|
4
|
+
def resource_controls_placement=(val)
|
5
|
+
@resource_controls_placement_instance = val
|
6
|
+
end
|
7
|
+
|
8
|
+
def resource_controls_placement
|
9
|
+
@resource_controls_placement_instance || :right
|
10
|
+
end
|
11
|
+
|
12
|
+
def resource_controls_on_the_left?
|
13
|
+
resource_controls_placement == :left
|
14
|
+
end
|
15
|
+
|
16
|
+
def resource_controls_on_the_right?
|
17
|
+
resource_controls_placement == :right
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/avo/configuration.rb
CHANGED
@@ -78,6 +78,17 @@ module Avo
|
|
78
78
|
|
79
79
|
super view
|
80
80
|
end
|
81
|
+
|
82
|
+
def authorized?
|
83
|
+
method = "view_#{id}?".to_sym
|
84
|
+
service = resource.authorization
|
85
|
+
|
86
|
+
if service.has_method? method
|
87
|
+
service.authorize_action(method, raise_exception: false)
|
88
|
+
else
|
89
|
+
true
|
90
|
+
end
|
91
|
+
end
|
81
92
|
end
|
82
93
|
end
|
83
94
|
end
|
@@ -3,12 +3,14 @@ module Avo
|
|
3
3
|
class TextField < BaseField
|
4
4
|
attr_reader :link_to_resource
|
5
5
|
attr_reader :as_html
|
6
|
+
attr_reader :protocol
|
6
7
|
|
7
8
|
def initialize(id, **args, &block)
|
8
9
|
super(id, **args, &block)
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
add_boolean_prop args, :link_to_resource
|
12
|
+
add_boolean_prop args, :as_html
|
13
|
+
add_string_prop args, :protocol
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
data/lib/avo/items_holder.rb
CHANGED