From a40ea0d62d0fb97a01adf7f02a7cd99e6591b6b4 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Thu, 9 Apr 2026 14:02:19 -0500 Subject: [PATCH] Show submitter callsign on the contacts index When a contact is linked to a logged-in user account, display that user's callsign in the Submitted column instead of a generic "Yes". Anonymous submissions still show "Yes"; scraped contacts show an em dash. --- lib/microwaveprop/radio.ex | 1 + lib/microwaveprop/radio/contact.ex | 4 ++- .../live/contact_live/index.ex | 8 +++-- .../live/contact_live_test.exs | 31 ++++++++++++++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/lib/microwaveprop/radio.ex b/lib/microwaveprop/radio.ex index 493c1d75..b7ecdb7f 100644 --- a/lib/microwaveprop/radio.ex +++ b/lib/microwaveprop/radio.ex @@ -28,6 +28,7 @@ defmodule Microwaveprop.Radio do |> limit(^@per_page) |> offset(^offset) |> Repo.all() + |> Repo.preload(:user) %{ entries: entries, diff --git a/lib/microwaveprop/radio/contact.ex b/lib/microwaveprop/radio/contact.ex index 0ff612e7..22dc9df9 100644 --- a/lib/microwaveprop/radio/contact.ex +++ b/lib/microwaveprop/radio/contact.ex @@ -4,6 +4,7 @@ defmodule Microwaveprop.Radio.Contact do import Ecto.Changeset + alias Microwaveprop.Accounts.User alias Microwaveprop.Radio.Maidenhead @primary_key {:id, :binary_id, autogenerate: true} @@ -39,9 +40,10 @@ defmodule Microwaveprop.Radio.Contact do field :user_submitted, :boolean, default: false field :submitter_email, :string - field :user_id, :binary_id field :flagged_invalid, :boolean, default: false + belongs_to :user, User + timestamps(type: :utc_datetime) end diff --git a/lib/microwaveprop_web/live/contact_live/index.ex b/lib/microwaveprop_web/live/contact_live/index.ex index f877cb11..fb948c90 100644 --- a/lib/microwaveprop_web/live/contact_live/index.ex +++ b/lib/microwaveprop_web/live/contact_live/index.ex @@ -80,6 +80,10 @@ defmodule MicrowavepropWeb.ContactLive.Index do ] @done_statuses [:complete, :unavailable] + defp submitted_cell(%{user: %{callsign: callsign}}) when is_binary(callsign), do: callsign + defp submitted_cell(%{user_submitted: true}), do: "Yes" + defp submitted_cell(_), do: "—" + defp enrichment_badge(contact) do details = Enum.map(@enrichment_fields, fn {field, name} -> @@ -183,7 +187,7 @@ defmodule MicrowavepropWeb.ContactLive.Index do {primary.band} {primary.mode} {primary.distance_km} - {if primary.user_submitted, do: "Yes", else: "—"} + {submitted_cell(primary)} {enrichment_badge(primary)} {if primary.flagged_invalid, do: "🚩"} {Calendar.strftime(primary.qso_timestamp, "%Y-%m-%d %H:%M")} @@ -202,7 +206,7 @@ defmodule MicrowavepropWeb.ContactLive.Index do {recip.band} {recip.mode} {recip.distance_km} - {if recip.user_submitted, do: "Yes", else: "—"} + {submitted_cell(recip)} {enrichment_badge(recip)} {if recip.flagged_invalid, do: "🚩"} {Calendar.strftime(recip.qso_timestamp, "%Y-%m-%d %H:%M")} diff --git a/test/microwaveprop_web/live/contact_live_test.exs b/test/microwaveprop_web/live/contact_live_test.exs index ca4b442f..fa33e540 100644 --- a/test/microwaveprop_web/live/contact_live_test.exs +++ b/test/microwaveprop_web/live/contact_live_test.exs @@ -1,6 +1,7 @@ defmodule MicrowavepropWeb.ContactLiveTest do use MicrowavepropWeb.ConnCase, async: true + import Microwaveprop.AccountsFixtures import Phoenix.LiveViewTest alias Microwaveprop.Radio.Contact @@ -36,9 +37,12 @@ defmodule MicrowavepropWeb.ContactLiveTest do distance_km: Decimal.new("295") } + {changeset_attrs, direct_attrs} = Map.split(Map.merge(default, attrs), [:user_submitted]) + {:ok, contact} = %Contact{} - |> Contact.changeset(Map.merge(default, attrs)) + |> Contact.changeset(direct_attrs) + |> Ecto.Changeset.change(changeset_attrs) |> Repo.insert() contact @@ -112,6 +116,31 @@ defmodule MicrowavepropWeb.ContactLiveTest do {:ok, _lv, html2} = live(conn, ~p"/contacts?page=2") assert html2 =~ "Page 2 of 2" end + + test "Submitted column shows the user's callsign when linked to an account", %{conn: conn} do + user = user_fixture(%{callsign: "W5UNIQ"}) + create_contact(%{station1: "K5ONE", user_submitted: true, user_id: user.id}) + + {:ok, _lv, html} = live(conn, ~p"/contacts?search=K5ONE") + assert html =~ "W5UNIQ" + end + + test "Submitted column shows 'Yes' when user_submitted but no user linked", %{conn: conn} do + create_contact(%{station1: "K5ANON", user_submitted: true, user_id: nil}) + + {:ok, _lv, html} = live(conn, ~p"/contacts?search=K5ANON") + # Locate the row containing our station and assert "Yes" appears in it + [row] = Regex.run(~r/]*>(?:(?!<\/tr>).)*K5ANON(?:(?!<\/tr>).)*<\/tr>/s, html) || [""] + assert row =~ ">Yes<" + end + + test "Submitted column shows dash for scraped contacts", %{conn: conn} do + create_contact(%{station1: "K5SCRAPE", user_submitted: false}) + + {:ok, _lv, html} = live(conn, ~p"/contacts?search=K5SCRAPE") + [row] = Regex.run(~r/]*>(?:(?!<\/tr>).)*K5SCRAPE(?:(?!<\/tr>).)*<\/tr>/s, html) || [""] + refute row =~ ">Yes<" + end end describe "Show" do