defmodule PhoenixKitWeb.Live.Modules.Storage.DimensionForm do @moduledoc """ Dimension form LiveView for storage dimension management. Provides form interface for creating and editing dimension presets. """ use PhoenixKitWeb, :live_view use Gettext, backend: PhoenixKitWeb.Gettext alias PhoenixKit.Modules.Storage alias PhoenixKit.Settings alias PhoenixKit.Utils.Routes def mount(params, _session, socket) do dimension_uuid = params["id"] dimension_type = case socket.assigns[:live_action] do :new_image -> "image" :new_video -> "video" _ -> nil end mode = if dimension_uuid, do: :edit, else: :new # Get project title from settings project_title = Settings.get_project_title() socket = socket |> assign(:mode, mode) |> assign(:dimension_uuid, dimension_uuid) |> assign(:current_locale, "en") |> assign(:current_path, Routes.path("/admin/settings/media/dimensions")) |> assign(:project_title, project_title) |> assign(:dimension, load_dimension_data(mode, dimension_uuid)) |> assign(:dimension_type, dimension_type) |> assign_form() {:ok, socket} end def handle_event("validate", %{"dimension" => dimension_params}, socket) do dimension_params = normalize_dimension_params(dimension_params) changeset = case socket.assigns.mode do :new -> Storage.change_dimension(%Storage.Dimension{}, dimension_params) :edit -> dimension = Storage.get_dimension(socket.assigns.dimension_uuid) Storage.change_dimension(dimension, dimension_params) end socket = socket |> assign(:changeset, changeset) |> assign_format_fields(changeset) {:noreply, socket} end def handle_event("save", %{"dimension" => dimension_params}, socket) do dimension_params = normalize_dimension_params(dimension_params) case socket.assigns.mode do :new -> create_dimension(socket, dimension_params) :edit -> update_dimension(socket, dimension_params) end end defp create_dimension(socket, dimension_params) do case Storage.create_dimension(dimension_params) do {:ok, _dimension} -> socket = socket |> put_flash(:info, "Dimension created successfully") |> push_navigate(to: Routes.path("/admin/settings/media/dimensions")) {:noreply, socket} {:error, changeset} -> socket = socket |> assign(:changeset, changeset) |> put_flash(:error, "Failed to create dimension") {:noreply, socket} end end defp update_dimension(socket, dimension_params) do dimension = Storage.get_dimension(socket.assigns.dimension_uuid) case Storage.update_dimension(dimension, dimension_params) do {:ok, _dimension} -> socket = socket |> put_flash(:info, "Dimension updated successfully") |> push_navigate(to: Routes.path("/admin/settings/media/dimensions")) {:noreply, socket} {:error, changeset} -> socket = socket |> assign(:changeset, changeset) |> put_flash(:error, "Failed to update dimension") {:noreply, socket} end end defp load_dimension_data(:new, _dimension_uuid), do: nil defp load_dimension_data(:edit, dimension_uuid) do Storage.get_dimension(dimension_uuid) end defp assign_form(%{assigns: %{mode: :new, dimension_type: dimension_type}} = socket) do # Set applies_to based on dimension_type initial_attrs = case dimension_type do "image" -> %{applies_to: "image"} "video" -> %{applies_to: "video"} _ -> %{} end changeset = Storage.change_dimension(%Storage.Dimension{}, initial_attrs) socket |> assign(:changeset, changeset) |> assign(:page_title, page_title_with_type(:new, dimension_type)) |> assign(:form_action, page_title_with_type(:new, dimension_type)) |> assign_format_fields(changeset) end defp assign_form(%{assigns: %{mode: :edit, dimension: dimension}} = socket) do changeset = Storage.change_dimension(dimension, %{}) dimension_type = dimension.applies_to socket |> assign(:changeset, changeset) |> assign(:dimension_type, dimension_type) |> assign(:page_title, "Edit Storage Dimension") |> assign(:form_action, "Update Dimension") |> assign_format_fields(changeset) end defp assign_format_fields(socket, changeset) do socket |> assign( :current_alternatives, Ecto.Changeset.get_field(changeset, :alternative_formats) || [] ) |> assign(:primary_format, Ecto.Changeset.get_field(changeset, :format)) end defp normalize_dimension_params(params) do params |> then(fn p -> case p["maintain_aspect_ratio"] do "true" -> Map.put(p, "maintain_aspect_ratio", true) "false" -> Map.put(p, "maintain_aspect_ratio", false) _ -> p end end) |> then(fn p -> alt = p["alternative_formats"] || [] Map.put(p, "alternative_formats", Enum.reject(alt, &(&1 == ""))) end) end defp page_title_with_type(:new, "image"), do: "Add Image Dimension" defp page_title_with_type(:new, "video"), do: "Add Video Dimension" defp page_title_with_type(:new, _), do: "Add Storage Dimension" # Helper function for input validation styling defp input_class(changeset, field) do if Keyword.has_key?(changeset.errors, field) do "input-error" else "" end end # Helper function to get field value from changeset or data defp get_field_value(changeset, field) do case changeset do %Ecto.Changeset{} -> Ecto.Changeset.get_field(changeset, field) _ -> nil end end # Helper function to render error messages defp render_error(changeset, field) do if Keyword.has_key?(changeset.errors, field) do errors = changeset.errors |> Keyword.get_values(field) |> Enum.map_join(", ", &extract_error_message/1) content = """
#{errors}
""" Phoenix.HTML.raw(content) else "" end end defp extract_error_message({message, _}), do: message end