super_settings 1.0.2 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/README.md +128 -26
  4. data/VERSION +1 -1
  5. data/app/helpers/super_settings/settings_helper.rb +13 -3
  6. data/app/views/layouts/super_settings/settings.html.erb +1 -1
  7. data/config/routes.rb +1 -1
  8. data/db/migrate/20210414004553_create_super_settings.rb +1 -7
  9. data/lib/super_settings/application/api.js +4 -1
  10. data/lib/super_settings/application/helper.rb +56 -17
  11. data/lib/super_settings/application/images/arrow-down-short.svg +3 -0
  12. data/lib/super_settings/application/images/arrow-up-short.svg +3 -0
  13. data/lib/super_settings/application/images/info-circle.svg +4 -0
  14. data/lib/super_settings/application/images/pencil-square.svg +4 -0
  15. data/lib/super_settings/application/images/plus.svg +3 -1
  16. data/lib/super_settings/application/images/trash3.svg +3 -0
  17. data/lib/super_settings/application/images/x-circle.svg +4 -0
  18. data/lib/super_settings/application/index.html.erb +54 -37
  19. data/lib/super_settings/application/layout.html.erb +5 -2
  20. data/lib/super_settings/application/layout_styles.css +7 -151
  21. data/lib/super_settings/application/layout_vars.css.erb +21 -0
  22. data/lib/super_settings/application/scripts.js +162 -37
  23. data/lib/super_settings/application/style_vars.css.erb +62 -0
  24. data/lib/super_settings/application/styles.css +183 -14
  25. data/lib/super_settings/application.rb +18 -11
  26. data/lib/super_settings/attributes.rb +1 -8
  27. data/lib/super_settings/configuration.rb +9 -0
  28. data/lib/super_settings/controller_actions.rb +2 -2
  29. data/lib/super_settings/engine.rb +1 -1
  30. data/lib/super_settings/history_item.rb +1 -1
  31. data/lib/super_settings/http_client.rb +165 -0
  32. data/lib/super_settings/rack_application.rb +3 -3
  33. data/lib/super_settings/rest_api.rb +5 -4
  34. data/lib/super_settings/setting.rb +13 -2
  35. data/lib/super_settings/storage/active_record_storage.rb +7 -0
  36. data/lib/super_settings/storage/history_attributes.rb +31 -0
  37. data/lib/super_settings/storage/http_storage.rb +60 -184
  38. data/lib/super_settings/storage/json_storage.rb +201 -0
  39. data/lib/super_settings/storage/mongodb_storage.rb +238 -0
  40. data/lib/super_settings/storage/redis_storage.rb +49 -111
  41. data/lib/super_settings/storage/s3_storage.rb +165 -0
  42. data/lib/super_settings/storage/storage_attributes.rb +64 -0
  43. data/lib/super_settings/storage/test_storage.rb +3 -5
  44. data/lib/super_settings/storage/transaction.rb +67 -0
  45. data/lib/super_settings/storage.rb +13 -6
  46. data/lib/super_settings/time_precision.rb +36 -0
  47. data/lib/super_settings.rb +11 -0
  48. data/super_settings.gemspec +4 -2
  49. metadata +22 -9
  50. data/lib/super_settings/application/images/edit.svg +0 -1
  51. data/lib/super_settings/application/images/info.svg +0 -1
  52. data/lib/super_settings/application/images/slash.svg +0 -1
  53. data/lib/super_settings/application/images/trash.svg +0 -1
@@ -15,8 +15,8 @@
15
15
 
16
16
  // Set the enabled status of the save button for submitting the form.
17
17
  function enableSaveButton() {
18
- const saveButton = document.querySelector("#save-settings");
19
- const discardButton = document.querySelector("#discard-changes");
18
+ const saveButton = document.querySelector("#super-settings-save-settings");
19
+ const discardButton = document.querySelector("#super-settings-discard-changes");
20
20
  if (saveButton) {
21
21
  const count = changesCount();
22
22
  const countSpan = saveButton.querySelector(".count");
@@ -117,6 +117,14 @@
117
117
  if (setting.description !== null && setting.description !== undefined) {
118
118
  row.querySelector(".super-settings-description .js-value-placeholder").innerHTML = escapeHTML(setting.description).replaceAll("\n", "<br>");
119
119
  }
120
+ if (setting.updated_at !== null && setting.updated_at !== undefined) {
121
+ const lastModified = new Date(Date.parse(setting.updated_at));
122
+ const lastModifiedFormatter = new Intl.DateTimeFormat(navigator.language, {month: "short", day: "numeric", year: "numeric"});
123
+ const lastModifiedString = lastModifiedFormatter.format(lastModified);
124
+ const lastModifiedElement = row.querySelector(".super-settings-last-modified .js-value-placeholder")
125
+ lastModifiedElement.innerText = lastModifiedString;
126
+ lastModifiedElement.title = dateFormatter().format(lastModified);
127
+ }
120
128
 
121
129
  return row
122
130
  }
@@ -182,6 +190,7 @@
182
190
  function editSettingRow(setting) {
183
191
  const row = elementFromSettingTemplate(setting, "#setting-row-edit-template");
184
192
  row.dataset.id = setting.id
193
+ row.dataset.key = setting.key
185
194
 
186
195
  row.querySelector(".super-settings-key input").value = setting.key;
187
196
  if (setting.description) {
@@ -223,9 +232,12 @@
223
232
  }
224
233
 
225
234
  // Create a table row with form elements for creating a new setting.
226
- function newSettingRow() {
235
+ function newSettingRow(key) {
236
+ if (!key) {
237
+ key = "";
238
+ }
227
239
  const randomId = "new" + Math.floor((Math.random() * 0xFFFFFFFFFFFFFF)).toString(16);
228
- const setting = {id: randomId, key: "", value: "", value_type: "string", new_record: true}
240
+ const setting = {id: randomId, key: key, value: "", value_type: "string", new_record: true}
229
241
  row = editSettingRow(setting);
230
242
  return row;
231
243
  }
@@ -239,7 +251,7 @@
239
251
  document.querySelector("#settings-table tbody").prepend(row);
240
252
  }
241
253
  bindSettingControlEvents(row);
242
- filterSettings(document.querySelector("#filter").value);
254
+ filterSettings(document.querySelector("#super-settings-filter").value);
243
255
  row.scrollIntoView({block: "nearest"});
244
256
  enableSaveButton();
245
257
  return row;
@@ -301,7 +313,7 @@
301
313
 
302
314
  // Programatically apply the filter again to keep it up to date with other changes.
303
315
  function applyFilter(value) {
304
- const filter = document.querySelector("#filter");
316
+ const filter = document.querySelector("#super-settings-filter");
305
317
  if (filter) {
306
318
  if (value) {
307
319
  filter.value = value;
@@ -330,11 +342,11 @@
330
342
  function showFlash(message, success) {
331
343
  const flash = document.querySelector(".js-flash");
332
344
  if (success) {
333
- flash.classList.add("text-success");
334
- flash.classList.remove("text-danger");
345
+ flash.classList.add("super-settings-text-success");
346
+ flash.classList.remove("super-settings-text-danger");
335
347
  } else {
336
- flash.classList.add("text-danger");
337
- flash.classList.remove("text-success");
348
+ flash.classList.add("tsuper-settings-ext-danger");
349
+ flash.classList.remove("super-settings-text-success");
338
350
  }
339
351
  flash.innerText = message;
340
352
  flash.style.display = "inline-block";
@@ -378,7 +390,7 @@
378
390
  tbody.insertAdjacentHTML("beforeend", rowsHTML);
379
391
 
380
392
  if (payload.previous_page_params || payload.next_page_params) {
381
- let paginationHTML = `<div class="align-center">`;
393
+ let paginationHTML = `<div class="super-settings-align-center">`;
382
394
  if (payload.previous_page_params) {
383
395
  paginationHTML += `<div style="float:left;"><a href="#" class="js-show-history" title="Newer" data-offset="${payload.previous_page_params.offset}" data-limit="${payload.previous_page_params.limit}" data-key="${payload.previous_page_params.key}")>&#8592; Newer</a></div>`;
384
396
  }
@@ -393,7 +405,7 @@
393
405
 
394
406
  // Show a modal window overlayed on the page.
395
407
  function showModal() {
396
- const modal = document.querySelector("#modal");
408
+ const modal = document.querySelector("#super-settings-modal");
397
409
  const content = document.querySelector(".super-settings-modal-content");
398
410
  modal.style.display = "block";
399
411
  modal.setAttribute("aria-hidden", "false");
@@ -409,7 +421,7 @@
409
421
 
410
422
  // Hide the modal window overlayed on the page.
411
423
  function hideModal() {
412
- const modal = document.querySelector("#modal");
424
+ const modal = document.querySelector("#super-settings-modal");
413
425
  const content = document.querySelector(".super-settings-modal-content");
414
426
  modal.style.display = "none";
415
427
  modal.setAttribute("aria-hidden", "true");
@@ -447,6 +459,33 @@
447
459
  return found;
448
460
  }
449
461
 
462
+ // Find a setting by key.
463
+ function findSettingByKey(key) {
464
+ let found = null;
465
+ activeSettings.forEach(function(setting) {
466
+ if (setting.key === key) {
467
+ found = setting;
468
+ return;
469
+ }
470
+ });
471
+ return found;
472
+ }
473
+
474
+ // Add a new setting.
475
+ function addSetting(key) {
476
+ const row = addRowToTable(newSettingRow(key));
477
+ row.querySelector(".super-settings-key input").focus();
478
+ }
479
+
480
+ function editSetting(setting) {
481
+ const row = addRowToTable(editSettingRow(setting));
482
+ if (row.querySelector(".super-settings-value .js-date-input")) {
483
+ row.querySelector(".super-settings-value .js-date-input").focus();
484
+ } else {
485
+ row.querySelector(".super-settings-value .js-setting-value").focus();
486
+ }
487
+ }
488
+
450
489
  /*** Event Listeners ***/
451
490
 
452
491
  // Listener for showing the setting history modal.
@@ -456,7 +495,7 @@
456
495
  return;
457
496
  }
458
497
 
459
- const modal = document.querySelector("#modal");
498
+ const modal = document.querySelector("#super-settings-modal");
460
499
  const content = document.querySelector(".super-settings-modal-content");
461
500
  let key = event.target.dataset.key;
462
501
  if (!key) {
@@ -533,23 +572,17 @@
533
572
  }
534
573
 
535
574
  // Listener for the add setting button.
536
- function addSetting(event) {
575
+ function addSettingListener(event) {
537
576
  event.preventDefault();
538
- const row = addRowToTable(newSettingRow());
539
- row.querySelector(".super-settings-key input").focus();
577
+ addSetting();
540
578
  }
541
579
 
542
580
  // Listener for the edit setting button.
543
- function editSetting(event) {
581
+ function editSettingListener(event) {
544
582
  event.preventDefault();
545
583
  const id = event.target.closest("tr").dataset.id;
546
- const setting = findSetting(id);
547
- const row = addRowToTable(editSettingRow(setting));
548
- if (row.querySelector(".super-settings-value .js-date-input")) {
549
- row.querySelector(".super-settings-value .js-date-input").focus();
550
- } else {
551
- row.querySelector(".super-settings-value .js-setting-value").focus();
552
- }
584
+ setting = findSetting(id);
585
+ editSetting(setting);
553
586
  }
554
587
 
555
588
  // Listener for the restore setting button.
@@ -592,7 +625,12 @@
592
625
  document.querySelectorAll("#settings-table tbody tr[data-edited=true]").forEach(function(row) {
593
626
  const data = {};
594
627
  settingsData.push(data);
628
+
595
629
  data.key = row.querySelector(".js-setting-key").value;
630
+ if (data.key != row.dataset.key) {
631
+ data.key_was = row.dataset.key;
632
+ }
633
+
596
634
  const deleted = row.querySelector(".js-setting-deleted");
597
635
  if (deleted && deleted.value === "1") {
598
636
  data.deleted = true;
@@ -635,13 +673,25 @@
635
673
  function refreshPage(event) {
636
674
  event.preventDefault();
637
675
  let url = window.location.href.replace(/\?.*/, "");
638
- const filter = document.querySelector("#filter").value;
676
+ const filter = document.querySelector("#super-settings-filter").value;
639
677
  if (filter !== "") {
640
678
  url += "?filter=" + escape(filter);
641
679
  }
642
680
  window.location = url;
643
681
  }
644
682
 
683
+ // Open the setting if the URL hash includes #edit=setting.
684
+ function fetchEditHash() {
685
+ const hash = window.location.hash;
686
+ if (hash.startsWith("#edit=")) {
687
+ const name = hash.replace("#edit=", "");
688
+ window.location.hash = "";
689
+ return name;
690
+ } else {
691
+ return null;
692
+ }
693
+ }
694
+
645
695
  // Support integration into single page applications where OAuth2 access tokens are used.
646
696
  // The access token can be passed either in the access_token query parameter per the
647
697
  // OAuth2 standard, or in the URL hash. Passing it in the hash will prevent it from ever
@@ -680,7 +730,7 @@
680
730
  // Bind event listeners for setting controls on a setting table row.
681
731
  function bindSettingControlEvents(parent) {
682
732
  addListener(parent.querySelectorAll(".js-remove-setting"), "click", removeSetting);
683
- addListener(parent.querySelectorAll(".js-edit-setting"), "click", editSetting);
733
+ addListener(parent.querySelectorAll(".js-edit-setting"), "click", editSettingListener);
684
734
  addListener(parent.querySelectorAll(".js-restore-setting"), "click", restoreSetting);
685
735
  addListener(parent.querySelectorAll(".js-show-history"), "click", showHistoryModal);
686
736
  addListener(parent.querySelectorAll(".js-no-op"), "click", noOp);
@@ -694,8 +744,9 @@
694
744
  const tbody = document.querySelector("#settings-table tbody");
695
745
  tbody.innerHTML = "";
696
746
  let count = settings.length;
697
- settings.forEach(function(setting) {
698
- const randomId = "setting" + Math.floor((Math.random() * 0xFFFFFFFFFFFFFF)).toString(16);
747
+
748
+ sortSettings(settings).forEach(function(setting) {
749
+ const randomId = "setting" + Math.floor((Math.random() * 0xFFFFFFFFFFFFF)).toString(16);
699
750
  setting.id = (setting.id || randomId);
700
751
  const row = settingRow(setting);
701
752
  tbody.appendChild(row);
@@ -703,12 +754,73 @@
703
754
  });
704
755
  document.querySelector(".js-settings-count").textContent = `${count} ${count === 1 ? "Setting" : "Settings"}`;
705
756
 
706
- const filter = document.querySelector("#filter");
757
+ const filter = document.querySelector("#super-settings-filter");
707
758
  if (filter) {
708
759
  filter.dispatchEvent(new Event("input"));
709
760
  }
710
761
  }
711
762
 
763
+ function sortOrder() {
764
+ const selectedSort = document.querySelector(".super-settings-sort-control[data-selected=true]");
765
+ const field = selectedSort.dataset.field;
766
+ const order = selectedSort.dataset.order;
767
+ return {field: field, order: order};
768
+ }
769
+
770
+ // Sort settings by the selected sort option.
771
+ function sortSettings(settings) {
772
+ const sort = sortOrder();
773
+ return settings.sort(function(a, b) {
774
+ let aValue = a[sort.field];
775
+ let bValue = b[sort.field];
776
+ if (sort.field == "updated_at") {
777
+ aValue = new Date(Date.parse(aValue));
778
+ bValue = new Date(Date.parse(bValue));
779
+ }
780
+
781
+ if (aValue === bValue) {
782
+ return 0;
783
+ } else if (sort.order === "asc") {
784
+ return (aValue < bValue) ? -1 : 1;
785
+ } else {
786
+ return (aValue > bValue) ? -1 : 1;
787
+ }
788
+ })
789
+ }
790
+
791
+ function setSortOrder(event) {
792
+ event.preventDefault();
793
+
794
+ const target = event.target.closest(".super-settings-sort-control");
795
+ let prevSelection = document.querySelector(".super-settings-sort-control[data-selected=true]");
796
+
797
+ if (prevSelection == target) {
798
+ selectSortElement(prevSelection, false);
799
+ target.querySelector(`[data-order=${target.dataset.order}]`).style.display = "none";
800
+ target.dataset.order = (target.dataset.order === "asc" ? "desc" : "asc");
801
+ target.querySelector(`[data-order=${target.dataset.order}]`).style.display = "inline-block";
802
+ } else {
803
+ selectSortElement(prevSelection, false);
804
+ }
805
+
806
+ selectSortElement(target, true);
807
+
808
+ renderSettingsTable(activeSettings);
809
+ }
810
+
811
+ function selectSortElement(element, selected) {
812
+ element.dataset.selected = selected;
813
+
814
+ const svg = element.querySelector(`[data-order=${element.dataset.order}]`).querySelector("svg");
815
+ if (selected) {
816
+ svg.style.backgroundColor = getComputedStyle(document.querySelector(".super-settings")).getPropertyValue("--primary-color");
817
+ svg.style.fill = "white";
818
+ } else {
819
+ svg.style.backgroundColor = null;
820
+ svg.style.fill = null;
821
+ }
822
+ }
823
+
712
824
  function promptUnsavedChanges(event) {
713
825
  if (changesCount() > 0) {
714
826
  return "Are you sure you want to leave?";
@@ -726,11 +838,19 @@
726
838
  }
727
839
  }
728
840
 
729
- function fetchActiveSettings() {
841
+ function fetchActiveSettings(editKey) {
730
842
  SuperSettingsAPI.fetchSettings(function(settings_hash) {
731
843
  const settings = settings_hash["settings"];
732
844
  activeSettings = settings;
733
845
  renderSettingsTable(settings);
846
+ if (editKey) {
847
+ const setting = findSettingByKey(editKey);
848
+ if (setting) {
849
+ editSetting(setting);
850
+ } else {
851
+ addSetting(editKey);
852
+ }
853
+ }
734
854
  enableSaveButton();
735
855
  });
736
856
  }
@@ -740,16 +860,21 @@
740
860
  docReady(function() {
741
861
  storeAccessToken();
742
862
 
743
- addListener(document.querySelector("#filter"), "input", filterListener);
744
- addListener(document.querySelector("#add-setting"), "click", addSetting);
745
- addListener(document.querySelector("#discard-changes"), "click", refreshPage);
746
- addListener(document.querySelector("#save-settings"), "click", updateSettings);
747
- addListener(document.querySelector("#modal"), "click", closeModal);
863
+ addListener(document.querySelector("#super-settings-filter"), "input", filterListener);
864
+ addListener(document.querySelector("#super-settings-add-setting"), "click", addSettingListener);
865
+ addListener(document.querySelector("#super-settings-discard-changes"), "click", refreshPage);
866
+ addListener(document.querySelector("#super-settings-save-settings"), "click", updateSettings);
867
+ addListener(document.querySelector("#super-settings-modal"), "click", closeModal);
868
+ addListener(document.querySelectorAll(".super-settings-sort-control"), "click", setSortOrder);
869
+
870
+ const editKey = fetchEditHash();
748
871
 
749
872
  const queryParams = new URLSearchParams(window.location.search);
750
873
  applyFilter(queryParams.get("filter"));
751
874
 
752
- fetchActiveSettings();
875
+ selectSortElement(document.querySelector(".super-settings-sort-control[data-selected=true]"), true);
876
+
877
+ fetchActiveSettings(editKey);
753
878
 
754
879
  window.onbeforeunload = promptUnsavedChanges;
755
880
  })
@@ -0,0 +1,62 @@
1
+ .super-settings {
2
+ --primary-color-h: 216;
3
+ --primary-color-s: 98%;
4
+ --primary-color-l: 52%;
5
+ --primary-color-hsl: var(--primary-color-h), var(--primary-color-s), var(--primary-color-l);
6
+ --primary-color: hsl(var(--primary-color-hsl));
7
+ --primary-contrast-color: #fff;
8
+ --primary-hover-color: hsl(var(--primary-color-h), var(--primary-color-s), calc(var(--primary-color-l) - 10%));
9
+ --primary-border-color: hsl(var(--primary-color-h), var(--primary-color-s), calc(var(--primary-color-l) + 10%));
10
+ }
11
+
12
+ <% unless color_scheme == :dark %>
13
+ .super-settings {
14
+ --edit-bg-color: #f2fdf2;
15
+ --deleted-row-color: darkred;
16
+ --deleted-row-bg-color: #ffd1d8;
17
+ --history-key-color: royalblue;
18
+ --table-header-bg-color: #fff;
19
+ --table-border-color: #dee2e6;
20
+ --alt-row-color: rgba(0, 0, 0, .05);
21
+ --form-control-color: #495057;
22
+ --form-control-bg-color: #fff;
23
+ --form-control-border-color: #ced4da;
24
+ --form-control-placeholder-color: #bbb;
25
+ --modal-bg-color: #fff;
26
+ --modal-transparency: 0.4;
27
+ --modal-control-color: #000;
28
+ --success-color: green;
29
+ --danger-color: firebrick;
30
+ --muted-color: #666;
31
+ --unselected-color: #666;
32
+ }
33
+ <% end %>
34
+
35
+ <% if color_scheme == :system %>
36
+ @media (prefers-color-scheme: dark) {
37
+ <% end %>
38
+ <% if color_scheme == :system || color_scheme == :dark %>
39
+ .super-settings {
40
+ --edit-bg-color: #8dc875;
41
+ --deleted-row-color: #e0b1b8;
42
+ --deleted-row-bg-color: #7a3636;
43
+ --history-key-color: #a7d6f4;
44
+ --table-header-bg-color: #333;
45
+ --table-border-color: #555;
46
+ --alt-row-color: rgba(0, 0, 0, .30);
47
+ --form-control-color: #eee;
48
+ --form-control-bg-color: #666;
49
+ --form-control-border-color: #555;
50
+ --form-control-placeholder-color: #aaa;
51
+ --modal-bg-color: #333;
52
+ --modal-transparency: 0.75;
53
+ --modal-control-color: #fff;
54
+ --success-color: #00ff00;
55
+ --danger-color: #ff0000;
56
+ --muted-color: #999;
57
+ --unselected-color: #ccc;
58
+ }
59
+ <% end %>
60
+ <% if color_scheme == :system %>
61
+ }
62
+ <% end %>
@@ -1,3 +1,10 @@
1
+ .super-settings-container {
2
+ padding-left: 15px;
3
+ padding-right: 15px;
4
+ margin-left: auto;
5
+ margin-right: auto;
6
+ }
7
+
1
8
  #settings-table td p {
2
9
  margin-top: 0;
3
10
  margin-bottom: 0.5rem;
@@ -11,13 +18,9 @@
11
18
  width: 100%;
12
19
  }
13
20
 
14
- .super-settings-edit-row {
15
- background-color: #f2fdf2 !important;
16
- }
17
-
18
21
  #settings-table tr[data-deleted] td {
19
- background-color: #ffd1d8 !important;
20
- color: darkred;
22
+ background-color: var(--deleted-row-bg-color) !important;
23
+ color: var(--deleted-row-color);
21
24
  text-decoration: line-through;
22
25
  }
23
26
 
@@ -25,16 +28,49 @@
25
28
  display: none;
26
29
  }
27
30
 
31
+ .super-settings-icon {
32
+ display: inline-block;
33
+ }
34
+
35
+ .super-settings-icon svg {
36
+ width: 100%;
37
+ height: 100%;
38
+ vertical-align: inherit;
39
+ }
40
+
41
+ .super-settings-btn-no-chrome {
42
+ display: inline-block;
43
+ vertical-align: middle;
44
+ background-color: transparent;
45
+ border: 0;
46
+ padding: 0;
47
+ cursor: pointer;
48
+ }
49
+
50
+
51
+
52
+ .super-settings-sort-control {
53
+ color: var(--unselected-color);
54
+ }
55
+
56
+ .super-settings-sort-control svg {
57
+ vertical-align: middle;
58
+ }
59
+
60
+ .super-settings-edit-row {
61
+ background-color: var(--edit-bg-color) !important;
62
+ }
63
+
28
64
  .super-settings-key {
29
65
  overflow-wrap: break-word;
30
66
  max-width: 30rem;
31
- min-width: 15rem;
67
+ min-width: 8rem;
32
68
  }
33
69
 
34
70
  .super-settings-value {
35
71
  overflow-wrap: break-word;
36
72
  max-width: 30rem;
37
- min-width: 15rem;
73
+ min-width: 8rem;
38
74
  }
39
75
 
40
76
  .super-settings-value-type {
@@ -59,7 +95,34 @@
59
95
 
60
96
  .super-settings-history-key {
61
97
  font-weight: normal;
62
- color: royalblue;
98
+ color: var(--history-key-color);
99
+ }
100
+
101
+ .super-settings-table {
102
+ width: 100%;
103
+ max-width: 100%;
104
+ margin-bottom: 1rem;
105
+ border-collapse: collapse;
106
+ }
107
+
108
+ .super-settings-table thead th {
109
+ vertical-align: bottom;
110
+ border-bottom: 2px solid var(--table-border-color);
111
+ white-space: nowrap;
112
+ }
113
+
114
+ .super-settings-table td, .super-settings-table th {
115
+ padding: 0.75rem;
116
+ vertical-align: top;
117
+ border-top: 1px solid var(--table-border-color);
118
+ }
119
+
120
+ .super-settings-table-striped tbody tr:nth-of-type(odd) {
121
+ background-color: var(--alt-row-color);
122
+ }
123
+
124
+ .super-settings-align-center {
125
+ text-align: center;
63
126
  }
64
127
 
65
128
  .super-settings-modal {
@@ -72,12 +135,12 @@
72
135
  width: 100%;
73
136
  height: 100%;
74
137
  overflow: auto;
75
- background-color: rgba(0,0,0,0.4);
138
+ background-color: rgba(0, 0, 0, var(--modal-transparency));
76
139
  }
77
140
 
78
141
  .super-settings-modal-dialog {
79
142
  margin: auto;
80
- background-color: #fff;
143
+ background-color: var(--modal-bg-color);
81
144
  position: relative;
82
145
  outline: 0;
83
146
  padding: 2em;
@@ -99,7 +162,7 @@
99
162
  right: 0;
100
163
  border: 0;
101
164
  padding: 1ex;
102
- background-color: inherit;
165
+ color: var(--modal-control-color);
103
166
  font-size: 1.5rem;
104
167
  font-weight: 500;
105
168
  }
@@ -122,6 +185,112 @@
122
185
  .super-settings-sticky-top {
123
186
  position: sticky;
124
187
  top: 0;
125
- padding: 1rem 0;
126
- background-color: white;
188
+ padding: 1rem;
189
+ background-color: var(--table-header-bg-color);
190
+ }
191
+
192
+ .super-settings-form-control {
193
+ font-family: inherit;
194
+ margin: 0;
195
+ overflow: visible;
196
+ display: block;
197
+ width: 100%;
198
+ padding: .375rem .75rem;
199
+ font-size: 1rem;
200
+ line-height: 1.5;
201
+ color: var(--form-control-color);
202
+ background-color: var(--form-control-bg-color);
203
+ background-clip: padding-box;
204
+ border: 1px solid var(--form-control-border-color);
205
+ border-radius: .25rem;
206
+ transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
207
+ }
208
+
209
+ .super-settings-form-control::placeholder {
210
+ color: var(--form-control-placeholder-color);
211
+ }
212
+
213
+ select.super-settings-form-control:not([size]):not([multiple]) {
214
+ height: calc(2.25rem + 2px);
215
+ }
216
+
217
+ .super-settings-form-check {
218
+ margin-top: .5rem;
219
+ display: inline-block;
220
+ }
221
+
222
+ .super-settings-form-check input[type=checkbox] {
223
+ vertical-align: middle;
224
+ }
225
+
226
+ .super-settings-form-inline {
227
+ display: inline-block;
228
+ }
229
+
230
+ .super-settings-form-inline .super-settings-form-control {
231
+ display: inline-block;
232
+ width: auto;
233
+ vertical-align: middle;
234
+ }
235
+
236
+ .super-settings-form-control textarea {
237
+ font-family: inherit;
238
+ margin: 0;
239
+ overflow: auto;
240
+ resize: vertical;
241
+ }
242
+
243
+ .super-settings-text-success {
244
+ color: var(--success-color) !important;
245
+ }
246
+
247
+ .super-settings-text-danger {
248
+ color: var(--danger-color) !important;
249
+ }
250
+
251
+ .super-settings-text-muted {
252
+ color: var(--muted-color) !important;
253
+ }
254
+
255
+ .super-settings-btn {
256
+ display: inline-block;
257
+ vertical-align: middle;
258
+ padding: 0.375rem 0.75rem;
259
+ border-radius: 0.375rem;
260
+ border: 1px solid #dcdcdc;
261
+ background-color:#f9f9f9;
262
+ text-decoration: none;
263
+ text-align: center;
264
+ font-family: Arial, sans-serif;
265
+ font-size: 1rem;
266
+ font-weight: 400;
267
+ line-height: 1.5;
268
+ user-select: none;
269
+ cursor: pointer;
270
+ transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out, box-shadow .15s ease-in-out;
271
+ }
272
+
273
+ .super-settings-btn:hover:not(:disabled) {
274
+ background-color:#e9e9e9;
275
+ }
276
+ .super-settings-btn:active {
277
+ position:relative;
278
+ top:1px;
279
+ }
280
+ .super-settings-btn:disabled {
281
+ opacity: 0.8;
282
+ cursor: not-allowed;
283
+ }
284
+
285
+ .super-settings-btn-primary {
286
+ background-color: var(--primary-color);
287
+ border-color: var(--primary-border-color);
288
+ color: var(--primary-contrast-color);
289
+ }
290
+ .super-settings-btn-primary:hover:not(:disabled) {
291
+ background-color: var(--primary-hover-color);
292
+ }
293
+
294
+ .super-settings-btn-primary:disabled {
295
+ opacity: 0.5;
127
296
  }