active_element 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -0
- data/.strong_versions.yml +2 -0
- data/Gemfile +10 -2
- data/Gemfile.lock +229 -4
- data/Rakefile +1 -0
- data/active_element.gemspec +7 -0
- data/app/assets/config/active_element/manifest.js +2 -0
- data/app/assets/javascripts/active_element/application.js +10 -0
- data/app/assets/javascripts/active_element/confirm.js +67 -0
- data/app/assets/javascripts/active_element/form.js +61 -0
- data/app/assets/javascripts/active_element/json_field.js +316 -0
- data/app/assets/javascripts/active_element/pagination.js +18 -0
- data/app/assets/javascripts/active_element/search_field.js +127 -0
- data/app/assets/javascripts/active_element/secret.js +40 -0
- data/app/assets/javascripts/active_element/setup.js +36 -0
- data/app/assets/javascripts/active_element/theme.js +42 -0
- data/app/assets/stylesheets/active_element/_variables.scss +142 -0
- data/app/assets/stylesheets/active_element/application.scss +77 -0
- data/app/controllers/active_element/application_controller.rb +41 -0
- data/app/controllers/active_element/text_searches_controller.rb +189 -0
- data/app/views/active_element/components/_horizontal_tabs.html.erb +32 -0
- data/app/views/active_element/components/_vertical_tabs.html.erb +38 -0
- data/app/views/active_element/components/button.html.erb +27 -0
- data/app/views/active_element/components/fields/_boolean.html.erb +11 -0
- data/app/views/active_element/components/form/_check_box.html.erb +3 -0
- data/app/views/active_element/components/form/_check_boxes.html.erb +33 -0
- data/app/views/active_element/components/form/_field.html.erb +28 -0
- data/app/views/active_element/components/form/_generic_field.html.erb +3 -0
- data/app/views/active_element/components/form/_json.html.erb +12 -0
- data/app/views/active_element/components/form/_label.html.erb +17 -0
- data/app/views/active_element/components/form/_option_groups_summary.html.erb +17 -0
- data/app/views/active_element/components/form/_select.html.erb +4 -0
- data/app/views/active_element/components/form/_summary.html.erb +40 -0
- data/app/views/active_element/components/form/_templates.html.erb +85 -0
- data/app/views/active_element/components/form/_text_area.html.erb +4 -0
- data/app/views/active_element/components/form/_text_search.html.erb +16 -0
- data/app/views/active_element/components/form.html.erb +78 -0
- data/app/views/active_element/components/json.html.erb +8 -0
- data/app/views/active_element/components/page_description.html.erb +3 -0
- data/app/views/active_element/components/secret/_field.html.erb +1 -0
- data/app/views/active_element/components/secret/_templates.html.erb +11 -0
- data/app/views/active_element/components/table/_collection_row.html.erb +30 -0
- data/app/views/active_element/components/table/_grouped_collection.html.erb +88 -0
- data/app/views/active_element/components/table/_pagination.html.erb +17 -0
- data/app/views/active_element/components/table/_ungrouped_collection.html.erb +49 -0
- data/app/views/active_element/components/table/collection.html.erb +39 -0
- data/app/views/active_element/components/table/item.html.erb +39 -0
- data/app/views/active_element/components/tabs.html.erb +7 -0
- data/app/views/active_element/decorators/_boolean.html.erb +5 -0
- data/app/views/active_element/decorators/_date.html.erb +3 -0
- data/app/views/active_element/decorators/_datetime.html.erb +3 -0
- data/app/views/active_element/decorators/_time.html.erb +3 -0
- data/app/views/active_element/forbidden.html.erb +33 -0
- data/app/views/active_element/main_menu/_item.html.erb +9 -0
- data/app/views/active_element/navbar/_menu.html.erb +30 -0
- data/app/views/active_element/theme/_select.html.erb +1 -0
- data/app/views/active_element/theme/_templates.html.erb +6 -0
- data/app/views/kaminari/_first_page.html.erb +3 -0
- data/app/views/kaminari/_gap.html.erb +3 -0
- data/app/views/kaminari/_last_page.html.erb +3 -0
- data/app/views/kaminari/_next_page.html.erb +3 -0
- data/app/views/kaminari/_page.html.erb +9 -0
- data/app/views/kaminari/_paginator.html.erb +17 -0
- data/app/views/kaminari/_prev_page.html.erb +3 -0
- data/app/views/layouts/active_element.html.erb +65 -0
- data/app/views/layouts/active_element_error.html.erb +40 -0
- data/config/routes.rb +5 -0
- data/lib/active_element/active_menu_link.rb +80 -0
- data/lib/active_element/active_record_text_search_authorization.rb +12 -0
- data/lib/active_element/colorized_string.rb +33 -0
- data/lib/active_element/component.rb +122 -0
- data/lib/active_element/components/button.rb +156 -0
- data/lib/active_element/components/collection_table.rb +118 -0
- data/lib/active_element/components/form.rb +210 -0
- data/lib/active_element/components/item_table.rb +57 -0
- data/lib/active_element/components/json.rb +31 -0
- data/lib/active_element/components/link_helpers.rb +9 -0
- data/lib/active_element/components/page_description.rb +28 -0
- data/lib/active_element/components/secret_fields.rb +15 -0
- data/lib/active_element/components/tab.rb +37 -0
- data/lib/active_element/components/tabs.rb +35 -0
- data/lib/active_element/components/translations.rb +18 -0
- data/lib/active_element/components/util/association_mapping.rb +80 -0
- data/lib/active_element/components/util/decorator.rb +107 -0
- data/lib/active_element/components/util/display_value_mapping.rb +48 -0
- data/lib/active_element/components/util/field_mapping.rb +144 -0
- data/lib/active_element/components/util/form_field_mapping.rb +104 -0
- data/lib/active_element/components/util/form_value_mapping.rb +49 -0
- data/lib/active_element/components/util/i18n.rb +66 -0
- data/lib/active_element/components/util/record_mapping.rb +111 -0
- data/lib/active_element/components/util.rb +43 -0
- data/lib/active_element/components.rb +20 -0
- data/lib/active_element/controller_action.rb +91 -0
- data/lib/active_element/engine.rb +26 -0
- data/lib/active_element/permissions_check.rb +101 -0
- data/lib/active_element/rails_component.rb +40 -0
- data/lib/active_element/route.rb +112 -0
- data/lib/active_element/routes.rb +62 -0
- data/lib/active_element/version.rb +1 -1
- data/lib/active_element.rb +91 -1
- data/lib/tasks/active_element.rake +23 -0
- data/rspec-documentation/dummy +1 -0
- data/rspec-documentation/pages/Components/Forms.md +1 -0
- data/rspec-documentation/pages/Components/Tables.md +47 -0
- data/rspec-documentation/pages/Components/Tabs.md +1 -0
- data/rspec-documentation/pages/Components.md +1 -0
- data/rspec-documentation/pages/Decorators/Inline Decorators.md +1 -0
- data/rspec-documentation/pages/Decorators/View Decorators.md +1 -0
- data/rspec-documentation/pages/Index.md +3 -0
- data/rspec-documentation/pages/Util/I18n.md +1 -0
- data/rspec-documentation/spec_helper.rb +35 -0
- metadata +191 -3
@@ -0,0 +1,40 @@
|
|
1
|
+
<% values = [] %>
|
2
|
+
<% fields.each do |field_name, type, options| %>
|
3
|
+
<% value = component.value_for(field_name) %>
|
4
|
+
|
5
|
+
<% if type == :check_box %>
|
6
|
+
|
7
|
+
<% if ['1', true].include?(value) %>
|
8
|
+
<% values << value %>
|
9
|
+
<div class="d-inline me-3">
|
10
|
+
<i class="text-success fa-regular fa-fw fa-circle-check"></i>
|
11
|
+
<span><%= options.fetch(:label) %></span>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% elsif type == :select %>
|
16
|
+
<% value = component.display_value_for_select(field_name, options) %>
|
17
|
+
<% if value.present? %>
|
18
|
+
<% values << value %>
|
19
|
+
<div class="d-inline me-3">
|
20
|
+
<span class="text-secondary"><%= options.fetch(:label) %>:</span>
|
21
|
+
<span class="ms-1"><%= value %></span>
|
22
|
+
</div>
|
23
|
+
<% end %>
|
24
|
+
<% elsif value.present? %>
|
25
|
+
<%# TODO: Handle other field types %>
|
26
|
+
|
27
|
+
<% values << value %>
|
28
|
+
<div class="d-inline me-3">
|
29
|
+
<span class="text-secondary"><%= options.fetch(:label) %>:</span>
|
30
|
+
<span class="ms-1"><%= value %></span>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<% end %>
|
34
|
+
<% end %>
|
35
|
+
|
36
|
+
<% if values.empty? %>
|
37
|
+
<div class="d-inline ms-3 me-3">
|
38
|
+
<span class="fst-italic text-secondary">(No filters applied)</span>
|
39
|
+
</div>
|
40
|
+
<% end %>
|
@@ -0,0 +1,85 @@
|
|
1
|
+
<div class="d-none" id="form-templates">
|
2
|
+
<div id="json-templates">
|
3
|
+
<ol id="json-list-group-template"></ol>
|
4
|
+
|
5
|
+
<li id="json-list-item-template" class="text-nowrap"></li>
|
6
|
+
|
7
|
+
<label id="json-form-check-label-template" class="form-check-label"></label>
|
8
|
+
<label id="json-label-template" class="mb-4 fw-bold"></label>
|
9
|
+
|
10
|
+
<div id="json-form-group-template" class="form-group p-3 text-wrap m-3"></div>
|
11
|
+
<div id="json-form-group-floating-template" class="form-floating m-3 text-wrap"></div>
|
12
|
+
<div id="json-form-check-template" class="form-check m-3"></div>
|
13
|
+
|
14
|
+
<input id="json-checkbox-field-template" type="checkbox" class="form-check-input json-checkbox-field" />
|
15
|
+
|
16
|
+
<input id="json-text-field-template" type="text" class="form-control m-1 json-text-field" />
|
17
|
+
|
18
|
+
<select id="json-select-template" class="form-select m-1 json-select-field"></select>
|
19
|
+
|
20
|
+
<%= active_element_component.destroy_button id: 'json-delete-button-template',
|
21
|
+
class: 'button-sm json-delete-button' %>
|
22
|
+
|
23
|
+
<%= active_element_component.button 'Delete Item', type: 'danger', id: 'json-delete-object-button-template',
|
24
|
+
class: 'json-delete-button w-25 float-end json-delete-object-button' %>
|
25
|
+
|
26
|
+
<%= active_element_component.button id: 'json-append-button-template',
|
27
|
+
class: 'btn-sm mt-3 mb-3 json-add-field-button' %>
|
28
|
+
|
29
|
+
<%= active_element_component.button 'Hide', id: 'json-expand-collapse-button-template',
|
30
|
+
class: 'float-end expand-collapse-button' %>
|
31
|
+
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<%= active_element_component.button 'Expand Form', id: 'form-expand-button-template', class: 'mb-1 btn-sm' do %>
|
35
|
+
<i class="fa-solid fa-fw fa-up-right-and-down-left-from-center"></i>
|
36
|
+
<% end %>
|
37
|
+
|
38
|
+
<%= active_element_component.button 'Collapse Form', id: 'form-collapse-button-template', class: 'mb-1 btn-sm' do %>
|
39
|
+
<i class="fa-solid fa-fw fa-down-left-and-up-right-to-center"></i>
|
40
|
+
<% end %>
|
41
|
+
|
42
|
+
|
43
|
+
<div id="form-search-field-templates">
|
44
|
+
<input id="form-search-field-hidden-input-template" type="hidden" autocomplete="off" />
|
45
|
+
<p id="form-search-field-response-error-template" class="text-danger position-absolute validation-error-message pt-1 m-0"></p>
|
46
|
+
<div id="form-search-field-results-template" class="search-field-results d-none border border-top-0"></div>
|
47
|
+
<div id="form-search-field-results-item-template" class="search-field-result p-2"></div>
|
48
|
+
<div id="form-search-field-spinner-template" class="invisible text-end">
|
49
|
+
<div style="position: relative; float: right; width: auto; right: 0.5rem; top: -1.7rem;">
|
50
|
+
<i class="fa-solid fa-spinner fa-spin"></i>
|
51
|
+
</div>
|
52
|
+
</div>
|
53
|
+
<div id="form-search-field-clear-button-template" class="invisible text-end">
|
54
|
+
<div style="position: relative; float: right; width: auto; right: 0.5rem; top: -1.7rem;">
|
55
|
+
<i class="fa-solid fa-delete-left" style="cursor: pointer;"></i>
|
56
|
+
</div>
|
57
|
+
</div>
|
58
|
+
</div>
|
59
|
+
|
60
|
+
<div id="form-modal-template"
|
61
|
+
class="modal fade"
|
62
|
+
tabindex="-1"
|
63
|
+
aria-hidden="true">
|
64
|
+
<div class="modal-dialog modal-dialog-centered modal-xl modal-dialog-scrollable">
|
65
|
+
<div class="modal-content">
|
66
|
+
<div class="modal-header">
|
67
|
+
<h5 class="modal-title" data-field-type="modal-title"></h5>
|
68
|
+
<button type="button" class="btn-close fs-3" data-bs-dismiss="modal" aria-label="Close">
|
69
|
+
<i class="fa-regular fa-rectangle-xmark"></i>
|
70
|
+
</button>
|
71
|
+
</div>
|
72
|
+
<div class="modal-body" data-field-type="modal-body"></div>
|
73
|
+
<div class="modal-footer" data-field-type="modal-footer"></div>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
</div>
|
77
|
+
|
78
|
+
<div id="form-confirm-button-template">
|
79
|
+
<%= active_element_component.button 'Confirm' %>
|
80
|
+
</div>
|
81
|
+
|
82
|
+
<div id="form-cancel-button-template">
|
83
|
+
<%= active_element_component.button 'Cancel' %>
|
84
|
+
</div>
|
85
|
+
</div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<%=
|
2
|
+
form.text_field field, value: component.value_for(field),
|
3
|
+
id: "#{form_id}-#{field}-text-search",
|
4
|
+
class: "form-control #{component.valid?(field) ? nil : 'is-invalid'}",
|
5
|
+
autocomplete: 'off',
|
6
|
+
placeholder: options[:placeholder].presence || 'Search...',
|
7
|
+
data: {
|
8
|
+
field_type: 'text-search',
|
9
|
+
form_id: form_id,
|
10
|
+
search_attributes: (
|
11
|
+
options.dig(:search, :attributes) || [options.dig(:search, :attribute)]
|
12
|
+
)&.to_json,
|
13
|
+
search_value: options.dig(:search, :value),
|
14
|
+
search_model: options.dig(:search, :model)
|
15
|
+
}
|
16
|
+
%>
|
@@ -0,0 +1,78 @@
|
|
1
|
+
<% if destroy %>
|
2
|
+
<%= active_element_component.destroy_button(record, float: 'end') %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% if modal %>
|
6
|
+
|
7
|
+
<div class="mt-4 mb-5 ms-3">
|
8
|
+
|
9
|
+
<div class="p-3 pb-4 border-bottom d-inline">
|
10
|
+
<%= active_element_component.button(
|
11
|
+
title: title.presence || 'Show Form',
|
12
|
+
icon: 'arrow-up-right-dots',
|
13
|
+
data: { field_type: 'form-modal', form_id: id, form_title: title }) %>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<div class="form-summary d-inline border-bottom border-start mt-1 p-3 pb-4">
|
17
|
+
<%= render partial: 'active_element/components/form/summary',
|
18
|
+
locals: { fields: fields, component: component } %>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<% elsif title.present? && expanded == false %>
|
24
|
+
|
25
|
+
<div data-field-type="form-expand" data-form-id="<%= id %>" class="mb-3">
|
26
|
+
<span class="fs-4 align-bottom"><%= title %></span>
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<% elsif title.blank? && expanded == false %>
|
30
|
+
|
31
|
+
<div data-field-type="form-expand" data-form-id="<%= id %>" class="mb-3"></div>
|
32
|
+
|
33
|
+
<% elsif title.present? %>
|
34
|
+
|
35
|
+
<span class="fs-4 align-bottom"><%= title %></span>
|
36
|
+
|
37
|
+
<% end %>
|
38
|
+
|
39
|
+
<div class="expand-collapse-form <%= modal ? 'd-none' : nil %>" id="form-wrapper-<%= id %>">
|
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
|
+
<% if %i[top both].include?(submit_position) %>
|
42
|
+
<div class="form-group sticky-top" style="top: 0.5rem;">
|
43
|
+
<%= form.submit submit_label, class: 'btn btn-success float-end' %>
|
44
|
+
</div>
|
45
|
+
<% end %>
|
46
|
+
|
47
|
+
<% fields.each_slice(columns) do |field_group| %>
|
48
|
+
<div class="row mb-3">
|
49
|
+
<% field_group.each do |field, type, options| %>
|
50
|
+
<div class="col-sm-3">
|
51
|
+
<%= render partial: 'active_element/components/form/label',
|
52
|
+
locals: { type: type, form: form, field: field, options: options } %>
|
53
|
+
</div>
|
54
|
+
|
55
|
+
|
56
|
+
<div class="col">
|
57
|
+
<%= render partial: 'active_element/components/form/field',
|
58
|
+
locals: {
|
59
|
+
id: id,
|
60
|
+
type: type,
|
61
|
+
form: form,
|
62
|
+
field: field,
|
63
|
+
options: options,
|
64
|
+
component: component,
|
65
|
+
record: record }
|
66
|
+
%>
|
67
|
+
</div>
|
68
|
+
<% end %>
|
69
|
+
</div>
|
70
|
+
<% end %>
|
71
|
+
|
72
|
+
<% if %i[bottom both].include?(submit_position) %>
|
73
|
+
<div class="form-group">
|
74
|
+
<%= form.submit submit_label, class: "btn btn-#{method == :post ? 'success' : 'primary'}" %>
|
75
|
+
</div>
|
76
|
+
<% end %>
|
77
|
+
<% end %>
|
78
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<span data-field-type="secret" data-secret="<%= secret %>"></span>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<div class="d-none" id="secret-templates">
|
2
|
+
<span id="secret-show-button-template">
|
3
|
+
<a href="#"><i class="fa-solid fa-fw fa-eye"></i></a>
|
4
|
+
</span>
|
5
|
+
|
6
|
+
<span id="secret-hide-button-template">
|
7
|
+
<a href="#"><i class="fa-solid fa-fw fa-eye-slash"></i></a>
|
8
|
+
</span>
|
9
|
+
|
10
|
+
<span id="secret-content-template"></span>
|
11
|
+
</div>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<tr class="<%= (index % 2).zero? ? 'even' : 'odd' %> <%= row_class_mapper.call(item) %>">
|
2
|
+
<% fields.each do |field, class_mapper, label, value_mapper| %>
|
3
|
+
<td class="align-middle <%= class_mapper.call(item) %>">
|
4
|
+
<% if component.secret_field?(field) %>
|
5
|
+
<%= controller.helpers.render partial: 'active_element/components/secret/field',
|
6
|
+
locals: { secret: value_mapper.call(item), label: label } %>
|
7
|
+
<% else %>
|
8
|
+
<%= value_mapper.call(item) %>
|
9
|
+
<% end %>
|
10
|
+
</td>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<% if show %>
|
14
|
+
<td class="<%= "#{class_name}-show" %> action-column text-end">
|
15
|
+
<%= active_element_component.show_button(item, show, class: 'btn-sm') %>
|
16
|
+
</td>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<% if edit %>
|
20
|
+
<td class="<%= "#{class_name}-edit" %> action-column text-end">
|
21
|
+
<%= active_element_component.edit_button(item, show, class: 'btn-sm') %>
|
22
|
+
</td>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<% if destroy %>
|
26
|
+
<td class="<%= "#{class_name}-destroy" %> action-column text-end">
|
27
|
+
<%= active_element_component.destroy_button(item, destroy, class: 'btn-sm') %>
|
28
|
+
</td>
|
29
|
+
<% end %>
|
30
|
+
</tr>
|
@@ -0,0 +1,88 @@
|
|
1
|
+
<div class="container grouped-table">
|
2
|
+
<div class="row">
|
3
|
+
<div class="col-sm-2">
|
4
|
+
<% if group_title == true %>
|
5
|
+
<h4><%= i18n.label(grouping_field).pluralize %></h4>
|
6
|
+
<% elsif group_title.present? %>
|
7
|
+
<h4><%= group_title %></h4>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<ol class="list-group pt-2 <%= group_title.present? ? 'mt-3' : nil %> sticky-top">
|
11
|
+
<% grouped_collection.each do |group_identifier, group| %>
|
12
|
+
<li class="list-group-item d-flex justify-content-between align-items-start">
|
13
|
+
|
14
|
+
<div class="ms-2 me-auto pe-3">
|
15
|
+
<a style="font-size: 0.8rem;"
|
16
|
+
href="#<%= "#{class_name}-collection-group-#{group_identifier}" %>">
|
17
|
+
<%= i18n.label(group_identifier) %>
|
18
|
+
</a>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<a href="#<%= "#{class_name}-collection-group-#{group_identifier}" %>">
|
22
|
+
<span class="badge bg-primary rounded-pill">
|
23
|
+
<%= group.size %>
|
24
|
+
</span>
|
25
|
+
</a>
|
26
|
+
|
27
|
+
</li>
|
28
|
+
<% end %>
|
29
|
+
</ol>
|
30
|
+
</div>
|
31
|
+
|
32
|
+
<div class="col ms-3 ps-4 border-start">
|
33
|
+
<table class="table <%= class_name %>">
|
34
|
+
<thead class="sticky-top">
|
35
|
+
<tr>
|
36
|
+
<% fields.each do |field, _class_mapper, label, _value_mapper| %>
|
37
|
+
<th>
|
38
|
+
<%= label %>
|
39
|
+
</th>
|
40
|
+
<% end %>
|
41
|
+
|
42
|
+
<% if show %>
|
43
|
+
<th></th>
|
44
|
+
<% end %>
|
45
|
+
|
46
|
+
<% if edit %>
|
47
|
+
<th></th>
|
48
|
+
<% end %>
|
49
|
+
|
50
|
+
<% if destroy %>
|
51
|
+
<th></th>
|
52
|
+
<% end %>
|
53
|
+
</tr>
|
54
|
+
</thead>
|
55
|
+
|
56
|
+
<tbody>
|
57
|
+
<% grouped_collection.each do |group_identifier, group| %>
|
58
|
+
|
59
|
+
<tr>
|
60
|
+
<th class="collection-group-separator" colspan="<%= fields.size + (show ? 1 : 0) + (edit ? 1 : 0) + (destroy ? 1 : 0) %>">
|
61
|
+
<%= i18n.label(group_identifier) %>
|
62
|
+
<a name="<%= "#{class_name}-collection-group-#{group_identifier}" %>"></a>
|
63
|
+
</th>
|
64
|
+
<% fields.each do %>
|
65
|
+
|
66
|
+
<% end %>
|
67
|
+
</tr>
|
68
|
+
|
69
|
+
<% group.sort.each_with_index do |item, index| %>
|
70
|
+
<%= render partial: 'active_element/components/table/collection_row',
|
71
|
+
locals: {
|
72
|
+
component: component,
|
73
|
+
item: item,
|
74
|
+
fields: fields,
|
75
|
+
index: index,
|
76
|
+
class_name: class_name,
|
77
|
+
show: show,
|
78
|
+
edit: edit,
|
79
|
+
destroy: destroy,
|
80
|
+
row_class_mapper: row_class_mapper
|
81
|
+
} %>
|
82
|
+
<% end %>
|
83
|
+
<% end %>
|
84
|
+
</tbody>
|
85
|
+
</table>
|
86
|
+
</div>
|
87
|
+
</div>
|
88
|
+
</div>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<div class="row ms-3 pt-3 pb-3 row-cols-lg-auto">
|
2
|
+
<div class="col-auto">
|
3
|
+
<%= paginate collection %>
|
4
|
+
</div>
|
5
|
+
|
6
|
+
<div class="col-auto mt-2 pe-0">
|
7
|
+
Displaying
|
8
|
+
</div>
|
9
|
+
<div class="col-auto">
|
10
|
+
<%= select_tag 'collection-table-page-size-selector',
|
11
|
+
options_for_select(page_sizes, page_size),
|
12
|
+
class: 'form-select form-inline' %>
|
13
|
+
</div>
|
14
|
+
<div class="col-auto mt-2 ps-0">
|
15
|
+
of <%= number_to_human(collection.total_count) %> <%= 'record'.pluralize(collection.total_count) %>.
|
16
|
+
</div>
|
17
|
+
</div>
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<table class="<%= class_name %> table" style="<%= style %>">
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<% fields.each do |field, class_name, label, _mapper, options| %>
|
5
|
+
<th class="text-nowrap">
|
6
|
+
<%= label %>
|
7
|
+
<% if options[:description].present? %>
|
8
|
+
<button type="button"
|
9
|
+
style="background: none; border: none; outline: 0; position: absolute; margin-top: 0.3rem"
|
10
|
+
data-bs-toggle="popover"
|
11
|
+
data-bs-content="<%= options[:description] %>">
|
12
|
+
<i class="text-secondary fa-solid fa-circle-info"></i>
|
13
|
+
</button>
|
14
|
+
<% end %>
|
15
|
+
</th>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<% if show %>
|
19
|
+
<th></th>
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
<% if edit %>
|
23
|
+
<th></th>
|
24
|
+
<% end %>
|
25
|
+
|
26
|
+
<% if destroy %>
|
27
|
+
<th></th>
|
28
|
+
<% end %>
|
29
|
+
</tr>
|
30
|
+
</thead>
|
31
|
+
|
32
|
+
<tbody>
|
33
|
+
<% collection.each_with_index do |item, index| %>
|
34
|
+
<%= render partial: 'active_element/components/table/collection_row',
|
35
|
+
locals: {
|
36
|
+
component: component,
|
37
|
+
item: item,
|
38
|
+
index: index,
|
39
|
+
fields: fields,
|
40
|
+
class_name: class_name,
|
41
|
+
show: show,
|
42
|
+
edit: edit,
|
43
|
+
destroy: destroy,
|
44
|
+
row_class_mapper: row_class_mapper
|
45
|
+
} %>
|
46
|
+
<% end %>
|
47
|
+
</tbody>
|
48
|
+
</table>
|
49
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<% if new %>
|
2
|
+
<%= active_element_component.new_button(collection, float: 'end', class: 'mb-3') %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% if display_pagination %>
|
6
|
+
<%=
|
7
|
+
render partial: 'active_element/components/table/pagination',
|
8
|
+
locals: { collection: collection, params: params, page_size: page_size, page_sizes: page_sizes }
|
9
|
+
%>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<% if group %>
|
13
|
+
<%= render partial: 'active_element/components/table/grouped_collection',
|
14
|
+
locals: { component: component,
|
15
|
+
collection: collection,
|
16
|
+
fields: fields,
|
17
|
+
grouped_collection: component.grouped_collection,
|
18
|
+
grouping_field: group,
|
19
|
+
group_title: group_title,
|
20
|
+
show: show,
|
21
|
+
edit: edit,
|
22
|
+
destroy: destroy,
|
23
|
+
class_name: class_name,
|
24
|
+
style: style,
|
25
|
+
i18n: i18n,
|
26
|
+
row_class_mapper: row_class_mapper } %>
|
27
|
+
<% else %>
|
28
|
+
<%= render partial: 'active_element/components/table/ungrouped_collection',
|
29
|
+
locals: { component: component,
|
30
|
+
collection: collection,
|
31
|
+
fields: fields,
|
32
|
+
show: show,
|
33
|
+
edit: edit,
|
34
|
+
destroy: destroy,
|
35
|
+
class_name: class_name,
|
36
|
+
style: style,
|
37
|
+
i18n: i18n,
|
38
|
+
row_class_mapper: row_class_mapper } %>
|
39
|
+
<% end %>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<% if destroy && item.present? %>
|
2
|
+
<%= active_element_component.destroy_button(item, destroy, float: 'end') %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% if edit && item.present? %>
|
6
|
+
<%= active_element_component.edit_button(item, edit, float: 'end') %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% if new %>
|
10
|
+
<%= active_element_component.new_button(item, float: 'end', class: 'mb-3') %>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<table class="<%= class_name %> table" style="<%= style %>">
|
14
|
+
<tbody>
|
15
|
+
<% fields.each do |field, class_mapper, label, value_mapper, options| %>
|
16
|
+
<tr>
|
17
|
+
<th>
|
18
|
+
<%= label %>
|
19
|
+
<% if options[:description].present? %>
|
20
|
+
<button type="button"
|
21
|
+
style="background: none; border: none; outline: 0; position: absolute; margin-top: 0.3rem"
|
22
|
+
data-bs-toggle="popover"
|
23
|
+
data-bs-content="<%= options[:description] %>">
|
24
|
+
<i class="text-secondary fa-solid fa-circle-info"></i>
|
25
|
+
</button>
|
26
|
+
<% end %>
|
27
|
+
</th>
|
28
|
+
<td class="<%= class_mapper.call(item) %>">
|
29
|
+
<% if component.secret_field?(field) %>
|
30
|
+
<%= controller.helpers.render partial: 'active_element/components/secret/field',
|
31
|
+
locals: { secret: value_mapper.call(item), label: label } %>
|
32
|
+
<% else %>
|
33
|
+
<%= value_mapper.call(item) %>
|
34
|
+
<% end %>
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
<% end %>
|
38
|
+
</tbody>
|
39
|
+
</table>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<div class="p-3">
|
2
|
+
<% if tabs.size > 10 %>
|
3
|
+
<%= controller.helpers.render partial: 'active_element/components/vertical_tabs', locals: { tabs: tabs, class_name: class_name } %>
|
4
|
+
<% else %>
|
5
|
+
<%= controller.helpers.render partial: 'active_element/components/horizontal_tabs', locals: { tabs: tabs, class_name: class_name } %>
|
6
|
+
<% end %>
|
7
|
+
</div>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<h1>Forbidden</h1>
|
2
|
+
|
3
|
+
<h2>You do not have access to this page</h2>
|
4
|
+
|
5
|
+
<hr/>
|
6
|
+
|
7
|
+
<% if missing_permissions.present? %>
|
8
|
+
<p>Your user account requires the following permission(s) to view this content:</p>
|
9
|
+
|
10
|
+
<div>
|
11
|
+
<ul style="list-style-type: none;">
|
12
|
+
<% missing_permissions.each do |missing_permission| %>
|
13
|
+
<li class="font-monospace"><%= missing_permission %></li>
|
14
|
+
<% end %>
|
15
|
+
</ul>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<hr/>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<p>Please contact your administrator if you need access to this page, or <%= link_to 'go back', request.referrer %> to the previous page and try a different option.</p>
|
22
|
+
|
23
|
+
<% if alternatives.present? %>
|
24
|
+
<div class="alternative-links">
|
25
|
+
<h5>Alternatively, try one of the following suggestions:</h5>
|
26
|
+
|
27
|
+
<ul class="pt-1" style="list-style-type: none">
|
28
|
+
<% alternatives.first(5).each do |route| %>
|
29
|
+
<li class="mt-1 font-monospace"><%= link_to route.title, route.path %></li>
|
30
|
+
<% end %>
|
31
|
+
</ul>
|
32
|
+
</div>
|
33
|
+
<% end %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<div class="application-menu sticky-top navbar navbar-dark bg-dark navbar-expand-lg">
|
2
|
+
<%= render partial: 'active_element/theme/select' %>
|
3
|
+
<div class="container p-0">
|
4
|
+
<a class="navbar-brand" href="#"><%= ActiveElement.application_title %></a>
|
5
|
+
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
6
|
+
<span class="navbar-toggler-icon"></span>
|
7
|
+
</button>
|
8
|
+
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
9
|
+
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
10
|
+
<% ActiveElement.navbar_items(current_user).each do |navbar_item| %>
|
11
|
+
<li class="nav-item">
|
12
|
+
<%=
|
13
|
+
link_to navbar_item.fetch(:title) { navbar_item.fetch(:label) },
|
14
|
+
navbar_item.fetch(:path),
|
15
|
+
class: "nav-link #{
|
16
|
+
ActiveElement.active_path_class(
|
17
|
+
user: current_user,
|
18
|
+
current_navbar_item: navbar_item,
|
19
|
+
current_path: request.path,
|
20
|
+
controller_path: controller_path,
|
21
|
+
action_name: action_name)
|
22
|
+
}"
|
23
|
+
%>
|
24
|
+
</li>
|
25
|
+
<% end %>
|
26
|
+
</li>
|
27
|
+
</ul>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div id="theme-select"></div>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<div id="theme-templates" class="d-none">
|
2
|
+
<div id="theme-select-buttons">
|
3
|
+
<a id="theme-dark-button-template" href="#" class="dark-theme" data-theme-switch-to="light"><i class="fa-regular fa-fw fa-moon"></i></a>
|
4
|
+
<a id="theme-light-button-template" href="#" class="light-theme" data-theme-switch-to="dark"><i class="fa-regular fa-fw fa-sun"></i></a>
|
5
|
+
</div>
|
6
|
+
</div>
|