diff --git a/assets/css/app.css b/assets/css/app.css index ede15d5..c753ca9 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -73,6 +73,7 @@ @custom-variant phx-click-loading (.phx-click-loading&, .phx-click-loading &); @custom-variant phx-submit-loading (.phx-submit-loading&, .phx-submit-loading &); @custom-variant phx-change-loading (.phx-change-loading&, .phx-change-loading &); +@custom-variant sidebar (body.sidebar-layout &); /* Make LiveView wrapper divs transparent for layout */ [data-phx-session] { @@ -551,6 +552,7 @@ code .hljs-deletion { } } + @media print { @page { size: A4 portrait; diff --git a/assets/js/app.js b/assets/js/app.js index 5f04cf7..296bc71 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -40,9 +40,24 @@ hljs.registerLanguage("javascript", javascript); hljs.registerLanguage("lua", lua); const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content"); + +let Hooks = {}; +Hooks.Layout = { + mounted() { + if (localStorage.getItem("layout") === "sidebar") { + document.body.classList.add("sidebar-layout"); + } + } +}; + +window.addEventListener("save-layout", () => { + localStorage.setItem("layout", document.body.classList.contains("sidebar-layout") ? "sidebar" : "minimal"); +}); + const liveSocket = new LiveSocket("/live", Socket, { longPollFallbackMs: 2500, params: { _csrf_token: csrfToken }, + hooks: Hooks, }); // Show progress bar on live navigation and form submits diff --git a/lib/alchemy_pub_web/components/layouts.ex b/lib/alchemy_pub_web/components/layouts.ex index eab2f20..9191d22 100644 --- a/lib/alchemy_pub_web/components/layouts.ex +++ b/lib/alchemy_pub_web/components/layouts.ex @@ -31,7 +31,7 @@ defmodule AlchemyPubWeb.Layouts do def app(assigns) do ~H""" -
+
<.flash_group flash={@flash} /> {render_slot(@inner_block)}
diff --git a/lib/alchemy_pub_web/page_live.ex b/lib/alchemy_pub_web/page_live.ex index d81746e..d16aeac 100644 --- a/lib/alchemy_pub_web/page_live.ex +++ b/lib/alchemy_pub_web/page_live.ex @@ -53,7 +53,8 @@ defmodule AlchemyPubWeb.PageLive do mute: false, all_pages: false, has_next: false, - admin: admin + admin: admin, + nav_section: nil ) |> stream_configure(:deck, []) |> stream(:deck, [])} @@ -151,6 +152,13 @@ defmodule AlchemyPubWeb.PageLive do {:noreply, socket} end + @impl true + def handle_event("toggle_nav", %{"section" => section}, socket) do + section = String.to_existing_atom(section) + nav_section = if socket.assigns.nav_section == section, do: nil, else: section + {:noreply, assign(socket, nav_section: nav_section)} + end + @impl true def handle_info({:add, _title}, socket) do {:noreply, socket |> rebuild(socket.assigns.params)} @@ -268,7 +276,20 @@ defmodule AlchemyPubWeb.PageLive do visible_pages |> filter_rank(:deck)} end - socket |> assign(posts: posts, pages: pages, decks: decks, tags: tags, params: params) + title = socket.assigns[:title] + tag = socket.assigns[:tag] + + natural_section = + cond do + tag != nil -> :tags + Enum.any?(posts, fn [t | _] -> t == title end) -> :articles + Enum.any?(decks, fn [t | _] -> t == title end) -> :decks + true -> nil + end + + nav_section = natural_section + + socket |> assign(posts: posts, pages: pages, decks: decks, tags: tags, params: params, nav_section: nav_section) end defp build_deck(socket, params, {title, meta, content}) do diff --git a/lib/alchemy_pub_web/page_live.html.heex b/lib/alchemy_pub_web/page_live.html.heex index de786ec..736f691 100644 --- a/lib/alchemy_pub_web/page_live.html.heex +++ b/lib/alchemy_pub_web/page_live.html.heex @@ -1,129 +1,237 @@ -
-
-
- -
- {raw(@page_title)} -
-
- +
+ <.link + :for={[title, _, _, meta] <- @decks} + class={["px-2 py-0.5", @title == title && "font-semibold underline underline-offset-4"]} + patch={"/#{title}"} + > + {raw(meta["title"])} + +
+
+ <.link + :for={{tag, title} <- @tags} + class={["px-2 py-0.5", @tag == tag && "font-semibold underline underline-offset-4"]} + patch={"/tag/#{tag}"} + > + {title} + +
+
+
+ +
+