defmodule FreediveWeb.ServiceLive do use FreediveWeb.LiliformLive alias Freedive.Api.Service require Logger def render(assigns) do ~H""" <.page name="Services" filters={@filters} details={@details}> """ end def on_mount_connected(socket) do Logger.warning("Mounting ServiceLive") Service.subscribe() {:ok, socket} end def items() do Service.list() end def filters() do [ %{ title: "Running", key: :running, icon: "circle-play", active: true }, %{ title: "Enabled", key: :enabled, icon: "circle-check", active: false } ] end def search(items, query) do items |> Enum.filter(fn {name, _item} -> String.contains?(String.downcase(name), String.downcase(query)) end) |> Enum.into(%{}, fn {name, item} -> {name, item} end) end def handle_event("action:" <> action, %{"name" => service_name}, socket) when action in ["start", "stop", "restart"] do case action do "start" -> Service.start(service_name) "stop" -> Service.stop(service_name) "restart" -> Service.restart(service_name) end {:noreply, socket} end def handle_event("command:" <> command, %{"name" => service_name}, socket) do Service.command(service_name, command) {:noreply, socket} end def handle_info({event, payload}, socket) do case event do :command -> # Logger.info("ServiceLive: Command: #{inspect(payload)}") socket = if socket.assigns.selected_item && payload.name == socket.assigns.selected_item.name do socket |> assign(:selected_item, %{socket.assigns.selected_item | busy: true}) else socket end {:noreply, socket} :refreshed -> # Logger.info("ServiceLive: Refreshed: #{inspect(payload)}") socket = if socket.assigns.selected_item && payload.name == socket.assigns.selected_item.name do socket |> assign(:selected_item, %{ socket.assigns.selected_item | running: payload.running, enabled: payload.enabled, busy: false }) |> assign(:items, socket.assigns.items |> Map.put(payload.name, payload)) else socket end {:noreply, socket} :stdlog -> # Logger.info("ServiceLive: Stdlog: #{inspect(payload)}") socket = if socket.assigns.selected_item && payload.name == socket.assigns.selected_item.name do socket |> assign(:selected_item, %{ socket.assigns.selected_item | log: socket.assigns.selected_item.log ++ payload.log, busy: false }) else socket end {:noreply, socket} _ -> Logger.warning("ServiceLive: Unknown event: #{event}, payload: #{inspect(payload)}") {:noreply, socket} end end end defmodule FreediveWeb.ServiceLive.Components do use Liliform.Component import Liliform.Icon import Liliform.Panel import Liliform.Title @doc """ Returns items as panel-blocks. """ attr :items, :list, default: [], doc: "items" attr :selected_item, :string, default: nil, doc: "selected item" attr :details, :string, default: nil, doc: "details" def items_block(%{details: true} = assigns) do ~H""" <.link class="panel-block pt-1 has-background-light" phx-click="tap" phx-value-name={@selected_item.name} > <.icon for="arrow-left" aria-hidden="true" has-text-dark />
Back
<.panel_block> <%!-- <.icon_raw for={@selected_item.icon} color="auto" size="3rem" class="" aria-hidden="true" /> --%> <.icon_raw for={@selected_item.icon} color="auto" size="3rem" aria-hidden="true" />
<.title is-4> <%= @selected_item.name %> <%= if @selected_item.running do %> <.icon for="circle-play" color="lightgreen" aria-hidden="true" /> <% else %> <.icon for="circle-stop" color="gray" aria-hidden="true" /> <% end %> <%= if @selected_item.enabled do %> <.icon for="circle-check" color="lightgreen" aria-hidden="true" /> <% else %> <.icon for="circle-x" color="gray" aria-hidden="true" /> <% end %> <.subtitle> <%= @selected_item.description %>
<%= if Map.has_key?(@selected_item, :log) and @selected_item.log != [] do %> <.panel_block>
<%= Enum.join(@selected_item.log, "\n") %>
<% end %> <.panel_block_div> <%= if @selected_item.running do %> <.icon_raw for="power" color="lightgreen" size="2rem" class="ml-2 mr-5" aria-hidden="true" /> <% else %> <.icon_raw for="power" color="gray" size="2rem" class="ml-2 mr-5" aria-hidden="true" /> <% end %>
<%= if @selected_item.running do %> <% else %> <% end %>
<%= if @selected_item.commands != [] and @selected_item.commands != nil do %> <.panel_block_div> <.icon_raw for="inspection-panel" color="auto" size="2rem" class="ml-1 mr-5" aria-hidden="true" />
<%= for command <- @selected_item.commands do %> <% end %>
<% end %> """ end def items_block(assigns) do ~H""" <%= for {_name, item} <- @items do %>
<.panel_block class={"panel-block pt-3 #{if @selected_item != nil and @selected_item.name == item.name, do: "has-background-info-light"}"} phx-click="tap" phx-value-name={item.name} > <.icon_raw for={item.icon} color="auto" size="1.8rem" aria-hidden="true" /> <%!--
--%> <.subtitle class="ml-3"> <%= item.name %> <%!--
--%>
<% end %> """ end end