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
|
||||
alias Chiya.Repo
|
||||
|
||||
alias Chiya.Notes.Note
|
||||
alias Chiya.Notes.{Note, NoteImage}
|
||||
|
||||
@preloads [:channels]
|
||||
@preloads [:channels, :images]
|
||||
|
||||
@doc """
|
||||
Returns the list of notes.
|
||||
|
@ -129,4 +129,28 @@ defmodule Chiya.Notes do
|
|||
def change_note(%Note{} = note, attrs \\ %{}) do
|
||||
Note.changeset(note, attrs)
|
||||
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
|
||||
|
|
|
@ -11,11 +11,13 @@ defmodule Chiya.Notes.Note do
|
|||
field :url, :string
|
||||
|
||||
many_to_many :channels, Chiya.Channels.Channel,
|
||||
# join_through: Chiya.Channels.ChannelNote,
|
||||
# join_through: Chiya.Channels.ChannelNote,
|
||||
join_through: "channels_notes",
|
||||
join_keys: [note: :id, channel: :id],
|
||||
on_replace: :delete
|
||||
|
||||
has_many :images, Chiya.Notes.NoteImage
|
||||
|
||||
timestamps()
|
||||
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 ChiyaWeb.Gettext
|
||||
import Phoenix.LiveView.Controller
|
||||
|
||||
unquote(verified_routes())
|
||||
end
|
||||
|
|
|
@ -29,8 +29,9 @@ defmodule ChiyaWeb.NoteController do
|
|||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
note = Notes.get_note!(id)
|
||||
render(conn, :show, note: note)
|
||||
# note = Notes.get_note!(id)
|
||||
# render(conn, :show, note: note)
|
||||
live_render(conn, NoteShowLive, session: %{ "note_id" => id })
|
||||
end
|
||||
|
||||
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}
|
||||
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
|
||||
|
||||
def handle_event("validate_email", params, socket) do
|
||||
|
|
|
@ -51,8 +51,10 @@ defmodule ChiyaWeb.Router do
|
|||
pipe_through [:browser, :require_authenticated_user]
|
||||
|
||||
resources "/channels", ChannelController
|
||||
resources "/notes", NoteController
|
||||
resources "/notes", NoteController, except: [:show]
|
||||
resources "/settings", SettingController, singleton: true
|
||||
|
||||
live "/notes/:id", NoteShowLive, :show
|
||||
end
|
||||
|
||||
## Authentication routes
|
||||
|
|
|
@ -5,12 +5,11 @@ defmodule Chiya.Uploaders.NoteImage do
|
|||
# Include ecto support (requires package waffle_ecto installed):
|
||||
# use Waffle.Ecto.Definition
|
||||
|
||||
@versions [:original, :dithered, :thumb, :thumb_dithered]
|
||||
@versions [:original, :full, :full_dithered, :thumb, :thumb_dithered]
|
||||
|
||||
# Whitelist file extensions:
|
||||
def validate({file, _}) do
|
||||
_file_extension = file.file_name |> Path.extname() |> String.downcase()
|
||||
|
||||
def validate({_file, _}) do
|
||||
# _file_extension = file.file_name |> Path.extname() |> String.downcase()
|
||||
# case Enum.member?(~w(.jpg .jpeg .gif .png), file_extension) do
|
||||
# true -> :ok
|
||||
# false -> {:error, "invalid file type"}
|
||||
|
@ -20,8 +19,12 @@ defmodule Chiya.Uploaders.NoteImage do
|
|||
:ok
|
||||
end
|
||||
|
||||
def transform(:full, _) do
|
||||
{:convert, "-strip -resize 1500000@ -gravity center -format png", :png}
|
||||
end
|
||||
|
||||
# Define a resize transformation:
|
||||
def transform(:dithered, _) do
|
||||
def transform(:full_dithered, _) do
|
||||
{:convert, "-strip -resize 1500000@ -colors 24 -dither FloydSteinberg -format png", :png}
|
||||
end
|
||||
|
||||
|
@ -43,21 +46,12 @@ defmodule Chiya.Uploaders.NoteImage do
|
|||
end
|
||||
|
||||
# Override the storage directory:
|
||||
def storage_dir(_version, {_file, _scope}) do
|
||||
"uploads/user/avatar"
|
||||
def storage_dir(_version, {_file, %{id: image_id, note_id: note_id}}) do
|
||||
"uploads/note/#{note_id}/#{image_id}"
|
||||
end
|
||||
|
||||
# Provide a default URL if there hasn't been a file uploaded
|
||||
# def default_url(version, scope) do
|
||||
# "/images/avatars/default_#{version}.png"
|
||||
# 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
|
||||
|
|
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