Packages

phoenix_kit

1.7.7
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib phoenix_kit_web live modules sitemaps settings.ex
Raw

lib/phoenix_kit_web/live/modules/sitemaps/settings.ex

defmodule PhoenixKitWeb.Live.Modules.Sitemaps.Settings do
@moduledoc """
LiveView for sitemap configuration and management.
Provides admin interface for:
- Enabling/disabling sitemap module
- Configuring data sources (entities, blogs, pages, static)
- Setting HTML sitemap style
- Manual sitemap regeneration
- Viewing generation statistics
"""
use PhoenixKitWeb, :live_view
use Gettext, backend: PhoenixKitWeb.Gettext
alias PhoenixKit.PubSub.Manager, as: PubSubManager
alias PhoenixKit.Settings
alias PhoenixKit.Sitemap
alias PhoenixKit.Sitemap.Generator
alias PhoenixKit.Sitemap.SchedulerWorker
alias PhoenixKit.Utils.Date, as: UtilsDate
alias PhoenixKit.Utils.Routes
@impl true
def mount(params, _session, socket) do
# Subscribe to sitemap updates for real-time UI refresh
if connected?(socket) do
PubSubManager.subscribe("sitemap:updates")
end
locale = params["locale"] || "en"
project_title = Settings.get_setting("project_title", "PhoenixKit")
site_url = Settings.get_setting("site_url", "")
config = Sitemap.get_config()
# Generate sitemap version from last_generated or current time
sitemap_version = get_sitemap_version(config)
socket =
socket
|> assign(:page_title, "Sitemap Settings")
|> assign(:project_title, project_title)
|> assign(:current_locale, locale)
|> assign(:current_path, Routes.path("/admin/settings/sitemap", locale: locale))
|> assign(:config, config)
|> assign(:site_url, site_url)
|> assign(:generating, false)
|> assign(:preview_mode, nil)
|> assign(:preview_content, nil)
|> assign(:show_preview, false)
|> assign(:show_html_preview, false)
|> assign(:sitemap_version, sitemap_version)
{:ok, socket}
end
@impl true
def handle_params(_params, _url, socket) do
{:noreply, socket}
end
@impl true
def handle_event("toggle_sitemap", _params, socket) do
new_enabled = !socket.assigns.config.enabled
result =
if new_enabled do
Sitemap.enable_system()
else
Sitemap.disable_system()
end
case result do
{:ok, _} ->
config = Sitemap.get_config()
message = if new_enabled, do: "Sitemap enabled", else: "Sitemap disabled"
{:noreply,
socket
|> assign(:config, config)
|> put_flash(:info, message)}
{:error, _} ->
{:noreply, put_flash(socket, :error, "Failed to update sitemap status")}
end
end
@impl true
def handle_event("toggle_source", %{"source" => source}, socket) do
# Router discovery uses different key pattern
key =
if source == "router_discovery" do
"sitemap_router_discovery_enabled"
else
"sitemap_include_#{source}"
end
current = Settings.get_boolean_setting(key, true)
case Settings.update_boolean_setting(key, !current) do
{:ok, _} ->
config = Sitemap.get_config()
{:noreply, assign(socket, :config, config)}
{:error, _} ->
{:noreply, put_flash(socket, :error, "Failed to update source setting")}
end
end
@impl true
def handle_event("toggle_html", _params, socket) do
current = socket.assigns.config.html_enabled
case Settings.update_boolean_setting("sitemap_html_enabled", !current) do
{:ok, _} ->
config = Sitemap.get_config()
{:noreply, assign(socket, :config, config)}
{:error, _} ->
{:noreply, put_flash(socket, :error, "Failed to update HTML sitemap setting")}
end
end
@impl true
def handle_event("toggle_schedule", _params, socket) do
current = socket.assigns.config.schedule_enabled
case Settings.update_boolean_setting("sitemap_schedule_enabled", !current) do
{:ok, _} ->
config = Sitemap.get_config()
{:noreply, assign(socket, :config, config)}
{:error, _} ->
{:noreply, put_flash(socket, :error, "Failed to update schedule setting")}
end
end
@impl true
def handle_event("update_style", %{"style" => style}, socket) do
case Settings.update_setting("sitemap_html_style", style) do
{:ok, _} ->
config = Sitemap.get_config()
{:noreply, assign(socket, :config, config)}
{:error, _} ->
{:noreply, put_flash(socket, :error, "Failed to update style")}
end
end
@impl true
def handle_event("update_interval", %{"interval" => interval_str}, socket) do
case Integer.parse(interval_str) do
{interval, _} when interval > 0 ->
case Settings.update_setting("sitemap_schedule_interval_hours", interval_str) do
{:ok, _} ->
config = Sitemap.get_config()
{:noreply, assign(socket, :config, config)}
{:error, _} ->
{:noreply, put_flash(socket, :error, "Failed to update interval")}
end
_ ->
{:noreply, put_flash(socket, :error, "Invalid interval value")}
end
end
@impl true
def handle_event("regenerate", _params, socket) do
# Get base URL for generation
base_url = Sitemap.get_base_url()
if base_url != "" do
# Use Oban worker for async generation (non-blocking UI)
case SchedulerWorker.regenerate_now() do
{:ok, _job} ->
{:noreply,
socket
|> assign(:generating, true)
|> put_flash(:info, "Sitemap generation queued. Stats will update automatically.")}
{:error, reason} ->
{:noreply,
socket
|> put_flash(:error, "Failed to queue generation: #{inspect(reason)}")}
end
else
{:noreply,
socket
|> put_flash(:error, "Please configure Base URL before generating")}
end
end
@impl true
def handle_event("preview", %{"type" => _type}, socket) do
base_url = Sitemap.get_base_url()
xsl_style = get_xsl_style(socket.assigns.config.html_style)
opts = [
base_url: base_url,
cache: false,
xsl_style: xsl_style,
xsl_enabled: socket.assigns.config.html_enabled
]
content =
case Generator.generate_xml(opts) do
{:ok, xml} -> xml
{:ok, xml, _parts} -> xml
_ -> "Error generating XML preview"
end
{:noreply,
socket
|> assign(:preview_mode, "xml")
|> assign(:preview_content, content)
|> assign(:show_preview, true)}
end
@impl true
def handle_event("close_preview", _params, socket) do
{:noreply,
socket
|> assign(:show_preview, false)
|> assign(:preview_mode, nil)
|> assign(:preview_content, nil)}
end
@impl true
def handle_event("preview_html", _params, socket) do
{:noreply, assign(socket, :show_html_preview, true)}
end
@impl true
def handle_event("close_html_preview", _params, socket) do
{:noreply, assign(socket, :show_html_preview, false)}
end
@impl true
def handle_event("invalidate_cache", _params, socket) do
Generator.invalidate_cache()
# Update version to force iframe reload after cache clear
new_version = DateTime.utc_now() |> DateTime.to_unix()
{:noreply,
socket
|> assign(:sitemap_version, new_version)
|> put_flash(:info, "Sitemap cache cleared")}
end
# Handle PubSub message when sitemap generation completes
@impl true
def handle_info({:sitemap_generated, %{url_count: count}}, socket) do
# Refresh config to get updated stats
config = Sitemap.get_config()
# Update sitemap version to force iframe reload
sitemap_version = get_sitemap_version(config)
{:noreply,
socket
|> assign(:generating, false)
|> assign(:config, config)
|> assign(:sitemap_version, sitemap_version)
|> put_flash(:info, "Sitemap generated successfully (#{count} URLs)")}
end
# Maps old HTML style names to new XSL style names
# hierarchical -> cards, grouped -> table, flat -> minimal
def get_xsl_style(html_style) do
case html_style do
"hierarchical" -> "cards"
"grouped" -> "table"
"flat" -> "minimal"
style when style in ["table", "cards", "minimal"] -> style
_ -> "table"
end
end
# Format ISO8601 timestamp string to human-readable format
def format_timestamp(nil), do: "Never"
def format_timestamp(iso_string) when is_binary(iso_string) do
case DateTime.from_iso8601(iso_string) do
{:ok, dt, _} ->
# Convert to NaiveDateTime for UtilsDate
ndt = DateTime.to_naive(dt)
UtilsDate.format_datetime_full_with_user_format(ndt)
_ ->
iso_string
end
end
def format_timestamp(_), do: "Never"
# Generate sitemap version string for cache busting
# Uses last_generated timestamp or current time
defp get_sitemap_version(config) do
case config.last_generated do
nil ->
# No sitemap generated yet, use current timestamp
DateTime.utc_now() |> DateTime.to_unix()
iso_string when is_binary(iso_string) ->
case DateTime.from_iso8601(iso_string) do
{:ok, dt, _} -> DateTime.to_unix(dt)
_ -> DateTime.utc_now() |> DateTime.to_unix()
end
end
end
end