Merge remote-tracking branch 'origin/main' into feature/220_ui_issues_2
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
commit
b1f6d29ca1
7 changed files with 45 additions and 44 deletions
|
|
@ -90,4 +90,4 @@ USER nobody
|
||||||
# above and adding an entrypoint. See https://github.com/krallin/tini for details
|
# above and adding an entrypoint. See https://github.com/krallin/tini for details
|
||||||
# ENTRYPOINT ["/tini", "--"]
|
# ENTRYPOINT ["/tini", "--"]
|
||||||
|
|
||||||
CMD ["/app/bin/server"]
|
ENTRYPOINT ["/app/bin/docker-entrypoint.sh"]
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@ For testing the production Docker build locally:
|
||||||
docker compose -f docker-compose.prod.yml up
|
docker compose -f docker-compose.prod.yml up
|
||||||
```
|
```
|
||||||
|
|
||||||
5. **Run database migrations:**
|
5. **Database migrations run automatically** on app start. For manual migration:
|
||||||
```bash
|
```bash
|
||||||
docker compose -f docker-compose.prod.yml exec app /app/bin/mv eval "Mv.Release.migrate"
|
docker compose -f docker-compose.prod.yml exec app /app/bin/mv eval "Mv.Release.migrate"
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -499,6 +499,7 @@ defmodule MvWeb.CoreComponents do
|
||||||
slot :col, required: true do
|
slot :col, required: true do
|
||||||
attr :label, :string
|
attr :label, :string
|
||||||
attr :class, :string
|
attr :class, :string
|
||||||
|
attr :col_click, :any, doc: "optional column-specific click handler that overrides row_click"
|
||||||
end
|
end
|
||||||
|
|
||||||
slot :action, doc: "the slot for showing user actions in the last table column"
|
slot :action, doc: "the slot for showing user actions in the last table column"
|
||||||
|
|
@ -534,9 +535,13 @@ defmodule MvWeb.CoreComponents do
|
||||||
<tr :for={row <- @rows} id={@row_id && @row_id.(row)}>
|
<tr :for={row <- @rows} id={@row_id && @row_id.(row)}>
|
||||||
<td
|
<td
|
||||||
:for={col <- @col}
|
:for={col <- @col}
|
||||||
phx-click={@row_click && @row_click.(row)}
|
phx-click={
|
||||||
|
(col[:col_click] && col[:col_click].(@row_item.(row))) ||
|
||||||
|
(@row_click && @row_click.(row))
|
||||||
|
}
|
||||||
class={
|
class={
|
||||||
col_class = Map.get(col, :class)
|
col_class = Map.get(col, :class)
|
||||||
|
has_click = col[:col_click] || @row_click
|
||||||
classes = ["max-w-xs"]
|
classes = ["max-w-xs"]
|
||||||
|
|
||||||
classes =
|
classes =
|
||||||
|
|
@ -547,7 +552,7 @@ defmodule MvWeb.CoreComponents do
|
||||||
end
|
end
|
||||||
|
|
||||||
classes =
|
classes =
|
||||||
if @row_click do
|
if has_click do
|
||||||
["hover:cursor-pointer" | classes]
|
["hover:cursor-pointer" | classes]
|
||||||
else
|
else
|
||||||
classes
|
classes
|
||||||
|
|
|
||||||
|
|
@ -1082,6 +1082,16 @@ defmodule MvWeb.MemberLive.Index do
|
||||||
|> Enum.map(&format_member_email/1)
|
|> Enum.map(&format_member_email/1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns a JS command to toggle member selection when clicking the checkbox column.
|
||||||
|
|
||||||
|
Used as `col_click` handler to ensure clicking anywhere in the checkbox column
|
||||||
|
toggles the checkbox instead of navigating to the member details.
|
||||||
|
"""
|
||||||
|
def checkbox_column_click(member) do
|
||||||
|
JS.push("select_member", value: %{id: member.id})
|
||||||
|
end
|
||||||
|
|
||||||
# Formats a member's email in the format "First Last <email>"
|
# Formats a member's email in the format "First Last <email>"
|
||||||
# Used for copy_emails feature and mailto links to create email-client-friendly format.
|
# Used for copy_emails feature and mailto links to create email-client-friendly format.
|
||||||
def format_member_email(member) do
|
def format_member_email(member) do
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@
|
||||||
<!-- <:col :let={member} label="Id">{member.id}</:col> -->
|
<!-- <:col :let={member} label="Id">{member.id}</:col> -->
|
||||||
<:col
|
<:col
|
||||||
:let={member}
|
:let={member}
|
||||||
|
col_click={&MvWeb.MemberLive.Index.checkbox_column_click/1}
|
||||||
label={
|
label={
|
||||||
~H"""
|
~H"""
|
||||||
<.input
|
<.input
|
||||||
|
|
@ -81,11 +82,7 @@
|
||||||
<.input
|
<.input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name={member.id}
|
name={member.id}
|
||||||
phx-click="select_member"
|
|
||||||
phx-value-id={member.id}
|
|
||||||
checked={MapSet.member?(@selected_members, member.id)}
|
checked={MapSet.member?(@selected_members, member.id)}
|
||||||
phx-capture-click
|
|
||||||
phx-stop-propagation
|
|
||||||
aria-label={gettext("Select member")}
|
aria-label={gettext("Select member")}
|
||||||
role="checkbox"
|
role="checkbox"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
9
rel/overlays/bin/docker-entrypoint.sh
Executable file
9
rel/overlays/bin/docker-entrypoint.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "==> Running database migrations..."
|
||||||
|
/app/bin/migrate
|
||||||
|
|
||||||
|
echo "==> Starting application..."
|
||||||
|
exec /app/bin/server
|
||||||
|
|
||||||
|
|
@ -285,14 +285,9 @@ defmodule MvWeb.MemberLive.IndexTest 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")
|
||||||
|
|
||||||
# Select two members
|
# Select two members by sending the select_member event directly
|
||||||
view
|
render_click(view, "select_member", %{"id" => member1.id})
|
||||||
|> element("[phx-click='select_member'][phx-value-id='#{member1.id}']")
|
render_click(view, "select_member", %{"id" => member2.id})
|
||||||
|> render_click()
|
|
||||||
|
|
||||||
view
|
|
||||||
|> element("[phx-click='select_member'][phx-value-id='#{member2.id}']")
|
|
||||||
|> render_click()
|
|
||||||
|
|
||||||
# Trigger copy_emails event
|
# Trigger copy_emails event
|
||||||
view |> element("#copy-emails-btn") |> render_click()
|
view |> element("#copy-emails-btn") |> render_click()
|
||||||
|
|
@ -336,10 +331,8 @@ defmodule MvWeb.MemberLive.IndexTest 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")
|
||||||
|
|
||||||
# Select member with umlauts
|
# Select member with umlauts by sending the select_member event directly
|
||||||
view
|
render_click(view, "select_member", %{"id" => member3.id})
|
||||||
|> element("[phx-click='select_member'][phx-value-id='#{member3.id}']")
|
|
||||||
|> render_click()
|
|
||||||
|
|
||||||
# Trigger copy_emails event - should not crash
|
# Trigger copy_emails event - should not crash
|
||||||
view |> element("#copy-emails-btn") |> render_click()
|
view |> element("#copy-emails-btn") |> render_click()
|
||||||
|
|
@ -355,10 +348,8 @@ defmodule MvWeb.MemberLive.IndexTest 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")
|
||||||
|
|
||||||
# Select a member
|
# Select a member by sending the select_member event directly
|
||||||
view
|
render_click(view, "select_member", %{"id" => member1.id})
|
||||||
|> element("[phx-click='select_member'][phx-value-id='#{member1.id}']")
|
|
||||||
|> render_click()
|
|
||||||
|
|
||||||
# Delete the member from the database
|
# Delete the member from the database
|
||||||
Ash.destroy!(member1)
|
Ash.destroy!(member1)
|
||||||
|
|
@ -379,14 +370,9 @@ defmodule MvWeb.MemberLive.IndexTest 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")
|
||||||
|
|
||||||
# Select two members
|
# Select two members by sending the select_member event directly
|
||||||
view
|
render_click(view, "select_member", %{"id" => member1.id})
|
||||||
|> element("[phx-click='select_member'][phx-value-id='#{member1.id}']")
|
render_click(view, "select_member", %{"id" => member2.id})
|
||||||
|> render_click()
|
|
||||||
|
|
||||||
view
|
|
||||||
|> element("[phx-click='select_member'][phx-value-id='#{member2.id}']")
|
|
||||||
|> render_click()
|
|
||||||
|
|
||||||
# Get the socket state to verify the formatted email string
|
# Get the socket state to verify the formatted email string
|
||||||
state = :sys.get_state(view.pid)
|
state = :sys.get_state(view.pid)
|
||||||
|
|
@ -415,10 +401,8 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
|
|
||||||
{:ok, view, _html} = live(conn, "/members")
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
|
|
||||||
# Select the test member
|
# Select the test member by sending the select_member event directly
|
||||||
view
|
render_click(view, "select_member", %{"id" => test_member.id})
|
||||||
|> element("[phx-click='select_member'][phx-value-id='#{test_member.id}']")
|
|
||||||
|> render_click()
|
|
||||||
|
|
||||||
# The format should be "Test Format <test.format@example.com>"
|
# The format should be "Test Format <test.format@example.com>"
|
||||||
# We verify this by checking the flash shows 1 email was copied
|
# We verify this by checking the flash shows 1 email was copied
|
||||||
|
|
@ -441,10 +425,8 @@ defmodule MvWeb.MemberLive.IndexTest 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")
|
||||||
|
|
||||||
# Select a member
|
# Select a member by sending the select_member event directly
|
||||||
view
|
render_click(view, "select_member", %{"id" => member1.id})
|
||||||
|> element("[phx-click='select_member'][phx-value-id='#{member1.id}']")
|
|
||||||
|> render_click()
|
|
||||||
|
|
||||||
# Button should now be visible
|
# Button should now be visible
|
||||||
assert has_element?(view, "#copy-emails-btn")
|
assert has_element?(view, "#copy-emails-btn")
|
||||||
|
|
@ -457,10 +439,8 @@ defmodule MvWeb.MemberLive.IndexTest 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")
|
||||||
|
|
||||||
# Select a member
|
# Select a member by sending the select_member event directly
|
||||||
view
|
render_click(view, "select_member", %{"id" => member1.id})
|
||||||
|> element("[phx-click='select_member'][phx-value-id='#{member1.id}']")
|
|
||||||
|> render_click()
|
|
||||||
|
|
||||||
# Click copy button
|
# Click copy button
|
||||||
view |> element("#copy-emails-btn") |> render_click()
|
view |> element("#copy-emails-btn") |> render_click()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue