defmodule ToweropsWeb.CheckLive.FormComponent do @moduledoc false use ToweropsWeb, :live_component alias Towerops.Monitoring @impl true def render(assigns) do ~H"""
<.form for={@form} id="check-form" phx-target={@myself} phx-change="validate" phx-submit="save" >

Add Service Check

<.input field={@form[:check_type]} type="select" options={[ {"HTTP/HTTPS Check", "http"}, {"TCP Port Check", "tcp"}, {"DNS Check", "dns"} ]} phx-change="change_type" phx-target={@myself} />
<.input field={@form[:name]} type="text" label="Check Name" placeholder="e.g., Web Server Check" />
<%= case @selected_type do %> <% "http" -> %> {render_http_fields(assigns)} <% "tcp" -> %> {render_tcp_fields(assigns)} <% "dns" -> %> {render_dns_fields(assigns)} <% _ -> %>
Select a check type to configure
<% end %>
<.input field={@form[:interval_seconds]} type="number" label="Interval (seconds)" />
<.input field={@form[:timeout_ms]} type="number" label="Timeout (ms)" />
<.button type="submit" phx-disable-with="Creating..."> Create Check <.button type="button" phx-click="close" phx-target={@myself} class="bg-white dark:bg-gray-700" > Cancel
""" end defp render_http_fields(assigns) do ~H"""
<.input field={@form[:url]} type="text" label="URL" placeholder="https://example.com/health" />
<.input field={@form[:method]} type="select" label="Method" options={["GET", "POST", "PUT", "DELETE", "HEAD"]} />
<.input field={@form[:expected_status]} type="number" label="Expected Status" placeholder="200" />
Advanced Options
<.input field={@form[:content_match]} type="text" label="Content Match (regex)" placeholder="Optional regex pattern" />
""" end defp render_tcp_fields(assigns) do ~H"""
<.input field={@form[:host]} type="text" label="Host" placeholder="example.com" />
<.input field={@form[:port]} type="number" label="Port" placeholder="80" />
<.input field={@form[:send_string]} type="text" label="Send String (optional)" placeholder="Text to send after connecting" />
<.input field={@form[:expect_string]} type="text" label="Expect String (optional)" placeholder="Expected response pattern" />
""" end defp render_dns_fields(assigns) do ~H"""
<.input field={@form[:hostname]} type="text" label="Hostname" placeholder="example.com" />
<.input field={@form[:record_type]} type="select" label="Record Type" options={["A", "AAAA", "CNAME", "MX", "TXT", "NS"]} />
<.input field={@form[:dns_server]} type="text" label="DNS Server (optional)" placeholder="8.8.8.8" />
<.input field={@form[:expected_result]} type="text" label="Expected Result (optional)" placeholder="Expected IP or value" />
""" end @impl true def mount(socket) do {:ok, socket} end @impl true def update(assigns, socket) do changeset = Monitoring.change_check(%Monitoring.Check{}) {:ok, socket |> assign(assigns) |> assign(:selected_type, "http") |> assign(:form, to_form(changeset)) |> assign_default_config("http")} end @impl true def handle_event("change_type", %{"check" => %{"check_type" => type}}, socket) do {:noreply, socket |> assign(:selected_type, type) |> assign_default_config(type)} end @impl true def handle_event("validate", %{"check" => check_params}, socket) do check_params = merge_config_params(check_params, socket.assigns.selected_type) changeset = %Monitoring.Check{} |> Monitoring.change_check(check_params) |> Map.put(:action, :validate) {:noreply, assign(socket, form: to_form(changeset))} end @impl true def handle_event("save", %{"check" => check_params}, socket) do check_params = merge_config_params(check_params, socket.assigns.selected_type) check_params = check_params |> Map.put("organization_id", socket.assigns.device.organization_id) |> Map.put("device_id", socket.assigns.device.id) |> Map.put("source_type", "manual") case Monitoring.create_check(check_params) do {:ok, check} -> # Schedule first execution Monitoring.schedule_check(check) notify_parent({:check_created, check}) {:noreply, socket} {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, form: to_form(changeset))} end end @impl true def handle_event("close", _params, socket) do notify_parent(:close) {:noreply, socket} end defp assign_default_config(socket, type) do config = case type do "http" -> %{ "url" => "", "method" => "GET", "expected_status" => "200", "verify_ssl" => "true", "follow_redirects" => "true" } "tcp" -> %{"host" => "", "port" => ""} "dns" -> %{"hostname" => "", "record_type" => "A"} _ -> %{} end assign(socket, :default_config, config) end defp merge_config_params(check_params, type) do config = case type do "http" -> maybe_add( %{ "url" => check_params["url"], "method" => check_params["method"] || "GET", "expected_status" => String.to_integer(check_params["expected_status"] || "200"), "verify_ssl" => check_params["verify_ssl"] == "true", "follow_redirects" => check_params["follow_redirects"] == "true" }, "regex", check_params["content_match"] ) "tcp" -> %{ "host" => check_params["host"], "port" => String.to_integer(check_params["port"] || "0") } |> maybe_add("send", check_params["send_string"]) |> maybe_add("expect", check_params["expect_string"]) "dns" -> %{ "hostname" => check_params["hostname"], "record_type" => check_params["record_type"] || "A" } |> maybe_add("server", check_params["dns_server"]) |> maybe_add("expected", check_params["expected_result"]) _ -> %{} end check_params |> Map.put("config", config) |> Map.put("check_type", type) end defp maybe_add(map, _key, nil), do: map defp maybe_add(map, _key, ""), do: map defp maybe_add(map, key, value), do: Map.put(map, key, value) defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) end