Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: improve announcements pages #530

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
22 changes: 20 additions & 2 deletions lib/atomic/organizations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ defmodule Atomic.Organizations do
{:error, %Ecto.Changeset{}}

"""
def create_announcement_with_post(attrs \\ %{}) do
def create_announcement_with_post(attrs \\ %{}, after_save \\ &{:ok, &1}) do
Multi.new()
|> Multi.insert(:post, fn _ ->
%Post{}
Expand All @@ -580,7 +580,7 @@ defmodule Atomic.Organizations do
|> Repo.transaction()
|> case do
{:ok, %{announcement: announcement, post: _post}} ->
{:ok, announcement}
after_save.({:ok, announcement})

{:error, _reason, changeset, _actions} ->
{:error, changeset}
Expand Down Expand Up @@ -639,4 +639,22 @@ defmodule Atomic.Organizations do
def change_announcement(%Announcement{} = announcement, attrs \\ %{}) do
Announcement.changeset(announcement, attrs)
end

@doc """
Updates an announcement image.

## Examples

iex> update_announcement_image(announcement, %{field: new_value})
{:ok, %Announcement{}}

iex> update_announcement_image(announcement, %{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def update_announcement_image(%Announcement{} = announcement, attrs) do
announcement
|> Announcement.image_changeset(attrs)
|> Repo.update()
end
end
36 changes: 33 additions & 3 deletions lib/atomic_web/live/announcement_live/form_component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule AtomicWeb.AnnouncementLive.FormComponent do
use AtomicWeb, :live_component

alias Atomic.Organizations
alias AtomicWeb.Components.ImageUploader

import AtomicWeb.Components.Forms

Expand All @@ -17,7 +18,8 @@ defmodule AtomicWeb.AnnouncementLive.FormComponent do
{:ok,
socket
|> assign(assigns)
|> assign(:changeset, changeset)}
|> assign(:changeset, changeset)
|> allow_upload(:image, accept: Uploaders.Post.extension_whitelist(), max_entries: 1)}
end

@impl true
Expand All @@ -35,10 +37,16 @@ defmodule AtomicWeb.AnnouncementLive.FormComponent do
save_announcement(socket, socket.assigns.action, announcement_params)
end

@impl true
def handle_event("cancel-image", %{"ref" => ref}, socket) do
{:noreply, cancel_upload(socket, :image, ref)}
end

defp save_announcement(socket, :edit, announcement_params) do
case Organizations.update_announcement(
socket.assigns.announcement,
announcement_params
announcement_params,
&consume_image_data(socket, &1)
) do
{:ok, _announcement} ->
{:noreply,
Expand All @@ -55,7 +63,10 @@ defmodule AtomicWeb.AnnouncementLive.FormComponent do
announcement_params =
Map.put(announcement_params, "organization_id", socket.assigns.organization.id)

case Organizations.create_announcement_with_post(announcement_params) do
case Organizations.create_announcement_with_post(
announcement_params,
&consume_image_data(socket, &1)
) do
{:ok, _announcement} ->
{:noreply,
socket
Expand All @@ -66,4 +77,23 @@ defmodule AtomicWeb.AnnouncementLive.FormComponent do
{:noreply, assign(socket, :changeset, changeset)}
end
end

defp consume_image_data(socket, {:ok, announcement}) do
consume_uploaded_entries(socket, :image, fn %{path: path}, entry ->
Organizations.update_announcement_image(announcement, %{
"image" => %Plug.Upload{
content_type: entry.client_type,
filename: entry.client_name,
path: path
}
})
end)
|> case do
[{:ok, announcement}] ->
{:ok, announcement}

_errors ->
{:ok, announcement}
end
end
end
23 changes: 19 additions & 4 deletions lib/atomic_web/live/announcement_live/form_component.html.heex
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
<div>
<.form :let={f} for={@changeset} id="announcement-form" phx-target={@myself} phx-change="validate" phx-submit="save">
<.field field={f[:title]} help_text={gettext("The title of the announcement")} type="text" placeholder="Title" required />
<div class="relative">
<.form :let={f} for={@changeset} id="announcement-form" phx-target={@myself} phx-change="validate" phx-submit="save" class="space-y-6">
<div class="relative pb-16">
<div class="grid gap-4 xl:grid-cols-2">
<div class="flex flex-col">
<.field field={f[:title]} type="text" placeholder="Choose a title for the announcement" required class="w-full" />

<.field field={f[:description]} help_text={gettext("Announcement description")} type="text" placeholder="Description" required />
<.field field={f[:description]} type="textarea" placeholder="Write a description" required class="w-full overflow-auto resize-none h-44 xl:h-64" />
</div>

<<<<<<< jc/improve-announcements
<div class="space-y-4">
<.live_component module={ImageUploader} id="uploader" uploads={@uploads} target={@myself} class="object-cover" />

<div class="flex justify-end">
<.button size={:md} color={:white} icon={:cube} type="submit"><%= gettext("Save Changes") %></.button>
</div>
</div>
</div>
=======
<div class="mt-8 flex w-full justify-end">
<.button size={:md} color={:white} icon="hero-cube" type="submit"><%= gettext("Save Changes") %></.button>
>>>>>>> develop
</div>
</.form>
</div>
2 changes: 1 addition & 1 deletion lib/atomic_web/live/announcement_live/index.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule AtomicWeb.AnnouncementLive.Index do
use AtomicWeb, :live_view

import AtomicWeb.Components.{Button, Empty, Pagination, Tabs}
import AtomicWeb.Components.{Announcement, Button, Empty, Pagination, Tabs}

alias Atomic.Accounts
alias Atomic.Organizations
Expand Down
15 changes: 4 additions & 11 deletions lib/atomic_web/live/announcement_live/index.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,10 @@
<div class="overflow-hidden bg-white">
<ul role="list" class="divide-y divide-zinc-200 overflow-auto">
<%= for announcement <- @announcements do %>
<li id={announcement.id}>
<.link navigate={Routes.announcement_show_path(@socket, :show, announcement)} class="block hover:bg-zinc-50">
<div class="px-4 py-4 lg:px-6">
<div class="flex items-center justify-between">
<p class="truncate text-sm font-medium text-zinc-900">
<%= announcement.title %>
</p>
</div>
<p class="mt-2 text-sm text-zinc-500">
<%= announcement.description %>
</p>
<li id={announcement.id} class="py-4 px-4 mx-auto max-w-5xl border-b border-gray-200 sm:px-2 lg:px-4">
<.link navigate={Routes.announcement_show_path(@socket, :show, announcement)}>
<div class="break-words">
<.announcement announcement={announcement} />
</div>
</.link>
</li>
Expand Down
2 changes: 2 additions & 0 deletions lib/atomic_web/live/announcement_live/show.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
defmodule AtomicWeb.AnnouncementLive.Show do
use AtomicWeb, :live_view

import AtomicWeb.Components.Announcement

alias Atomic.Accounts
alias Atomic.Organizations

Expand Down
30 changes: 11 additions & 19 deletions lib/atomic_web/live/announcement_live/show.html.heex
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
<div class="py-4 px-4 sm:px-0">
<div class="px-4 flex flex-col gap-2 mt-6 sm:flex-row sm:items-center">
<div>
<div class="flex justify-between items-center">
<h4 class="text-2xl font-bold text-zinc-800">
<%= @announcement.title %>
</h4>
</div>
<p class="mt-1 text-zinc-500">
<%= @announcement.description %>
</p>
</div>
<div id={@announcement.id} class="py-4 px-4 mx-auto max-w-5xl sm:px-2 lg:px-4">
<.link navigate={Routes.announcement_show_path(@socket, :show, @announcement)}>
<.announcement announcement={@announcement} />
</.link>
</div>
<%= if @has_permissions? do %>
<.link patch={Routes.announcement_edit_path(@socket, :edit, @announcement.organization, @announcement)} class="px-4 button">
<div type="button" class="inline-flex justify-center py-2 px-4 w-fit text-sm font-medium text-zinc-700 bg-white rounded-md border border-zinc-300 shadow-sm hover:bg-zinc-50" id="sort-menu-button" aria-expanded="false" aria-haspopup="true">
<.icon name={:pencil} solid class="mr-3 w-5 h-5 text-zinc-400" /> Edit
</div>
</.link>
<% end %>
</div>

<%= if @has_permissions? do %>
<.link patch={Routes.announcement_edit_path(@socket, :edit, @announcement.organization, @announcement)} class="px-2 button">
<div type="button" class="inline-flex justify-center py-2 px-4 w-fit text-sm font-medium text-zinc-700 bg-white rounded-md border border-zinc-300 shadow-sm hover:bg-zinc-50" id="sort-menu-button" aria-expanded="false" aria-haspopup="true">
<.icon name="hero-pencil-solid" class="mr-3 w-5 h-5 text-zinc-400" /> Edit
</div>
</.link>
<% end %>
Loading