[feat](trx-frontend-http): reorder the controls tray sections
CI / lint (push) Successful in 2m23s
CI / frontend (push) Failing after 31s
CI / reuse (push) Successful in 3s
CI / test (push) Successful in 8m14s

The radio's own settings now come first, then audio, then the scheduler:
Advanced radio controls, Audio controls, Scheduler controls.

The advanced section is not in the markup — ui-core builds it at runtime
and gathers the SDR settings, virtual channel and TX limit rows into it,
appending the result, which put it last however the markup was ordered.
It is inserted ahead of the audio section instead.

The signal readout and the TX meters stay where they are, between the
controls and the sections: they are readouts rather than a section, and
on an SDR the spectrum covers them anyway.

Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
sjg
2026-08-03 22:41:08 +02:00
parent 730f129404
commit c073d03ffb
4 changed files with 42 additions and 30 deletions
@@ -743,7 +743,7 @@ function elementById(id) {
const element = document.getElementById(id);
if (element) body.appendChild(element);
});
tray.appendChild(details);
tray.insertBefore(details, document.getElementById("audio-controls"));
api.applyLayout(savedLayoutName(), { persist: false });
}
}
@@ -372,34 +372,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
<div class="vchan-picker" id="vchan-picker"></div>
</div>
</div>
<details id="scheduler-controls" class="advanced-radio-controls scheduler-controls-section">
<summary>Scheduler controls</summary>
<div class="advanced-radio-body">
<div class="scheduler-control-row" style="display:none">
<div class="scheduler-release-wrap">
<div class="scheduler-action-row">
<div class="scheduler-step-controls">
<button id="scheduler-prev-btn" type="button">Previous Entry</button>
<button id="scheduler-next-btn" type="button">Next Entry</button>
</div>
<button id="scheduler-release-btn" type="button">Release to Scheduler</button>
<div id="scheduler-cycle-status" class="interleave-ring-wrap" style="display:none;">
<svg class="interleave-ring" viewBox="0 0 36 36">
<circle class="interleave-ring-bg" cx="18" cy="18" r="15.915" />
<circle class="interleave-ring-fill" id="interleave-ring-fill" cx="18" cy="18" r="15.915"
stroke-dasharray="100" stroke-dashoffset="100" />
</svg>
<div class="interleave-ring-text">
<div class="interleave-ring-label" id="interleave-active-name">--</div>
<div class="interleave-ring-sub" id="interleave-countdown">--</div>
</div>
</div>
</div>
<div id="scheduler-release-status" class="scheduler-release-status">Scheduler is controlling the rig.</div>
</div>
</div>
</div>
</details>
<div class="full-row label-below-row">
<div class="label"><span>Signal</span></div>
<div class="signal" style="gap: 1rem;">
@@ -448,6 +420,34 @@ SPDX-License-Identifier: GPL-2.0-or-later
</div>
</div>
</details>
<details id="scheduler-controls" class="advanced-radio-controls scheduler-controls-section">
<summary>Scheduler controls</summary>
<div class="advanced-radio-body">
<div class="scheduler-control-row" style="display:none">
<div class="scheduler-release-wrap">
<div class="scheduler-action-row">
<div class="scheduler-step-controls">
<button id="scheduler-prev-btn" type="button">Previous Entry</button>
<button id="scheduler-next-btn" type="button">Next Entry</button>
</div>
<button id="scheduler-release-btn" type="button">Release to Scheduler</button>
<div id="scheduler-cycle-status" class="interleave-ring-wrap" style="display:none;">
<svg class="interleave-ring" viewBox="0 0 36 36">
<circle class="interleave-ring-bg" cx="18" cy="18" r="15.915" />
<circle class="interleave-ring-fill" id="interleave-ring-fill" cx="18" cy="18" r="15.915"
stroke-dasharray="100" stroke-dashoffset="100" />
</svg>
<div class="interleave-ring-text">
<div class="interleave-ring-label" id="interleave-active-name">--</div>
<div class="interleave-ring-sub" id="interleave-countdown">--</div>
</div>
</div>
</div>
<div id="scheduler-release-status" class="scheduler-release-status">Scheduler is controlling the rig.</div>
</div>
</div>
</div>
</details>
</div>
</div>
</div>
@@ -317,7 +317,10 @@ function elementById<T extends HTMLElement>(id: string): T {
const element = document.getElementById(id);
if (element) body.appendChild(element);
});
tray.appendChild(details);
// Ahead of the collapsibles the markup ships: the radio's own settings
// come before audio and the scheduler, and appending would put the
// section built here last whatever the markup says.
tray.insertBefore(details, document.getElementById("audio-controls"));
api.applyLayout(savedLayoutName(), { persist: false });
}
}
@@ -23,6 +23,15 @@ try {
await page.locator("summary", { hasText: "Audio controls" }).click();
assert.equal(await page.locator("#rx-audio-btn").count(), 1);
// Section order in the tray. "Advanced radio controls" is built at runtime,
// so it lands wherever ui-core puts it rather than where the markup says —
// appending, as it once did, always left it last.
const sections = await page.evaluate(() =>
[...document.querySelectorAll(".controls-tray > details")].map((section) =>
section.querySelector("summary").textContent.trim()));
assert.deepEqual(sections, ["Advanced radio controls", "Audio controls", "Scheduler controls"],
`tray sections are ${JSON.stringify(sections)}`);
// Mode is a button group over a hidden <select>, which stays the value a
// dozen call sites and several plugins read. The click has to reach it, and
// the select must not take part in layout while it does.