feat(watchlist): the DXHunter watchlist as an OpsLog tab
The concept, transplanted: a list of callsigns or prefixes being hunted, matched against the live spot stream, one card per entry with the spots underneath and the two questions that matter answered on every line — is this slot still needed, and what is it worth (the cluster's own NEW badges, read from the same status index). The file is DXHunter's own watchlist.json, field for field, ClubLog block included though phase 2 will fill it — a file that round-trips unchanged is the whole of 'same format', and a test pins it with a real DXHunter entry. Global (dataDir), not per profile. CONTEST is per entry, not the global mode DXHunter has: a contest entry is judged against the current UTC day — the boundary lives in the query's date bound, so midnight needs no timer and resets nothing. Normal entries read the same in-memory worked index the alerts use. Prefix matching is why RI0SP catches RI0SP/MM, pinned by test. Notify goes through the existing alert:fired event — the frontend already toasts and sounds it — throttled to one alert per entry per two minutes, because a DXpedition lights every skimmer on the planet. Tab wired like NET Control: opt-in from Tools, persisted, closable. Single click fills the callsign, double click works the spot — the cluster's own gesture, kept.
This commit is contained in:
Vendored
+13
@@ -30,6 +30,7 @@ import {lotwusers} from '../models';
|
||||
import {lookup} from '../models';
|
||||
import {netctl} from '../models';
|
||||
import {scp} from '../models';
|
||||
import {watchlist} from '../models';
|
||||
|
||||
export function ACOMSetOperate(arg1:boolean):Promise<void>;
|
||||
|
||||
@@ -1357,6 +1358,18 @@ export function UploadCallsign(arg1:string):Promise<string>;
|
||||
|
||||
export function UploadQSOsManual(arg1:string,arg2:Array<number>):Promise<void>;
|
||||
|
||||
export function WatchlistAdd(arg1:string,arg2:boolean):Promise<void>;
|
||||
|
||||
export function WatchlistEntries():Promise<Array<watchlist.Entry>>;
|
||||
|
||||
export function WatchlistRemove(arg1:string):Promise<void>;
|
||||
|
||||
export function WatchlistSetContest(arg1:string,arg2:boolean):Promise<void>;
|
||||
|
||||
export function WatchlistSetNotify(arg1:string,arg2:boolean):Promise<void>;
|
||||
|
||||
export function WatchlistWorkedSlots(arg1:Array<main.WatchlistSlotQuery>):Promise<Array<boolean>>;
|
||||
|
||||
export function WebPublishColumns():Promise<Array<Record<string, string>>>;
|
||||
|
||||
export function WinkeyerBackspace():Promise<void>;
|
||||
|
||||
@@ -2654,6 +2654,30 @@ export function UploadQSOsManual(arg1, arg2) {
|
||||
return window['go']['main']['App']['UploadQSOsManual'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function WatchlistAdd(arg1, arg2) {
|
||||
return window['go']['main']['App']['WatchlistAdd'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function WatchlistEntries() {
|
||||
return window['go']['main']['App']['WatchlistEntries']();
|
||||
}
|
||||
|
||||
export function WatchlistRemove(arg1) {
|
||||
return window['go']['main']['App']['WatchlistRemove'](arg1);
|
||||
}
|
||||
|
||||
export function WatchlistSetContest(arg1, arg2) {
|
||||
return window['go']['main']['App']['WatchlistSetContest'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function WatchlistSetNotify(arg1, arg2) {
|
||||
return window['go']['main']['App']['WatchlistSetNotify'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function WatchlistWorkedSlots(arg1) {
|
||||
return window['go']['main']['App']['WatchlistWorkedSlots'](arg1);
|
||||
}
|
||||
|
||||
export function WebPublishColumns() {
|
||||
return window['go']['main']['App']['WebPublishColumns']();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user