super_settings 1.0.2 → 2.0.1

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.
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
  }