super_settings 2.3.1 → 2.4.0

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.
@@ -1,8 +1,8 @@
1
1
  (function() {
2
- // Return the table row element for a setting.
3
- function findSettingRow(id) {
2
+ // Return the card element for a setting.
3
+ function findSettingCard(id) {
4
4
  if (id) {
5
- return document.querySelector('#settings-table tr[data-id="' + id + '"]');
5
+ return document.querySelector('#settings-container .super-settings-card[data-id="' + id + '"]');
6
6
  } else {
7
7
  return null;
8
8
  }
@@ -10,7 +10,7 @@
10
10
 
11
11
  // Return the number of settings that have been edited.
12
12
  function changesCount() {
13
- return document.querySelectorAll("#settings-table tbody tr[data-edited=true]").length;
13
+ return document.querySelectorAll("#settings-container .super-settings-card[data-edited=true]").length;
14
14
  }
15
15
 
16
16
  // Set the enabled status of the save button for submitting the form.
@@ -55,11 +55,11 @@
55
55
  }
56
56
 
57
57
  // Get the value of a setting from the edit form field.
58
- function getSettingEditValue(row) {
59
- if (row.querySelector(".super-settings-value input.js-setting-value[type=checkbox]")) {
60
- return row.querySelector(".super-settings-value input.js-setting-value[type=checkbox]").checked;
58
+ function getSettingEditValue(card) {
59
+ if (card.querySelector(".super-settings-card-value input.js-setting-value[type=checkbox]")) {
60
+ return card.querySelector(".super-settings-card-value input.js-setting-value[type=checkbox]").checked;
61
61
  } else {
62
- return row.querySelector(".super-settings-value .js-setting-value").value;
62
+ return card.querySelector(".super-settings-card-value .js-setting-value").value;
63
63
  }
64
64
  }
65
65
 
@@ -94,39 +94,39 @@
94
94
  return template.content.firstChild;
95
95
  }
96
96
 
97
- // Create a table row element for displaying a setting.
98
- function settingRow(setting) {
99
- const row = elementFromSettingTemplate(setting, "#setting-row-template");
100
- row.dataset.id = setting.id
101
- row.dataset.key = setting.key
102
- row.querySelector(".js-setting-key").value = setting.key;
97
+ // Create a card element for displaying a setting.
98
+ function settingCard(setting) {
99
+ const card = elementFromSettingTemplate(setting, "#setting-card-template");
100
+ card.dataset.id = setting.id
101
+ card.dataset.key = setting.key
102
+ card.querySelector(".js-setting-key").value = setting.key;
103
103
  if (setting.deleted) {
104
- row.dataset.edited = true
105
- row.dataset.deleted = true
106
- row.querySelector(".js-setting-deleted").value = "1";
104
+ card.dataset.edited = true
105
+ card.dataset.deleted = true
106
+ card.querySelector(".js-setting-deleted").value = "1";
107
107
  }
108
108
  if (setting.key !== null && setting.key !== undefined) {
109
- row.querySelector(".super-settings-key .js-value-placeholder").innerText = setting.key;
109
+ card.querySelector(".super-settings-card-key .js-value-placeholder").innerText = setting.key;
110
110
  }
111
111
  if (setting.value !== null && setting.value !== undefined) {
112
- setSettingDisplayValue(row.querySelector(".super-settings-value .js-value-placeholder"), setting);
112
+ setSettingDisplayValue(card.querySelector(".super-settings-card-value .js-value-placeholder"), setting);
113
113
  }
114
114
  if (setting.value_type !== null && setting.value_type !== undefined) {
115
- row.querySelector(".super-settings-value-type .js-value-placeholder").innerText = setting.value_type;
115
+ card.querySelector(".super-settings-card-type .js-value-placeholder").innerText = setting.value_type;
116
116
  }
117
117
  if (setting.description !== null && setting.description !== undefined) {
118
- row.querySelector(".super-settings-description .js-value-placeholder").innerHTML = escapeHTML(setting.description).replaceAll("\n", "<br>");
118
+ card.querySelector(".super-settings-card-description .js-value-placeholder").innerHTML = escapeHTML(setting.description).replaceAll("\n", "<br>");
119
119
  }
120
120
  if (setting.updated_at !== null && setting.updated_at !== undefined) {
121
121
  const lastModified = new Date(Date.parse(setting.updated_at));
122
122
  const lastModifiedFormatter = new Intl.DateTimeFormat(navigator.language, {month: "short", day: "numeric", year: "numeric"});
123
123
  const lastModifiedString = lastModifiedFormatter.format(lastModified);
124
- const lastModifiedElement = row.querySelector(".super-settings-last-modified .js-value-placeholder")
124
+ const lastModifiedElement = card.querySelector(".super-settings-card-modified .js-value-placeholder")
125
125
  lastModifiedElement.innerText = lastModifiedString;
126
126
  lastModifiedElement.title = dateFormatter().format(lastModified);
127
127
  }
128
128
 
129
- return row
129
+ return card
130
130
  }
131
131
 
132
132
  // Create an input element from a template depending on the value type.
@@ -186,23 +186,23 @@
186
186
  return element;
187
187
  }
188
188
 
189
- // Create a table row with form elements for editing a setting.
190
- function editSettingRow(setting) {
191
- const row = elementFromSettingTemplate(setting, "#setting-row-edit-template");
192
- row.dataset.id = setting.id
193
- row.dataset.key = setting.key
189
+ // Create a card with form elements for editing a setting.
190
+ function editSettingCard(setting) {
191
+ const card = elementFromSettingTemplate(setting, "#setting-card-edit-template");
192
+ card.dataset.id = setting.id
193
+ card.dataset.key = setting.key
194
194
 
195
- row.querySelector(".super-settings-key input").value = setting.key;
195
+ card.querySelector(".super-settings-card-key input").value = setting.key;
196
196
  if (setting.description) {
197
- row.querySelector(".super-settings-description textarea").value = setting.description;
197
+ card.querySelector(".super-settings-card-description textarea").value = setting.description;
198
198
  }
199
199
 
200
200
  const valueInput = valueInputElement(setting);
201
- const valuePlaceholder = row.querySelector(".super-settings-value .js-value-placeholder");
201
+ const valuePlaceholder = card.querySelector(".super-settings-card-value .js-value-placeholder");
202
202
  valuePlaceholder.innerHTML = "";
203
203
  valuePlaceholder.appendChild(valueInput);
204
204
 
205
- const valueType = row.querySelector(".super-settings-value-type select");
205
+ const valueType = card.querySelector(".super-settings-card-type select");
206
206
  for (let i = 0; i < valueType.options.length; i++) {
207
207
  if (valueType.options[i].value === setting.value_type) {
208
208
  valueType.selectedIndex = i;
@@ -215,49 +215,52 @@
215
215
  setting.errors.forEach(function(error) {
216
216
  errorsHTML += `<div>${escapeHTML(error)}</div>`
217
217
  });
218
- row.querySelector(".js-setting-errors").innerHTML = errorsHTML;
218
+ card.querySelector(".js-setting-errors").innerHTML = errorsHTML;
219
219
  }
220
220
 
221
221
  if (setting.new_record) {
222
- row.dataset.newrecord = "true";
222
+ card.dataset.newrecord = "true";
223
223
  }
224
224
 
225
- const timezone = row.querySelector(".timezone");
225
+ const timezone = card.querySelector(".timezone");
226
226
  if (timezone) {
227
227
  tzName = Intl.DateTimeFormat().resolvedOptions().timeZone;
228
228
  timezone.innerText = tzName;
229
229
  }
230
230
 
231
- return row
231
+ return card
232
232
  }
233
233
 
234
- // Create a table row with form elements for creating a new setting.
235
- function newSettingRow(key) {
234
+ // Create a card with form elements for creating a new setting.
235
+ function newSettingCard(key, valueType) {
236
236
  if (!key) {
237
237
  key = "";
238
238
  }
239
+ if (!valueType) {
240
+ valueType = "string";
241
+ }
239
242
  const randomId = "new" + Math.floor((Math.random() * 0xFFFFFFFFFFFFFF)).toString(16);
240
- const setting = {id: randomId, key: key, value: "", value_type: "string", new_record: true}
241
- row = editSettingRow(setting);
242
- return row;
243
+ const setting = {id: randomId, key: key, value: "", value_type: valueType, new_record: true}
244
+ card = editSettingCard(setting);
245
+ return card;
243
246
  }
244
247
 
245
- // Add a setting table row the table of settings.
246
- function addRowToTable(row) {
247
- const existingRow = findSettingRow(row.dataset.id);
248
- if (existingRow) {
249
- existingRow.replaceWith(row);
248
+ // Add a setting card to the container of settings.
249
+ function addCardToContainer(card) {
250
+ const existingCard = findSettingCard(card.dataset.id);
251
+ if (existingCard) {
252
+ existingCard.replaceWith(card);
250
253
  } else {
251
- document.querySelector("#settings-table tbody").prepend(row);
254
+ document.querySelector("#settings-container").prepend(card);
252
255
  }
253
- bindSettingControlEvents(row);
256
+ bindSettingControlEvents(card);
254
257
  filterSettings(document.querySelector("#super-settings-filter").value);
255
- row.scrollIntoView({block: "nearest"});
258
+ card.scrollIntoView({block: "nearest"});
256
259
  enableSaveButton();
257
- return row;
260
+ return card;
258
261
  }
259
262
 
260
- // Update the window location URL to reflect the current filter text.
263
+ // Update the filter URL and settings count display.
261
264
  function updateFilterURL(filter) {
262
265
  const queryParams = new URLSearchParams(window.location.search);
263
266
  if (filter === "") {
@@ -272,23 +275,28 @@
272
275
  }
273
276
  }
274
277
 
278
+ // Update the settings count display.
279
+ function updateSettingsCount(count) {
280
+ document.querySelector(".js-settings-count").textContent = `${count} ${count === 1 ? "Setting" : "Settings"}`;
281
+ }
282
+
275
283
  // Apply the given filter to only show settings that have a key, value, or description
276
284
  // that includes the filter text. Settings that are currently being edited will also be shown.
277
285
  function filterSettings(filterText) {
278
286
  const filters = [];
279
287
  filterText.split(" ").forEach(function(filter) {
280
288
  filter = filter.toUpperCase();
281
- filters.push(function(tr) {
289
+ filters.push(function(card) {
282
290
  let text = "";
283
- const settingKey = tr.querySelector(".super-settings-key");
291
+ const settingKey = card.querySelector(".super-settings-card-key");
284
292
  if (settingKey) {
285
293
  text += " " + settingKey.textContent.toUpperCase();
286
294
  }
287
- const settingValue = tr.querySelector(".super-settings-value");
295
+ const settingValue = card.querySelector(".super-settings-card-value");
288
296
  if (settingValue) {
289
297
  text += " " + settingValue.textContent.toUpperCase();
290
298
  }
291
- const settingDescription = tr.querySelector(".setting-description");
299
+ const settingDescription = card.querySelector(".super-settings-card-description");
292
300
  if (settingDescription) {
293
301
  text += " " + settingDescription.textContent.toUpperCase();
294
302
  }
@@ -296,19 +304,24 @@
296
304
  });
297
305
  });
298
306
 
299
- document.querySelectorAll("#settings-table tbody tr").forEach(function(tr) {
307
+ let visibleCount = 0;
308
+ document.querySelectorAll("#settings-container .super-settings-card").forEach(function(card) {
300
309
  let matched = true;
301
- if (!tr.dataset.edited) {
310
+ if (!card.dataset.edited) {
302
311
  filters.forEach(function(filter) {
303
- matched = matched && filter(tr);
312
+ matched = matched && filter(card);
304
313
  });
305
314
  }
306
315
  if (matched) {
307
- tr.style.display = "table-row";
316
+ card.style.display = "";
317
+ visibleCount++;
308
318
  } else {
309
- tr.style.display = "none";
319
+ card.style.display = "none";
310
320
  }
311
321
  });
322
+
323
+ updateFilterURL(filterText);
324
+ updateSettingsCount(visibleCount);
312
325
  }
313
326
 
314
327
  // Programatically apply the filter again to keep it up to date with other changes.
@@ -323,12 +336,12 @@
323
336
 
324
337
  // Display validation errors on settings form.
325
338
  function showValidationErrors(errors) {
326
- const table = document.querySelector("#settings-table");
339
+ const container = document.querySelector("#settings-container");
327
340
  Object.keys(errors).forEach(function(key) {
328
- table.querySelectorAll(".super-settings-edit-row").forEach(function(row) {
329
- const settingKey = row.querySelector(".js-setting-key");
341
+ container.querySelectorAll(".super-settings-card-edit").forEach(function(card) {
342
+ const settingKey = card.querySelector(".js-setting-key");
330
343
  if (settingKey && settingKey.value === key) {
331
- const errorsElement = row.querySelector(".js-setting-errors");
344
+ const errorsElement = card.querySelector(".js-setting-errors");
332
345
  if (errorsElement) {
333
346
  errorsElement.innerText = errors[key].join("; ");
334
347
  errorsElement.style.display = "block";
@@ -379,15 +392,19 @@
379
392
  function renderHistoryTable(parent, payload) {
380
393
  parent.innerHTML = document.querySelector("#setting-history-table").innerHTML.trim();
381
394
  parent.querySelector(".super-settings-history-key").innerText = payload.key;
382
- const tbody = parent.querySelector("tbody");
383
- let rowsHTML = "";
395
+ const historyItems = parent.querySelector("#super-settings-history");
396
+ let itemsHTML = "";
384
397
  payload.histories.forEach(function(history) {
385
398
  const date = new Date(Date.parse(history.created_at));
386
399
  const dateString = dateFormatter().format(date);
387
400
  const value = (history.deleted ? '<em class="super-settings-text-danger">deleted</em>' : escapeHTML(history.value));
388
- rowsHTML += `<tr><td class="super-settings-text-nowrap">${escapeHTML(dateString)}</td><td>${escapeHTML(history.changed_by)}</td><td>${value}</td></tr>`;
401
+ itemsHTML += `<div class="super-settings-history-item">
402
+ <div class="super-settings-history-time">${escapeHTML(dateString)}</div>
403
+ <div class="super-settings-history-user">${escapeHTML(history.changed_by)}</div>
404
+ <div class="super-settings-history-value">${value}</div>
405
+ </div>`;
389
406
  });
390
- tbody.insertAdjacentHTML("beforeend", rowsHTML);
407
+ historyItems.insertAdjacentHTML("beforeend", itemsHTML);
391
408
 
392
409
  if (payload.previous_page_params || payload.next_page_params) {
393
410
  let paginationHTML = `<div class="super-settings-align-center">`;
@@ -398,7 +415,7 @@
398
415
  paginationHTML += `<div style="float:right;"><a href="#" class="js-show-history" title="Older" data-offset="${payload.next_page_params.offset}" data-limit="${payload.next_page_params.limit}" data-key="${payload.next_page_params.key}")>Older &#8594;</a></div>`;
399
416
  }
400
417
  paginationHTML += '<div style="clear:both;"></div>';
401
- parent.querySelector("table").insertAdjacentHTML("afterend", paginationHTML);
418
+ parent.querySelector(".super-settings-history-container").insertAdjacentHTML("afterend", paginationHTML);
402
419
  }
403
420
  addListener(parent.querySelectorAll(".js-show-history"), "click", showHistoryModal);
404
421
  }
@@ -472,17 +489,17 @@
472
489
  }
473
490
 
474
491
  // Add a new setting.
475
- function addSetting(key) {
476
- const row = addRowToTable(newSettingRow(key));
477
- row.querySelector(".super-settings-key input").focus();
492
+ function addSetting(key, valueType) {
493
+ const card = addCardToContainer(newSettingCard(key, valueType));
494
+ card.querySelector(".super-settings-card-key input").focus();
478
495
  }
479
496
 
480
497
  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();
498
+ const card = addCardToContainer(editSettingCard(setting));
499
+ if (card.querySelector(".super-settings-card-value .js-date-input")) {
500
+ card.querySelector(".super-settings-card-value .js-date-input").focus();
484
501
  } else {
485
- row.querySelector(".super-settings-value .js-setting-value").focus();
502
+ card.querySelector(".super-settings-card-value .js-setting-value").focus();
486
503
  }
487
504
  }
488
505
 
@@ -499,9 +516,9 @@
499
516
  const content = document.querySelector(".super-settings-modal-content");
500
517
  let key = event.target.dataset.key;
501
518
  if (!key) {
502
- const row = event.target.closest("tr");
503
- if (row) {
504
- const id = row.dataset.id;
519
+ const card = event.target.closest(".super-settings-card");
520
+ if (card) {
521
+ const id = card.dataset.id;
505
522
  const setting = findSetting(id);
506
523
  if (setting) {
507
524
  key = setting.key;
@@ -541,21 +558,21 @@
541
558
  // different input elements for the setting value.
542
559
  function changeSettingType(event) {
543
560
  event.preventDefault();
544
- const row = event.target.closest("tr");
561
+ const card = event.target.closest(".super-settings-card");
545
562
  const valueType = event.target.options[event.target.selectedIndex].value;
546
563
  var setting = {
547
- id: row.dataset.id,
548
- key: row.querySelector(".super-settings-key input").value,
549
- value: getSettingEditValue(row),
564
+ id: card.dataset.id,
565
+ key: card.querySelector(".super-settings-card-key input").value,
566
+ value: getSettingEditValue(card),
550
567
  value_type: valueType,
551
- description: row.querySelector(".super-settings-description textarea").value,
552
- new_record: row.dataset.newrecord
568
+ description: card.querySelector(".super-settings-card-description textarea").value,
569
+ new_record: card.dataset.newrecord
553
570
  }
554
- const addedRow = addRowToTable(editSettingRow(setting));
555
- if (addedRow.querySelector(".super-settings-value .js-date-input")) {
556
- addedRow.querySelector(".super-settings-value .js-date-input").focus();
571
+ const addedCard = addCardToContainer(editSettingCard(setting));
572
+ if (addedCard.querySelector(".super-settings-card-value .js-date-input")) {
573
+ addedCard.querySelector(".super-settings-card-value .js-date-input").focus();
557
574
  } else {
558
- addedRow.querySelector(".super-settings-value .js-setting-value").focus();
575
+ addedCard.querySelector(".super-settings-card-value .js-setting-value").focus();
559
576
  }
560
577
  }
561
578
 
@@ -580,7 +597,7 @@
580
597
  // Listener for the edit setting button.
581
598
  function editSettingListener(event) {
582
599
  event.preventDefault();
583
- const id = event.target.closest("tr").dataset.id;
600
+ const id = event.target.closest(".super-settings-card").dataset.id;
584
601
  setting = findSetting(id);
585
602
  editSetting(setting);
586
603
  }
@@ -588,15 +605,19 @@
588
605
  // Listener for the restore setting button.
589
606
  function restoreSetting(event) {
590
607
  event.preventDefault();
591
- const row = event.target.closest("tr");
592
- const id = row.dataset.id;
608
+ const card = event.target.closest(".super-settings-card");
609
+ const id = card.dataset.id;
593
610
  const setting = findSetting(id);
594
611
  if (setting) {
595
- const newRow = settingRow(setting);
596
- bindSettingControlEvents(newRow);
597
- row.replaceWith(newRow);
612
+ const newCard = settingCard(setting);
613
+ bindSettingControlEvents(newCard);
614
+ card.replaceWith(newCard);
598
615
  } else {
599
- row.remove();
616
+ card.remove();
617
+ // Update the settings count after removing the card
618
+ setTimeout(function() {
619
+ filterSettings(document.querySelector("#super-settings-filter").value);
620
+ }, 0);
600
621
  }
601
622
  enableSaveButton();
602
623
  }
@@ -604,15 +625,19 @@
604
625
  // Listener for the remove setting button.
605
626
  function removeSetting(event) {
606
627
  event.preventDefault();
607
- const settingRow = event.target.closest("tr");
608
- if (settingRow.dataset["id"]) {
609
- settingRow.querySelector("input.js-setting-deleted").value = "1";
610
- settingRow.dataset.edited = true;
611
- settingRow.dataset.deleted = true;
612
- settingRow.querySelector(".js-remove-setting").style.display = "none";
613
- settingRow.querySelector(".js-restore-setting").style.display = "inline-block";
628
+ const settingCard = event.target.closest(".super-settings-card");
629
+ if (settingCard.dataset["id"]) {
630
+ settingCard.querySelector("input.js-setting-deleted").value = "1";
631
+ settingCard.dataset.edited = true;
632
+ settingCard.dataset.deleted = true;
633
+ settingCard.querySelector(".js-remove-setting").style.display = "none";
634
+ settingCard.querySelector(".js-restore-setting").style.display = "inline-block";
614
635
  } else {
615
- settingRow.remove();
636
+ settingCard.remove();
637
+ // Update the settings count after removing an unsaved setting
638
+ setTimeout(function() {
639
+ filterSettings(document.querySelector("#super-settings-filter").value);
640
+ }, 0);
616
641
  }
617
642
  enableSaveButton();
618
643
  }
@@ -622,28 +647,28 @@
622
647
  event.preventDefault();
623
648
  event.target.disabled = true;
624
649
  const settingsData = [];
625
- document.querySelectorAll("#settings-table tbody tr[data-edited=true]").forEach(function(row) {
650
+ document.querySelectorAll("#settings-container .super-settings-card[data-edited=true]").forEach(function(card) {
626
651
  const data = {};
627
652
  settingsData.push(data);
628
653
 
629
- data.key = row.querySelector(".js-setting-key").value;
630
- if (data.key != row.dataset.key) {
631
- data.key_was = row.dataset.key;
654
+ data.key = card.querySelector(".js-setting-key").value;
655
+ if (data.key != card.dataset.key) {
656
+ data.key_was = card.dataset.key;
632
657
  }
633
658
 
634
- const deleted = row.querySelector(".js-setting-deleted");
659
+ const deleted = card.querySelector(".js-setting-deleted");
635
660
  if (deleted && deleted.value === "1") {
636
661
  data.deleted = true;
637
662
  } else {
638
- if (row.querySelector(".js-setting-value")) {
639
- data.value = getSettingEditValue(row);
663
+ if (card.querySelector(".js-setting-value")) {
664
+ data.value = getSettingEditValue(card);
640
665
  }
641
- if (row.querySelector(".js-setting-value-type")) {
642
- const valueTypeSelect = row.querySelector(".js-setting-value-type");
666
+ if (card.querySelector(".js-setting-value-type")) {
667
+ const valueTypeSelect = card.querySelector(".js-setting-value-type");
643
668
  data.value_type = valueTypeSelect.options[valueTypeSelect.selectedIndex].value;
644
669
  }
645
- if (row.querySelector(".super-settings-description textarea")) {
646
- data.description = row.querySelector(".super-settings-description textarea").value;
670
+ if (card.querySelector(".super-settings-card-description textarea")) {
671
+ data.description = card.querySelector(".super-settings-card-description textarea").value;
647
672
  }
648
673
  }
649
674
  });
@@ -680,16 +705,29 @@
680
705
  window.location = url;
681
706
  }
682
707
 
683
- // Open the setting if the URL hash includes #edit=setting.
684
- function fetchEditHash() {
708
+ // Parse URL hash looking for URL-style parameters like #edit=setting&type=string.
709
+ function fetchURLHash() {
685
710
  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;
711
+ if (hash.length <= 1) {
712
+ return {};
692
713
  }
714
+
715
+ // Remove the # and check if it looks like URL parameters
716
+ const hashParams = hash.substring(1);
717
+ if (!hashParams.includes('=')) {
718
+ return {};
719
+ }
720
+
721
+ const params = {};
722
+ hashParams.split('&').forEach(function(param) {
723
+ const [key, value] = param.split('=', 2);
724
+ if (key && value) {
725
+ params[decodeURIComponent(key)] = decodeURIComponent(value);
726
+ }
727
+ });
728
+
729
+ window.location.hash = "";
730
+ return params;
693
731
  }
694
732
 
695
733
  // Support integration into single page applications where OAuth2 access tokens are used.
@@ -739,20 +777,20 @@
739
777
  addListener(parent.querySelectorAll(".js-time-input"), "change", changeDateTime);
740
778
  }
741
779
 
742
- // Initialize the table with all the settings plus any changes from a failed form submission.
743
- function renderSettingsTable(settings) {
744
- const tbody = document.querySelector("#settings-table tbody");
745
- tbody.innerHTML = "";
780
+ // Initialize the container with all the settings plus any changes from a failed form submission.
781
+ function renderSettingsContainer(settings) {
782
+ const container = document.querySelector("#settings-container");
783
+ container.innerHTML = "";
746
784
  let count = settings.length;
747
785
 
748
786
  sortSettings(settings).forEach(function(setting) {
749
787
  const randomId = "setting" + Math.floor((Math.random() * 0xFFFFFFFFFFFFF)).toString(16);
750
788
  setting.id = (setting.id || randomId);
751
- const row = settingRow(setting);
752
- tbody.appendChild(row);
753
- bindSettingControlEvents(row);
789
+ const card = settingCard(setting);
790
+ container.appendChild(card);
791
+ bindSettingControlEvents(card);
754
792
  });
755
- document.querySelector(".js-settings-count").textContent = `${count} ${count === 1 ? "Setting" : "Settings"}`;
793
+ updateSettingsCount(count);
756
794
 
757
795
  const filter = document.querySelector("#super-settings-filter");
758
796
  if (filter) {
@@ -805,7 +843,7 @@
805
843
 
806
844
  selectSortElement(target, true);
807
845
 
808
- renderSettingsTable(activeSettings);
846
+ renderSettingsContainer(activeSettings);
809
847
  }
810
848
 
811
849
  function selectSortElement(element, selected) {
@@ -838,17 +876,17 @@
838
876
  }
839
877
  }
840
878
 
841
- function fetchActiveSettings(editKey) {
879
+ function fetchActiveSettings(hashParams) {
842
880
  SuperSettingsAPI.fetchSettings(function(settings_hash) {
843
881
  const settings = settings_hash["settings"];
844
882
  activeSettings = settings;
845
- renderSettingsTable(settings);
846
- if (editKey) {
847
- const setting = findSettingByKey(editKey);
883
+ renderSettingsContainer(settings);
884
+ if (hashParams && hashParams.edit) {
885
+ const setting = findSettingByKey(hashParams.edit);
848
886
  if (setting) {
849
887
  editSetting(setting);
850
888
  } else {
851
- addSetting(editKey);
889
+ addSetting(hashParams.edit, hashParams.type);
852
890
  }
853
891
  }
854
892
  enableSaveButton();
@@ -867,14 +905,14 @@
867
905
  addListener(document.querySelector("#super-settings-modal"), "click", closeModal);
868
906
  addListener(document.querySelectorAll(".super-settings-sort-control"), "click", setSortOrder);
869
907
 
870
- const editKey = fetchEditHash();
908
+ const hashParams = fetchURLHash();
871
909
 
872
910
  const queryParams = new URLSearchParams(window.location.search);
873
911
  applyFilter(queryParams.get("filter"));
874
912
 
875
913
  selectSortElement(document.querySelector(".super-settings-sort-control[data-selected=true]"), true);
876
914
 
877
- fetchActiveSettings(editKey);
915
+ fetchActiveSettings(hashParams);
878
916
 
879
917
  window.onbeforeunload = promptUnsavedChanges;
880
918
  })
@@ -17,7 +17,7 @@
17
17
  --history-key-color: royalblue;
18
18
  --table-header-bg-color: #fff;
19
19
  --table-border-color: #dee2e6;
20
- --alt-row-color: rgba(0, 0, 0, .05);
20
+ --alt-row-color: rgba(0, 0, 0, .03);
21
21
  --form-control-color: #495057;
22
22
  --form-control-bg-color: #fff;
23
23
  --form-control-border-color: #ced4da;
@@ -27,8 +27,17 @@
27
27
  --modal-control-color: #000;
28
28
  --success-color: green;
29
29
  --danger-color: firebrick;
30
- --muted-color: #666;
30
+ --muted-color: #999;
31
31
  --unselected-color: #666;
32
+ --btn-hover-color: #e9e9e9;
33
+ --card-bg-color: #fff;
34
+
35
+ /* Icon Colors */
36
+ --icon-info-color: #0d7ff0;
37
+ --icon-edit-color: #0c8024;
38
+ --icon-delete-color: #dc3545;
39
+ --icon-cancel-color: #dc3545;
40
+ --icon-disabled-color: #c0c0c0;
32
41
  }
33
42
  <% end %>
34
43
 
@@ -37,7 +46,7 @@
37
46
  <% end %>
38
47
  <% if color_scheme == :system || color_scheme == :dark %>
39
48
  .super-settings {
40
- --edit-bg-color: #8dc875;
49
+ --edit-bg-color: #437330;
41
50
  --deleted-row-color: #e0b1b8;
42
51
  --deleted-row-bg-color: #7a3636;
43
52
  --history-key-color: #a7d6f4;
@@ -47,14 +56,23 @@
47
56
  --form-control-color: #eee;
48
57
  --form-control-bg-color: #666;
49
58
  --form-control-border-color: #555;
59
+ --btn-hover-color: #c0c0c0;
50
60
  --form-control-placeholder-color: #aaa;
51
61
  --modal-bg-color: #333;
52
62
  --modal-transparency: 0.75;
53
63
  --modal-control-color: #fff;
54
64
  --success-color: #00ff00;
55
65
  --danger-color: #ff0000;
56
- --muted-color: #999;
66
+ --muted-color: #ccc;
57
67
  --unselected-color: #ccc;
68
+ --card-bg-color: #484848;
69
+
70
+ /* Icon Colors */
71
+ --icon-info-color: #71b0f0;
72
+ --icon-edit-color: #7dde90;
73
+ --icon-delete-color: #eb8791;
74
+ --icon-cancel-color: #eb8791;
75
+ --icon-disabled-color: #aaa;
58
76
  }
59
77
  <% end %>
60
78
  <% if color_scheme == :system %>