admin: show the nickname on the contact detail page
A labeled grid row leading the channels, rather than a second name in
the header — the grid is where attributes live, and the header stays
the name and the avatar alone.
Assisted-by: GLM-5.3 via pi
diff --git a/lib/pro_tacts/admin/contacts_show.rb b/lib/pro_tacts/admin/contacts_show.rb
index dfa1ae5..540a325 100644
--- a/lib/pro_tacts/admin/contacts_show.rb
+++ b/lib/pro_tacts/admin/contacts_show.rb
@@ -50,13 +50,17 @@ module ProTacts
#: () -> bool
def has_data?
- @contact.phones.any? || @contact.emails.any? || @contact.addresses.any? ||
+ !@contact.nickname.nil? ||
+ @contact.phones.any? || @contact.emails.any? || @contact.addresses.any? ||
!@birthday.nil? || !@contact.notes.nil?
end
# A missing TYPE parameter still gets a key: the fallback names
# the kind of value, so no row renders unlabeled in the grid.
def rows
+ # The nickname leads the grid: closest to the name the header
+ # already shows, ahead of the channels that reach the person.
+ row("nickname", @contact.nickname) if @contact.nickname
@contact.phones.each { |phone| row(phone.type || "phone", phone.value) }
@contact.emails.each { |email| row(email.type || "email", email.value) }
@contact.addresses.each { |address| row(address.type || "address", address_lines(address)) }
diff --git a/test/pro_tacts/admin/test_contacts_pages.rb b/test/pro_tacts/admin/test_contacts_pages.rb
index e6b423b..a08e0ea 100644
--- a/test/pro_tacts/admin/test_contacts_pages.rb
+++ b/test/pro_tacts/admin/test_contacts_pages.rb
@@ -250,6 +250,7 @@ class AdminContactsPagesTest < Minitest::Test
get "/contacts/bare"
assert_equal 200, last_response.status
+ refute_includes last_response.body, '<dt class="type-label">nickname</dt>'
refute_includes last_response.body, '<dt class="type-label">notes</dt>'
refute_includes last_response.body, '<dt class="type-label">birthday</dt>'
end
@@ -282,6 +283,23 @@ class AdminContactsPagesTest < Minitest::Test
end
end
+ # The nickname is an attribute like the others here — a labeled
+ # grid row, leading the channels — not a second name in the header,
+ # which stays the name and the avatar alone.
+ def test_show_renders_the_nickname_as_a_row
+ red = ADA.sub("FN:Ada Lovelace", "FN:Sarah\r\nNICKNAME:Red").sub("UID:ada", "UID:red")
+
+ with_contacts({"red" => red}) do
+ get "/contacts/red"
+
+ assert_includes last_response.body, '<dt class="type-label">nickname</dt>'
+ assert_includes last_response.body, "Red"
+ # The row leads the grid, ahead of the first phone.
+ body = last_response.body
+ assert body.index('">nickname</dt>') < body.index('">mobile</dt>')
+ end
+ end
+
def test_show_of_an_unknown_contact_is_404
with_contacts({}) { get "/contacts/nope" }