Skip to content

Commit dad72a6

Browse files
committed
Better grouping
1 parent aac97cc commit dad72a6

File tree

3 files changed

+116
-18
lines changed

3 files changed

+116
-18
lines changed

composer.html

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,16 @@
1919

2020
<body>
2121
<div id="header-section">
22-
<div class="controls">
23-
<select id="settings-dropdown" onchange="loadSelectedFile()"></select>
24-
<button id="export-button" onclick="exportToJson()" style="float: right;">Export</button>
22+
<div class="controls" style="display: flex; justify-content: space-between;">
23+
<div>
24+
<select id="settings-dropdown" onchange="loadSelectedFile()"></select>
25+
</div>
26+
<div>
27+
<button id="export-button" onclick="exportToJson()">Export</button>
28+
<button id="import-button" onclick="document.getElementById('import-file').click();"
29+
style="margin-right:0;">Import</button>
30+
<input type="file" id="import-file" onchange="importFromJson()" style="display: none;" />
31+
</div>
2532
</div>
2633
</div>
2734

@@ -99,6 +106,39 @@ <h2>Commands</h2>
99106
URL.revokeObjectURL(url);
100107
}
101108

109+
async function importFromJson() {
110+
const fileInput = document.getElementById('import-file');
111+
const file = fileInput.files[0];
112+
113+
if (!file) {
114+
alert('Please select a file to import.');
115+
return;
116+
}
117+
118+
displaySettings();
119+
console.log('Importing settings from file:', file.name);
120+
const reader = new FileReader();
121+
reader.onload = async function (event) {
122+
try {
123+
const entries = Object.entries(JSON.parse(event.target.result));
124+
125+
for (const [key, value] of entries) {
126+
const settingObj = getByKey(key);
127+
if (settingObj) {
128+
const checkbox = document.getElementById(`checkbox-${settingObj.id}`);
129+
checkbox.checked = true;
130+
checkbox.parentElement.parentElement.classList.remove('transparent');
131+
setInputValue(settingObj.id, value);
132+
}
133+
}
134+
} catch (error) {
135+
console.error('Error importing settings:', error);
136+
showToast('Failed to import settings. Please check the file format.');
137+
}
138+
};
139+
reader.readAsText(file);
140+
}
141+
102142
function displaySettings() {
103143
const settingsSection = document.getElementById('settings-section');
104144
settingsSection.innerHTML = '';
@@ -110,20 +150,21 @@ <h2>Commands</h2>
110150
settingsContainer.className = 'settings-container';
111151

112152
const groupHeading = document.createElement('h3');
113-
groupHeading.textContent = groupName.replace(/_/g, "");
153+
groupHeading.textContent = groupName.replace(/_/g, " ");
114154
settingsSection.appendChild(groupHeading);
115155

116156
for (const [key, setting] of Object.entries(group)) {
117157
// Create the top-level container
118158
const row = document.createElement('div');
119159
row.className = 'setting transparent';
120160
row.setAttribute('id', `setting-${setting.id}`);
161+
row.setAttribute('data-search', key);
121162

122163
// Build the "include" checkbox + label
123164
row.innerHTML = `
124165
<div class="checkbox-container">
125166
<input type="checkbox" id="checkbox-${setting.id}" onchange="updateCheckBox(this, '${setting.id}')"/>
126-
<label for="checkbox-${setting.id}"><h4>${key} <small>(${setting.id})</small></h4></label>
167+
<label for="checkbox-${setting.id}"><h4 title="${key}">${setting.display_name} <small>(${setting.id})</small></h4></label>
127168
</div>${renderInputContainer(key, setting)}
128169
`;
129170

functions.js

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,20 @@ const intervalPatterns = [
66
/^(cold|hot)_fix_timeout$/
77
];
88

9+
const grouping = {
10+
"^(hot|cold)_": "satellite",
11+
"^sat_send_flag$": "satellite",
12+
"^rejoin_interval$": "lr",
13+
"^app_(key|eui)$": "lr",
14+
"^device_eui$": "lr",
15+
"^horizontal_accuracy$": "ublox",
16+
"^motion_ths$": "gps",
17+
"^enable_motion_trig_gps$": "gps",
18+
"^rf_open_sky_detection": 0,
19+
"^rf_scan": 0,
20+
"(^.{2,}?)_": 1
21+
};
22+
923
const bitmapSettings = [/^.*_flag$/];
1024

1125
const skipPorts = ['port_lr_messaging', 'port_flash_log', 'port_values', 'port_messages', 'port_commands'];
@@ -116,7 +130,8 @@ function filterSettings() {
116130
const settings = group.querySelectorAll('.setting');
117131

118132
settings.forEach(setting => {
119-
const matchesSearch = setting.querySelector('h4').textContent.toLowerCase().includes(query);
133+
const dataSearch = setting.getAttribute('data-search') || setting.querySelector('h4').textContent;
134+
const matchesSearch = dataSearch.toLowerCase().includes(query);
120135
const isNonDefault = setting.classList.contains('value-not-default');
121136
const shouldShow = matchesSearch && (!showNonDefaultOnly || isNonDefault);
122137

@@ -253,16 +268,38 @@ function guessTimeUnit(seconds) {
253268
return '1';
254269
}
255270

271+
function formatSettingName(settingName, group) {
272+
if (settingName.startsWith(group + "_")) {
273+
settingName = settingName.replace(group + "_", "");
274+
}
275+
276+
return settingName;
277+
}
278+
279+
function getGroupName(key) {
280+
for (const [rx, groupName] of Object.entries(grouping)) {
281+
const match = key.match(rx);
282+
if (match) {
283+
if (typeof groupName === 'number') {
284+
return match[groupName];
285+
} else {
286+
return groupName;
287+
}
288+
}
289+
}
290+
return key;
291+
}
292+
256293
function groupAndSortSettings() {
257294
const grouped = {};
258295
const other = {};
259296

260297
for (const key in settingsData.settings) {
261-
const prefix = key.split('_')[0];
262-
if (!grouped[prefix]) {
263-
grouped[prefix] = {};
298+
const groupName = getGroupName(key);
299+
if (!grouped[groupName]) {
300+
grouped[groupName] = {};
264301
}
265-
grouped[prefix][key] = settingsData.settings[key];
302+
grouped[groupName][key] = settingsData.settings[key];
266303
}
267304

268305
// Move singletons into "_other"
@@ -273,13 +310,24 @@ function groupAndSortSettings() {
273310
delete grouped[prefix];
274311
}
275312
}
313+
276314
if (Object.keys(other).length > 0) {
277315
grouped["_other"] = other;
278316
}
279317

318+
for (const groupName in grouped) {
319+
for (const key in grouped[groupName]) {
320+
grouped[groupName][key].display_name = formatSettingName(key, groupName);
321+
}
322+
}
323+
280324
// Sort groups
281325
const sortedGroups = Object.keys(grouped).sort().reduce((acc, group) => {
282-
acc[group] = Object.keys(grouped[group]).sort().reduce((groupAcc, key) => {
326+
acc[group] = Object.keys(grouped[group]).sort((a, b) => {
327+
const nameA = grouped[group][a].display_name.toLowerCase();
328+
const nameB = grouped[group][b].display_name.toLowerCase();
329+
return nameA.localeCompare(nameB);
330+
}).reduce((groupAcc, key) => {
283331
groupAcc[key] = grouped[group][key];
284332
return groupAcc;
285333
}, {});

index.html

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646

4747
<div class="settings-section hidden-when-no-settings">
4848
<h2>Settings</h2>
49-
<div class="search">
49+
<div id="search" class="search">
5050
<input type="text" id="settings-search" placeholder="Search settings..." oninput="filterSettings()">
5151
<label>
5252
<input type="checkbox" id="non-default-checkbox" onchange="filterSettings()"> Hide default settings
@@ -58,8 +58,8 @@ <h2>Settings</h2>
5858
<div id="settings-section"></div>
5959
</div>
6060

61-
<div class="commands-section hidden-when-no-settings">
62-
<a name="allcommands"></a>
61+
<div id="other-commands" class="commands-section hidden-when-no-settings">
62+
<a name="other-commands"></a>
6363
<h2>Commands</h2>
6464
<div id="commands-buttons-section"></div>
6565
</div>
@@ -182,11 +182,17 @@ <h2>Commands</h2>
182182
const progressContainer = document.getElementById('settings-progress');
183183
const progressBar = document.querySelector('#settings-progress div');
184184
const settingsSection = document.getElementById('settings-section');
185+
const commandsSection = document.getElementById('other-commands');
186+
const search = document.getElementById('search');
187+
document.getElementById('settings-search').value = '';
188+
185189

186190
try {
191+
search.classList.add('hidden');
187192
progressBar.style.width = `0%`;
188193
progressContainer.style.display = 'block';
189-
settingsSection.style.display = 'none';
194+
settingsSection.classList.add('hidden');
195+
commandsSection.classList.add('hidden');
190196

191197
const importedSettings = JSON.parse(event.target.result);
192198

@@ -208,7 +214,9 @@ <h2>Commands</h2>
208214
console.error('Error importing settings:', error);
209215
showToast('Failed to import settings. Please check the file format.');
210216
} finally {
211-
settingsSection.style.display = 'block';
217+
search.classList.remove('hidden');
218+
settingsSection.classList.remove('hidden');
219+
commandsSection.classList.remove('hidden');
212220
progressContainer.style.display = 'none';
213221
}
214222
};
@@ -407,15 +415,16 @@ <h4>${device.name}</h4>
407415
settingsContainer.className = 'settings-container';
408416

409417
const groupHeading = document.createElement('h3');
410-
groupHeading.textContent = groupName.replace(/_/g, "");
418+
groupHeading.textContent = groupName.replace(/_/g, " ");
411419
settingsSection.appendChild(groupHeading);
412420

413421
for (const [key, setting] of Object.entries(group)) {
414422
const row = document.createElement('div');
415423
row.className = 'setting disabled with-controls';
416424
row.setAttribute('id', `setting-${setting.id}`);
425+
row.setAttribute('data-search', key);
417426
row.innerHTML = `
418-
<h4>${key} (${setting.id})</h4>
427+
<h4>${setting.display_name} (${setting.id})</h4>
419428
420429
${renderInput(key, setting)}
421430

0 commit comments

Comments
 (0)