avo 1.18.1 → 1.19.1.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 +5 -3
- data/Gemfile.lock +198 -169
- data/app/components/avo/fields/belongs_to_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/belongs_to_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/common/multiple_file_viewer_component.html.erb +1 -1
- data/app/components/avo/fields/common/single_file_viewer_component.html.erb +1 -2
- data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
- 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 +6 -1
- data/app/components/avo/fields/index_component.rb +2 -2
- data/app/components/avo/fields/text_field/index_component.html.erb +5 -1
- data/app/components/avo/fields/text_field/show_component.html.erb +5 -1
- data/app/components/avo/fields/trix_field/edit_component.html.erb +1 -1
- data/app/components/avo/index/grid_item_component.html.erb +4 -4
- data/app/components/avo/index/resource_controls_component.html.erb +1 -1
- data/app/components/avo/index/resource_controls_component.rb +23 -7
- data/app/components/avo/index/resource_table_component.html.erb +1 -1
- data/app/components/avo/panel_component.rb +3 -4
- data/app/components/avo/resource_component.rb +5 -1
- data/app/components/avo/views/resource_edit_component.html.erb +2 -2
- data/app/components/avo/views/resource_edit_component.rb +3 -3
- data/app/components/avo/views/resource_index_component.html.erb +2 -8
- data/app/components/avo/views/resource_index_component.rb +7 -15
- data/app/components/avo/views/resource_new_component.html.erb +2 -2
- data/app/components/avo/views/resource_new_component.rb +6 -2
- data/app/components/avo/views/resource_show_component.html.erb +5 -4
- data/app/components/avo/views/resource_show_component.rb +11 -6
- data/app/controllers/avo/actions_controller.rb +1 -1
- data/app/controllers/avo/application_controller.rb +4 -77
- data/app/controllers/avo/attachments_controller.rb +3 -2
- data/app/controllers/avo/base_controller.rb +30 -23
- data/app/controllers/avo/home_controller.rb +5 -1
- data/app/controllers/avo/relations_controller.rb +3 -3
- data/app/controllers/avo/search_controller.rb +1 -1
- data/app/helpers/avo/application_helper.rb +12 -0
- data/app/helpers/avo/resources_helper.rb +1 -1
- data/app/helpers/avo/url_helpers.rb +77 -0
- data/app/packs/entrypoints/application.css +1 -0
- data/app/packs/entrypoints/application.js +7 -0
- data/app/packs/js/controllers/loading_button_controller.js +22 -0
- data/app/packs/stylesheets/components/status.css +22 -15
- data/app/packs/stylesheets/spinner.css +49 -0
- data/app/views/avo/actions/show.html.erb +2 -2
- data/app/views/avo/base/_actions.html.erb +3 -3
- data/app/views/avo/base/_filters.html.erb +1 -1
- data/app/views/avo/home/failed_to_load.html.erb +3 -0
- data/app/views/avo/partials/_failed_state.html.erb +16 -0
- data/app/views/avo/partials/_paginator.html.erb +2 -2
- data/app/views/avo/partials/_profile_dropdown.html.erb +7 -5
- data/app/views/avo/relations/new.html.erb +0 -2
- data/app/views/avo/sidebar/_sidebar.html.erb +1 -1
- data/app/views/kaminari/_page.html.erb +1 -1
- data/config/routes.rb +7 -5
- data/db/factories.rb +9 -0
- data/lib/avo/app.rb +12 -12
- data/lib/avo/base_action.rb +9 -1
- data/lib/avo/base_resource.rb +41 -8
- data/lib/avo/configuration.rb +4 -0
- data/lib/avo/fields/base_field.rb +15 -4
- data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -19
- data/lib/avo/fields/has_base_field.rb +35 -0
- data/lib/avo/fields/has_many_field.rb +1 -19
- data/lib/avo/fields/has_one_field.rb +3 -19
- data/lib/avo/fields/key_value_field.rb +4 -4
- data/lib/avo/fields/text_field.rb +2 -0
- data/lib/avo/services/authorization_service.rb +8 -4
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/locales/avo.en.yml +12 -3
- data/lib/generators/avo/templates/locales/avo.ro.yml +7 -0
- data/public/avo-packs/css/{application-f9191617.css → application-c3b50b28.css} +54 -12
- data/public/avo-packs/css/application-c3b50b28.css.br +0 -0
- data/public/avo-packs/css/{application-f9191617.css.gz → application-c3b50b28.css.gz} +0 -0
- data/public/avo-packs/css/application-c3b50b28.css.map +1 -0
- data/public/avo-packs/css/application-c3b50b28.css.map.br +0 -0
- data/public/avo-packs/css/application-c3b50b28.css.map.gz +0 -0
- data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js +2 -0
- data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.br +0 -0
- data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.gz +0 -0
- data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map +1 -0
- data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map.br +0 -0
- data/public/avo-packs/js/actioncable-7119dbc1a908641fb263.chunk.js.map.gz +0 -0
- data/public/avo-packs/js/application-6fc968cfa52976c4582b.js +26 -0
- data/public/avo-packs/js/{application-cc89f096028eb1d4d971.js.LICENSE.txt → application-6fc968cfa52976c4582b.js.LICENSE.txt} +0 -0
- data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.br +0 -0
- data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.gz +0 -0
- data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map +1 -0
- data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map.br +0 -0
- data/public/avo-packs/js/application-6fc968cfa52976c4582b.js.map.gz +0 -0
- data/public/avo-packs/manifest.json +21 -21
- metadata +30 -24
- data/public/avo-packs/css/application-f9191617.css.br +0 -0
- data/public/avo-packs/css/application-f9191617.css.map +0 -1
- data/public/avo-packs/css/application-f9191617.css.map.br +0 -0
- data/public/avo-packs/css/application-f9191617.css.map.gz +0 -0
- data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js +0 -2
- data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.br +0 -0
- data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.gz +0 -0
- data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.map +0 -1
- data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.map.br +0 -0
- data/public/avo-packs/js/219-9aa2b689f44613118203.chunk.js.map.gz +0 -0
- data/public/avo-packs/js/application-cc89f096028eb1d4d971.js +0 -26
- data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.br +0 -0
- data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.gz +0 -0
- data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.map +0 -1
- data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.map.br +0 -0
- data/public/avo-packs/js/application-cc89f096028eb1d4d971.js.map.gz +0 -0
@@ -5,12 +5,13 @@ module Avo
|
|
5
5
|
before_action :set_resource_name
|
6
6
|
before_action :set_resource
|
7
7
|
before_action :hydrate_resource
|
8
|
-
before_action :authorize_action
|
9
8
|
before_action :set_model, only: [:show, :edit, :destroy, :update]
|
9
|
+
before_action :authorize_action
|
10
10
|
before_action :reset_pagination_if_filters_changed, only: :index
|
11
11
|
before_action :cache_applied_filters, only: :index
|
12
12
|
|
13
13
|
def index
|
14
|
+
@view = :index
|
14
15
|
@page_title = resource_name.humanize
|
15
16
|
add_breadcrumb resource_name.humanize
|
16
17
|
|
@@ -58,6 +59,7 @@ module Avo
|
|
58
59
|
end
|
59
60
|
|
60
61
|
def show
|
62
|
+
@view = :show
|
61
63
|
set_actions
|
62
64
|
|
63
65
|
@resource = @resource.hydrate(model: @model, view: :show, user: _current_user, params: params)
|
@@ -70,25 +72,27 @@ module Avo
|
|
70
72
|
via_model = via_resource.class.find_scope.find params[:via_resource_id]
|
71
73
|
via_resource.hydrate model: via_model
|
72
74
|
|
73
|
-
add_breadcrumb via_resource.plural_name, resources_path(via_resource
|
74
|
-
add_breadcrumb via_resource.model_title, resource_path(via_model)
|
75
|
+
add_breadcrumb via_resource.plural_name, resources_path(resource: via_resource)
|
76
|
+
add_breadcrumb via_resource.model_title, resource_path(model: via_model, resource: via_resource)
|
75
77
|
else
|
76
|
-
add_breadcrumb resource_name.humanize, resources_path(@resource
|
78
|
+
add_breadcrumb resource_name.humanize, resources_path(resource: @resource)
|
77
79
|
end
|
78
80
|
|
79
81
|
add_breadcrumb @resource.model_title
|
80
82
|
end
|
81
83
|
|
82
84
|
def new
|
85
|
+
@view = :new
|
83
86
|
@model = @resource.model_class.new
|
84
87
|
@resource = @resource.hydrate(model: @model, view: :new, user: _current_user)
|
85
88
|
|
86
89
|
@page_title = @resource.default_panel_name
|
87
|
-
add_breadcrumb resource_name.humanize, resources_path(@resource
|
90
|
+
add_breadcrumb resource_name.humanize, resources_path(resource: @resource)
|
88
91
|
add_breadcrumb t("avo.new").humanize
|
89
92
|
end
|
90
93
|
|
91
94
|
def edit
|
95
|
+
@view = :edit
|
92
96
|
@resource = @resource.hydrate(model: @model, view: :edit, user: _current_user)
|
93
97
|
|
94
98
|
@page_title = @resource.default_panel_name
|
@@ -99,13 +103,13 @@ module Avo
|
|
99
103
|
via_model = via_resource.class.find_scope.find params[:via_resource_id]
|
100
104
|
via_resource.hydrate model: via_model
|
101
105
|
|
102
|
-
add_breadcrumb via_resource.plural_name, resources_path(
|
103
|
-
add_breadcrumb via_resource.model_title, resource_path(via_model)
|
106
|
+
add_breadcrumb via_resource.plural_name, resources_path(resource: @resource)
|
107
|
+
add_breadcrumb via_resource.model_title, resource_path(model: via_model, resource: via_resource)
|
104
108
|
else
|
105
|
-
add_breadcrumb resource_name.humanize, resources_path(@resource
|
109
|
+
add_breadcrumb resource_name.humanize, resources_path(resource: @resource)
|
106
110
|
end
|
107
111
|
|
108
|
-
add_breadcrumb @resource.model_title, resource_path(@resource.model)
|
112
|
+
add_breadcrumb @resource.model_title, resource_path(model: @resource.model, resource: @resource)
|
109
113
|
add_breadcrumb t("avo.edit").humanize
|
110
114
|
end
|
111
115
|
|
@@ -117,12 +121,13 @@ module Avo
|
|
117
121
|
respond_to do |format|
|
118
122
|
if saved
|
119
123
|
redirect_path = if params[:via_relation_class].present? && params[:via_resource_id].present?
|
120
|
-
|
124
|
+
parent_resource = ::Avo::App.get_resource_by_model_name params[:via_relation_class].safe_constantize
|
125
|
+
resource_path(model: params[:via_relation_class].safe_constantize, resource: parent_resource, resource_id: params[:via_resource_id])
|
121
126
|
else
|
122
|
-
resource_path(@model)
|
127
|
+
resource_path(model: @model, resource: @resource)
|
123
128
|
end
|
124
129
|
|
125
|
-
format.html { redirect_to redirect_path, notice: "#{@model.class.name}
|
130
|
+
format.html { redirect_to redirect_path, notice: "#{@model.class.name} #{t("avo.was_successfully_created")}." }
|
126
131
|
format.json { render :show, status: :created, location: @model }
|
127
132
|
else
|
128
133
|
flash[:error] = t "avo.you_missed_something_check_form"
|
@@ -139,7 +144,7 @@ module Avo
|
|
139
144
|
|
140
145
|
respond_to do |format|
|
141
146
|
if saved
|
142
|
-
format.html { redirect_to params[:referrer] || resource_path(@model), notice: "#{@model.class.name}
|
147
|
+
format.html { redirect_to params[:referrer] || resource_path(model: @model, resource: @resource), notice: "#{@model.class.name} #{t("avo.was_successfully_updated")}." }
|
143
148
|
format.json { render :show, status: :ok, location: @model }
|
144
149
|
else
|
145
150
|
flash[:error] = t "avo.you_missed_something_check_form"
|
@@ -153,19 +158,17 @@ module Avo
|
|
153
158
|
@model.destroy!
|
154
159
|
|
155
160
|
respond_to do |format|
|
156
|
-
format.html { redirect_to params[:referrer] || resources_path(@
|
161
|
+
format.html { redirect_to params[:referrer] || resources_path(resource: @resource, turbo_frame: params[:turbo_frame], view_type: params[:view_type]), notice: t("avo.resource_destroyed", attachment_class: @attachment_class) }
|
157
162
|
format.json { head :no_content }
|
158
163
|
end
|
159
164
|
end
|
160
165
|
|
161
166
|
private
|
162
167
|
|
163
|
-
def model_route_key
|
164
|
-
singular_name @resource.model_class
|
165
|
-
end
|
166
|
-
|
167
168
|
def model_params
|
168
|
-
|
169
|
+
model_param_key = @resource.singular_model_key
|
170
|
+
|
171
|
+
request_params = params.require(model_param_key).permit(permitted_params)
|
169
172
|
|
170
173
|
if @resource.devise_password_optional && request_params[:password].blank? && request_params[:password_confirmation].blank?
|
171
174
|
request_params.delete(:password_confirmation)
|
@@ -248,9 +251,13 @@ module Avo
|
|
248
251
|
model = @resource.class.find_scope.find params[:resource_id]
|
249
252
|
end
|
250
253
|
|
251
|
-
@actions =
|
252
|
-
|
253
|
-
|
254
|
+
@actions =
|
255
|
+
@resource
|
256
|
+
.get_actions
|
257
|
+
.map do |action|
|
258
|
+
action.new(model: model, resource: @resource, view: @view)
|
259
|
+
end
|
260
|
+
.select { |action| action.visible_in_view }
|
254
261
|
end
|
255
262
|
|
256
263
|
def applied_filters
|
@@ -282,7 +289,7 @@ module Avo
|
|
282
289
|
end
|
283
290
|
|
284
291
|
def applied_filters_cache_key
|
285
|
-
"avo.base_controller.#{@resource.
|
292
|
+
"avo.base_controller.#{@resource.model_key}.applied_filters"
|
286
293
|
end
|
287
294
|
end
|
288
295
|
end
|
@@ -7,8 +7,12 @@ module Avo
|
|
7
7
|
redirect_to Avo.configuration.home_path
|
8
8
|
elsif !Rails.env.development?
|
9
9
|
@page_title = "Get started"
|
10
|
-
|
10
|
+
resource = Avo::App.resources.min_by { |resource| resource.model_key }
|
11
|
+
redirect_to resources_path(resource: resource)
|
11
12
|
end
|
12
13
|
end
|
14
|
+
|
15
|
+
def failed_to_load
|
16
|
+
end
|
13
17
|
end
|
14
18
|
end
|
@@ -48,8 +48,8 @@ module Avo
|
|
48
48
|
|
49
49
|
respond_to do |format|
|
50
50
|
if @model.save
|
51
|
-
format.html { redirect_to resource_path(@model), notice: t("avo.attachment_class_attached", attachment_class: @attachment_class) }
|
52
|
-
format.json { render :show, status: :created, location: resource_path(@model) }
|
51
|
+
format.html { redirect_to resource_path(model: @model, resource: @resource), notice: t("avo.attachment_class_attached", attachment_class: @attachment_class) }
|
52
|
+
format.json { render :show, status: :created, location: resource_path(model: @model, resource: @resource) }
|
53
53
|
else
|
54
54
|
format.html { render :new }
|
55
55
|
format.json { render json: @model.errors, status: :unprocessable_entity }
|
@@ -65,7 +65,7 @@ module Avo
|
|
65
65
|
end
|
66
66
|
|
67
67
|
respond_to do |format|
|
68
|
-
format.html { redirect_to params[:referrer] || resource_path(@model), notice: t("avo.attachment_class_detached", attachment_class: @attachment_class) }
|
68
|
+
format.html { redirect_to params[:referrer] || resource_path(model: @model, resource: @resource), notice: t("avo.attachment_class_detached", attachment_class: @attachment_class) }
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -39,6 +39,10 @@ module Avo
|
|
39
39
|
|
40
40
|
def a_button(label = nil, **args, &block)
|
41
41
|
args[:class] = button_classes(args[:class], color: args[:color], variant: args[:variant], size: args[:size])
|
42
|
+
if args[:spinner]
|
43
|
+
args["data-controller"] = "loading-button"
|
44
|
+
# args["data-action"] = "click->loading-button#onClick"
|
45
|
+
end
|
42
46
|
|
43
47
|
locals = {
|
44
48
|
label: label,
|
@@ -154,5 +158,13 @@ module Avo
|
|
154
158
|
|
155
159
|
classes
|
156
160
|
end
|
161
|
+
|
162
|
+
def get_model_class(model)
|
163
|
+
if model.instance_of?(Class)
|
164
|
+
model
|
165
|
+
else
|
166
|
+
model.class
|
167
|
+
end
|
168
|
+
end
|
157
169
|
end
|
158
170
|
end
|
@@ -42,7 +42,7 @@ module Avo
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def item_selector_init(resource)
|
45
|
-
"data-resource-name='#{resource.
|
45
|
+
"data-resource-name='#{resource.model_key}' data-resource-id='#{resource.model.id}' data-controller='item-selector'"
|
46
46
|
end
|
47
47
|
|
48
48
|
def item_selector_input(floating: false, size: :md)
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Avo
|
2
|
+
module UrlHelpers
|
3
|
+
def resources_path(resource:, keep_query_params: false, **args)
|
4
|
+
return if resource.nil?
|
5
|
+
|
6
|
+
existing_params = {}
|
7
|
+
begin
|
8
|
+
if keep_query_params
|
9
|
+
existing_params =
|
10
|
+
Addressable::URI.parse(request.fullpath).query_values.symbolize_keys
|
11
|
+
end
|
12
|
+
rescue
|
13
|
+
end
|
14
|
+
|
15
|
+
# This entry uses `route_key` instead of `model_key` because it's rails that needs `fish_index` to build the correct path
|
16
|
+
avo.send :"resources_#{resource.route_key}_path", **existing_params, **args
|
17
|
+
end
|
18
|
+
|
19
|
+
def resource_path(
|
20
|
+
model:,
|
21
|
+
resource:,
|
22
|
+
resource_id: nil,
|
23
|
+
keep_query_params: false,
|
24
|
+
**args
|
25
|
+
)
|
26
|
+
if model.respond_to? :id
|
27
|
+
id = model
|
28
|
+
elsif resource_id.present?
|
29
|
+
id = resource_id
|
30
|
+
end
|
31
|
+
|
32
|
+
avo.send :"resources_#{resource.singular_model_key}_path", id, **args
|
33
|
+
end
|
34
|
+
|
35
|
+
def new_resource_path(model:, resource:, **args)
|
36
|
+
avo.send :"new_resources_#{resource.singular_model_key}_path", **args
|
37
|
+
end
|
38
|
+
|
39
|
+
def edit_resource_path(model:, resource:, **args)
|
40
|
+
avo.send :"edit_resources_#{resource.singular_model_key}_path", model, **args
|
41
|
+
end
|
42
|
+
|
43
|
+
def resource_attach_path(resource, model_id, related_name, related_id = nil)
|
44
|
+
helpers.avo.resources_associations_new_path(resource.singular_model_key, model_id, related_name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def resource_detach_path(
|
48
|
+
model_name, # teams
|
49
|
+
model_id, # 1
|
50
|
+
related_name, # admin
|
51
|
+
related_id = nil
|
52
|
+
)
|
53
|
+
avo.resources_associations_destroy_path(model_name, model_id, related_name, related_id)
|
54
|
+
end
|
55
|
+
|
56
|
+
def related_resources_path(
|
57
|
+
parent_model,
|
58
|
+
model,
|
59
|
+
keep_query_params: false,
|
60
|
+
**args
|
61
|
+
)
|
62
|
+
return if model.nil?
|
63
|
+
|
64
|
+
existing_params = {}
|
65
|
+
|
66
|
+
begin
|
67
|
+
if keep_query_params
|
68
|
+
existing_params =
|
69
|
+
Addressable::URI.parse(request.fullpath).query_values.symbolize_keys
|
70
|
+
end
|
71
|
+
rescue
|
72
|
+
end
|
73
|
+
|
74
|
+
avo.resources_associations_index_path(@parent_resource.model_class.model_name.route_key, @parent_resource.model.id, **existing_params, **args )
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -17,6 +17,7 @@
|
|
17
17
|
@import './../stylesheets/breadcrumbs.css';
|
18
18
|
@import './../stylesheets/search.css';
|
19
19
|
@import './../stylesheets/active-storage.css';
|
20
|
+
@import './../stylesheets/spinner.css';
|
20
21
|
|
21
22
|
@import './../stylesheets/components/status.css';
|
22
23
|
@import './../stylesheets/components/code.css';
|
@@ -46,6 +46,13 @@ document.addEventListener('turbo:load', () => {
|
|
46
46
|
document.body.classList.remove('turbo-loading')
|
47
47
|
initTippy()
|
48
48
|
})
|
49
|
+
|
50
|
+
document.addEventListener('turbo:before-fetch-response', (e) => {
|
51
|
+
if (e.detail.fetchResponse.response.status === 500) {
|
52
|
+
const id = e.srcElement.getAttribute('id')
|
53
|
+
e.srcElement.src = `${window.Avo.configuration.root_path}/failed_to_load?turbo_frame=${id}`
|
54
|
+
}
|
55
|
+
})
|
49
56
|
document.addEventListener('turbo:visit', () => document.body.classList.add('turbo-loading'))
|
50
57
|
document.addEventListener('turbo:submit-start', () => document.body.classList.add('turbo-loading'))
|
51
58
|
document.addEventListener('turbo:before-cache', () => {
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { Controller } from 'stimulus'
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
spinnerMarkup = `<div class="button-spinner">
|
5
|
+
<div class="double-bounce1"></div>
|
6
|
+
<div class="double-bounce2"></div>
|
7
|
+
</div>`;
|
8
|
+
|
9
|
+
connect() {
|
10
|
+
const button = this.context.scope.element
|
11
|
+
this.context.scope.element.addEventListener('click', () => {
|
12
|
+
button.style.width = `${button.getBoundingClientRect().width}px`
|
13
|
+
button.style.height = `${button.getBoundingClientRect().height}px`
|
14
|
+
button.innerHTML = this.spinnerMarkup
|
15
|
+
button.classList.add('justify-center')
|
16
|
+
|
17
|
+
setTimeout(() => {
|
18
|
+
button.setAttribute('disabled', 'disabled')
|
19
|
+
}, 1)
|
20
|
+
})
|
21
|
+
}
|
22
|
+
}
|
@@ -5,8 +5,8 @@
|
|
5
5
|
position: relative;
|
6
6
|
}
|
7
7
|
|
8
|
-
|
9
|
-
.
|
8
|
+
.spinner .double-bounce1,
|
9
|
+
.spinner .double-bounce2 {
|
10
10
|
width: 100%;
|
11
11
|
height: 100%;
|
12
12
|
border-radius: 50%;
|
@@ -16,26 +16,33 @@
|
|
16
16
|
top: 0;
|
17
17
|
left: 0;
|
18
18
|
|
19
|
-
-webkit-animation: sk-bounce
|
20
|
-
animation: sk-bounce
|
19
|
+
-webkit-animation: sk-bounce 2s infinite ease-in-out;
|
20
|
+
animation: sk-bounce 2s infinite ease-in-out;
|
21
21
|
}
|
22
22
|
|
23
|
-
.double-bounce2 {
|
24
|
-
-webkit-animation-delay: -
|
25
|
-
animation-delay: -
|
23
|
+
.spinner .double-bounce2 {
|
24
|
+
-webkit-animation-delay: -1s;
|
25
|
+
animation-delay: -1s;
|
26
26
|
}
|
27
27
|
|
28
28
|
@-webkit-keyframes sk-bounce {
|
29
|
-
0%,
|
30
|
-
|
29
|
+
0%,
|
30
|
+
100% {
|
31
|
+
-webkit-transform: scale(0);
|
32
|
+
}
|
33
|
+
50% {
|
34
|
+
-webkit-transform: scale(1);
|
35
|
+
}
|
31
36
|
}
|
32
37
|
|
33
38
|
@keyframes sk-bounce {
|
34
|
-
0%,
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
0%,
|
40
|
+
100% {
|
41
|
+
transform: scale(0);
|
42
|
+
-webkit-transform: scale(0);
|
43
|
+
}
|
44
|
+
50% {
|
45
|
+
transform: scale(1);
|
46
|
+
-webkit-transform: scale(1);
|
40
47
|
}
|
41
48
|
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
.button-spinner {
|
2
|
+
width: 24px;
|
3
|
+
height: 24px;
|
4
|
+
|
5
|
+
position: relative;
|
6
|
+
margin: 100px auto;
|
7
|
+
}
|
8
|
+
|
9
|
+
.button-spinner > .double-bounce1,
|
10
|
+
.button-spinner > .double-bounce2 {
|
11
|
+
width: 100%;
|
12
|
+
height: 100%;
|
13
|
+
border-radius: 50%;
|
14
|
+
background-color: #333;
|
15
|
+
opacity: 0.5;
|
16
|
+
position: absolute;
|
17
|
+
top: 0;
|
18
|
+
left: 0;
|
19
|
+
|
20
|
+
-webkit-animation: sk-bounce 2s infinite ease-in-out;
|
21
|
+
animation: sk-bounce 2s infinite ease-in-out;
|
22
|
+
}
|
23
|
+
|
24
|
+
.button-spinner > .double-bounce2 {
|
25
|
+
-webkit-animation-delay: -1s;
|
26
|
+
animation-delay: -1s;
|
27
|
+
}
|
28
|
+
|
29
|
+
@-webkit-keyframes sk-bounce {
|
30
|
+
0%,
|
31
|
+
100% {
|
32
|
+
-webkit-transform: scale(0);
|
33
|
+
}
|
34
|
+
50% {
|
35
|
+
-webkit-transform: scale(1);
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
@keyframes sk-bounce {
|
40
|
+
0%,
|
41
|
+
100% {
|
42
|
+
transform: scale(0);
|
43
|
+
-webkit-transform: scale(0);
|
44
|
+
}
|
45
|
+
50% {
|
46
|
+
transform: scale(1);
|
47
|
+
-webkit-transform: scale(1);
|
48
|
+
}
|
49
|
+
}
|
@@ -3,11 +3,11 @@
|
|
3
3
|
data-controller="action"
|
4
4
|
data-no-confirmation="<%= @action.no_confirmation %>"
|
5
5
|
data-action-target="controllerDiv"
|
6
|
-
data-resource-name="<%= @resource.
|
6
|
+
data-resource-name="<%= @resource.model_key %>"
|
7
7
|
data-resource-id="<%= params[:id] %>"
|
8
8
|
class="hidden text-blue-gray-800"
|
9
9
|
>
|
10
|
-
<%= form_with model: @model, scope: 'fields', url: "#{
|
10
|
+
<%= form_with model: @model, scope: 'fields', url: "#{@resource.records_path}/actions/#{@action.param_id}", data: {'turbo-frame': '_top', 'action-target': 'form'} do |form| %>
|
11
11
|
<%= render Avo::ModalComponent.new do |c| %>
|
12
12
|
<% c.heading do %>
|
13
13
|
<%= @action.action_name %>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<%= a_button class: "focus:outline-none",
|
4
4
|
color: 'light-blue',
|
5
5
|
'data-action': "click->toggle-panel#togglePanel",
|
6
|
-
'data-actions-dropdown-button': @resource.
|
6
|
+
'data-actions-dropdown-button': @resource.model_key do
|
7
7
|
%>
|
8
8
|
<%= svg 'arrow-left', class: 'h-4 mr-1 transform -rotate-90' %> <%= t 'avo.actions' %>
|
9
9
|
<% end %>
|
@@ -14,8 +14,8 @@
|
|
14
14
|
<%
|
15
15
|
@actions.each_with_index do |action, index|
|
16
16
|
path = action_name == 'show' ?
|
17
|
-
"#{
|
18
|
-
"#{
|
17
|
+
"#{@resource.record_path}/actions/#{action.param_id}" :
|
18
|
+
"#{@resource.records_path}/actions/#{action.param_id}"
|
19
19
|
if action_name == 'show' || action.standalone
|
20
20
|
disabled = false
|
21
21
|
else
|
@@ -24,7 +24,7 @@
|
|
24
24
|
|
25
25
|
<div class="p-4 border-gray-300 border-t">
|
26
26
|
<% if params[:filters].present? %>
|
27
|
-
<%= a_link t('avo.reset_filters'), resources_path(@resource
|
27
|
+
<%= a_link t('avo.reset_filters'), resources_path(resource: @resource, filters: nil, keep_query_params: true), color: 'blue-gray', class: 'w-full justify-center' %>
|
28
28
|
<% else %>
|
29
29
|
<%= a_button t('avo.reset_filters'), color: 'blue-gray', class: 'w-full justify-center', disabled: true %>
|
30
30
|
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<%
|
2
|
+
classes = 'absolute inset-auto left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2'
|
3
|
+
label = t 'avo.failed_to_load'
|
4
|
+
%>
|
5
|
+
<div class="relative flex-1 py-12">
|
6
|
+
<div class="relative block text-gray-300 h-40 w-full">
|
7
|
+
<%= svg 'avocado', class: "#{classes} h-20 text-gray-400" %>
|
8
|
+
<%= svg 'code', class: "#{classes} h-8 -ml-20 -mt-12" %>
|
9
|
+
<%= svg 'fire', class: "#{classes} h-8 -ml-10 -mt-24" %>
|
10
|
+
<%= svg 'color-swatch', class: "#{classes} h-8 ml-8 -mt-24" %>
|
11
|
+
<%= svg 'globe', class: "#{classes} h-8 ml-20 -mt-12" %>
|
12
|
+
<%= svg 'library', class: "#{classes} h-8 -ml-20 mt-4" %>
|
13
|
+
<%= svg 'photograph', class: "#{classes} h-8 ml-20 mt-4" %>
|
14
|
+
</div>
|
15
|
+
<div class="relative block text-center text-lg text-gray-400 font-semibold -mt-10"><%= label %> <%= params[:turbo_frame].to_s.humanize.downcase if params[:turbo_frame].present? %></div>
|
16
|
+
</div>
|
@@ -29,9 +29,9 @@
|
|
29
29
|
|
30
30
|
<% per_page_options.each do |option| %>
|
31
31
|
<% if @parent_resource.present? %>
|
32
|
-
<%= link_to "Change to #{option} items per page", related_resources_path(@parent_resource.
|
32
|
+
<%= link_to "Change to #{option} items per page", related_resources_path(@parent_resource.model_class, @resource.model_class, per_page: option, keep_query_params: true), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
|
33
33
|
<% else %>
|
34
|
-
<%= link_to "Change to #{option} items per page", resources_path(@resource
|
34
|
+
<%= link_to "Change to #{option} items per page", resources_path(resource: @resource, per_page: option, keep_query_params: true), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
|
35
35
|
<% end %>
|
36
36
|
<% end %>
|
37
37
|
</div>
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
<% destroy_user_session_path = "destroy_#{Avo.configuration.current_user_resource_name}_session_path".to_sym %>
|
2
|
+
|
3
|
+
<div <% if main_app.respond_to?(destroy_user_session_path) %> data-controller="toggle-panel" <% end %>>
|
2
4
|
<a href="javascript:void(0);" class="flex items-center cursor-pointer font-semibold text-gray-700" data-action="click->toggle-panel#togglePanel">
|
3
5
|
<% if _current_user.respond_to?(:avatar) && _current_user.avatar.present? %>
|
4
6
|
<%= image_tag _current_user.avatar, class: "h-12 rounded-full border-4 border-white mr-1" %>
|
@@ -10,14 +12,14 @@
|
|
10
12
|
<% else %>
|
11
13
|
Avo user
|
12
14
|
<% end %>
|
13
|
-
<% if main_app.respond_to?(
|
15
|
+
<% if main_app.respond_to?(destroy_user_session_path) %>
|
14
16
|
<%= svg 'chevron-down', class: "ml-1 h-4" %>
|
15
17
|
<% end %>
|
16
18
|
</a>
|
17
19
|
|
18
|
-
<% if main_app.respond_to?(
|
19
|
-
<div class="hidden absolute inset-auto
|
20
|
-
<%= button_to t('avo.sign_out'), main_app.destroy_user_session_path, method: :delete, form: { "data-turbo" => "false" }, class: "appearance-none bg-white text-left cursor-pointer text-green-600 font-semibold hover:text-white hover:bg-green-500 block px-4 py-1 w-full" %>
|
20
|
+
<% if main_app.respond_to?(destroy_user_session_path) %>
|
21
|
+
<div class="hidden absolute inset-auto right-0 mr-6 mt-0 py-4 bg-white rounded-xl min-w-[200px] shadow-context" data-toggle-panel-target="panel">
|
22
|
+
<%= button_to t('avo.sign_out'), main_app.send(:destroy_user_session_path), method: :delete, form: { "data-turbo" => "false" }, class: "appearance-none bg-white text-left cursor-pointer text-green-600 font-semibold hover:text-white hover:bg-green-500 block px-4 py-1 w-full" %>
|
21
23
|
</div>
|
22
24
|
<% end %>
|
23
25
|
</div>
|
@@ -22,8 +22,6 @@
|
|
22
22
|
</div>
|
23
23
|
</div>
|
24
24
|
|
25
|
-
<%#= form.hidden_field :resource_ids, value: params[:resource_ids], 'data-action-target': 'resourceIds' %>
|
26
|
-
|
27
25
|
<% c.controls do %>
|
28
26
|
<%= a_button t('avo.cancel'), 'data-action': 'click->modal#close', size: :sm %>
|
29
27
|
<%= a_button t('avo.attach'), type: :submit, color: :green, size: :sm %>
|
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
<div class="w-full">
|
14
14
|
<% Avo::App.resources_navigation(_current_user).sort_by { |r| r.navigation_label }.each do |resource| %>
|
15
|
-
<%= render Avo::NavigationLinkComponent.new label: resource.navigation_label, path: resources_path(resource
|
15
|
+
<%= render Avo::NavigationLinkComponent.new label: resource.navigation_label, path: resources_path(resource: resource) %>
|
16
16
|
<% end %>
|
17
17
|
|
18
18
|
<% sidebar_partials = Avo::App.get_sidebar_partials %>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<% url = resources_path(@resource
|
1
|
+
<% url = resources_path(resource: @resource, page: page, keep_query_params: true) %>
|
2
2
|
<% if page.current? %>
|
3
3
|
<button type="button" class="hidden md:inline-flex -ml-px relative items-center px-4 py-2 border bg-gray-100 text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 z-10 outline-none border-primary-300 active:bg-gray-100 transition ease-in-out duration-150">
|
4
4
|
<%= page %>
|
data/config/routes.rb
CHANGED
@@ -10,6 +10,8 @@ Avo::Engine.routes.draw do
|
|
10
10
|
post "/resources/:resource_name/:id/attachments/", to: "attachments#create"
|
11
11
|
end
|
12
12
|
|
13
|
+
get "failed_to_load", to: "home#failed_to_load"
|
14
|
+
|
13
15
|
scope "resources", as: "resources" do
|
14
16
|
# Attachments
|
15
17
|
get "/:resource_name/:id/active_storage_attachments/:attachment_name/:signed_attachment_id", to: "attachments#show"
|
@@ -24,10 +26,10 @@ Avo::Engine.routes.draw do
|
|
24
26
|
instance_eval(&Avo::App.draw_routes)
|
25
27
|
|
26
28
|
# Relations
|
27
|
-
get "/:resource_name/:id/:related_name/new", to: "relations#new"
|
28
|
-
get "/:resource_name/:id/:related_name/", to: "relations#index"
|
29
|
-
get "/:resource_name/:id/:related_name/:related_id", to: "relations#show"
|
30
|
-
post "/:resource_name/:id/:related_name", to: "relations#create"
|
31
|
-
delete "/:resource_name/:id/:related_name/:related_id", to: "relations#destroy"
|
29
|
+
get "/:resource_name/:id/:related_name/new", to: "relations#new", as: "associations_new"
|
30
|
+
get "/:resource_name/:id/:related_name/", to: "relations#index", as: "associations_index"
|
31
|
+
get "/:resource_name/:id/:related_name/:related_id", to: "relations#show", as: "associations_show"
|
32
|
+
post "/:resource_name/:id/:related_name", to: "relations#create", as: "associations_create"
|
33
|
+
delete "/:resource_name/:id/:related_name/:related_id", to: "relations#destroy", as: "associations_destroy"
|
32
34
|
end
|
33
35
|
end
|
data/db/factories.rb
CHANGED
@@ -44,4 +44,13 @@ FactoryBot.define do
|
|
44
44
|
factory :comment do
|
45
45
|
body { Faker::Lorem.paragraphs(number: rand(4...10)).join("\n") }
|
46
46
|
end
|
47
|
+
|
48
|
+
factory :person do
|
49
|
+
name { "#{Faker::Name.first_name} #{Faker::Name.last_name}" }
|
50
|
+
end
|
51
|
+
|
52
|
+
factory :spouse do
|
53
|
+
name { "#{Faker::Name.first_name} #{Faker::Name.last_name}" }
|
54
|
+
type { "Spouse" }
|
55
|
+
end
|
47
56
|
end
|