defmodule ToweropsWeb.SiteLive.Form do @moduledoc false use ToweropsWeb, :live_view alias Phoenix.HTML.Form alias Towerops.Agents alias Towerops.Sites alias Towerops.Sites.Site @impl true def mount(_params, _session, socket) do organization = socket.assigns.current_scope.organization {:ok, socket |> assign(:organization, organization) |> assign(:available_parent_sites, Sites.list_organization_sites(organization.id)) |> assign(:available_agents, Agents.list_organization_agent_tokens(organization.id))} end @impl true def handle_params(params, _url, socket) do {:noreply, apply_action(socket, socket.assigns.live_action, params)} end defp apply_action(socket, :new, _params) do changeset = Sites.change_site(%Site{organization_id: socket.assigns.organization.id}) # Get inherited agent info from organization org_agent = find_org_agent( socket.assigns.organization.default_agent_token_id, socket.assigns.available_agents ) socket |> assign(:page_title, t("New Site")) |> assign(:site, %Site{}) |> assign(:form, to_form(changeset)) |> assign(:org_agent, org_agent) end defp apply_action(socket, :edit, %{"id" => id}) do site = Sites.get_organization_site!(socket.assigns.organization.id, id) changeset = Sites.change_site(site) # Filter out the current site and its descendants from parent options available_parent_sites = Enum.reject(socket.assigns.available_parent_sites, fn s -> s.id == site.id end) # Get inherited agent info from organization org_agent = find_org_agent( socket.assigns.organization.default_agent_token_id, socket.assigns.available_agents ) socket |> assign(:page_title, t("Edit Site")) |> assign(:site, site) |> assign(:form, to_form(changeset)) |> assign(:available_parent_sites, available_parent_sites) |> assign(:org_agent, org_agent) end @impl true def handle_event("validate", %{"site" => site_params}, socket) do changeset = socket.assigns.site |> Sites.change_site(site_params) |> Map.put(:action, :validate) {:noreply, assign(socket, :form, to_form(changeset))} end @impl true def handle_event("save", %{"site" => site_params}, socket) do save_site(socket, socket.assigns.live_action, site_params) end @impl true def handle_event("geocode", _params, socket) do address = Form.input_value(socket.assigns.form, :address) if address && String.trim(address) != "" do case Towerops.Geocoding.geocode(address) do {:ok, %{latitude: lat, longitude: lng, formatted_address: formatted_address}} -> # Update the form with the geocoded coordinates updated_params = %{ "latitude" => lat, "longitude" => lng, "address" => formatted_address } changeset = socket.assigns.site |> Sites.change_site(updated_params) |> Map.put(:action, :validate) {:noreply, socket |> assign(:form, to_form(changeset)) |> put_flash(:info, t("Address geocoded successfully!"))} {:error, :no_api_key} -> {:noreply, put_flash( socket, :error, "Geocoding is not configured. Please contact your administrator to configure the Google Maps API key." )} {:error, reason} when is_binary(reason) -> {:noreply, put_flash(socket, :error, t("Geocoding failed: %{reason}", reason: reason))} {:error, _} -> {:noreply, put_flash(socket, :error, t("Geocoding failed. Please check the address and try again."))} end else {:noreply, put_flash(socket, :error, t("Please enter an address to geocode"))} end end @impl true def handle_event("delete", _params, socket) do case Sites.delete_site(socket.assigns.site) do {:ok, _} -> {:noreply, socket |> put_flash(:info, t_equipment("Site deleted successfully")) |> push_navigate(to: ~p"/sites")} {:error, _} -> {:noreply, put_flash(socket, :error, t_equipment("Unable to delete site"))} end end @impl true def handle_event("apply_snmp_to_all", _params, socket) do {count, _} = Sites.apply_snmp_config_to_all_equipment(socket.assigns.site.id) {:noreply, put_flash( socket, :info, t_equipment("Applied SNMP configuration to %{count} device records at this site", count: count) )} end @impl true def handle_event("apply_agent_to_all", _params, socket) do {count, _} = Sites.apply_agent_to_all_equipment(socket.assigns.site.id) {:noreply, put_flash(socket, :info, t_equipment("Applied agent to %{count} device records at this site", count: count))} end defp save_site(socket, :new, site_params) do site_params = Map.put(site_params, "organization_id", socket.assigns.organization.id) case Sites.create_site(site_params) do {:ok, site} -> {:noreply, socket |> put_flash(:info, t_equipment("Site created successfully! Now add your first device.")) |> push_navigate(to: ~p"/sites/#{site.id}")} {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, :form, to_form(changeset))} end end defp save_site(socket, :edit, site_params) do case Sites.update_site(socket.assigns.site, site_params) do {:ok, _site} -> {:noreply, socket |> put_flash(:info, t_equipment("Site updated successfully")) |> push_navigate(to: ~p"/sites")} {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, :form, to_form(changeset))} end end # Find organization's default agent in the available agents list defp find_org_agent(nil, _agents), do: nil defp find_org_agent(agent_id, agents), do: Enum.find(agents, &(&1.id == agent_id)) end