fix: bulk edit refused the fields it offered (#3)
My mistake yesterday: the new confirmation columns went into uploadStatusCols — the QSL Manager's FILTER whitelist — instead of bulkEditableCols. The dialog listed QRZ.com received status and the ten dates, and the repository refused them at Apply, after the operator had selected 54 QSOs. Moved to the right map. And two fields have been broken this way since long before: State and County were offered under "Contacted station" (whose IOTA / POTA / SOTA / SIG siblings are all allowed) but were missing from the whitelist, so choosing one always failed. Added — they are exactly what an import loses and what a whole run shares. The real fix is the test. Two lists in two languages had to agree by hand and nothing checked it, so the failure only ever surfaced as an error message at the last click. The new tests read the ACTUAL field ids out of BulkEditModal.tsx and FilterBuilder.tsx and assert the repository accepts every one — a field added to the UI alone now fails the build instead of the operator.
This commit is contained in:
+52
-27
@@ -536,23 +536,11 @@ type UploadRow struct {
|
||||
// uploadStatusCols whitelists the per-service sent-status columns the QSL
|
||||
// Manager may filter on (guards the dynamic column name in the query).
|
||||
var uploadStatusCols = map[string]bool{
|
||||
"lotw_sent": true,
|
||||
"eqsl_sent": true,
|
||||
"qrzcom_qso_upload_status": true,
|
||||
"qrzcom_qso_download_status": true,
|
||||
"clublog_qso_upload_status": true,
|
||||
"hrdlog_qso_upload_status": true,
|
||||
// Confirmation dates (ADIF YYYYMMDD strings, so plain TEXT like the rest).
|
||||
"qsl_sent_date": true,
|
||||
"qsl_rcvd_date": true,
|
||||
"lotw_sent_date": true,
|
||||
"lotw_rcvd_date": true,
|
||||
"eqsl_sent_date": true,
|
||||
"eqsl_rcvd_date": true,
|
||||
"qrzcom_qso_upload_date": true,
|
||||
"qrzcom_qso_download_date": true,
|
||||
"clublog_qso_upload_date": true,
|
||||
"hrdlog_qso_upload_date": true,
|
||||
"lotw_sent": true,
|
||||
"eqsl_sent": true,
|
||||
"qrzcom_qso_upload_status": true,
|
||||
"clublog_qso_upload_status": true,
|
||||
"hrdlog_qso_upload_status": true,
|
||||
}
|
||||
|
||||
// ListForUpload returns QSOs whose per-service sent-status column equals
|
||||
@@ -755,16 +743,28 @@ func (r *Repo) MarkEQSLSent(ctx context.Context, id int64, date string) error {
|
||||
// which would be corrupted or meaningless if bulk-set to a single value.
|
||||
var bulkEditableCols = map[string]bool{
|
||||
// QSL / upload status
|
||||
"lotw_sent": true,
|
||||
"lotw_rcvd": true,
|
||||
"eqsl_sent": true,
|
||||
"eqsl_rcvd": true,
|
||||
"qsl_sent": true,
|
||||
"qsl_rcvd": true,
|
||||
"qsl_via": true,
|
||||
"qrzcom_qso_upload_status": true,
|
||||
"clublog_qso_upload_status": true,
|
||||
"hrdlog_qso_upload_status": true,
|
||||
"lotw_sent": true,
|
||||
"lotw_rcvd": true,
|
||||
"eqsl_sent": true,
|
||||
"eqsl_rcvd": true,
|
||||
"qsl_sent": true,
|
||||
"qsl_rcvd": true,
|
||||
"qsl_via": true,
|
||||
"qrzcom_qso_upload_status": true,
|
||||
"qrzcom_qso_download_status": true,
|
||||
"clublog_qso_upload_status": true,
|
||||
"hrdlog_qso_upload_status": true,
|
||||
// Confirmation DATES. ADIF YYYYMMDD strings, so plain TEXT like the rest.
|
||||
"qsl_sent_date": true,
|
||||
"qsl_rcvd_date": true,
|
||||
"lotw_sent_date": true,
|
||||
"lotw_rcvd_date": true,
|
||||
"eqsl_sent_date": true,
|
||||
"eqsl_rcvd_date": true,
|
||||
"qrzcom_qso_upload_date": true,
|
||||
"qrzcom_qso_download_date": true,
|
||||
"clublog_qso_upload_date": true,
|
||||
"hrdlog_qso_upload_date": true,
|
||||
// My station / operator
|
||||
"station_callsign": true,
|
||||
"operator": true,
|
||||
@@ -787,6 +787,14 @@ var bulkEditableCols = map[string]bool{
|
||||
"my_arrl_sect": true,
|
||||
"my_darc_dok": true,
|
||||
"my_vucc_grids": true,
|
||||
// Contacted station: the LOCATION fields only. State and county are the ones
|
||||
// an import loses and a whole run shares (a park activation, a county line
|
||||
// operation), and the dialog has always offered them — but they were missing
|
||||
// here, so choosing one failed at Apply. The rest of the contacted station
|
||||
// (callsign, name, RST…) stays deliberately out: bulk-setting those would
|
||||
// corrupt the log.
|
||||
"state": true,
|
||||
"cnty": true,
|
||||
// Contest — the exchange/label fields that are constant across a run.
|
||||
// (srx/stx serial numbers stay excluded: they are per-QSO.)
|
||||
"contest_id": true,
|
||||
@@ -2820,3 +2828,20 @@ func parseTimeLoose(s string) time.Time {
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// IsBulkEditable reports whether a column may be written by a bulk edit. Used by
|
||||
// the app layer's own test to prove that every field the UI offers is actually
|
||||
// accepted here — the two lists live in different packages and drifted apart
|
||||
// once already: the new confirmation columns were added to the QSL Manager's
|
||||
// filter whitelist instead of this one, so the UI offered fields that the
|
||||
// repository then refused with "field … is not bulk-editable".
|
||||
func IsBulkEditable(column string) bool { return bulkEditableCols[column] }
|
||||
|
||||
// IsFilterable reports whether a column may appear in a query filter. Same
|
||||
// reason as IsBulkEditable.
|
||||
func IsFilterable(column string) bool { return filterableColumns[column] }
|
||||
|
||||
// IsBulkEditableExtra / IsFilterableExtra cover the ADIF fields that have no
|
||||
// column of their own and live in extras_json.
|
||||
func IsBulkEditableExtra(field string) bool { _, ok := bulkEditableExtras[field]; return ok }
|
||||
func IsFilterableExtra(field string) bool { _, ok := filterableExtras[field]; return ok }
|
||||
|
||||
Reference in New Issue
Block a user