defmodule PhoenixKitWeb.Live.Modules.Blogging.New do @moduledoc """ LiveView for creating a new blog workspace. """ use PhoenixKitWeb, :live_view use Gettext, backend: PhoenixKitWeb.Gettext alias PhoenixKit.Settings alias PhoenixKit.Utils.Routes alias PhoenixKitWeb.Live.Modules.Blogging def mount(params, _session, socket) do locale = params["locale"] || socket.assigns[:current_locale] || "en" Gettext.put_locale(PhoenixKitWeb.Gettext, locale) Process.put(:phoenix_kit_current_locale, locale) {initial_params, auto?, last_generated_slug} = normalize_slug_params(%{}, true, "") socket = socket |> assign(:current_locale, locale) |> assign(:project_title, Settings.get_setting("project_title", "PhoenixKit")) |> assign(:page_title, gettext("Create Blog")) |> assign(:current_path, Routes.path("/admin/settings/blogging/new", locale: locale)) |> assign(:slug_autogenerated?, auto?) |> assign(:last_generated_slug, last_generated_slug) |> assign(:form_params, initial_params) |> assign(:form, new_blog_form(initial_params)) {:ok, socket} end def handle_params(_params, _uri, socket), do: {:noreply, socket} def handle_event("update_new_blog", %{"blog" => params}, socket) do {normalized_params, auto?, last_generated_slug} = normalize_slug_params( params, socket.assigns.slug_autogenerated?, socket.assigns.last_generated_slug ) {:noreply, socket |> assign(:slug_autogenerated?, auto?) |> assign(:last_generated_slug, last_generated_slug) |> assign(:form_params, normalized_params) |> assign(:form, new_blog_form(normalized_params))} end def handle_event("manual_slug", %{"value" => value}, socket) do current_params = socket.assigns.form_params name = Map.get(current_params, "name", "") auto_slug = if name == "", do: "", else: Blogging.slugify(name) sanitized = value |> to_string() |> String.trim() |> case do "" -> "" slug -> Blogging.slugify(slug) end cond do sanitized == "" -> updated = Map.put(current_params, "slug", auto_slug) {:noreply, socket |> assign(:slug_autogenerated?, true) |> assign(:last_generated_slug, auto_slug) |> assign(:form_params, updated) |> assign(:form, new_blog_form(updated))} sanitized == auto_slug -> updated = Map.put(current_params, "slug", auto_slug) {:noreply, socket |> assign(:slug_autogenerated?, true) |> assign(:last_generated_slug, auto_slug) |> assign(:form_params, updated) |> assign(:form, new_blog_form(updated))} true -> updated = Map.put(current_params, "slug", sanitized) {:noreply, socket |> assign(:slug_autogenerated?, false) |> assign(:form_params, updated) |> assign(:form, new_blog_form(updated))} end end def handle_event("add_blog", %{"blog" => params}, socket) do {normalized_params, auto?, last_generated_slug} = normalize_slug_params( params, socket.assigns.slug_autogenerated?, socket.assigns.last_generated_slug ) name = Map.get(normalized_params, "name", "") mode = Map.get(normalized_params, "mode", "timestamp") slug = Map.get(normalized_params, "slug") socket = socket |> assign(:slug_autogenerated?, auto?) |> assign(:last_generated_slug, last_generated_slug) |> assign(:form_params, normalized_params) |> assign(:form, new_blog_form(normalized_params)) case Blogging.add_blog(name, mode, slug) do {:ok, blog} -> locale = socket.assigns.current_locale {:noreply, socket |> put_flash(:info, gettext("Blog \"%{name}\" created", name: blog["name"])) |> push_navigate(to: Routes.path("/admin/settings/blogging", locale: locale))} {:error, :already_exists} -> {:noreply, put_flash(socket, :error, gettext("That blog already exists"))} {:error, :invalid_name} -> {:noreply, put_flash(socket, :error, gettext("Please enter a valid blog name"))} {:error, :invalid_mode} -> {:noreply, put_flash(socket, :error, gettext("Invalid storage mode"))} {:error, :invalid_slug} -> {:noreply, put_flash( socket, :error, gettext( "Invalid slug format. Please use only lowercase letters, numbers, and hyphens (e.g. my-blog-name)" ) )} {:error, _reason} -> {:noreply, put_flash(socket, :error, gettext("Failed to add blog"))} end end def handle_event("cancel", _params, socket) do {:noreply, push_navigate(socket, to: Routes.path("/admin/settings/blogging", locale: socket.assigns.current_locale) )} end defp new_blog_form(params) when is_map(params) do defaults = %{"name" => "", "slug" => "", "mode" => "timestamp"} values = Map.merge(defaults, params) to_form(values, as: :blog) end defp normalize_slug_params(params, slug_autogenerated?, last_generated_slug) do mode = params |> Map.get("mode", "timestamp") |> to_string() |> String.downcase() |> case do "slug" -> "slug" _ -> "timestamp" end name = params |> Map.get("name", "") |> to_string() |> String.trim() slug_input = params |> Map.get("slug", "") |> to_string() trimmed_slug = String.trim(slug_input) sanitized_input = if trimmed_slug == "" do "" else Blogging.slugify(slug_input) end auto_slug = if name == "" do "" else Blogging.slugify(name) end if slug_autogenerated? do slug_value = auto_slug {%{"name" => name, "slug" => slug_value, "mode" => mode}, true, slug_value} else slug_value = case sanitized_input do "" -> auto_slug value -> value end auto? = slug_value == auto_slug new_last_generated = if auto?, do: slug_value, else: last_generated_slug {%{"name" => name, "slug" => slug_value, "mode" => mode}, auto?, new_last_generated} end end end