devel #36
30 changed files with 235 additions and 120 deletions
|
@ -14,7 +14,7 @@ const plugins = [
|
||||||
]
|
]
|
||||||
|
|
||||||
let opts = {
|
let opts = {
|
||||||
entryPoints: ['js/app.js'],
|
entryPoints: ['js/app.js', 'js/public.js'],
|
||||||
bundle: true,
|
bundle: true,
|
||||||
target: 'es2017',
|
target: 'es2017',
|
||||||
outdir: '../priv/static/assets',
|
outdir: '../priv/static/assets',
|
||||||
|
|
|
@ -54,6 +54,10 @@
|
||||||
@apply underline decoration-2 decoration-theme-primary;
|
@apply underline decoration-2 decoration-theme-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prose img {
|
||||||
|
@apply rounded;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set width and color for identity icons */
|
/* Set width and color for identity icons */
|
||||||
a[rel] svg {
|
a[rel] svg {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
|
|
|
@ -35,3 +35,8 @@
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lightbox span img {
|
||||||
|
width: 75%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
17
assets/js/public.js
Normal file
17
assets/js/public.js
Normal file
|
@ -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")
|
||||||
|
}
|
||||||
|
})
|
|
@ -9,9 +9,13 @@ defmodule Chiya.Channels do
|
||||||
alias Chiya.Notes.Note
|
alias Chiya.Notes.Note
|
||||||
|
|
||||||
@preloads [:notes]
|
@preloads [:notes]
|
||||||
@public_preloads [notes: (from n in Note,
|
@public_preloads [
|
||||||
where: not is_nil(n.published_at),
|
notes:
|
||||||
order_by: [desc: n.published_at])]
|
from(n in Note,
|
||||||
|
where: not is_nil(n.published_at),
|
||||||
|
order_by: [desc: n.published_at]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns the list of channels.
|
Returns the list of channels.
|
||||||
|
|
|
@ -21,7 +21,7 @@ defmodule Chiya.Notes do
|
||||||
"""
|
"""
|
||||||
def list_notes do
|
def list_notes do
|
||||||
Note
|
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.all()
|
||||||
|> Repo.preload(@preloads)
|
|> Repo.preload(@preloads)
|
||||||
end
|
end
|
||||||
|
@ -70,7 +70,6 @@ defmodule Chiya.Notes do
|
||||||
|
|
||||||
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 """
|
@doc """
|
||||||
Creates a note.
|
Creates a note.
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@ defmodule ChiyaWeb do
|
||||||
those modules here.
|
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
|
def router do
|
||||||
quote do
|
quote do
|
||||||
|
@ -56,6 +57,9 @@ defmodule ChiyaWeb do
|
||||||
use Phoenix.LiveView,
|
use Phoenix.LiveView,
|
||||||
layout: {ChiyaWeb.Layouts, :app}
|
layout: {ChiyaWeb.Layouts, :app}
|
||||||
|
|
||||||
|
# Import admin components
|
||||||
|
import ChiyaWeb.AdminComponents
|
||||||
|
|
||||||
unquote(html_helpers())
|
unquote(html_helpers())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -78,6 +82,25 @@ defmodule ChiyaWeb do
|
||||||
|
|
||||||
# Include general helpers for rendering HTML
|
# Include general helpers for rendering HTML
|
||||||
unquote(html_helpers())
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -93,7 +116,6 @@ defmodule ChiyaWeb do
|
||||||
alias Phoenix.LiveView.JS
|
alias Phoenix.LiveView.JS
|
||||||
|
|
||||||
# Custom functions
|
# Custom functions
|
||||||
import ChiyaWeb.AdminComponents
|
|
||||||
import ChiyaWeb.Format, only: [from_now: 1, pretty_date: 1]
|
import ChiyaWeb.Format, only: [from_now: 1, pretty_date: 1]
|
||||||
alias ChiyaWeb.Markdown
|
alias ChiyaWeb.Markdown
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule ChiyaWeb.AdminComponents do
|
defmodule ChiyaWeb.AdminComponents do
|
||||||
|
use Phoenix.Component
|
||||||
|
|
||||||
use Phoenix.Component
|
|
||||||
use Phoenix.VerifiedRoutes,
|
use Phoenix.VerifiedRoutes,
|
||||||
endpoint: ChiyaWeb.Endpoint,
|
endpoint: ChiyaWeb.Endpoint,
|
||||||
router: ChiyaWeb.Router,
|
router: ChiyaWeb.Router,
|
||||||
|
@ -8,6 +8,15 @@ defmodule ChiyaWeb.AdminComponents do
|
||||||
|
|
||||||
import ChiyaWeb.CoreComponents
|
import ChiyaWeb.CoreComponents
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders a horizontal line
|
||||||
|
"""
|
||||||
|
def line(assigns) do
|
||||||
|
~H"""
|
||||||
|
<hr class="my-6 dark:border-gray-700" />
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Renders a UI for uploading files
|
Renders a UI for uploading files
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule ChiyaWeb.CoreComponents do
|
||||||
Icons are provided by [heroicons](https://heroicons.com). See `icon/1` for usage.
|
Icons are provided by [heroicons](https://heroicons.com). See `icon/1` for usage.
|
||||||
"""
|
"""
|
||||||
use Phoenix.Component
|
use Phoenix.Component
|
||||||
|
|
||||||
use Phoenix.VerifiedRoutes,
|
use Phoenix.VerifiedRoutes,
|
||||||
endpoint: ChiyaWeb.Endpoint,
|
endpoint: ChiyaWeb.Endpoint,
|
||||||
router: ChiyaWeb.Router,
|
router: ChiyaWeb.Router,
|
||||||
|
@ -19,23 +20,13 @@ defmodule ChiyaWeb.CoreComponents do
|
||||||
|
|
||||||
def favicon(assigns) do
|
def favicon(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png" />
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png" />
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png" />
|
||||||
<link rel="manifest" href="/favicon/site.webmanifest">
|
<link rel="manifest" href="/favicon/site.webmanifest" />
|
||||||
<link rel="mask-icon" href="/favicon/safari-pinned-tab.svg" color="#5bbad5">
|
<link rel="mask-icon" href="/favicon/safari-pinned-tab.svg" color="#5bbad5" />
|
||||||
<meta name="msapplication-TileColor" content="#da532c">
|
<meta name="msapplication-TileColor" content="#da532c" />
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff" />
|
||||||
"""
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Renders a horizontal line
|
|
||||||
"""
|
|
||||||
def line(assigns) do
|
|
||||||
~H"""
|
|
||||||
<hr class="my-6 dark:border-gray-700" />
|
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -176,8 +167,10 @@ defmodule ChiyaWeb.CoreComponents do
|
||||||
role="alert"
|
role="alert"
|
||||||
class={[
|
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",
|
"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 == :info &&
|
||||||
@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"
|
"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}
|
{@rest}
|
||||||
>
|
>
|
||||||
|
@ -526,7 +519,11 @@ defmodule ChiyaWeb.CoreComponents do
|
||||||
phx-update={match?(%Phoenix.LiveView.LiveStream{}, @rows) && "stream"}
|
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"
|
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"
|
||||||
>
|
>
|
||||||
<tr :for={row <- @rows} id={@row_id && @row_id.(row)} class="group hover:bg-gray-50 dark:hover:bg-gray-800">
|
<tr
|
||||||
|
:for={row <- @rows}
|
||||||
|
id={@row_id && @row_id.(row)}
|
||||||
|
class="group hover:bg-gray-50 dark:hover:bg-gray-800"
|
||||||
|
>
|
||||||
<td
|
<td
|
||||||
:for={{col, i} <- Enum.with_index(@col)}
|
:for={{col, i} <- Enum.with_index(@col)}
|
||||||
phx-click={@row_click && @row_click.(row)}
|
phx-click={@row_click && @row_click.(row)}
|
||||||
|
@ -576,7 +573,9 @@ defmodule ChiyaWeb.CoreComponents do
|
||||||
<div class="mt-14">
|
<div class="mt-14">
|
||||||
<dl class="-my-4 divide-y divide-gray-100 dark:divide-gray-800">
|
<dl class="-my-4 divide-y divide-gray-100 dark:divide-gray-800">
|
||||||
<div :for={item <- @item} class="flex gap-4 py-4 sm:gap-8">
|
<div :for={item <- @item} class="flex gap-4 py-4 sm:gap-8">
|
||||||
<dt class="w-1/4 flex-none text-[0.8125rem] leading-6 text-gray-500 dark:text-gray-300"><%= item.title %></dt>
|
<dt class="w-1/4 flex-none text-[0.8125rem] leading-6 text-gray-500 dark:text-gray-300">
|
||||||
|
<%= item.title %>
|
||||||
|
</dt>
|
||||||
<dd class="text-sm leading-6 text-gray-700 dark:text-gray-400"><%= render_slot(item) %></dd>
|
<dd class="text-sm leading-6 text-gray-700 dark:text-gray-400"><%= render_slot(item) %></dd>
|
||||||
</div>
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
<div class="flex items-center justify-end border-b border-theme-dim/50 py-3">
|
<div class="flex items-center justify-end border-b border-theme-dim/50 py-3">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<%= for channel <- @channels do %>
|
<%= for channel <- @channels do %>
|
||||||
<.link
|
<.link
|
||||||
href={~p"/#{channel.slug}"}
|
href={~p"/#{channel.slug}"}
|
||||||
class="text-xs font-semibold leading-6 text-theme-base hover:text-theme-base/75"
|
class="text-xs font-semibold leading-6 text-theme-base hover:text-theme-base/75"
|
||||||
>
|
>
|
||||||
<%= channel.name %>
|
<%= channel.name %>
|
||||||
</.link>
|
</.link>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<.favicon />
|
<.favicon />
|
||||||
|
|
||||||
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
|
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
|
||||||
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
|
<script defer phx-track-static type="text/javascript" src={~p"/assets/public.js"}>
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||||
|
@ -20,12 +20,14 @@
|
||||||
delete document.documentElement.dataset["mode"]
|
delete document.documentElement.dataset["mode"]
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style><%= @settings.custom_css %></style>
|
<style>
|
||||||
|
<%= @settings.custom_css %>
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-theme-background antialiased">
|
<body class="bg-theme-background antialiased">
|
||||||
<.admin_bar current_user={@current_user} />
|
<.admin_bar current_user={@current_user} />
|
||||||
<%= @inner_content %>
|
<%= @inner_content %>
|
||||||
|
|
||||||
<%= raw @settings.custom_html %>
|
<%= raw(@settings.custom_html) %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
17
lib/chiya_web/components/public_components.ex
Normal file
17
lib/chiya_web/components/public_components.ex
Normal file
|
@ -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"""
|
||||||
|
<hr class="my-6 border-theme-dim" />
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule ChiyaWeb.ApiController do
|
defmodule ChiyaWeb.ApiController do
|
||||||
use ChiyaWeb, :controller
|
use ChiyaWeb, :controller
|
||||||
|
|
||||||
def notes(conn, _params) do
|
def notes(conn, _params) do
|
||||||
notes = Chiya.Notes.list_notes()
|
notes = Chiya.Notes.list_notes()
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
</.header>
|
</.header>
|
||||||
|
|
||||||
<.table id="identities" rows={@identities} row_click={&JS.navigate(~p"/admin/identities/#{&1}")}>
|
<.table id="identities" rows={@identities} row_click={&JS.navigate(~p"/admin/identities/#{&1}")}>
|
||||||
<:col :let={identity} label="Icon"><%= raw identity.icon %></:col>
|
<:col :let={identity} label="Icon"><%= raw(identity.icon) %></:col>
|
||||||
<:col :let={identity} label="Name"><%= identity.name %></:col>
|
<:col :let={identity} label="Name"><%= identity.name %></:col>
|
||||||
<:col :let={identity} label="Rel"><%= identity.rel %></:col>
|
<:col :let={identity} label="Rel"><%= identity.rel %></:col>
|
||||||
<:col :let={identity} label="Url"><%= identity.url %></:col>
|
<:col :let={identity} label="Url"><%= identity.url %></:col>
|
||||||
|
|
|
@ -4,12 +4,17 @@ defmodule ChiyaWeb.PageController do
|
||||||
def home(conn, _params) do
|
def home(conn, _params) do
|
||||||
settings = conn.assigns.settings
|
settings = conn.assigns.settings
|
||||||
|
|
||||||
channel = case settings.home_channel_id do
|
channel =
|
||||||
nil -> nil
|
case settings.home_channel_id do
|
||||||
id -> Chiya.Channels.get_channel!(id) |> Chiya.Channels.preload_channel_public()
|
nil -> nil
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def channel(conn, %{"slug" => channel_slug}) do
|
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.get_channel_by_slug!(channel_slug)
|
||||||
|> Chiya.Channels.preload_channel_public()
|
|> 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
|
end
|
||||||
|
|
||||||
def note(conn, %{"slug" => note_slug}) do
|
def note(conn, %{"slug" => note_slug}) do
|
||||||
|
@ -26,7 +35,11 @@ defmodule ChiyaWeb.PageController do
|
||||||
if is_nil(note.published_at) do
|
if is_nil(note.published_at) do
|
||||||
render_error(conn, :not_found)
|
render_error(conn, :not_found)
|
||||||
else
|
else
|
||||||
render(conn, :note, layout: {ChiyaWeb.Layouts, "public.html"}, note: note, page_title: note.name)
|
render(conn, :note,
|
||||||
|
layout: {ChiyaWeb.Layouts, "public.html"},
|
||||||
|
note: note,
|
||||||
|
page_title: note.name
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule ChiyaWeb.PageHTML do
|
defmodule ChiyaWeb.PageHTML do
|
||||||
use ChiyaWeb, :html
|
use ChiyaWeb, :html_public
|
||||||
|
|
||||||
embed_templates "page_html/*"
|
embed_templates "page_html/*"
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,10 @@
|
||||||
|
|
||||||
<div class="w-full mt-6 sm:w-auto flex flex-col gap-1.5">
|
<div class="w-full mt-6 sm:w-auto flex flex-col gap-1.5">
|
||||||
<%= for note <- @channel.notes do %>
|
<%= for note <- @channel.notes do %>
|
||||||
<a href={~p"/n/#{note.slug}"} class="rounded -mx-2 -my-0.5 px-2 py-0.5 hover:bg-theme-primary/10 transition">
|
<a
|
||||||
|
href={~p"/n/#{note.slug}"}
|
||||||
|
class="rounded -mx-2 -my-0.5 px-2 py-0.5 hover:bg-theme-primary/10 transition"
|
||||||
|
>
|
||||||
<span class="text-theme-heading text-lg font-semibold leading-8"><%= note.name %></span>
|
<span class="text-theme-heading text-lg font-semibold leading-8"><%= note.name %></span>
|
||||||
<span class="text-theme-base text-sm"><%= pretty_date(note.published_at) %></span>
|
<span class="text-theme-base text-sm"><%= pretty_date(note.published_at) %></span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
href={identity.url}
|
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"
|
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 %>
|
<%= identity.name %>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,8 +26,13 @@
|
||||||
<%= if @channel do %>
|
<%= if @channel do %>
|
||||||
<div class="w-full mt-6 sm:w-auto flex flex-col gap-1.5">
|
<div class="w-full mt-6 sm:w-auto flex flex-col gap-1.5">
|
||||||
<%= for note <- @channel.notes do %>
|
<%= for note <- @channel.notes do %>
|
||||||
<a href={~p"/n/#{note.slug}"} class="rounded -mx-2 -my-0.5 px-2 py-0.5 hover:bg-theme-primary/10 transition">
|
<a
|
||||||
<span class="text-theme-heading text-lg font-semibold leading-8"><%= note.name %></span>
|
href={~p"/n/#{note.slug}"}
|
||||||
|
class="rounded -mx-2 -my-0.5 px-2 py-0.5 hover:bg-theme-primary/10 transition"
|
||||||
|
>
|
||||||
|
<span class="text-theme-heading text-lg font-semibold leading-8">
|
||||||
|
<%= note.name %>
|
||||||
|
</span>
|
||||||
<span class="text-theme-base text-sm"><%= pretty_date(note.published_at) %></span>
|
<span class="text-theme-base text-sm"><%= pretty_date(note.published_at) %></span>
|
||||||
</a>
|
</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,35 +1,39 @@
|
||||||
<header>
|
<div class="px-4 py-10 sm:py-28 sm:px-6 lg:px-8 xl:py-32 xl:px-28">
|
||||||
<h1 class="text-3xl font-semibold leading-8 text-theme-heading font-serif underline underline-offset-2 decoration-theme-primary">
|
<div class="mx-auto max-w-xl lg:mx-0">
|
||||||
<%= @note.name %>
|
<header>
|
||||||
</h1>
|
<h1 class="text-3xl font-semibold leading-8 text-theme-heading font-serif underline underline-offset-2 decoration-theme-primary">
|
||||||
<p class="mt-2 text-sm leading-6 text-theme-base font-semibold">
|
<%= @note.name %>
|
||||||
<%= pretty_date(@note.published_at) %>
|
</h1>
|
||||||
</p>
|
<p class="mt-2 text-sm leading-6 text-theme-base font-semibold">
|
||||||
</header>
|
<%= pretty_date(@note.published_at) %>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="prose mt-8">
|
||||||
|
<%= Markdown.render(@note.content) |> raw %>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="prose mt-8">
|
<%= if !Enum.empty?(@note.images) do %>
|
||||||
<%= Markdown.render(@note.content) |> raw %>
|
<.line />
|
||||||
</section>
|
|
||||||
|
|
||||||
<%= if !Enum.empty?(@note.images) do %>
|
<div class="flex flex-wrap gap-3" id="images">
|
||||||
<.line />
|
<%= for image <- @note.images do %>
|
||||||
|
<article>
|
||||||
|
<a href={"#image-#{image.id}"}>
|
||||||
|
<img
|
||||||
|
class="rounded-lg w-28 border"
|
||||||
|
src={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :thumb_dithered)}
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<a href="#images" class="lightbox" id={"image-#{image.id}"}>
|
||||||
|
<span>
|
||||||
|
<img src={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :full_dithered)} loading="lazy" />
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-3" id="images">
|
</article>
|
||||||
<%= for image <- @note.images do %>
|
<% end %>
|
||||||
<article>
|
</div>
|
||||||
<a href={"#image-#{image.id}"}>
|
|
||||||
<img
|
|
||||||
class="rounded-lg w-28 border"
|
|
||||||
src={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :thumb_dithered)}
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a href="#images" class="lightbox" id={"image-#{image.id}"}>
|
|
||||||
<span style={"background-image: url('#{ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :full_dithered)}')"}>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</article>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ defmodule ChiyaWeb.SettingHTML do
|
||||||
"""
|
"""
|
||||||
attr :changeset, Ecto.Changeset, required: true
|
attr :changeset, Ecto.Changeset, required: true
|
||||||
attr :action, :string, required: true
|
attr :action, :string, required: true
|
||||||
|
attr :channels, :list, required: true
|
||||||
|
|
||||||
def setting_form(assigns)
|
def setting_form(assigns)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
defmodule ChiyaWeb.Error do
|
defmodule ChiyaWeb.Error do
|
||||||
import Plug.Conn, only: [put_status: 2]
|
import Plug.Conn, only: [put_status: 2]
|
||||||
import Phoenix.Controller, only: [put_view: 2, render: 3]
|
import Phoenix.Controller, only: [put_view: 2, render: 3]
|
||||||
|
|
||||||
def render_error(conn, :not_found, assigns \\ []) do
|
def render_error(conn, :not_found, assigns \\ []) do
|
||||||
conn
|
conn
|
||||||
|> put_status(:not_found)
|
|> put_status(:not_found)
|
||||||
|> put_view(ChiyaWeb.ErrorHTML)
|
|> put_view(ChiyaWeb.ErrorHTML)
|
||||||
|> render("404.html", assigns)
|
|> render("404.html", assigns)
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -30,5 +30,6 @@ defmodule ChiyaWeb.Format do
|
||||||
def pretty_date(%NaiveDateTime{} = date) do
|
def pretty_date(%NaiveDateTime{} = date) do
|
||||||
Calendar.strftime(date, "%d.%m.%Y")
|
Calendar.strftime(date, "%d.%m.%Y")
|
||||||
end
|
end
|
||||||
|
|
||||||
def pretty_date(_), do: ""
|
def pretty_date(_), do: ""
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,7 +40,7 @@ defmodule ChiyaWeb.NoteShowLive do
|
||||||
<article>
|
<article>
|
||||||
<a href={"#image-#{image.id}"}>
|
<a href={"#image-#{image.id}"}>
|
||||||
<img
|
<img
|
||||||
class="rounded-lg w-28 "
|
class="rounded-lg border border-theme-dim w-28"
|
||||||
src={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :thumb_dithered)}
|
src={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :thumb_dithered)}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
@ -56,7 +56,8 @@ defmodule ChiyaWeb.NoteShowLive do
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="#images" class="lightbox" id={"image-#{image.id}"}>
|
<a href="#images" class="lightbox" id={"image-#{image.id}"}>
|
||||||
<span style={"background-image: url('#{ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :full_dithered)}')"}>
|
<span>
|
||||||
|
<img src={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :full_dithered)} />
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
defmodule ChiyaWeb.Markdown do
|
defmodule ChiyaWeb.Markdown do
|
||||||
|
@options [
|
||||||
|
footnotes: true,
|
||||||
|
breaks: true,
|
||||||
|
escape: true
|
||||||
|
]
|
||||||
|
|
||||||
@options [
|
def render(markdown) do
|
||||||
footnotes: true,
|
markdown
|
||||||
breaks: true,
|
|> Earmark.as_html!(@options)
|
||||||
escape: true
|
end
|
||||||
]
|
|
||||||
|
|
||||||
def render(markdown) do
|
|
||||||
markdown
|
|
||||||
|> Earmark.as_html!(@options)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
6
mix.exs
6
mix.exs
|
@ -71,7 +71,11 @@ defmodule Chiya.MixProject do
|
||||||
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
|
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
|
||||||
"assets.setup": ["tailwind.install --if-missing", "cmd --cd assets npm install"],
|
"assets.setup": ["tailwind.install --if-missing", "cmd --cd assets npm install"],
|
||||||
"assets.build": ["tailwind default", "cmd --cd assets node build.js"],
|
"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
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,14 @@ defmodule ChiyaWeb.IdentityControllerTest do
|
||||||
|
|
||||||
import Chiya.IdentitiesFixtures
|
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 %{
|
@update_attrs %{
|
||||||
active: false,
|
active: false,
|
||||||
name: "some updated name",
|
name: "some updated name",
|
||||||
|
|
Loading…
Reference in a new issue