ash_hq/lib/ash_hq_web/views/app_view_live.ex

218 lines
7 KiB
Elixir
Raw Normal View History

2022-03-26 10:17:01 +13:00
defmodule AshHqWeb.AppViewLive do
use Surface.LiveView,
container: {:div, class: "h-full"}
2022-03-28 10:26:35 +13:00
alias AshHqWeb.Components.Search
alias AshHqWeb.Pages.{Docs, Home}
2022-03-26 10:17:01 +13:00
alias Phoenix.LiveView.JS
2022-03-28 10:26:35 +13:00
require Ash.Query
2022-03-26 10:17:01 +13:00
data configured_theme, :string, default: :system
data searching, :boolean, default: false
2022-03-28 10:26:35 +13:00
data selected_versions, :map, default: %{}
data libraries, :list, default: []
2022-03-26 10:17:01 +13:00
def render(assigns) do
~F"""
<div
id="app"
class={"h-full font-sans": true, "#{@configured_theme}": true}
phx-hook="ColorTheme"
>
2022-03-28 10:26:35 +13:00
<Search
id="search-box"
close={close_search()}
libraries={@libraries}
change_versions="change-versions"
selected_versions={@selected_versions}
/>
2022-03-29 11:05:19 +13:00
<button id="search-button" class="hidden" phx-click={AshHqWeb.AppViewLive.toggle_search()} />
2022-03-28 10:26:35 +13:00
<div
id="main-container"
class="h-full bg-white dark:bg-primary-black dark:text-silver-phoenix overflow-x-hidden"
>
2022-03-26 10:17:01 +13:00
<div class="flex justify-between pt-4 px-4">
<div class="flex flex-row align-baseline">
2022-03-28 10:26:35 +13:00
<a href="/">
<img class="h-10 hidden dark:block" src="/images/ash-framework-dark.png">
<img class="h-10 dark:hidden" src="/images/ash-framework-light.png">
</a>
2022-03-26 10:17:01 +13:00
</div>
2022-03-28 10:26:35 +13:00
<div class="flex flex-row align-middle items-center space-x-2">
2022-03-29 11:05:19 +13:00
<a
href="/docs/guides/ash/main/Getting-Started"
class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600"
>Get Started</a>
2022-03-29 08:47:43 +13:00
<div>|</div>
2022-03-28 10:26:35 +13:00
<a href="/docs" class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600">Docs</a>
<div>|</div>
<a href="https://github.com/ash-project">
2022-03-29 11:05:19 +13:00
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6 dark:fill-gray-400 dark:hover:fill-gray-200 hover:fill-gray-600"
viewBox="0 0 24 24"
><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" /></svg>
2022-03-28 10:26:35 +13:00
</a>
2022-03-26 10:17:01 +13:00
<button phx-click="toggle_theme">
{#case @configured_theme}
{#match "light"}
2022-03-28 10:26:35 +13:00
<Heroicons.Outline.SunIcon class="w-6 h-6 hover:text-gray-600" />
2022-03-26 10:17:01 +13:00
{#match _}
2022-03-29 11:05:19 +13:00
<Heroicons.Outline.MoonIcon class="w-6 h-6 text-gray-400 fill-gray-400 hover:fill-gray-200 hover:text-gray-200" />
2022-03-26 10:17:01 +13:00
{/case}
</button>
</div>
</div>
2022-03-28 10:26:35 +13:00
{#case @live_action}
{#match :home}
<Home id="home" />
{#match :docs_dsl}
2022-03-29 11:05:19 +13:00
<Docs
id="docs"
params={@params}
change_versions="change-versions"
selected_versions={@selected_versions}
libraries={@libraries}
/>
2022-03-28 10:26:35 +13:00
{/case}
2022-03-26 10:17:01 +13:00
</div>
</div>
"""
end
2022-03-28 10:26:35 +13:00
def handle_params(params, uri, socket) do
{:noreply, assign(socket, params: params, uri: uri)}
2022-03-26 10:17:01 +13:00
end
2022-03-28 10:26:35 +13:00
def handle_event("change-versions", %{"versions" => versions}, socket) do
{:noreply,
socket
|> assign(:selected_versions, versions)
|> load_docs()
|> push_event("selected-versions", versions)}
2022-03-26 10:17:01 +13:00
end
def handle_event("toggle_theme", _, socket) do
theme =
case socket.assigns.configured_theme do
"light" ->
"dark"
"dark" ->
"light"
end
{:noreply,
socket
|> assign(:configured_theme, theme)
|> push_event("set_theme", %{theme: theme})}
end
2022-03-28 10:26:35 +13:00
defp load_docs(socket) do
new_libraries =
socket.assigns.libraries
|> Enum.map(fn library ->
Map.update!(library, :versions, fn versions ->
Enum.map(versions, fn version ->
if version.id == socket.assigns[:selected_versions][library.id] do
dsls_query = Ash.Query.sort(AshHq.Docs.Dsl, order: :asc)
options_query = Ash.Query.sort(AshHq.Docs.Option, order: :asc)
extensions_query =
AshHq.Docs.Extension
|> Ash.Query.sort(order: :asc)
|> Ash.Query.load(options: options_query, dsls: dsls_query)
2022-03-29 08:47:43 +13:00
AshHq.Docs.load!(version, extensions: extensions_query, guides: :url_safe_name)
2022-03-28 10:26:35 +13:00
else
version
end
end)
end)
end)
assign(socket, :libraries, new_libraries)
2022-03-26 10:17:01 +13:00
end
2022-03-28 10:26:35 +13:00
def mount(_params, session, socket) do
configured_theme = session["theme"] || "dark"
2022-03-26 10:17:01 +13:00
2022-03-28 10:26:35 +13:00
configured_library_versions =
case session["selected_versions"] do
nil ->
%{}
"" ->
%{}
value ->
value
|> String.split(",")
|> Map.new(fn str ->
str
|> String.split(":")
|> List.to_tuple()
end)
2022-03-26 10:17:01 +13:00
end
2022-03-28 10:26:35 +13:00
socket =
socket
|> assign(:selected_versions, configured_library_versions)
|> AshPhoenix.LiveView.keep_live(
:libraries,
fn _socket ->
versions_query =
AshHq.Docs.LibraryVersion
|> Ash.Query.sort(version: :desc)
|> Ash.Query.filter(processed == true)
2022-03-29 08:47:43 +13:00
|> Ash.Query.deselect(:data)
2022-03-28 10:26:35 +13:00
AshHq.Docs.Library.read!(load: [versions: versions_query])
end,
after_fetch: fn results, socket ->
selected_versions =
Enum.reduce(results, socket.assigns[:selected_versions] || %{}, fn library, acc ->
case Enum.at(library.versions, 0) do
nil ->
acc
version ->
Map.put_new(acc, library.id, version.id)
end
end)
socket
|> assign(
:selected_versions,
selected_versions
)
|> push_event("selected_versions", selected_versions)
end
)
|> load_docs()
2022-03-26 10:17:01 +13:00
2022-03-28 10:26:35 +13:00
{:ok, assign(socket, configured_theme: configured_theme)}
2022-03-26 10:17:01 +13:00
end
2022-03-28 10:26:35 +13:00
def toggle_search(js \\ %JS{}) do
js
|> JS.dispatch("js:noscroll-main", to: "#search-box")
|> JS.toggle(
2022-03-29 11:05:19 +13:00
in: "fade-in transition",
out: "fade-out transition",
to: "#search-box"
2022-03-28 10:26:35 +13:00
)
|> JS.dispatch("js:focus", to: "#search-input")
2022-03-26 10:17:01 +13:00
end
2022-03-28 10:26:35 +13:00
def close_search(js \\ %JS{}) do
js
|> JS.dispatch("js:noscroll-main", to: "#search-box")
|> JS.hide(
2022-03-29 11:05:19 +13:00
transition: "fade-out",
to: "#search-box"
2022-03-28 10:26:35 +13:00
)
|> JS.dispatch("js:focus", to: "#search-input")
2022-03-26 10:17:01 +13:00
end
end