From 6ec31b61ced2c1486ff6d3b0a4c9c977d44fdb8f Mon Sep 17 00:00:00 2001 From: rouggy Date: Thu, 2 Jul 2026 11:41:53 +0200 Subject: [PATCH] fix: bug while creating a new profile --- app.go | 3 ++- frontend/src/components/SettingsModal.tsx | 6 ++++-- internal/extsvc/qrz.go | 6 ++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app.go b/app.go index 10c8f68..4bafcfb 100644 --- a/app.go +++ b/app.go @@ -608,7 +608,8 @@ func (a *App) startup(ctx context.Context) { // Route CAT/OmniRig debug lines into the unified app log (they used to go // to a separate cat.log in the old HamLog folder, which users couldn't find). cat.LogSink = applog.Printf - audio.LogSink = applog.Printf // capture audio-goroutine panics in the app log + audio.LogSink = applog.Printf // capture audio-goroutine panics in the app log + extsvc.LogSink = applog.Printf // log raw QRZ (and other) service responses for diagnosis applog.Printf("startup: data dir = %s", dataDir) // The local SQLite file ALWAYS holds per-operator configuration — settings, // station profiles, rigs/antennas, cluster nodes, UDP, QSL templates, award diff --git a/frontend/src/components/SettingsModal.tsx b/frontend/src/components/SettingsModal.tsx index e0fe10f..724adc0 100644 --- a/frontend/src/components/SettingsModal.tsx +++ b/frontend/src/components/SettingsModal.tsx @@ -133,8 +133,10 @@ const emptyProfile = (): Profile => ({ is_active: false, sort_order: 0, db: { backend: '', host: '', port: 3306, user: '', password: '', database: '' }, - created_at: '' as any, - updated_at: '' as any, + // Server-managed timestamps — send null (NOT "") so Go's time.Time unmarshal + // leaves the zero value instead of failing to parse an empty RFC3339 string. + created_at: null as any, + updated_at: null as any, }); interface Props { diff --git a/internal/extsvc/qrz.go b/internal/extsvc/qrz.go index b375b41..3f1b754 100644 --- a/internal/extsvc/qrz.go +++ b/internal/extsvc/qrz.go @@ -16,6 +16,10 @@ import ( // subscription used elsewhere for callsign data — they're different keys. const qrzAPIURL = "https://logbook.qrz.com/api" +// LogSink receives diagnostics such as raw QRZ responses. Set to applog.Printf +// at startup; defaults to a no-op so the package is usable without wiring. +var LogSink = func(string, ...any) {} + // UploadQRZ pushes one ADIF record to the QRZ.com logbook identified by // apiKey. It returns OK when the QSO is inserted or already present // (QRZ reports a duplicate as a FAIL with a "duplicate" reason, which we @@ -67,6 +71,7 @@ func UploadQRZ(ctx context.Context, client *http.Client, apiKey, adifRecord stri if resp.StatusCode != http.StatusOK { return UploadResult{}, fmt.Errorf("qrz: http %d: %s", resp.StatusCode, strings.TrimSpace(string(body))) } + LogSink("qrz: INSERT raw response: %s", strings.TrimSpace(string(body))) return parseQRZResponse(string(body)) } @@ -171,6 +176,7 @@ func TestQRZ(ctx context.Context, client *http.Client, apiKey string) (string, e } defer resp.Body.Close() body, _ := io.ReadAll(io.LimitReader(resp.Body, 64*1024)) + LogSink("qrz: STATUS raw response: %s", strings.TrimSpace(string(body))) vals, err := url.ParseQuery(strings.TrimSpace(string(body))) if err != nil { return "", fmt.Errorf("qrz: bad response: %w", err)