Skip to content

Commit 3c9ba41

Browse files
authored
Use prima modal in ip_rules settings (#5910)
* Use prima modal in ip_rules settings * Remove unused alias * Do not render portal in test environment - fixes tests * Simplify invitation modal tests * Bump CI cache version to rebuild with prima 0.2.1 The CI was using cached dependencies with prima 0.1.9, which doesn't support the portal parameter needed for tests. Bumping the cache version forces a rebuild with the correct prima 0.2.1 from mix.lock. * CI debugging * Use correct mix env * Resolve mix.env() at compile-time
1 parent 111a8b9 commit 3c9ba41

9 files changed

Lines changed: 69 additions & 87 deletions

File tree

.github/workflows/elixir.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ concurrency:
1111
cancel-in-progress: true
1212

1313
env:
14-
CACHE_VERSION: v15
14+
CACHE_VERSION: v16
1515
PERSISTENT_CACHE_DIR: cached
1616

1717
jobs:

lib/plausible_web/live/components/prima_modal.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ defmodule PlausibleWeb.Live.Components.PrimaModal do
44
alias Prima.Modal
55

66
attr :id, :string, required: true
7+
attr :use_portal?, :boolean, default: Mix.env() not in [:test, :ce_test]
78
slot :inner_block, required: true
89

910
def modal(assigns) do
1011
~H"""
11-
<Modal.modal id={@id}>
12+
<Modal.modal portal={@use_portal?} id={@id}>
1213
<Modal.modal_overlay
1314
transition_enter={{"ease-out duration-300", "opacity-0", "opacity-100"}}
1415
transition_leave={{"ease-in duration-200", "opacity-100", "opacity-0"}}

lib/plausible_web/live/shields/ip_rules.ex

Lines changed: 57 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule PlausibleWeb.Live.Shields.IPRules do
55

66
use PlausibleWeb, :live_component
77

8-
alias PlausibleWeb.Live.Components.Modal
8+
alias PlausibleWeb.Live.Components.PrimaModal
99
alias Plausible.Shields
1010
alias Plausible.Shield
1111

@@ -50,9 +50,7 @@ defmodule PlausibleWeb.Live.Shields.IPRules do
5050
<.button
5151
:if={@ip_rules_count < Shields.maximum_ip_rules()}
5252
id="add-ip-rule"
53-
x-data
54-
x-on:click={Modal.JS.open("ip-rule-form-modal")}
55-
class="mt-4"
53+
phx-click={Prima.Modal.JS.open("ip-rule-form-modal")}
5654
>
5755
Add IP address
5856
</.button>
@@ -61,8 +59,7 @@ defmodule PlausibleWeb.Live.Shields.IPRules do
6159
<.filter_bar :if={@ip_rules_count < Shields.maximum_ip_rules()} filtering_enabled?={false}>
6260
<.button
6361
id="add-ip-rule"
64-
x-data
65-
x-on:click={Modal.JS.open("ip-rule-form-modal")}
62+
phx-click={Prima.Modal.JS.open("ip-rule-form-modal")}
6663
mt?={false}
6764
>
6865
Add IP address
@@ -139,50 +136,63 @@ defmodule PlausibleWeb.Live.Shields.IPRules do
139136
</div>
140137
<% end %>
141138
142-
<.live_component module={Modal} id="ip-rule-form-modal">
143-
<.form
144-
:let={f}
145-
for={@form}
146-
phx-submit="save-ip-rule"
147-
phx-target={@myself}
148-
class="max-w-md w-full mx-auto"
149-
>
150-
<.title>Add IP to block list</.title>
151-
152-
<div class="mt-4">
153-
<p
154-
:if={not ip_rule_present?(@ip_rules, @remote_ip)}
155-
class="text-sm text-gray-500 dark:text-gray-400 mb-4"
139+
<PrimaModal.modal id="ip-rule-form-modal">
140+
<div class="p-5 sm:p-6 max-w-md">
141+
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
142+
<button
143+
phx-click={Prima.Modal.JS.close()}
144+
class="text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400"
156145
>
157-
Your current IP address is: <span class="font-mono"><%= @remote_ip %></span>.
158-
<.styled_link phx-target={@myself} phx-click="prefill-own-ip-rule">
159-
Click here
160-
</.styled_link>
161-
to block your own traffic, or enter a custom address below.
162-
</p>
163-
164-
<.input
165-
autofocus
166-
field={f[:inet]}
167-
label="IP address"
168-
placeholder="e.g. 192.168.127.12"
169-
/>
146+
<span class="sr-only">Close</span>
147+
<Heroicons.x_mark class="size-6" />
148+
</button>
170149
</div>
150+
<div class="flex flex-col gap-y-4 text-center sm:text-left">
151+
<PrimaModal.modal_title>
152+
Add IP to block list
153+
</PrimaModal.modal_title>
154+
<.form
155+
:let={f}
156+
for={@form}
157+
phx-submit="save-ip-rule"
158+
phx-target={@myself}
159+
>
160+
<div>
161+
<p
162+
:if={not ip_rule_present?(@ip_rules, @remote_ip)}
163+
class="text-sm text-gray-500 dark:text-gray-400 mb-4"
164+
>
165+
Your current IP address is: <span class="font-mono"><%= @remote_ip %></span>.
166+
<.styled_link phx-target={@myself} phx-click="prefill-own-ip-rule">
167+
Click here
168+
</.styled_link>
169+
to block your own traffic, or enter a custom address below.
170+
</p>
171171
172-
<.input
173-
field={f[:description]}
174-
label="Description (optional)"
175-
placeholder="e.g. The Office"
176-
/>
172+
<.input
173+
data-autofocus
174+
field={f[:inet]}
175+
label="IP address"
176+
placeholder="e.g. 192.168.127.12"
177+
/>
178+
</div>
177179
178-
<p class="mt-4 text-sm text-gray-500 dark:text-gray-400">
179-
Once added, we will start rejecting traffic from this IP within a few minutes.
180-
</p>
181-
<.button type="submit" class="w-full">
182-
Add IP address
183-
</.button>
184-
</.form>
185-
</.live_component>
180+
<.input
181+
field={f[:description]}
182+
label="Description (optional)"
183+
placeholder="e.g. The Office"
184+
/>
185+
186+
<p class="mt-4 text-sm text-gray-500 dark:text-gray-400">
187+
Once added, we will start rejecting traffic from this IP within a few minutes.
188+
</p>
189+
<.button type="submit" class="w-full">
190+
Add IP address
191+
</.button>
192+
</.form>
193+
</div>
194+
</div>
195+
</PrimaModal.modal>
186196
</.tile>
187197
</.settings_tiles>
188198
</div>
@@ -212,7 +222,7 @@ defmodule PlausibleWeb.Live.Shields.IPRules do
212222
{:ok, rule} ->
213223
socket =
214224
socket
215-
|> Modal.close("ip-rule-form-modal")
225+
|> Prima.Modal.push_close("ip-rule-form-modal")
216226
|> assign(
217227
form: new_form(),
218228
ip_rules: [rule | socket.assigns.ip_rules],

lib/plausible_web/live/sites.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ defmodule PlausibleWeb.Live.Sites do
498498
class="group relative cursor-pointer"
499499
id={"site-card-#{hash_domain(@site.domain)}"}
500500
data-domain={@site.domain}
501-
phx-click={Prima.Modal.open(@modal_id)}
501+
phx-click={Prima.Modal.JS.open(@modal_id)}
502502
>
503503
<div class="col-span-1 flex flex-col gap-y-5 bg-white dark:bg-gray-900 rounded-md shadow-sm p-6 group-hover:shadow-lg cursor-pointer transition duration-100">
504504
<div class="w-full flex items-center justify-between gap-x-2.5">
@@ -730,7 +730,7 @@ defmodule PlausibleWeb.Live.Sites do
730730
<div class="p-5 pb-3 sm:p-6 sm:pb-3">
731731
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
732732
<button
733-
phx-click={Prima.Modal.close()}
733+
phx-click={Prima.Modal.JS.close()}
734734
class="text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400"
735735
>
736736
<span class="sr-only">Close</span>

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ defmodule Plausible.MixProject do
114114
{:phoenix_live_view, "~> 1.1"},
115115
{:php_serializer, "~> 2.0"},
116116
{:plug, "~> 1.13", override: true},
117-
{:prima, "~> 0.1.8"},
117+
{:prima, "~> 0.2.1"},
118118
{:plug_cowboy, "~> 2.3"},
119119
{:polymorphic_embed, "~> 5.0"},
120120
{:postgrex, "~> 0.19.0"},

mix.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135
"plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"},
136136
"polymorphic_embed": {:hex, :polymorphic_embed, "5.0.3", "37444e0af941026a2c29b0539b6471bdd6737a6492a19264bf2bb0118e3ac242", [:mix], [{:attrs, "~> 0.6", [hex: :attrs, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_html_helpers, "~> 1.0", [hex: :phoenix_html_helpers, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}], "hexpm", "2fed44f57abf0a0fc7642e0eb0807a55b65de1562712cc0620772cbbb80e49c1"},
137137
"postgrex": {:hex, :postgrex, "0.19.3", "a0bda6e3bc75ec07fca5b0a89bffd242ca209a4822a9533e7d3e84ee80707e19", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d31c28053655b78f47f948c85bb1cf86a9c1f8ead346ba1aa0d0df017fa05b61"},
138-
"prima": {:hex, :prima, "0.1.9", "34868e3570cf2c4fac42d6254e33678e9d75a8fe3d3253a38ee437f6481a2896", [:mix], [{:esbuild, "~> 0.7", [hex: :esbuild, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "7f24efb617dd94da867bf2d362eeab846897270eff989aeaa261f04590feae3f"},
138+
"prima": {:hex, :prima, "0.2.1", "337d9ee0cc3a09115ba9969d4bb592c0c4b56a6826a039ad890b4dc3c03ffb80", [:mix], [{:esbuild, "~> 0.7", [hex: :esbuild, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "bc5e2b34986d66206720c5a14fa148f77c8c2dc1fec60260923053568e91d634"},
139139
"prom_ex": {:hex, :prom_ex, "1.11.0", "1f6d67f2dead92224cb4f59beb3e4d319257c5728d9638b4a5e8ceb51a4f9c7e", [:mix], [{:absinthe, ">= 1.7.0", [hex: :absinthe, repo: "hexpm", optional: true]}, {:broadway, ">= 1.1.0", [hex: :broadway, repo: "hexpm", optional: true]}, {:ecto, ">= 3.11.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:finch, "~> 0.18", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, ">= 2.10.0", [hex: :oban, repo: "hexpm", optional: true]}, {:octo_fetch, "~> 0.4", [hex: :octo_fetch, repo: "hexpm", optional: false]}, {:peep, "~> 3.0", [hex: :peep, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, ">= 0.20.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, ">= 1.16.0", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 2.6.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, ">= 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.2", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.1", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "76b074bc3730f0802978a7eb5c7091a65473eaaf07e99ec9e933138dcc327805"},
140140
"public_suffix": {:git, "https://github.com/axelson/publicsuffix-elixir", "fa40c243d4b5d8598b90cff268bc4e33f3bb63f1", []},
141141
"ranch": {:hex, :ranch, "1.8.1", "208169e65292ac5d333d6cdbad49388c1ae198136e4697ae2f474697140f201c", [:make, :rebar3], [], "hexpm", "aed58910f4e21deea992a67bf51632b6d60114895eb03bb392bb733064594dd0"},

test/plausible_web/live/shields/ip_addresses_test.exs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,7 @@ defmodule PlausibleWeb.Live.Shields.IPAddressesTest do
4545
conn = get(conn, "/#{site.domain}/settings/shields/ip_addresses")
4646
resp = html_response(conn, 200)
4747

48-
assert element_exists?(resp, ~s/button#add-ip-rule[x-data]/)
49-
attr = text_of_attr(resp, ~s/button#add-ip-rule/, "x-on:click")
50-
51-
assert attr =~ "open-modal"
52-
assert attr =~ "ip-rule-form-modal"
48+
assert element_exists?(resp, ~s/button#add-ip-rule/)
5349
end
5450

5551
test "add rule button is not rendered when maximum reached", %{conn: conn, site: site} do

test/plausible_web/live/sites_test.exs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,7 @@ defmodule PlausibleWeb.Live.SitesTest do
104104

105105
{:ok, _lv, html} = live(conn, "/sites")
106106

107-
template = find_portal_template(html, "#invitation-modal-#{transfer.transfer_id}")
108-
109-
assert text(template) =~
107+
assert text_of_element(html, "#invitation-modal-#{transfer.transfer_id}") =~
110108
"You are unable to accept the ownership of this site because your account does not have a subscription"
111109
end
112110

@@ -203,9 +201,8 @@ defmodule PlausibleWeb.Live.SitesTest do
203201

204202
{:ok, _lv, html} = live(conn, "/sites")
205203

206-
template = find_portal_template(html, "#invitation-modal-#{transfer.transfer_id}")
207-
208-
assert text(template) =~ "Owning this site would exceed your site limit"
204+
assert text_of_element(html, "#invitation-modal-#{transfer.transfer_id}") =~
205+
"Owning this site would exceed your site limit"
209206
end
210207

211208
@tag :ee_only
@@ -222,9 +219,7 @@ defmodule PlausibleWeb.Live.SitesTest do
222219

223220
{:ok, _lv, html} = live(conn, "/sites")
224221

225-
template = find_portal_template(html, "#invitation-modal-#{transfer.transfer_id}")
226-
227-
assert text(template) =~
222+
assert text_of_element(html, "#invitation-modal-#{transfer.transfer_id}") =~
228223
"The site uses Custom Properties, which your current subscription does not support"
229224
end
230225

test/support/html.ex

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -81,26 +81,6 @@ defmodule Plausible.Test.Support.HTML do
8181
text_of_attr(element, "name")
8282
end
8383

84-
@doc """
85-
When using liveview <.portal> element, it renders a <template> that gets rendered into DOM
86-
by JS. In order to make assertions about portal contents, we need to find the <template> element
87-
and get its contents. Unfortunately <template> elements are not treated like standard elements by LazyHTML.
88-
Functions like LazyHTML.text() or LazyHTML.query() return nothing for <template> elements. So this function tricks LazyHTML by:
89-
1. Finding the template element
90-
2. Transforming it into a <div> so it can be used like a normal LazyHTML node
91-
)
92-
"""
93-
def find_portal_template(html, id) do
94-
template_id = id <> "-portal"
95-
96-
[{"template", attrs, children}] =
97-
lazy_parse(html)
98-
|> find(template_id)
99-
|> LazyHTML.to_tree()
100-
101-
LazyHTML.from_tree([{"div", attrs, children}])
102-
end
103-
10484
defp lazy_parse(%LazyHTML{} = lazy) do
10585
lazy
10686
end

0 commit comments

Comments
 (0)