avo 1.22.2 → 1.23.0
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/README.md +6 -0
- data/app/{views/avo/partials/_alert.html.erb → components/avo/alert_component.html.erb} +0 -0
- data/app/components/avo/alert_component.rb +11 -0
- data/app/components/avo/alerts_component.html.erb +3 -0
- data/app/components/avo/alerts_component.rb +5 -0
- data/app/components/avo/navigation_link_component.rb +1 -1
- data/app/{views/avo/partials/_turbo_frame_wrap.html.erb → components/avo/turbo_frame_wrapper_component.html.erb} +2 -2
- data/app/components/avo/turbo_frame_wrapper_component.rb +9 -0
- data/app/controllers/avo/application_controller.rb +7 -0
- data/app/controllers/avo/base_controller.rb +0 -1
- data/app/helpers/avo/application_helper.rb +1 -1
- data/app/javascript/js/application.js +1 -1
- data/app/javascript/js/controllers/action_controller.js +1 -1
- data/app/javascript/js/controllers/actions_picker_controller.js +1 -1
- data/app/javascript/js/controllers/alerts_controller.js +1 -1
- data/app/javascript/js/controllers/attachments_controller.js +1 -1
- data/app/javascript/js/controllers/fields/belongs_to_field_controller.js +1 -1
- data/app/javascript/js/controllers/fields/code_field_controller.js +1 -1
- data/app/javascript/js/controllers/fields/date_field_controller.js +1 -1
- data/app/javascript/js/controllers/fields/key_value_controller.js +3 -3
- data/app/javascript/js/controllers/fields/simple_mde_controller.js +1 -1
- data/app/javascript/js/controllers/fields/trix_field_controller.js +1 -1
- data/app/javascript/js/controllers/filter_controller.js +3 -7
- data/app/javascript/js/controllers/hidden_input_controller.js +1 -1
- data/app/javascript/js/controllers/item_select_all_controller.js +4 -4
- data/app/javascript/js/controllers/item_selector_controller.js +1 -1
- data/app/javascript/js/controllers/loading_button_controller.js +1 -1
- data/app/javascript/js/controllers/modal_controller.js +10 -1
- data/app/javascript/js/controllers/per_page_controller.js +1 -1
- data/app/javascript/js/controllers/search_controller.js +7 -2
- data/app/javascript/js/controllers/tippy_controller.js +1 -1
- data/app/javascript/js/controllers/toggle_panel_controller.js +1 -1
- data/app/views/avo/actions/show.html.erb +7 -3
- data/app/views/layouts/avo/application.html.erb +1 -1
- data/lib/avo/base_action.rb +21 -0
- data/lib/avo/licensing/h_q.rb +55 -1
- data/lib/avo/version.rb +1 -1
- data/public/avo-assets/avo.js +2569 -1926
- data/public/avo-assets/avo.js.map +3 -3
- metadata +8 -5
- data/app/views/avo/partials/_alerts.html.erb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93ddc5b52a7eb149886833f2eda8dcf69e5cfa29af5d357f57dfbc3b6e03800e
|
4
|
+
data.tar.gz: 44050a09443ff49550f7d9e3c22c3a4b03eea83f9c0d3a08bbc4a97d5084a355
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 346e58ffb98b4b60576282f43a766f6e9e388dcf83041dffc8b1f9c1e81292271869e2f356df92471afa77e51eff5945f127a236e2adc1c41a24ccb6847d2a5f
|
7
|
+
data.tar.gz: 5dbeae53b1d1179117f035c1bc2b806c9f88064f5af9c9c1498fbd6fe24107d96a67c02345f437f2cd73789de4935932c97f52730142e970808a68e49c5e2aa0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -73,3 +73,9 @@ Please read the [UPGRADE_GUIDE.MD](https://docs.avohq.io/1.0/upgrade.html)
|
|
73
73
|
|
74
74
|
|
75
75
|
![Alt](https://repobeats.axiom.co/api/embed/1481a6a259064f02a7936470d12a50802a9c98a4.svg "Repobeats analytics image")
|
76
|
+
|
77
|
+
# Shoutouts
|
78
|
+
|
79
|
+
[Get a box of waffles and some of the best app monitoring from Appsignal](https://appsignal.com/r/93dbe69bfb) 🧇
|
80
|
+
|
81
|
+
[Get $100 in credits from Digital Ocean](https://www.digitalocean.com/?refcode=efc1fe881d74&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge) 💸
|
File without changes
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::NavigationLinkComponent < ViewComponent::Base
|
4
|
-
def initialize(label: nil, path: nil, active: :inclusive, size: :md, target:
|
4
|
+
def initialize(label: nil, path: nil, active: :inclusive, size: :md, target: nil)
|
5
5
|
@label = label
|
6
6
|
@path = path
|
7
7
|
@active = active
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# When rendering the frames the flashed content gets lost.
|
4
4
|
# By including the alerts partial, the stimulus will pick them up and display them to the user.
|
5
5
|
%>
|
6
|
-
<%= render
|
6
|
+
<%= render Avo::AlertsComponent.new if helpers.flash.present? && name.present? %>
|
7
7
|
|
8
|
-
<%=
|
8
|
+
<%= content %>
|
9
9
|
<% if name.present? %></turbo-frame><% end %>
|
@@ -13,6 +13,7 @@ module Avo
|
|
13
13
|
protect_from_forgery with: :exception
|
14
14
|
before_action :init_app
|
15
15
|
before_action :check_avo_license
|
16
|
+
before_action :set_locale
|
16
17
|
before_action :set_authorization
|
17
18
|
before_action :_authenticate!
|
18
19
|
before_action :set_container_classes
|
@@ -245,5 +246,11 @@ module Avo
|
|
245
246
|
def model_param_key
|
246
247
|
@resource.form_scope
|
247
248
|
end
|
249
|
+
|
250
|
+
def set_locale
|
251
|
+
I18n.locale = params[:locale] || I18n.default_locale
|
252
|
+
|
253
|
+
I18n.default_locale = I18n.locale
|
254
|
+
end
|
248
255
|
end
|
249
256
|
end
|
@@ -84,7 +84,6 @@ module Avo
|
|
84
84
|
def new
|
85
85
|
@model = @resource.model_class.new
|
86
86
|
@resource = @resource.hydrate(model: @model, view: :new, user: _current_user)
|
87
|
-
# abort @model.course.inspect
|
88
87
|
|
89
88
|
@page_title = @resource.default_panel_name
|
90
89
|
add_breadcrumb resource_name.humanize, resources_path(resource: @resource)
|
@@ -14,7 +14,7 @@ import 'codemirror/mode/vue/vue'
|
|
14
14
|
import 'codemirror/mode/xml/xml'
|
15
15
|
import 'codemirror/mode/yaml/yaml'
|
16
16
|
|
17
|
-
import { Controller } from 'stimulus'
|
17
|
+
import { Controller } from '@hotwired/stimulus'
|
18
18
|
import CodeMirror from 'codemirror'
|
19
19
|
|
20
20
|
import { castBoolean } from '../../helpers/cast_boolean'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/* eslint-disable max-len */
|
2
|
-
import { Controller } from 'stimulus'
|
2
|
+
import { Controller } from '@hotwired/stimulus'
|
3
3
|
import { castBoolean } from '../../helpers/cast_boolean'
|
4
4
|
|
5
5
|
export default class extends Controller {
|
@@ -39,7 +39,7 @@ export default class extends Controller {
|
|
39
39
|
|
40
40
|
deleteRow(event) {
|
41
41
|
if (this.options.disable_deleting_rows || !this.options.editable) return
|
42
|
-
const { index } = event.
|
42
|
+
const { index } = event.params
|
43
43
|
this.fieldValue.splice(index, 1)
|
44
44
|
this.updateTextareaInput()
|
45
45
|
this.updateKeyValueComponent()
|
@@ -93,7 +93,7 @@ export default class extends Controller {
|
|
93
93
|
if (this.options.editable) {
|
94
94
|
result += `<a
|
95
95
|
href="javascript:void(0);"
|
96
|
-
data-index="${index}"
|
96
|
+
data-key-value-index-param="${index}"
|
97
97
|
data-action="click->key-value#deleteRow"
|
98
98
|
title="${this.options.delete_text}"
|
99
99
|
data-tippy="tooltip"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Controller } from 'stimulus'
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
2
2
|
import URI from 'urijs'
|
3
3
|
|
4
4
|
export default class extends Controller {
|
@@ -26,16 +26,12 @@ export default class extends Controller {
|
|
26
26
|
// then we convert the percent encodings into raw bytes which
|
27
27
|
// can be fed into btoa.
|
28
28
|
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
|
29
|
-
|
30
|
-
return String.fromCharCode('0x' + p1);
|
31
|
-
}));
|
29
|
+
(match, p1) => String.fromCharCode(`0x${p1}`)))
|
32
30
|
}
|
33
31
|
|
34
32
|
b64DecodeUnicode(str) {
|
35
33
|
// Going backwards: from bytestream, to percent-encoding, to original string.
|
36
|
-
return decodeURIComponent(atob(str).split('').map(
|
37
|
-
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
38
|
-
}).join(''));
|
34
|
+
return decodeURIComponent(atob(str).split('').map((c) => `%${(`00${c.charCodeAt(0).toString(16)}`).slice(-2)}`).join(''))
|
39
35
|
}
|
40
36
|
|
41
37
|
changeFilter() {
|
@@ -1,20 +1,20 @@
|
|
1
|
-
import { Controller } from 'stimulus'
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
2
2
|
|
3
3
|
export default class extends Controller {
|
4
|
-
static targets = [
|
4
|
+
static targets = ['itemCheckbox', 'checkbox']
|
5
5
|
|
6
6
|
connect() {
|
7
7
|
this.resourceName = this.element.dataset.resourceName
|
8
8
|
}
|
9
9
|
|
10
10
|
toggle(event) {
|
11
|
-
|
11
|
+
const value = !!event.target.checked
|
12
12
|
document.querySelectorAll(`[data-controller="item-selector"][data-resource-name="${this.resourceName}"] input[type=checkbox]`)
|
13
13
|
.forEach((checkbox) => checkbox.checked != value && checkbox.click())
|
14
14
|
}
|
15
15
|
|
16
16
|
update() {
|
17
|
-
|
17
|
+
let allSelected = true
|
18
18
|
this.itemCheckboxTargets.forEach((checkbox) => allSelected = allSelected && checkbox.checked)
|
19
19
|
this.checkboxTarget.checked = allSelected
|
20
20
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Controller } from 'stimulus'
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
2
2
|
|
3
3
|
export default class extends Controller {
|
4
4
|
static targets = ['modal']
|
@@ -8,4 +8,13 @@ export default class extends Controller {
|
|
8
8
|
|
9
9
|
document.dispatchEvent(new Event('actions-modal:close'))
|
10
10
|
}
|
11
|
+
|
12
|
+
delayedClose() {
|
13
|
+
const vm = this
|
14
|
+
|
15
|
+
setTimeout(() => {
|
16
|
+
vm.modalTarget.remove()
|
17
|
+
document.dispatchEvent(new Event('actions-modal:close'))
|
18
|
+
}, 500)
|
19
|
+
}
|
11
20
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/* eslint-disable no-underscore-dangle */
|
2
2
|
import * as Mousetrap from 'mousetrap'
|
3
|
-
import { Controller } from 'stimulus'
|
3
|
+
import { Controller } from '@hotwired/stimulus'
|
4
4
|
import { Turbo } from '@hotwired/turbo-rails'
|
5
5
|
import { autocomplete } from '@algolia/autocomplete-js'
|
6
6
|
import URI from 'urijs'
|
@@ -177,11 +177,16 @@ export default class extends Controller {
|
|
177
177
|
openOnFocus: true,
|
178
178
|
detachedMediaQuery: '',
|
179
179
|
getSources: ({ query }) => {
|
180
|
+
document.body.classList.add('search-loading')
|
180
181
|
const endpoint = that.searchUrl(query)
|
181
182
|
|
182
183
|
return that
|
183
184
|
.debouncedFetch(endpoint)
|
184
|
-
.then((response) =>
|
185
|
+
.then((response) => {
|
186
|
+
document.body.classList.remove('search-loading')
|
187
|
+
|
188
|
+
return response.json()
|
189
|
+
})
|
185
190
|
.then((data) => Object.keys(data).map((resourceName) => that.addSource(resourceName, data[resourceName])))
|
186
191
|
},
|
187
192
|
})
|
@@ -7,7 +7,11 @@
|
|
7
7
|
data-resource-id="<%= params[:id] %>"
|
8
8
|
class="hidden text-slate-800"
|
9
9
|
>
|
10
|
-
<%= form_with model: @model,
|
10
|
+
<%= form_with model: @model,
|
11
|
+
scope: 'fields',
|
12
|
+
url: "#{@resource.records_path}/actions/#{@action.param_id}",
|
13
|
+
data: @action.class.form_data_attributes do |form|
|
14
|
+
%>
|
11
15
|
<%= render Avo::ModalComponent.new do |c| %>
|
12
16
|
<% c.heading do %>
|
13
17
|
<%= @action.action_name %>
|
@@ -26,8 +30,8 @@
|
|
26
30
|
<% end %>
|
27
31
|
|
28
32
|
<% c.controls do %>
|
29
|
-
<%= a_button @action.cancel_button_label,
|
30
|
-
<%= a_button @action.confirm_button_label, type: :submit, color: :green, size: :sm %>
|
33
|
+
<%= a_button @action.cancel_button_label, data: { action: 'click->modal#close' }, size: :sm %>
|
34
|
+
<%= a_button @action.confirm_button_label, type: :submit, color: :green, size: :sm, data: @action.class.submit_button_data_attributes %>
|
31
35
|
<% end %>
|
32
36
|
<% end %>
|
33
37
|
<% end %>
|
data/lib/avo/base_action.rb
CHANGED
@@ -15,6 +15,7 @@ module Avo
|
|
15
15
|
class_attribute :fields
|
16
16
|
class_attribute :standalone, default: false
|
17
17
|
class_attribute :visible
|
18
|
+
class_attribute :may_download_file, default: false
|
18
19
|
|
19
20
|
attr_accessor :response
|
20
21
|
attr_accessor :model
|
@@ -22,6 +23,26 @@ module Avo
|
|
22
23
|
attr_accessor :user
|
23
24
|
attr_accessor :fields_loader
|
24
25
|
|
26
|
+
class << self
|
27
|
+
def form_data_attributes
|
28
|
+
# We can't respond with a file download from Turbo se we disable it on the form
|
29
|
+
if may_download_file
|
30
|
+
{ 'turbo': false }
|
31
|
+
else
|
32
|
+
{ 'turbo-frame': '_top', 'action-target': 'form' }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# We can't respond with a file download from Turbo se we disable close the modal manually after a while (it's a hack, we know)
|
37
|
+
def submit_button_data_attributes
|
38
|
+
if may_download_file
|
39
|
+
{ action: 'click->modal#delayedClose' }
|
40
|
+
else
|
41
|
+
{}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
25
46
|
def action_name
|
26
47
|
return name if name.present?
|
27
48
|
|
data/lib/avo/licensing/h_q.rb
CHANGED
@@ -23,6 +23,12 @@ module Avo
|
|
23
23
|
|
24
24
|
begin
|
25
25
|
perform_and_cache_request
|
26
|
+
rescue Errno::EHOSTUNREACH => exception
|
27
|
+
cache_and_return_error "HTTP host not reachable error.", exception.message
|
28
|
+
rescue Errno::ECONNRESET => exception
|
29
|
+
cache_and_return_error "HTTP connection reset error.", exception.message
|
30
|
+
rescue Errno::ECONNREFUSED => exception
|
31
|
+
cache_and_return_error "HTTP connection refused error.", exception.message
|
26
32
|
rescue HTTParty::Error => exception
|
27
33
|
cache_and_return_error "HTTP client error.", exception.message
|
28
34
|
rescue Net::OpenTimeout => exception
|
@@ -71,7 +77,55 @@ module Avo
|
|
71
77
|
environment: Rails.env,
|
72
78
|
ip: current_request.ip,
|
73
79
|
host: current_request.host,
|
74
|
-
port: current_request.port
|
80
|
+
port: current_request.port,
|
81
|
+
app_name: app_name
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
def app_name
|
86
|
+
Rails.application.class.to_s.split("::").first
|
87
|
+
rescue
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
|
91
|
+
def avo_metadata
|
92
|
+
resources = App.resources
|
93
|
+
field_definitions = resources.map(&:get_field_definitions)
|
94
|
+
fields_count = field_definitions.map(&:count).sum
|
95
|
+
fields_per_resource = sprintf("%0.01f", fields_count / (resources.count + 0.0))
|
96
|
+
|
97
|
+
field_types = {}
|
98
|
+
custom_fields_count = 0
|
99
|
+
field_definitions.each do |fields|
|
100
|
+
fields.each do |field|
|
101
|
+
field_types[field.type] ||= 0
|
102
|
+
field_types[field.type] += 1
|
103
|
+
|
104
|
+
custom_fields_count += 1 if field.custom?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
{
|
109
|
+
resources_count: resources.count,
|
110
|
+
fields_count: fields_count,
|
111
|
+
fields_per_resource: fields_per_resource,
|
112
|
+
custom_fields_count: custom_fields_count,
|
113
|
+
field_types: field_types,
|
114
|
+
**other_metadata(:actions),
|
115
|
+
**other_metadata(:filters),
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
def other_metadata(type = :actions)
|
120
|
+
resources = App.resources
|
121
|
+
|
122
|
+
types = resources.map(&:"get_#{type}")
|
123
|
+
type_count = types.flatten.uniq.count
|
124
|
+
type_per_resource = sprintf("%0.01f", types.map(&:count).sum / (resources.count + 0.0))
|
125
|
+
|
126
|
+
{
|
127
|
+
"#{type}_count": type_count,
|
128
|
+
"#{type}_per_resource": type_per_resource,
|
75
129
|
}
|
76
130
|
end
|
77
131
|
|
data/lib/avo/version.rb
CHANGED