commit
9be8ec73d3
11 changed files with 115 additions and 21 deletions
|
@ -60,6 +60,10 @@ config :waffle,
|
||||||
storage: Waffle.Storage.Local,
|
storage: Waffle.Storage.Local,
|
||||||
storage_dir_prefix: "priv/waffle/public"
|
storage_dir_prefix: "priv/waffle/public"
|
||||||
|
|
||||||
|
# Configure Timezones with :tz
|
||||||
|
config :elixir,
|
||||||
|
:time_zone_database, Tz.TimeZoneDatabase
|
||||||
|
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
import_config "#{config_env()}.exs"
|
import_config "#{config_env()}.exs"
|
||||||
|
|
|
@ -8,8 +8,17 @@ defmodule Chiya.Channels.Channel do
|
||||||
field :content, :string
|
field :content, :string
|
||||||
field :name, :string
|
field :name, :string
|
||||||
field :slug, ChannelSlug.Type
|
field :slug, ChannelSlug.Type
|
||||||
field :visibility, Ecto.Enum, values: [:public, :private, :unlisted]
|
field :visibility, Ecto.Enum, values: [
|
||||||
field :layout, Ecto.Enum, values: [:default, :gallery]
|
:public,
|
||||||
|
:private,
|
||||||
|
:unlisted
|
||||||
|
]
|
||||||
|
field :layout, Ecto.Enum, values: [
|
||||||
|
:default,
|
||||||
|
:microblog,
|
||||||
|
:photoblog,
|
||||||
|
:gallery
|
||||||
|
]
|
||||||
|
|
||||||
many_to_many :notes, Chiya.Notes.Note,
|
many_to_many :notes, Chiya.Notes.Note,
|
||||||
join_through: "channels_notes",
|
join_through: "channels_notes",
|
||||||
|
@ -28,10 +37,10 @@ defmodule Chiya.Channels.Channel do
|
||||||
|> validate_exclusion(:slug, ~w(admin user dev))
|
|> validate_exclusion(:slug, ~w(admin user dev))
|
||||||
end
|
end
|
||||||
|
|
||||||
def icon(%Chiya.Channels.Channel{visibility: vis}) do
|
def icon(%Chiya.Channels.Channel{visibility: visibility}) do
|
||||||
case(vis) do
|
case(visibility) do
|
||||||
:public -> "🌍"
|
|
||||||
:private -> "🔒"
|
:private -> "🔒"
|
||||||
|
:public -> "🌍"
|
||||||
:unlisted -> "👁️"
|
:unlisted -> "👁️"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -238,6 +238,7 @@ defmodule ChiyaWeb.CoreComponents do
|
||||||
"""
|
"""
|
||||||
attr :for, :any, required: true, doc: "the datastructure for the form"
|
attr :for, :any, required: true, doc: "the datastructure for the form"
|
||||||
attr :as, :any, default: nil, doc: "the server side parameter to collect all input under"
|
attr :as, :any, default: nil, doc: "the server side parameter to collect all input under"
|
||||||
|
attr :class, :string, default: "shadow rounded mt-10 bg-white dark:bg-gray-900"
|
||||||
|
|
||||||
attr :rest, :global,
|
attr :rest, :global,
|
||||||
include: ~w(autocomplete name rel action enctype method novalidate target multipart),
|
include: ~w(autocomplete name rel action enctype method novalidate target multipart),
|
||||||
|
@ -248,8 +249,8 @@ defmodule ChiyaWeb.CoreComponents do
|
||||||
|
|
||||||
def simple_form(assigns) do
|
def simple_form(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<.form :let={f} for={@for} as={@as} {@rest}>
|
<.form :let={f} for={@for} as={@as} {@rest} class={@class}>
|
||||||
<div class="space-y-8 p-3 shadow rounded bg-white dark:bg-gray-900 mt-10">
|
<div class="space-y-8 p-3">
|
||||||
<%= render_slot(@inner_block, f) %>
|
<%= render_slot(@inner_block, f) %>
|
||||||
<div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
|
<div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
|
||||||
<%= render_slot(action, f) %>
|
<%= render_slot(action, f) %>
|
||||||
|
@ -323,8 +324,7 @@ defmodule ChiyaWeb.CoreComponents do
|
||||||
attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs"
|
attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs"
|
||||||
|
|
||||||
attr :rest, :global,
|
attr :rest, :global,
|
||||||
include: ~w(autocomplete accept cols disabled form max maxlength min minlength
|
include: ~w(autocomplete accept cols disabled form max maxlength min minlength pattern placeholder readonly required rows size step)
|
||||||
pattern placeholder readonly required rows size step)
|
|
||||||
|
|
||||||
slot :inner_block
|
slot :inner_block
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ defmodule ChiyaWeb.PublicComponents do
|
||||||
statics: ChiyaWeb.static_paths()
|
statics: ChiyaWeb.static_paths()
|
||||||
|
|
||||||
import ChiyaWeb.Format
|
import ChiyaWeb.Format
|
||||||
|
import ChiyaWeb.Markdown, only: [render: 1]
|
||||||
|
import Phoenix.HTML, only: [raw: 1]
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Renders a horizontal line
|
Renders a horizontal line
|
||||||
|
@ -90,9 +92,31 @@ defmodule ChiyaWeb.PublicComponents do
|
||||||
</section>
|
</section>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_ ->
|
:microblog ->
|
||||||
~H"""
|
~H"""
|
||||||
<section class="default | mt-6 sm:w-auto flex flex-col gap-1.5">
|
<section class="note-list microblog | mt-6 text-theme-base">
|
||||||
|
<%= for note <- assigns.notes do %>
|
||||||
|
<article class="mt-8 first:mt-0">
|
||||||
|
<div class="prose prose-gruvbox">
|
||||||
|
<%= raw render(note.content) %>
|
||||||
|
</div>
|
||||||
|
<time class="text-theme-base/75">
|
||||||
|
<%= pretty_datetime(note.published_at) %>
|
||||||
|
</time>
|
||||||
|
<span>·</span>
|
||||||
|
<a href={~p"/#{note.slug}"} class="text-theme-base/75">Permalink</a>
|
||||||
|
</article>
|
||||||
|
<% end %>
|
||||||
|
</section>
|
||||||
|
"""
|
||||||
|
|
||||||
|
:photoblog ->
|
||||||
|
~H"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
_ -> # default, show headings only
|
||||||
|
~H"""
|
||||||
|
<section class="note-list default | mt-6 sm:w-auto flex flex-col gap-1.5">
|
||||||
<%= for note <- assigns.notes do %>
|
<%= for note <- assigns.notes do %>
|
||||||
<a
|
<a
|
||||||
href={~p"/#{note.slug}"}
|
href={~p"/#{note.slug}"}
|
||||||
|
|
|
@ -104,6 +104,46 @@ defmodule ChiyaWeb.NoteController do
|
||||||
|> text(raw_note)
|
|> text(raw_note)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def publish(conn, %{"id" => id}) do
|
||||||
|
note_params = %{published_at: NaiveDateTime.local_now()}
|
||||||
|
note = Notes.get_note_preloaded!(id)
|
||||||
|
|
||||||
|
case Notes.update_note(note, note_params) do
|
||||||
|
{:ok, note} ->
|
||||||
|
conn
|
||||||
|
|> put_flash(:info, "Note published successfully.")
|
||||||
|
|> redirect(to: ~p"/admin/notes/#{note}")
|
||||||
|
|
||||||
|
{:error, %Ecto.Changeset{} = changeset} ->
|
||||||
|
render(conn, :edit,
|
||||||
|
note: note,
|
||||||
|
changeset: changeset,
|
||||||
|
channels: to_channel_options(),
|
||||||
|
tags: note.tags
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unpublish(conn, %{"id" => id}) do
|
||||||
|
note_params = %{published_at: nil}
|
||||||
|
note = Notes.get_note_preloaded!(id)
|
||||||
|
|
||||||
|
case Notes.update_note(note, note_params) do
|
||||||
|
{:ok, note} ->
|
||||||
|
conn
|
||||||
|
|> put_flash(:info, "Note un-published successfully.")
|
||||||
|
|> redirect(to: ~p"/admin/notes/#{note}")
|
||||||
|
|
||||||
|
{:error, %Ecto.Changeset{} = changeset} ->
|
||||||
|
render(conn, :edit,
|
||||||
|
note: note,
|
||||||
|
changeset: changeset,
|
||||||
|
channels: to_channel_options(),
|
||||||
|
tags: note.tags
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def edit_image(conn, %{"image_id" => id}) do
|
def edit_image(conn, %{"image_id" => id}) do
|
||||||
image = Notes.get_note_image!(id)
|
image = Notes.get_note_image!(id)
|
||||||
changeset = Notes.change_note_image(image)
|
changeset = Notes.change_note_image(image)
|
||||||
|
|
|
@ -69,16 +69,20 @@
|
||||||
</article>
|
</article>
|
||||||
<% end %>
|
<% end %>
|
||||||
</aside>
|
</aside>
|
||||||
|
<% else %>
|
||||||
|
<.line />
|
||||||
|
|
||||||
|
<h2 class="mb-6 text-theme-base">No comments yet.</h2>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<.line />
|
<.line />
|
||||||
|
|
||||||
<.simple_form :let={f} for={@changeset} action={~p"/#{@note.slug}/comment"}>
|
<.simple_form :let={f} for={@changeset} action={~p"/#{@note.slug}/comment"} 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 field={f[:author_name]} type="text" placeholder="Name" />
|
<.input field={f[:author_name]} type="text" 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" />
|
||||||
<.input field={f[:content]} type="textarea" placeholder="Content" rows="3" />
|
<.input field={f[:content]} type="textarea" placeholder="Content" 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" />
|
||||||
<.input field={f[:note_id]} type="hidden" />
|
<.input field={f[:note_id]} type="hidden" />
|
||||||
<:actions>
|
<:actions>
|
||||||
<.button>Submit Comment</.button>
|
<.button>Submit Comment</.button>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
defmodule ChiyaWeb.Format do
|
defmodule ChiyaWeb.Format do
|
||||||
def from_now(%DateTime{} = later) do
|
def from_now(%DateTime{} = later) do
|
||||||
now = DateTime.utc_now()
|
now = DateTime.local_now()
|
||||||
diff = DateTime.diff(now, later)
|
diff = DateTime.diff(now, later)
|
||||||
do_from_now(diff)
|
do_from_now(diff)
|
||||||
end
|
end
|
||||||
|
|
||||||
def from_now(%NaiveDateTime{} = later) do
|
def from_now(%NaiveDateTime{} = later) do
|
||||||
now = NaiveDateTime.utc_now()
|
now = NaiveDateTime.local_now()
|
||||||
diff = NaiveDateTime.diff(now, later)
|
diff = NaiveDateTime.diff(now, later)
|
||||||
do_from_now(diff)
|
do_from_now(diff)
|
||||||
end
|
end
|
||||||
|
@ -27,9 +27,9 @@ defmodule ChiyaWeb.Format do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def pretty_date(%NaiveDateTime{} = date) do
|
def pretty_date(%NaiveDateTime{} = date), do: Calendar.strftime(date, "%d.%m.%Y")
|
||||||
Calendar.strftime(date, "%d.%m.%Y")
|
|
||||||
end
|
|
||||||
|
|
||||||
def pretty_date(_), do: ""
|
def pretty_date(_), do: ""
|
||||||
|
|
||||||
|
def pretty_datetime(%NaiveDateTime{} = date), do: Calendar.strftime(date, "%d.%m.%Y %H:%M")
|
||||||
|
def pretty_datetime(_), do: ""
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,6 +25,15 @@ defmodule ChiyaWeb.NoteShowLive do
|
||||||
<.link href={~p"/admin/notes/#{@note}/raw"}>
|
<.link href={~p"/admin/notes/#{@note}/raw"}>
|
||||||
<.button>Raw</.button>
|
<.button>Raw</.button>
|
||||||
</.link>
|
</.link>
|
||||||
|
<%= if is_nil(@note.published_at) do %>
|
||||||
|
<.link href={~p"/admin/notes/#{@note}/publish"}>
|
||||||
|
<.button>Publish</.button>
|
||||||
|
</.link>
|
||||||
|
<% else %>
|
||||||
|
<.link href={~p"/admin/notes/#{@note}/unpublish"}>
|
||||||
|
<.button>Un-Publish</.button>
|
||||||
|
</.link>
|
||||||
|
<% end %>
|
||||||
</:actions>
|
</:actions>
|
||||||
</.header>
|
</.header>
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,8 @@ defmodule ChiyaWeb.Router do
|
||||||
|
|
||||||
live "/notes/:id", NoteShowLive, :show
|
live "/notes/:id", NoteShowLive, :show
|
||||||
get "/notes/:id/raw", NoteController, :raw
|
get "/notes/:id/raw", NoteController, :raw
|
||||||
|
get "/notes/:id/publish", NoteController, :publish
|
||||||
|
get "/notes/:id/unpublish", NoteController, :unpublish
|
||||||
|
|
||||||
get "/notes/:id/image/:image_id", NoteController, :edit_image
|
get "/notes/:id/image/:image_id", NoteController, :edit_image
|
||||||
put "/notes/:id/image/:image_id", NoteController, :update_image
|
put "/notes/:id/image/:image_id", NoteController, :update_image
|
||||||
|
|
3
mix.exs
3
mix.exs
|
@ -55,7 +55,8 @@ defmodule Chiya.MixProject do
|
||||||
{:waffle, "~> 1.1"},
|
{:waffle, "~> 1.1"},
|
||||||
{:waffle_ecto, "~> 0.0.12"},
|
{:waffle_ecto, "~> 0.0.12"},
|
||||||
{:earmark, "~> 1.4"},
|
{:earmark, "~> 1.4"},
|
||||||
{:yaml_front_matter, "~> 1.0.0"}
|
{:yaml_front_matter, "~> 1.0.0"},
|
||||||
|
{:tz, "~> 0.26.1"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
1
mix.lock
1
mix.lock
|
@ -53,6 +53,7 @@
|
||||||
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
|
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
|
||||||
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
|
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
|
||||||
"telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"},
|
"telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"},
|
||||||
|
"tz": {:hex, :tz, "0.26.1", "773555ecb9c01c87fcf969b4c2d2140e63fe6b3d7d9520fa2134ac1072b540a8", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:mint, "~> 1.5", [hex: :mint, repo: "hexpm", optional: true]}], "hexpm", "da38cea41e9cfd0deaa7f634e167a30399dcc8b84fd3da32e1d972466053f57c"},
|
||||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
|
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
|
||||||
"waffle": {:hex, :waffle, "1.1.7", "518f9bdda7b9b3d0958ad6ab16066631ce028f5f12217382822a428895fc4be3", [:mix], [{:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:ex_aws_s3, "~> 2.1", [hex: :ex_aws_s3, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "e97e7b10b7f380687b5dc5e65b391538a802eff636605ad183e0bed29b45b0ef"},
|
"waffle": {:hex, :waffle, "1.1.7", "518f9bdda7b9b3d0958ad6ab16066631ce028f5f12217382822a428895fc4be3", [:mix], [{:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:ex_aws_s3, "~> 2.1", [hex: :ex_aws_s3, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "e97e7b10b7f380687b5dc5e65b391538a802eff636605ad183e0bed29b45b0ef"},
|
||||||
"waffle_ecto": {:hex, :waffle_ecto, "0.0.12", "e5c17c49b071b903df71861c642093281123142dc4e9908c930db3e06795b040", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:waffle, "~> 1.0", [hex: :waffle, repo: "hexpm", optional: false]}], "hexpm", "585fe6371057066d2e8e3383ddd7a2437ff0668caf3f4cbf5a041e0de9837168"},
|
"waffle_ecto": {:hex, :waffle_ecto, "0.0.12", "e5c17c49b071b903df71861c642093281123142dc4e9908c930db3e06795b040", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:waffle, "~> 1.0", [hex: :waffle, repo: "hexpm", optional: false]}], "hexpm", "585fe6371057066d2e8e3383ddd7a2437ff0668caf3f4cbf5a041e0de9837168"},
|
||||||
|
|
Loading…
Reference in a new issue