defmodule AshHqWeb.Components.DocSidebar do @moduledoc "The left sidebar of the docs pages" use Surface.Component alias AshHqWeb.DocRoutes alias Surface.Components.LivePatch prop class, :css_class, default: "" prop libraries, :list, required: true prop extension, :any, default: nil prop guide, :any, default: nil prop library, :any, default: nil prop library_version, :any, default: nil prop selected_versions, :map, default: %{} prop id, :string, required: true prop dsl, :any, required: true prop module, :any, required: true prop sidebar_state, :map, required: true prop collapse_sidebar, :event, required: true prop expand_sidebar, :event, required: true prop add_version, :event, required: true prop remove_version, :event, required: true prop change_version, :event, required: true @spec render(any) :: Phoenix.LiveView.Rendered.t() def render(assigns) do ~F""" """ end defp has_selected_guide?(guides_by_library, guide_id) do Enum.any?(guides_by_library, fn {_, guides} -> Enum.any?(guides, &(&1.id == guide_id)) end) end defp render_dsls(assigns, dsls, path) do ~F""" """ end def render_icon(assigns, "Resource") do ~F""" """ end def render_icon(assigns, "Api") do ~F""" """ end def render_icon(assigns, "DataLayer") do ~F""" """ end def render_icon(assigns, "Flow") do ~F""" """ end def render_icon(assigns, "Notifier") do ~F""" """ end def render_icon(assigns, "Registry") do ~F""" """ end def render_icon(assigns, _) do ~F""" """ end @start_guides ["Tutorials", "Topics", "How To", "Misc"] defp guides_by_category_and_library(libraries, selected_versions) do libraries = Enum.filter(libraries, fn library -> selected_versions[library.id] && selected_versions[library.id] != "" end) library_name_to_order = libraries |> Enum.sort_by(& &1.order) |> Enum.map(& &1.display_name) libraries |> Enum.flat_map(fn library -> library.versions |> Enum.find(&Ash.Resource.loaded?(&1, :guides)) |> case do nil -> [] %{guides: guides} -> Enum.map(guides, &{&1, library.display_name}) end end) |> Enum.group_by(fn {guide, _} -> guide.category end) |> Enum.map(fn {category, guides} -> guides_by_library = library_name_to_order |> Enum.map(fn name -> {name, Enum.flat_map(guides, fn {guide, guide_lib_name} -> if name == guide_lib_name do [guide] else [] end end)} end) |> Enum.reject(fn {_, guides} -> Enum.empty?(guides) end) {category, guides_by_library} end) |> partially_alphabetically_sort(@start_guides, []) end defp get_extensions(libraries, selected_versions) do libraries |> Enum.filter(fn library -> selected_versions[library.id] && selected_versions[library.id] != "" end) |> Enum.sort_by(& &1.order) |> Enum.flat_map(fn library -> case Enum.find(library.versions, &Ash.Resource.loaded?(&1, :extensions)) do nil -> [] version -> case version.extensions do [] -> [] extensions -> [{library.display_name, extensions}] end end end) end @last_categories ["Errors"] defp modules_by_category(libraries, selected_versions) do libraries = Enum.filter(libraries, fn library -> selected_versions[library.id] && selected_versions[library.id] != "" end) libraries |> Enum.flat_map(fn library -> library.versions |> Enum.find(&Ash.Resource.loaded?(&1, :modules)) |> case do nil -> [] %{modules: modules} -> modules end end) |> Enum.group_by(fn module -> module.category end) |> Enum.sort_by(fn {category, _} -> category end) |> Enum.map(fn {category, modules} -> {category, Enum.sort_by(modules, & &1.name)} end) |> partially_alphabetically_sort([], @last_categories) end defp partially_alphabetically_sort(keyed_list, first, last) do {first_items, rest} = Enum.split_with(keyed_list, fn {key, _} -> key in first end) {last_items, rest} = Enum.split_with(rest, fn {key, _} -> key in last end) first_items |> Enum.sort_by(fn {key, _} -> Enum.find_index(first, &(&1 == key)) end) |> Enum.concat(Enum.sort_by(rest, &elem(&1, 0))) |> Enum.concat( Enum.sort_by(last_items, fn {key, _} -> Enum.find_index(last, &(&1 == key)) end) ) end end