defmodule AshHqWeb.Pages.Docs do use Surface.LiveComponent alias Phoenix.LiveView.JS alias AshHqWeb.Components.{CalloutText, DocSidebar, Tag} alias AshHqWeb.Routes prop params, :map, required: true prop change_versions, :event, required: true prop selected_versions, :map, required: true prop libraries, :list, default: [] prop uri, :string data library, :any data extension, :any data docs, :any data library_version, :any data guide, :any data doc_path, :list, default: [] data dsls, :list, default: [] data dsl, :any data options, :list, default: [] data module, :any data function, :any @spec render(any) :: Phoenix.LiveView.Rendered.t() def render(assigns) do ~F"""
{#if @doc_path && @doc_path != []}
{#case @doc_path} {#match [item]}
{item}
{#match path} {#for item <- :lists.droplast(path)} {item} {/for} {List.last(path)} {/case}
{/if}
""" end def path_to_name(path, name) do Enum.map_join(path ++ [name], "-", &Routes.sanitize_name/1) end defp render_tags(assigns, option) do ~F""" {#if option.required} Required {/if} """ end def show_sidebar() do %JS{} |> JS.toggle( to: "#mobile-sidebar-container", in: { "transition ease-in duration-100", "opacity-0", "opacity-100" }, out: { "transition ease-out duration-75", "opacity-100", "opacity-0" } ) end def update(assigns, socket) do {:ok, socket |> assign(assigns) |> assign_library() |> assign_extension() |> assign_guide() |> assign_module() |> assign_function() |> assign_dsl() |> assign_docs()} end defp assign_guide(socket) do guide = if socket.assigns[:params]["guide"] && socket.assigns.library_version do Enum.find(socket.assigns.library_version.guides, fn guide -> guide.url_safe_name == socket.assigns[:params]["guide"] end) end assign(socket, :guide, guide) end defp assign_dsl(socket) do case socket.assigns[:params]["dsl_path"] do nil -> assign(socket, :dsl, nil) path -> dsl = Enum.find( socket.assigns.extension.dsls, fn dsl -> Enum.map(dsl.path, &Routes.sanitize_name/1) ++ [Routes.sanitize_name(dsl.name)] == path end ) assign( socket, :dsl, dsl ) end end defp assign_function(socket) do if socket.assigns.module do socket.assigns.uri |> URI.parse() |> Map.get(:fragment) |> case do nil -> assign(socket, :function, nil) "" -> assign(socket, :function, nil) fragment -> assign( socket, :function, Enum.find(socket.assigns.module.functions, fn func -> "#{Routes.sanitize_name(func.name)}-#{func.arity}" == fragment end) ) end else assign(socket, :function, nil) end end defp assign_module(socket) do if socket.assigns.library && socket.assigns.library_version && socket.assigns[:params]["module"] do module = Enum.find( socket.assigns.library_version.modules, &(Routes.sanitize_name(&1.name) == socket.assigns[:params]["module"]) ) assign(socket, module: module ) else assign(socket, :module, nil) end end defp assign_docs(socket) do cond do socket.assigns.module -> assign(socket, docs: AshHq.Docs.Extensions.RenderMarkdown.render!(socket.assigns.module, :doc), doc_paths: [socket.assigns.library.name, socket.assigns.module.name], options: [] ) socket.assigns.dsl -> assign(socket, docs: AshHq.Docs.Extensions.RenderMarkdown.render!(socket.assigns.dsl, :doc), doc_path: [ socket.assigns.library.name, socket.assigns.extension.name ] ++ socket.assigns.dsl.path ++ [socket.assigns.dsl.name], options: Enum.filter( socket.assigns.extension.options, &(&1.path == socket.assigns.dsl.path ++ [socket.assigns.dsl.name]) ) ) socket.assigns.extension -> assign(socket, docs: AshHq.Docs.Extensions.RenderMarkdown.render!(socket.assigns.extension, :doc), doc_path: [socket.assigns.library.name, socket.assigns.extension.name], options: [] ) socket.assigns.guide -> assign(socket, docs: AshHq.Docs.Extensions.RenderMarkdown.render!(socket.assigns.guide, :text), doc_path: [socket.assigns.library.name, socket.assigns.guide.name], options: [] ) socket.assigns.library_version -> assign(socket, docs: AshHq.Docs.Extensions.RenderMarkdown.render!(socket.assigns.library_version, :doc), doc_path: [socket.assigns.library.name], options: [] ) true -> assign(socket, docs: "", doc_path: [], dsls: []) end end defp assign_extension(socket) do if socket.assigns.library && socket.assigns[:params]["extension"] do extensions = get_extensions(socket.assigns.library, socket.assigns.selected_versions) assign(socket, extension: Enum.find(extensions, fn extension -> Routes.sanitize_name(extension.name) == socket.assigns[:params]["extension"] end) ) else assign(socket, :extension, nil) end end def mount(socket) do {:ok, socket} end defp get_extensions(library, selected_versions) do case Enum.find(library.versions, &(&1.id == selected_versions[library.id])) do nil -> [] version -> version.extensions end end defp assign_library(socket) do if !socket.assigns[:library] || socket.assigns.params["library"] != Routes.sanitize_name(socket.assigns.library.name) do case Enum.find( socket.assigns.libraries, &(Routes.sanitize_name(&1.name) == socket.assigns.params["library"]) ) do nil -> assign(socket, library: nil, library_version: nil) library -> socket = if socket.assigns[:params]["version"] do library_version = Enum.find( library.versions, &(Routes.sanitize_name(&1.version) == socket.assigns[:params]["version"]) ) if library_version do new_selected_versions = Map.put(socket.assigns.selected_versions, library.id, library_version.id) assign( socket, selected_versions: new_selected_versions, library_version: library_version ) |> push_event("selected-versions", new_selected_versions) else assign(socket, :library_version, nil) end else assign(socket, :library_version, nil) end assign(socket, :library, library) end else socket end end end