feat(member-live): default the overview to comfortable density with folded-in email
This commit is contained in:
parent
0a23d03d9d
commit
4d100aef22
10 changed files with 58 additions and 44 deletions
|
|
@ -29,9 +29,9 @@ defmodule MvWeb.MemberLive.Index.ViewSettings do
|
||||||
@cookie_max_age 365 * 24 * 60 * 60
|
@cookie_max_age 365 * 24 * 60 * 60
|
||||||
|
|
||||||
@defaults %{
|
@defaults %{
|
||||||
density: :compact,
|
density: :comfortable,
|
||||||
compact_member: true,
|
compact_member: true,
|
||||||
member_include_email: false,
|
member_include_email: true,
|
||||||
compact_address: true
|
compact_address: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,9 +47,9 @@ defmodule MvWeb.MemberLive.Index.ViewSettings do
|
||||||
|
|
||||||
@doc "The global default view settings used when nothing is stored."
|
@doc "The global default view settings used when nothing is stored."
|
||||||
@spec defaults() :: %{
|
@spec defaults() :: %{
|
||||||
density: :compact,
|
density: :comfortable,
|
||||||
compact_member: true,
|
compact_member: true,
|
||||||
member_include_email: false,
|
member_include_email: true,
|
||||||
compact_address: true
|
compact_address: true
|
||||||
}
|
}
|
||||||
def defaults, do: @defaults
|
def defaults, do: @defaults
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ defmodule MvWeb.MemberLive.Index.ViewSettingsTest do
|
||||||
|
|
||||||
alias MvWeb.MemberLive.Index.ViewSettings
|
alias MvWeb.MemberLive.Index.ViewSettings
|
||||||
|
|
||||||
test "defaults are all-compact with the email line off" do
|
test "defaults are comfortable density with the compact cells and email line on" do
|
||||||
assert ViewSettings.defaults() == %{
|
assert ViewSettings.defaults() == %{
|
||||||
density: :compact,
|
density: :comfortable,
|
||||||
compact_member: true,
|
compact_member: true,
|
||||||
member_include_email: false,
|
member_include_email: true,
|
||||||
compact_address: true
|
compact_address: true
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
@ -90,7 +90,7 @@ defmodule MvWeb.MemberLive.Index.ViewSettingsTest do
|
||||||
# from cookie
|
# from cookie
|
||||||
compact_address: false,
|
compact_address: false,
|
||||||
# default
|
# default
|
||||||
member_include_email: false
|
member_include_email: true
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ defmodule MvWeb.MemberLive.IndexA11yHardeningTest do
|
||||||
# LiveView test is that the guarded checkbox markup exists in both densities.
|
# LiveView test is that the guarded checkbox markup exists in both densities.
|
||||||
assert has_element?(view, "#members-table-guard input[type='checkbox'].checkbox")
|
assert has_element?(view, "#members-table-guard input[type='checkbox'].checkbox")
|
||||||
|
|
||||||
# Switch to comfortable via the view-settings dropdown.
|
# Toggle density via the view-settings dropdown (default is comfortable, so
|
||||||
|
# this switches to compact) to check the other density too.
|
||||||
view |> element("[data-testid='view-settings-button']") |> render_click()
|
view |> element("[data-testid='view-settings-button']") |> render_click()
|
||||||
view |> element("[data-testid='view-setting-density']") |> render_click()
|
view |> element("[data-testid='view-setting-density']") |> render_click()
|
||||||
assert has_element?(view, "#members-table-guard input[type='checkbox'].checkbox")
|
assert has_element?(view, "#members-table-guard input[type='checkbox'].checkbox")
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,12 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
|
||||||
conn: conn,
|
conn: conn,
|
||||||
field_string: field
|
field_string: field
|
||||||
} do
|
} do
|
||||||
conn = conn_with_oidc_user(conn)
|
# Email is folded into the Member cell by default; turn the fold off so email
|
||||||
|
# is a separate, sortable column for this cross-column-sort test.
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> conn_with_oidc_user()
|
||||||
|
|> Plug.Conn.put_session("member_view_settings", ~s({"member_include_email":false}))
|
||||||
|
|
||||||
{:ok, view, _html} =
|
{:ok, view, _html} =
|
||||||
live(
|
live(
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,9 @@ defmodule MvWeb.MemberLive.IndexDefaultColumnsTest do
|
||||||
# Composite Name + Address cells.
|
# Composite Name + Address cells.
|
||||||
assert has_element?(view, "[data-testid='member-name']")
|
assert has_element?(view, "[data-testid='member-name']")
|
||||||
assert has_element?(view, "[data-testid='member-address']")
|
assert has_element?(view, "[data-testid='member-address']")
|
||||||
# E-Mail is its own column by default (compact Member field, email line off).
|
# E-Mail is folded into the Member cell by default (include-email on), so it
|
||||||
assert has_element?(view, "[data-testid='email']")
|
# shows as the in-cell email line rather than a separate column.
|
||||||
|
assert has_element?(view, "[data-testid='member-name-email']")
|
||||||
# Fee type, fee status, groups, join date headers.
|
# Fee type, fee status, groups, join date headers.
|
||||||
assert has_element?(view, "[data-testid='membership_fee_type']")
|
assert has_element?(view, "[data-testid='membership_fee_type']")
|
||||||
assert has_element?(view, "[data-testid='join_date']")
|
assert has_element?(view, "[data-testid='join_date']")
|
||||||
|
|
@ -47,17 +48,18 @@ defmodule MvWeb.MemberLive.IndexDefaultColumnsTest do
|
||||||
test "the individual name/address sub-fields are hidden by default", %{conn: conn} do
|
test "the individual name/address sub-fields are hidden by default", %{conn: conn} do
|
||||||
{:ok, view, _html} = live(conn, ~p"/members")
|
{:ok, view, _html} = live(conn, ~p"/members")
|
||||||
|
|
||||||
# The composite Name/Address cells replace their constituents by default.
|
# The composite Name/Address cells replace their constituents by default, and
|
||||||
# E-Mail is excluded here: it is a default-visible column of its own.
|
# the email is folded into the Member cell (include-email on), so no separate
|
||||||
for field <- ~w(first_name last_name city street house_number postal_code country) do
|
# email column shows either.
|
||||||
|
for field <- ~w(first_name last_name email city street house_number postal_code country) do
|
||||||
refute has_element?(view, "[data-testid='#{field}']")
|
refute has_element?(view, "[data-testid='#{field}']")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "an explicit field selection still overrides the curated default", %{conn: conn} do
|
test "an explicit field selection still overrides the curated default", %{conn: conn} do
|
||||||
{:ok, view, _html} = live(conn, ~p"/members?fields=email")
|
{:ok, view, _html} = live(conn, ~p"/members?fields=join_date")
|
||||||
|
|
||||||
assert has_element?(view, "[data-testid='email']")
|
assert has_element?(view, "[data-testid='join_date']")
|
||||||
refute has_element?(view, "[data-testid='member-name']")
|
refute has_element?(view, "[data-testid='member-name']")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,13 @@ defmodule MvWeb.MemberLive.IndexDensityTest do
|
||||||
view
|
view
|
||||||
end
|
end
|
||||||
|
|
||||||
test "defaults to compact when nothing is stored", %{conn: conn} do
|
test "defaults to comfortable when nothing is stored", %{conn: conn} do
|
||||||
{:ok, view, _html} = live(conn, ~p"/members")
|
{:ok, view, _html} = live(conn, ~p"/members")
|
||||||
|
|
||||||
assert has_element?(view, "[data-testid='members-table-scroll'][data-density='compact']")
|
assert has_element?(view, "[data-testid='members-table-scroll'][data-density='comfortable']")
|
||||||
# The compact-mode toggle reflects the active (compact) state.
|
# The compact-mode toggle reflects the active (comfortable, i.e. not compact) state.
|
||||||
open_view_settings(view)
|
open_view_settings(view)
|
||||||
assert has_element?(view, "[data-testid='view-setting-density'][aria-checked='true']")
|
assert has_element?(view, "[data-testid='view-setting-density'][aria-checked='false']")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "toggle switches the density token and the control state", %{conn: conn} do
|
test "toggle switches the density token and the control state", %{conn: conn} do
|
||||||
|
|
@ -41,12 +41,12 @@ defmodule MvWeb.MemberLive.IndexDensityTest do
|
||||||
open_view_settings(view)
|
open_view_settings(view)
|
||||||
view |> element("[data-testid='view-setting-density']") |> render_click()
|
view |> element("[data-testid='view-setting-density']") |> render_click()
|
||||||
|
|
||||||
assert has_element?(view, "[data-testid='members-table-scroll'][data-density='comfortable']")
|
|
||||||
assert has_element?(view, "[data-testid='view-setting-density'][aria-checked='false']")
|
|
||||||
|
|
||||||
# Toggling again returns to compact.
|
|
||||||
view |> element("[data-testid='view-setting-density']") |> render_click()
|
|
||||||
assert has_element?(view, "[data-testid='members-table-scroll'][data-density='compact']")
|
assert has_element?(view, "[data-testid='members-table-scroll'][data-density='compact']")
|
||||||
|
assert has_element?(view, "[data-testid='view-setting-density'][aria-checked='true']")
|
||||||
|
|
||||||
|
# Toggling again returns to comfortable.
|
||||||
|
view |> element("[data-testid='view-setting-density']") |> render_click()
|
||||||
|
assert has_element?(view, "[data-testid='members-table-scroll'][data-density='comfortable']")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "restores a persisted density from the session on reload", %{conn: conn} do
|
test "restores a persisted density from the session on reload", %{conn: conn} do
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,9 @@ defmodule MvWeb.MemberLive.IndexFieldVisibilityTest do
|
||||||
|
|
||||||
describe "URL parameter persistence" do
|
describe "URL parameter persistence" do
|
||||||
test "field selection is persisted in URL", %{conn: conn} do
|
test "field selection is persisted in URL", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
# Email is offered as a togglable column only when it is not folded into the
|
||||||
|
# Member cell; unfold it so the dropdown lists it.
|
||||||
|
conn = conn |> conn_with_oidc_user() |> non_compact()
|
||||||
{:ok, view, _html} = live(conn, "/members")
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
|
|
||||||
# Open dropdown and hide email
|
# Open dropdown and hide email
|
||||||
|
|
@ -374,7 +376,7 @@ defmodule MvWeb.MemberLive.IndexFieldVisibilityTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "handles rapid toggling", %{conn: conn} do
|
test "handles rapid toggling", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn |> conn_with_oidc_user() |> non_compact()
|
||||||
{:ok, view, _html} = live(conn, "/members")
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
|
|
||||||
# Open dropdown
|
# Open dropdown
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,8 @@ defmodule MvWeb.MemberLive.IndexMemberFieldsDisplayTest do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn_with_oidc_user(conn)
|
||||||
{:ok, _view, html} = live(conn, "/members")
|
{:ok, _view, html} = live(conn, "/members")
|
||||||
|
|
||||||
# The composite Member cell carries first + last name; the in-cell email
|
# The composite Member cell carries first + last name and the in-cell email
|
||||||
# line stays off by default, but the email is surfaced in its own column
|
# line (include-email on by default), so all three values are rendered.
|
||||||
# (compact Member field, include-email off).
|
|
||||||
for m <- [m1, m2], field <- [m.first_name, m.last_name, m.email] do
|
for m <- [m1, m2], field <- [m.first_name, m.last_name, m.email] do
|
||||||
assert html =~ field
|
assert html =~ field
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,9 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
# those tests additionally opt out via `non_compact/1`. Either way a `fields`
|
# those tests additionally opt out via `non_compact/1`. Either way a `fields`
|
||||||
# param rides on every push_patch, hence the relaxed substring assertions.
|
# param rides on every push_patch, hence the relaxed substring assertions.
|
||||||
test "clicking a column header toggles sort order and updates the URL", %{conn: conn} do
|
test "clicking a column header toggles sort order and updates the URL", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
# Email is folded into the Member cell by default; unfold it to a separate
|
||||||
|
# sortable column for this column-sort test.
|
||||||
|
conn = conn |> conn_with_oidc_user() |> non_compact()
|
||||||
{:ok, view, _html} = live(conn, "/members?fields=email")
|
{:ok, view, _html} = live(conn, "/members?fields=email")
|
||||||
|
|
||||||
# The component data test ids are built with the name of the field
|
# The component data test ids are built with the name of the field
|
||||||
|
|
@ -247,7 +249,7 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "sorting works with search query", %{conn: conn} do
|
test "sorting works with search query", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn |> conn_with_oidc_user() |> non_compact()
|
||||||
{:ok, view, _html} = live(conn, "/members?fields=email&query=test")
|
{:ok, view, _html} = live(conn, "/members?fields=email&query=test")
|
||||||
|
|
||||||
view
|
view
|
||||||
|
|
@ -261,7 +263,7 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "sorting maintains search query when toggling order", %{conn: conn} do
|
test "sorting maintains search query when toggling order", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn |> conn_with_oidc_user() |> non_compact()
|
||||||
|
|
||||||
{:ok, view, _html} =
|
{:ok, view, _html} =
|
||||||
live(conn, "/members?fields=email&query=test&sort_field=email&sort_order=asc")
|
live(conn, "/members?fields=email&query=test&sort_field=email&sort_order=asc")
|
||||||
|
|
@ -280,7 +282,7 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
describe "URL param handling" do
|
describe "URL param handling" do
|
||||||
@describetag :ui
|
@describetag :ui
|
||||||
test "handle_params reads sort query and applies it", %{conn: conn} do
|
test "handle_params reads sort query and applies it", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn |> conn_with_oidc_user() |> non_compact()
|
||||||
|
|
||||||
{:ok, view, _html} =
|
{:ok, view, _html} =
|
||||||
live(conn, "/members?fields=email&query=&sort_field=email&sort_order=desc")
|
live(conn, "/members?fields=email&query=&sort_field=email&sort_order=desc")
|
||||||
|
|
@ -300,7 +302,7 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "handle_params preserves search query with sort params", %{conn: conn} do
|
test "handle_params preserves search query with sort params", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn |> conn_with_oidc_user() |> non_compact()
|
||||||
|
|
||||||
{:ok, view, _html} =
|
{:ok, view, _html} =
|
||||||
live(conn, "/members?fields=email&query=test&sort_field=email&sort_order=desc")
|
live(conn, "/members?fields=email&query=test&sort_field=email&sort_order=desc")
|
||||||
|
|
@ -313,7 +315,7 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
describe "search and sort integration" do
|
describe "search and sort integration" do
|
||||||
@describetag :ui
|
@describetag :ui
|
||||||
test "search maintains sort state", %{conn: conn} do
|
test "search maintains sort state", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn |> conn_with_oidc_user() |> non_compact()
|
||||||
|
|
||||||
{:ok, view, _html} =
|
{:ok, view, _html} =
|
||||||
live(conn, "/members?fields=email&query=&sort_field=email&sort_order=desc")
|
live(conn, "/members?fields=email&query=&sort_field=email&sort_order=desc")
|
||||||
|
|
@ -328,7 +330,7 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "sort maintains search state", %{conn: conn} do
|
test "sort maintains search state", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn |> conn_with_oidc_user() |> non_compact()
|
||||||
|
|
||||||
{:ok, view, _html} =
|
{:ok, view, _html} =
|
||||||
live(conn, "/members?fields=email&query=test&sort_field=email&sort_order=asc")
|
live(conn, "/members?fields=email&query=test&sort_field=email&sort_order=asc")
|
||||||
|
|
@ -1607,7 +1609,7 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "boolean filters are preserved during navigation actions", %{conn: conn} do
|
test "boolean filters are preserved during navigation actions", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn |> conn_with_oidc_user() |> non_compact()
|
||||||
boolean_field = create_boolean_custom_field()
|
boolean_field = create_boolean_custom_field()
|
||||||
|
|
||||||
{:ok, view, _html} =
|
{:ok, view, _html} =
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ defmodule MvWeb.MemberLive.IndexViewSettingsTest do
|
||||||
§1.20 — the view-settings dropdown toggles: the composite "Member" and address
|
§1.20 — the view-settings dropdown toggles: the composite "Member" and address
|
||||||
fields, the "include email" sub-toggle and their effect on the rendered
|
fields, the "include email" sub-toggle and their effect on the rendered
|
||||||
columns. Turning a composite off surfaces the underlying separate columns.
|
columns. Turning a composite off surfaces the underlying separate columns.
|
||||||
§1.2 — email is not in the Member cell by default.
|
§1.2 — email is folded into the Member cell by default (include-email on).
|
||||||
"""
|
"""
|
||||||
use MvWeb.ConnCase, async: false
|
use MvWeb.ConnCase, async: false
|
||||||
|
|
||||||
|
|
@ -34,20 +34,23 @@ defmodule MvWeb.MemberLive.IndexViewSettingsTest do
|
||||||
view
|
view
|
||||||
end
|
end
|
||||||
|
|
||||||
test "member cell hides the email line by default", %{conn: conn} do
|
test "member cell shows the email line by default", %{conn: conn} do
|
||||||
{:ok, view, _html} = live(conn, ~p"/members")
|
{:ok, view, _html} = live(conn, ~p"/members")
|
||||||
|
|
||||||
assert has_element?(view, "[data-testid='member-name']")
|
assert has_element?(view, "[data-testid='member-name']")
|
||||||
refute has_element?(view, "[data-testid='member-name-email']")
|
assert has_element?(view, "[data-testid='member-name-email']", "ada@example.com")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "the include-email sub-toggle surfaces the email line in the member cell", %{conn: conn} do
|
test "the include-email sub-toggle removes the email line from the member cell", %{conn: conn} do
|
||||||
{:ok, view, _html} = live(conn, ~p"/members")
|
{:ok, view, _html} = live(conn, ~p"/members")
|
||||||
|
|
||||||
|
# Email is folded into the Member cell by default; the sub-toggle turns it off.
|
||||||
|
assert has_element?(view, "[data-testid='member-name-email']", "ada@example.com")
|
||||||
|
|
||||||
open_view_settings(view)
|
open_view_settings(view)
|
||||||
view |> element("[data-testid='view-setting-member-include-email']") |> render_click()
|
view |> element("[data-testid='view-setting-member-include-email']") |> render_click()
|
||||||
|
|
||||||
assert has_element?(view, "[data-testid='member-name-email']", "ada@example.com")
|
refute has_element?(view, "[data-testid='member-name-email']")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "turning off the compact member field shows separate name columns", %{conn: conn} do
|
test "turning off the compact member field shows separate name columns", %{conn: conn} do
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue