add settings editor component for unified on-site editing
All checks were successful
deploy / deploy (push) Successful in 4m13s
All checks were successful
deploy / deploy (push) Successful in 4m13s
Phase 3b of unified editing mode. The Settings tab now shows context-specific forms: custom pages get editable title, slug, meta, visibility and nav options; system pages get read-only info with links to admin; product/collection pages show provider info. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -61,6 +61,9 @@ defmodule BerrypodWeb.PageEditorHook do
|
||||
|> assign(:theme_editor_contrast_warning, :ok)
|
||||
|> assign(:theme_editor_customise_open, false)
|
||||
|> assign(:theme_editor_presets, Presets.all_with_descriptions())
|
||||
# Settings editing state
|
||||
|> assign(:settings_dirty, false)
|
||||
|> assign(:settings_save_status, :idle)
|
||||
|> attach_hook(:editor_params, :handle_params, &handle_editor_params/3)
|
||||
|> attach_hook(:editor_events, :handle_event, &handle_editor_event/3)
|
||||
|> attach_hook(:editor_info, :handle_info, &handle_editor_info/2)
|
||||
@@ -212,6 +215,16 @@ defmodule BerrypodWeb.PageEditorHook do
|
||||
load_theme_state(socket)
|
||||
end
|
||||
|
||||
# Initialize settings form from current page if not already set
|
||||
# Only custom pages have editable settings (meta_description, published, etc.)
|
||||
socket =
|
||||
if is_nil(socket.assigns[:settings_form]) && socket.assigns[:page] &&
|
||||
socket.assigns.page[:type] == "custom" do
|
||||
init_settings_form(socket)
|
||||
else
|
||||
socket
|
||||
end
|
||||
|
||||
assign(socket, :editor_active_tab, :settings)
|
||||
end
|
||||
|
||||
@@ -251,6 +264,15 @@ defmodule BerrypodWeb.PageEditorHook do
|
||||
end
|
||||
end
|
||||
|
||||
# Settings editing events (custom page settings)
|
||||
defp handle_editor_event("settings_" <> action, params, socket) do
|
||||
if socket.assigns.is_admin do
|
||||
handle_settings_action(action, params, socket)
|
||||
else
|
||||
{:cont, socket}
|
||||
end
|
||||
end
|
||||
|
||||
defp handle_editor_event(_event, _params, socket), do: {:cont, socket}
|
||||
|
||||
# ── Block manipulation actions ───────────────────────────────────
|
||||
@@ -721,6 +743,106 @@ defmodule BerrypodWeb.PageEditorHook do
|
||||
# Catch-all for unknown theme actions
|
||||
defp handle_theme_action(_action, _params, socket), do: {:halt, socket}
|
||||
|
||||
# ── Settings editing actions (custom page settings) ────────────────
|
||||
|
||||
# Validate page settings form (live as-you-type)
|
||||
defp handle_settings_action("validate_page", %{"page" => params}, socket) do
|
||||
page = socket.assigns.page
|
||||
|
||||
# Only allow editing custom pages
|
||||
if page && page.type == "custom" do
|
||||
socket =
|
||||
socket
|
||||
|> assign(:settings_form, params)
|
||||
|> assign(:settings_dirty, has_settings_changed?(page, params))
|
||||
|> assign(:settings_save_status, :idle)
|
||||
|
||||
{:halt, socket}
|
||||
else
|
||||
{:halt, socket}
|
||||
end
|
||||
end
|
||||
|
||||
# Save page settings
|
||||
defp handle_settings_action("save_page", %{"page" => params}, socket) do
|
||||
page = socket.assigns.page
|
||||
|
||||
# Only allow editing custom pages
|
||||
if page && page.type == "custom" do
|
||||
# Normalize checkbox fields (unchecked checkboxes aren't sent)
|
||||
params =
|
||||
params
|
||||
|> Map.put_new("published", "false")
|
||||
|> Map.put_new("show_in_nav", "false")
|
||||
|
||||
old_slug = page.slug
|
||||
|
||||
# Fetch the Page struct from DB (assigns.page may be a map from cache)
|
||||
page_struct = Pages.get_page_struct(page.slug)
|
||||
|
||||
case Pages.update_custom_page(page_struct, params) do
|
||||
{:ok, updated_page} ->
|
||||
# Reinitialize form from saved page
|
||||
socket =
|
||||
socket
|
||||
|> assign(:page, updated_page)
|
||||
|> assign(:settings_form, nil)
|
||||
|> assign(:settings_dirty, false)
|
||||
|> assign(:settings_save_status, :saved)
|
||||
|
||||
# Reinit form with new page values
|
||||
socket = init_settings_form(socket)
|
||||
|
||||
# If slug changed, redirect to new URL
|
||||
socket =
|
||||
if updated_page.slug != old_slug do
|
||||
push_navigate(socket, to: "/#{updated_page.slug}")
|
||||
else
|
||||
socket
|
||||
end
|
||||
|
||||
{:halt, socket}
|
||||
|
||||
{:error, _changeset} ->
|
||||
socket = assign(socket, :settings_save_status, :error)
|
||||
{:halt, socket}
|
||||
end
|
||||
else
|
||||
{:halt, socket}
|
||||
end
|
||||
end
|
||||
|
||||
# Catch-all for unknown settings actions
|
||||
defp handle_settings_action(_action, _params, socket), do: {:halt, socket}
|
||||
|
||||
# Check if settings have changed from current page values
|
||||
defp has_settings_changed?(page, params) do
|
||||
page.title != (params["title"] || "") or
|
||||
page.slug != (params["slug"] || "") or
|
||||
(page.meta_description || "") != (params["meta_description"] || "") or
|
||||
to_string(page.published) != (params["published"] || "false") or
|
||||
to_string(page.show_in_nav) != (params["show_in_nav"] || "false") or
|
||||
(page.nav_label || "") != (params["nav_label"] || "") or
|
||||
to_string(page.nav_position || 0) != (params["nav_position"] || "0")
|
||||
end
|
||||
|
||||
# Initialize settings form from page values
|
||||
defp init_settings_form(socket) do
|
||||
page = socket.assigns.page
|
||||
|
||||
form = %{
|
||||
"title" => page.title || "",
|
||||
"slug" => page.slug || "",
|
||||
"meta_description" => page.meta_description || "",
|
||||
"published" => to_string(page.published),
|
||||
"show_in_nav" => to_string(page.show_in_nav),
|
||||
"nav_label" => page.nav_label || "",
|
||||
"nav_position" => to_string(page.nav_position || 0)
|
||||
}
|
||||
|
||||
assign(socket, :settings_form, form)
|
||||
end
|
||||
|
||||
# Helper to update a theme setting and regenerate CSS
|
||||
defp update_theme_setting(socket, attrs, field) do
|
||||
case Settings.update_theme_settings(attrs) do
|
||||
|
||||
Reference in New Issue
Block a user