devel #57
15 changed files with 86 additions and 49 deletions
|
@ -8,7 +8,11 @@ defmodule Chiya.Notes.Note do
|
|||
@derive {Jason.Encoder, only: [:id, :name, :content, :slug, :channels]}
|
||||
schema "notes" do
|
||||
field :content, :string
|
||||
field :kind, Ecto.Enum, values: [:post, :bookmark], default: :post
|
||||
|
||||
field :kind, Ecto.Enum,
|
||||
values: [:post, :bookmark],
|
||||
default: :post
|
||||
|
||||
field :name, :string
|
||||
field :published_at, :naive_datetime
|
||||
field :slug, NoteSlug.Type
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
defmodule Chiya.Notes.NoteImport do
|
||||
import Ecto.Changeset
|
||||
import Ecto.Changeset
|
||||
|
||||
defstruct [:file]
|
||||
defstruct [:file]
|
||||
|
||||
@types %{file: :string}
|
||||
@types %{file: :string}
|
||||
|
||||
def change_note_import(params) do
|
||||
{%Chiya.Notes.NoteImport{}, @types}
|
||||
|> cast(params, Map.keys(@types))
|
||||
|> validate_required(:file)
|
||||
end
|
||||
end
|
||||
def change_note_import(params) do
|
||||
{%Chiya.Notes.NoteImport{}, @types}
|
||||
|> cast(params, Map.keys(@types))
|
||||
|> validate_required(:file)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -75,7 +75,6 @@ defmodule Chiya.Notes.References do
|
|||
end)
|
||||
end
|
||||
|
||||
|
||||
def update_references({:ok, note}, attrs) do
|
||||
new_reference_slugs = get_reference_ids(attrs["content"])
|
||||
old_reference_slugs = Enum.map(note.links_from, fn n -> n.slug end)
|
||||
|
|
|
@ -321,8 +321,11 @@ defmodule ChiyaWeb.CoreComponents do
|
|||
attr :prompt, :string, default: nil, doc: "the prompt for select inputs"
|
||||
attr :options, :list, doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2"
|
||||
attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs"
|
||||
attr :rest, :global, include: ~w(autocomplete accept cols disabled form max maxlength min minlength
|
||||
|
||||
attr :rest, :global,
|
||||
include: ~w(autocomplete accept cols disabled form max maxlength min minlength
|
||||
pattern placeholder readonly required rows size step)
|
||||
|
||||
slot :inner_block
|
||||
|
||||
def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
|
||||
|
|
|
@ -16,4 +16,4 @@
|
|||
<section class="mx-auto max-w-2xl px-4 mb-16">
|
||||
<.flash_group flash={@flash} />
|
||||
<%= @inner_content %>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -32,10 +32,12 @@
|
|||
</main>
|
||||
|
||||
<footer class="px-4 py-1 sm:px-6 lg:px-8 bg-white/30 dark:bg-black/30 text-gray-900 dark:text-gray-100 text-xs leading-6 font-semibold">
|
||||
<span class="text-theme-primary">⌘</span> <span>Chiya</span> <span class="rounded-full bg-theme-primary/10 px-2 text-xs font-medium leading-6 text-theme-primary">
|
||||
v<%= Application.spec(:chiya, :vsn) %></span>
|
||||
<span class="text-theme-primary">⌘</span> <span>Chiya</span>
|
||||
<span class="rounded-full bg-theme-primary/10 px-2 text-xs font-medium leading-6 text-theme-primary">
|
||||
v<%= Application.spec(:chiya, :vsn) %>
|
||||
</span>
|
||||
</footer>
|
||||
|
||||
<%= raw(@settings.custom_html) %>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<section class="p-4 rounded flex gap-4 bg-gray-100 shadow border border-gray-300 dark:border-gray-700 dark:bg-gray-800">
|
||||
<img
|
||||
class="rounded-full w-24"
|
||||
src={ChiyaWeb.Uploaders.UserImage.url({@current_user.user_image, @current_user}, :thumb)}
|
||||
/>
|
||||
<img
|
||||
class="rounded-full w-24"
|
||||
src={ChiyaWeb.Uploaders.UserImage.url({@current_user.user_image, @current_user}, :thumb)}
|
||||
/>
|
||||
<div class="flex-1 dark:text-gray-200">
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">Welcome back,</p>
|
||||
<h2 class="text-xl font-semibold"><%= @current_user.email %></h2>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">Welcome back,</p>
|
||||
<h2 class="text-xl font-semibold"><%= @current_user.email %></h2>
|
||||
</div>
|
||||
<.link href={~p"/user"}>
|
||||
<.button>Profile</.button>
|
||||
|
@ -13,7 +13,10 @@
|
|||
</section>
|
||||
|
||||
<section class="mt-4 flex gap-4">
|
||||
<a href="/admin/notes/new" class="p-4 rounded text-gray-700 bg-gray-100 shadow border border-gray-300 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 hover:text-gray-700/80 dark:hover:text-gray-200/80 transition hover:shadow-none">
|
||||
<a
|
||||
href="/admin/notes/new"
|
||||
class="p-4 rounded text-gray-700 bg-gray-100 shadow border border-gray-300 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 hover:text-gray-700/80 dark:hover:text-gray-200/80 transition hover:shadow-none"
|
||||
>
|
||||
<.icon name="hero-document-plus" /> New Note
|
||||
</a>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
|
||||
<.table id="channels" rows={@channels} row_click={&JS.navigate(~p"/admin/channels/#{&1}")}>
|
||||
<:col :let={channel} label="Name"><%= channel.name %></:col>
|
||||
<:col :let={channel} label="Visibility"><%= Chiya.Channels.Channel.icon(channel) %> <%= channel.visibility %></:col>
|
||||
<:col :let={channel} label="Visibility">
|
||||
<%= Chiya.Channels.Channel.icon(channel) %> <%= channel.visibility %>
|
||||
</:col>
|
||||
<:col :let={channel} label="Notes"><%= Enum.count(channel.notes) %></:col>
|
||||
<:col :let={channel} label="Slug"><%= channel.slug %></:col>
|
||||
<:action :let={channel}>
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
<:subtitle>Use this form to manage note image records in your database.</:subtitle>
|
||||
</.header>
|
||||
|
||||
<.simple_form :let={f} for={@changeset} action={~p"/admin/notes/#{@image.note.id}/image/#{@image.id}"}>
|
||||
<.simple_form
|
||||
:let={f}
|
||||
for={@changeset}
|
||||
action={~p"/admin/notes/#{@image.note.id}/image/#{@image.id}"}
|
||||
>
|
||||
<.error :if={@changeset.action}>
|
||||
Oops, something went wrong! Please check the errors below.
|
||||
</.error>
|
||||
|
@ -17,5 +21,4 @@
|
|||
</:actions>
|
||||
</.simple_form>
|
||||
|
||||
|
||||
<.back navigate={~p"/admin/notes/#{@image.note_id}"}>Back to notes</.back>
|
||||
<.back navigate={~p"/admin/notes/#{@image.note_id}"}>Back to notes</.back>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</.error>
|
||||
|
||||
<.input field={f[:file]} type="file" label="Markdown file" accept="text/markdown, text/plain" />
|
||||
|
||||
|
||||
<:actions>
|
||||
<.button>Import Note</.button>
|
||||
</:actions>
|
||||
|
|
|
@ -12,9 +12,20 @@
|
|||
</.header>
|
||||
|
||||
<section class="flex flex-row flex-wrap mt-4 gap-3">
|
||||
<a href={~p"/admin/notes"} class="text-sm dark:text-gray-300 rounded-full bg-gray-300 hover:bg-gray-400 dark:bg-gray-700 dark:hover:bg-gray-600 px-2 py-1">All</a>
|
||||
<a
|
||||
href={~p"/admin/notes"}
|
||||
class="text-sm dark:text-gray-300 rounded-full bg-gray-300 hover:bg-gray-400 dark:bg-gray-700 dark:hover:bg-gray-600 px-2 py-1"
|
||||
>
|
||||
All
|
||||
</a>
|
||||
<%= for channel <- @channels do %>
|
||||
<a href={~p"/admin/notes?channel=#{channel.slug}"} class="text-sm dark:text-gray-300 rounded-full bg-gray-300 hover:bg-gray-400 dark:bg-gray-700 dark:hover:bg-gray-600 px-2 py-1"><%= channel.name %> <span class="text-gray-600 dark:text-gray-500">(<%= Enum.count(channel.notes) %>)</span></a>
|
||||
<a
|
||||
href={~p"/admin/notes?channel=#{channel.slug}"}
|
||||
class="text-sm dark:text-gray-300 rounded-full bg-gray-300 hover:bg-gray-400 dark:bg-gray-700 dark:hover:bg-gray-600 px-2 py-1"
|
||||
>
|
||||
<%= channel.name %>
|
||||
<span class="text-gray-600 dark:text-gray-500">(<%= Enum.count(channel.notes) %>)</span>
|
||||
</a>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
|
|
|
@ -17,4 +17,4 @@
|
|||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
<%= @note.name %>
|
||||
</h1>
|
||||
<p class="mt-2 text-sm leading-6 text-theme-base">
|
||||
<span>Published</span> <time class="text-theme-primary font-semibold"><%= pretty_date(@note.published_at) %></time>
|
||||
<span>Published</span>
|
||||
<time class="text-theme-primary font-semibold"><%= pretty_date(@note.published_at) %></time>
|
||||
<span>·</span>
|
||||
<span>Last Updated</span> <time class="text-theme-primary font-semibold"><%= pretty_date(@note.updated_at) %></time>
|
||||
<span>Last Updated</span>
|
||||
<time class="text-theme-primary font-semibold"><%= pretty_date(@note.updated_at) %></time>
|
||||
<%= if @current_user do %>
|
||||
<span>·</span>
|
||||
<a href={~p"/admin/notes/#{@note}/edit"} class="text-theme-primary font-semibold">Edit</a>
|
||||
<span>·</span>
|
||||
<a href={~p"/admin/notes/#{@note}/edit"} class="text-theme-primary font-semibold">Edit</a>
|
||||
<% end %>
|
||||
</p>
|
||||
</header>
|
||||
|
@ -23,10 +25,18 @@
|
|||
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<%= for image <- @note.images do %>
|
||||
<a href={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :full_dithered)} class="lightbox | w-28" data-gallery="note" data-description={ChiyaWeb.Markdown.render(image.content)}>
|
||||
<img src={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :thumb_dithered)} class="rounded"/>
|
||||
<a
|
||||
href={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :full_dithered)}
|
||||
class="lightbox | w-28"
|
||||
data-gallery="note"
|
||||
data-description={ChiyaWeb.Markdown.render(image.content)}
|
||||
>
|
||||
<img
|
||||
src={ChiyaWeb.Uploaders.NoteImage.url({image.path, image}, :thumb_dithered)}
|
||||
class="rounded"
|
||||
/>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -29,7 +29,9 @@ defmodule ChiyaWeb.NoteShowLive do
|
|||
</.header>
|
||||
|
||||
<.list>
|
||||
<:item title="Published at"><%= pretty_date(@note.published_at) %> <span>(<%= from_now(@note.published_at) %>)</span></:item>
|
||||
<:item title="Published at">
|
||||
<%= pretty_date(@note.published_at) %> <span>(<%= from_now(@note.published_at) %>)</span>
|
||||
</:item>
|
||||
<:item title="Channels"><%= @channels %></:item>
|
||||
<:item title="Kind"><%= @note.kind %></:item>
|
||||
<:item title="Url"><%= @note.url %></:item>
|
||||
|
@ -48,11 +50,7 @@ defmodule ChiyaWeb.NoteShowLive do
|
|||
class="rounded-lg border border-theme-dim w-28"
|
||||
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?"
|
||||
>
|
||||
<.button phx-click="delete_image" phx-value-id={image.id} data-confirm="Are you sure?">
|
||||
Delete Image
|
||||
</.button>
|
||||
</a>
|
||||
|
@ -140,7 +138,7 @@ defmodule ChiyaWeb.NoteShowLive do
|
|||
id
|
||||
|> Notes.get_note_image!()
|
||||
|> Notes.update_note_image(assigns)
|
||||
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
|
@ -154,6 +152,6 @@ defmodule ChiyaWeb.NoteShowLive do
|
|||
end
|
||||
|
||||
defp note_links(notes) do
|
||||
Enum.map_join(notes, ", ",fn n -> n.name end)
|
||||
Enum.map_join(notes, ", ", fn n -> n.name end)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,14 +2,16 @@ defmodule Chiya.Repo.Migrations.FixNoteImageReference do
|
|||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
drop constraint :note_images, "note_images_note_id_fkey"
|
||||
drop constraint(:note_images, "note_images_note_id_fkey")
|
||||
|
||||
alter table(:note_images) do
|
||||
modify :note_id, references(:notes, on_delete: :delete_all)
|
||||
end
|
||||
end
|
||||
|
||||
def down do
|
||||
drop constraint :note_images, "note_images_note_id_fkey"
|
||||
drop constraint(:note_images, "note_images_note_id_fkey")
|
||||
|
||||
alter table(:note_images) do
|
||||
modify :note_id, references(:notes, on_delete: :nothing)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue