active_element 0.0.2 → 0.0.4
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 +1 -1
- data/Gemfile.lock +8 -9
- 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 +13 -19
- 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/app/views/layouts/active_element_error.html.erb +1 -1
- 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: f044724b30fa122fb6700ecd4afa352e26d4b920aec89ee4ff3548cb2ef66c20
|
4
|
+
data.tar.gz: 5b0fab5e11fea56667782189c3ebdcdfe95fcc0935fa93ddfeb9ad9d7f8015af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9dc8ec715c992280a32943a7a2e6190d3af8d87260145aed268b94bdee2f3d4b574ddf5f10fdfd9de68f5d651da1958c120b4e08945099c65700a52bcd7e752
|
7
|
+
data.tar.gz: a400b8fbe592d4af7bd347aeb7f4e0ae2fe3597f0edba862c01ffc4cd15eeb6ba5fe1ead8dcbb8e5f43f23cbdc9242ef197d5b4861add208f8656e9c900728ea
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
@@ -8,9 +8,9 @@ gemspec
|
|
8
8
|
gem 'devise', '~> 4.9'
|
9
9
|
gem 'devpack', '~> 0.4.1'
|
10
10
|
gem 'factory_bot_rails', '~> 5.2'
|
11
|
+
gem 'paintbrush', path: '../paintbrush'
|
11
12
|
gem 'rake', '~> 13.0'
|
12
13
|
gem 'rspec', '~> 3.12'
|
13
|
-
gem 'rspec-documentation'
|
14
14
|
gem 'rspec-file_fixtures', '~> 0.1.6'
|
15
15
|
gem 'rspec-html', '~> 0.3.2'
|
16
16
|
gem 'rspec-its', '~> 1.3'
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,15 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ../paintbrush
|
3
|
+
specs:
|
4
|
+
paintbrush (0.1.1)
|
5
|
+
|
1
6
|
PATH
|
2
7
|
remote: .
|
3
8
|
specs:
|
4
|
-
active_element (0.0.
|
9
|
+
active_element (0.0.4)
|
5
10
|
bootstrap (~> 5.3.0alpha3)
|
6
|
-
faraday (~> 2.7)
|
7
11
|
kaminari (~> 1.2)
|
12
|
+
paintbrush (~> 0.1.1)
|
8
13
|
rails (~> 6.1)
|
9
14
|
rouge (~> 4.1)
|
10
15
|
sassc (~> 2.4)
|
@@ -102,10 +107,6 @@ GEM
|
|
102
107
|
factory_bot_rails (5.2.0)
|
103
108
|
factory_bot (~> 5.2.0)
|
104
109
|
railties (>= 4.2.0)
|
105
|
-
faraday (2.7.4)
|
106
|
-
faraday-net_http (>= 2.0, < 3.1)
|
107
|
-
ruby2_keywords (>= 0.0.4)
|
108
|
-
faraday-net_http (3.0.2)
|
109
110
|
ffi (1.15.5)
|
110
111
|
globalid (1.1.0)
|
111
112
|
activesupport (>= 5.0)
|
@@ -202,7 +203,6 @@ GEM
|
|
202
203
|
rspec-mocks (~> 3.12.0)
|
203
204
|
rspec-core (3.12.2)
|
204
205
|
rspec-support (~> 3.12.0)
|
205
|
-
rspec-documentation (0.0.1)
|
206
206
|
rspec-expectations (3.12.3)
|
207
207
|
diff-lcs (>= 1.2.0, < 2.0)
|
208
208
|
rspec-support (~> 3.12.0)
|
@@ -253,7 +253,6 @@ GEM
|
|
253
253
|
rubocop-capybara (~> 2.17)
|
254
254
|
rubocop-factory_bot (~> 2.22)
|
255
255
|
ruby-progressbar (1.13.0)
|
256
|
-
ruby2_keywords (0.0.5)
|
257
256
|
sassc (2.4.0)
|
258
257
|
ffi (~> 1.9)
|
259
258
|
sassc-rails (2.1.2)
|
@@ -299,9 +298,9 @@ DEPENDENCIES
|
|
299
298
|
devise (~> 4.9)
|
300
299
|
devpack (~> 0.4.1)
|
301
300
|
factory_bot_rails (~> 5.2)
|
301
|
+
paintbrush!
|
302
302
|
rake (~> 13.0)
|
303
303
|
rspec (~> 3.12)
|
304
|
-
rspec-documentation
|
305
304
|
rspec-file_fixtures (~> 0.1.6)
|
306
305
|
rspec-html (~> 0.3.2)
|
307
306
|
rspec-its (~> 1.3)
|
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.1'
|
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
|
-
render_to_string partial:
|
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
|