avo 2.7.1.pre.1 → 2.8.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 +2 -0
- data/Gemfile.lock +5 -5
- data/app/components/avo/alert_component.rb +6 -0
- data/app/components/avo/card_component.html.erb +2 -2
- data/app/components/avo/common_field_wrapper_component.html.erb +10 -3
- data/app/components/avo/common_field_wrapper_component.rb +27 -1
- data/app/components/avo/edit/field_wrapper_component.html.erb +1 -1
- data/app/components/avo/fields/badge_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/badge_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +21 -10
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +7 -1
- data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +27 -15
- data/app/components/avo/fields/belongs_to_field/edit_component.rb +4 -0
- 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/boolean_field/edit_component.html.erb +4 -2
- data/app/components/avo/fields/boolean_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/boolean_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +7 -1
- data/app/components/avo/fields/boolean_group_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/boolean_group_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/code_field/edit_component.html.erb +7 -5
- data/app/components/avo/fields/code_field/show_component.html.erb +2 -2
- data/app/components/avo/fields/common/key_value_component.html.erb +10 -4
- data/app/components/avo/fields/common/key_value_component.rb +2 -0
- data/app/components/avo/fields/country_field/edit_component.html.erb +4 -2
- data/app/components/avo/fields/country_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/country_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/date_field/edit_component.html.erb +6 -4
- data/app/components/avo/fields/date_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/date_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/date_time_field/edit_component.html.erb +6 -4
- data/app/components/avo/fields/date_time_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/date_time_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/edit_component.rb +7 -0
- data/app/components/avo/fields/external_image_field/edit_component.html.erb +5 -2
- data/app/components/avo/fields/external_image_field/index_component.html.erb +6 -4
- data/app/components/avo/fields/external_image_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/file_field/edit_component.html.erb +6 -1
- data/app/components/avo/fields/file_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/file_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/files_field/edit_component.html.erb +7 -1
- data/app/components/avo/fields/files_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/files_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/gravatar_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/gravatar_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/hidden_field/edit_component.html.erb +5 -1
- data/app/components/avo/fields/id_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/id_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/id_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/index_component.rb +3 -0
- data/app/components/avo/fields/key_value_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/key_value_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/markdown_field/edit_component.html.erb +8 -5
- data/app/components/avo/fields/markdown_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/number_field/edit_component.html.erb +7 -4
- data/app/components/avo/fields/number_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/number_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/password_field/edit_component.html.erb +4 -2
- data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +7 -4
- data/app/components/avo/fields/progress_bar_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/progress_bar_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/select_field/edit_component.html.erb +9 -3
- data/app/components/avo/fields/select_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/select_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/show_component.rb +3 -0
- data/app/components/avo/fields/status_field/edit_component.html.erb +6 -3
- data/app/components/avo/fields/status_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/status_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/tags_field/edit_component.html.erb +19 -11
- data/app/components/avo/fields/tags_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/tags_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/text_field/edit_component.html.erb +5 -2
- data/app/components/avo/fields/text_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/text_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/textarea_field/edit_component.html.erb +6 -3
- data/app/components/avo/fields/textarea_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/trix_field/edit_component.html.erb +13 -4
- data/app/components/avo/fields/trix_field/edit_component.rb +3 -0
- data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
- data/app/components/avo/index/field_wrapper_component.html.erb +12 -5
- data/app/components/avo/index/field_wrapper_component.rb +27 -3
- data/app/components/avo/panel_component.rb +4 -3
- data/app/components/avo/resource_component.rb +1 -0
- data/app/components/avo/show/field_wrapper_component.html.erb +1 -1
- data/app/components/avo/show/field_wrapper_component.rb +2 -1
- data/app/components/avo/views/resource_edit_component.html.erb +7 -4
- data/app/components/avo/views/resource_edit_component.rb +2 -1
- data/app/components/avo/views/resource_index_component.html.erb +6 -3
- data/app/components/avo/views/resource_index_component.rb +7 -1
- data/app/components/avo/views/resource_new_component.html.erb +7 -2
- data/app/components/avo/views/resource_new_component.rb +2 -1
- data/app/components/avo/views/resource_show_component.html.erb +9 -7
- data/app/components/avo/views/resource_show_component.rb +1 -0
- data/app/controllers/avo/actions_controller.rb +4 -1
- data/app/controllers/avo/base_controller.rb +14 -8
- data/app/controllers/avo/search_controller.rb +7 -1
- data/app/javascript/js/controllers/custom/course_resource_controller.js +102 -0
- data/app/javascript/js/controllers/fields/code_field_controller.js +7 -1
- data/app/javascript/js/controllers/fields/key_value_controller.js +1 -0
- data/app/javascript/js/controllers/fields/tags_field_controller.js +0 -1
- data/app/javascript/js/controllers/menu_controller.js +4 -3
- data/app/javascript/js/controllers/resource_edit_controller.js +72 -0
- data/app/javascript/js/controllers/resource_index_controller.js +4 -0
- data/app/javascript/js/controllers/resource_show_controller.js +4 -0
- data/app/javascript/js/controllers/search_controller.js +28 -5
- data/app/javascript/js/controllers.js +10 -0
- data/app/views/avo/associations/new.html.erb +2 -1
- data/app/views/avo/base/_select_filter.html.erb +1 -1
- data/app/views/avo/base/_text_filter.html.erb +1 -0
- data/app/views/avo/partials/_logo.html.erb +3 -2
- data/app/views/avo/partials/_navbar.html.erb +1 -1
- data/config/routes.rb +1 -1
- data/db/factories.rb +1 -0
- data/lib/avo/base_action.rb +9 -2
- data/lib/avo/base_card.rb +0 -23
- data/lib/avo/base_resource.rb +17 -15
- data/lib/avo/concerns/has_fields.rb +93 -0
- data/lib/avo/concerns/has_html_attributes.rb +110 -0
- data/lib/avo/concerns/has_stimulus_controllers.rb +42 -0
- data/lib/avo/fields/base_field.rb +23 -13
- data/lib/avo/fields/select_field.rb +1 -1
- data/lib/avo/grid_collector.rb +4 -4
- data/lib/avo/html/builder.rb +117 -0
- data/lib/avo/licensing/pro_license.rb +1 -0
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +4 -0
- data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +11 -1
- data/lib/generators/avo/templates/cards/metric_card_sample.tt +11 -1
- data/lib/generators/avo/templates/field/components/edit_component.html.erb.tt +1 -1
- data/lib/generators/avo/templates/field/components/index_component.html.erb.tt +1 -1
- data/lib/generators/avo/templates/field/components/show_component.html.erb.tt +1 -1
- data/lib/generators/avo/templates/initializer/avo.tt +1 -1
- data/lib/generators/avo/templates/locales/avo.en.yml +3 -3
- data/public/avo-assets/avo.css +28 -8
- data/public/avo-assets/avo.js +148 -148
- data/public/avo-assets/avo.js.map +3 -3
- data/public/avo-assets/logomark.png +0 -0
- metadata +13 -10
- data/app/assets/builds/action_cable.js +0 -2
- data/app/assets/builds/action_cable.js.map +0 -7
- data/app/assets/builds/avo.css +0 -9610
- data/app/assets/builds/avo.js +0 -512
- data/app/assets/builds/avo.js.map +0 -7
- data/lib/avo/fields_collector.rb +0 -70
@@ -1,6 +1,9 @@
|
|
1
|
-
|
2
|
-
class
|
3
|
-
|
1
|
+
<%= content_tag :div,
|
2
|
+
class: "space-y-12",
|
3
|
+
data: {
|
4
|
+
'model-id': @resource.model.id,
|
5
|
+
**@resource.stimulus_data_attributes
|
6
|
+
} do %>
|
4
7
|
<% @resource.panels.each do |resource_panel| %>
|
5
8
|
<%= form_with model: @resource.model,
|
6
9
|
scope: @resource.form_scope,
|
@@ -70,4 +73,4 @@
|
|
70
73
|
<% end %>
|
71
74
|
<% end %>
|
72
75
|
<% end %>
|
73
|
-
|
76
|
+
<% end %>
|
@@ -6,6 +6,7 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
|
|
6
6
|
|
7
7
|
def initialize(resource: nil)
|
8
8
|
@resource = resource
|
9
|
+
@view = :edit
|
9
10
|
|
10
11
|
split_panel_fields
|
11
12
|
end
|
@@ -29,6 +30,6 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
|
|
29
30
|
private
|
30
31
|
|
31
32
|
def via_index?
|
32
|
-
params[:via_view] ==
|
33
|
+
params[:via_view] == "index"
|
33
34
|
end
|
34
35
|
end
|
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
<%= content_tag :div,
|
2
|
+
data: {
|
3
|
+
**@resource.stimulus_data_attributes
|
4
|
+
} do %>
|
2
5
|
<%= render Avo::PanelComponent.new(title: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
|
3
6
|
<% c.tools do %>
|
4
7
|
<% if can_attach? %>
|
@@ -31,7 +34,7 @@
|
|
31
34
|
>
|
32
35
|
<% if @resource.search_query.present? %>
|
33
36
|
<div class="flex items-center px-4 w-64">
|
34
|
-
<%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.
|
37
|
+
<%= render partial: 'avo/partials/resource_search', locals: {resource: @resource.model_name.collection} %>
|
35
38
|
</div>
|
36
39
|
<% else %>
|
37
40
|
<%# Offset for the space-y-2 property when the serach is missing %>
|
@@ -72,4 +75,4 @@
|
|
72
75
|
<% end %>
|
73
76
|
<% end %>
|
74
77
|
<% end %>
|
75
|
-
|
78
|
+
<% end %>
|
@@ -28,11 +28,12 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
28
28
|
@turbo_frame = turbo_frame
|
29
29
|
@parent_model = parent_model
|
30
30
|
@applied_filters = applied_filters
|
31
|
+
@view = :index
|
31
32
|
end
|
32
33
|
|
33
34
|
def title
|
34
35
|
if @reflection.present?
|
35
|
-
return
|
36
|
+
return name if field.present?
|
36
37
|
|
37
38
|
reflection_resource.plural_name
|
38
39
|
else
|
@@ -143,4 +144,9 @@ class Avo::Views::ResourceIndexComponent < Avo::ResourceComponent
|
|
143
144
|
def reflection_model_class
|
144
145
|
@reflection.active_record.to_s
|
145
146
|
end
|
147
|
+
|
148
|
+
def name
|
149
|
+
field.custom_name? ? field.name : field.plural_name
|
150
|
+
end
|
151
|
+
|
146
152
|
end
|
@@ -1,4 +1,9 @@
|
|
1
|
-
|
1
|
+
<%= content_tag :div,
|
2
|
+
class: "space-y-12",
|
3
|
+
data: {
|
4
|
+
'model-id': @resource.model.id,
|
5
|
+
**@resource.stimulus_data_attributes
|
6
|
+
} do %>
|
2
7
|
<% @resource.panels.each do |resource_panel| %>
|
3
8
|
<%= form_with model: @resource.model,
|
4
9
|
scope: @resource.form_scope,
|
@@ -52,4 +57,4 @@
|
|
52
57
|
<% end %>
|
53
58
|
<% end %>
|
54
59
|
<% end %>
|
55
|
-
|
60
|
+
<% end %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class Avo::Views::ResourceNewComponent <
|
3
|
+
class Avo::Views::ResourceNewComponent < Avo::ResourceComponent
|
4
4
|
include Avo::ResourcesHelper
|
5
5
|
include Avo::ApplicationHelper
|
6
6
|
|
@@ -10,6 +10,7 @@ class Avo::Views::ResourceNewComponent < ViewComponent::Base
|
|
10
10
|
)
|
11
11
|
@resource = resource
|
12
12
|
@model = model
|
13
|
+
@view = :new
|
13
14
|
end
|
14
15
|
|
15
16
|
def back_path
|
@@ -1,8 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
data
|
4
|
-
|
5
|
-
|
1
|
+
<%= content_tag :div,
|
2
|
+
class: "space-y-12",
|
3
|
+
data: {
|
4
|
+
'model-id': @resource.model.id,
|
5
|
+
selected_resources_name: @resource.model_key,
|
6
|
+
selected_resources: [@resource.model.id],
|
7
|
+
**@resource.stimulus_data_attributes
|
8
|
+
} do %>
|
6
9
|
<% @resource.panels.each_with_index do |resource_panel, index| %>
|
7
10
|
<%= render Avo::PanelComponent.new(title: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: index) do |c| %>
|
8
11
|
<% c.tools do %>
|
@@ -99,7 +102,6 @@
|
|
99
102
|
<% end %>
|
100
103
|
<% end %>
|
101
104
|
<% end %>
|
102
|
-
|
103
105
|
<% if should_display_invalid_fields_errors? %>
|
104
106
|
<turbo-stream action="append" target="alerts">
|
105
107
|
<template>
|
@@ -109,4 +111,4 @@
|
|
109
111
|
</template>
|
110
112
|
</turbo-stream>
|
111
113
|
<% end %>
|
112
|
-
|
114
|
+
<% end %>
|
@@ -75,9 +75,9 @@ module Avo
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def show
|
78
|
-
set_actions
|
79
|
-
|
80
78
|
@resource.hydrate(model: @model, view: :show, user: _current_user, params: params)
|
79
|
+
|
80
|
+
set_actions
|
81
81
|
|
82
82
|
@page_title = @resource.default_panel_name.to_s
|
83
83
|
|
@@ -102,7 +102,17 @@ module Avo
|
|
102
102
|
@resource = @resource.hydrate(model: @model, view: :new, user: _current_user)
|
103
103
|
|
104
104
|
@page_title = @resource.default_panel_name.to_s
|
105
|
-
|
105
|
+
|
106
|
+
if params[:via_relation_class].present? && params[:via_resource_id].present?
|
107
|
+
via_resource = Avo::App.get_resource_by_model_name params[:via_relation_class]
|
108
|
+
via_model = via_resource.class.find_scope.find params[:via_resource_id]
|
109
|
+
via_resource.hydrate model: via_model
|
110
|
+
|
111
|
+
add_breadcrumb via_resource.plural_name, resources_path(resource: via_resource)
|
112
|
+
add_breadcrumb via_resource.model_title, resource_path(model: via_model, resource: via_resource)
|
113
|
+
end
|
114
|
+
|
115
|
+
add_breadcrumb @resource.plural_name.humanize
|
106
116
|
add_breadcrumb t("avo.new").humanize
|
107
117
|
end
|
108
118
|
|
@@ -302,14 +312,10 @@ module Avo
|
|
302
312
|
end
|
303
313
|
|
304
314
|
def set_actions
|
305
|
-
if params[:resource_id].present?
|
306
|
-
model = @resource.class.find_scope.find params[:resource_id]
|
307
|
-
end
|
308
|
-
|
309
315
|
@actions = @resource
|
310
316
|
.get_actions
|
311
317
|
.map do |action|
|
312
|
-
action.new(model: model, resource: @resource, view: @view)
|
318
|
+
action.new(model: @model, resource: @resource, view: @view)
|
313
319
|
end
|
314
320
|
.select { |action| action.visible_in_view }
|
315
321
|
end
|
@@ -51,8 +51,14 @@ module Avo
|
|
51
51
|
|
52
52
|
results = apply_search_metadata(query, resource)
|
53
53
|
|
54
|
+
header = resource.plural_name
|
55
|
+
|
56
|
+
if results.length > 0
|
57
|
+
header += " (#{results.length})"
|
58
|
+
end
|
59
|
+
|
54
60
|
result_object = {
|
55
|
-
header:
|
61
|
+
header: header,
|
56
62
|
help: resource.class.search_query_help,
|
57
63
|
results: results,
|
58
64
|
count: results.length
|
@@ -0,0 +1,102 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
2
|
+
|
3
|
+
const LOADER_CLASSES = 'absolute bg-gray-100 opacity-10 w-full h-full'
|
4
|
+
|
5
|
+
export default class extends Controller {
|
6
|
+
static targets = ['countrySelectInput', 'citySelectInput', 'citySelectWrapper'];
|
7
|
+
|
8
|
+
static values = {
|
9
|
+
view: String,
|
10
|
+
}
|
11
|
+
|
12
|
+
// Te fields initial value
|
13
|
+
static initialValue
|
14
|
+
|
15
|
+
get placeholder() {
|
16
|
+
return this.citySelectInputTarget.ariaPlaceholder
|
17
|
+
}
|
18
|
+
|
19
|
+
set loading(isLoading) {
|
20
|
+
if (isLoading) {
|
21
|
+
// create a loader overlay
|
22
|
+
const loadingDiv = document.createElement('div')
|
23
|
+
loadingDiv.className = LOADER_CLASSES
|
24
|
+
loadingDiv.dataset.target = 'city-loader'
|
25
|
+
|
26
|
+
// add the loader overlay
|
27
|
+
this.citySelectWrapperTarget.prepend(loadingDiv)
|
28
|
+
this.citySelectWrapperTarget.classList.add('opacity-50')
|
29
|
+
} else {
|
30
|
+
// remove the loader overlay
|
31
|
+
this.citySelectWrapperTarget.querySelector('[data-target="city-loader"]').remove()
|
32
|
+
this.citySelectWrapperTarget.classList.remove('opacity-50')
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
async connect() {
|
37
|
+
// Add the controller functionality only on forms
|
38
|
+
if (['edit', 'new'].includes(this.viewValue)) {
|
39
|
+
this.captureTheInitialValue()
|
40
|
+
|
41
|
+
// Trigger the change on load
|
42
|
+
await this.onCountryChange()
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
// Read the country select.
|
47
|
+
// If there's any value selected show the cities and prefill them.
|
48
|
+
async onCountryChange() {
|
49
|
+
if (this.hasCountrySelectInputTarget && this.countrySelectInputTarget) {
|
50
|
+
// Get the country
|
51
|
+
const country = this.countrySelectInputTarget.value
|
52
|
+
// Dynamically fetch the cities for this country
|
53
|
+
const cities = await this.fetchCitiesForCountry(country)
|
54
|
+
|
55
|
+
// Clear the select of options
|
56
|
+
Object.keys(this.citySelectInputTarget.options).forEach(() => {
|
57
|
+
this.citySelectInputTarget.options.remove(0)
|
58
|
+
})
|
59
|
+
|
60
|
+
// Add blank option
|
61
|
+
this.citySelectInputTarget.add(new Option(this.placeholder))
|
62
|
+
|
63
|
+
// Add the new cities
|
64
|
+
cities.forEach((city) => {
|
65
|
+
this.citySelectInputTarget.add(new Option(city, city))
|
66
|
+
})
|
67
|
+
|
68
|
+
// Check if the initial value is present in the cities array and select it.
|
69
|
+
// If not, select the first item
|
70
|
+
const currentOptions = Array.from(this.citySelectInputTarget.options).map((item) => item.value)
|
71
|
+
if (currentOptions.includes(this.initialValue)) {
|
72
|
+
this.citySelectInputTarget.value = this.initialValue
|
73
|
+
} else {
|
74
|
+
// Select the first item
|
75
|
+
this.citySelectInputTarget.value = this.citySelectInputTarget.options[0].value
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
// Private
|
81
|
+
|
82
|
+
captureTheInitialValue() {
|
83
|
+
this.initialValue = this.citySelectInputTarget.value
|
84
|
+
}
|
85
|
+
|
86
|
+
async fetchCitiesForCountry(country) {
|
87
|
+
if (!country) {
|
88
|
+
return []
|
89
|
+
}
|
90
|
+
|
91
|
+
this.loading = true
|
92
|
+
|
93
|
+
const response = await fetch(
|
94
|
+
`${window.Avo.configuration.root_path}/resources/courses/cities?country=${country}`,
|
95
|
+
)
|
96
|
+
const data = await response.json()
|
97
|
+
|
98
|
+
this.loading = false
|
99
|
+
|
100
|
+
return data
|
101
|
+
}
|
102
|
+
}
|
@@ -32,8 +32,14 @@ export default class extends Controller {
|
|
32
32
|
lineNumbers: true,
|
33
33
|
}
|
34
34
|
|
35
|
+
const vm = this
|
36
|
+
|
35
37
|
setTimeout(() => {
|
36
|
-
CodeMirror.fromTextArea(this.elementTarget, options)
|
38
|
+
CodeMirror.fromTextArea(this.elementTarget, options).on('change', (cm) => {
|
39
|
+
// Add this innerText change and dispatch an event to allow stimulus to pick up the input event.
|
40
|
+
vm.elementTarget.innerText = cm.getValue()
|
41
|
+
vm.elementTarget.dispatchEvent(new Event('input'))
|
42
|
+
})
|
37
43
|
}, 1)
|
38
44
|
}
|
39
45
|
}
|
@@ -72,6 +72,7 @@ export default class extends Controller {
|
|
72
72
|
result = Object.assign(...this.fieldValue.map(([key, val]) => ({ [key]: val })))
|
73
73
|
}
|
74
74
|
this.inputTarget.innerText = JSON.stringify(result)
|
75
|
+
this.inputTarget.dispatchEvent(new Event('input'))
|
75
76
|
}
|
76
77
|
|
77
78
|
updateKeyValueComponent() {
|
@@ -22,10 +22,11 @@ export default class extends Controller {
|
|
22
22
|
}
|
23
23
|
|
24
24
|
get initiallyCollapsed() {
|
25
|
-
if (this.
|
26
|
-
|
25
|
+
if (this.defaultState === 'collapsed') {
|
26
|
+
return this.userState === 'collapsed'
|
27
|
+
}
|
27
28
|
|
28
|
-
return
|
29
|
+
return this.userState === 'collapsed'
|
29
30
|
}
|
30
31
|
|
31
32
|
connect() {
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
2
|
+
import camelCase from 'lodash/camelCase'
|
3
|
+
|
4
|
+
export default class extends Controller {
|
5
|
+
static targets = []
|
6
|
+
|
7
|
+
static values = {
|
8
|
+
view: String,
|
9
|
+
}
|
10
|
+
|
11
|
+
debugOnInput(e) {
|
12
|
+
// eslint-disable-next-line no-console
|
13
|
+
console.log('onInput', e, e.target.value)
|
14
|
+
}
|
15
|
+
|
16
|
+
toggle({ params }) {
|
17
|
+
const { toggleTarget, toggleTargets } = params
|
18
|
+
|
19
|
+
if (toggleTarget) {
|
20
|
+
this.toggleAvoTarget(toggleTarget)
|
21
|
+
}
|
22
|
+
|
23
|
+
if (toggleTargets && toggleTargets.length > 0) {
|
24
|
+
toggleTargets.forEach(this.toggleAvoTarget.bind(this))
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
disable({ params }) {
|
29
|
+
const { disableTarget, disableTargets } = params
|
30
|
+
|
31
|
+
if (disableTarget) {
|
32
|
+
this.disableAvoTarget(disableTarget)
|
33
|
+
}
|
34
|
+
|
35
|
+
if (disableTargets && disableTargets.length > 0) {
|
36
|
+
disableTargets.forEach(this.disableAvoTarget.bind(this))
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
// Private
|
41
|
+
|
42
|
+
toggleAvoTarget(targetName) {
|
43
|
+
// compose the default wrapper data value
|
44
|
+
const target = camelCase(targetName)
|
45
|
+
const element = document.querySelector(`[data-resource-edit-target="${target}"]`)
|
46
|
+
|
47
|
+
if (element) {
|
48
|
+
element.classList.toggle('hidden')
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
disableAvoTarget(targetName) {
|
53
|
+
// compose the default wrapper data value
|
54
|
+
const target = camelCase(targetName)
|
55
|
+
|
56
|
+
// find & disable direct selector
|
57
|
+
document.querySelectorAll(`[data-resource-edit-target="${target}"]`).forEach(this.toggleItemDisabled)
|
58
|
+
|
59
|
+
// find & disable inputs
|
60
|
+
document.querySelectorAll(`[data-resource-edit-target="${target}"] input`).forEach(this.toggleItemDisabled)
|
61
|
+
|
62
|
+
// find & disable select fields
|
63
|
+
document.querySelectorAll(`[data-resource-edit-target="${target}"] select`).forEach(this.toggleItemDisabled)
|
64
|
+
|
65
|
+
// find & disable buttons for belongs_to
|
66
|
+
document.querySelectorAll(`[data-resource-edit-target="${target}"] [data-slot="value"] button`).forEach(this.toggleItemDisabled)
|
67
|
+
}
|
68
|
+
|
69
|
+
toggleItemDisabled(item) {
|
70
|
+
item.disabled = !item.disabled
|
71
|
+
}
|
72
|
+
}
|
@@ -55,7 +55,10 @@ export default class extends Controller {
|
|
55
55
|
searchUrl(query) {
|
56
56
|
const url = URI()
|
57
57
|
|
58
|
-
|
58
|
+
return url.segment(this.searchSegments()).search(this.searchParams(query)).toString()
|
59
|
+
}
|
60
|
+
|
61
|
+
searchSegments() {
|
59
62
|
let segments = [
|
60
63
|
window.Avo.configuration.root_path,
|
61
64
|
'avo_api',
|
@@ -67,6 +70,19 @@ export default class extends Controller {
|
|
67
70
|
segments = [window.Avo.configuration.root_path, 'avo_api', 'search']
|
68
71
|
}
|
69
72
|
|
73
|
+
return segments
|
74
|
+
}
|
75
|
+
|
76
|
+
searchParams(query) {
|
77
|
+
let params = {
|
78
|
+
q: query,
|
79
|
+
global: false,
|
80
|
+
}
|
81
|
+
|
82
|
+
if (this.isGlobalSearch) {
|
83
|
+
params.global = true
|
84
|
+
}
|
85
|
+
|
70
86
|
if (this.isBelongsToSearch) {
|
71
87
|
params = {
|
72
88
|
...params,
|
@@ -85,13 +101,13 @@ export default class extends Controller {
|
|
85
101
|
}
|
86
102
|
}
|
87
103
|
|
88
|
-
return
|
104
|
+
return params
|
89
105
|
}
|
90
106
|
|
91
107
|
handleOnSelect({ item }) {
|
92
108
|
if (this.isBelongsToSearch) {
|
93
|
-
this.hiddenIdTarget
|
94
|
-
this.buttonTarget
|
109
|
+
this.updateFieldAttribute(this.hiddenIdTarget, 'value', item._id)
|
110
|
+
this.updateFieldAttribute(this.buttonTarget, 'value', item._label)
|
95
111
|
|
96
112
|
document.querySelector('.aa-DetachedOverlay').remove()
|
97
113
|
|
@@ -180,7 +196,7 @@ export default class extends Controller {
|
|
180
196
|
}
|
181
197
|
|
182
198
|
clearValue() {
|
183
|
-
this.clearValueTargets.map((
|
199
|
+
this.clearValueTargets.map((t) => this.updateFieldAttribute(t, 'value', ''))
|
184
200
|
this.clearButtonTarget.classList.add('hidden')
|
185
201
|
}
|
186
202
|
|
@@ -229,4 +245,11 @@ export default class extends Controller {
|
|
229
245
|
this.buttonTarget.removeAttribute('disabled')
|
230
246
|
}
|
231
247
|
}
|
248
|
+
|
249
|
+
// Private
|
250
|
+
|
251
|
+
updateFieldAttribute(target, attribute, value) {
|
252
|
+
target.setAttribute(attribute, value)
|
253
|
+
target.dispatchEvent(new Event('input'))
|
254
|
+
}
|
232
255
|
}
|
@@ -7,6 +7,7 @@ import BelongsToFieldController from './controllers/fields/belongs_to_field_cont
|
|
7
7
|
import BooleanFilterController from './controllers/boolean_filter_controller'
|
8
8
|
import CodeFieldController from './controllers/fields/code_field_controller'
|
9
9
|
import CopyToClipboardController from './controllers/copy_to_clipboard_controller'
|
10
|
+
import CourseResourceController from './controllers/custom/course_resource_controller'
|
10
11
|
import DashboardCardController from './controllers/dashboard_card_controller'
|
11
12
|
import DateFieldController from './controllers/fields/date_field_controller'
|
12
13
|
import FilterController from './controllers/filter_controller'
|
@@ -20,6 +21,9 @@ import MobileController from './controllers/mobile_controller'
|
|
20
21
|
import ModalController from './controllers/modal_controller'
|
21
22
|
import MultipleSelectFilterController from './controllers/multiple_select_filter_controller'
|
22
23
|
import PerPageController from './controllers/per_page_controller'
|
24
|
+
import ResourceEditController from './controllers/resource_edit_controller'
|
25
|
+
import ResourceIndexController from './controllers/resource_index_controller'
|
26
|
+
import ResourceShowController from './controllers/resource_show_controller'
|
23
27
|
import SearchController from './controllers/search_controller'
|
24
28
|
import SelectController from './controllers/select_controller'
|
25
29
|
import SelectFilterController from './controllers/select_filter_controller'
|
@@ -46,6 +50,9 @@ application.register('mobile', MobileController)
|
|
46
50
|
application.register('modal', ModalController)
|
47
51
|
application.register('multiple-select-filter', MultipleSelectFilterController)
|
48
52
|
application.register('per-page', PerPageController)
|
53
|
+
application.register('resource-edit', ResourceEditController)
|
54
|
+
application.register('resource-index', ResourceIndexController)
|
55
|
+
application.register('resource-show', ResourceShowController)
|
49
56
|
application.register('search', SearchController)
|
50
57
|
application.register('select', SelectController)
|
51
58
|
application.register('select-filter', SelectFilterController)
|
@@ -61,3 +68,6 @@ application.register('date-field', DateFieldController)
|
|
61
68
|
application.register('key-value', KeyValueController)
|
62
69
|
application.register('simple-mde', SimpleMdeController)
|
63
70
|
application.register('trix-field', TrixFieldController)
|
71
|
+
|
72
|
+
// Custom controllers
|
73
|
+
application.register('course-resource', CourseResourceController)
|
@@ -16,7 +16,8 @@
|
|
16
16
|
field: @field,
|
17
17
|
model_key: @field.target_resource&.model_key,
|
18
18
|
foreign_key: 'related_id',
|
19
|
-
resource: @resource
|
19
|
+
resource: @resource,
|
20
|
+
view: :new
|
20
21
|
%>
|
21
22
|
<% else %>
|
22
23
|
<div class="flex-1 flex flex-col items-center justify-center px-0 md:px-24 text-base">
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<%= filter_wrapper name: filter.name do %>
|
7
7
|
<%= select_tag filter.id, options_for_select(filter.options.invert, filter.applied_or_default_value(@applied_filters)),
|
8
8
|
class: input_classes('w-full mb-0'),
|
9
|
-
include_blank: '—',
|
9
|
+
include_blank: filter.class.empty_message || '—',
|
10
10
|
id: "avo_filters_#{filter.id.parameterize.underscore}",
|
11
11
|
'data-filter-class': filter.class,
|
12
12
|
'data-select-filter-target': 'selector',
|
@@ -7,6 +7,7 @@
|
|
7
7
|
<%= text_field_tag filter.id, filter.applied_or_default_value(@applied_filters),
|
8
8
|
class: input_classes('w-full mb-0'),
|
9
9
|
id: "avo_filters_#{filter.id.parameterize.underscore}",
|
10
|
+
placeholder: filter.class.empty_message,
|
10
11
|
'data-filter-class': filter.class.to_s,
|
11
12
|
'data-text-filter-target': 'text',
|
12
13
|
'data-action': 'keypress->text-filter#tryToSubmit'
|
@@ -1,3 +1,4 @@
|
|
1
|
-
<%= link_to root_path, class: 'logo-placeholder h-
|
2
|
-
<%= image_tag '/avo-assets/logo.png', class: '
|
1
|
+
<%= link_to root_path, class: 'logo-placeholder h-full w-full flex justify-start' do %>
|
2
|
+
<%= image_tag '/avo-assets/logo.png', class: 'hidden sm:block object-contain', title: 'Avo' %>
|
3
|
+
<%= image_tag '/avo-assets/logomark.png', class: 'sm:hidden object-contain', title: 'Avo' %>
|
3
4
|
<% end %>
|
@@ -2,7 +2,7 @@
|
|
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 lg:space-x-0 w-
|
5
|
+
<div class="flex items-center space-x-2 lg:space-x-0 w-auto lg:w-64 flex-shrink-0 h-full">
|
6
6
|
<%= a_button class: 'lg:hidden', icon: 'menu', size: :xs, compact: true, style: :text, data: { action: 'click->mobile#toggleSidebar' } %>
|
7
7
|
<%= render partial: "avo/partials/logo" %>
|
8
8
|
</div>
|
data/config/routes.rb
CHANGED
@@ -48,7 +48,7 @@ Avo::Engine.routes.draw do
|
|
48
48
|
post "/debug/refresh_license", to: "debug#refresh_license"
|
49
49
|
end
|
50
50
|
|
51
|
-
if Rails.env.development?
|
51
|
+
if Rails.env.development? || Rails.env.staging?
|
52
52
|
scope "/avo_private", as: "avo_private" do
|
53
53
|
get "/design", to: "private#design"
|
54
54
|
end
|