All checks were successful
deploy / deploy (push) Successful in 3m27s
- Add header and footer nav editors to Site tab with drag-to-reorder, add/remove items, and destination picker (pages, collections, external) - Live preview updates as you edit nav items - Remove legacy /admin/navigation page and controller (was saving to Settings table, now uses nav_items table) - Update error_html.ex and pages/editor.ex to load nav from nav_items table - Update link_scanner to read from nav_items table, edit path now /?edit=site - Add Site.default_header_nav/0 and default_footer_nav/0 for previews/errors - Remove fallback logic from theme_hook.ex (database is now source of truth) - Seed default nav items and social links during setup Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
91 lines
2.7 KiB
Elixir
91 lines
2.7 KiB
Elixir
defmodule BerrypodWeb.ThemeHook do
|
|
@moduledoc """
|
|
LiveView on_mount hook for theme settings, CSS, and media assigns.
|
|
|
|
Mounted in the public_shop live_session alongside CartHook.
|
|
Eliminates the identical theme-loading boilerplate from every shop LiveView.
|
|
|
|
## Actions
|
|
|
|
- `:mount_theme` — loads theme settings, CSS, and media assigns
|
|
- `:require_site_live` — redirects unauthenticated visitors to /coming-soon
|
|
when the shop is not live
|
|
"""
|
|
|
|
import Phoenix.Component, only: [assign: 3]
|
|
|
|
alias Berrypod.{Products, Settings, Site, Media}
|
|
alias Berrypod.Theme.{CSSCache, CSSGenerator}
|
|
|
|
def on_mount(:mount_theme, _params, _session, socket) do
|
|
theme_settings = Settings.get_theme_settings()
|
|
|
|
generated_css =
|
|
case CSSCache.get() do
|
|
{:ok, css} ->
|
|
css
|
|
|
|
:miss ->
|
|
css = CSSGenerator.generate(theme_settings, &BerrypodWeb.Endpoint.static_path/1)
|
|
CSSCache.put(css)
|
|
css
|
|
end
|
|
|
|
socket =
|
|
socket
|
|
|> assign(:theme_settings, theme_settings)
|
|
|> assign(:site_name, Settings.site_name())
|
|
|> assign(:site_description, Settings.site_description())
|
|
|> assign(:generated_css, generated_css)
|
|
|> assign(:logo_image, Media.get_logo())
|
|
|> assign(:header_image, Media.get_header())
|
|
|> assign(:categories, Products.list_categories())
|
|
|> assign(:mode, :shop)
|
|
|> assign(
|
|
:is_admin,
|
|
!!(socket.assigns[:current_scope] && socket.assigns.current_scope.user)
|
|
)
|
|
|> assign(:header_nav_items, load_header_nav())
|
|
|> assign(:footer_nav_items, load_footer_nav())
|
|
|> assign(:social_links, Site.social_links_for_shop())
|
|
|> assign(:announcement_text, Site.announcement_text())
|
|
|> assign(:announcement_link, Site.announcement_link())
|
|
|> assign(:announcement_style, Site.announcement_style())
|
|
|
|
{:cont, socket}
|
|
end
|
|
|
|
def on_mount(:require_site_live, _params, _session, socket) do
|
|
cond do
|
|
Settings.site_live?() ->
|
|
{:cont, socket}
|
|
|
|
# mount_current_scope runs first, so current_scope is already validated
|
|
socket.assigns[:current_scope] && socket.assigns.current_scope.user ->
|
|
{:cont, socket}
|
|
|
|
true ->
|
|
{:halt, Phoenix.LiveView.redirect(socket, to: "/coming-soon")}
|
|
end
|
|
end
|
|
|
|
defp load_header_nav do
|
|
Site.nav_items_for_shop("header") |> add_active_slugs()
|
|
end
|
|
|
|
defp load_footer_nav do
|
|
Site.nav_items_for_shop("footer")
|
|
end
|
|
|
|
# Add active_slugs for Shop nav item to highlight on collection and pdp pages
|
|
defp add_active_slugs(items) do
|
|
Enum.map(items, fn item ->
|
|
if item["slug"] == "collection" do
|
|
Map.put(item, "active_slugs", ["collection", "pdp"])
|
|
else
|
|
item
|
|
end
|
|
end)
|
|
end
|
|
end
|