mirror of
https://github.com/ash-project/ash_hq.git
synced 2024-09-20 05:13:23 +12:00
WIP
This commit is contained in:
parent
86798987d4
commit
4e219667f2
17 changed files with 417 additions and 115 deletions
|
@ -1,3 +1,7 @@
|
||||||
defmodule AshHq.Docs do
|
defmodule AshHq.Docs do
|
||||||
use Ash.Api, otp_app: :ash_hq
|
use Ash.Api, otp_app: :ash_hq
|
||||||
|
|
||||||
|
execution do
|
||||||
|
timeout 30_000
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -93,6 +93,7 @@ defmodule AshHq.Docs.Importer do
|
||||||
end
|
end
|
||||||
|
|
||||||
LibraryVersion.build!(library.id, version, result, %{
|
LibraryVersion.build!(library.id, version, result, %{
|
||||||
|
timeout: :infinity,
|
||||||
id: id,
|
id: id,
|
||||||
doc: result[:doc],
|
doc: result[:doc],
|
||||||
guides: result[:guides],
|
guides: result[:guides],
|
||||||
|
@ -105,7 +106,7 @@ defmodule AshHq.Docs.Importer do
|
||||||
|
|
||||||
for version <- LibraryVersion.unprocessed!() do
|
for version <- LibraryVersion.unprocessed!() do
|
||||||
try do
|
try do
|
||||||
LibraryVersion.process!(version)
|
LibraryVersion.process!(version, timeout: :infinity)
|
||||||
rescue
|
rescue
|
||||||
e ->
|
e ->
|
||||||
Logger.error(
|
Logger.error(
|
||||||
|
|
|
@ -13,7 +13,8 @@ defmodule AshHq.Docs.Dsl do
|
||||||
:extension_type,
|
:extension_type,
|
||||||
:extension_name,
|
:extension_name,
|
||||||
:version_name,
|
:version_name,
|
||||||
:library_name
|
:library_name,
|
||||||
|
:library_id
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -99,6 +100,7 @@ defmodule AshHq.Docs.Dsl do
|
||||||
first :extension_name, :extension, :name
|
first :extension_name, :extension, :name
|
||||||
first :version_name, :library_version, :version
|
first :version_name, :library_version, :version
|
||||||
first :library_name, [:library_version, :library], :name
|
first :library_name, [:library_version, :library], :name
|
||||||
|
first :library_id, [:library_version, :library], :id
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
|
|
|
@ -12,7 +12,8 @@ defmodule AshHq.Docs.Function do
|
||||||
load_for_search([
|
load_for_search([
|
||||||
:version_name,
|
:version_name,
|
||||||
:library_name,
|
:library_name,
|
||||||
:module_name
|
:module_name,
|
||||||
|
:library_id
|
||||||
])
|
])
|
||||||
|
|
||||||
type "Code"
|
type "Code"
|
||||||
|
@ -81,6 +82,7 @@ defmodule AshHq.Docs.Function do
|
||||||
aggregates do
|
aggregates do
|
||||||
first :version_name, :library_version, :version
|
first :version_name, :library_version, :version
|
||||||
first :library_name, [:library_version, :library], :name
|
first :library_name, [:library_version, :library], :name
|
||||||
|
first :library_id, [:library_version, :library], :id
|
||||||
first :module_name, :module, :name
|
first :module_name, :module, :name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@ defmodule AshHq.Docs.Guide.Changes.SetRoute do
|
||||||
|
|
||||||
def change(changeset, _, _) do
|
def change(changeset, _, _) do
|
||||||
if !Ash.Changeset.get_attribute(changeset, :route) &&
|
if !Ash.Changeset.get_attribute(changeset, :route) &&
|
||||||
(Ash.Changeset.changing_attribute?(:name) || Ash.Changeset.changing_attribute?(:category)) do
|
(Ash.Changeset.changing_attribute?(changeset, :name) ||
|
||||||
|
Ash.Changeset.changing_attribute?(changeset, :category)) do
|
||||||
category = Ash.Changeset.get_attribute(changeset, :category)
|
category = Ash.Changeset.get_attribute(changeset, :category)
|
||||||
name = Ash.Changeset.get_attribute(changeset, :name)
|
name = Ash.Changeset.get_attribute(changeset, :name)
|
||||||
Ash.Changeset.change_attribute(changeset, :route, to_path(category) <> "/" <> to_path(name))
|
Ash.Changeset.change_attribute(changeset, :route, to_path(category) <> "/" <> to_path(name))
|
||||||
|
|
|
@ -10,7 +10,8 @@ defmodule AshHq.Docs.Module do
|
||||||
search do
|
search do
|
||||||
load_for_search [
|
load_for_search [
|
||||||
:version_name,
|
:version_name,
|
||||||
:library_name
|
:library_name,
|
||||||
|
:library_id
|
||||||
]
|
]
|
||||||
|
|
||||||
type "Code"
|
type "Code"
|
||||||
|
@ -69,6 +70,7 @@ defmodule AshHq.Docs.Module do
|
||||||
aggregates do
|
aggregates do
|
||||||
first :version_name, :library_version, :version
|
first :version_name, :library_version, :version
|
||||||
first :library_name, [:library_version, :library], :name
|
first :library_name, [:library_version, :library], :name
|
||||||
|
first :library_id, [:library_version, :library], :id
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
|
|
|
@ -13,7 +13,8 @@ defmodule AshHq.Docs.Option do
|
||||||
:extension_type,
|
:extension_type,
|
||||||
:extension_name,
|
:extension_name,
|
||||||
:version_name,
|
:version_name,
|
||||||
:library_name
|
:library_name,
|
||||||
|
:library_id
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -85,6 +86,7 @@ defmodule AshHq.Docs.Option do
|
||||||
first :extension_order, [:dsl, :extension], :order
|
first :extension_order, [:dsl, :extension], :order
|
||||||
first :version_name, :library_version, :version
|
first :version_name, :library_version, :version
|
||||||
first :library_name, [:library_version, :library], :name
|
first :library_name, [:library_version, :library], :name
|
||||||
|
first :library_id, [:library_version, :library], :id
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
|
|
|
@ -20,7 +20,7 @@ defmodule AshHqWeb.Components.DocSidebar do
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~F"""
|
~F"""
|
||||||
<aside id={@id} class={"grid w-64 h-full overflow-y-scroll", @class} aria-label="Sidebar">
|
<aside id={@id} class={"grid w-64 h-full overflow-y-scroll pb-36", @class} aria-label="Sidebar">
|
||||||
<div class="py-3 px-3">
|
<div class="py-3 px-3">
|
||||||
<ul class="space-y-2">
|
<ul class="space-y-2">
|
||||||
{#for library <- @libraries}
|
{#for library <- @libraries}
|
||||||
|
@ -44,11 +44,7 @@ defmodule AshHqWeb.Components.DocSidebar do
|
||||||
{#for guide <- guides}
|
{#for guide <- guides}
|
||||||
<li class="ml-3">
|
<li class="ml-3">
|
||||||
<LivePatch
|
<LivePatch
|
||||||
to={Routes.guide_link(
|
to={Routes.doc_link(guide, @selected_versions)}
|
||||||
library,
|
|
||||||
selected_version_name(library, @selected_versions),
|
|
||||||
guide.route
|
|
||||||
)}
|
|
||||||
class={
|
class={
|
||||||
"flex items-center p-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
|
"flex items-center p-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
|
||||||
"dark:bg-gray-600": @guide && @guide.id == guide.id
|
"dark:bg-gray-600": @guide && @guide.id == guide.id
|
||||||
|
@ -69,7 +65,7 @@ defmodule AshHqWeb.Components.DocSidebar do
|
||||||
{#for extension <- get_extensions(library, @selected_versions)}
|
{#for extension <- get_extensions(library, @selected_versions)}
|
||||||
<li class="ml-3">
|
<li class="ml-3">
|
||||||
<LivePatch
|
<LivePatch
|
||||||
to={Routes.extension_link(library, selected_version_name(library, @selected_versions), extension.name)}
|
to={Routes.doc_link(extension, @selected_versions)}
|
||||||
class={
|
class={
|
||||||
"flex items-center p-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
|
"flex items-center p-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
|
||||||
"dark:bg-gray-600": @extension && @extension.id == extension.id
|
"dark:bg-gray-600": @extension && @extension.id == extension.id
|
||||||
|
@ -90,7 +86,7 @@ defmodule AshHqWeb.Components.DocSidebar do
|
||||||
{#for module <- @library_version.modules}
|
{#for module <- @library_version.modules}
|
||||||
<li class="ml-3">
|
<li class="ml-3">
|
||||||
<LivePatch
|
<LivePatch
|
||||||
to={Routes.module_link(library, @library_version.version, module.name)}
|
to={Routes.doc_link(module, @selected_versions)}
|
||||||
class={
|
class={
|
||||||
"flex items-center pt-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
|
"flex items-center pt-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
|
||||||
"dark:bg-gray-600": @module && @module.id == module.id
|
"dark:bg-gray-600": @module && @module.id == module.id
|
||||||
|
@ -131,7 +127,7 @@ defmodule AshHqWeb.Components.DocSidebar do
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
<LivePatch
|
<LivePatch
|
||||||
to={Routes.dsl_link(@library, @library_version.version, @extension.name, dsl)}
|
to={Routes.doc_link(dsl, @selected_versions)}
|
||||||
class={
|
class={
|
||||||
"flex items-center p-1 text-base font-normal rounded-lg hover:text-orange-300",
|
"flex items-center p-1 text-base font-normal rounded-lg hover:text-orange-300",
|
||||||
"text-orange-600 dark:text-orange-400 font-bold": @dsl && @dsl.id == dsl.id
|
"text-orange-600 dark:text-orange-400 font-bold": @dsl && @dsl.id == dsl.id
|
||||||
|
@ -204,12 +200,16 @@ defmodule AshHqWeb.Components.DocSidebar do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp selected_version_name(library, selected_versions) do
|
defp selected_version_name(library, selected_versions) do
|
||||||
case Enum.find(library.versions, &(&1.id == selected_versions[library.id])) do
|
if selected_versions[library.id] == "latest" do
|
||||||
nil ->
|
"latest"
|
||||||
nil
|
else
|
||||||
|
case Enum.find(library.versions, &(&1.id == selected_versions[library.id])) do
|
||||||
|
nil ->
|
||||||
|
nil
|
||||||
|
|
||||||
version ->
|
version ->
|
||||||
version.version
|
version.version
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ defmodule AshHqWeb.Components.Search do
|
||||||
class="text-black form-select rounded-md pt-1 py-2 w-3/4 border dark:border-0 bg-gray-100 dark:bg-white"
|
class="text-black form-select rounded-md pt-1 py-2 w-3/4 border dark:border-0 bg-gray-100 dark:bg-white"
|
||||||
name={"versions[#{library.id}]"}
|
name={"versions[#{library.id}]"}
|
||||||
selected={Map.get(@selected_versions, library.id)}
|
selected={Map.get(@selected_versions, library.id)}
|
||||||
options={Enum.map(library.versions, &{&1.version, &1.id})}
|
options={[{"latest", "latest"}] ++ Enum.map(library.versions, &{&1.version, &1.id})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -134,7 +134,7 @@ defmodule AshHqWeb.Components.Search do
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#for item <- results.items}
|
{#for item <- results.items}
|
||||||
<LiveRedirect to={Routes.doc_link(item)} opts={id: item.id}>
|
<LiveRedirect to={Routes.doc_link(item, @selected_versions)} opts={id: item.id}>
|
||||||
<div class={
|
<div class={
|
||||||
"rounded-lg mb-4 py-4 px-2 hover:bg-gray-400 dark:hover:bg-gray-600",
|
"rounded-lg mb-4 py-4 px-2 hover:bg-gray-400 dark:hover:bg-gray-600",
|
||||||
"bg-gray-400 dark:bg-gray-600": @selected_item.id == item.id,
|
"bg-gray-400 dark:bg-gray-600": @selected_item.id == item.id,
|
||||||
|
@ -213,10 +213,31 @@ defmodule AshHqWeb.Components.Search do
|
||||||
if socket.assigns[:search] in [nil, ""] || socket.assigns[:selected_versions] in [nil, %{}] do
|
if socket.assigns[:search] in [nil, ""] || socket.assigns[:selected_versions] in [nil, %{}] do
|
||||||
assign(socket, :results, %{})
|
assign(socket, :results, %{})
|
||||||
else
|
else
|
||||||
|
versions =
|
||||||
|
Enum.map(socket.assigns.selected_versions, fn
|
||||||
|
{library_id, "latest"} ->
|
||||||
|
Enum.find_value(socket.assigns.libraries, fn library ->
|
||||||
|
if library.id == library_id do
|
||||||
|
case Enum.find(library.versions, &String.contains?(&1.version, ".")) ||
|
||||||
|
Enum.at(library.versions, 0) do
|
||||||
|
nil ->
|
||||||
|
nil
|
||||||
|
|
||||||
|
version ->
|
||||||
|
version.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
{_, version_id} ->
|
||||||
|
version_id
|
||||||
|
end)
|
||||||
|
|> Enum.reject(&is_nil/1)
|
||||||
|
|
||||||
%{results: results, item_list: item_list} =
|
%{results: results, item_list: item_list} =
|
||||||
AshHq.Docs.Search.run!(
|
AshHq.Docs.Search.run!(
|
||||||
socket.assigns.search,
|
socket.assigns.search,
|
||||||
Map.values(socket.assigns.selected_versions)
|
versions
|
||||||
)
|
)
|
||||||
|
|
||||||
selected_item = Enum.at(item_list, 0)
|
selected_item = Enum.at(item_list, 0)
|
||||||
|
|
|
@ -54,7 +54,7 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<span class="grid overflow-hidden lg:hidden">
|
<span class="grid overflow-hidden xl:hidden">
|
||||||
<div
|
<div
|
||||||
id="mobile-sidebar-container"
|
id="mobile-sidebar-container"
|
||||||
class="overflow-hidden hidden fixed w-min h-full transition bg-white dark:bg-primary-black"
|
class="overflow-hidden hidden fixed w-min h-full transition bg-white dark:bg-primary-black"
|
||||||
|
@ -322,8 +322,8 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp assign_extension(socket) do
|
defp assign_extension(socket) do
|
||||||
if socket.assigns.library && socket.assigns[:params]["extension"] do
|
if socket.assigns.library_version && socket.assigns[:params]["extension"] do
|
||||||
extensions = get_extensions(socket.assigns.library, socket.assigns.selected_versions)
|
extensions = socket.assigns.library_version.extensions
|
||||||
|
|
||||||
assign(socket,
|
assign(socket,
|
||||||
extension:
|
extension:
|
||||||
|
@ -340,16 +340,6 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
{:ok, socket}
|
{:ok, socket}
|
||||||
end
|
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
|
defp assign_library(socket) do
|
||||||
if !socket.assigns[:library] ||
|
if !socket.assigns[:library] ||
|
||||||
socket.assigns.params["library"] != Routes.sanitize_name(socket.assigns.library.name) do
|
socket.assigns.params["library"] != Routes.sanitize_name(socket.assigns.library.name) do
|
||||||
|
@ -364,10 +354,17 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
socket =
|
socket =
|
||||||
if socket.assigns[:params]["version"] do
|
if socket.assigns[:params]["version"] do
|
||||||
library_version =
|
library_version =
|
||||||
Enum.find(
|
case socket.assigns[:params]["version"] do
|
||||||
library.versions,
|
"latest" ->
|
||||||
&(Routes.sanitize_name(&1.version) == socket.assigns[:params]["version"])
|
Enum.find(library.versions, &String.contains?(&1.version, ".")) ||
|
||||||
)
|
Enum.at(library.versions, 0)
|
||||||
|
|
||||||
|
version ->
|
||||||
|
Enum.find(
|
||||||
|
library.versions,
|
||||||
|
&(Routes.sanitize_name(&1.version) == version)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
if library_version do
|
if library_version do
|
||||||
new_selected_versions =
|
new_selected_versions =
|
||||||
|
|
|
@ -2,6 +2,9 @@ defmodule AshHqWeb.Pages.Home do
|
||||||
use Surface.LiveComponent
|
use Surface.LiveComponent
|
||||||
|
|
||||||
alias AshHqWeb.Components.{CalloutText, CodeExample, SearchBar}
|
alias AshHqWeb.Components.{CalloutText, CodeExample, SearchBar}
|
||||||
|
alias Surface.Components.LiveRedirect
|
||||||
|
|
||||||
|
prop libraries, :list, default: []
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~F"""
|
~F"""
|
||||||
|
@ -15,6 +18,23 @@ defmodule AshHqWeb.Pages.Home do
|
||||||
or build your own extensions. Plug-and-play with other excellent tools like <CalloutText>Phoenix</CalloutText> and <CalloutText>Absinthe</CalloutText>.
|
or build your own extensions. Plug-and-play with other excellent tools like <CalloutText>Phoenix</CalloutText> and <CalloutText>Absinthe</CalloutText>.
|
||||||
</div>
|
</div>
|
||||||
<SearchBar class="hidden sm:block mt-16" />
|
<SearchBar class="hidden sm:block mt-16" />
|
||||||
|
|
||||||
|
<div class="grid grid-cols-3 w-full place-content-evenly mt-12">
|
||||||
|
<div class="grid grid-cols-1 text-center">
|
||||||
|
Data Layers
|
||||||
|
<LiveRedirect to={"/"}>
|
||||||
|
AshPostgres
|
||||||
|
</LiveRedirect>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 text-center">
|
||||||
|
APIs
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 text-center">
|
||||||
|
Build your own
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="pt-6 pb-6 w-full hidden sm:block mt-36">
|
<div class="pt-6 pb-6 w-full hidden sm:block mt-36">
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-10">
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-10">
|
||||||
<CodeExample
|
<CodeExample
|
||||||
|
|
|
@ -1,78 +1,95 @@
|
||||||
defmodule AshHqWeb.Routes do
|
defmodule AshHqWeb.Routes do
|
||||||
def guide_link(library, version, route) do
|
|
||||||
"/docs/guides/#{sanitize_name(library.name)}/#{sanitize_name(version)}/#{route}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def library_link(library, nil) do
|
|
||||||
"/docs/dsl/#{sanitize_name(library.name)}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def library_link(library, name) do
|
def library_link(library, name) do
|
||||||
"/docs/dsl/#{sanitize_name(library.name)}/#{sanitize_name(name)}"
|
"/docs/dsl/#{sanitize_name(library.name)}/#{sanitize_name(name)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def extension_link(library, name, extension) do
|
def doc_link(entity, selected_versions \\ %{})
|
||||||
"/docs/dsl/#{sanitize_name(library.name)}/#{sanitize_name(name)}/#{sanitize_name(extension)}"
|
|
||||||
|
def doc_link(%AshHq.Docs.Library{name: name}, _selected_version) do
|
||||||
|
"/docs/dsl/#{sanitize_name(name)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def dsl_link(library, name, extension, item) do
|
def doc_link(
|
||||||
|
%AshHq.Docs.Module{
|
||||||
|
name: name,
|
||||||
|
library_name: library_name,
|
||||||
|
version_name: version_name,
|
||||||
|
library_id: library_id
|
||||||
|
},
|
||||||
|
selected_versions
|
||||||
|
) do
|
||||||
|
"/docs/module/#{sanitize_name(library_name)}/#{version(version_name, library_id, selected_versions)}/#{sanitize_name(name)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def doc_link(
|
||||||
|
%AshHq.Docs.Function{
|
||||||
|
name: name,
|
||||||
|
arity: arity,
|
||||||
|
type: type,
|
||||||
|
module_name: module_name,
|
||||||
|
library_name: library_name,
|
||||||
|
version_name: version_name,
|
||||||
|
library_id: library_id
|
||||||
|
},
|
||||||
|
selected_versions
|
||||||
|
) do
|
||||||
|
"/docs/module/#{sanitize_name(library_name)}/#{version(version_name, IO.inspect(library_id), selected_versions)}/#{sanitize_name(module_name)}/##{type}-#{sanitize_name(name)}-#{arity}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def doc_link(
|
||||||
|
%AshHq.Docs.Guide{
|
||||||
|
route: route,
|
||||||
|
library_version: %{
|
||||||
|
library_name: library_name,
|
||||||
|
version: version,
|
||||||
|
library_id: library_id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selected_versions
|
||||||
|
) do
|
||||||
|
"/docs/guides/#{sanitize_name(library_name)}/#{version(version, library_id, selected_versions)}/#{route}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def doc_link(
|
||||||
|
%AshHq.Docs.LibraryVersion{
|
||||||
|
library_name: library_name,
|
||||||
|
version: version,
|
||||||
|
library_id: library_id
|
||||||
|
},
|
||||||
|
selected_versions
|
||||||
|
) do
|
||||||
|
"/docs/dsl/#{sanitize_name(library_name)}/#{version(version, library_id, selected_versions)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def doc_link(
|
||||||
|
%AshHq.Docs.Extension{
|
||||||
|
library_version: %{
|
||||||
|
library_name: library_name,
|
||||||
|
version: version,
|
||||||
|
library_id: library_id
|
||||||
|
},
|
||||||
|
name: name
|
||||||
|
},
|
||||||
|
selected_versions
|
||||||
|
) do
|
||||||
|
"/docs/dsl/#{sanitize_name(library_name)}/#{version(version, library_id, selected_versions)}/#{sanitize_name(name)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def doc_link(item, selected_versions) do
|
||||||
case item do
|
case item do
|
||||||
%AshHq.Docs.Dsl{} = item ->
|
%AshHq.Docs.Dsl{} = item ->
|
||||||
"/docs/dsl/#{sanitize_name(library.name)}/#{sanitize_name(name)}/#{sanitize_name(extension)}/#{Enum.map_join(item.path ++ [item.name], "/", &sanitize_name/1)}"
|
"/docs/dsl/#{sanitize_name(item.library_name)}/#{version(item.version_name, item.library_id, selected_versions)}/#{sanitize_name(item.extension_name)}/#{Enum.map_join(item.path ++ [item.name], "/", &sanitize_name/1)}"
|
||||||
|
|
||||||
%AshHq.Docs.Option{} = item ->
|
%AshHq.Docs.Option{} = item ->
|
||||||
"/docs/dsl/#{sanitize_name(library.name)}/#{sanitize_name(name)}/#{sanitize_name(extension)}/#{Enum.map_join(item.path, "/", &sanitize_name/1)}##{item.name}"
|
"/docs/dsl/#{sanitize_name(item.library_name)}/#{version(item.version_name, item.library_id, selected_versions)}/#{sanitize_name(item.extension_name)}/#{Enum.map_join(item.path, "/", &sanitize_name/1)}##{item.name}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def module_link(library, version, module) do
|
defp version(version_name, library_id, selected_versions) do
|
||||||
"/docs/module/#{sanitize_name(library.name)}/#{sanitize_name(version)}/#{sanitize_name(module)}"
|
if selected_versions[library_id] == "latest" do
|
||||||
end
|
"latest"
|
||||||
|
else
|
||||||
def doc_link(%AshHq.Docs.Module{
|
version_name
|
||||||
name: name,
|
|
||||||
library_name: library_name,
|
|
||||||
version_name: version_name
|
|
||||||
}) do
|
|
||||||
"/docs/module/#{sanitize_name(library_name)}/#{sanitize_name(version_name)}/#{sanitize_name(name)}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def doc_link(%AshHq.Docs.Function{
|
|
||||||
name: name,
|
|
||||||
arity: arity,
|
|
||||||
type: type,
|
|
||||||
module_name: module_name,
|
|
||||||
library_name: library_name,
|
|
||||||
version_name: version_name
|
|
||||||
}) do
|
|
||||||
"/docs/module/#{sanitize_name(library_name)}/#{sanitize_name(version_name)}/#{sanitize_name(module_name)}/##{type}-#{sanitize_name(name)}-#{arity}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def doc_link(%AshHq.Docs.Guide{
|
|
||||||
route: route,
|
|
||||||
library_version: %{library_name: library_name, version: version}
|
|
||||||
}) do
|
|
||||||
"/docs/guides/#{sanitize_name(library_name)}/#{sanitize_name(version)}/#{route}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def doc_link(%AshHq.Docs.LibraryVersion{library_name: library_name, version: version}) do
|
|
||||||
"/docs/dsl/#{sanitize_name(library_name)}/#{sanitize_name(version)}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def doc_link(%AshHq.Docs.Extension{
|
|
||||||
library_version: %{library_name: library_name, version: version},
|
|
||||||
name: name
|
|
||||||
}) do
|
|
||||||
"/docs/dsl/#{sanitize_name(library_name)}/#{sanitize_name(version)}/#{sanitize_name(name)}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def doc_link(item) do
|
|
||||||
case item do
|
|
||||||
%AshHq.Docs.Dsl{} = item ->
|
|
||||||
"/docs/dsl/#{sanitize_name(item.library_name)}/#{sanitize_name(item.version_name)}/#{sanitize_name(item.extension_name)}/#{Enum.map_join(item.path ++ [item.name], "/", &sanitize_name/1)}"
|
|
||||||
|
|
||||||
%AshHq.Docs.Option{} = item ->
|
|
||||||
"/docs/dsl/#{sanitize_name(item.library_name)}/#{sanitize_name(item.version_name)}/#{sanitize_name(item.extension_name)}/#{Enum.map_join(item.path, "/", &sanitize_name/1)}##{item.name}"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,12 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
alias Phoenix.LiveView.JS
|
alias Phoenix.LiveView.JS
|
||||||
require Ash.Query
|
require Ash.Query
|
||||||
|
|
||||||
data(configured_theme, :string, default: :system)
|
data configured_theme, :string, default: :system
|
||||||
data(searching, :boolean, default: false)
|
data searching, :boolean, default: false
|
||||||
data(selected_versions, :map, default: %{})
|
data selected_versions, :map, default: %{}
|
||||||
data(libraries, :list, default: [])
|
data libraries, :list, default: []
|
||||||
data(selected_types, :map, default: %{})
|
data selected_types, :map, default: %{}
|
||||||
data(sidebar_state, :map, default: %{})
|
data sidebar_state, :map, default: %{}
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~F"""
|
~F"""
|
||||||
|
@ -58,7 +58,7 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
href="/docs/guides/ash/main/getting-started"
|
href="/docs/guides/ash/main/getting-started"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600"
|
class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600"
|
||||||
>Get Started</a>
|
>Quick Start</a>
|
||||||
<div>|</div>
|
<div>|</div>
|
||||||
<a
|
<a
|
||||||
href="/docs/guides/ash/main/overview"
|
href="/docs/guides/ash/main/overview"
|
||||||
|
@ -212,25 +212,40 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
socket.assigns.libraries
|
socket.assigns.libraries
|
||||||
|> Enum.map(fn library ->
|
|> Enum.map(fn library ->
|
||||||
Map.update!(library, :versions, fn versions ->
|
Map.update!(library, :versions, fn versions ->
|
||||||
|
latest_version =
|
||||||
|
Enum.find(versions, &String.contains?(&1.version, ".")) || Enum.at(versions, 0)
|
||||||
|
|
||||||
Enum.map(versions, fn version ->
|
Enum.map(versions, fn version ->
|
||||||
if version.id == socket.assigns[:selected_versions][library.id] do
|
if (socket.assigns[:selected_versions][library.id] == "latest" && latest_version &&
|
||||||
dsls_query = Ash.Query.sort(AshHq.Docs.Dsl, order: :asc)
|
version.id == latest_version.id) ||
|
||||||
options_query = Ash.Query.sort(AshHq.Docs.Option, order: :asc)
|
version.id == socket.assigns[:selected_versions][library.id] do
|
||||||
functions_query = Ash.Query.sort(AshHq.Docs.Function, name: :asc, arity: :asc)
|
dsls_query = AshHq.Docs.Dsl |> Ash.Query.sort(order: :asc) |> load_for_search()
|
||||||
|
|
||||||
|
options_query =
|
||||||
|
AshHq.Docs.Option |> Ash.Query.sort(order: :asc) |> load_for_search()
|
||||||
|
|
||||||
|
functions_query =
|
||||||
|
AshHq.Docs.Function
|
||||||
|
|> Ash.Query.sort(name: :asc, arity: :asc)
|
||||||
|
|> load_for_search()
|
||||||
|
|
||||||
|
guides_query = AshHq.Docs.Guide |> Ash.Query.new() |> load_for_search()
|
||||||
|
|
||||||
modules_query =
|
modules_query =
|
||||||
AshHq.Docs.Module
|
AshHq.Docs.Module
|
||||||
|> Ash.Query.sort(order: :asc)
|
|> Ash.Query.sort(order: :asc)
|
||||||
|> Ash.Query.load(functions: functions_query)
|
|> Ash.Query.load(functions: functions_query)
|
||||||
|
|> load_for_search()
|
||||||
|
|
||||||
extensions_query =
|
extensions_query =
|
||||||
AshHq.Docs.Extension
|
AshHq.Docs.Extension
|
||||||
|> Ash.Query.sort(order: :asc)
|
|> Ash.Query.sort(order: :asc)
|
||||||
|> Ash.Query.load(options: options_query, dsls: dsls_query)
|
|> Ash.Query.load(options: options_query, dsls: dsls_query)
|
||||||
|
|> load_for_search()
|
||||||
|
|
||||||
AshHq.Docs.load!(version,
|
AshHq.Docs.load!(version,
|
||||||
extensions: extensions_query,
|
extensions: extensions_query,
|
||||||
guides: [],
|
guides: guides_query,
|
||||||
modules: modules_query
|
modules: modules_query
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
|
@ -327,7 +342,7 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
:selected_types,
|
:selected_types,
|
||||||
selected_types
|
selected_types
|
||||||
)
|
)
|
||||||
|> push_event("selected_versions", selected_versions)
|
|> push_event("selected-versions", selected_versions)
|
||||||
|> push_event("selected_types", %{types: selected_types})
|
|> push_event("selected_types", %{types: selected_types})
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
@ -364,4 +379,13 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
)
|
)
|
||||||
|> JS.dispatch("js:focus", to: "#search-input")
|
|> JS.dispatch("js:focus", to: "#search-input")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp load_for_search(query) do
|
||||||
|
Ash.Query.load(
|
||||||
|
query,
|
||||||
|
IO.inspect(AshHq.Docs.Extensions.Search.load_for_search(query.resource),
|
||||||
|
label: inspect(query.resource)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
2
mix.lock
2
mix.lock
|
@ -1,5 +1,5 @@
|
||||||
%{
|
%{
|
||||||
"ash": {:git, "https://github.com/ash-project/ash.git", "a012287c3b621ac15d0d7b00735c6ebc9c477163", []},
|
"ash": {:git, "https://github.com/ash-project/ash.git", "ea1adcf2309e6a317cda288af949da2ae582f7eb", []},
|
||||||
"ash_phoenix": {:git, "https://github.com/ash-project/ash_phoenix.git", "9de0ff87780bd16d06dcde1bac6a8e041a31659d", []},
|
"ash_phoenix": {:git, "https://github.com/ash-project/ash_phoenix.git", "9de0ff87780bd16d06dcde1bac6a8e041a31659d", []},
|
||||||
"ash_postgres": {:git, "https://github.com/ash-project/ash_postgres.git", "48c6142040d389272d235b7e62d354a3a37a825e", []},
|
"ash_postgres": {:git, "https://github.com/ash-project/ash_postgres.git", "48c6142040d389272d235b7e62d354a3a37a825e", []},
|
||||||
"castore": {:hex, :castore, "0.1.16", "2675f717adc700475345c5512c381ef9273eb5df26bdd3f8c13e2636cf4cc175", [:mix], [], "hexpm", "28ed2c43d83b5c25d35c51bc0abf229ac51359c170cba76171a462ced2e4b651"},
|
"castore": {:hex, :castore, "0.1.16", "2675f717adc700475345c5512c381ef9273eb5df26bdd3f8c13e2636cf4cc175", [:mix], [], "hexpm", "28ed2c43d83b5c25d35c51bc0abf229ac51359c170cba76171a462ced2e4b651"},
|
||||||
|
|
29
priv/repo/migrations/20220406215156_migrate_resources5.exs
Normal file
29
priv/repo/migrations/20220406215156_migrate_resources5.exs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
defmodule AshHq.Repo.Migrations.MigrateResources5 do
|
||||||
|
@moduledoc """
|
||||||
|
Updates resources based on their most recent snapshots.
|
||||||
|
|
||||||
|
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||||
|
"""
|
||||||
|
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
alter table(:libraries) do
|
||||||
|
add :description, :text
|
||||||
|
end
|
||||||
|
|
||||||
|
alter table(:guides) do
|
||||||
|
modify :category, :text, null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
alter table(:guides) do
|
||||||
|
modify :category, :text, null: true
|
||||||
|
end
|
||||||
|
|
||||||
|
alter table(:libraries) do
|
||||||
|
remove :description
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
110
priv/resource_snapshots/repo/guides/20220406215157.json
Normal file
110
priv/resource_snapshots/repo/guides/20220406215157.json
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "fragment(\"uuid_generate_v4()\")",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": true,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "id",
|
||||||
|
"type": "uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "order",
|
||||||
|
"type": "bigint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "name",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "text",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "text_html",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "\"Guides\"",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "category",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "route",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": {
|
||||||
|
"destination_field": "id",
|
||||||
|
"destination_field_default": null,
|
||||||
|
"destination_field_generated": null,
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"name": "guides_library_version_id_fkey",
|
||||||
|
"on_delete": "delete",
|
||||||
|
"on_update": null,
|
||||||
|
"table": "library_versions"
|
||||||
|
},
|
||||||
|
"size": null,
|
||||||
|
"source": "library_version_id",
|
||||||
|
"type": "uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"has_create_action": true,
|
||||||
|
"hash": "E01C44270CD9127EF1BDE286D0DA9AED8BB0A8CE72BE9FF3F76C82148C0A413F",
|
||||||
|
"identities": [],
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"repo": "Elixir.AshHq.Repo",
|
||||||
|
"table": "guides"
|
||||||
|
}
|
70
priv/resource_snapshots/repo/libraries/20220406215157.json
Normal file
70
priv/resource_snapshots/repo/libraries/20220406215157.json
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "fragment(\"uuid_generate_v4()\")",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": true,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "id",
|
||||||
|
"type": "uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "name",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "display_name",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "description",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "[]",
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "track_branches",
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"text"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"has_create_action": true,
|
||||||
|
"hash": "70099624C119120DD5B91858CB2497E6D76C81E6CFFD60966D85F5A3CE534D04",
|
||||||
|
"identities": [],
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"repo": "Elixir.AshHq.Repo",
|
||||||
|
"table": "libraries"
|
||||||
|
}
|
Loading…
Reference in a new issue