add note images
This commit is contained in:
parent
0715da85b8
commit
98e82deb94
10 changed files with 199 additions and 23 deletions
|
@ -6,9 +6,9 @@ defmodule Chiya.Notes do
|
||||||
import Ecto.Query, warn: false
|
import Ecto.Query, warn: false
|
||||||
alias Chiya.Repo
|
alias Chiya.Repo
|
||||||
|
|
||||||
alias Chiya.Notes.Note
|
alias Chiya.Notes.{Note, NoteImage}
|
||||||
|
|
||||||
@preloads [:channels]
|
@preloads [:channels, :images]
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns the list of notes.
|
Returns the list of notes.
|
||||||
|
@ -129,4 +129,28 @@ defmodule Chiya.Notes do
|
||||||
def change_note(%Note{} = note, attrs \\ %{}) do
|
def change_note(%Note{} = note, attrs \\ %{}) do
|
||||||
Note.changeset(note, attrs)
|
Note.changeset(note, attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Creates a note image and attaches it to a note
|
||||||
|
"""
|
||||||
|
def create_note_image(attrs) do
|
||||||
|
case %NoteImage{}
|
||||||
|
|> NoteImage.insert_changeset(attrs)
|
||||||
|
|> Repo.insert() do
|
||||||
|
{:ok, note_image} ->
|
||||||
|
note_image
|
||||||
|
|> change_note_image(attrs)
|
||||||
|
|> Repo.update()
|
||||||
|
|
||||||
|
{:error, changeset} ->
|
||||||
|
{:error, changeset}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns an `%Ecto.Changeset{}` for tracking note_image changes.
|
||||||
|
"""
|
||||||
|
def change_note_image(%NoteImage{} = note_image, attrs \\ %{}) do
|
||||||
|
NoteImage.changeset(note_image, attrs)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,11 +11,13 @@ defmodule Chiya.Notes.Note do
|
||||||
field :url, :string
|
field :url, :string
|
||||||
|
|
||||||
many_to_many :channels, Chiya.Channels.Channel,
|
many_to_many :channels, Chiya.Channels.Channel,
|
||||||
# join_through: Chiya.Channels.ChannelNote,
|
# join_through: Chiya.Channels.ChannelNote,
|
||||||
join_through: "channels_notes",
|
join_through: "channels_notes",
|
||||||
join_keys: [note: :id, channel: :id],
|
join_keys: [note: :id, channel: :id],
|
||||||
on_replace: :delete
|
on_replace: :delete
|
||||||
|
|
||||||
|
has_many :images, Chiya.Notes.NoteImage
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
28
lib/chiya/notes/note_image.ex
Normal file
28
lib/chiya/notes/note_image.ex
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
defmodule Chiya.Notes.NoteImage do
|
||||||
|
use Ecto.Schema
|
||||||
|
use Waffle.Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
schema "note_images" do
|
||||||
|
field :content, :string, default: ""
|
||||||
|
field :path, Chiya.Uploaders.NoteImage.Type
|
||||||
|
field :note_id, :id
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(note_image, attrs) do
|
||||||
|
note_image
|
||||||
|
|> cast(attrs, [:content, :note_id])
|
||||||
|
|> cast_attachments(attrs, [:path], allow_paths: true)
|
||||||
|
|> validate_required([:path, :note_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def insert_changeset(note_image, attrs) do
|
||||||
|
note_image
|
||||||
|
|> cast(attrs, [:note_id])
|
||||||
|
|> validate_required([:note_id])
|
||||||
|
end
|
||||||
|
end
|
|
@ -44,6 +44,7 @@ defmodule ChiyaWeb do
|
||||||
|
|
||||||
import Plug.Conn
|
import Plug.Conn
|
||||||
import ChiyaWeb.Gettext
|
import ChiyaWeb.Gettext
|
||||||
|
import Phoenix.LiveView.Controller
|
||||||
|
|
||||||
unquote(verified_routes())
|
unquote(verified_routes())
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,8 +29,9 @@ defmodule ChiyaWeb.NoteController do
|
||||||
end
|
end
|
||||||
|
|
||||||
def show(conn, %{"id" => id}) do
|
def show(conn, %{"id" => id}) do
|
||||||
note = Notes.get_note!(id)
|
# note = Notes.get_note!(id)
|
||||||
render(conn, :show, note: note)
|
# render(conn, :show, note: note)
|
||||||
|
live_render(conn, NoteShowLive, session: %{ "note_id" => id })
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit(conn, %{"id" => id}) do
|
def edit(conn, %{"id" => id}) do
|
||||||
|
|
106
lib/chiya_web/live/note_show_live.ex
Normal file
106
lib/chiya_web/live/note_show_live.ex
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
defmodule ChiyaWeb.NoteShowLive do
|
||||||
|
use ChiyaWeb, :live_view
|
||||||
|
|
||||||
|
alias Chiya.Notes
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def render(assigns) do
|
||||||
|
~H"""
|
||||||
|
<.header>
|
||||||
|
Note <%= @note.id %>
|
||||||
|
<:subtitle>This is a note record from your database.</:subtitle>
|
||||||
|
<:actions>
|
||||||
|
<.link href={~p"/admin/notes/#{@note}/edit"}>
|
||||||
|
<.button>Edit note</.button>
|
||||||
|
</.link>
|
||||||
|
</:actions>
|
||||||
|
</.header>
|
||||||
|
|
||||||
|
<.list>
|
||||||
|
<:item title="Name"><%= @note.name %></:item>
|
||||||
|
<:item title="Content"><%= @note.content %></:item>
|
||||||
|
<:item title="Slug"><%= @note.slug %></:item>
|
||||||
|
<:item title="Published at"><%= @note.published_at %></:item>
|
||||||
|
<:item title="Kind"><%= @note.kind %></:item>
|
||||||
|
<:item title="Url"><%= @note.url %></:item>
|
||||||
|
</.list>
|
||||||
|
|
||||||
|
<.line />
|
||||||
|
|
||||||
|
<div class="flex flex-wrap gap-3">
|
||||||
|
<%= for image <- @note.images do %>
|
||||||
|
<article>
|
||||||
|
<img
|
||||||
|
class="rounded-lg w-28 "
|
||||||
|
src={Chiya.Uploaders.NoteImage.url({image.path, image}, :thumb)}
|
||||||
|
/>
|
||||||
|
<p class="text-center text-xs text-zinc-700"><a href="">Delete image</a></p>
|
||||||
|
</article>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<.line />
|
||||||
|
|
||||||
|
<.header>
|
||||||
|
Note Images
|
||||||
|
<:subtitle>Add images here</:subtitle>
|
||||||
|
</.header>
|
||||||
|
|
||||||
|
<.simple_form
|
||||||
|
for={@image_form}
|
||||||
|
id="image_form"
|
||||||
|
phx-submit="update_image"
|
||||||
|
phx-change="validate_image"
|
||||||
|
multipart={true}
|
||||||
|
>
|
||||||
|
<.live_upload upload={@uploads.note_images} />
|
||||||
|
|
||||||
|
<:actions>
|
||||||
|
<.button phx-disable-with="Changing...">Add Images</.button>
|
||||||
|
</:actions>
|
||||||
|
</.simple_form>
|
||||||
|
|
||||||
|
<.back navigate={~p"/admin/notes"}>Back to notes</.back>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def mount(%{"id" => note_id}, _session, socket) do
|
||||||
|
image_changeset = Notes.change_note_image(%Chiya.Notes.NoteImage{})
|
||||||
|
|
||||||
|
{:ok,
|
||||||
|
socket
|
||||||
|
|> assign(:note, Notes.get_note_preloaded!(note_id))
|
||||||
|
|> assign(:uploaded_files, [])
|
||||||
|
|> assign(:image_form, to_form(image_changeset))
|
||||||
|
|> allow_upload(:note_images, accept: ~w(.jpg .jpeg .gif .png), max_entries: 100)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event("validate_image", _params, socket) do
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Phoenix.LiveView
|
||||||
|
def handle_event("cancel-upload", %{"ref" => ref}, socket) do
|
||||||
|
{:noreply, cancel_upload(socket, :note_images, ref)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Phoenix.LiveView
|
||||||
|
def handle_event("update_image", _params, socket) do
|
||||||
|
uploaded_files =
|
||||||
|
consume_uploaded_entries(socket, :note_images, fn %{path: path}, _entry ->
|
||||||
|
{:ok, _note_image} =
|
||||||
|
Notes.create_note_image(%{
|
||||||
|
path: path,
|
||||||
|
note_id: socket.assigns.note.id
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, path}
|
||||||
|
end)
|
||||||
|
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> update(:uploaded_files, &(&1 ++ uploaded_files))
|
||||||
|
|> assign(:note, Notes.get_note_preloaded!(socket.assigns.note.id))}
|
||||||
|
end
|
||||||
|
end
|
|
@ -143,7 +143,10 @@ defmodule ChiyaWeb.UserSettingsLive do
|
||||||
{:ok, path}
|
{:ok, path}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
{:noreply, update(socket, :uploaded_files, &(&1 ++ uploaded_files))}
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> update(:uploaded_files, &(&1 ++ uploaded_files))
|
||||||
|
|> assign(:user, Accounts.get_user!(user.id))}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("validate_email", params, socket) do
|
def handle_event("validate_email", params, socket) do
|
||||||
|
|
|
@ -51,8 +51,10 @@ defmodule ChiyaWeb.Router do
|
||||||
pipe_through [:browser, :require_authenticated_user]
|
pipe_through [:browser, :require_authenticated_user]
|
||||||
|
|
||||||
resources "/channels", ChannelController
|
resources "/channels", ChannelController
|
||||||
resources "/notes", NoteController
|
resources "/notes", NoteController, except: [:show]
|
||||||
resources "/settings", SettingController, singleton: true
|
resources "/settings", SettingController, singleton: true
|
||||||
|
|
||||||
|
live "/notes/:id", NoteShowLive, :show
|
||||||
end
|
end
|
||||||
|
|
||||||
## Authentication routes
|
## Authentication routes
|
||||||
|
|
|
@ -5,12 +5,11 @@ defmodule Chiya.Uploaders.NoteImage do
|
||||||
# Include ecto support (requires package waffle_ecto installed):
|
# Include ecto support (requires package waffle_ecto installed):
|
||||||
# use Waffle.Ecto.Definition
|
# use Waffle.Ecto.Definition
|
||||||
|
|
||||||
@versions [:original, :dithered, :thumb, :thumb_dithered]
|
@versions [:original, :full, :full_dithered, :thumb, :thumb_dithered]
|
||||||
|
|
||||||
# Whitelist file extensions:
|
# Whitelist file extensions:
|
||||||
def validate({file, _}) do
|
def validate({_file, _}) do
|
||||||
_file_extension = file.file_name |> Path.extname() |> String.downcase()
|
# _file_extension = file.file_name |> Path.extname() |> String.downcase()
|
||||||
|
|
||||||
# case Enum.member?(~w(.jpg .jpeg .gif .png), file_extension) do
|
# case Enum.member?(~w(.jpg .jpeg .gif .png), file_extension) do
|
||||||
# true -> :ok
|
# true -> :ok
|
||||||
# false -> {:error, "invalid file type"}
|
# false -> {:error, "invalid file type"}
|
||||||
|
@ -20,8 +19,12 @@ defmodule Chiya.Uploaders.NoteImage do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def transform(:full, _) do
|
||||||
|
{:convert, "-strip -resize 1500000@ -gravity center -format png", :png}
|
||||||
|
end
|
||||||
|
|
||||||
# Define a resize transformation:
|
# Define a resize transformation:
|
||||||
def transform(:dithered, _) do
|
def transform(:full_dithered, _) do
|
||||||
{:convert, "-strip -resize 1500000@ -colors 24 -dither FloydSteinberg -format png", :png}
|
{:convert, "-strip -resize 1500000@ -colors 24 -dither FloydSteinberg -format png", :png}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -43,21 +46,12 @@ defmodule Chiya.Uploaders.NoteImage do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Override the storage directory:
|
# Override the storage directory:
|
||||||
def storage_dir(_version, {_file, _scope}) do
|
def storage_dir(_version, {_file, %{id: image_id, note_id: note_id}}) do
|
||||||
"uploads/user/avatar"
|
"uploads/note/#{note_id}/#{image_id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Provide a default URL if there hasn't been a file uploaded
|
# Provide a default URL if there hasn't been a file uploaded
|
||||||
# def default_url(version, scope) do
|
# def default_url(version, scope) do
|
||||||
# "/images/avatars/default_#{version}.png"
|
# "/images/avatars/default_#{version}.png"
|
||||||
# end
|
# end
|
||||||
|
|
||||||
# Specify custom headers for s3 objects
|
|
||||||
# Available options are [:cache_control, :content_disposition,
|
|
||||||
# :content_encoding, :content_length, :content_type,
|
|
||||||
# :expect, :expires, :storage_class, :website_redirect_location]
|
|
||||||
#
|
|
||||||
# def s3_object_headers(version, {file, scope}) do
|
|
||||||
# [content_type: MIME.from_path(file.file_name)]
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
|
|
15
priv/repo/migrations/20230308191004_create_note_images.exs
Normal file
15
priv/repo/migrations/20230308191004_create_note_images.exs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
defmodule Chiya.Repo.Migrations.CreateNoteImages do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:note_images) do
|
||||||
|
add :path, :string
|
||||||
|
add :content, :text
|
||||||
|
add :note_id, references(:notes, on_delete: :nothing)
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
create index(:note_images, [:note_id])
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue