feat: awards folder in the data folder, anybody can create its own awards.

This commit is contained in:
2026-07-13 18:03:06 +02:00
parent c170d6091e
commit 656e238a59
8 changed files with 950 additions and 31 deletions
+9 -19
View File
@@ -1,5 +1,5 @@
import { useEffect, useMemo, useState } from 'react';
import { Plus, Trash2, RotateCcw, Save, Download, Upload, Loader2, Search, Share2 } from 'lucide-react';
import { Plus, Trash2, RotateCcw, Save, Download, Upload, Loader2, Search, FolderOpen } from 'lucide-react';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
@@ -18,7 +18,7 @@ import {
ImportAwardReferencesText, GetAwardPresets, ApplyAwardPreset,
ListCountries, DXCCForCountry, DXCCName,
PopulateBuiltinReferences, HasBuiltinReferences,
ExportAwards, ImportAwards, ExportAward, InspectAwardImport, ApplyAwardImport, GetCatalogCodes,
ExportAwards, ImportAwards, InspectAwardImport, ApplyAwardImport, GetCatalogCodes, OpenAwardsFolder,
} from '../../wailsjs/go/main/App';
// Above this many references the editor stops loading the whole list and
@@ -238,18 +238,6 @@ export function AwardEditor({ open, onClose, onSaved }: Props) {
if (p) setErr(t('awed.exportedTo', { path: p }));
} catch (e: any) { setErr(String(e?.message ?? e)); }
}
// Export ONE award — the unit you actually share. It carries its definition AND
// its references AND their regexes (read from the database), so the person you
// send it to gets a working award, not an empty shell.
async function exportOne() {
if (!cur?.code) return;
setErr('');
try {
const p = await ExportAward(cur.code);
if (p) setErr(t('awed.exportedTo', { path: p }));
} catch (e: any) { setErr(String(e?.message ?? e)); }
}
// Import: LOOK FIRST, then ask.
//
// This used to merge by code with "imported wins", silently — import a WAPC
@@ -526,17 +514,19 @@ export function AwardEditor({ open, onClose, onSaved }: Props) {
<DialogFooter className="px-5 py-3 border-t !flex-row">
<Button variant="ghost" onClick={reset}><RotateCcw className="size-3.5 mr-1" /> {t('awed.resetDefaults')}</Button>
{/* Share ONE award — the unit you actually send someone. The bundle
below is a backup, which is a different job. */}
<Button variant="outline" onClick={exportOne} disabled={!cur?.code} title={t('awed.exportOneTitle')}>
<Share2 className="size-3.5 mr-1" /> {t('awed.exportOne', { code: cur?.code ?? '' })}
</Button>
<Button variant="outline" onClick={exportAwards} title={t('awed.exportTitle')}>
<Download className="size-3.5 mr-1" /> {t('awed.export')}
</Button>
<Button variant="outline" onClick={importAwards} title={t('awed.importTitle')}>
<Upload className="size-3.5 mr-1" /> {t('awed.import')}
</Button>
{/* The drop folder: put an award JSON here and it installs on restart —
no rebuild, nobody to ask. Opening it beats printing a path someone
then has to retype. */}
<Button variant="ghost" onClick={() => OpenAwardsFolder().catch((e: any) => setErr(String(e?.message ?? e)))}
title={t('awed.awardsFolderTip')}>
<FolderOpen className="size-3.5 mr-1" /> {t('awed.awardsFolder')}
</Button>
<div className="flex-1" />
<Button variant="outline" onClick={onClose}>{t('awed.cancel')}</Button>
<Button onClick={save}><Save className="size-3.5 mr-1" /> {t('awed.save')}</Button>