-
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.
A reusable Cancel/Ok dialog box (#12)
* A reusable Cancel/Ok dialog box
- Loading branch information
1 parent
72e1583
commit 247d171
Showing
10 changed files
with
265 additions
and
1 deletion.
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
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,3 @@ | ||
import Config | ||
|
||
import_config "#{Mix.env()}.exs" |
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 @@ | ||
import Config |
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 @@ | ||
import Config |
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,8 @@ | ||
import Config | ||
|
||
# Because we don't care, and just want to supress the message in test | ||
config :phoenix, :json_library, Jason | ||
|
||
config :crunch_berry, CrunchBerry.TestEndpoint, | ||
secret_key_base: "oc2RUnRoYkZlR0dM7JwlpbM9AsauRm0R1n+sUP71YsY9eflg4uWyeVFXHrAzDXL7", | ||
live_view: [signing_salt: "FqRkKpuzaujIZQGN"] |
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,97 @@ | ||
defmodule CrunchBerry.Components.ConfirmModal do | ||
@moduledoc """ | ||
# ConfirmModal | ||
Reusable Cancel/Ok dialog box. ConfirmModal is a stateless component | ||
that takes a title and a message to display, and then sends a | ||
`confirm-ok` or `confirm-cancel` event to the hosting live view based on | ||
user selection. | ||
Required assigns | ||
* `title:` The title of the dialog box | ||
* `message:` The message to display. Should describe an action that the user will confirm or cancel on | ||
Optional assigns | ||
* `call_to_action:` a prompt for action, defaults to "Are you sure you wish to proceed?" | ||
* `event_prefix:` a string to prefix the "ok" and "cancel" events, defaults to 'confirm', so the | ||
default events are "confirm-ok" and "confirm-cancel", but `:event_prefix` was set to "ask", then the events | ||
would be "ask-ok" and "ask-cancel" | ||
## example: | ||
In the markup | ||
``` | ||
... | ||
<%= if @reupload do %> | ||
<%= live_component CrunchBerry.Components.ConfirmModal, | ||
title: "Re-upload CSV", | ||
message: "This will clear the current session, and replace it with a new csv file." %> | ||
<% end %> | ||
... | ||
``` | ||
In the live view: | ||
``` | ||
def handle_event("confirm-ok", _, socket) do | ||
... do stuff, and don't say we didn't warn you | ||
{:noreply, assign(socket, reupload: false)} | ||
end | ||
def handle_event("confirm-cancel", _, socket) do | ||
{:noreply, assign(socket, reupload: false)} | ||
end | ||
``` | ||
""" | ||
use Phoenix.HTML | ||
use Phoenix.LiveComponent | ||
|
||
@impl Phoenix.LiveComponent | ||
def update(assigns, socket) do | ||
event_prefix = Map.get(assigns, :event_prefix, "confirm") | ||
|
||
socket = | ||
assign(socket, | ||
title: assigns.title, | ||
message: assigns.message, | ||
call_to_action: Map.get(assigns, :call_to_action, "Are you sure you wish to proceed?"), | ||
cancel_event: "#{event_prefix}-cancel", | ||
ok_event: "#{event_prefix}-ok" | ||
) | ||
|
||
{:ok, socket} | ||
end | ||
|
||
@impl Phoenix.LiveComponent | ||
def render(assigns) do | ||
~H""" | ||
<div | ||
class="fixed inset-0 w-full h-full z-20 bg-black bg-opacity-50 overflow-y-auto flex items-center backdrop-filter backdrop-blur-sm" | ||
tabindex="-1" | ||
role="dialog" | ||
aria-modal="true" | ||
phx-capture-click="close" | ||
phx-window-keydown="close" | ||
phx-key="escape" | ||
phx-page-loading> | ||
<div class="relative mx-auto my-10 opacity-100 w-11/12 md:max-w-md rounded overflow-y-auto"> | ||
<div class="relative bg-white shadow-lg rounded-md text-gray-900 z-20 flow-root"> | ||
<div> | ||
<button phx-click={@cancel_event} aria_hidden="true" class="text-gray-400 text-2xl absolute top-0 right-0 py-1 px-3 rounded-full cursor-pointer hover:no-underline hover:text-black duration-50" title: "Close">×</button> | ||
</div> | ||
<div class="w-full max-w-lg p-2"> | ||
<h2 class="font-bold block w-full text-center text-grey-darkest mb-2 pt-4"><%= @title %></h2> | ||
<div class="text-center"> | ||
<%= @message %> | ||
</div> | ||
<div class="text-center"> | ||
<%= @call_to_action %> | ||
</div> | ||
<div class="text-right p-2"> | ||
<button phx-click={@cancel_event} class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded">Cancel</button> | ||
<button phx-click={@ok_event} class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded">Ok</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
""" | ||
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
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,136 @@ | ||
defmodule Optimizer.Api.UserLive.UploadSalesCSV.ConfirmModalTest do | ||
use ExUnit.Case | ||
import Phoenix.ConnTest | ||
alias CrunchBerry.Components.ConfirmModal | ||
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 "update" do | ||
test "defaults are set correctly", %{socket: socket} do | ||
requireds = %{ | ||
title: "This is the title", | ||
message: "This event will happen" | ||
} | ||
|
||
assert {:ok, %{assigns: assigns}} = ConfirmModal.update(requireds, socket) | ||
|
||
assert %{ | ||
call_to_action: "Are you sure you wish to proceed?", | ||
cancel_event: "confirm-cancel", | ||
message: "This event will happen", | ||
ok_event: "confirm-ok", | ||
title: "This is the title" | ||
} = assigns | ||
end | ||
|
||
test "can override event_prefix", %{socket: socket} do | ||
params = %{ | ||
title: "This is the title", | ||
message: "This event will happen", | ||
event_prefix: "ask", | ||
call_to_action: "Do it?" | ||
} | ||
|
||
assert {:ok, %{assigns: assigns}} = ConfirmModal.update(params, socket) | ||
|
||
assert %{ | ||
call_to_action: "Do it?", | ||
cancel_event: "ask-cancel", | ||
message: "This event will happen", | ||
ok_event: "ask-ok", | ||
title: "This is the title" | ||
} = assigns | ||
end | ||
end | ||
|
||
describe "render" do | ||
test "defaults render correctly", %{socket: socket} do | ||
requireds = %{ | ||
title: "This is the title", | ||
message: "This event will happen" | ||
} | ||
|
||
{:ok, %{assigns: assigns}} = ConfirmModal.update(requireds, socket) | ||
|
||
result = render_component(ConfirmModal, assigns) | ||
|
||
assert result =~ "This is the title" | ||
assert result =~ "This event will happen" | ||
assert result =~ "phx-click=\"confirm-ok\"" | ||
assert result =~ "phx-click=\"confirm-cancel\"" | ||
end | ||
|
||
test "overrides render correctly" do | ||
requireds = %{ | ||
title: "This is the title", | ||
message: "This event will happen", | ||
event_prefix: "ask", | ||
call_to_action: "Do it?" | ||
} | ||
|
||
result = render_component(ConfirmModal, requireds) | ||
|
||
assert result =~ "This is the title" | ||
assert result =~ "This event will happen" | ||
assert result =~ "phx-click=\"ask-ok\"" | ||
assert result =~ "phx-click=\"ask-cancel\"" | ||
end | ||
end | ||
|
||
defmodule LiveViewFixture do | ||
use Phoenix.LiveView | ||
|
||
def mount(_params, _session, socket) do | ||
{:ok, assign(socket, message: "None")} | ||
end | ||
|
||
def render(assigns) do | ||
~H""" | ||
<%= live_component CrunchBerry.Components.ConfirmModal, | ||
title: "Re-upload CSV", | ||
message: "This will clear the current session, and replace it with a new csv file." %> | ||
<div> | ||
click: <%= @message %> | ||
</div> | ||
""" | ||
end | ||
|
||
def handle_event(event, _params, socket) do | ||
{:noreply, assign(socket, message: event)} | ||
end | ||
end | ||
|
||
describe "events" do | ||
test "ok click", %{conn: conn} do | ||
{:ok, view, html} = live_isolated(conn, LiveViewFixture) | ||
assert html =~ "click: None" | ||
|
||
click_html = | ||
view | ||
|> element("button", "Ok") | ||
|> render_click() | ||
|
||
assert click_html =~ "click: confirm-ok" | ||
end | ||
|
||
test "cancel click, %", %{conn: conn} do | ||
{:ok, view, html} = live_isolated(conn, LiveViewFixture) | ||
assert html =~ "click: None" | ||
|
||
click_html = | ||
view | ||
|> element("button", "Cancel") | ||
|> render_click() | ||
|
||
assert click_html =~ "click: confirm-cancel" | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
defmodule CrunchBerry.TestEndpoint do | ||
@moduledoc """ | ||
Fake endpoint for the purposes of running tests | ||
""" | ||
use Phoenix.Endpoint, otp_app: :crunch_berry | ||
end |