defmodule BDS.Desktop.ShellLive.ShellCommandRunner do @moduledoc false import Phoenix.Component, only: [assign: 3] alias BDS.Desktop.ShellCommands alias BDS.Desktop.ShellLive.{TabHelpers, TaskLocalization} alias BDS.UI.Workbench @doc """ Execute a shell command and apply its result to the socket. `callbacks` requires: * `:reload` — `(socket, workbench -> socket)` * `:append_output` — `(socket, title, message, details, level -> socket)` """ def execute(socket, action, params \\ %{}, callbacks) do case ShellCommands.execute(action, params) do {:ok, result} -> apply_result(socket, result, callbacks) {:error, %{message: message}} -> callbacks.append_output.(socket, TaskLocalization.command_title(action), message, nil, "error") {:error, reason} -> callbacks.append_output.(socket, TaskLocalization.command_title(action), inspect(reason), nil, "error") end end def apply_result(socket, %{kind: "task_queued", title: title, message: message, panel_tab: panel_tab}, callbacks) do workbench = socket.assigns.workbench |> Workbench.set_panel_visible(true) |> Workbench.set_panel_tab(String.to_existing_atom(panel_tab)) socket |> callbacks.append_output.( TaskLocalization.translate_for_socket(socket, title), TaskLocalization.translate_for_socket(socket, message), nil, "info" ) |> callbacks.reload.(workbench) end def apply_result(socket, %{kind: "output", title: title, message: message} = result, callbacks) do callbacks.append_output.( socket, TaskLocalization.translate_for_socket(socket, title), TaskLocalization.translate_for_socket(socket, message), Map.get(result, :details), Map.get(result, :level, "info") ) end def apply_result(socket, %{kind: "open_url", title: title, message: message, url: url}, callbacks) do callbacks.append_output.( socket, TaskLocalization.translate_for_socket(socket, title), TaskLocalization.translate_for_socket(socket, message), url, "info" ) end def apply_result(socket, %{kind: "open_editor", route: route, title: title, subtitle: subtitle} = result, callbacks) do route_atom = String.to_existing_atom(route) tab_id = TabHelpers.tab_id_for_route(route_atom, route) workbench = Workbench.open_tab(socket.assigns.workbench, route_atom, tab_id, :pin) tab_meta = Map.put(socket.assigns.tab_meta, {route_atom, tab_id}, %{ title: TaskLocalization.translate_for_socket(socket, title), subtitle: TaskLocalization.translate_for_socket(socket, subtitle), action: Map.get(result, :action), payload: Map.get(result, :payload), project_id: Map.get(result, :project_id), editor_meta: TaskLocalization.translate_editor_meta(Map.get(result, :editorMeta, []), socket.assigns.page_language) }) socket |> assign(:tab_meta, tab_meta) |> callbacks.reload.(workbench) end def apply_result(socket, _result, _callbacks), do: socket def safe_existing_atom(action) when is_binary(action) do String.to_existing_atom(action) rescue ArgumentError -> nil end def safe_existing_atom(_), do: nil end