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

feat: partners pages #442

Merged
merged 37 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e85ea53
Update partners index page
MarioRodrigues10 Oct 13, 2023
5109fea
Run formatter
MarioRodrigues10 Oct 13, 2023
f8db132
Merge branch 'develop' into mr/update-partners-page
MarioRodrigues10 Nov 10, 2023
e946817
Merge branch 'develop' into mr/update-partners-page
MarioRodrigues10 Feb 18, 2024
626debf
feat: partners page
MarioRodrigues10 Mar 8, 2024
5fc9f9f
Merge branch 'develop' of https://github.com/cesium/atomic into develop
MarioRodrigues10 Mar 8, 2024
84f8047
fix: merge conflicts
MarioRodrigues10 Mar 8, 2024
5f36449
chore: partners page
MarioRodrigues10 Mar 8, 2024
10728ed
fix: linting
MarioRodrigues10 Mar 8, 2024
fc14243
Merge branch 'develop' of https://github.com/cesium/atomic into mr/up…
MarioRodrigues10 Mar 9, 2024
795bfcb
chore: implement suggestions
MarioRodrigues10 Mar 9, 2024
092a5bb
fix: CI
MarioRodrigues10 Mar 9, 2024
91bd42a
chore: implement suggestions
MarioRodrigues10 Mar 11, 2024
b7e8958
chore: merge recent changes
MarioRodrigues10 Mar 22, 2024
f4aa867
chore: index and show page
MarioRodrigues10 Mar 27, 2024
ec69d6c
chore: update show page
MarioRodrigues10 Apr 12, 2024
f373ca1
Merge branch 'develop' of https://github.com/cesium/atomic into mr/up…
MarioRodrigues10 Apr 17, 2024
4130e52
chore: show and forms
MarioRodrigues10 Apr 18, 2024
083b397
Merge branch 'develop' of https://github.com/cesium/atomic into mr/up…
MarioRodrigues10 Apr 18, 2024
72d9c7e
feat: forms
MarioRodrigues10 Apr 24, 2024
baf5172
fix: remove IOs
MarioRodrigues10 Apr 24, 2024
6fd1479
Merge branch 'develop' into mr/update-partners-page
MarioRodrigues10 Apr 24, 2024
c004bb4
feat: add inactive partners
MarioRodrigues10 Apr 24, 2024
21f26d3
fix: remove unnecessary comment
MarioRodrigues10 Apr 24, 2024
56a5835
chore: implement suggestions
MarioRodrigues10 Jun 10, 2024
71ff9b4
chore: implement suggestions
MarioRodrigues10 Jun 17, 2024
4fbc539
fix: remove unnecessary comment
MarioRodrigues10 Jun 17, 2024
bd3fc85
fix: remove unnecessary state
MarioRodrigues10 Jun 17, 2024
34f189e
chore: state to archive nomenclature
MarioRodrigues10 Jun 17, 2024
c391482
chore: icons
MarioRodrigues10 Jun 17, 2024
f1f5462
chore: function name
MarioRodrigues10 Jun 17, 2024
1acc227
chore: implement suggestions
MarioRodrigues10 Jun 17, 2024
1ff218f
chore: implement suggestions
MarioRodrigues10 Jun 18, 2024
903adf5
chore: implement suggestions
MarioRodrigues10 Jul 1, 2024
95c3140
chore: documentation
MarioRodrigues10 Jul 1, 2024
c267f44
fix: website link
MarioRodrigues10 Jul 1, 2024
673ec83
Merge branch 'develop' into mr/update-partners-page
MarioRodrigues10 Jul 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/atomic/activities/activity.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ defmodule Atomic.Activities.Activity do
alias Atomic.Activities.{
ActivityEnrollment,
ActivitySpeaker,
Location,
Speaker
}

alias Atomic.Events.Event
alias Atomic.Feed.Post
alias Atomic.Location
alias Atomic.Organizations.Organization

@required_fields ~w(title description start finish minimum_entries maximum_entries organization_id enrolled)a
Expand Down
2 changes: 1 addition & 1 deletion lib/atomic/events/event.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ defmodule Atomic.Events.Event do
use Atomic.Schema

alias Atomic.Activities.Activity
alias Atomic.Activities.Location
alias Atomic.Events.EventEnrollment
alias Atomic.Events.EventOrganization
alias Atomic.Location

@required_fields ~w(name location_id)a
@optional_fields ~w(description event_organization_id)a
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule Atomic.Activities.Location do
defmodule Atomic.Location do
@moduledoc """
An activity location embedded struct schema.
A location embedded struct schema.
"""
use Atomic.Schema

Expand Down
2 changes: 1 addition & 1 deletion lib/atomic/organizations/organization.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Atomic.Organizations.Organization do
use Atomic.Schema

alias Atomic.Accounts.User
alias Atomic.Activities.Location
alias Atomic.Location
alias Atomic.Organizations.{Announcement, Board, Card, Department, Membership, Partner}
alias Atomic.Uploaders

Expand Down
15 changes: 11 additions & 4 deletions lib/atomic/organizations/partner.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ defmodule Atomic.Organizations.Partner do
"""
use Atomic.Schema

alias Atomic.Location
alias Atomic.Organizations.Organization
alias Atomic.Socials

@required_fields ~w(name organization_id)a
@optional_fields ~w(description state image)a
@states ~w(active inactive)a
@optional_fields ~w(description benefits archived image notes)a

@derive {
Flop.Schema,
Expand All @@ -24,17 +25,23 @@ defmodule Atomic.Organizations.Partner do
schema "partners" do
field :name, :string
field :description, :string
field :state, Ecto.Enum, values: @states, default: :active
field :benefits, :string
field :archived, :boolean, default: false
field :image, Uploaders.PartnerImage.Type

embeds_one :location, Location, on_replace: :update
embeds_one :socials, Socials, on_replace: :update
belongs_to :organization, Organization

field :notes, :string

timestamps()
end

def changeset(partner, attrs) do
partner
|> cast(attrs, @required_fields ++ @optional_fields)
|> cast_embed(:location, with: &Location.changeset/2)
|> cast_embed(:socials, with: &Socials.changeset/2)
|> cast_attachments(attrs, [:image])
|> validate_required(@required_fields)
|> unique_constraint(:name)
Expand Down
79 changes: 66 additions & 13 deletions lib/atomic/partnerships.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ defmodule Atomic.Partners do
use Atomic.Context

alias Atomic.Organizations.Partner
alias Atomic.Socials

@doc """
Returns the list of partners.
Expand All @@ -25,17 +26,10 @@ defmodule Atomic.Partners do
|> Flop.validate_and_run(flop, for: Partner)
end

@doc """
Returns the list of partners belonging to an organization.
## Examples
iex> list_partners_by_organization_id("99d7c9e5-4212-4f59-a097-28aaa33c2621")
[%Partner{}, ...]
"""
def list_partners_by_organization_id(id) do
Repo.all(from p in Partner, where: p.organization_id == ^id)
def list_partners(opts) when is_list(opts) do
Partner
|> apply_filters(opts)
|> Repo.all()
end

@doc """
Expand Down Expand Up @@ -66,10 +60,11 @@ defmodule Atomic.Partners do
{:error, %Ecto.Changeset{}}
"""
def create_partner(attrs \\ %{}, _after_save \\ &{:ok, &1}) do
def create_partner(attrs \\ %{}, after_save \\ &{:ok, &1}) do
%Partner{}
|> Partner.changeset(attrs)
|> Repo.insert()
|> after_save(after_save)
end

@doc """
Expand All @@ -84,10 +79,29 @@ defmodule Atomic.Partners do
{:error, %Ecto.Changeset{}}
"""
def update_partner(%Partner{} = partner, attrs, _after_save \\ &{:ok, &1}) do
def update_partner(%Partner{} = partner, attrs, after_save \\ &{:ok, &1}) do
partner
|> Partner.changeset(attrs)
|> Repo.update()
|> after_save(after_save)
end

@doc """
Updates a partner's picture.
## Examples
iex> update_partner_picture(partner, %{image: %Plug.Upload{}})
{:ok, %Partner{}}
iex> update_partner_picture(partner, %{image: %Plug.Upload{}})
{:error, %Ecto.Changeset{}}
"""
def update_partner_picture(%Partner{} = partner, attrs, _after_save \\ &{:ok, &1}) do
partner
|> Partner.image_changeset(attrs)
|> Repo.update()
end

@doc """
Expand All @@ -106,6 +120,41 @@ defmodule Atomic.Partners do
Repo.delete(partner)
end

@doc """
Archives a partner.
## Examples
iex> archive_partner(partner)
{:ok, %Partner{}}
iex> archive_partner(partner)
{:error, %Ecto.Changeset{}}
"""
def archive_partner(%Partner{} = partner) do
partner
|> Partner.changeset(%{archived: true})
|> Repo.update()
end

@doc """
Unarchives a partner.
## Examples
iex> unarchive_partner(partner)
{:ok, %Partner{}}
iex> unarchive_partner(partner)
{:error, %Ecto.Changeset{}}
"""
def unarchive_partner(%Partner{} = partner) do
partner
|> Partner.changeset(%{archived: false})
|> Repo.update()
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking partner changes.
Expand All @@ -118,4 +167,8 @@ defmodule Atomic.Partners do
def change_partner(%Partner{} = partner, attrs \\ %{}) do
Partner.changeset(partner, attrs)
end

def change_partner_socials(%Socials{} = socials, attrs \\ %{}) do
Socials.changeset(socials, attrs)
end
end
25 changes: 25 additions & 0 deletions lib/atomic/socials/socials.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
defmodule Atomic.Socials do
@moduledoc """
A socials embedded struct schema.
"""
use Atomic.Schema

@optional_fields ~w(instagram facebook x youtube tiktok website)a

@derive Jason.Encoder
@primary_key false
embedded_schema do
field :instagram, :string
field :facebook, :string
field :x, :string
field :youtube, :string
field :tiktok, :string
field :website, :string
end

def changeset(socials, attrs) do
socials
|> cast(attrs, @optional_fields)
|> validate_format(:website, ~r{^https?://}, message: "must start with http:// or https://")
end
end
3 changes: 2 additions & 1 deletion lib/atomic/uploaders/partner_image.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ defmodule Atomic.Uploaders.PartnerImage do
Uploader for partner images.
"""
use Atomic.Uploader

alias Atomic.Organizations.Partner

def storage_dir(_version, {_file, %Partner{} = scope}) do
"uploads/partners/#{scope.id}"
"uploads/atomic/partners/#{scope.id}"
end
end
110 changes: 108 additions & 2 deletions lib/atomic_web/live/partner_live/edit.ex
Original file line number Diff line number Diff line change
@@ -1,21 +1,127 @@
defmodule AtomicWeb.PartnerLive.Edit do
use AtomicWeb, :live_view

alias Atomic.Organizations.Partner
alias Atomic.Partners
alias Phoenix.LiveView.JS

@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end

@impl true
def handle_params(%{"id" => partner_id} = _params, _, socket) do
def handle_params(
%{"id" => partner_id} = _params,
_,
%{:assigns => %{:live_action => :edit}} = socket
) do
partner = Partners.get_partner!(partner_id)

{:noreply,
socket
|> assign(:page_title, partner.name)
|> assign(:action, nil)
|> assign(:partner, partner)
|> assign(:current_page, :partner)}
|> assign(:current_page, :partners)}
end

@impl true
def handle_params(_params, _, %{:assigns => %{:live_action => :new}} = socket) do
{:noreply,
socket
|> assign(:page_title, "New Partner")
|> assign(:action, nil)
|> assign(:partner, %Partner{organization_id: socket.assigns.current_organization.id})
|> assign(:current_page, :partners)}
end

@impl true
def handle_event("set-action", %{"action" => action}, socket) do
{:noreply, assign(socket, :action, action |> String.to_atom())}
end

@impl true
def handle_event("clear-action", _params, socket) do
{:noreply, assign(socket, :action, nil)}
end

@impl true
def handle_event("confirm-action", _params, %{assigns: %{action: :delete}} = socket) do
partner = socket.assigns.partner
organization_id = partner.organization_id

case Partners.delete_partner(partner) do
{:ok, _partner} ->
{:noreply,
socket
|> put_flash(:success, "Partner deleted successfully")
|> push_redirect(to: Routes.partner_index_path(socket, :index, organization_id))}

{:error, _reason} ->
{:noreply, put_flash(socket, :error, "Failed to delete partner")}
end
end

@impl true
def handle_event("confirm-action", _params, %{assigns: %{action: :archive}} = socket) do
partner = socket.assigns.partner
organization_id = partner.organization_id

case Partners.archive_partner(partner) do
{:ok, _partner} ->
{:noreply,
socket
|> put_flash(:success, "Partner archived successfully")
|> push_redirect(to: Routes.partner_index_path(socket, :index, organization_id))}

{:error, _reason} ->
{:noreply, put_flash(socket, :error, "Failed to delete partner")}
end
end

def handle_event("confirm-action", _params, %{assigns: %{action: :unarchive}} = socket) do
partner = socket.assigns.partner
organization_id = partner.organization_id

case Partners.unarchive_partner(partner) do
{:ok, _partner} ->
{:noreply,
socket
|> put_flash(:success, "Partner archived successfully")
|> push_redirect(to: Routes.partner_index_path(socket, :index, organization_id))}

{:error, _reason} ->
{:noreply, put_flash(socket, :error, "Failed to delete partner")}
end
end

defp display_action_goal_confirm_title(action) do
case action do
:archive ->
gettext("Are you sure you want to archive this partner?")

:unarchive ->
gettext("Are you sure you want to unarchive this partner?")

:delete ->
gettext("Are you sure you want do delete this partner?")
end
end

defp display_action_goal_confirm_description(action, partner) do
case action do
:archive ->
gettext("You can always change you mind later and make it public again.")

:unarchive ->
gettext("This will make it so that any person can view this partner.")

:delete ->
gettext(
"This will permanently delete %{partner_name}, this action is not reversible.",
partner_name: partner.name
)
end
end
end
Loading
Loading