diff --git a/assets/build.js b/assets/build.js index a1d8d11..b993d1a 100644 --- a/assets/build.js +++ b/assets/build.js @@ -14,7 +14,7 @@ const plugins = [ ] let opts = { - entryPoints: ['js/app.js'], + entryPoints: ['js/app.js', 'js/public.js'], bundle: true, target: 'es2017', outdir: '../priv/static/assets', diff --git a/assets/css/app.css b/assets/css/app.css index c526f3e..95f241d 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -54,6 +54,10 @@ @apply underline decoration-2 decoration-theme-primary; } +.prose img { + @apply rounded; +} + /* Set width and color for identity icons */ a[rel] svg { width: 1em; diff --git a/assets/css/lightbox.css b/assets/css/lightbox.css index c2754f9..8366b1a 100644 --- a/assets/css/lightbox.css +++ b/assets/css/lightbox.css @@ -35,3 +35,8 @@ background-size: contain; } +.lightbox span img { + width: 75%; + margin: 0 auto; +} + diff --git a/assets/js/public.js b/assets/js/public.js new file mode 100644 index 0000000..3af215d --- /dev/null +++ b/assets/js/public.js @@ -0,0 +1,17 @@ +import lolight from "../vendor/lolight" + +lolight("pre code") + +document + .querySelector("#dark-mode-toggle") + .addEventListener("click", (e) => { + e.preventDefault() + const data = document.documentElement.dataset + if (data["mode"] && data["mode"] == "dark") { + delete data["mode"] + window.localStorage.removeItem("theme") + } else { + data["mode"] = "dark" + window.localStorage.setItem("theme", "dark") + } + }) \ No newline at end of file diff --git a/lib/chiya/channels.ex b/lib/chiya/channels.ex index 6205e43..c06e0db 100644 --- a/lib/chiya/channels.ex +++ b/lib/chiya/channels.ex @@ -9,9 +9,13 @@ defmodule Chiya.Channels do alias Chiya.Notes.Note @preloads [:notes] - @public_preloads [notes: (from n in Note, - where: not is_nil(n.published_at), - order_by: [desc: n.published_at])] + @public_preloads [ + notes: + from(n in Note, + where: not is_nil(n.published_at), + order_by: [desc: n.published_at] + ) + ] @doc """ Returns the list of channels. @@ -56,7 +60,7 @@ defmodule Chiya.Channels do Gets a single channel by its slug with all associated entities preloaded. """ def get_channel_by_slug!(slug), do: Repo.get_by!(Channel, slug: slug) - + @doc """ Creates a channel. diff --git a/lib/chiya/channels/channel.ex b/lib/chiya/channels/channel.ex index 0500e86..5d18d16 100644 --- a/lib/chiya/channels/channel.ex +++ b/lib/chiya/channels/channel.ex @@ -12,7 +12,7 @@ defmodule Chiya.Channels.Channel do many_to_many :notes, Chiya.Notes.Note, join_through: "channels_notes", join_keys: [channel: :id, note: :id] - + timestamps() end diff --git a/lib/chiya/notes.ex b/lib/chiya/notes.ex index ab8b783..571c4c6 100644 --- a/lib/chiya/notes.ex +++ b/lib/chiya/notes.ex @@ -21,7 +21,7 @@ defmodule Chiya.Notes do """ def list_notes do Note - |> order_by([n], [desc: n.updated_at, desc: n.published_at]) + |> order_by([n], desc: n.updated_at, desc: n.published_at) |> Repo.all() |> Repo.preload(@preloads) end @@ -67,9 +67,8 @@ defmodule Chiya.Notes do """ def get_note_preloaded!(id), do: Repo.get!(Note, id) |> preload_note() - - def get_note_by_slug_preloaded!(slug), do: Repo.get_by!(Note, slug: slug) |> preload_note() + def get_note_by_slug_preloaded!(slug), do: Repo.get_by!(Note, slug: slug) |> preload_note() @doc """ Creates a note. diff --git a/lib/chiya_web.ex b/lib/chiya_web.ex index ab785de..330ed59 100644 --- a/lib/chiya_web.ex +++ b/lib/chiya_web.ex @@ -17,7 +17,8 @@ defmodule ChiyaWeb do those modules here. """ - def static_paths, do: ~w(assets fonts images favicon favicon.ico robots.txt browserconfig.xml site.webmanifest) + def static_paths, + do: ~w(assets fonts images favicon favicon.ico robots.txt browserconfig.xml site.webmanifest) def router do quote do @@ -56,6 +57,9 @@ defmodule ChiyaWeb do use Phoenix.LiveView, layout: {ChiyaWeb.Layouts, :app} + # Import admin components + import ChiyaWeb.AdminComponents + unquote(html_helpers()) end end @@ -78,6 +82,25 @@ defmodule ChiyaWeb do # Include general helpers for rendering HTML unquote(html_helpers()) + + # Import admin components + import ChiyaWeb.AdminComponents + end + end + + def html_public do + quote do + use Phoenix.Component + + # Import convenience functions from controllers + import Phoenix.Controller, + only: [get_csrf_token: 0, view_module: 1, view_template: 1] + + # Include general helpers for rendering HTML + unquote(html_helpers()) + + # Import public components + import ChiyaWeb.PublicComponents end end @@ -93,10 +116,9 @@ defmodule ChiyaWeb do alias Phoenix.LiveView.JS # Custom functions - import ChiyaWeb.AdminComponents import ChiyaWeb.Format, only: [from_now: 1, pretty_date: 1] alias ChiyaWeb.Markdown - + # Routes generation with the ~p sigil unquote(verified_routes()) end diff --git a/lib/chiya_web/components/admin_components.ex b/lib/chiya_web/components/admin_components.ex index cd71075..add47c0 100644 --- a/lib/chiya_web/components/admin_components.ex +++ b/lib/chiya_web/components/admin_components.ex @@ -1,6 +1,6 @@ defmodule ChiyaWeb.AdminComponents do + use Phoenix.Component - use Phoenix.Component use Phoenix.VerifiedRoutes, endpoint: ChiyaWeb.Endpoint, router: ChiyaWeb.Router, @@ -8,6 +8,15 @@ defmodule ChiyaWeb.AdminComponents do import ChiyaWeb.CoreComponents + @doc """ + Renders a horizontal line + """ + def line(assigns) do + ~H""" +
+ """ + end + @doc """ Renders a UI for uploading files """ @@ -139,4 +148,4 @@ defmodule ChiyaWeb.AdminComponents do defp upload_error_to_string(:too_large), do: "Too large" defp upload_error_to_string(:too_many_files), do: "You have selected too many files" defp upload_error_to_string(:not_accepted), do: "You have selected an unacceptable file type" -end \ No newline at end of file +end diff --git a/lib/chiya_web/components/core_components.ex b/lib/chiya_web/components/core_components.ex index a17cf83..8113a4c 100644 --- a/lib/chiya_web/components/core_components.ex +++ b/lib/chiya_web/components/core_components.ex @@ -9,6 +9,7 @@ defmodule ChiyaWeb.CoreComponents do Icons are provided by [heroicons](https://heroicons.com). See `icon/1` for usage. """ use Phoenix.Component + use Phoenix.VerifiedRoutes, endpoint: ChiyaWeb.Endpoint, router: ChiyaWeb.Router, @@ -19,23 +20,13 @@ defmodule ChiyaWeb.CoreComponents do def favicon(assigns) do ~H""" - - - - - - - - """ - end - - - @doc """ - Renders a horizontal line - """ - def line(assigns) do - ~H""" -
+ + + + + + + """ end @@ -176,8 +167,10 @@ defmodule ChiyaWeb.CoreComponents do role="alert" class={[ "fixed hidden top-2 right-2 w-80 sm:w-96 z-50 rounded-lg p-3 shadow-md shadow-gray-900/5 ring-1", - @kind == :info && "bg-emerald-50 text-emerald-800 ring-emerald-500 fill-cyan-900 dark:bg-emerald-900 dark:text-emerald-200 hover:opacity-40", - @kind == :error && "bg-rose-50 p-3 text-rose-900 shadow-md ring-rose-500 fill-rose-900 dark:bg-rose-900 dark:text-rose-200 hover:opacity-40" + @kind == :info && + "bg-emerald-50 text-emerald-800 ring-emerald-500 fill-cyan-900 dark:bg-emerald-900 dark:text-emerald-200 hover:opacity-40", + @kind == :error && + "bg-rose-50 p-3 text-rose-900 shadow-md ring-rose-500 fill-rose-900 dark:bg-rose-900 dark:text-rose-200 hover:opacity-40" ]} {@rest} > @@ -526,7 +519,11 @@ defmodule ChiyaWeb.CoreComponents do phx-update={match?(%Phoenix.LiveView.LiveStream{}, @rows) && "stream"} class="relative divide-y divide-gray-100 border-t border-gray-200 text-sm leading-6 text-gray-700 dark:text-gray-200 dark:border-gray-700 dark:divide-gray-800" > - +
-
<%= item.title %>
+
+ <%= item.title %> +
<%= render_slot(item) %>
diff --git a/lib/chiya_web/components/layouts/public.html.heex b/lib/chiya_web/components/layouts/public.html.heex index 45e71f3..7c2a7a0 100644 --- a/lib/chiya_web/components/layouts/public.html.heex +++ b/lib/chiya_web/components/layouts/public.html.heex @@ -2,12 +2,12 @@
<%= for channel <- @channels do %> - <.link - href={~p"/#{channel.slug}"} - class="text-xs font-semibold leading-6 text-theme-base hover:text-theme-base/75" - > - <%= channel.name %> - + <.link + href={~p"/#{channel.slug}"} + class="text-xs font-semibold leading-6 text-theme-base hover:text-theme-base/75" + > + <%= channel.name %> + <% end %>
diff --git a/lib/chiya_web/components/layouts/root_app.html.heex b/lib/chiya_web/components/layouts/root_app.html.heex index af16941..fdc13d9 100644 --- a/lib/chiya_web/components/layouts/root_app.html.heex +++ b/lib/chiya_web/components/layouts/root_app.html.heex @@ -7,7 +7,7 @@ <.live_title suffix={" · #{@settings.title}"}> <%= assigns[:page_title] || "Admin" %> - + <.favicon /> diff --git a/lib/chiya_web/components/layouts/root_public.html.heex b/lib/chiya_web/components/layouts/root_public.html.heex index 7ec655d..2ebbecd 100644 --- a/lib/chiya_web/components/layouts/root_public.html.heex +++ b/lib/chiya_web/components/layouts/root_public.html.heex @@ -7,11 +7,11 @@ <.live_title suffix={" · #{@settings.title}"}> <%= assigns[:page_title] || "Home" %> - + <.favicon /> - - + <.admin_bar current_user={@current_user} /> <%= @inner_content %> - <%= raw @settings.custom_html %> + <%= raw(@settings.custom_html) %> - \ No newline at end of file + diff --git a/lib/chiya_web/components/public_components.ex b/lib/chiya_web/components/public_components.ex new file mode 100644 index 0000000..ef5689d --- /dev/null +++ b/lib/chiya_web/components/public_components.ex @@ -0,0 +1,17 @@ +defmodule ChiyaWeb.PublicComponents do + use Phoenix.Component + + use Phoenix.VerifiedRoutes, + endpoint: ChiyaWeb.Endpoint, + router: ChiyaWeb.Router, + statics: ChiyaWeb.static_paths() + + @doc """ + Renders a horizontal line + """ + def line(assigns) do + ~H""" +
+ """ + end +end diff --git a/lib/chiya_web/controllers/api_controller.ex b/lib/chiya_web/controllers/api_controller.ex index 7f0cd01..da8553d 100644 --- a/lib/chiya_web/controllers/api_controller.ex +++ b/lib/chiya_web/controllers/api_controller.ex @@ -1,8 +1,8 @@ defmodule ChiyaWeb.ApiController do - use ChiyaWeb, :controller + use ChiyaWeb, :controller def notes(conn, _params) do notes = Chiya.Notes.list_notes() json(conn, %{notes: notes}) end -end \ No newline at end of file +end diff --git a/lib/chiya_web/controllers/identity_html/index.html.heex b/lib/chiya_web/controllers/identity_html/index.html.heex index d26a833..50072fe 100644 --- a/lib/chiya_web/controllers/identity_html/index.html.heex +++ b/lib/chiya_web/controllers/identity_html/index.html.heex @@ -8,7 +8,7 @@ <.table id="identities" rows={@identities} row_click={&JS.navigate(~p"/admin/identities/#{&1}")}> - <:col :let={identity} label="Icon"><%= raw identity.icon %> + <:col :let={identity} label="Icon"><%= raw(identity.icon) %> <:col :let={identity} label="Name"><%= identity.name %> <:col :let={identity} label="Rel"><%= identity.rel %> <:col :let={identity} label="Url"><%= identity.url %> diff --git a/lib/chiya_web/controllers/page_controller.ex b/lib/chiya_web/controllers/page_controller.ex index 2175a33..2abf172 100644 --- a/lib/chiya_web/controllers/page_controller.ex +++ b/lib/chiya_web/controllers/page_controller.ex @@ -4,12 +4,17 @@ defmodule ChiyaWeb.PageController do def home(conn, _params) do settings = conn.assigns.settings - channel = case settings.home_channel_id do - nil -> nil - id -> Chiya.Channels.get_channel!(id) |> Chiya.Channels.preload_channel_public() - end + channel = + case settings.home_channel_id do + nil -> nil + id -> Chiya.Channels.get_channel!(id) |> Chiya.Channels.preload_channel_public() + end - render(conn, :home, layout: {ChiyaWeb.Layouts, "public.html"}, channel: channel, page_title: "Home") + render(conn, :home, + layout: {ChiyaWeb.Layouts, "public.html"}, + channel: channel, + page_title: "Home" + ) end def channel(conn, %{"slug" => channel_slug}) do @@ -17,7 +22,11 @@ defmodule ChiyaWeb.PageController do Chiya.Channels.get_channel_by_slug!(channel_slug) |> Chiya.Channels.preload_channel_public() - render(conn, :channel, layout: {ChiyaWeb.Layouts, "public.html"}, channel: channel, page_title: channel.name) + render(conn, :channel, + layout: {ChiyaWeb.Layouts, "public.html"}, + channel: channel, + page_title: channel.name + ) end def note(conn, %{"slug" => note_slug}) do @@ -25,8 +34,12 @@ defmodule ChiyaWeb.PageController do if is_nil(note.published_at) do render_error(conn, :not_found) - else - render(conn, :note, layout: {ChiyaWeb.Layouts, "public.html"}, note: note, page_title: note.name) + else + render(conn, :note, + layout: {ChiyaWeb.Layouts, "public.html"}, + note: note, + page_title: note.name + ) end end end diff --git a/lib/chiya_web/controllers/page_html.ex b/lib/chiya_web/controllers/page_html.ex index c12bd37..a43f0ea 100644 --- a/lib/chiya_web/controllers/page_html.ex +++ b/lib/chiya_web/controllers/page_html.ex @@ -1,5 +1,5 @@ defmodule ChiyaWeb.PageHTML do - use ChiyaWeb, :html + use ChiyaWeb, :html_public embed_templates "page_html/*" end diff --git a/lib/chiya_web/controllers/page_html/channel.html.heex b/lib/chiya_web/controllers/page_html/channel.html.heex index 87f88f4..681f6a0 100644 --- a/lib/chiya_web/controllers/page_html/channel.html.heex +++ b/lib/chiya_web/controllers/page_html/channel.html.heex @@ -9,11 +9,14 @@
<%= for note <- @channel.notes do %> - + <%= note.name %> <%= pretty_date(note.published_at) %> <% end %>
- + diff --git a/lib/chiya_web/controllers/page_html/home.html.heex b/lib/chiya_web/controllers/page_html/home.html.heex index 408631f..14f12d2 100644 --- a/lib/chiya_web/controllers/page_html/home.html.heex +++ b/lib/chiya_web/controllers/page_html/home.html.heex @@ -16,7 +16,7 @@ href={identity.url} class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-theme-primary/10 transition" > - <%= raw identity.icon %> + <%= raw(identity.icon) %> <%= identity.name %> @@ -26,8 +26,13 @@ <%= if @channel do %>
<%= for note <- @channel.notes do %> - - <%= note.name %> + + + <%= note.name %> + <%= pretty_date(note.published_at) %> <% end %> diff --git a/lib/chiya_web/controllers/page_html/note.html.heex b/lib/chiya_web/controllers/page_html/note.html.heex index 0337a79..d9a91ee 100644 --- a/lib/chiya_web/controllers/page_html/note.html.heex +++ b/lib/chiya_web/controllers/page_html/note.html.heex @@ -1,35 +1,39 @@ -
-

- <%= @note.name %> -

-

- <%= pretty_date(@note.published_at) %> -

-
+
+
+
+

+ <%= @note.name %> +

+

+ <%= pretty_date(@note.published_at) %> +

+
+
+ <%= Markdown.render(@note.content) |> raw %> +
-
- <%= Markdown.render(@note.content) |> raw %> -
+ <%= if !Enum.empty?(@note.images) do %> + <.line /> -<%= if !Enum.empty?(@note.images) do %> - <.line /> - -
- <%= for image <- @note.images do %> - +
+ <%= for image <- @note.images do %> + + <% end %> +
<% end %>
-<% end %> - +
diff --git a/lib/chiya_web/controllers/setting_html.ex b/lib/chiya_web/controllers/setting_html.ex index a1808ef..6b4aad8 100644 --- a/lib/chiya_web/controllers/setting_html.ex +++ b/lib/chiya_web/controllers/setting_html.ex @@ -8,6 +8,7 @@ defmodule ChiyaWeb.SettingHTML do """ attr :changeset, Ecto.Changeset, required: true attr :action, :string, required: true + attr :channels, :list, required: true def setting_form(assigns) end diff --git a/lib/chiya_web/error.ex b/lib/chiya_web/error.ex index c628a48..36849a8 100644 --- a/lib/chiya_web/error.ex +++ b/lib/chiya_web/error.ex @@ -1,11 +1,11 @@ defmodule ChiyaWeb.Error do - import Plug.Conn, only: [put_status: 2] - import Phoenix.Controller, only: [put_view: 2, render: 3] + import Plug.Conn, only: [put_status: 2] + import Phoenix.Controller, only: [put_view: 2, render: 3] - def render_error(conn, :not_found, assigns \\ []) do - conn - |> put_status(:not_found) - |> put_view(ChiyaWeb.ErrorHTML) - |> render("404.html", assigns) - end -end \ No newline at end of file + def render_error(conn, :not_found, assigns \\ []) do + conn + |> put_status(:not_found) + |> put_view(ChiyaWeb.ErrorHTML) + |> render("404.html", assigns) + end +end diff --git a/lib/chiya_web/format.ex b/lib/chiya_web/format.ex index 982546f..32d6ce3 100644 --- a/lib/chiya_web/format.ex +++ b/lib/chiya_web/format.ex @@ -30,5 +30,6 @@ defmodule ChiyaWeb.Format do def pretty_date(%NaiveDateTime{} = date) do Calendar.strftime(date, "%d.%m.%Y") end + def pretty_date(_), do: "" end diff --git a/lib/chiya_web/live/note_show_live.ex b/lib/chiya_web/live/note_show_live.ex index 6ca17d3..3189156 100644 --- a/lib/chiya_web/live/note_show_live.ex +++ b/lib/chiya_web/live/note_show_live.ex @@ -40,7 +40,7 @@ defmodule ChiyaWeb.NoteShowLive do
@@ -56,7 +56,8 @@ defmodule ChiyaWeb.NoteShowLive do

- + +
diff --git a/lib/chiya_web/markdown.ex b/lib/chiya_web/markdown.ex index 6fd73b0..cad2760 100644 --- a/lib/chiya_web/markdown.ex +++ b/lib/chiya_web/markdown.ex @@ -1,14 +1,12 @@ defmodule ChiyaWeb.Markdown do + @options [ + footnotes: true, + breaks: true, + escape: true + ] - @options [ - footnotes: true, - breaks: true, - escape: true - ] - - def render(markdown) do - markdown - |> Earmark.as_html!(@options) - end - + def render(markdown) do + markdown + |> Earmark.as_html!(@options) + end end diff --git a/mix.exs b/mix.exs index 13db5b5..c2f30d2 100644 --- a/mix.exs +++ b/mix.exs @@ -71,7 +71,11 @@ defmodule Chiya.MixProject do test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"], "assets.setup": ["tailwind.install --if-missing", "cmd --cd assets npm install"], "assets.build": ["tailwind default", "cmd --cd assets node build.js"], - "assets.deploy": ["tailwind default --minify", "cmd --cd assets node build.js --deploy", "phx.digest"] + "assets.deploy": [ + "tailwind default --minify", + "cmd --cd assets node build.js --deploy", + "phx.digest" + ] ] end end diff --git a/priv/repo/migrations/20230308191004_create_note_images.exs b/priv/repo/migrations/20230308191004_create_note_images.exs index 91f519d..77e0c6c 100644 --- a/priv/repo/migrations/20230308191004_create_note_images.exs +++ b/priv/repo/migrations/20230308191004_create_note_images.exs @@ -12,4 +12,4 @@ defmodule Chiya.Repo.Migrations.CreateNoteImages do create index(:note_images, [:note_id]) end -end \ No newline at end of file +end diff --git a/test/chiya/identities_test.exs b/test/chiya/identities_test.exs index 4e103a1..3181d9a 100644 --- a/test/chiya/identities_test.exs +++ b/test/chiya/identities_test.exs @@ -26,7 +26,7 @@ defmodule Chiya.IdentitiesTest do name: "some name", public: true, rel: "some rel", - url: "some url", + url: "some url", icon: "some icon" } diff --git a/test/chiya_web/controllers/identity_controller_test.exs b/test/chiya_web/controllers/identity_controller_test.exs index 46acd4d..458dfaa 100644 --- a/test/chiya_web/controllers/identity_controller_test.exs +++ b/test/chiya_web/controllers/identity_controller_test.exs @@ -3,7 +3,14 @@ defmodule ChiyaWeb.IdentityControllerTest do import Chiya.IdentitiesFixtures - @create_attrs %{active: true, name: "some name", public: true, rel: "some rel", url: "some url", icon: "some icon"} + @create_attrs %{ + active: true, + name: "some name", + public: true, + rel: "some rel", + url: "some url", + icon: "some icon" + } @update_attrs %{ active: false, name: "some updated name",