diff --git a/elixir/apps/web/lib/web/live/policies/index.ex b/elixir/apps/web/lib/web/live/policies/index.ex
index 08156bc34..fa323dd7c 100644
--- a/elixir/apps/web/lib/web/live/policies/index.ex
+++ b/elixir/apps/web/lib/web/live/policies/index.ex
@@ -9,6 +9,7 @@ defmodule Web.Policies.Index do
socket =
socket
+ |> assign(stale: false)
|> assign(page_title: "Policies")
|> assign_live_table("policies",
query_module: Policies.Policy.Query,
@@ -64,6 +65,7 @@ defmodule Web.Policies.Index do
<:content>
<.flash_group flash={@flash} />
<.live_table
+ stale={@stale}
id="policies"
rows={@policies}
row_id={&"policies-#{&1.id}"}
@@ -117,28 +119,11 @@ defmodule Web.Policies.Index do
"""
end
- def handle_event(event, params, socket) when event in ["paginate", "order_by", "filter"],
- do: handle_live_table_event(event, params, socket)
-
- def handle_info({:create_policy, _policy_id}, socket) do
- {:noreply, socket}
- end
-
- def handle_info({:delete_policy, policy_id}, socket) do
- if Enum.find(socket.assigns.policies, fn policy -> policy.id == policy_id end) do
- policies =
- Enum.filter(socket.assigns.policies, fn
- policy -> policy.id != policy_id
- end)
-
- {:noreply, assign(socket, policies: policies)}
- else
- {:noreply, socket}
- end
- end
+ def handle_event(event, params, socket)
+ when event in ["paginate", "order_by", "filter", "reload"],
+ do: handle_live_table_event(event, params, socket)
def handle_info({_action, _policy_id}, socket) do
- socket = reload_live_table!(socket, "policies")
- {:noreply, socket}
+ {:noreply, assign(socket, stale: true)}
end
end
diff --git a/elixir/apps/web/lib/web/live/resources/index.ex b/elixir/apps/web/lib/web/live/resources/index.ex
index d98f590b8..9bbfcc106 100644
--- a/elixir/apps/web/lib/web/live/resources/index.ex
+++ b/elixir/apps/web/lib/web/live/resources/index.ex
@@ -15,6 +15,7 @@ defmodule Web.Resources.Index do
socket =
socket
+ |> assign(stale: false)
|> assign(page_title: "Resources")
|> assign(internet_site: internet_site)
|> assign_live_table("resources",
@@ -87,6 +88,7 @@ defmodule Web.Resources.Index do
<:content>
<.flash_group flash={@flash} />
<.live_table
+ stale={@stale}
id="resources"
rows={@resources}
row_id={&"resource-#{&1.id}"}
@@ -161,27 +163,11 @@ defmodule Web.Resources.Index do
"""
end
- def handle_event(event, params, socket) when event in ["paginate", "order_by", "filter"],
- do: handle_live_table_event(event, params, socket)
-
- def handle_info({:create_resource, _resource_id}, socket) do
- {:noreply, socket}
- end
-
- def handle_info({:delete_resource, resource_id}, socket) do
- if Enum.find(socket.assigns.policies, fn resource -> resource.id == resource_id end) do
- policies =
- Enum.filter(socket.assigns.policies, fn resource ->
- resource.id != resource_id
- end)
-
- {:noreply, assign(socket, policies: policies)}
- else
- {:noreply, socket}
- end
- end
+ def handle_event(event, params, socket)
+ when event in ["paginate", "order_by", "filter", "reload"],
+ do: handle_live_table_event(event, params, socket)
def handle_info({_action, _resource_id}, socket) do
- {:noreply, reload_live_table!(socket, "resources")}
+ {:noreply, assign(socket, stale: true)}
end
end
diff --git a/elixir/apps/web/lib/web/live_table.ex b/elixir/apps/web/lib/web/live_table.ex
index 450974ef2..f5f655551 100644
--- a/elixir/apps/web/lib/web/live_table.ex
+++ b/elixir/apps/web/lib/web/live_table.ex
@@ -15,6 +15,7 @@ defmodule Web.LiveTable do
attr :ordered_by, :any, required: true, doc: "the current order for the table"
attr :filters, :list, required: true, doc: "the query filters enabled for the table"
attr :filter, :map, required: true, doc: "the filter form for the table"
+ attr :stale, :boolean, default: false, doc: "hint to the UI that the table data is stale"
attr :metadata, :map,
required: true,
@@ -40,7 +41,7 @@ defmodule Web.LiveTable do
def live_table(assigns) do
~H"""
- <.resource_filter live_table_id={@id} form={@filter} filters={@filters} />
+ <.resource_filter stale={@stale} live_table_id={@id} form={@filter} filters={@filters} />
<.table_header table_id={@id} columns={@col} actions={@action} ordered_by={@ordered_by} />
@@ -152,7 +153,21 @@ defmodule Web.LiveTable do
>
<.input type="hidden" name="table_id" value={@live_table_id} />
-
+
+
+ <.button
+ :if={@stale}
+ id={"#{@live_table_id}-reload-btn"}
+ type="button"
+ style="info"
+ title="The table data has changed."
+ phx-click="reload"
+ phx-value-table_id={@live_table_id}
+ >
+ <.icon name="hero-arrow-path" class="mr-1 w-3.5 h-3.5" /> Reload
+
+
+
<.filter
:for={filter <- @filters}
live_table_id={@live_table_id}
@@ -536,6 +551,8 @@ defmodule Web.LiveTable do
callback = Map.fetch!(socket.assigns.callback_by_table_id, id)
list_opts = Map.get(socket.assigns[:list_opts_by_table_id] || %{}, id, [])
+ socket = assign(socket, stale: false)
+
case callback.(socket, list_opts) do
{:error, _reason} ->
uri = URI.parse(socket.assigns.uri)
@@ -776,6 +793,10 @@ defmodule Web.LiveTable do
end
end
+ def handle_live_table_event("reload", %{"table_id" => id}, socket) do
+ {:noreply, reload_live_table!(socket, id)}
+ end
+
def handle_live_table_event("paginate", %{"table_id" => id, "cursor" => cursor}, socket) do
update_query_params(socket, fn query_params ->
put_cursor_to_params(query_params, id, cursor)
diff --git a/elixir/apps/web/test/web/live/policies/index_test.exs b/elixir/apps/web/test/web/live/policies/index_test.exs
index ec66ffdc8..78398eb69 100644
--- a/elixir/apps/web/test/web/live/policies/index_test.exs
+++ b/elixir/apps/web/test/web/live/policies/index_test.exs
@@ -77,4 +77,55 @@ defmodule Web.Live.Policies.IndexTest do
assert rendered_policy["group"] =~ policy.actor_group.name
assert rendered_policy["resource"] =~ policy.resource.name
end
+
+ describe "handle_info/2" do
+ test "Shows reload button when policy is created", %{
+ account: account,
+ identity: identity,
+ conn: conn
+ } do
+ {:ok, lv, html} =
+ conn
+ |> authorize_conn(identity)
+ |> live(~p"/#{account}/policies")
+
+ refute html =~ "The table data has changed."
+ refute html =~ "reload-btn"
+
+ Fixtures.Policies.create_policy(account: account, description: "foo bar")
+
+ reload_btn =
+ lv
+ |> element("#policies-reload-btn")
+ |> render()
+
+ assert reload_btn
+ end
+
+ test "Shows reload button when policy is deleted", %{
+ account: account,
+ identity: identity,
+ conn: conn
+ } do
+ policy = Fixtures.Policies.create_policy(account: account, description: "foo bar")
+ subject = Fixtures.Auth.create_subject(identity: identity)
+
+ {:ok, lv, html} =
+ conn
+ |> authorize_conn(identity)
+ |> live(~p"/#{account}/policies")
+
+ refute html =~ "The table data has changed."
+ refute html =~ "reload-btn"
+
+ Domain.Policies.delete_policy(policy, subject)
+
+ reload_btn =
+ lv
+ |> element("#policies-reload-btn")
+ |> render()
+
+ assert reload_btn
+ end
+ end
end
diff --git a/elixir/apps/web/test/web/live/resources/index_test.exs b/elixir/apps/web/test/web/live/resources/index_test.exs
index 3efddacf3..a057918fb 100644
--- a/elixir/apps/web/test/web/live/resources/index_test.exs
+++ b/elixir/apps/web/test/web/live/resources/index_test.exs
@@ -205,4 +205,55 @@ defmodule Web.Live.Resources.IndexTest do
assert row["authorized groups"] =~ "and 1 more"
end)
end
+
+ describe "handle_info/2" do
+ test "Shows reload button when resource is created", %{
+ account: account,
+ identity: identity,
+ conn: conn
+ } do
+ {:ok, lv, html} =
+ conn
+ |> authorize_conn(identity)
+ |> live(~p"/#{account}/resources")
+
+ refute html =~ "The table data has changed."
+ refute html =~ "reload-btn"
+
+ Fixtures.Resources.create_resource(account: account)
+
+ reload_btn =
+ lv
+ |> element("#resources-reload-btn")
+ |> render()
+
+ assert reload_btn
+ end
+
+ test "Shows reload button when resource is deleted", %{
+ account: account,
+ identity: identity,
+ conn: conn
+ } do
+ resource = Fixtures.Resources.create_resource(account: account)
+ subject = Fixtures.Auth.create_subject(identity: identity)
+
+ {:ok, lv, html} =
+ conn
+ |> authorize_conn(identity)
+ |> live(~p"/#{account}/resources")
+
+ refute html =~ "The table data has changed."
+ refute html =~ "reload-btn"
+
+ Domain.Resources.delete_resource(resource, subject)
+
+ reload_btn =
+ lv
+ |> element("#resources-reload-btn")
+ |> render()
+
+ assert reload_btn
+ end
+ end
end