active_element 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/Gemfile.lock +3 -7
- data/active_element.gemspec +1 -1
- data/app/assets/javascripts/active_element/application.js +3 -1
- data/app/assets/javascripts/active_element/popover.js +6 -0
- data/app/assets/javascripts/active_element/setup.js +12 -0
- data/app/assets/javascripts/active_element/{search_field.js → text_search_field.js} +2 -2
- data/app/assets/javascripts/active_element/toast.js +8 -0
- data/app/assets/stylesheets/active_element/application.scss +65 -1
- data/app/controllers/active_element/application_controller.rb +12 -18
- data/app/views/active_element/components/form/_label.html.erb +2 -2
- data/app/views/active_element/components/form/_templates.html.erb +8 -8
- data/app/views/active_element/components/form.html.erb +3 -3
- data/app/views/active_element/components/table/_collection_row.html.erb +3 -3
- data/app/views/active_element/components/table/collection.html.erb +1 -1
- data/app/views/active_element/components/table/item.html.erb +3 -3
- data/app/views/active_element/navbar/_menu.html.erb +2 -2
- data/app/views/layouts/active_element.html.erb +21 -23
- data/config/routes.rb +10 -1
- data/lib/active_element/components/button.rb +6 -41
- data/lib/active_element/components/form.rb +12 -3
- data/lib/active_element/components/text_search/active_record_authorization.rb +13 -0
- data/lib/active_element/components/text_search/authorization.rb +117 -0
- data/lib/active_element/components/text_search/component.rb +118 -0
- data/lib/active_element/components/text_search/sql.rb +107 -0
- data/lib/active_element/components/text_search.rb +23 -0
- data/lib/active_element/components/util/decorator.rb +2 -2
- data/lib/active_element/components/util/record_path.rb +84 -0
- data/lib/active_element/components/util.rb +7 -2
- data/lib/active_element/components.rb +1 -0
- data/lib/active_element/controller_action.rb +9 -10
- data/lib/active_element/controller_interface.rb +78 -0
- data/lib/active_element/permissions_check.rb +33 -29
- data/lib/active_element/permissions_report.rb +57 -0
- data/lib/active_element/route.rb +1 -1
- data/lib/active_element/routes.rb +1 -1
- data/lib/active_element/version.rb +1 -1
- data/lib/active_element.rb +24 -10
- data/lib/tasks/active_element.rake +1 -16
- data/rspec-documentation/pages/Components/Tables.md +2 -2
- data/rspec-documentation/spec_helper.rb +1 -1
- metadata +19 -12
- data/app/controllers/active_element/text_searches_controller.rb +0 -189
- data/lib/active_element/active_record_text_search_authorization.rb +0 -12
- data/lib/active_element/colorized_string.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55c4ed1b8eb3233fc4c071184ac145f01888d72b751fafafa68ff32873600e15
|
4
|
+
data.tar.gz: ce1fba3786c8b1084678a26f27bb72107fdfec3de8dec53e6ccf4d45e32d526c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f3461c71414a3264a4e8911e642a5ca2fddbcf8cb456eef49f777a86eae69b094a35e7e133401428d4168062198a88fe63e6c909e62dab46ca965d00d7aa85e
|
7
|
+
data.tar.gz: 469fb951cb7ccd0ab11ebb54b207d2c59ca5a8fbe2fc06f49d3ef58aaff69389870ec39e48b2c243a503ac036ae8d198e19c6120b7a4d881ba56a5b839f66e0f
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
active_element (0.0.
|
4
|
+
active_element (0.0.5)
|
5
5
|
bootstrap (~> 5.3.0alpha3)
|
6
|
-
faraday (~> 2.7)
|
7
6
|
kaminari (~> 1.2)
|
7
|
+
paintbrush (~> 0.1.2)
|
8
8
|
rails (~> 6.1)
|
9
9
|
rouge (~> 4.1)
|
10
10
|
sassc (~> 2.4)
|
@@ -102,10 +102,6 @@ GEM
|
|
102
102
|
factory_bot_rails (5.2.0)
|
103
103
|
factory_bot (~> 5.2.0)
|
104
104
|
railties (>= 4.2.0)
|
105
|
-
faraday (2.7.5)
|
106
|
-
faraday-net_http (>= 2.0, < 3.1)
|
107
|
-
ruby2_keywords (>= 0.0.4)
|
108
|
-
faraday-net_http (3.0.2)
|
109
105
|
ffi (1.15.5)
|
110
106
|
globalid (1.1.0)
|
111
107
|
activesupport (>= 5.0)
|
@@ -153,6 +149,7 @@ GEM
|
|
153
149
|
racc (~> 1.4)
|
154
150
|
orm_adapter (0.5.0)
|
155
151
|
paint (2.3.0)
|
152
|
+
paintbrush (0.1.2)
|
156
153
|
parallel (1.23.0)
|
157
154
|
parser (3.2.2.1)
|
158
155
|
ast (~> 2.4.1)
|
@@ -252,7 +249,6 @@ GEM
|
|
252
249
|
rubocop-capybara (~> 2.17)
|
253
250
|
rubocop-factory_bot (~> 2.22)
|
254
251
|
ruby-progressbar (1.13.0)
|
255
|
-
ruby2_keywords (0.0.5)
|
256
252
|
sassc (2.4.0)
|
257
253
|
ffi (~> 1.9)
|
258
254
|
sassc-rails (2.1.2)
|
data/active_element.gemspec
CHANGED
@@ -31,8 +31,8 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
32
32
|
|
33
33
|
spec.add_runtime_dependency 'bootstrap', '~> 5.3.0alpha3'
|
34
|
-
spec.add_runtime_dependency 'faraday', '~> 2.7'
|
35
34
|
spec.add_runtime_dependency 'kaminari', '~> 1.2'
|
35
|
+
spec.add_runtime_dependency 'paintbrush', '~> 0.1.2'
|
36
36
|
spec.add_runtime_dependency 'rails', '~> 6.1'
|
37
37
|
spec.add_runtime_dependency 'rouge', '~> 4.1'
|
38
38
|
spec.add_runtime_dependency 'sassc', '~> 2.4'
|
@@ -4,7 +4,9 @@
|
|
4
4
|
//= require active_element/theme
|
5
5
|
//= require active_element/secret
|
6
6
|
//= require active_element/json_field
|
7
|
-
//= require active_element/
|
7
|
+
//= require active_element/text_search_field
|
8
8
|
//= require active_element/form
|
9
9
|
//= require active_element/confirm
|
10
10
|
//= require active_element/pagination
|
11
|
+
//= require active_element/toast
|
12
|
+
//= require active_element/popover
|
@@ -20,6 +20,17 @@
|
|
20
20
|
return element;
|
21
21
|
};
|
22
22
|
|
23
|
+
const navbar = document.querySelector('.navbar.application-menu');
|
24
|
+
|
25
|
+
window.addEventListener('scroll', () => {
|
26
|
+
if (window.scrollY > 50) {
|
27
|
+
navbar.classList.add('shrink');
|
28
|
+
} else {
|
29
|
+
navbar.classList.remove('shrink');
|
30
|
+
}
|
31
|
+
});
|
32
|
+
|
33
|
+
|
23
34
|
const ActiveElement = {
|
24
35
|
log: (message) => { console.log(`[ActiveElement] ${message}`); },
|
25
36
|
_id: 0,
|
@@ -28,6 +39,7 @@
|
|
28
39
|
cloneElement,
|
29
40
|
components: {},
|
30
41
|
jsonData: {},
|
42
|
+
controller_path: document.querySelector('meta[name="active_element_controller_path"]').content
|
31
43
|
};
|
32
44
|
|
33
45
|
window.ActiveElement = ActiveElement;
|
@@ -37,7 +37,7 @@
|
|
37
37
|
resultsItem.innerText = attributes.length === 0 ? value : `${attributes.join(', ')} (${value})`;
|
38
38
|
resultsItem.addEventListener('click', () => {
|
39
39
|
hiddenInput.value = value;
|
40
|
-
element.value =
|
40
|
+
element.value = value;
|
41
41
|
searchResultsContainer.replaceChildren();
|
42
42
|
searchResultsContainer.classList.add('d-none');
|
43
43
|
});
|
@@ -97,7 +97,7 @@
|
|
97
97
|
searchResultsContainer.replaceChildren();
|
98
98
|
|
99
99
|
fetch(
|
100
|
-
|
100
|
+
`/${ActiveElement.controller_path}/_active_element_text_search/`,
|
101
101
|
{
|
102
102
|
method: 'POST',
|
103
103
|
headers: { 'Content-Type': 'application/json' },
|
@@ -0,0 +1,8 @@
|
|
1
|
+
(() => {
|
2
|
+
const elements = [].slice.call(document.querySelectorAll('.toast'));
|
3
|
+
const toasts = elements.map(function (element) {
|
4
|
+
return new bootstrap.Toast(element, { animation: true, autohide: true, delay: 10000 })
|
5
|
+
});
|
6
|
+
|
7
|
+
toasts.forEach((toast) => toast.show());
|
8
|
+
})();
|
@@ -1,7 +1,22 @@
|
|
1
1
|
@import "variables";
|
2
2
|
@import "bootstrap";
|
3
3
|
|
4
|
-
.navbar-
|
4
|
+
.navbar.application-menu {
|
5
|
+
height: 5rem;
|
6
|
+
transition: height 0.5s ease-in-out, background-position 0.8s ease-in-out;
|
7
|
+
background-position: right 1.2rem center;
|
8
|
+
background-repeat: no-repeat;
|
9
|
+
|
10
|
+
&.shrink {
|
11
|
+
height: 3rem;
|
12
|
+
background-position: right -50rem center;
|
13
|
+
}
|
14
|
+
|
15
|
+
&:hover {
|
16
|
+
height: 5rem;
|
17
|
+
background-position: right 1.2rem center;
|
18
|
+
background-repeat: no-repeat;
|
19
|
+
}
|
5
20
|
}
|
6
21
|
|
7
22
|
td.action-column {
|
@@ -51,6 +66,55 @@ form {
|
|
51
66
|
}
|
52
67
|
}
|
53
68
|
|
69
|
+
.search-field-results {
|
70
|
+
min-width: 20rem;
|
71
|
+
position: absolute;
|
72
|
+
.search-field-result {
|
73
|
+
cursor: pointer;
|
74
|
+
&:hover {
|
75
|
+
background-color: #{$blue};
|
76
|
+
color: #{$white};
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
.flash.toast {
|
82
|
+
position: absolute;
|
83
|
+
margin-top: 2rem;
|
84
|
+
margin-right: 1rem;
|
85
|
+
padding: 0;
|
86
|
+
|
87
|
+
&.notice {
|
88
|
+
.toast-body {
|
89
|
+
background: #{$blue-100};
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
&.alert {
|
94
|
+
.toast-body {
|
95
|
+
background: #{$red-100};
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
[data-bs-theme="dark"] {
|
101
|
+
.flash.toast {
|
102
|
+
&.notice {
|
103
|
+
.toast-body {
|
104
|
+
color: #{$white};
|
105
|
+
background: #{$blue-700};
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
&.alert {
|
110
|
+
.toast-body {
|
111
|
+
color: #{$white};
|
112
|
+
background: #{$red-700};
|
113
|
+
}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
54
118
|
#theme-select {
|
55
119
|
font-size: 1.5rem;
|
56
120
|
padding: 0.2rem 0.8rem;
|
@@ -8,34 +8,28 @@ module ActiveElement
|
|
8
8
|
|
9
9
|
layout 'active_element'
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
helper_method :active_element_component
|
15
|
-
helper_method :render_active_element_hook
|
16
|
-
|
17
|
-
def self.permit_user(permissions, **kwargs)
|
18
|
-
active_element_permissions << [permissions, kwargs]
|
19
|
-
|
20
|
-
nil
|
11
|
+
def self.active_element
|
12
|
+
@active_element ||= ActiveElement::ControllerInterface.new(self)
|
21
13
|
end
|
22
14
|
|
23
|
-
def
|
24
|
-
@
|
15
|
+
def active_element
|
16
|
+
@active_element ||= ActiveElement::ControllerInterface.new(self.class, self)
|
25
17
|
end
|
26
18
|
|
19
|
+
before_action -> { active_element.authenticator&.call }
|
20
|
+
before_action -> { ActiveElement::ControllerAction.new(self).process_action }
|
21
|
+
|
22
|
+
helper_method :active_element
|
23
|
+
helper_method :render_active_element_hook
|
24
|
+
|
27
25
|
def render_active_element_hook(hook)
|
28
26
|
render_to_string partial: hook
|
29
27
|
rescue ActionView::MissingTemplate
|
30
28
|
nil
|
31
29
|
end
|
32
30
|
|
33
|
-
def
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.active_element_permissions
|
38
|
-
@active_element_permissions ||= []
|
31
|
+
def _active_element_text_search
|
32
|
+
render(**ActiveElement::Components::TextSearch::Component.new(controller: self).response)
|
39
33
|
end
|
40
34
|
end
|
41
35
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
<%= form.label field
|
1
|
+
<%= form.label field do %>
|
2
|
+
<%= options[:label] %>
|
2
3
|
<% if options[:description].present? %>
|
3
|
-
<%= options[:label] %>
|
4
4
|
<button type="button"
|
5
5
|
style="background: none; border: none; outline: 0; position: absolute; margin-top: 0.3rem"
|
6
6
|
data-bs-toggle="popover"
|
@@ -17,25 +17,25 @@
|
|
17
17
|
|
18
18
|
<select id="json-select-template" class="form-select m-1 json-select-field"></select>
|
19
19
|
|
20
|
-
<%=
|
20
|
+
<%= active_element.component.destroy_button id: 'json-delete-button-template',
|
21
21
|
class: 'button-sm json-delete-button' %>
|
22
22
|
|
23
|
-
<%=
|
23
|
+
<%= active_element.component.button 'Delete Item', type: 'danger', id: 'json-delete-object-button-template',
|
24
24
|
class: 'json-delete-button w-25 float-end json-delete-object-button' %>
|
25
25
|
|
26
|
-
<%=
|
26
|
+
<%= active_element.component.button id: 'json-append-button-template',
|
27
27
|
class: 'btn-sm mt-3 mb-3 json-add-field-button' %>
|
28
28
|
|
29
|
-
<%=
|
29
|
+
<%= active_element.component.button 'Hide', id: 'json-expand-collapse-button-template',
|
30
30
|
class: 'float-end expand-collapse-button' %>
|
31
31
|
|
32
32
|
</div>
|
33
33
|
|
34
|
-
<%=
|
34
|
+
<%= active_element.component.button 'Expand Form', id: 'form-expand-button-template', class: 'mb-1 btn-sm' do %>
|
35
35
|
<i class="fa-solid fa-fw fa-up-right-and-down-left-from-center"></i>
|
36
36
|
<% end %>
|
37
37
|
|
38
|
-
<%=
|
38
|
+
<%= active_element.component.button 'Collapse Form', id: 'form-collapse-button-template', class: 'mb-1 btn-sm' do %>
|
39
39
|
<i class="fa-solid fa-fw fa-down-left-and-up-right-to-center"></i>
|
40
40
|
<% end %>
|
41
41
|
|
@@ -76,10 +76,10 @@
|
|
76
76
|
</div>
|
77
77
|
|
78
78
|
<div id="form-confirm-button-template">
|
79
|
-
<%=
|
79
|
+
<%= active_element.component.button 'Confirm' %>
|
80
80
|
</div>
|
81
81
|
|
82
82
|
<div id="form-cancel-button-template">
|
83
|
-
<%=
|
83
|
+
<%= active_element.component.button 'Cancel' %>
|
84
84
|
</div>
|
85
85
|
</div>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% if destroy %>
|
2
|
-
<%=
|
2
|
+
<%= active_element.component.destroy_button(record, float: 'end') %>
|
3
3
|
<% end %>
|
4
4
|
|
5
5
|
<% if modal %>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<div class="mt-4 mb-5 ms-3">
|
8
8
|
|
9
9
|
<div class="p-3 pb-4 border-bottom d-inline">
|
10
|
-
<%=
|
10
|
+
<%= active_element.component.button(
|
11
11
|
title: title.presence || 'Show Form',
|
12
12
|
icon: 'arrow-up-right-dots',
|
13
13
|
data: { field_type: 'form-modal', form_id: id, form_title: title }) %>
|
@@ -40,7 +40,7 @@
|
|
40
40
|
<%= form_with local: true, **kwargs, method: method, id: id, class: "#{class_name} m-3 #{modal == false && expanded == false ? 'd-none' : nil}" do |form| %>
|
41
41
|
<% if %i[top both].include?(submit_position) %>
|
42
42
|
<div class="form-group sticky-top" style="top: 0.5rem;">
|
43
|
-
<%= form.submit submit_label, class:
|
43
|
+
<%= form.submit submit_label, class: "btn btn-#{method == :post ? 'success' : 'primary'} float-end" %>
|
44
44
|
</div>
|
45
45
|
<% end %>
|
46
46
|
|
@@ -12,19 +12,19 @@
|
|
12
12
|
|
13
13
|
<% if show %>
|
14
14
|
<td class="<%= "#{class_name}-show" %> action-column text-end">
|
15
|
-
<%=
|
15
|
+
<%= active_element.component.show_button(item, show, class: 'btn-sm') %>
|
16
16
|
</td>
|
17
17
|
<% end %>
|
18
18
|
|
19
19
|
<% if edit %>
|
20
20
|
<td class="<%= "#{class_name}-edit" %> action-column text-end">
|
21
|
-
<%=
|
21
|
+
<%= active_element.component.edit_button(item, show, class: 'btn-sm') %>
|
22
22
|
</td>
|
23
23
|
<% end %>
|
24
24
|
|
25
25
|
<% if destroy %>
|
26
26
|
<td class="<%= "#{class_name}-destroy" %> action-column text-end">
|
27
|
-
<%=
|
27
|
+
<%= active_element.component.destroy_button(item, destroy, class: 'btn-sm') %>
|
28
28
|
</td>
|
29
29
|
<% end %>
|
30
30
|
</tr>
|
@@ -1,13 +1,13 @@
|
|
1
1
|
<% if destroy && item.present? %>
|
2
|
-
<%=
|
2
|
+
<%= active_element.component.destroy_button(item, destroy, float: 'end') %>
|
3
3
|
<% end %>
|
4
4
|
|
5
5
|
<% if edit && item.present? %>
|
6
|
-
<%=
|
6
|
+
<%= active_element.component.edit_button(item, edit, float: 'end') %>
|
7
7
|
<% end %>
|
8
8
|
|
9
9
|
<% if new %>
|
10
|
-
<%=
|
10
|
+
<%= active_element.component.new_button(item, float: 'end', class: 'mb-3') %>
|
11
11
|
<% end %>
|
12
12
|
|
13
13
|
<table class="<%= class_name %> table" style="<%= style %>">
|
@@ -7,14 +7,14 @@
|
|
7
7
|
</button>
|
8
8
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
9
9
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
10
|
-
<% ActiveElement.navbar_items(current_user).each do |navbar_item| %>
|
10
|
+
<% ActiveElement.navbar_items(active_element.current_user).each do |navbar_item| %>
|
11
11
|
<li class="nav-item">
|
12
12
|
<%=
|
13
13
|
link_to navbar_item.fetch(:title) { navbar_item.fetch(:label) },
|
14
14
|
navbar_item.fetch(:path),
|
15
15
|
class: "nav-link #{
|
16
16
|
ActiveElement.active_path_class(
|
17
|
-
user: current_user,
|
17
|
+
user: active_element.current_user,
|
18
18
|
current_navbar_item: navbar_item,
|
19
19
|
current_path: request.path,
|
20
20
|
controller_path: controller_path,
|
@@ -7,18 +7,15 @@
|
|
7
7
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.9.2/umd/popper.min.js" integrity="sha512-2rNj2KJ+D8s1ceNasTIex6z4HWyOnEYLVC3FigGOmyQCZc2eBXKgOxQmo3oKLHyfcj53uz4QMsRCWNbLd32Q1g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
8
8
|
|
9
9
|
<%= stylesheet_link_tag 'active_element/application', 'data-turbolinks-track': 'reload' %>
|
10
|
-
<%= javascript_include_tag 'active_element/application', 'data-turbolinks-track': 'reload' %>
|
11
10
|
|
12
11
|
<% if Rails.application.assets.find_asset('application.css').present? %>
|
13
12
|
<%= stylesheet_link_tag 'application', 'data-turbolinks-track': 'reload' %>
|
14
13
|
<% end %>
|
15
14
|
|
16
|
-
<% if Rails.application.assets.find_asset('application.js').present? %>
|
17
|
-
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
|
18
|
-
<% end %>
|
19
|
-
|
20
15
|
<%= csrf_meta_tag %>
|
21
16
|
|
17
|
+
<meta name="active_element_controller_path" content="<%= controller_path %>">
|
18
|
+
|
22
19
|
<%= render_active_element_hook 'active_element/after_head' %>
|
23
20
|
</head>
|
24
21
|
|
@@ -28,11 +25,21 @@
|
|
28
25
|
<%= render_active_element_hook 'active_element/after_navbar' %>
|
29
26
|
|
30
27
|
<% flash.each do |type, message| %>
|
31
|
-
<div class="flash
|
32
|
-
|
33
|
-
|
34
|
-
<
|
35
|
-
|
28
|
+
<div class="flash toast <%= type %> position-absolute top-0 end-0 mt-5" role="alert" aria-live="assertive" aria-atomic="true">
|
29
|
+
<div class="toast-header">
|
30
|
+
<% if type == 'notice' %>
|
31
|
+
<i class="fa-solid me-2 text-info fa-circle-info"></i>
|
32
|
+
<% elsif type == 'alert' %>
|
33
|
+
<i class="fa-solid me-2 text-danger fa-circle-exclamation"></i>
|
34
|
+
<% else %>
|
35
|
+
<i class="fa-solid me-2 text-info fa-circle-info"></i>
|
36
|
+
<% end %>
|
37
|
+
<strong class="me-auto"><%= type.titleize %></strong>
|
38
|
+
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
39
|
+
</div>
|
40
|
+
<div class="toast-body fw-bold align-middle">
|
41
|
+
<%= message %>
|
42
|
+
</div>
|
36
43
|
</div>
|
37
44
|
<% end %>
|
38
45
|
|
@@ -48,18 +55,9 @@
|
|
48
55
|
|
49
56
|
<%= render_active_element_hook 'active_element/after_content' %>
|
50
57
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
})
|
56
|
-
|
57
|
-
document.querySelectorAll('.flash .btn-close').forEach(element => {
|
58
|
-
element.onclick = ev => {
|
59
|
-
ev.stopPropagation();
|
60
|
-
ev.target.parentElement.parentElement.classList.add('d-none');
|
61
|
-
};
|
62
|
-
});
|
63
|
-
</script>
|
58
|
+
<%= javascript_include_tag 'active_element/application', 'data-turbolinks-track': 'reload' %>
|
59
|
+
<% if Rails.application.assets.find_asset('application.js').present? %>
|
60
|
+
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
|
61
|
+
<% end %>
|
64
62
|
</body>
|
65
63
|
</html>
|
data/config/routes.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
ActiveElement::Engine.routes.draw do
|
4
|
-
|
4
|
+
ActiveElement.eager_load_controllers
|
5
|
+
|
6
|
+
ActiveElement::ApplicationController.descendants.map do |descendant|
|
7
|
+
post "#{descendant.controller_path}/_active_element_text_search",
|
8
|
+
controller: descendant.controller_path,
|
9
|
+
action: '_active_element_text_search'
|
10
|
+
|
11
|
+
# Permissions for text search are managed by ActiveElement::Components::TextSearch::Authorization
|
12
|
+
descendant.active_element.permit_action :_active_element_text_search, always: true
|
13
|
+
end
|
5
14
|
end
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module ActiveElement
|
4
4
|
module Components
|
5
5
|
# A clickable button.
|
6
|
-
# rubocop:disable Metrics/ClassLength
|
7
6
|
class Button
|
8
7
|
# rubocop:disable Metrics/MethodLength
|
9
8
|
def initialize(controller, record, flag_or_options, confirm: false, type: :primary, method: nil,
|
@@ -75,45 +74,6 @@ module ActiveElement
|
|
75
74
|
{ 'end' => 'float-end', 'start' => 'float-start', nil => nil }.fetch(float)
|
76
75
|
end
|
77
76
|
|
78
|
-
def namespace_prefix
|
79
|
-
# XXX: We guess the namespace from the current controller's module name. This will work
|
80
|
-
# most of the time but will break the current record's controller exists in a different
|
81
|
-
# namespace to the current controller, e.g. `BackEndAdmin::UsersController` and
|
82
|
-
# `FrontEndAdmin::ThemesController` - if `FrontEndAdmin::ThemesController` renders a
|
83
|
-
# collection of `User` objects, the "show" path will be wrong:
|
84
|
-
# `front_end_admin_user_path`. Maybe descend through the full controller class tree to
|
85
|
-
# find a best match ?
|
86
|
-
namespace = controller.class.name.deconstantize.underscore
|
87
|
-
return nil if namespace.blank?
|
88
|
-
|
89
|
-
"#{namespace}_"
|
90
|
-
end
|
91
|
-
|
92
|
-
def record_path
|
93
|
-
return nil if record.nil?
|
94
|
-
|
95
|
-
controller.helpers.public_send(default_record_path, record)
|
96
|
-
rescue NoMethodError
|
97
|
-
controller.helpers.public_send(sti_record_path, record)
|
98
|
-
end
|
99
|
-
|
100
|
-
def default_record_path
|
101
|
-
"#{record_path_prefix}#{namespace_prefix}#{record_name}_path"
|
102
|
-
end
|
103
|
-
|
104
|
-
def sti_record_path
|
105
|
-
"#{record_path_prefix}#{namespace_prefix}#{sti_record_name}_path"
|
106
|
-
end
|
107
|
-
|
108
|
-
def record_path_prefix
|
109
|
-
case type
|
110
|
-
when :edit
|
111
|
-
'edit_'
|
112
|
-
when :new
|
113
|
-
'new_'
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
77
|
def title
|
118
78
|
return flag_or_options[:title] if flag_or_options.is_a?(Hash) && flag_or_options[:title].present?
|
119
79
|
return default_action_title if %i[show destroy edit new].include?(type)
|
@@ -150,7 +110,12 @@ module ActiveElement
|
|
150
110
|
def sti_record_name
|
151
111
|
Util.sti_record_name(record)
|
152
112
|
end
|
113
|
+
|
114
|
+
def record_path
|
115
|
+
return nil unless record.class.is_a?(ActiveModel::Naming)
|
116
|
+
|
117
|
+
Util::RecordPath.new(record: record, controller: controller, type: type).path
|
118
|
+
end
|
153
119
|
end
|
154
120
|
end
|
155
|
-
# rubocop:enable Metrics/ClassLength
|
156
121
|
end
|
@@ -22,6 +22,7 @@ module ActiveElement
|
|
22
22
|
@modal = modal
|
23
23
|
@kwargs = kwargs
|
24
24
|
@columns = columns
|
25
|
+
@action = kwargs.delete(:action) { default_action }
|
25
26
|
@method = kwargs.delete(:method) { default_method }.to_s.downcase.to_sym
|
26
27
|
end
|
27
28
|
# rubocop:enable Metrics/MethodLength
|
@@ -30,7 +31,7 @@ module ActiveElement
|
|
30
31
|
'active_element/components/form'
|
31
32
|
end
|
32
33
|
|
33
|
-
def locals # rubocop:disable Metrics/MethodLength
|
34
|
+
def locals # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
34
35
|
{
|
35
36
|
component: self,
|
36
37
|
fields: Util::FormFieldMapping.new(record, fields, i18n).fields_with_types_and_options,
|
@@ -39,6 +40,7 @@ module ActiveElement
|
|
39
40
|
submit_position: submit_position,
|
40
41
|
class_name: class_name,
|
41
42
|
method: method,
|
43
|
+
action: action,
|
42
44
|
kwargs: kwargs,
|
43
45
|
destroy: destroy,
|
44
46
|
modal: modal,
|
@@ -130,7 +132,8 @@ module ActiveElement
|
|
130
132
|
|
131
133
|
private
|
132
134
|
|
133
|
-
attr_reader :fields, :submit, :title, :kwargs, :item, :method, :
|
135
|
+
attr_reader :fields, :submit, :title, :kwargs, :item, :method, :action,
|
136
|
+
:destroy, :modal, :expanded, :columns
|
134
137
|
|
135
138
|
def valid_field?(field)
|
136
139
|
return true if record.respond_to?("#{field}_changed?") && !record.public_send("#{field}_changed?")
|
@@ -197,7 +200,7 @@ module ActiveElement
|
|
197
200
|
|
198
201
|
def default_method
|
199
202
|
case controller.action_name
|
200
|
-
when 'edit'
|
203
|
+
when 'edit', 'update'
|
201
204
|
'PATCH'
|
202
205
|
when 'index'
|
203
206
|
'GET'
|
@@ -205,6 +208,12 @@ module ActiveElement
|
|
205
208
|
'POST'
|
206
209
|
end
|
207
210
|
end
|
211
|
+
|
212
|
+
def default_action
|
213
|
+
return controller.request.path unless record.is_a?(ActiveModel::Naming)
|
214
|
+
|
215
|
+
Util::RecordPath.new(record: record, controller: controller).path
|
216
|
+
end
|
208
217
|
end
|
209
218
|
end
|
210
219
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
ActiveRecord::Base.class_eval do
|
4
|
+
class << self
|
5
|
+
def authorize_active_element_text_search(with:, providing:)
|
6
|
+
ActiveElement::Components::TextSearch.register_authorized_text_search(
|
7
|
+
model: self,
|
8
|
+
with: with,
|
9
|
+
providing: providing
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|