ash_hq/lib/ash_hq_web/views/app_view_live.ex

403 lines
12 KiB
Elixir
Raw Normal View History

2022-03-26 10:17:01 +13:00
defmodule AshHqWeb.AppViewLive do
# credo:disable-for-this-file Credo.Check.Readability.MaxLineLength
2022-03-26 10:17:01 +13:00
use Surface.LiveView,
container: {:div, class: "h-full"}
alias AshHqWeb.Components.AppView.TopBar
alias AshHqWeb.Components.{CatalogueModal, Search}
alias AshHqWeb.Pages.{Ashley, Blog, Docs, Forum, Home, Media, UserSettings}
2022-03-26 10:17:01 +13:00
alias Phoenix.LiveView.JS
alias Surface.Components.Context
2022-03-28 10:26:35 +13:00
require Ash.Query
2022-03-26 10:17:01 +13:00
2022-12-21 20:25:09 +13:00
import AshHqWeb.Tails
data(configured_theme, :string, default: :system)
data(selected_versions, :map, default: %{})
data(libraries, :list, default: [])
data(selected_types, :map, default: %{})
data(current_user, :map)
data(library, :any, default: nil)
data(extension, :any, default: nil)
data(docs, :any, default: nil)
data(library_version, :any, default: nil)
data(guide, :any, default: nil)
data(doc_path, :list, default: [])
data(dsls, :list, default: [])
data(dsl, :any, default: nil)
data(options, :list, default: [])
data(module, :any, default: nil)
def render(%{platform: :ios} = assigns) do
~F"""
{#case @live_action}
{#match :home}
<Home id="home" />
{/case}
"""
end
2022-03-26 10:17:01 +13:00
def render(assigns) do
~F"""
<div
id="app"
class={classes([@configured_theme, "h-full font-sans": true])}
2022-03-26 10:17:01 +13:00
phx-hook="ColorTheme"
>
2022-12-27 22:31:13 +13:00
<head>
<meta property="og:type" content="text/html">
<meta property="og:image" content="https://ash-hq.org/images/ash-logo-side.png">
2022-12-27 22:31:13 +13:00
<meta property="og:url" content={to_string(@uri)}>
<meta property="og:site_name" content="Ash HQ">
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:domain" content="ash-hq.org">
<meta property="twitter:site" content="@AshFramework">
<!-- Need to adjust this for future blog writers -->
<meta property="twitter:creator" content="@ZachSDaniel1">
{#if @live_action not in [:docs_dsl, :blog, :forum]}
2022-12-27 22:31:13 +13:00
<meta property="og:title" content="Ash Framework">
<meta
property="og:description"
content="A declarative foundation for ambitious Elixir applications. Model your domain, derive the rest."
/>
{/if}
</head>
<Search
id="search-box"
2023-01-05 05:18:04 +13:00
uri={@uri}
close={close_search()}
libraries={@libraries}
selected_types={@selected_types}
change_types="change-types"
2022-09-28 16:18:05 +13:00
selected_versions={@selected_versions}
change_versions="change-versions"
2022-09-28 16:18:05 +13:00
remove_version="remove_version"
/>
<CatalogueModal
id="catalogue-box"
libraries={@libraries}
selected_versions={@selected_versions}
2022-09-28 16:18:05 +13:00
change_versions="change-versions"
2023-02-01 05:13:42 +13:00
show_catalogue_call_to_action={@show_catalogue_call_to_action}
/>
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"
2022-04-02 08:11:17 +13:00
class={
"w-full min-h-screen bg-white dark:bg-base-dark-850 dark:text-white flex flex-col items-stretch",
"h-screen overflow-y-auto": @live_action != :docs_dsl
2022-04-02 08:11:17 +13:00
}
2022-03-28 10:26:35 +13:00
>
<TopBar
live_action={@live_action}
toggle_theme="toggle_theme"
configured_theme={@configured_theme}
current_user={@current_user}
/>
{#for flash <- List.wrap(live_flash(@flash, :error))}
<p class="alert alert-warning" role="alert">{flash}</p>
{/for}
{#for flash <- List.wrap(live_flash(@flash, :info))}
<p class="alert alert-info max-h-min" role="alert">{flash}</p>
{/for}
{#case @live_action}
{#match :home}
<Home id="home" device_brand={@device_brand} />
{#match :blog}
<Blog id="blog" params={@params} />
{#match :docs_dsl}
<Docs
id="docs"
uri={@uri}
params={@params}
remove_version="remove_version"
change_versions="change-versions"
selected_versions={@selected_versions}
libraries={@libraries}
2023-02-01 05:13:42 +13:00
show_catalogue_call_to_action={@show_catalogue_call_to_action}
/>
{#match :user_settings}
<UserSettings id="user_settings" current_user={@current_user} />
2022-12-18 21:40:51 +13:00
{#match :media}
<Media id="media" />
{#match :forum}
<Forum id="forum" params={@params} />
{#match :ashley}
<Ashley id="ashley" current_user={@current_user} params={@params} />
{/case}
2022-12-09 19:47:45 +13:00
{#if @live_action not in [:docs_dsl, :ashley]}
<footer class="p-8 sm:p-6 bg-base-light-200 dark:bg-base-dark-850 sm:justify-center sticky">
2022-10-23 00:51:22 +13:00
<div class="md:flex md:justify-around">
<div class="flex justify-center mb-6 md:mb-0">
<a href="/" class="flex items-center">
<img src="/images/ash-logo-side.svg" class="mr-3 h-32" alt="Ash Framework Logo">
</a>
</div>
2022-10-23 00:51:22 +13:00
<div class="grid grid-cols-3 gap-8 sm:gap-6">
<div>
<h2 class="mb-6 text-sm font-semibold text-gray-900 uppercase dark:text-white">Resources</h2>
<ul class="text-gray-600 dark:text-gray-400">
<li class="mb-4">
<a href="https://github.com/ash-project" class="hover:underline">Source</a>
</li>
<li class="mb-4">
<a href="/docs/guides/ash/latest/tutorials/get-started" class="hover:underline">Get Started</a>
2022-10-23 00:51:22 +13:00
</li>
2022-12-18 21:40:51 +13:00
<li class="mb-4">
<a href="/blog" class="hover:underline">Blog</a>
</li>
2022-12-18 21:40:51 +13:00
<li>
<a href="/media" class="hover:underline">Media</a>
</li>
2022-10-23 00:51:22 +13:00
</ul>
</div>
<div>
<h2 class="mb-6 text-sm font-semibold text-gray-900 uppercase dark:text-white">Community</h2>
<ul class="text-gray-600 dark:text-gray-400">
<li class="mb-4">
<a href="https://twitter.com/AshFramework" class="hover:underline">Twitter</a>
</li>
<li>
<a href="https://discord.gg/D7FNG2q" class="hover:underline">Discord</a>
</li>
</ul>
</div>
<div>
<h2 class="mb-6 text-sm font-semibold text-gray-900 uppercase dark:text-white">Help Us</h2>
<ul class="text-gray-600 dark:text-gray-400">
<li class="mb-4">
<a href="https://github.com/ash-project/ash_hq/issues/new/choose" class="hover:underline">Report an issue</a>
</li>
<li>
<a href="/docs/guides/ash/latest/how_to/contribute" class="hover:underline">Contribute</a>
2022-10-23 00:51:22 +13:00
</li>
</ul>
</div>
</div>
</div>
</footer>
{/if}
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,
socket
|> assign(params: params, uri: uri)}
2022-03-26 10:17:01 +13:00
end
def handle_info({:page_title, title}, socket) do
2023-01-18 17:53:21 +13:00
{:noreply, assign(socket, :page_title, "Ash Framework - #{title}")}
end
2023-02-01 05:13:42 +13:00
def handle_event("dismiss_catalogue_call_to_action", _, socket) do
{:noreply,
socket
|> assign(:show_catalogue_call_to_action, false)
|> push_event("catalogue-call-to-action-dismissed", %{})}
end
2022-08-31 20:11:15 +12:00
def handle_event("remove_version", %{"library" => library}, socket) do
new_selected_versions = Map.put(socket.assigns.selected_versions, library, "")
{:noreply,
socket
|> set_selected_library_versions(new_selected_versions)}
2022-08-31 20:11:15 +12:00
end
def handle_event("add_version", %{"library" => library}, socket) do
new_selected_versions = Map.put(socket.assigns.selected_versions, library, "latest")
{:noreply,
socket
|> set_selected_library_versions(new_selected_versions)}
2022-08-31 20:11:15 +12:00
end
2022-03-28 10:26:35 +13:00
def handle_event("change-versions", %{"versions" => versions}, socket) do
{:noreply,
socket
|> set_selected_library_versions(versions)}
2022-03-26 10:17:01 +13:00
end
2022-03-30 17:40:17 +13:00
def handle_event("change-types", %{"types" => types}, socket) do
types =
types
|> Enum.filter(fn {_, value} ->
value == "true"
end)
|> Enum.map(&elem(&1, 0))
{:noreply,
socket
|> assign(
:selected_types,
types
)
|> push_event("selected-types", %{types: types})}
end
2022-03-26 10:17:01 +13:00
def handle_event("toggle_theme", _, socket) do
theme =
case socket.assigns.configured_theme do
"light" ->
"dark"
"dark" ->
2022-04-02 11:49:26 +13:00
"system"
"system" ->
2022-03-26 10:17:01 +13:00
"light"
end
{:noreply,
socket
|> assign(:configured_theme, theme)
|> push_event("set_theme", %{theme: theme})}
end
def mount(_params, session, socket) do
socket = assign(socket, :page_title, "Ash Framework")
socket =
assign_new(socket, :user_agent, fn _assigns ->
get_connect_params(socket)["user_agent"]
end)
2023-01-19 16:03:23 +13:00
socket = assign(socket, :device_brand, "Apple")
socket = Context.put(socket, platform: socket.assigns.platform)
2022-04-02 11:49:26 +13:00
configured_theme = session["theme"] || "system"
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-30 17:40:17 +13:00
all_types = AshHq.Docs.Extensions.Search.Types.types()
selected_types =
case session["selected_types"] do
nil ->
AshHq.Docs.Extensions.Search.Types.types()
types ->
types
|> String.split(",")
|> Enum.filter(&(&1 in all_types))
end
2022-06-05 08:58:50 +12:00
versions_query =
AshHq.Docs.LibraryVersion
|> Ash.Query.sort(version: :desc)
libraries = AshHq.Docs.Library.read!(load: [versions: versions_query])
selected_versions =
2022-08-20 04:35:07 +12:00
Enum.reduce(libraries, configured_library_versions, fn library, acc ->
if library.name in ["ash", "ash_phoenix", "ash_postgres"] do
2022-08-31 20:11:15 +12:00
Map.put_new(acc, library.id, "latest")
else
Map.put_new(acc, library.id, "")
end
2022-06-05 08:58:50 +12:00
end)
2022-03-26 10:17:01 +13:00
2022-06-05 08:58:50 +12:00
{:ok,
socket
2023-02-01 05:13:42 +13:00
|> assign(
:show_catalogue_call_to_action,
session["catalogue_call_to_action_dismissed"] != "true"
)
2022-06-05 08:58:50 +12:00
|> assign(:libraries, libraries)
|> assign(
:selected_versions,
selected_versions
)
|> assign(
:selected_types,
selected_types
)
2022-09-13 13:25:03 +12:00
|> assign(configured_theme: configured_theme)
|> set_selected_library_versions(selected_versions)
|> push_event("selected_types", %{types: selected_types})}
2022-03-26 10:17:01 +13:00
end
defp set_selected_library_versions(socket, library_versions) do
socket
|> assign(:selected_versions, library_versions)
|> push_event("selected-versions", library_versions)
end
2022-03-28 10:26:35 +13:00
def toggle_search(js \\ %JS{}) do
js
|> JS.toggle(
2022-03-30 05:12:28 +13:00
to: "#search-box",
in: {
"transition ease-in duration-100",
"opacity-0",
"opacity-100"
},
out: {
"transition ease-out duration-75",
"opacity-100",
"opacity-0"
}
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-09-28 16:18:05 +13:00
def toggle_catalogue(js \\ %JS{}) do
js
|> JS.toggle(
to: "#catalogue-box",
in: {
"transition ease-in duration-100",
"opacity-0",
"opacity-100"
},
out: {
"transition ease-out duration-75",
"opacity-100",
"opacity-0"
}
)
|> JS.dispatch("phx:js:scroll-to", detail: %{id: "catalogue-box"})
2022-09-28 16:18:05 +13:00
end
2022-03-28 10:26:35 +13:00
def close_search(js \\ %JS{}) do
js
|> JS.hide(
2022-03-29 11:05:19 +13:00
transition: "fade-out",
to: "#search-box"
2022-03-28 10:26:35 +13:00
)
2022-09-28 16:18:05 +13:00
|> JS.hide(transition: "fade-out", to: "#search-versions")
|> JS.show(transition: "fade-in", to: "#search-body")
end
def close_catalogue(js \\ %JS{}) do
js
|> JS.hide(
transition: "fade-out",
to: "#catalogue-box"
)
2022-03-26 10:17:01 +13:00
end
end