feat(cluster): show the grid, and flag a new one
Finishes the half of this that was already computing on the backend and reaching nobody. A Grid column in the Geo group, NEW GRID as a badge in Status, a filled cell in the marker's own colour, and a filter chip. new_grid joins lib/spotMarkers rather than getting colours of its own, so the badge, the cell fill and the chip cannot drift apart - and the per-marker colour setting will drive it with the rest from one table. Magenta: the last hue in the categorical set not already spoken for, and one that does not read as a status, because a new square is never urgent the way a new entity is. The band map leaves it to the cluster, as it already leaves the prefix. The pill is 22 px tall and its accent strip stops being readable past three segments. A row carrying a new grid is no longer "dull", or the dimming would grey out the one thing worth looking at. The column is off by default, like the other Geo columns: it is only ever filled for stations this receiver decoded over the UDP link, so for an operator who does not run digital it would be a permanently empty column.
This commit is contained in:
@@ -193,7 +193,7 @@ function statusColor(s: SpotStatusEntry | undefined): string | null {
|
||||
function isDull(s: SpotStatusEntry | undefined): boolean {
|
||||
if (!s || !s.status) return false;
|
||||
if (s.status === 'new' || s.status === 'new-band' || s.status === 'new-mode' || s.status === 'new-slot' || s.status === 'new-call') return false;
|
||||
return !(s.worked_call || s.new_pota || s.new_county || s.new_pfx);
|
||||
return !(s.worked_call || s.new_pota || s.new_county || s.new_pfx || s.new_grid);
|
||||
}
|
||||
|
||||
const makeColCatalog = (t: TFn): ColEntry[] => [
|
||||
@@ -266,6 +266,7 @@ const makeColCatalog = (t: TFn): ColEntry[] => [
|
||||
if (s?.new_county) parts.push(t('clg2.newCounty'));
|
||||
if (s?.new_pota) parts.push(t('clg2.newPota'));
|
||||
if (s?.new_pfx) parts.push(t('clg2.newPfx'));
|
||||
if (s?.new_grid) parts.push(t('clg2.newGrid'));
|
||||
return parts.join(' ');
|
||||
},
|
||||
cellRenderer: (p: any) => {
|
||||
@@ -286,6 +287,7 @@ const makeColCatalog = (t: TFn): ColEntry[] => [
|
||||
if (s?.new_county) parts.push({ text: t('clg2.newCounty'), color: markerColour('new_county') });
|
||||
if (s?.new_pota) parts.push({ text: t('clg2.newPota'), color: markerColour('new_pota') });
|
||||
if (s?.new_pfx) parts.push({ text: t('clg2.newPfx'), color: markerColour('new_pfx') });
|
||||
if (s?.new_grid) parts.push({ text: t('clg2.newGrid'), color: markerColour('new_grid') });
|
||||
if (parts.length === 0) return <span style={{ color: 'var(--muted-foreground)', fontSize: 10 }}>—</span>;
|
||||
return (
|
||||
<span style={{ whiteSpace: 'nowrap' }}>
|
||||
@@ -362,6 +364,18 @@ const makeColCatalog = (t: TFn): ColEntry[] => [
|
||||
: { color: 'var(--muted-foreground)' }) as any,
|
||||
tooltipValueGetter: (p: any) => (statusFor(p)?.new_pfx ? t('clg2.tipNewPfx') : undefined),
|
||||
},
|
||||
{
|
||||
group: 'Geo', label: t('clg2.c.grid'), colId: 'grid',
|
||||
headerName: t('clg2.c.grid'), width: 70, cellClass: 'font-mono',
|
||||
// Not on the spot: the square a station announced in a CQ that THIS receiver
|
||||
// decoded over the WSJT-X link, so it is filled for the digital watering
|
||||
// hole being monitored and empty everywhere else. A cluster line carries the
|
||||
// spotter's grid at best, never the DX's.
|
||||
valueGetter: (p: any) => statusFor(p)?.grid ?? '',
|
||||
cellStyle: (p: any) => (statusFor(p)?.new_grid ? fillStyle(markerColour('new_grid')) : null) as any,
|
||||
cellRenderer: (p: any) => cellText(p.value, null),
|
||||
tooltipValueGetter: (p: any) => (statusFor(p)?.new_grid ? t('clg2.tipNewGrid') : undefined),
|
||||
},
|
||||
{
|
||||
group: 'Geo', label: t('clg2.c.county'), colId: 'county',
|
||||
headerName: t('clg2.c.county'), width: 130, cellClass: 'font-mono',
|
||||
|
||||
Reference in New Issue
Block a user