From b49b7c954c891d0f5132cd042a91f5eb01f24ac5 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 22 Mar 2025 22:14:30 +0200 Subject: [PATCH] Add LiveViews for DBI Servers. --- .../metadata/dbi_server.ex | 12 +- .../live/dbi_server_live/form_component.ex | 83 +++++++++++++ .../live/dbi_server_live/index.ex | 116 ++++++++++++++++++ .../live/dbi_server_live/show.ex | 65 ++++++++++ lib/decentralised_book_index_web/router.ex | 7 ++ 5 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 lib/decentralised_book_index_web/live/dbi_server_live/form_component.ex create mode 100644 lib/decentralised_book_index_web/live/dbi_server_live/index.ex create mode 100644 lib/decentralised_book_index_web/live/dbi_server_live/show.ex diff --git a/lib/decentralised_book_index/metadata/dbi_server.ex b/lib/decentralised_book_index/metadata/dbi_server.ex index f877ff7..c01bddd 100644 --- a/lib/decentralised_book_index/metadata/dbi_server.ex +++ b/lib/decentralised_book_index/metadata/dbi_server.ex @@ -10,7 +10,17 @@ defmodule DecentralisedBookIndex.Metadata.DBIServer do end actions do - defaults [:read] + defaults [:read, :destroy] + + create :create do + primary? true + accept [:name, :url] + end + + update :update do + primary? true + accept [:name, :url] + end end attributes do diff --git a/lib/decentralised_book_index_web/live/dbi_server_live/form_component.ex b/lib/decentralised_book_index_web/live/dbi_server_live/form_component.ex new file mode 100644 index 0000000..3d194eb --- /dev/null +++ b/lib/decentralised_book_index_web/live/dbi_server_live/form_component.ex @@ -0,0 +1,83 @@ +defmodule DecentralisedBookIndexWeb.DbiServerLive.FormComponent do + use DecentralisedBookIndexWeb, :live_component + + @impl true + def render(assigns) do + ~H""" +
+ <.header> + {@title} + <:subtitle>Use this form to manage servers records in your database. + + + <.simple_form + for={@form} + id="dbi_server-form" + phx-target={@myself} + phx-change="validate" + phx-submit="save" + > + <.input field={@form[:name]} type="text" label="Name" /><.input + field={@form[:url]} + type="text" + label="Url" + /> + + <:actions> + <.button phx-disable-with="Saving...">Save server + + +
+ """ + end + + @impl true + def update(assigns, socket) do + {:ok, + socket + |> assign(assigns) + |> assign_form()} + end + + @impl true + def handle_event("validate", %{"dbi_server" => dbi_server_params}, socket) do + {:noreply, + assign(socket, form: AshPhoenix.Form.validate(socket.assigns.form, dbi_server_params))} + end + + def handle_event("save", %{"dbi_server" => dbi_server_params}, socket) do + case AshPhoenix.Form.submit(socket.assigns.form, params: dbi_server_params) do + {:ok, dbi_server} -> + notify_parent({:saved, dbi_server}) + + socket = + socket + |> put_flash(:info, "Server #{socket.assigns.form.source.type}d successfully") + |> push_patch(to: socket.assigns.patch) + + {:noreply, socket} + + {:error, form} -> + {:noreply, assign(socket, form: form)} + end + end + + defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) + + defp assign_form(%{assigns: %{dbi_server: dbi_server}} = socket) do + form = + if dbi_server do + AshPhoenix.Form.for_update(dbi_server, :update, + as: "dbi_server", + actor: socket.assigns.current_user + ) + else + AshPhoenix.Form.for_create(DecentralisedBookIndex.Metadata.DBIServer, :create, + as: "dbi_server", + actor: socket.assigns.current_user + ) + end + + assign(socket, form: to_form(form)) + end +end diff --git a/lib/decentralised_book_index_web/live/dbi_server_live/index.ex b/lib/decentralised_book_index_web/live/dbi_server_live/index.ex new file mode 100644 index 0000000..38cbf6f --- /dev/null +++ b/lib/decentralised_book_index_web/live/dbi_server_live/index.ex @@ -0,0 +1,116 @@ +defmodule DecentralisedBookIndexWeb.DbiServerLive.Index do + use DecentralisedBookIndexWeb, :live_view + + @impl true + def render(assigns) do + ~H""" + <.header> + Listing servers + <:actions> + <.link patch={~p"/servers/new"}> + <.button>New server + + + + + <.table + id="dbi_servers" + rows={@streams.dbi_servers} + row_click={fn {_id, dbi_server} -> JS.navigate(~p"/servers/#{dbi_server}") end} + > + <:col :let={{_id, dbi_server}} label="Name">{dbi_server.name} + + <:col :let={{_id, dbi_server}} label="Url">{dbi_server.url} + + <:action :let={{_id, dbi_server}}> +
+ <.link navigate={~p"/servers/#{dbi_server}"}>Show +
+ + <.link patch={~p"/servers/#{dbi_server}/edit"}>Edit + + + <:action :let={{id, dbi_server}}> + <.link + phx-click={JS.push("delete", value: %{id: dbi_server.id}) |> hide("##{id}")} + data-confirm="Are you sure?" + > + Delete + + + + + <.modal + :if={@live_action in [:new, :edit]} + id="dbi_server-modal" + show + on_cancel={JS.patch(~p"/servers")} + > + <.live_component + module={DecentralisedBookIndexWeb.DbiServerLive.FormComponent} + id={(@dbi_server && @dbi_server.id) || :new} + title={@page_title} + current_user={@current_user} + action={@live_action} + dbi_server={@dbi_server} + patch={~p"/servers"} + /> + + """ + end + + @impl true + def mount(_params, _session, socket) do + {:ok, + socket + |> stream( + :dbi_servers, + Ash.read!(DecentralisedBookIndex.Metadata.DBIServer, actor: socket.assigns[:current_user]) + ) + |> assign_new(:current_user, fn -> nil end)} + end + + @impl true + def handle_params(params, _url, socket) do + {:noreply, apply_action(socket, socket.assigns.live_action, params)} + end + + defp apply_action(socket, :edit, %{"id" => id}) do + socket + |> assign(:page_title, "Edit server") + |> assign( + :dbi_server, + Ash.get!(DecentralisedBookIndex.Metadata.DBIServer, id, actor: socket.assigns.current_user) + ) + end + + defp apply_action(socket, :new, _params) do + socket + |> assign(:page_title, "New server") + |> assign(:dbi_server, nil) + end + + defp apply_action(socket, :index, _params) do + socket + |> assign(:page_title, "Listing servers") + |> assign(:dbi_server, nil) + end + + @impl true + def handle_info( + {DecentralisedBookIndexWeb.DbiServerLive.FormComponent, {:saved, dbi_server}}, + socket + ) do + {:noreply, stream_insert(socket, :dbi_servers, dbi_server)} + end + + @impl true + def handle_event("delete", %{"id" => id}, socket) do + dbi_server = + Ash.get!(DecentralisedBookIndex.Metadata.DBIServer, id, actor: socket.assigns.current_user) + + Ash.destroy!(dbi_server, actor: socket.assigns.current_user) + + {:noreply, stream_delete(socket, :dbi_servers, dbi_server)} + end +end diff --git a/lib/decentralised_book_index_web/live/dbi_server_live/show.ex b/lib/decentralised_book_index_web/live/dbi_server_live/show.ex new file mode 100644 index 0000000..5548ca6 --- /dev/null +++ b/lib/decentralised_book_index_web/live/dbi_server_live/show.ex @@ -0,0 +1,65 @@ +defmodule DecentralisedBookIndexWeb.DbiServerLive.Show do + use DecentralisedBookIndexWeb, :live_view + + @impl true + def render(assigns) do + ~H""" + <.header> + Dbi server {@dbi_server.id} + <:subtitle>This is a dbi_server record from your database. + + <:actions> + <.link patch={~p"/dbi_servers/#{@dbi_server}/show/edit"} phx-click={JS.push_focus()}> + <.button>Edit dbi_server + + + + + <.list> + <:item title="Id">{@dbi_server.id} + + <:item title="Name">{@dbi_server.name} + + <:item title="Url">{@dbi_server.url} + + + <.back navigate={~p"/dbi_servers"}>Back to dbi_servers + + <.modal + :if={@live_action == :edit} + id="dbi_server-modal" + show + on_cancel={JS.patch(~p"/dbi_servers/#{@dbi_server}")} + > + <.live_component + module={DecentralisedBookIndexWeb.DbiServerLive.FormComponent} + id={@dbi_server.id} + title={@page_title} + action={@live_action} + current_user={@current_user} + dbi_server={@dbi_server} + patch={~p"/dbi_servers/#{@dbi_server}"} + /> + + """ + end + + @impl true + def mount(_params, _session, socket) do + {:ok, socket} + end + + @impl true + def handle_params(%{"id" => id}, _, socket) do + {:noreply, + socket + |> assign(:page_title, page_title(socket.assigns.live_action)) + |> assign( + :dbi_server, + Ash.get!(DecentralisedBookIndex.Metadata.DBIServer, id, actor: socket.assigns.current_user) + )} + end + + defp page_title(:show), do: "Show Dbi server" + defp page_title(:edit), do: "Edit Dbi server" +end diff --git a/lib/decentralised_book_index_web/router.ex b/lib/decentralised_book_index_web/router.ex index 9053f38..eb14164 100644 --- a/lib/decentralised_book_index_web/router.ex +++ b/lib/decentralised_book_index_web/router.ex @@ -58,6 +58,13 @@ defmodule DecentralisedBookIndexWeb.Router do live "/publishers/:id", PublisherLive.Show, :show live "/publishers/:id/show/edit", PublisherLive.Show, :edit + live "/servers", DbiServerLive.Index, :index + live "/servers/new", DbiServerLive.Index, :new + live "/servers/:id/edit", DbiServerLive.Index, :edit + + live "/servers/:id", DbiServerLive.Show, :show + live "/servers/:id/show/edit", DbiServerLive.Show, :edit + ash_authentication_live_session :authenticated_routes do # in each liveview, add one of the following at the top of the module: #