feat(counties): right-click to re-derive a US county from the ULS database
The automatic pass fills a blank county only, and deliberately: a value the operator or QRZ supplied usually beats one derived from a ZIP code. That leaves no way at all to correct a county already stored — and the Connecticut planning regions are exactly that case. Every CT contact logged before that correction holds a county the state abolished in 2022, and filling blanks never reaches one of them. So the new entry OVERWRITES, because it is asked for by hand on a chosen set of rows precisely because the stored value is believed wrong. Only US entities are touched, only callsigns the database holds, and only when the answer actually differs — so re-running it on a mixed selection is safe and the count reported is the number of counties that really changed. Award refs are re-materialised: the county IS the reference for CQ USA-CA and the state for WAS. The entry appears only once the database has been downloaded, and appears without a restart when one finishes — an action that can only ever answer "no database" is not worth a line in a menu this long.
This commit is contained in:
+27
-7
@@ -11,7 +11,7 @@ import {
|
||||
SaveCabrilloFile, ExportCabrillo, ExportCabrilloFiltered, ExportCabrilloSelected,
|
||||
ContestDupe,
|
||||
GetQSO, UpdateQSO, DeleteQSO, DeleteQSOs, DeleteAllQSO,
|
||||
UpdateQSOsFromCty, UpdateQSOsFromQRZ, UpdateQSOsFromClublog, UploadQSOsManual, SendQSORecordingEmail,
|
||||
UpdateQSOsFromCty, UpdateQSOsFromQRZ, UpdateQSOsFromClublog, UpdateQSOsCountyFromULS, ULSStatus, UploadQSOsManual, SendQSORecordingEmail,
|
||||
LookupCallsign, GetStationSettings, GetListsSettings,
|
||||
GetStartupStatus, CheckForUpdate, DownloadAndApplyUpdate, GetLiveStations, GetWhatsNew, GetChangelog,
|
||||
SMTPConfigured, SendLogToDeveloper,
|
||||
@@ -3583,6 +3583,26 @@ export default function App() {
|
||||
catch (e: any) { setError(String(e?.message ?? e)); }
|
||||
finally { setBulkProgress(null); }
|
||||
}
|
||||
// Whether the offline US county database holds anything. It gates the
|
||||
// right-click entry below: an action that can only answer "no database" is
|
||||
// not worth a line in a menu this long. Re-read when a download finishes, so
|
||||
// the entry appears without a restart.
|
||||
const [ulsReady, setUlsReady] = useState(false);
|
||||
useEffect(() => {
|
||||
const read = () => ULSStatus().then((s: any) => setUlsReady((s?.count ?? 0) > 0)).catch(() => {});
|
||||
read();
|
||||
const off = EventsOn('uls:done', () => { read(); });
|
||||
return () => { off(); };
|
||||
}, []);
|
||||
|
||||
// Re-derive the county of the selected US contacts from the offline ULS
|
||||
// database, OVERWRITING what is stored. Offered only once that database has
|
||||
// been downloaded — see ulsReady above.
|
||||
async function bulkUpdateCountyFromULS(ids: number[]) {
|
||||
if (ids.length === 0) return;
|
||||
try { await afterBulkUpdate(await UpdateQSOsCountyFromULS(ids as any), t('qctx.fromUlsLabel')); }
|
||||
catch (e: any) { setError(String(e?.message ?? e)); }
|
||||
}
|
||||
async function bulkUpdateFromClublog(ids: number[]) {
|
||||
if (ids.length === 0) return;
|
||||
try { await afterBulkUpdate(await UpdateQSOsFromClublog(ids as any), 'from ClubLog'); }
|
||||
@@ -5252,7 +5272,7 @@ export default function App() {
|
||||
return (
|
||||
<div className="h-full w-full min-h-0 flex flex-col bg-card border border-border rounded-lg overflow-hidden">
|
||||
<WorkedBeforeGrid key={`wbg-${activeProfileId ?? 'x'}`} wb={wbWithAwards as any} myGrid={station.my_grid} awardCols={awardCols} busy={wbBusy} currentCall={callsign} onRowDoubleClicked={(q) => openEdit(q.id as number)}
|
||||
onUpdateFromCty={bulkUpdateFromCty} onUpdateFromQRZ={bulkUpdateFromQRZ} onUpdateFromClublog={bulkUpdateFromClublog}
|
||||
onUpdateFromCty={bulkUpdateFromCty} onUpdateFromQRZ={bulkUpdateFromQRZ} onUpdateFromClublog={bulkUpdateFromClublog} onUpdateCountyFromULS={ulsReady ? bulkUpdateCountyFromULS : undefined}
|
||||
onSendTo={bulkSendTo} onSendRecording={bulkSendRecording} onSendEQSL={(ids) => setEqslQsoId(ids[0] ?? null)}
|
||||
onBulkEdit={openBulkEdit} onExportSelected={exportSelectedADIF} onExportSelectedFields={exportSelectedFields}
|
||||
onExportCabrilloSelected={exportSelectedCabrillo} onDelete={(ids) => setDeletingIds(ids)} />
|
||||
@@ -5282,7 +5302,7 @@ export default function App() {
|
||||
<div className="h-full w-full min-h-0 flex flex-col rounded-lg overflow-hidden border border-border">
|
||||
<NetControlPanel onLogged={refresh} countries={countries} bands={bands} modes={modes}
|
||||
qsoMenuHandlers={{
|
||||
onUpdateFromCty: bulkUpdateFromCty, onUpdateFromQRZ: bulkUpdateFromQRZ, onUpdateFromClublog: bulkUpdateFromClublog,
|
||||
onUpdateFromCty: bulkUpdateFromCty, onUpdateFromQRZ: bulkUpdateFromQRZ, onUpdateFromClublog: bulkUpdateFromClublog, onUpdateCountyFromULS: ulsReady ? bulkUpdateCountyFromULS : undefined,
|
||||
onSendTo: bulkSendTo, onSendRecording: bulkSendRecording, onSendEQSL: (ids: number[]) => setEqslQsoId(ids[0] ?? null),
|
||||
onDelete: (ids: number[]) => setDeletingIds(ids),
|
||||
}} />
|
||||
@@ -5306,7 +5326,7 @@ export default function App() {
|
||||
onRowDoubleClicked={(q) => openEdit(q.id as number)}
|
||||
onUpdateFromCty={bulkUpdateFromCty}
|
||||
onUpdateFromQRZ={bulkUpdateFromQRZ}
|
||||
onUpdateFromClublog={bulkUpdateFromClublog}
|
||||
onUpdateFromClublog={bulkUpdateFromClublog} onUpdateCountyFromULS={ulsReady ? bulkUpdateCountyFromULS : undefined}
|
||||
onSendTo={bulkSendTo}
|
||||
onSendRecording={bulkSendRecording}
|
||||
onSendEQSL={(ids) => setEqslQsoId(ids[0] ?? null)}
|
||||
@@ -6622,7 +6642,7 @@ export default function App() {
|
||||
onRowDoubleClicked={(q) => openEdit(q.id as number)}
|
||||
onUpdateFromCty={bulkUpdateFromCty}
|
||||
onUpdateFromQRZ={bulkUpdateFromQRZ}
|
||||
onUpdateFromClublog={bulkUpdateFromClublog}
|
||||
onUpdateFromClublog={bulkUpdateFromClublog} onUpdateCountyFromULS={ulsReady ? bulkUpdateCountyFromULS : undefined}
|
||||
onSendTo={bulkSendTo}
|
||||
onSendRecording={bulkSendRecording}
|
||||
onSendEQSL={(ids) => setEqslQsoId(ids[0] ?? null)}
|
||||
@@ -6902,7 +6922,7 @@ export default function App() {
|
||||
|
||||
<TabsContent value="worked" className="mt-0 flex flex-col min-h-0 flex-1">
|
||||
<WorkedBeforeGrid key={`wbg-${activeProfileId ?? 'x'}`} wb={wbWithAwards as any} myGrid={station.my_grid} awardCols={awardCols} busy={wbBusy} currentCall={callsign} onRowDoubleClicked={(q) => openEdit(q.id as number)}
|
||||
onUpdateFromCty={bulkUpdateFromCty} onUpdateFromQRZ={bulkUpdateFromQRZ} onUpdateFromClublog={bulkUpdateFromClublog} onSendTo={bulkSendTo} onSendRecording={bulkSendRecording}
|
||||
onUpdateFromCty={bulkUpdateFromCty} onUpdateFromQRZ={bulkUpdateFromQRZ} onUpdateFromClublog={bulkUpdateFromClublog} onUpdateCountyFromULS={ulsReady ? bulkUpdateCountyFromULS : undefined} onSendTo={bulkSendTo} onSendRecording={bulkSendRecording}
|
||||
onSendEQSL={(ids) => setEqslQsoId(ids[0] ?? null)}
|
||||
onBulkEdit={openBulkEdit} onExportSelected={exportSelectedADIF} onExportSelectedFields={exportSelectedFields}
|
||||
onExportCabrilloSelected={exportSelectedCabrillo} onDelete={(ids) => setDeletingIds(ids)} />
|
||||
@@ -6999,7 +7019,7 @@ export default function App() {
|
||||
<TabsContent value="net" className="mt-0 flex flex-col min-h-0 flex-1">
|
||||
<NetControlPanel onLogged={refresh} countries={countries} bands={bands} modes={modes}
|
||||
qsoMenuHandlers={{
|
||||
onUpdateFromCty: bulkUpdateFromCty, onUpdateFromQRZ: bulkUpdateFromQRZ, onUpdateFromClublog: bulkUpdateFromClublog,
|
||||
onUpdateFromCty: bulkUpdateFromCty, onUpdateFromQRZ: bulkUpdateFromQRZ, onUpdateFromClublog: bulkUpdateFromClublog, onUpdateCountyFromULS: ulsReady ? bulkUpdateCountyFromULS : undefined,
|
||||
onSendTo: bulkSendTo, onSendRecording: bulkSendRecording, onSendEQSL: (ids: number[]) => setEqslQsoId(ids[0] ?? null),
|
||||
onDelete: (ids: number[]) => setDeletingIds(ids),
|
||||
}} />
|
||||
|
||||
Reference in New Issue
Block a user