From bcd7e409ba396e7c2845d9e709e0d7d4f58367bc Mon Sep 17 00:00:00 2001 From: rouggy Date: Mon, 31 Aug 2026 19:05:56 +0200 Subject: [PATCH] fix(cluster): a disconnected server keeps its pill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pills listed live SESSIONS, so disconnecting one made it vanish — along with the only way back. They now list every enabled server, and a server with no session shows as disconnected: the state you click to undo. The address, known only while a session exists, drops out of the tooltip rather than reading ':0'. --- changelog.json | 4 ++-- frontend/src/App.tsx | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/changelog.json b/changelog.json index 1d6b894..374a77a 100644 --- a/changelog.json +++ b/changelog.json @@ -15,7 +15,7 @@ "QSO editor, QSL Info: the confirmation channels are listed paper QSL and LoTW first — the two that carry an ARRL award — then alphabetically, in both the picker and the status table.", "Band map: a chevron in the footer folds the colour legend away and brings it back — four lines of a short screen, remembered between sessions.", "Band map: ctrl+wheel no longer zooms it — that gesture is the window zoom everywhere else in OpsLog. The + and − buttons keep the zoom.", - "DX Cluster: the server pills drop the CONNECTED/DISCONNECTED word — the colour already said it — and clicking one now connects or disconnects that server on its own, without opening Settings. State, retries, address and last error moved into the tooltip." + "DX Cluster: a pill per configured server, connected or not. The CONNECTED/DISCONNECTED word is gone — the colour already said it — and clicking a pill connects or disconnects that server on its own, without opening Settings. State, retries, address and last error moved into the tooltip." ], "fr": [ "Changer de base de réglages n’affiche plus « OpsLog is already running » : la relance automatique attend désormais que l’instance qui se ferme libère son verrou au lieu de la prendre de vitesse.", @@ -30,7 +30,7 @@ "Éditeur de QSO, onglet QSL : les canaux de confirmation sont classés QSL papier puis LoTW — les deux qui comptent pour un diplôme ARRL — puis par ordre alphabétique, dans le sélecteur comme dans le tableau.", "Band map : un chevron dans le pied de page replie la légende des couleurs et la fait revenir — quatre lignes gagnées sur un petit écran, mémorisé d’une session à l’autre.", "Band map : ctrl+molette ne zoome plus la carte — ce geste est le zoom de la fenêtre partout ailleurs dans OpsLog. Les boutons + et − gardent le zoom.", - "DX Cluster : les pastilles de serveur perdent le mot CONNECTED/DISCONNECTED — la couleur le disait déjà — et cliquer sur l’une connecte ou déconnecte ce serveur seul, sans passer par les réglages. État, tentatives, adresse et dernière erreur passent dans l’infobulle." + "DX Cluster : une pastille par serveur configuré, connecté ou non. Le mot CONNECTED/DISCONNECTED disparaît — la couleur le disait déjà — et cliquer sur une pastille connecte ou déconnecte ce serveur seul, sans passer par les réglages. État, tentatives, adresse et dernière erreur passent dans l’infobulle." ] }, { diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index bd9d3ab..3b369da 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -8124,12 +8124,23 @@ export default function App() { > Disconnect all - {clusterServerStatuses.length === 0 && ( + {clusterServers.filter((x) => x.enabled).length === 0 && ( No active sessions — configure clusters in Settings → DX Cluster. )} - {clusterServerStatuses.map((s) => { + {clusterServers + .filter((x) => x.enabled) + .sort((a, b) => a.sort_order - b.sort_order) + .map((srv) => { + // A disconnected server has no session to report, so it has no + // entry in the status list at all — the pill stands in for it + // as "disconnected", which is exactly the state you click to + // undo. + const live = clusterServerStatuses.find((x) => x.server_id === srv.id); + const s: ServerStatus = live ?? { + server_id: srv.id, name: srv.name, host: '', port: 0, state: 'disconnected', + }; const isMaster = clusterServers .filter((x) => x.enabled) .sort((a, b) => a.sort_order - b.sort_order)[0]?.id === s.server_id; @@ -8159,7 +8170,7 @@ export default function App() { s.state === 'error' ? 'bg-danger-muted text-danger-muted-foreground border-danger-border' : 'bg-muted text-muted-foreground border-border', )} - title={`${s.name} — ${s.state.toUpperCase()}${s.retries ? ` #${s.retries}` : ''} · ${s.host}:${s.port}${s.error ? ' — ' + s.error : ''}\n${up || busy ? t('clu.pillDisconnect') : t('clu.pillConnect')}`} + title={`${s.name} — ${s.state.toUpperCase()}${s.retries ? ` #${s.retries}` : ''}${s.host ? ` · ${s.host}:${s.port}` : ''}${s.error ? ' — ' + s.error : ''}\n${up || busy ? t('clu.pillDisconnect') : t('clu.pillConnect')}`} > {isMaster && } {s.name}