feat: added Cabrillo export

This commit is contained in:
2026-07-04 11:39:33 +02:00
parent 18438d7737
commit 5bbcaab71a
9 changed files with 357 additions and 2 deletions
@@ -52,6 +52,18 @@ export function AwardRefSelector({ dxcc, value, onChange, fieldValues, heightCla
const entries = value ? value.split(';').filter(Boolean) : [];
// When the reference set is cleared (a QSO was logged or the call was reset),
// also blank the picker's own state — the search box and the highlighted /
// selected reference — so the Awards tab starts fresh for the next contact.
useEffect(() => {
if (!value) {
setSelectedEntry(null);
setSelectedRef(null);
setQ('');
setSearchResults([]);
}
}, [value]);
useEffect(() => {
Promise.all([GetAwardDefs(), GetAwardReferenceMeta()])
.then(([d, m]) => {
+21 -1
View File
@@ -15,6 +15,8 @@ type Props = {
onBulkEdit?: (ids: number[]) => void;
onExportSelected?: (ids: number[]) => void;
onExportFiltered?: () => void;
onExportCabrilloSelected?: (ids: number[]) => void;
onExportCabrilloFiltered?: () => void;
onDelete?: (ids: number[]) => void;
};
@@ -32,7 +34,7 @@ const UPLOAD_TARGETS: { service: string; label: string }[] = [
// or picks a command. (We deliberately do NOT close on scroll/resize: the QSO
// list auto-refreshes and AG Grid fires internal scroll events on refresh,
// which used to dismiss the menu the instant it appeared.)
export function QSOContextMenu({ menu, onClose, onUpdateFromCty, onUpdateFromQRZ, onUpdateFromClublog, onSendTo, onSendRecording, onSendEQSL, onBulkEdit, onExportSelected, onExportFiltered, onDelete }: Props) {
export function QSOContextMenu({ menu, onClose, onUpdateFromCty, onUpdateFromQRZ, onUpdateFromClublog, onSendTo, onSendRecording, onSendEQSL, onBulkEdit, onExportSelected, onExportFiltered, onExportCabrilloSelected, onExportCabrilloFiltered, onDelete }: Props) {
useEffect(() => {
if (!menu) return;
const close = () => onClose();
@@ -142,6 +144,24 @@ export function QSOContextMenu({ menu, onClose, onUpdateFromCty, onUpdateFromQRZ
<span>Export filtered view to ADIF (no limit)</span>
</button>
)}
{onExportCabrilloSelected && (
<button
className="flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-accent/50"
onClick={() => { onExportCabrilloSelected(menu.ids); onClose(); }}
>
<FileDown className="size-4 text-amber-600" />
<span>Export selected to Cabrillo ({n})</span>
</button>
)}
{onExportCabrilloFiltered && (
<button
className="flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-accent/50"
onClick={() => { onExportCabrilloFiltered(); onClose(); }}
>
<FileDown className="size-4 text-amber-700" />
<span>Export filtered view to Cabrillo (no limit)</span>
</button>
)}
</>
)}
+5 -1
View File
@@ -59,6 +59,8 @@ type Props = {
onBulkEdit?: (ids: number[]) => void;
onExportSelected?: (ids: number[]) => void;
onExportFiltered?: () => void;
onExportCabrilloSelected?: (ids: number[]) => void;
onExportCabrilloFiltered?: () => void;
onDelete?: (ids: number[]) => void;
// One column per defined award; the cell shows the reference this QSO counts
// for (from row.award_refs[CODE], attached by the parent). Hidden by default.
@@ -228,7 +230,7 @@ export const GROUP_ORDER = [
'Contest', 'Propagation', 'My station', 'Misc',
];
export function RecentQSOsGrid({ rows, selectAllSignal, onRowDoubleClicked, onRowSelected, onUpdateFromCty, onUpdateFromQRZ, onUpdateFromClublog, onSendTo, onSendRecording, onSendEQSL, onBulkEdit, onExportSelected, onExportFiltered, onDelete, awardCols }: Props) {
export function RecentQSOsGrid({ rows, selectAllSignal, onRowDoubleClicked, onRowSelected, onUpdateFromCty, onUpdateFromQRZ, onUpdateFromClublog, onSendTo, onSendRecording, onSendEQSL, onBulkEdit, onExportSelected, onExportFiltered, onExportCabrilloSelected, onExportCabrilloFiltered, onDelete, awardCols }: Props) {
const gridRef = useRef<any>(null);
const [pickerOpen, setPickerOpen] = useState(false);
const [menu, setMenu] = useState<QSOMenuState>(null);
@@ -416,6 +418,8 @@ export function RecentQSOsGrid({ rows, selectAllSignal, onRowDoubleClicked, onRo
onBulkEdit={onBulkEdit}
onExportSelected={onExportSelected}
onExportFiltered={onExportFiltered}
onExportCabrilloSelected={onExportCabrilloSelected}
onExportCabrilloFiltered={onExportCabrilloFiltered}
onDelete={onDelete}
/>