devel #131
12 changed files with 259 additions and 201 deletions
|
@ -1,2 +1,3 @@
|
||||||
erlang 25.2.3
|
erlang 25.2.3
|
||||||
elixir 1.14.3-otp-25
|
elixir 1.14.3-otp-25
|
||||||
|
nodejs 18.16.0
|
||||||
|
|
|
@ -53,6 +53,8 @@ defmodule Chiya.Channels do
|
||||||
"""
|
"""
|
||||||
def get_channel!(id), do: Repo.get!(Channel, id)
|
def get_channel!(id), do: Repo.get!(Channel, id)
|
||||||
|
|
||||||
|
def get_channel(id), do: Repo.get(Channel, id)
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets a single channel with all associated entities preloaded.
|
Gets a single channel with all associated entities preloaded.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -218,6 +218,15 @@ defmodule Chiya.Notes do
|
||||||
Repo.delete(note)
|
Repo.delete(note)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def publish_note(%Note{} = note, published_at) do
|
||||||
|
{1, nil} =
|
||||||
|
Note
|
||||||
|
|> where([n], n.id == ^note.id)
|
||||||
|
|> Repo.update_all(set: [published_at: published_at])
|
||||||
|
|
||||||
|
{:ok, note}
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns an `%Ecto.Changeset{}` for tracking note changes.
|
Returns an `%Ecto.Changeset{}` for tracking note changes.
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@ defmodule Chiya.Site.Setting do
|
||||||
:custom_css,
|
:custom_css,
|
||||||
:custom_html,
|
:custom_html,
|
||||||
:home_channel_id,
|
:home_channel_id,
|
||||||
:default_channel_id
|
:default_channel_id,
|
||||||
|
:micropub_channel_id
|
||||||
])
|
])
|
||||||
|> validate_required([:title, :subtitle, :theme, :user_agent])
|
|> validate_required([:title, :subtitle, :theme, :user_agent])
|
||||||
end
|
end
|
||||||
|
|
|
@ -58,7 +58,7 @@ defmodule ChiyaWeb do
|
||||||
layout: {ChiyaWeb.Layouts, :app}
|
layout: {ChiyaWeb.Layouts, :app}
|
||||||
|
|
||||||
# Import admin components
|
# Import admin components
|
||||||
import ChiyaWeb.AdminComponents
|
import ChiyaWeb.CoreComponents
|
||||||
|
|
||||||
unquote(html_helpers())
|
unquote(html_helpers())
|
||||||
end
|
end
|
||||||
|
@ -69,7 +69,7 @@ defmodule ChiyaWeb do
|
||||||
use Phoenix.LiveComponent
|
use Phoenix.LiveComponent
|
||||||
|
|
||||||
# Import admin components
|
# Import admin components
|
||||||
import ChiyaWeb.AdminComponents
|
import ChiyaWeb.CoreComponents
|
||||||
|
|
||||||
unquote(html_helpers())
|
unquote(html_helpers())
|
||||||
end
|
end
|
||||||
|
@ -84,7 +84,7 @@ defmodule ChiyaWeb do
|
||||||
only: [get_csrf_token: 0, view_module: 1, view_template: 1]
|
only: [get_csrf_token: 0, view_module: 1, view_template: 1]
|
||||||
|
|
||||||
# Import admin components
|
# Import admin components
|
||||||
import ChiyaWeb.AdminComponents
|
import ChiyaWeb.CoreComponents
|
||||||
|
|
||||||
# Include general helpers for rendering HTML
|
# Include general helpers for rendering HTML
|
||||||
unquote(html_helpers())
|
unquote(html_helpers())
|
||||||
|
@ -112,7 +112,6 @@ defmodule ChiyaWeb do
|
||||||
# HTML escaping functionality
|
# HTML escaping functionality
|
||||||
import Phoenix.HTML
|
import Phoenix.HTML
|
||||||
# Core UI components and translation
|
# Core UI components and translation
|
||||||
import ChiyaWeb.CoreComponents
|
|
||||||
import ChiyaWeb.Gettext
|
import ChiyaWeb.Gettext
|
||||||
|
|
||||||
# Shortcut for generating JS commands
|
# Shortcut for generating JS commands
|
||||||
|
|
|
@ -1,126 +0,0 @@
|
||||||
defmodule ChiyaWeb.AdminComponents do
|
|
||||||
use Phoenix.Component
|
|
||||||
|
|
||||||
use Phoenix.VerifiedRoutes,
|
|
||||||
endpoint: ChiyaWeb.Endpoint,
|
|
||||||
router: ChiyaWeb.Router,
|
|
||||||
statics: ChiyaWeb.static_paths()
|
|
||||||
|
|
||||||
import ChiyaWeb.CoreComponents
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Renders a horizontal line
|
|
||||||
"""
|
|
||||||
def line(assigns) do
|
|
||||||
~H"""
|
|
||||||
<hr class="my-6 dark:border-gray-700" />
|
|
||||||
"""
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Renders a UI for uploading files
|
|
||||||
"""
|
|
||||||
|
|
||||||
attr :upload, :map, required: true
|
|
||||||
attr :cancel_upload, :string, default: "cancel-upload"
|
|
||||||
|
|
||||||
def live_upload(assigns) do
|
|
||||||
~H"""
|
|
||||||
<div>
|
|
||||||
<.live_file_input upload={@upload} class="dark:text-gray-300" />
|
|
||||||
|
|
||||||
<section phx-drop-target={@upload.ref}>
|
|
||||||
<%= for entry <- @upload.entries do %>
|
|
||||||
<article class="upload-entry">
|
|
||||||
<figure>
|
|
||||||
<.live_img_preview entry={entry} />
|
|
||||||
<figcaption class="dark:text-gray-100"><%= entry.client_name %></figcaption>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<div class="flex">
|
|
||||||
<%!-- entry.progress will update automatically for in-flight entries --%>
|
|
||||||
<progress value={entry.progress} max="100" class="w-full">
|
|
||||||
<%= entry.progress %>%
|
|
||||||
</progress>
|
|
||||||
|
|
||||||
<%!-- a regular click event whose handler will invoke Phoenix.LiveView.cancel_upload/3 --%>
|
|
||||||
<button
|
|
||||||
class="px-2 dark:text-white"
|
|
||||||
type="button"
|
|
||||||
phx-click="cancel-upload"
|
|
||||||
phx-value-ref={entry.ref}
|
|
||||||
aria-label="cancel"
|
|
||||||
>
|
|
||||||
×
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%!-- Phoenix.Component.upload_errors/2 returns a list of error atoms --%>
|
|
||||||
<%= for err <- upload_errors(@upload, entry) do %>
|
|
||||||
<p class="alert alert-danger"><%= upload_error_to_string(err) %></p>
|
|
||||||
<% end %>
|
|
||||||
</article>
|
|
||||||
<% end %>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
"""
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Renders the admin menu bar
|
|
||||||
"""
|
|
||||||
|
|
||||||
attr :current_user, :map, required: true
|
|
||||||
attr :settings, :map, required: true
|
|
||||||
|
|
||||||
def admin_bar(assigns) do
|
|
||||||
~H"""
|
|
||||||
<ul class="sticky top-0 backdrop-blur-sm z-10 flex items-center gap-4 py-3 px-4 sm:px-6 lg:px-8 bg-white/30 dark:bg-black/30">
|
|
||||||
<li>
|
|
||||||
<.link
|
|
||||||
href={~p"/"}
|
|
||||||
class="flex gap-3 text-sm leading-6 font-semibold text-gray-900 dark:text-gray-100 dark:hover:text-gray-300 hover:text-gray-700"
|
|
||||||
>
|
|
||||||
<%= @settings.title %>
|
|
||||||
</.link>
|
|
||||||
</li>
|
|
||||||
<li class="flex-1"></li>
|
|
||||||
<%= if @current_user do %>
|
|
||||||
<li>
|
|
||||||
<.link
|
|
||||||
href={~p"/admin"}
|
|
||||||
class="text-sm leading-6 text-gray-900 dark:text-gray-100 dark:hover:text-gray-300 hover:text-gray-700"
|
|
||||||
>
|
|
||||||
Admin
|
|
||||||
</.link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<.link
|
|
||||||
href={~p"/user/log_out"}
|
|
||||||
method="delete"
|
|
||||||
class="text-sm leading-6 text-gray-900 dark:text-gray-100 dark:hover:text-gray-300 hover:text-gray-700"
|
|
||||||
>
|
|
||||||
Log out
|
|
||||||
</.link>
|
|
||||||
</li>
|
|
||||||
<% else %>
|
|
||||||
<li>
|
|
||||||
<.link
|
|
||||||
href={~p"/user/log_in"}
|
|
||||||
class="text-xs leading-6 text-gray-900 dark:text-gray-100 font-semibold dark:hover:text-gray-300 hover:text-gray-700"
|
|
||||||
>
|
|
||||||
Log in
|
|
||||||
</.link>
|
|
||||||
</li>
|
|
||||||
<% end %>
|
|
||||||
<li>
|
|
||||||
<.darkmode_toggle />
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
"""
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
|
|
@ -653,6 +653,118 @@ defmodule ChiyaWeb.CoreComponents do
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders a horizontal line
|
||||||
|
"""
|
||||||
|
def line(assigns) do
|
||||||
|
~H"""
|
||||||
|
<hr class="my-6 dark:border-gray-700" />
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders a UI for uploading files
|
||||||
|
"""
|
||||||
|
|
||||||
|
attr :upload, :map, required: true
|
||||||
|
attr :cancel_upload, :string, default: "cancel-upload"
|
||||||
|
|
||||||
|
def live_upload(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div>
|
||||||
|
<.live_file_input upload={@upload} class="dark:text-gray-300" />
|
||||||
|
|
||||||
|
<section phx-drop-target={@upload.ref}>
|
||||||
|
<%= for entry <- @upload.entries do %>
|
||||||
|
<article class="upload-entry">
|
||||||
|
<figure>
|
||||||
|
<.live_img_preview entry={entry} />
|
||||||
|
<figcaption class="dark:text-gray-100"><%= entry.client_name %></figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<div class="flex">
|
||||||
|
<%!-- entry.progress will update automatically for in-flight entries --%>
|
||||||
|
<progress value={entry.progress} max="100" class="w-full">
|
||||||
|
<%= entry.progress %>%
|
||||||
|
</progress>
|
||||||
|
|
||||||
|
<%!-- a regular click event whose handler will invoke Phoenix.LiveView.cancel_upload/3 --%>
|
||||||
|
<button
|
||||||
|
class="px-2 dark:text-white"
|
||||||
|
type="button"
|
||||||
|
phx-click="cancel-upload"
|
||||||
|
phx-value-ref={entry.ref}
|
||||||
|
aria-label="cancel"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%!-- Phoenix.Component.upload_errors/2 returns a list of error atoms --%>
|
||||||
|
<%= for err <- upload_errors(@upload, entry) do %>
|
||||||
|
<p class="alert alert-danger"><%= upload_error_to_string(err) %></p>
|
||||||
|
<% end %>
|
||||||
|
</article>
|
||||||
|
<% end %>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders the admin menu bar
|
||||||
|
"""
|
||||||
|
|
||||||
|
attr :current_user, :map, required: true
|
||||||
|
attr :settings, :map, required: true
|
||||||
|
|
||||||
|
def admin_bar(assigns) do
|
||||||
|
~H"""
|
||||||
|
<ul class="sticky top-0 backdrop-blur-sm z-10 flex items-center gap-4 py-3 px-4 sm:px-6 lg:px-8 bg-white/30 dark:bg-black/30">
|
||||||
|
<li>
|
||||||
|
<.link
|
||||||
|
href={~p"/"}
|
||||||
|
class="flex gap-3 text-sm leading-6 font-semibold text-gray-900 dark:text-gray-100 dark:hover:text-gray-300 hover:text-gray-700"
|
||||||
|
>
|
||||||
|
<%= @settings.title %>
|
||||||
|
</.link>
|
||||||
|
</li>
|
||||||
|
<li class="flex-1"></li>
|
||||||
|
<%= if @current_user do %>
|
||||||
|
<li>
|
||||||
|
<.link
|
||||||
|
href={~p"/admin"}
|
||||||
|
class="text-sm leading-6 text-gray-900 dark:text-gray-100 dark:hover:text-gray-300 hover:text-gray-700"
|
||||||
|
>
|
||||||
|
Admin
|
||||||
|
</.link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<.link
|
||||||
|
href={~p"/user/log_out"}
|
||||||
|
method="delete"
|
||||||
|
class="text-sm leading-6 text-gray-900 dark:text-gray-100 dark:hover:text-gray-300 hover:text-gray-700"
|
||||||
|
>
|
||||||
|
Log out
|
||||||
|
</.link>
|
||||||
|
</li>
|
||||||
|
<% else %>
|
||||||
|
<li>
|
||||||
|
<.link
|
||||||
|
href={~p"/user/log_in"}
|
||||||
|
class="text-xs leading-6 text-gray-900 dark:text-gray-100 font-semibold dark:hover:text-gray-300 hover:text-gray-700"
|
||||||
|
>
|
||||||
|
Log in
|
||||||
|
</.link>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
<li>
|
||||||
|
<.darkmode_toggle />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
## JS Commands
|
## JS Commands
|
||||||
|
|
||||||
def show(js \\ %JS{}, selector) do
|
def show(js \\ %JS{}, selector) do
|
||||||
|
@ -734,4 +846,9 @@ defmodule ChiyaWeb.CoreComponents do
|
||||||
def translate_errors(errors, field) when is_list(errors) do
|
def translate_errors(errors, field) when is_list(errors) do
|
||||||
for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts})
|
for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule ChiyaWeb.Layouts do
|
defmodule ChiyaWeb.Layouts do
|
||||||
use ChiyaWeb, :html
|
use ChiyaWeb, :html
|
||||||
|
|
||||||
import ChiyaWeb.PublicComponents
|
import ChiyaWeb.PublicComponents, only: [divider: 1]
|
||||||
|
|
||||||
embed_templates "layouts/*"
|
embed_templates "layouts/*"
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,35 @@ defmodule ChiyaWeb.PublicComponents do
|
||||||
import ChiyaWeb.Format
|
import ChiyaWeb.Format
|
||||||
import ChiyaWeb.Markdown, only: [render: 1]
|
import ChiyaWeb.Markdown, only: [render: 1]
|
||||||
import Phoenix.HTML, only: [raw: 1]
|
import Phoenix.HTML, only: [raw: 1]
|
||||||
import ChiyaWeb.CoreComponents
|
|
||||||
|
@doc """
|
||||||
|
Renders a [Hero Icon](https://heroicons.com).
|
||||||
|
|
||||||
|
Hero icons come in three styles – outline, solid, and mini.
|
||||||
|
By default, the outline style is used, but solid an mini may
|
||||||
|
be applied by using the `-solid` and `-mini` suffix.
|
||||||
|
|
||||||
|
You can customize the size and colors of the icons by setting
|
||||||
|
width, height, and background color classes.
|
||||||
|
|
||||||
|
Icons are extracted from your `priv/hero_icons` directory and bundled
|
||||||
|
within your compiled app.css by the plugin in your `assets/tailwind.config.js`.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
<.icon name="hero-cake" />
|
||||||
|
<.icon name="hero-cake-solid" />
|
||||||
|
<.icon name="hero-cake-mini" />
|
||||||
|
<.icon name="hero-bolt" class="bg-blue-500 w-10 h-10" />
|
||||||
|
"""
|
||||||
|
attr :name, :string, required: true
|
||||||
|
attr :class, :string, default: nil
|
||||||
|
|
||||||
|
def icon(%{name: "hero-" <> _} = assigns) do
|
||||||
|
~H"""
|
||||||
|
<span class={[@name, @class]} />
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Renders a middot as divider
|
Renders a middot as divider
|
||||||
|
@ -164,58 +192,58 @@ defmodule ChiyaWeb.PublicComponents do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def comment_form(assigns) do
|
# def comment_form(assigns) do
|
||||||
~H"""
|
# ~H"""
|
||||||
<.simple_form :let={f} for={@changeset} action="" class="bg-theme-background -m-3">
|
# <.simple_form :let={f} for={@changeset} action="" class="bg-theme-background -m-3">
|
||||||
<.error :if={@changeset.action}>
|
# <.error :if={@changeset.action}>
|
||||||
Oops, something went wrong! Please check the errors below.
|
# Oops, something went wrong! Please check the errors below.
|
||||||
</.error>
|
# </.error>
|
||||||
<.input
|
# <.input
|
||||||
field={f[:author_name]}
|
# field={f[:author_name]}
|
||||||
type="text"
|
# type="text"
|
||||||
placeholder="Name"
|
# placeholder="Name"
|
||||||
class="bg-theme-background dark:bg-theme-background border-theme-base/20 dark:border-theme-base/20 text-theme-base dark:text-theme-base placeholder-theme-base/40 dark:placeholder-theme-base/60 dark:focus:border-theme-base/60 dark:focus:border-theme-base/60"
|
# class="bg-theme-background dark:bg-theme-background border-theme-base/20 dark:border-theme-base/20 text-theme-base dark:text-theme-base placeholder-theme-base/40 dark:placeholder-theme-base/60 dark:focus:border-theme-base/60 dark:focus:border-theme-base/60"
|
||||||
/>
|
# />
|
||||||
<.input
|
# <.input
|
||||||
field={f[:content]}
|
# field={f[:content]}
|
||||||
type="textarea"
|
# type="textarea"
|
||||||
placeholder="Content"
|
# placeholder="Content"
|
||||||
rows="3"
|
# rows="3"
|
||||||
class="bg-theme-background dark:bg-theme-background border-theme-base/20 dark:border-theme-base/20 text-theme-base dark:text-theme-base placeholder-theme-base/60 dark:placeholder-theme-base/60 focus:border-theme-base/60 dark:focus:border-theme-base/60"
|
# class="bg-theme-background dark:bg-theme-background border-theme-base/20 dark:border-theme-base/20 text-theme-base dark:text-theme-base placeholder-theme-base/60 dark:placeholder-theme-base/60 focus:border-theme-base/60 dark:focus:border-theme-base/60"
|
||||||
/>
|
# />
|
||||||
<.input field={f[:note_id]} type="hidden" />
|
# <.input field={f[:note_id]} type="hidden" />
|
||||||
<:actions>
|
# <:actions>
|
||||||
<.button>Submit Comment</.button>
|
# <.button>Submit Comment</.button>
|
||||||
</:actions>
|
# </:actions>
|
||||||
</.simple_form>
|
# </.simple_form>
|
||||||
"""
|
# """
|
||||||
end
|
# end
|
||||||
|
|
||||||
def comment_list(assigns) do
|
# def comment_list(assigns) do
|
||||||
~H"""
|
# ~H"""
|
||||||
<%= if not Enum.empty?(assigns.note.comments) do %>
|
# <%= if not Enum.empty?(assigns.note.comments) do %>
|
||||||
<.line />
|
# <.line />
|
||||||
|
|
||||||
<h2 class="mb-6 text-theme-base"><%= Enum.count(assigns.note.comments) %> Comments</h2>
|
# <h2 class="mb-6 text-theme-base"><%= Enum.count(assigns.note.comments) %> Comments</h2>
|
||||||
|
|
||||||
<aside id="comments" class="flex flex-col gap-6">
|
# <aside id="comments" class="flex flex-col gap-6">
|
||||||
<%= for comment <- assigns.note.comments do %>
|
# <%= for comment <- assigns.note.comments do %>
|
||||||
<article class="text-theme-base bg-theme-base/10 p-1">
|
# <article class="text-theme-base bg-theme-base/10 p-1">
|
||||||
<header class="flex flex-row justify-between">
|
# <header class="flex flex-row justify-between">
|
||||||
<strong class="text-theme-primary"><%= comment.author_name %></strong>
|
# <strong class="text-theme-primary"><%= comment.author_name %></strong>
|
||||||
<span class="text-theme-dim"><%= from_now(comment.inserted_at) %></span>
|
# <span class="text-theme-dim"><%= from_now(comment.inserted_at) %></span>
|
||||||
</header>
|
# </header>
|
||||||
<p><%= comment.content %></p>
|
# <p><%= comment.content %></p>
|
||||||
</article>
|
# </article>
|
||||||
<% end %>
|
# <% end %>
|
||||||
</aside>
|
# </aside>
|
||||||
<% else %>
|
# <% else %>
|
||||||
<.line />
|
# <.line />
|
||||||
|
|
||||||
<h2 class="mb-6 text-theme-base">No comments yet.</h2>
|
# <h2 class="mb-6 text-theme-base">No comments yet.</h2>
|
||||||
<% end %>
|
# <% end %>
|
||||||
"""
|
# """
|
||||||
end
|
# end
|
||||||
|
|
||||||
defp gallery_name(note), do: "gallery-#{note.id}"
|
defp gallery_name(note), do: "gallery-#{note.id}"
|
||||||
|
|
||||||
|
|
|
@ -105,10 +105,9 @@ defmodule ChiyaWeb.NoteController do
|
||||||
end
|
end
|
||||||
|
|
||||||
def publish(conn, %{"id" => id}) do
|
def publish(conn, %{"id" => id}) do
|
||||||
note_params = %{published_at: NaiveDateTime.local_now()}
|
|
||||||
note = Notes.get_note_preloaded!(id)
|
note = Notes.get_note_preloaded!(id)
|
||||||
|
|
||||||
case Notes.update_note(note, note_params) do
|
case Notes.publish_note(note, NaiveDateTime.local_now()) do
|
||||||
{:ok, note} ->
|
{:ok, note} ->
|
||||||
conn
|
conn
|
||||||
|> put_flash(:info, "Note published successfully.")
|
|> put_flash(:info, "Note published successfully.")
|
||||||
|
@ -125,10 +124,9 @@ defmodule ChiyaWeb.NoteController do
|
||||||
end
|
end
|
||||||
|
|
||||||
def unpublish(conn, %{"id" => id}) do
|
def unpublish(conn, %{"id" => id}) do
|
||||||
note_params = %{published_at: nil}
|
|
||||||
note = Notes.get_note_preloaded!(id)
|
note = Notes.get_note_preloaded!(id)
|
||||||
|
|
||||||
case Notes.update_note(note, note_params) do
|
case Notes.publish_note(note, nil) do
|
||||||
{:ok, note} ->
|
{:ok, note} ->
|
||||||
conn
|
conn
|
||||||
|> put_flash(:info, "Note un-published successfully.")
|
|> put_flash(:info, "Note un-published successfully.")
|
||||||
|
|
|
@ -20,9 +20,12 @@ defmodule ChiyaWeb.Indie.MicropubHandler do
|
||||||
Logger.info("Properties: #{inspect(properties)}")
|
Logger.info("Properties: #{inspect(properties)}")
|
||||||
Logger.info("Type: #{type}")
|
Logger.info("Type: #{type}")
|
||||||
|
|
||||||
|
settings = Chiya.Site.get_settings()
|
||||||
|
micropub_channel_id = settings.micropub_channel_id
|
||||||
|
|
||||||
with :ok <- verify_token(access_token),
|
with :ok <- verify_token(access_token),
|
||||||
{:ok, post_type} <- Props.get_post_type(properties),
|
{:ok, post_type} <- Props.get_post_type(properties),
|
||||||
{:ok, note_attrs} <- get_attrs(type, post_type, properties),
|
{:ok, note_attrs} <- get_attrs(type, post_type, properties, micropub_channel_id),
|
||||||
{:ok, note} <- Chiya.Notes.create_note(note_attrs) do
|
{:ok, note} <- Chiya.Notes.create_note(note_attrs) do
|
||||||
Logger.info("Note created!")
|
Logger.info("Note created!")
|
||||||
{:ok, :created, Chiya.Notes.Note.note_url(note)}
|
{:ok, :created, Chiya.Notes.Note.note_url(note)}
|
||||||
|
@ -157,16 +160,18 @@ defmodule ChiyaWeb.Indie.MicropubHandler do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_attrs(type, post_type, properties) do
|
defp get_attrs(type, post_type, properties, default_channel_id) do
|
||||||
Logger.info("Creating a #{type}/#{post_type}..")
|
Logger.info("Creating a #{type}/#{post_type}..")
|
||||||
|
|
||||||
|
channel = Chiya.Channels.get_channel(default_channel_id)
|
||||||
|
|
||||||
case post_type do
|
case post_type do
|
||||||
:note -> get_note_attrs(properties)
|
:note -> get_note_attrs(properties, channel)
|
||||||
_ -> {:error, :insufficient_scope}
|
_ -> {:error, :insufficient_scope}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_note_attrs(p) do
|
defp get_note_attrs(p, default_channel) do
|
||||||
content = Props.get_content(p)
|
content = Props.get_content(p)
|
||||||
name = Props.get_title(p) || String.slice(content, 0..15)
|
name = Props.get_title(p) || String.slice(content, 0..15)
|
||||||
tags = Props.get_tags(p) |> Enum.join(",")
|
tags = Props.get_tags(p) |> Enum.join(",")
|
||||||
|
@ -176,13 +181,19 @@ defmodule ChiyaWeb.Indie.MicropubHandler do
|
||||||
do: NaiveDateTime.local_now(),
|
do: NaiveDateTime.local_now(),
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
{:ok,
|
attrs = %{
|
||||||
%{
|
content: content,
|
||||||
content: content,
|
name: name,
|
||||||
name: name,
|
tags_string: tags,
|
||||||
tags_string: tags,
|
published_at: published_at
|
||||||
published_at: published_at
|
}
|
||||||
}}
|
|
||||||
|
attrs =
|
||||||
|
if default_channel,
|
||||||
|
do: Map.put(attrs, :channel, default_channel),
|
||||||
|
else: attrs
|
||||||
|
|
||||||
|
{:ok, attrs}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_hostname(),
|
defp get_hostname(),
|
||||||
|
|
|
@ -60,13 +60,21 @@ defmodule ChiyaWeb.NoteShowLive do
|
||||||
<article>
|
<article>
|
||||||
<a href={"/admin/notes/#{@note.id}/image/#{image.id}"}>
|
<a href={"/admin/notes/#{@note.id}/image/#{image.id}"}>
|
||||||
<img
|
<img
|
||||||
class="rounded-lg border border-theme-dim w-28 mb-3"
|
class={[
|
||||||
|
"rounded-lg border border-theme-dim w-28 mb-3",
|
||||||
|
image.featured && "border-theme-primary"
|
||||||
|
]}
|
||||||
src={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :thumb_dithered)}
|
src={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :thumb_dithered)}
|
||||||
/>
|
/>
|
||||||
<.button phx-click="delete_image" phx-value-id={image.id} data-confirm="Are you sure?">
|
|
||||||
Delete Image
|
|
||||||
</.button>
|
|
||||||
</a>
|
</a>
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<.button phx-click="delete_image" phx-value-id={image.id} data-confirm="Are you sure?">
|
||||||
|
<.icon name="hero-trash" />
|
||||||
|
</.button>
|
||||||
|
<.button phx-click="toggle_favorite" phx-value-id={image.id}>
|
||||||
|
<.icon name="hero-star-solid" />
|
||||||
|
</.button>
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
@ -138,6 +146,7 @@ defmodule ChiyaWeb.NoteShowLive do
|
||||||
|> assign(:note, Notes.get_note_preloaded!(socket.assigns.note.id))}
|
|> assign(:note, Notes.get_note_preloaded!(socket.assigns.note.id))}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl Phoenix.LiveView
|
||||||
def handle_event("validate_edit_image", assigns, socket) do
|
def handle_event("validate_edit_image", assigns, socket) do
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|
@ -147,6 +156,7 @@ defmodule ChiyaWeb.NoteShowLive do
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl Phoenix.LiveView
|
||||||
def handle_event("update_edit_image", %{"id" => id} = assigns, socket) do
|
def handle_event("update_edit_image", %{"id" => id} = assigns, socket) do
|
||||||
id
|
id
|
||||||
|> Notes.get_note_image!()
|
|> Notes.get_note_image!()
|
||||||
|
@ -164,6 +174,14 @@ defmodule ChiyaWeb.NoteShowLive do
|
||||||
{:noreply, assign(socket, :note, Notes.get_note_preloaded!(socket.assigns.note.id))}
|
{:noreply, assign(socket, :note, Notes.get_note_preloaded!(socket.assigns.note.id))}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl Phoenix.LiveView
|
||||||
|
def handle_event("toggle_favorite", %{"id" => id}, socket) do
|
||||||
|
image = Notes.get_note_image!(id)
|
||||||
|
Notes.update_note_image(image, %{featured: !image.featured})
|
||||||
|
|
||||||
|
{:noreply, assign(socket, :note, Notes.get_note_preloaded!(socket.assigns.note.id))}
|
||||||
|
end
|
||||||
|
|
||||||
defp note_links(notes), do: Enum.map_join(notes, ", ", fn n -> n.name end)
|
defp note_links(notes), do: Enum.map_join(notes, ", ", fn n -> n.name end)
|
||||||
defp note_tags(tags), do: Enum.map_join(tags, ", ", fn t -> t.name end)
|
defp note_tags(tags), do: Enum.map_join(tags, ", ", fn t -> t.name end)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue