active_element 0.0.10 → 0.0.12
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 -2
- data/.strong_versions.yml +1 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +115 -75
- data/Makefile +10 -0
- data/active_element.gemspec +1 -1
- data/app/assets/javascripts/active_element/application.js +1 -0
- data/app/assets/javascripts/active_element/form.js +16 -32
- data/app/assets/javascripts/active_element/json_field.js +391 -135
- data/app/assets/javascripts/active_element/setup.js +13 -8
- data/app/assets/javascripts/active_element/text_search_field.js +38 -27
- data/app/assets/javascripts/active_element/theme.js +1 -1
- data/app/assets/javascripts/active_element/timezones.js +6 -0
- data/app/assets/stylesheets/active_element/_dark.scss +86 -0
- data/app/assets/stylesheets/active_element/_variables.scss +2 -1
- data/app/assets/stylesheets/active_element/application.scss +166 -33
- data/app/controllers/active_element/application_controller.rb +5 -0
- data/app/controllers/concerns/active_element/default_controller_actions.rb +38 -0
- data/app/views/active_element/_user.html.erb +20 -0
- data/app/views/active_element/components/fields/_json.html.erb +24 -0
- data/app/views/active_element/components/form/_check_box.html.erb +1 -0
- data/app/views/active_element/components/form/_check_boxes.html.erb +1 -1
- data/app/views/active_element/components/form/_datetime_range_field.html.erb +14 -0
- data/app/views/active_element/components/form/_field.html.erb +10 -7
- data/app/views/active_element/components/form/_generic_field.html.erb +1 -0
- data/app/views/active_element/components/form/_json.html.erb +10 -2
- data/app/views/active_element/components/form/_label.html.erb +12 -1
- data/app/views/active_element/components/form/_select.html.erb +4 -1
- data/app/views/active_element/components/form/_summary.html.erb +11 -1
- data/app/views/active_element/components/form/_templates.html.erb +42 -24
- data/app/views/active_element/components/form/_text_area.html.erb +2 -1
- data/app/views/active_element/components/form/_text_search.html.erb +8 -4
- data/app/views/active_element/components/form.html.erb +20 -17
- data/app/views/active_element/components/json.html.erb +1 -0
- data/app/views/active_element/components/navbar.html.erb +26 -0
- data/app/views/active_element/components/table/_collection_row.html.erb +2 -1
- data/app/views/active_element/components/table/_field.html.erb +8 -0
- data/app/views/active_element/components/table/_ungrouped_collection.html.erb +1 -0
- data/app/views/active_element/components/table/collection.html.erb +1 -1
- data/app/views/active_element/components/table/item.html.erb +6 -4
- data/app/views/active_element/default_views/edit.html.erb +5 -0
- data/app/views/active_element/default_views/forbidden.html.erb +7 -0
- data/app/views/active_element/default_views/index.html.erb +15 -0
- data/app/views/active_element/default_views/new.html.erb +4 -0
- data/app/views/active_element/default_views/show.html.erb +7 -0
- data/app/views/active_element/navbar/_menu.html.erb +1 -30
- data/app/views/active_element/theme/_select.html.erb +1 -1
- data/app/views/layouts/active_element.html.erb +16 -1
- data/config/brakeman.ignore +48 -0
- data/config/locales/en.yml +3 -0
- data/example_app/.gitattributes +7 -0
- data/example_app/.gitignore +35 -0
- data/example_app/.ruby-version +1 -0
- data/example_app/Gemfile +34 -0
- data/example_app/Gemfile.lock +296 -0
- data/example_app/README.md +24 -0
- data/example_app/Rakefile +6 -0
- data/example_app/app/assets/config/manifest.js +4 -0
- data/example_app/app/assets/images/.keep +0 -0
- data/example_app/app/assets/stylesheets/application.css +15 -0
- data/example_app/app/channels/application_cable/channel.rb +4 -0
- data/example_app/app/channels/application_cable/connection.rb +4 -0
- data/example_app/app/controllers/application_controller.rb +12 -0
- data/example_app/app/controllers/concerns/.keep +0 -0
- data/example_app/app/controllers/pets_controller.rb +7 -0
- data/example_app/app/controllers/users_controller.rb +7 -0
- data/example_app/app/helpers/application_helper.rb +2 -0
- data/example_app/app/javascript/application.js +3 -0
- data/example_app/app/javascript/controllers/application.js +9 -0
- data/example_app/app/javascript/controllers/hello_controller.js +7 -0
- data/example_app/app/javascript/controllers/index.js +11 -0
- data/example_app/app/jobs/application_job.rb +7 -0
- data/example_app/app/mailers/application_mailer.rb +4 -0
- data/example_app/app/models/application_record.rb +3 -0
- data/example_app/app/models/concerns/.keep +0 -0
- data/example_app/app/models/pet.rb +3 -0
- data/example_app/app/models/user.rb +8 -0
- data/example_app/app/views/layouts/application.html.erb +16 -0
- data/example_app/app/views/layouts/mailer.html.erb +13 -0
- data/example_app/app/views/layouts/mailer.text.erb +1 -0
- data/example_app/app/views/pets/index.html.erb +3 -0
- data/example_app/app/views/users/show.html.erb +3 -0
- data/example_app/bin/bundle +109 -0
- data/example_app/bin/importmap +4 -0
- data/example_app/bin/rails +4 -0
- data/example_app/bin/rake +4 -0
- data/example_app/bin/setup +33 -0
- data/example_app/config/application.rb +22 -0
- data/example_app/config/boot.rb +4 -0
- data/example_app/config/cable.yml +10 -0
- data/example_app/config/credentials.yml.enc +1 -0
- data/example_app/config/database.yml +25 -0
- data/example_app/config/environment.rb +5 -0
- data/example_app/config/environments/development.rb +70 -0
- data/example_app/config/environments/production.rb +93 -0
- data/example_app/config/environments/test.rb +60 -0
- data/example_app/config/importmap.rb +7 -0
- data/example_app/config/initializers/assets.rb +12 -0
- data/example_app/config/initializers/content_security_policy.rb +25 -0
- data/example_app/config/initializers/devise.rb +16 -0
- data/example_app/config/initializers/filter_parameter_logging.rb +8 -0
- data/example_app/config/initializers/inflections.rb +16 -0
- data/example_app/config/initializers/permissions_policy.rb +11 -0
- data/example_app/config/locales/devise.en.yml +65 -0
- data/example_app/config/locales/en.yml +33 -0
- data/example_app/config/puma.rb +43 -0
- data/example_app/config/routes.rb +8 -0
- data/example_app/config/storage.yml +34 -0
- data/example_app/config.ru +6 -0
- data/example_app/db/migrate/20230616210539_create_pet.rb +12 -0
- data/example_app/db/migrate/20230616211328_devise_create_users.rb +46 -0
- data/example_app/db/schema.rb +37 -0
- data/example_app/db/seeds.rb +33 -0
- data/example_app/lib/assets/.keep +0 -0
- data/example_app/lib/tasks/.keep +0 -0
- data/example_app/log/.keep +0 -0
- data/example_app/public/404.html +67 -0
- data/example_app/public/422.html +67 -0
- data/example_app/public/500.html +66 -0
- data/example_app/public/apple-touch-icon-precomposed.png +0 -0
- data/example_app/public/apple-touch-icon.png +0 -0
- data/example_app/public/favicon.ico +0 -0
- data/example_app/public/robots.txt +1 -0
- data/example_app/storage/.keep +0 -0
- data/example_app/test/application_system_test_case.rb +5 -0
- data/example_app/test/channels/application_cable/connection_test.rb +11 -0
- data/example_app/test/controllers/.keep +0 -0
- data/example_app/test/fixtures/files/.keep +0 -0
- data/example_app/test/fixtures/users.yml +11 -0
- data/example_app/test/helpers/.keep +0 -0
- data/example_app/test/integration/.keep +0 -0
- data/example_app/test/mailers/.keep +0 -0
- data/example_app/test/models/.keep +0 -0
- data/example_app/test/models/user_test.rb +7 -0
- data/example_app/test/system/.keep +0 -0
- data/example_app/test/test_helper.rb +13 -0
- data/example_app/tmp/.keep +0 -0
- data/example_app/tmp/pids/.keep +0 -0
- data/example_app/tmp/storage/.keep +0 -0
- data/example_app/vendor/.keep +0 -0
- data/example_app/vendor/javascript/.keep +0 -0
- data/lib/active_element/component.rb +9 -2
- data/lib/active_element/components/collection_table.rb +9 -2
- data/lib/active_element/components/email_fields.rb +14 -0
- data/lib/active_element/components/form.rb +48 -17
- data/lib/active_element/components/navbar.rb +64 -0
- data/lib/active_element/components/phone_fields.rb +14 -0
- data/lib/active_element/components/text_search/authorization.rb +9 -6
- data/lib/active_element/components/text_search/component.rb +4 -2
- data/lib/active_element/components/text_search.rb +13 -0
- data/lib/active_element/components/util/association_mapping.rb +74 -19
- data/lib/active_element/components/util/display_value_mapping.rb +13 -4
- data/lib/active_element/components/util/form_field_mapping.rb +139 -10
- data/lib/active_element/components/util/form_value_mapping.rb +3 -3
- data/lib/active_element/components/util/i18n.rb +1 -1
- data/lib/active_element/components/util/numeric_field.rb +73 -0
- data/lib/active_element/components/util/record_mapping.rb +43 -11
- data/lib/active_element/components/util/record_path.rb +21 -4
- data/lib/active_element/components/util.rb +13 -5
- data/lib/active_element/components.rb +3 -0
- data/lib/active_element/controller_action.rb +8 -2
- data/lib/active_element/controller_interface.rb +56 -18
- data/lib/active_element/controller_state.rb +44 -0
- data/lib/active_element/default_controller.rb +137 -0
- data/lib/active_element/default_record_params.rb +62 -0
- data/lib/active_element/default_search.rb +110 -0
- data/lib/active_element/json_field_schema.rb +59 -0
- data/lib/active_element/pre_render_processors/json.rb +98 -0
- data/lib/active_element/pre_render_processors.rb +11 -0
- data/lib/active_element/route.rb +12 -0
- data/lib/active_element/routes.rb +2 -1
- data/lib/active_element/version.rb +1 -1
- data/lib/active_element.rb +15 -32
- data/lib/tasks/active_element.rake +12 -1
- data/rspec-documentation/_head.html.erb +34 -0
- data/rspec-documentation/pages/000-Introduction.md +18 -0
- data/rspec-documentation/pages/005-Setup.md +75 -0
- data/rspec-documentation/pages/010-Components/Form Fields/Check Boxes.md +1 -0
- data/rspec-documentation/pages/010-Components/Form Fields/JSON/Controller Params.md +97 -0
- data/rspec-documentation/pages/010-Components/Form Fields/JSON/Schema.md +283 -0
- data/rspec-documentation/pages/010-Components/Form Fields/JSON/Types.md +36 -0
- data/rspec-documentation/pages/010-Components/Form Fields/JSON.md +70 -0
- data/rspec-documentation/pages/010-Components/Form Fields/Text Search.md +133 -0
- data/rspec-documentation/pages/010-Components/Form Fields.md +46 -0
- data/rspec-documentation/pages/010-Components/Forms.md +44 -0
- data/rspec-documentation/pages/010-Components/JSON Data.md +23 -0
- data/rspec-documentation/pages/010-Components/Navbar.md +56 -0
- data/rspec-documentation/pages/010-Components/Page Section Title.md +13 -0
- data/rspec-documentation/pages/010-Components/Page Subtitle.md +11 -0
- data/rspec-documentation/pages/010-Components/Page Title.md +11 -0
- data/rspec-documentation/pages/010-Components/Tables/Collection Table.md +29 -0
- data/rspec-documentation/pages/010-Components/Tables/Item Table.md +18 -0
- data/rspec-documentation/pages/010-Components/Tables/Options.md +19 -0
- data/rspec-documentation/pages/010-Components/Tables.md +29 -0
- data/rspec-documentation/pages/010-Components.md +15 -0
- data/rspec-documentation/pages/020-Access Control/010-Authentication.md +20 -0
- data/rspec-documentation/pages/020-Access Control/020-Authorization/Environments.md +9 -0
- data/rspec-documentation/pages/020-Access Control/020-Authorization/Permissions/Custom Routes.md +41 -0
- data/rspec-documentation/pages/020-Access Control/020-Authorization/Permissions.md +58 -0
- data/rspec-documentation/pages/020-Access Control/020-Authorization/Setup.md +27 -0
- data/rspec-documentation/pages/020-Access Control/020-Authorization.md +11 -0
- data/rspec-documentation/pages/020-Access Control.md +31 -0
- data/rspec-documentation/pages/040-Decorators/Inline Decorators.md +24 -0
- data/rspec-documentation/pages/040-Decorators/View Decorators.md +55 -0
- data/rspec-documentation/pages/040-Decorators.md +12 -0
- data/rspec-documentation/pages/300-Alternatives.md +21 -0
- data/rspec-documentation/pages/900-License.md +11 -0
- data/rspec-documentation/spec_helper.rb +53 -16
- data/rspec-documentation/support.rb +84 -0
- metadata +159 -14
- data/rspec-documentation/pages/Components/Forms.md +0 -1
- data/rspec-documentation/pages/Components/Tables.md +0 -47
- data/rspec-documentation/pages/Components.md +0 -1
- data/rspec-documentation/pages/Decorators/Inline Decorators.md +0 -1
- data/rspec-documentation/pages/Decorators/View Decorators.md +0 -1
- data/rspec-documentation/pages/Index.md +0 -3
- data/rspec-documentation/pages/Util/I18n.md +0 -1
- /data/rspec-documentation/pages/{Components → 010-Components}/Tabs.md +0 -0
@@ -1,13 +1,11 @@
|
|
1
1
|
(() => {
|
2
2
|
const generateId = () => {
|
3
|
-
|
4
|
-
|
5
|
-
return `active-element-element-${ActiveElement._id}`;
|
3
|
+
return `ae-${crypto.randomUUID()}`;
|
6
4
|
};
|
7
5
|
|
8
6
|
const getAntiCsrfToken = () => {
|
9
|
-
const param = document.querySelector('meta[name="csrf-param"]')
|
10
|
-
const value = document.querySelector('meta[name="csrf-token"]')
|
7
|
+
const param = document.querySelector('meta[name="csrf-param"]')?.content;
|
8
|
+
const value = document.querySelector('meta[name="csrf-token"]')?.content;
|
11
9
|
|
12
10
|
return { param, value };
|
13
11
|
};
|
@@ -23,6 +21,8 @@
|
|
23
21
|
const navbar = document.querySelector('.navbar.application-menu');
|
24
22
|
|
25
23
|
window.addEventListener('scroll', () => {
|
24
|
+
if (!navbar) return;
|
25
|
+
|
26
26
|
if (window.scrollY > 50) {
|
27
27
|
navbar.classList.add('shrink');
|
28
28
|
} else {
|
@@ -32,12 +32,17 @@
|
|
32
32
|
|
33
33
|
|
34
34
|
const ActiveElement = {
|
35
|
-
|
36
|
-
|
35
|
+
debug: false,
|
36
|
+
log: {
|
37
|
+
debug: (message) => { ActiveElement.debug && console.log(`[ActiveElement:debug]`, message); },
|
38
|
+
info: (message) => { console.log(`[ActiveElement:info] ${message}`); },
|
39
|
+
error: (message) => { console.log(`[ActiveElement:error] ${message}`); },
|
40
|
+
},
|
37
41
|
generateId,
|
38
42
|
getAntiCsrfToken,
|
39
43
|
cloneElement,
|
40
44
|
components: {},
|
45
|
+
getRequestId: () => ActiveElement.generateId(),
|
41
46
|
jsonData: window.ActiveElement?.jsonData || {},
|
42
47
|
controller_path: document.querySelector('meta[name="active_element_controller_path"]').content
|
43
48
|
};
|
@@ -45,4 +50,4 @@
|
|
45
50
|
window.ActiveElement = ActiveElement;
|
46
51
|
})();
|
47
52
|
|
48
|
-
ActiveElement.log('Initialized');
|
53
|
+
ActiveElement.log.info('Initialized');
|
@@ -7,17 +7,23 @@
|
|
7
7
|
try {
|
8
8
|
return JSON.parse(json);
|
9
9
|
} catch (error) {
|
10
|
-
ActiveElement.log(error);
|
10
|
+
ActiveElement.log.error(error);
|
11
11
|
return defaultValue;
|
12
12
|
}
|
13
13
|
};
|
14
14
|
|
15
|
+
const getDisplayValue = ({ value, attributes, simplify = false }) => {
|
16
|
+
if (attributes.length === 0) return value;
|
17
|
+
if (attributes.length === 1 && attributes[0] === value) return value;
|
18
|
+
if (simplify) return attributes[0];
|
19
|
+
|
20
|
+
return attributes.join(', ');
|
21
|
+
};
|
22
|
+
|
15
23
|
const processResponse = ({
|
16
|
-
element, response, hiddenInput, spinner,
|
24
|
+
element, response, hiddenInput, spinner, searchResultsContainer, responseErrorContainer
|
17
25
|
}) => {
|
18
26
|
spinner.classList.add('invisible');
|
19
|
-
clearButton.classList.remove('invisible');
|
20
|
-
|
21
27
|
if (response.ok) {
|
22
28
|
response.json().then((json) => {
|
23
29
|
if (json.request_id !== lastRequestId) {
|
@@ -34,10 +40,10 @@
|
|
34
40
|
json.results.forEach(({ value, attributes }) => {
|
35
41
|
const resultsItem = cloneElement('results-item');
|
36
42
|
|
37
|
-
resultsItem.innerText =
|
43
|
+
resultsItem.innerText = getDisplayValue({ value, attributes });
|
38
44
|
resultsItem.addEventListener('click', () => {
|
39
45
|
hiddenInput.value = value;
|
40
|
-
element.value = value;
|
46
|
+
element.value = getDisplayValue({ value, attributes, simplify: true });
|
41
47
|
searchResultsContainer.replaceChildren();
|
42
48
|
searchResultsContainer.classList.add('d-none');
|
43
49
|
});
|
@@ -48,7 +54,7 @@
|
|
48
54
|
});
|
49
55
|
} else {
|
50
56
|
response.json().then((json) => responseErrorContainer.innerText = json.message)
|
51
|
-
.catch(() => responseErrorContainer.innerText = 'An
|
57
|
+
.catch(() => responseErrorContainer.innerText = 'An unexpected error occurred');
|
52
58
|
}
|
53
59
|
};
|
54
60
|
|
@@ -58,35 +64,40 @@
|
|
58
64
|
const hiddenId = `${id}-hidden-value`;
|
59
65
|
const formId = element.dataset.formId;
|
60
66
|
const form = document.querySelector(`#${formId}`);
|
67
|
+
const hiddenInput = document.querySelector(`#${hiddenId}`);
|
61
68
|
const model = element.dataset.searchModel;
|
62
69
|
const attributes = tryParseJSON(element.dataset.searchAttributes, []);
|
63
70
|
const value = element.dataset.searchValue;
|
64
71
|
const token = ActiveElement.getAntiCsrfToken();
|
65
|
-
const hiddenInput = cloneElement('hidden-input');
|
66
72
|
const responseErrorContainer = cloneElement('response-error');
|
67
73
|
const searchResultsContainer = cloneElement('results');
|
68
|
-
const
|
69
|
-
const
|
70
|
-
|
71
|
-
searchResultsContainer.classList.add('d-none');
|
72
|
-
});
|
74
|
+
const icons = cloneElement('icons');
|
75
|
+
const spinner = icons.querySelector('[data-item-class="spinner"]');
|
76
|
+
const clearButton = icons.querySelector('[data-item-class="clear"]');
|
73
77
|
|
78
|
+
if (element.value) clearButton.classList.remove('invisible');
|
74
79
|
clearButton.addEventListener('click', () => {
|
75
80
|
element.value = '';
|
76
81
|
hiddenInput.value = '';
|
77
|
-
responseErrorContainer.innerText = '';
|
78
|
-
spinner.classList.add('invisible');
|
79
82
|
clearButton.classList.add('invisible');
|
80
83
|
});
|
81
84
|
|
85
|
+
document.addEventListener('click', () => {
|
86
|
+
searchResultsContainer.classList.add('d-none');
|
87
|
+
});
|
88
|
+
|
89
|
+
element.addEventListener('change', () => {
|
90
|
+
hiddenInput.value = element.value;
|
91
|
+
if (element.value) clearButton.classList.remove('invisible');
|
92
|
+
});
|
93
|
+
|
82
94
|
element.addEventListener('keyup', () => {
|
83
95
|
const query = element.value;
|
84
|
-
const requestId =
|
96
|
+
const requestId = ActiveElement.getRequestId();
|
85
97
|
lastRequestId = requestId;
|
86
98
|
|
87
|
-
clearButton.classList.add('invisible');
|
88
99
|
spinner.classList.remove('invisible');
|
89
|
-
|
100
|
+
if (element.value) clearButton.classList.remove('invisible');
|
90
101
|
searchResultsContainer.classList.add('d-none');
|
91
102
|
|
92
103
|
if (!query || query.length < 3) {
|
@@ -102,21 +113,21 @@
|
|
102
113
|
method: 'POST',
|
103
114
|
headers: { 'Content-Type': 'application/json' },
|
104
115
|
body: JSON.stringify({
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
116
|
+
...{
|
117
|
+
request_id: requestId,
|
118
|
+
model,
|
119
|
+
value,
|
120
|
+
attributes,
|
121
|
+
query,
|
122
|
+
},
|
123
|
+
...(token.param && token.value ? { [token.param]: token.value } : {})
|
111
124
|
}),
|
112
125
|
}
|
113
126
|
).then((response) => processResponse(
|
114
|
-
{ element, response, spinner,
|
127
|
+
{ element, response, spinner, hiddenInput, searchResultsContainer, responseErrorContainer }
|
115
128
|
));
|
116
129
|
});
|
117
130
|
|
118
|
-
hiddenInput.name = element.name;
|
119
|
-
if (element.value) hiddenInput.value = element.value;
|
120
131
|
form.append(hiddenInput);
|
121
132
|
element.parentElement.append(searchResultsContainer);
|
122
133
|
element.parentElement.append(clearButton);
|
@@ -0,0 +1,86 @@
|
|
1
|
+
[data-bs-theme="dark"] {
|
2
|
+
.navbar.application-menu {
|
3
|
+
background-color: #15303a !important;
|
4
|
+
}
|
5
|
+
|
6
|
+
.dropdown-item:hover {
|
7
|
+
--bs-dropdown-link-hover-bg: #{$blue-700};
|
8
|
+
}
|
9
|
+
|
10
|
+
.flash.toast {
|
11
|
+
&.notice {
|
12
|
+
.toast-body {
|
13
|
+
color: #{$white};
|
14
|
+
background: #{$blue-700};
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
&.alert {
|
19
|
+
.toast-body {
|
20
|
+
color: #{$white};
|
21
|
+
background: #{$red-700};
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
.json-field {
|
27
|
+
.form-group {
|
28
|
+
background-color: #58575755;
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
.popover {
|
33
|
+
.popover-header {
|
34
|
+
background-color: #{$dark};
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
.search-field-results {
|
39
|
+
background-color: $dark;
|
40
|
+
.search-field-result {
|
41
|
+
color: #{$light};
|
42
|
+
}
|
43
|
+
.search-field-result {
|
44
|
+
cursor: pointer;
|
45
|
+
&:hover {
|
46
|
+
background-color: #{darken($blue, 8%)};
|
47
|
+
color: #{$light};
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
table {
|
53
|
+
tbody {
|
54
|
+
tr {
|
55
|
+
&.odd {
|
56
|
+
td, th { background-color: #{rgba($dark, 0.3)}; }
|
57
|
+
}
|
58
|
+
|
59
|
+
&.even {
|
60
|
+
td, th { background-color: #{lighten(rgba($dark, 0.3), 8%)}; }
|
61
|
+
}
|
62
|
+
|
63
|
+
&:hover {
|
64
|
+
td, th { background-color: #{rgba($primary, 0.2)}; }
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
.pagination {
|
71
|
+
.page-link {
|
72
|
+
--bs-pagination-active-bg: #505050;
|
73
|
+
--bs-pagination-active-color: #{darken($light, 10%)};
|
74
|
+
}
|
75
|
+
--bs-pagination-hover-color: #8e8c84;
|
76
|
+
--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(50, 93, 136, 0.25);
|
77
|
+
--bs-pagination-active-color: #333433;
|
78
|
+
--bs-pagination-active-bg: #626262;
|
79
|
+
--bs-pagination-bg: #{$dark};
|
80
|
+
--bs-pagination-disabled-bg: #464646;
|
81
|
+
--bs-pagination-border-color: #{$dark};
|
82
|
+
--bs-pagination-active-border-color: #{$dark};
|
83
|
+
--bs-pagination-disabled-color: #dfd7ca;
|
84
|
+
--bs-pagination-disabled-border-color: #000;
|
85
|
+
}
|
86
|
+
}
|
@@ -79,6 +79,7 @@ $nav-pills-link-active-bg: $gray-200 !default;
|
|
79
79
|
// Navbar
|
80
80
|
|
81
81
|
$navbar-dark-hover-color: $white !default;
|
82
|
+
$navbar-light-hover-color: $green !default;
|
82
83
|
$navbar-light-hover-color: $black !default;
|
83
84
|
$navbar-light-active-color: $black !default;
|
84
85
|
|
@@ -137,6 +138,6 @@ $breadcrumb-border-radius: .25rem !default;
|
|
137
138
|
|
138
139
|
// Close
|
139
140
|
|
140
|
-
$btn-close-color: $
|
141
|
+
$btn-close-color: $dark !default;
|
141
142
|
$btn-close-opacity: .8 !default;
|
142
143
|
$btn-close-hover-opacity: 1 !default;
|
@@ -1,28 +1,27 @@
|
|
1
1
|
@import "variables";
|
2
2
|
@import "bootstrap";
|
3
|
+
@import "dark";
|
3
4
|
|
4
|
-
.
|
5
|
+
.application-menu {
|
5
6
|
height: 5rem;
|
7
|
+
padding-left: 2rem;
|
8
|
+
top: 0;
|
6
9
|
transition: height 0.5s ease-in-out, background-position 0.8s ease-in-out;
|
7
|
-
background-
|
8
|
-
background-repeat: no-repeat;
|
10
|
+
background-color: #456060 !important;
|
9
11
|
z-index: 2000;
|
10
|
-
|
11
|
-
|
12
|
-
height: 3rem;
|
13
|
-
background-position: right -50rem center;
|
12
|
+
.dropdown-toggle::after {
|
13
|
+
color: #{$blue};
|
14
14
|
}
|
15
15
|
|
16
|
-
|
17
|
-
height: 5rem;
|
18
|
-
background-position: right 1.2rem center;
|
19
|
-
background-repeat: no-repeat;
|
16
|
+
&.shrink {
|
17
|
+
height: 2.5rem;
|
20
18
|
}
|
21
19
|
}
|
22
20
|
|
23
21
|
.main.content {
|
24
|
-
top:
|
22
|
+
top: 7rem;
|
25
23
|
position: relative;
|
24
|
+
padding-bottom: 3rem;
|
26
25
|
}
|
27
26
|
|
28
27
|
td.action-column {
|
@@ -48,6 +47,22 @@ table {
|
|
48
47
|
display: none;
|
49
48
|
}
|
50
49
|
}
|
50
|
+
|
51
|
+
tbody {
|
52
|
+
tr {
|
53
|
+
&.odd {
|
54
|
+
td, th { background-color: #{rgba($light, 0.3)}; }
|
55
|
+
}
|
56
|
+
|
57
|
+
&.even {
|
58
|
+
td, th { background-color: #{darken(rgba($light, 0.3), 10%)}; }
|
59
|
+
}
|
60
|
+
|
61
|
+
&:hover {
|
62
|
+
td, th { background-color: #{rgba($primary, 0.2)}; }
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
51
66
|
}
|
52
67
|
|
53
68
|
form {
|
@@ -56,10 +71,137 @@ form {
|
|
56
71
|
}
|
57
72
|
}
|
58
73
|
|
74
|
+
.modal-dialog.modal-dialog-scrollable.json-field-modal .modal-content {
|
75
|
+
max-height: 80%;
|
76
|
+
min-height: 80%;
|
77
|
+
margin-top: 5rem;
|
78
|
+
}
|
79
|
+
|
59
80
|
.json-field {
|
81
|
+
ol.json-array-field {
|
82
|
+
margin-top: 1rem;
|
83
|
+
}
|
84
|
+
|
85
|
+
ol {
|
86
|
+
line-height: 2rem;
|
87
|
+
|
88
|
+
&.array-of-objects {
|
89
|
+
margin-top: 2.8rem;
|
90
|
+
}
|
91
|
+
|
92
|
+
ol {
|
93
|
+
margin-top: 1rem;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
ol.focus {
|
98
|
+
margin-top: 0;
|
99
|
+
}
|
100
|
+
|
101
|
+
li {
|
102
|
+
scroll-margin-top: 6rem;
|
103
|
+
}
|
104
|
+
|
105
|
+
.form-group {
|
106
|
+
padding: 1rem;
|
107
|
+
background-color: #58575755;
|
108
|
+
}
|
109
|
+
|
110
|
+
.form-check {
|
111
|
+
display: flex;
|
112
|
+
align-items: center;
|
113
|
+
margin-left: 1.25rem !important;
|
114
|
+
|
115
|
+
.form-check-input {
|
116
|
+
margin-top: 0;
|
117
|
+
}
|
118
|
+
|
119
|
+
.form-check-label {
|
120
|
+
margin-left: 0.4rem;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
.json-delete-object-button {
|
124
|
+
// margin-top: 1rem;
|
125
|
+
// margin-right: 1.8rem;
|
126
|
+
// margin-bottom: 1rem;
|
127
|
+
}
|
128
|
+
|
129
|
+
.form-floating {
|
130
|
+
.json-date-field-label, .json-time-field-label, .json-datetime-local-field-label, .json-datetime-field-label {
|
131
|
+
position: relative;
|
132
|
+
display: inline;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
&.modal-body {
|
137
|
+
ol {
|
138
|
+
margin-top: 0;
|
139
|
+
}
|
140
|
+
|
141
|
+
.json-delete-object-button {
|
142
|
+
margin-top: 0;
|
143
|
+
margin-right: 0;
|
144
|
+
}
|
145
|
+
|
146
|
+
.form-group {
|
147
|
+
padding: 1rem;
|
148
|
+
margin-top: 0.8rem;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
.focus {
|
153
|
+
.focus-field-name {
|
154
|
+
}
|
155
|
+
|
156
|
+
.focus-field-syntax {
|
157
|
+
}
|
158
|
+
|
159
|
+
.focus-field-value {
|
160
|
+
text-decoration: none;
|
161
|
+
font-weight: bold;
|
162
|
+
|
163
|
+
&:hover {
|
164
|
+
text-decoration: underline;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
.expand-button {
|
169
|
+
margin-right: 0.4rem;
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
|
174
|
+
.delete-object-button-wrapper {
|
175
|
+
padding-bottom: 2rem;
|
176
|
+
}
|
177
|
+
|
178
|
+
|
179
|
+
.json-array-field {
|
180
|
+
li .json-text-field,
|
181
|
+
li .json-select-field,
|
182
|
+
li .json-integer-field,
|
183
|
+
li .json-float-field,
|
184
|
+
li .json-decimal-field,
|
185
|
+
li .json-date-field,
|
186
|
+
li .json-time-field,
|
187
|
+
li .json-datetime-field {
|
188
|
+
&.deletable {
|
189
|
+
width: calc(100% - 3.2rem);
|
190
|
+
}
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
60
194
|
.form-control, .form-select {
|
61
|
-
width: calc(100% - 2.5rem);
|
62
195
|
display: inline;
|
196
|
+
.append-button {
|
197
|
+
display: inline;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
.form-group {
|
202
|
+
border-radius: 10px;
|
203
|
+
background-color: #dddada55;
|
204
|
+
border-radius: 10px;
|
63
205
|
}
|
64
206
|
|
65
207
|
.action-button {
|
@@ -73,8 +215,15 @@ form {
|
|
73
215
|
}
|
74
216
|
|
75
217
|
.search-field-results {
|
76
|
-
min-width:
|
218
|
+
min-width: 25rem;
|
219
|
+
background-color: $white;
|
220
|
+
max-height: 15rem;
|
221
|
+
z-index: 3000;
|
77
222
|
position: absolute;
|
223
|
+
overflow-y: auto;
|
224
|
+
.search-field-result {
|
225
|
+
color: #{$dark};
|
226
|
+
}
|
78
227
|
.search-field-result {
|
79
228
|
cursor: pointer;
|
80
229
|
&:hover {
|
@@ -89,6 +238,7 @@ form {
|
|
89
238
|
margin-top: 2rem;
|
90
239
|
margin-right: 1rem;
|
91
240
|
padding: 0;
|
241
|
+
z-index: 3000;
|
92
242
|
|
93
243
|
&.notice {
|
94
244
|
.toast-body {
|
@@ -103,29 +253,12 @@ form {
|
|
103
253
|
}
|
104
254
|
}
|
105
255
|
|
106
|
-
|
107
|
-
.
|
108
|
-
&.notice {
|
109
|
-
.toast-body {
|
110
|
-
color: #{$white};
|
111
|
-
background: #{$blue-700};
|
112
|
-
}
|
113
|
-
}
|
114
|
-
|
115
|
-
&.alert {
|
116
|
-
.toast-body {
|
117
|
-
color: #{$white};
|
118
|
-
background: #{$red-700};
|
119
|
-
}
|
120
|
-
}
|
121
|
-
}
|
256
|
+
.user-menu-icon {
|
257
|
+
font-size: 1.5rem;
|
122
258
|
}
|
123
259
|
|
124
260
|
#theme-select {
|
125
261
|
font-size: 1.5rem;
|
126
|
-
padding: 0.2rem 0.8rem;
|
127
|
-
position: absolute;
|
128
|
-
right: 0;
|
129
262
|
|
130
263
|
a {
|
131
264
|
&.dark-theme {
|
@@ -5,6 +5,7 @@ module ActiveElement
|
|
5
5
|
# authentication as Superuser, and standardised HTML widgets.
|
6
6
|
class ApplicationController < ActionController::Base
|
7
7
|
include ActionView::Helpers::TagHelper
|
8
|
+
include ActiveElement::DefaultControllerActions
|
8
9
|
|
9
10
|
layout 'active_element'
|
10
11
|
|
@@ -12,6 +13,10 @@ module ActiveElement
|
|
12
13
|
@active_element ||= ActiveElement::ControllerInterface.new(self)
|
13
14
|
end
|
14
15
|
|
16
|
+
def self.active_element_editable_fields(*args)
|
17
|
+
@active_element_assigned_editable_fields = args
|
18
|
+
end
|
19
|
+
|
15
20
|
def active_element
|
16
21
|
@active_element ||= ActiveElement::ControllerInterface.new(self.class, self)
|
17
22
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveElement
|
4
|
+
# Default Rails actions to be performed if not defined by a controller, allows developers to
|
5
|
+
# define a controller and have basic boilerplate for typical functionality which can be
|
6
|
+
# overridden and customized as needed.
|
7
|
+
module DefaultControllerActions
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
def index
|
11
|
+
ActiveElement::DefaultController.new(controller: self).index
|
12
|
+
end
|
13
|
+
|
14
|
+
def show
|
15
|
+
ActiveElement::DefaultController.new(controller: self).show
|
16
|
+
end
|
17
|
+
|
18
|
+
def new
|
19
|
+
ActiveElement::DefaultController.new(controller: self).new
|
20
|
+
end
|
21
|
+
|
22
|
+
def create
|
23
|
+
ActiveElement::DefaultController.new(controller: self).create
|
24
|
+
end
|
25
|
+
|
26
|
+
def edit
|
27
|
+
ActiveElement::DefaultController.new(controller: self).edit
|
28
|
+
end
|
29
|
+
|
30
|
+
def update
|
31
|
+
ActiveElement::DefaultController.new(controller: self).update
|
32
|
+
end
|
33
|
+
|
34
|
+
def destroy
|
35
|
+
ActiveElement::DefaultController.new(controller: self).destroy
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<li class="nav-item dropdown" style="list-style: none">
|
2
|
+
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
3
|
+
<i class="fa-solid fa-user text-primary user-menu-icon"></i>
|
4
|
+
</a>
|
5
|
+
<ul class="dropdown-menu dropdown-menu-end">
|
6
|
+
<% if active_element.current_user.present? %>
|
7
|
+
<li class="dropdown-header">Signed in as <span class="text-primary"><%= active_element.current_user.email %></span></li>
|
8
|
+
<li><hr class="dropdown-divider"/></li>
|
9
|
+
<% if active_element.sign_in_path.present? %>
|
10
|
+
<li><%= link_to 'Sign Out', active_element.sign_out_path,
|
11
|
+
method: active_element.sign_out_method,
|
12
|
+
class: 'dropdown-item' %></li>
|
13
|
+
<% end %>
|
14
|
+
<% elsif active_element.sign_out_path.present? %>
|
15
|
+
<li><%= link_to 'Sign In', active_element.sign_in_path,
|
16
|
+
method: active_element.sign_in_method,
|
17
|
+
class: 'dropdown-item' %></li>
|
18
|
+
<% end %>
|
19
|
+
</ul>
|
20
|
+
</li>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<a data-modal-id="<%= "#json-modal-#{field_id}" %>"
|
2
|
+
data-json-modal-link="true"
|
3
|
+
data-bs-toggle="modal"
|
4
|
+
data-bs-target="#json-modal-<%= field_id %>"
|
5
|
+
class="text-decoration-none"
|
6
|
+
href="#">Inspect JSON <i class="fa-solid fa-magnifying-glass"></i></a>
|
7
|
+
<div id="json-modal-<%= field_id %>" class="modal fade"
|
8
|
+
tabindex="-1"
|
9
|
+
aria-hidden="true">
|
10
|
+
<div class="modal-dialog modal-dialog-centered modal-xl modal-dialog-scrollable">
|
11
|
+
<div class="modal-content">
|
12
|
+
<div class="modal-header">
|
13
|
+
<h5 class="modal-title" data-field-type="modal-title">JSON Inspector</h5>
|
14
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
15
|
+
<i class="fa-solid fa-xmark"></i>
|
16
|
+
</button>
|
17
|
+
</div>
|
18
|
+
<div class="modal-body p-3" data-field-type="modal-body">
|
19
|
+
<%= ActiveElement.json_pretty_print(value) %>
|
20
|
+
</div>
|
21
|
+
<div class="modal-footer" data-field-type="modal-footer"></div>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
@@ -21,7 +21,7 @@
|
|
21
21
|
<div class="row w-100">
|
22
22
|
<% slice.each do |label, name, checked| %>
|
23
23
|
<div class="col">
|
24
|
-
<%= subform.check_box(name, checked: checked, class: 'me-2') %>
|
24
|
+
<%= subform.check_box(name, checked: checked, class: 'me-2', tabindex: component.tabindex) %>
|
25
25
|
<%= subform.label name, label %>
|
26
26
|
</div>
|
27
27
|
<br/>
|