Skip to content

Commit 58e86f1

Browse files
committed
Streamline/Update UI
1 parent 61bc204 commit 58e86f1

File tree

10 files changed

+653
-519
lines changed

10 files changed

+653
-519
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2727
- Systray: Support multiple instances
2828
- UI: Validate that key ports do not overlap across editors and pages
2929
- UI: Provide additional details in error dialogue
30+
- UI: LED preview - show instance's name the preview is applicable to
3031
- Http-Server: Support Cross-Origin Resource Sharing (CORS) (#1496)
3132

3233
**JSON-API**
@@ -58,6 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5859
- Refactored: Decouple WebServer and SSDPHandler
5960
- Refactored: Corrected thread affinity across various classes
6061
- Refactored: Improved code resilience and error handling
62+
- Refactored: Streamlined the UI code
6163
- Standalone grabber do not capture screens when no connection to remote host
6264
- Fixed: Python 3.12 crashes (#1747)
6365
- osX Grabber: Use ScreenCaptureKit under macOS 15 and above
@@ -68,6 +70,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6870
- Fixed Screen capture error (#1824)
6971
- Fixed Provide custom forwarding targets is not possible (#1713)
7072
- Fixed Last update of an effect event is not removed in sources overview
73+
- UI: Instance listings are sorted, enabled instances are high-lighted in drop-downs
7174

7275
**JSON-API**
7376
- Refactored JSON-API to ensure consistent authorization behaviour across sessions and single requests with token authorization.

assets/webconfig/content/login.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ <h3 class="panel-title">Login</h3>
1313
<input name="show_pw" type="checkbox" id="show_pw" /><label for="show_pw">Show/Hide Password</label>
1414
</div>
1515
<div class="form-group">
16-
<button type="submit" class="btn btn-sm btn-success" id="btn_password" onclick="requestAuthorization(document.getElementById('password').value); return false;"><i class="fa fa-fw fa-unlock"></i>Login</button>
16+
<button type="submit" class="btn btn-sm btn-success" id="btn_password" disabled onclick="requestAuthorization(document.getElementById('password').value); return false;"><i class="fa fa-fw fa-unlock"></i>Login</button>
1717
</div>
1818
</form>
1919
</div>

assets/webconfig/js/content_dashboard.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ $(document).ready(function () {
189189
}
190190
}
191191
}
192-
updateUiOnInstance(window.currentHyperionInstance);
193-
updateHyperionInstanceListing();
194192

193+
updateHyperionInstanceListing();
194+
updateUiOnInstance(window.currentHyperionInstance);
195195
}
196196

197197
function updateGlobalComponents() {

assets/webconfig/js/content_general.js

Lines changed: 60 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ $(document).ready(function () {
3131
requestWriteConfig(conf_editor.getValue());
3232
});
3333

34+
createTable('ithead', 'itbody', 'itable');
35+
36+
// Initialize the table header
37+
if ($('#ithead').length === 0) {
38+
$('.ithead').html(createTableRow([$.i18n('conf_general_inst_namehead'), "", $.i18n('conf_general_inst_actionhead'), ""], true, true));
39+
}
40+
41+
buildInstanceList();
42+
3443
// Instance handling functions
3544
function handleInstanceRename(instance) {
3645
showInfoDialog('renInst', $.i18n('conf_general_inst_renreq_t'), getInstanceName(instance));
@@ -59,81 +68,75 @@ $(document).ready(function () {
5968
// Build the instance list
6069
function buildInstanceList() {
6170

62-
const instances = serverInfo.instance;
63-
64-
// Ensure .itbody exists and clear it
6571
const $itbody = $('.itbody');
6672
if ($itbody.length === 0) {
6773
console.warn("Element '.itbody' does not exist. Aborting instance list build.");
6874
return;
6975
}
70-
$itbody.empty(); // Explicitly clear the content before adding new rows
7176

72-
// Collect rows in a document fragment for efficient DOM updates
73-
const $rows = $(document.createDocumentFragment());
77+
const data = window.serverInfo.instance;
78+
if (data) {
79+
const instances = Object.values(data);
80+
81+
// Sort instances by friendly_name (case-insensitive)
82+
instances.sort((a, b) => a.friendly_name.toLowerCase().localeCompare(b.friendly_name.toLowerCase()));
83+
84+
$itbody.empty(); // Explicitly clear the content before adding new rows
85+
86+
// Collect rows in a document fragment for efficient DOM updates
87+
const $rows = $(document.createDocumentFragment());
7488

75-
for (const instance in instances) {
76-
const instanceID = instances[instance].instance;
77-
const enableStyle = instances[instance].running ? "checked" : "";
78-
const renameBtn = `<button id="instren_${instanceID}" type="button" class="btn btn-primary">
89+
// Build all instance rows
90+
for (const instance of instances) {
91+
const instanceID = instance.instance;
92+
const enableStyle = instance.running ? "checked" : "";
93+
const renameBtn = `<button id="instren_${instanceID}" type="button" class="btn btn-primary">
7994
<i class="mdi mdi-lead-pencil"></i>
8095
</button>`;
81-
const delBtn = `<button id="instdel_${instanceID}" type="button" class="btn btn-danger">
96+
const delBtn = `<button id="instdel_${instanceID}" type="button" class="btn btn-danger">
8297
<i class="mdi mdi-delete-forever"></i>
8398
</button>`;
84-
const startBtn = `<input id="inst_${instanceID}" ${enableStyle} type="checkbox"
99+
const startBtn = `<input id="inst_${instanceID}" ${enableStyle} type="checkbox"
100+
class="toggle-instance"
85101
data-toggle="toggle" data-onstyle="success font-weight-bold"
86102
data-on="${$.i18n('general_btn_on')}" data-offstyle="default font-weight-bold"
87103
data-off="${$.i18n('general_btn_off')}">`;
88104

89-
// Generate a table row and add it to the document fragment
90-
const $row = createTableRow(
91-
[
92-
instances[instance].friendly_name,
93-
startBtn,
94-
renameBtn,
95-
delBtn
96-
],
97-
false,
98-
true
99-
);
100-
101-
$rows.append($row);
102-
}
103-
104-
// Append all rows to .itbody in one operation
105-
$itbody.append($rows);
106-
107-
// Reapply event listeners
108-
for (const instance in instances) {
109-
const instanceID = instances[instance].instance;
110-
111-
const readOnly = window.readOnlyMode;
112-
$('#instren_' + instanceID).prop('disabled', readOnly);
113-
$('#inst_' + instanceID).prop('disabled', readOnly);
114-
$('#instdel_' + instanceID).prop('disabled', readOnly);
115-
116-
$('#instren_' + instanceID).off().on('click', function () {
117-
handleInstanceRename(instanceID);
118-
});
119-
120-
$('#instdel_' + instanceID).off().on('click', function () {
121-
handleInstanceDelete(instanceID);
122-
});
123-
124-
$('#inst_' + instanceID).bootstrapToggle();
125-
$('#inst_' + instanceID).change(function () {
126-
const isChecked = $(this).prop('checked');
127-
requestInstanceStartStop(instanceID, isChecked);
128-
});
105+
const $row = createTableRow(
106+
[instance.friendly_name, startBtn, renameBtn, delBtn],
107+
false,
108+
true
109+
);
110+
111+
$rows.append($row);
112+
}
113+
114+
$itbody.append($rows);
115+
116+
// Apply Bootstrap toggles and event handlers
117+
for (const instance of instances) {
118+
const instanceID = instance.instance;
119+
const readOnly = window.readOnlyMode;
120+
121+
$('#instren_' + instanceID).prop('disabled', readOnly).off().on('click', function () {
122+
handleInstanceRename(instanceID);
123+
});
124+
125+
$('#instdel_' + instanceID).prop('disabled', readOnly).off().on('click', function () {
126+
handleInstanceDelete(instanceID);
127+
});
128+
129+
const $toggle = $('#inst_' + instanceID);
130+
$toggle.prop('disabled', readOnly);
131+
$toggle.bootstrapToggle(); // Reapply toggle
132+
$toggle.off('change').on('change', function () {
133+
const isChecked = $(this).prop('checked');
134+
requestInstanceStartStop(instanceID, isChecked);
135+
});
136+
}
129137
}
130138
}
131139

132-
// Initialize table
133-
createTable('ithead', 'itbody', 'itable');
134-
$('.ithead').html(createTableRow([$.i18n('conf_general_inst_namehead'), "", $.i18n('conf_general_inst_actionhead'), ""], true, true));
135-
buildInstanceList();
136-
137140
// Instance name input validation
138141
$('#inst_name').off().on('input', function (e) {
139142
const isValid = e.currentTarget.value.length >= 5 && !window.readOnlyMode;

0 commit comments

Comments
 (0)