add note images

This commit is contained in:
Inhji 2023-03-09 07:28:06 +01:00
parent 0715da85b8
commit 98e82deb94
10 changed files with 199 additions and 23 deletions

View file

@ -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

View file

@ -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

View 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

View file

@ -44,6 +44,7 @@ defmodule ChiyaWeb do
import Plug.Conn
import ChiyaWeb.Gettext
import Phoenix.LiveView.Controller
unquote(verified_routes())
end

View file

@ -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

View 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

View file

@ -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

View file

@ -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

View file

@ -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

View 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