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}