defmodule PhoenixKitOG do @moduledoc """ OpenGraph template + hierarchical assignment plugin for PhoenixKit. See `AGENTS.md` for the high-level architecture. The integration seam with `phoenix_kit_publishing` is `refine_og/4` — publishing's `Web.Controller.build_og_data/4` calls it when this module is loaded. ## Module callbacks Implements `PhoenixKit.Module` so the host app's discovery picks this up automatically — no config line. Settings key: `phoenix_kit_og_enabled`. """ use PhoenixKit.Module alias PhoenixKit.Dashboard.Tab alias PhoenixKit.Settings alias PhoenixKitOG.{Assignments, Render, Slots, Templates, Variables} # =========================================================================== # Required PhoenixKit.Module callbacks # =========================================================================== @impl PhoenixKit.Module def module_key, do: "phoenix_kit_og" @impl PhoenixKit.Module def module_name, do: "OpenGraph" @impl PhoenixKit.Module def enabled? do Settings.get_boolean_setting("phoenix_kit_og_enabled", false) rescue _ -> false catch :exit, _ -> false end @impl PhoenixKit.Module def enable_system do Settings.update_boolean_setting_with_module( "phoenix_kit_og_enabled", true, module_key() ) end @impl PhoenixKit.Module def disable_system do Settings.update_boolean_setting_with_module( "phoenix_kit_og_enabled", false, module_key() ) end # =========================================================================== # Optional callbacks # =========================================================================== @impl PhoenixKit.Module def version, do: "0.2.0" @impl PhoenixKit.Module def permission_metadata do %{ key: module_key(), label: "OpenGraph", icon: "hero-share", description: "OpenGraph image templates + assignment per module/group/post" } end @impl PhoenixKit.Module def admin_tabs do [ %Tab{ id: :admin_phoenix_kit_og, label: "OpenGraph", icon: "hero-share", path: "open-graph", priority: 650, level: :admin, permission: module_key(), match: :prefix, group: :admin_modules, subtab_display: :when_active, highlight_with_subtabs: false, live_view: {PhoenixKitOG.Web.TemplatesLive, :index} }, %Tab{ id: :admin_phoenix_kit_og_templates, label: "Templates", icon: "hero-rectangle-stack", path: "open-graph", priority: 651, level: :admin, permission: module_key(), # Highlight on any /admin/open-graph URL that isn't the # Assignments subtab — so the list page, `/new`, and # `/:uuid/edit` all light Templates up, but Assignments keeps # its own subtab active. match: fn path -> String.starts_with?(path, "/admin/open-graph") and not String.starts_with?(path, "/admin/open-graph/assignments") end, parent: :admin_phoenix_kit_og, live_view: {PhoenixKitOG.Web.TemplatesLive, :index} }, %Tab{ id: :admin_phoenix_kit_og_assignments, label: "Assignments", icon: "hero-arrows-pointing-in", path: "open-graph/assignments", priority: 652, level: :admin, permission: module_key(), parent: :admin_phoenix_kit_og, live_view: {PhoenixKitOG.Web.AssignmentsLive, :index} } ] end @impl PhoenixKit.Module def css_sources, do: [:phoenix_kit_og] # The editor ships two LiveView JS hooks (drag/resize + keyboard). Declaring # the bundle here lets core's :phoenix_kit_js_sources compiler fold it into # the host's single LiveSocket at construction — the registration that # survives LiveView navigation (an inline