-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Helper to render flash message displays in a consistent way
- Loading branch information
1 parent
247d171
commit 6d24125
Showing
3 changed files
with
313 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
defmodule CrunchBerry.Components.FlashMessage do | ||
@moduledoc """ | ||
Function to render flash message blocks in a consistent manner | ||
Uses layout for flash messages that was established in ecom_api, and makes | ||
it available to inject into components and layouts | ||
Flash messages are local to a component, so we can't package this up as a | ||
live_view component, because then the component would only display flash messages for itself. | ||
The assigns in the argument are *mandatory* | ||
e.g. | ||
``` | ||
<%= CrunchBerry.Components.FlashMessage.render_flash(%{flash: @flash, myself: @myself}) %> | ||
``` | ||
Or, if you are using the live_helper | ||
``` | ||
<%= render_flash(assigns) %> | ||
``` | ||
## N.B. Using in a stateless component | ||
Note well, in order for change tracking to work in a stateless component, | ||
you must pass the flash into the assigns. See the test `describe "in a stateless component" do` | ||
for a full example, but in a nutshell: | ||
If StateslessComponentFixture is using the `render_flash/1` then you need to pass in flash to the | ||
component for change tracking to work | ||
``` | ||
<%= live_component StatelessComponentFixture, flash: @flash %>` | ||
``` | ||
""" | ||
import Phoenix.LiveView.Helpers | ||
|
||
def render_flash(assigns) do | ||
~H""" | ||
<%= render_flash_block(%{flash: @flash, myself: @myself, color: "red", type: :error}) %> | ||
<%= render_flash_block(%{flash: @flash, myself: @myself, color: "green", type: :info}) %> | ||
""" | ||
end | ||
|
||
defp render_flash_block(assigns) do | ||
~H""" | ||
<%= if live_flash(@flash, @type) do %> | ||
<div class={"bg-true-#{@color}-50 pt-3 pb-1 px-4"}> | ||
<div class="flex"> | ||
<div class="flex-shrink-0"> | ||
<span class={"material-icons text-#{@color}-1"}>check_circle</span> | ||
</div> | ||
<div class="ml-2 mt-0.5"> | ||
<p class={"text-sm font-medium text-#{@color}-1"}> | ||
<%= live_flash(@flash, @type) %> | ||
</p> | ||
</div> | ||
<div class="ml-auto pl-3"> | ||
<div class="-my-1.5"> | ||
<%= render_button(%{color: @color, myself: @myself, type: @type}) %> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<% end %> | ||
""" | ||
end | ||
|
||
defp render_button(assigns) do | ||
if Map.get(assigns, :myself) do | ||
~H""" | ||
<button type="button" phx-click="lv:clear-flash" phx-value-key={@type} phx-target={@myself} | ||
class={"text-2xl inline-flex px-1.5 pb-0.5 rounded-md text-#{@color}-1 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-#{@color}-50 focus:ring-#{@color}-1"}> | ||
× | ||
</button> | ||
""" | ||
else | ||
~H""" | ||
<button type="button" phx-click="lv:clear-flash" phx-value-key={@type} | ||
class={"text-2xl inline-flex px-1.5 pb-0.5 rounded-md text-#{@color}-1 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-#{@color}-50 focus:ring-#{@color}-1"}> | ||
× | ||
</button> | ||
""" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
defmodule Optimizer.Api.UserLive.UploadSalesCSV.FlashMessageTest do | ||
use ExUnit.Case | ||
import Phoenix.ConnTest | ||
import Phoenix.LiveViewTest | ||
|
||
@endpoint CrunchBerry.TestEndpoint | ||
|
||
setup do | ||
conn = build_conn() | ||
socket = %Phoenix.LiveView.Socket{} | ||
start_supervised!(CrunchBerry.TestEndpoint) | ||
{:ok, socket: socket, conn: conn} | ||
end | ||
|
||
describe "Renders in a view" do | ||
defmodule LiveViewFixture do | ||
use Phoenix.LiveView | ||
import CrunchBerry.Components.LiveHelpers | ||
|
||
def mount(_params, _session, socket) do | ||
{:ok, socket} | ||
end | ||
|
||
def render(assigns) do | ||
~H""" | ||
<div id="flash-content"> | ||
<%= render_flash(assigns) %> | ||
</div> | ||
<button phx-click="push-me" phx-value="button">Click</button> | ||
""" | ||
end | ||
|
||
def handle_event(event, _params, socket) do | ||
socket = Phoenix.LiveView.put_flash(socket, :info, "Info flash message") | ||
{:noreply, assign(socket, message: event)} | ||
end | ||
end | ||
|
||
test "Flash renders", %{conn: conn} do | ||
# Start out without a flash message | ||
{:ok, view, html} = live_isolated(conn, LiveViewFixture) | ||
refute html =~ "flash message" | ||
|
||
# click to create the flash message | ||
click_html = | ||
view | ||
|> element("button", "Click") | ||
|> render_click() | ||
|
||
# Verify that it is there | ||
assert click_html =~ "flash message" | ||
|
||
dismissed_html = | ||
view | ||
|> element("#flash-content button") | ||
|> render_click() | ||
|
||
refute dismissed_html =~ "flash message" | ||
end | ||
end | ||
|
||
defmodule ComponentFixture do | ||
use Phoenix.HTML | ||
use Phoenix.LiveComponent | ||
import CrunchBerry.Components.LiveHelpers | ||
|
||
def render(assigns) do | ||
~H""" | ||
<div> | ||
<div id="flash-content"> | ||
<%= render_flash(assigns) %> | ||
</div> | ||
<button phx-click="push-me" phx-value="button" phx-target={@myself}>Click</button> | ||
</div> | ||
""" | ||
end | ||
|
||
def handle_event(event, _params, socket) do | ||
socket = Phoenix.LiveView.put_flash(socket, :info, "Info flash message") | ||
{:noreply, assign(socket, message: event)} | ||
end | ||
end | ||
|
||
describe "in a stateful component" do | ||
defmodule ComponentViewFixture do | ||
use Phoenix.LiveView | ||
|
||
def mount(_params, _session, socket) do | ||
{:ok, socket} | ||
end | ||
|
||
def render(assigns) do | ||
~H""" | ||
<div> | ||
<%= live_component ComponentFixture, id: "test-fixture" %> | ||
</div> | ||
""" | ||
end | ||
|
||
def handle_event(event, _params, socket) do | ||
socket = Phoenix.LiveView.put_flash(socket, :info, "Info flash message") | ||
{:noreply, assign(socket, message: event)} | ||
end | ||
end | ||
|
||
test "renders correctly", %{conn: conn} do | ||
# Start out without a flash message | ||
{:ok, view, html} = live_isolated(conn, ComponentViewFixture) | ||
refute html =~ "flash message" | ||
|
||
# click to create the flash message | ||
click_html = | ||
view | ||
|> element("button", "Click") | ||
|> render_click() | ||
|
||
# Verify that it is there | ||
assert click_html =~ "flash message" | ||
|
||
dismissed_html = | ||
view | ||
|> element("#flash-content button") | ||
|> render_click() | ||
|
||
refute dismissed_html =~ "flash message" | ||
end | ||
end | ||
|
||
describe "in a stateless component" do | ||
defmodule StatelessComponentFixture do | ||
use Phoenix.HTML | ||
use Phoenix.LiveComponent | ||
import CrunchBerry.Components.LiveHelpers | ||
|
||
def render(assigns) do | ||
~H""" | ||
<div> | ||
<div id="flash-content"> | ||
<%= render_flash(assigns) %> | ||
</div> | ||
<button phx-click="push-me" phx-value="button">Click</button> | ||
</div> | ||
""" | ||
end | ||
end | ||
|
||
defmodule ViewStatelessComponentFixture do | ||
use Phoenix.LiveView | ||
|
||
def mount(_params, _session, socket) do | ||
{:ok, socket} | ||
end | ||
|
||
def render(assigns) do | ||
~H""" | ||
<div> | ||
<%= live_component StatelessComponentFixture, flash: @flash %> | ||
</div> | ||
""" | ||
end | ||
|
||
def handle_event(event, _params, socket) do | ||
socket = Phoenix.LiveView.put_flash(socket, :error, "stateless flash error message") | ||
{:noreply, assign(socket, message: event)} | ||
end | ||
end | ||
|
||
test "renders correctly", %{conn: conn} do | ||
# Start out without a flash message | ||
{:ok, view, html} = live_isolated(conn, ViewStatelessComponentFixture) | ||
refute html =~ "stateless flash error message" | ||
|
||
# click to create the flash message | ||
click_html = | ||
view | ||
|> element("button", "Click") | ||
|> render_click() | ||
|
||
# Verify that it is there | ||
assert click_html =~ "stateless flash error message" | ||
|
||
dismissed_html = | ||
view | ||
|> element("#flash-content button") | ||
|> render_click() | ||
|
||
refute dismissed_html =~ "stateless flash error message" | ||
end | ||
end | ||
end |