This commit is contained in:
2026-06-07 17:45:08 +02:00
parent 7d80d26bbd
commit 3dd9620cca
7 changed files with 133 additions and 77 deletions
+30 -56
View File
@@ -105,6 +105,14 @@ function fmtDateTimeUTC(s: any): string {
type ColEntry = ColDef<ClusterSpot> & { group: string; label: string; defaultVisible?: boolean };
// statusFor resolves the precomputed spot status (new / new-band / new-slot /
// worked-call) for an ag-Grid cell's row.
function statusFor(p: any): SpotStatusEntry | undefined {
return p?.context?.spotStatus?.[
spotStatusKey(p.data?.dx_call, p.data?.band ?? '', p.data?.comment ?? '', p.data?.freq_hz)
];
}
const COL_CATALOG: ColEntry[] = [
{
group: 'Spot', label: 'Time', colId: 'time',
@@ -117,28 +125,15 @@ const COL_CATALOG: ColEntry[] = [
group: 'Spot', label: 'Call', colId: 'call',
headerName: 'Call', field: 'dx_call' as any, width: 120,
defaultVisible: true,
cellRenderer: (p: any) => {
if (!p.value) return '';
const status: SpotStatusEntry | undefined = p.context?.spotStatus?.[
spotStatusKey(p.data.dx_call, p.data.band ?? '', p.data.comment ?? '', p.data.freq_hz)
];
const isNew = status?.status === 'new';
const workedCall = !!status?.worked_call;
const style: any = {
fontFamily: 'ui-monospace, monospace', fontWeight: 700, fontSize: 12,
};
if (isNew) {
// New DXCC entity — soft rose pill, no clashing border.
style.backgroundColor = '#ffe4e6';
style.color = '#be123c';
style.padding = '1px 7px';
style.borderRadius = 4;
} else if (workedCall) {
style.color = '#0369a1'; // already worked this exact call
} else {
style.color = '#b8410c'; // new call in a worked entity
}
return <span style={style} title={isNew ? `NEW DXCC: ${status?.country ?? ''}` : workedCall ? 'Already worked this call' : undefined}>{p.value}</span>;
cellClass: 'font-mono',
// New DXCC entity → fill the whole cell (no padded pill, so calls stay
// aligned with non-new rows). Text colour also flags worked-call vs new-call.
cellStyle: (p: any): any => (statusFor(p)?.status === 'new'
? { backgroundColor: '#ffe4e6', color: '#be123c', fontWeight: 700 }
: { color: statusFor(p)?.worked_call ? '#0369a1' : '#b8410c', fontWeight: 700 }),
tooltipValueGetter: (p: any) => {
const s = statusFor(p);
return s?.status === 'new' ? `NEW DXCC: ${s?.country ?? ''}` : s?.worked_call ? 'Already worked this call' : undefined;
},
},
{
@@ -159,46 +154,25 @@ const COL_CATALOG: ColEntry[] = [
group: 'Spot', label: 'Band', colId: 'band',
headerName: 'Band', field: 'band' as any, width: 75,
defaultVisible: true,
cellClass: 'flex items-center',
cellRenderer: (p: any) => {
const status: SpotStatusEntry | undefined = p.context?.spotStatus?.[
spotStatusKey(p.data.dx_call, p.data.band ?? '', p.data.comment ?? '', p.data.freq_hz)
];
const newBand = status?.status === 'new-band';
return p.value
? <span
style={{
fontFamily: 'ui-monospace, monospace', fontSize: 12,
fontWeight: newBand ? 700 : 400,
...(newBand ? { backgroundColor: '#fde68a', color: '#92400e', padding: '1px 7px', borderRadius: 4 } : {}),
}}
title={newBand ? 'NEW BAND for this entity' : undefined}
>{p.value}</span>
: '';
},
cellClass: 'font-mono',
// NEW BAND for this entity → fill the cell (keeps the band text aligned).
cellStyle: (p: any) => (statusFor(p)?.status === 'new-band'
? { backgroundColor: '#fde68a', color: '#92400e', fontWeight: 700 }
: undefined),
tooltipValueGetter: (p: any) => (statusFor(p)?.status === 'new-band' ? 'NEW BAND for this entity' : undefined),
},
{
group: 'Spot', label: 'Mode', colId: 'mode',
headerName: 'Mode', colSpan: undefined, width: 80,
defaultVisible: true,
cellClass: 'flex items-center',
cellClass: 'font-mono',
valueGetter: (p: any) => p.data ? inferSpotMode(p.data.comment ?? '', p.data.freq_hz) : '',
cellRenderer: (p: any) => {
const status: SpotStatusEntry | undefined = p.context?.spotStatus?.[
spotStatusKey(p.data.dx_call, p.data.band ?? '', p.data.comment ?? '', p.data.freq_hz)
];
const newSlot = status?.status === 'new-slot';
return p.value
? <span
style={{
fontFamily: 'ui-monospace, monospace', fontSize: 12,
fontWeight: newSlot ? 700 : 400,
...(newSlot ? { backgroundColor: '#fef08a', color: '#854d0e', padding: '1px 7px', borderRadius: 4 } : {}),
}}
title={newSlot ? 'NEW SLOT (mode not yet worked on this band)' : undefined}
>{p.value}</span>
: <span style={{ color: '#a8a29e', fontSize: 10 }}></span>;
},
// NEW SLOT (mode not yet worked on this band) → fill the cell.
cellStyle: (p: any) => (statusFor(p)?.status === 'new-slot'
? { backgroundColor: '#fef08a', color: '#854d0e', fontWeight: 700 }
: undefined),
cellRenderer: (p: any) => p.value ? p.value : <span style={{ color: '#a8a29e', fontSize: 10 }}></span>,
tooltipValueGetter: (p: any) => (statusFor(p)?.status === 'new-slot' ? 'NEW SLOT (mode not yet worked on this band)' : undefined),
},
{
group: 'Spot', label: 'Pfx', colId: 'pfx',