feat(appearance): four QSL categories, each scoped to chosen channels
Replaces the four fixed rules with the model Logger32 uses and the operator asked for: Worked / Confirmed / QSL sent / To be sent, and inside each, which channels count — paper QSL, LoTW, eQSL, QRZ.com. No ticks means every channel, because a rule the operator has not narrowed must not quietly become a rule about nothing. "To be sent" is FIRST in the order, and that is the substantive decision here. A contact can be confirmed on LoTW and still owe a paper card; the colour an operator scans for is the one meaning "something is still owed". Placed after "confirmed" that row goes green and the card never gets printed. "Worked" is the catch-all — nothing sent, nothing requested, nothing back — and is off by default, since turning it on paints every remaining row. R and Q both count as owed: ADIF says requested and queued, and both mean the card has not gone out.
This commit is contained in:
+47
-10
@@ -6,8 +6,8 @@ import "testing"
|
||||
// that is not plainly a hex colour has to be refused rather than passed on.
|
||||
func TestRowColorsRefuseAnythingButHex(t *testing.T) {
|
||||
in := RowColorSettings{Enabled: true, Rules: []RowColorRule{
|
||||
{ID: "confirmed_lotw", Color: "#123abc", Enabled: true},
|
||||
{ID: "sent_waiting", Color: "red; background:url(x)", Enabled: true},
|
||||
{ID: "confirmed", Color: "#123abc", Enabled: true},
|
||||
{ID: "sent", Color: "red; background:url(x)", Enabled: true},
|
||||
{ID: "to_send", Color: "", Enabled: true},
|
||||
}}
|
||||
got := normRowColors(in)
|
||||
@@ -16,11 +16,11 @@ func TestRowColorsRefuseAnythingButHex(t *testing.T) {
|
||||
for _, r := range got.Rules {
|
||||
byID[r.ID] = r
|
||||
}
|
||||
if byID["confirmed_lotw"].Color != "#123abc" {
|
||||
t.Errorf("a valid colour was rewritten: %q", byID["confirmed_lotw"].Color)
|
||||
if byID["confirmed"].Color != "#123abc" {
|
||||
t.Errorf("a valid colour was rewritten: %q", byID["confirmed"].Color)
|
||||
}
|
||||
if byID["sent_waiting"].Color != rowColorDefaults["sent_waiting"] {
|
||||
t.Errorf("an injection attempt survived: %q", byID["sent_waiting"].Color)
|
||||
if byID["sent"].Color != rowColorDefaults["sent"] {
|
||||
t.Errorf("an injection attempt survived: %q", byID["sent"].Color)
|
||||
}
|
||||
if byID["to_send"].Color != rowColorDefaults["to_send"] {
|
||||
t.Errorf("an empty colour was kept: %q", byID["to_send"].Color)
|
||||
@@ -34,7 +34,7 @@ func TestRowColorsKeepPriorityOrder(t *testing.T) {
|
||||
// Saved in a jumbled order, as a hand-edited settings row could be.
|
||||
got := normRowColors(RowColorSettings{Rules: []RowColorRule{
|
||||
{ID: "to_send", Color: "#111111"},
|
||||
{ID: "confirmed_lotw", Color: "#222222"},
|
||||
{ID: "confirmed", Color: "#222222"},
|
||||
}})
|
||||
if len(got.Rules) != len(rowColorOrder) {
|
||||
t.Fatalf("got %d rules, want every one present", len(got.Rules))
|
||||
@@ -44,9 +44,13 @@ func TestRowColorsKeepPriorityOrder(t *testing.T) {
|
||||
t.Errorf("rule %d is %q, want %q", i, got.Rules[i].ID, id)
|
||||
}
|
||||
}
|
||||
// The saved colours survived the reordering.
|
||||
if got.Rules[0].Color != "#222222" {
|
||||
t.Errorf("confirmed_lotw lost its colour: %q", got.Rules[0].Color)
|
||||
// The saved colours survived the reordering: each stayed with its own rule.
|
||||
byID := map[string]string{}
|
||||
for _, r := range got.Rules {
|
||||
byID[r.ID] = r.Color
|
||||
}
|
||||
if byID["to_send"] != "#111111" || byID["confirmed"] != "#222222" {
|
||||
t.Errorf("colours moved between rules: %v", byID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,3 +79,36 @@ func TestRowColorsNormaliseStyleAndIntensity(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Channels are normalised to the canonical order, and anything unknown is
|
||||
// dropped. Empty stays empty, because empty means "every channel" — a rule the
|
||||
// operator has not narrowed must not silently become a rule about nothing.
|
||||
func TestRowColorChannelsNormalise(t *testing.T) {
|
||||
got := normRowColors(RowColorSettings{Rules: []RowColorRule{
|
||||
{ID: "confirmed", Color: "#111111", Channels: []string{"LOTW", "pigeon", "qsl", "lotw"}},
|
||||
{ID: "sent", Color: "#222222"},
|
||||
}})
|
||||
byID := map[string][]string{}
|
||||
for _, r := range got.Rules {
|
||||
byID[r.ID] = r.Channels
|
||||
}
|
||||
if len(byID["confirmed"]) != 2 || byID["confirmed"][0] != "qsl" || byID["confirmed"][1] != "lotw" {
|
||||
t.Errorf("confirmed channels = %v, want [qsl lotw] — canonical order, deduped, unknown dropped", byID["confirmed"])
|
||||
}
|
||||
if len(byID["sent"]) != 0 {
|
||||
t.Errorf("sent channels = %v, want empty (meaning every channel)", byID["sent"])
|
||||
}
|
||||
}
|
||||
|
||||
// The order IS the priority, and "to send" leads. A contact confirmed on LoTW
|
||||
// that still owes a paper card must read as owing the card — put after
|
||||
// "confirmed" it would go green and never be printed.
|
||||
func TestToSendOutranksConfirmed(t *testing.T) {
|
||||
got := normRowColors(RowColorSettings{})
|
||||
if got.Rules[0].ID != "to_send" {
|
||||
t.Errorf("first rule is %q, want to_send", got.Rules[0].ID)
|
||||
}
|
||||
if got.Rules[len(got.Rules)-1].ID != "worked" {
|
||||
t.Errorf("last rule is %q, want worked as the catch-all", got.Rules[len(got.Rules)-1].ID)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user