Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/cesium/atomic into mr/up…
Browse files Browse the repository at this point in the history
…date-partners-page
  • Loading branch information
MarioRodrigues10 committed Apr 18, 2024
2 parents 4130e52 + 8562dce commit 083b397
Show file tree
Hide file tree
Showing 36 changed files with 1,402 additions and 219 deletions.
2 changes: 1 addition & 1 deletion assets/css/components/button.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* Buttons */

.atomic-button {
@apply inline-flex items-center justify-center font-medium transition duration-150 ease-in-out border rounded-md focus:outline-none;
@apply inline-flex items-center justify-center font-medium transition duration-150 ease-in-out border rounded-md select-none focus:outline-none;
}

/* Buttons - sizes */
Expand Down
7 changes: 5 additions & 2 deletions lib/atomic/accounts/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule Atomic.Accounts.User do

alias Atomic.Accounts.Course
alias Atomic.Activities.ActivityEnrollment
alias Atomic.Organizations.{Membership, Organization}
alias Atomic.Organizations.{Collaborator, Membership, Organization}
alias Atomic.Uploaders.ProfilePicture

@required_fields ~w(email password)a
Expand All @@ -23,14 +23,17 @@ defmodule Atomic.Accounts.User do
field :password, :string, virtual: true, redact: true
field :hashed_password, :string, redact: true
field :confirmed_at, :naive_datetime

field :phone_number, :string
field :profile_picture, ProfilePicture.Type
field :role, Ecto.Enum, values: @roles, default: :student

belongs_to :course, Course
belongs_to :current_organization, Organization

has_many :activity_enrollments, ActivityEnrollment
has_many :memberships, Membership
has_many :collaborators, Collaborator

many_to_many :organizations, Organization, join_through: Membership

timestamps()
Expand Down
194 changes: 191 additions & 3 deletions lib/atomic/departments.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ defmodule Atomic.Departments do
"""
use Atomic.Context

alias Atomic.Accounts.User
alias Atomic.Organizations.{Collaborator, Department}
alias AtomicWeb.DepartmentEmails
alias AtomicWeb.Router.Helpers

@doc """
Returns the list of departments.
Expand Down Expand Up @@ -87,10 +90,11 @@ defmodule Atomic.Departments do
{:error, %Ecto.Changeset{}}
"""
def create_department(attrs \\ %{}) do
def create_department(attrs \\ %{}, after_save \\ &{:ok, &1}) do
%Department{}
|> Department.changeset(attrs)
|> Repo.insert()
|> after_save(after_save)
end

@doc """
Expand All @@ -105,10 +109,11 @@ defmodule Atomic.Departments do
{:error, %Ecto.Changeset{}}
"""
def update_department(%Department{} = department, attrs) do
def update_department(%Department{} = department, attrs, after_save \\ &{:ok, &1}) do
department
|> Department.changeset(attrs)
|> Repo.update()
|> after_save(after_save)
end

@doc """
Expand All @@ -127,6 +132,42 @@ defmodule Atomic.Departments do
Repo.delete(department)
end

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

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

@doc """
Returns an `%Ecto.Changeset{}` for tracking department changes.
Expand Down Expand Up @@ -180,7 +221,11 @@ defmodule Atomic.Departments do
** (Ecto.NoResultsError)
"""
def get_collaborator!(id), do: Repo.get!(Collaborator, id)
def get_collaborator!(id, opts \\ []) do
Collaborator
|> apply_filters(opts)
|> Repo.get!(id)
end

@doc """
Gets a single collaborator.
Expand Down Expand Up @@ -251,6 +296,24 @@ defmodule Atomic.Departments do
|> Repo.update()
end

@doc """
Accepts a collaborator.
## Examples
iex> accept_collaborator(collaborator)
{:ok, %Collaborator{}}
iex> accept_collaborator(collaborator)
{:error, %Ecto.Changeset{}}
"""
def accept_collaborator(%Collaborator{} = collaborator) do
collaborator
|> Collaborator.changeset(%{accepted: true, accepted_at: NaiveDateTime.utc_now()})
|> Repo.update()
end

@doc """
Deletes a collaborator.
Expand Down Expand Up @@ -280,6 +343,21 @@ defmodule Atomic.Departments do
Collaborator.changeset(collaborator, attrs)
end

@doc """
Returns a paginated list of collaborators.
## Examples
iex> list_display_collaborators()
[%Collaborator{}, ...]
"""
def list_display_collaborators(%{} = flop, opts \\ []) do
Collaborator
|> apply_filters(opts)
|> Flop.validate_and_run(flop, for: Collaborator)
end

@doc """
Returns the list of collaborators belonging to a department.
Expand All @@ -295,4 +373,114 @@ defmodule Atomic.Departments do
|> where([c], c.department_id == ^id)
|> Repo.all()
end

@doc """
Updates a department banner.
## Examples
iex> update_department_banner(department, %{field: new_value})
{:ok, %Department{}}
iex> update_department_banner(department, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_department_banner(%Department{} = department, attrs) do
department
|> Department.banner_changeset(attrs)
|> Repo.update()
end

@doc """
Get all admins of an organization that are collaborators of a department.
## Examples
iex> get_admin_collaborators(department)
[%User{}, ...]
"""
def get_admin_collaborators(%Department{} = department) do
User
|> join(:inner, [u], c in assoc(u, :collaborators))
|> where([u, c], c.department_id == ^department.id and c.accepted == true)
|> join(:inner, [u, c], m in assoc(u, :memberships))
|> where(
[u, c, m],
m.organization_id == ^department.organization_id and m.role in [:admin, :owner]
)
|> Repo.all()
end

@doc """
Request collaborator access and send email.
## Examples
iex> request_collaborator_access(user, department)
{:ok, %Collaborator{}}
iex> request_collaborator_access(user, department)
{:error, %Ecto.Changeset{}}
"""
def request_collaborator_access(%User{} = user, %Department{} = department) do
case create_collaborator(%{department_id: department.id, user_id: user.id}) do
{:ok, %Collaborator{} = collaborator} ->
DepartmentEmails.send_collaborator_request_email(
collaborator |> Repo.preload(:user),
department,
Helpers.department_show_path(
AtomicWeb.Endpoint,
:edit_collaborator,
department.organization_id,
department,
collaborator,
tab: "collaborators"
),
to: get_admin_collaborators(department) |> Enum.map(& &1.email)
)

{:ok, collaborator}

error ->
error
end
end

@doc """
Accept collaborator request and send email.
## Examples
iex> accept_collaborator_request(collaborator)
{:ok, %Collaborator{}}
iex> accept_collaborator_request(collaborator)
{:error, %Ecto.Changeset{}}
"""
def accept_collaborator_request(%Collaborator{} = collaborator) do
collaborator
|> Repo.preload(department: [:organization])
|> accept_collaborator()
|> case do
{:ok, collaborator} ->
DepartmentEmails.send_collaborator_accepted_email(
collaborator,
collaborator.department,
Helpers.department_show_path(
AtomicWeb.Endpoint,
:show,
collaborator.department.organization,
collaborator.department
),
to: collaborator.user.email
)

error ->
error
end
end
end
19 changes: 17 additions & 2 deletions lib/atomic/organizations/collaborator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,29 @@ defmodule Atomic.Organizations.Collaborator do
alias Atomic.Accounts.User
alias Atomic.Organizations.Department

@required_fields ~w(user_id department_id)a
@optional_fields ~w(accepted)a
@required_fields ~w(user_id department_id accepted)a
@optional_fields ~w(accepted_at)a

@derive {
Flop.Schema,
default_limit: 7,
filterable: [:accepted],
sortable: [:collaborator_name, :inserted_at, :updated_at],
default_order: %{
order_by: [:inserted_at],
order_directions: [:desc]
},
join_fields: [
collaborator_name: [binding: :user, field: :name, path: [:user, :name]]
]
}

schema "collaborators" do
belongs_to :user, User
belongs_to :department, Department

field :accepted, :boolean, default: false
field :accepted_at, :naive_datetime

timestamps()
end
Expand Down
10 changes: 9 additions & 1 deletion lib/atomic/organizations/department.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ defmodule Atomic.Organizations.Department do
alias Atomic.Organizations.Organization

@required_fields ~w(name organization_id)a
@optional_fields ~w(description)a
@optional_fields ~w(description collaborator_applications archived)a

schema "departments" do
field :name, :string
field :description, :string
field :banner, Atomic.Uploaders.Banner.Type
field :collaborator_applications, :boolean, default: false
field :archived, :boolean, default: false

belongs_to :organization, Organization, on_replace: :delete_if_exists

Expand All @@ -22,4 +25,9 @@ defmodule Atomic.Organizations.Department do
|> cast(attrs, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
end

def banner_changeset(department, attrs) do
department
|> cast_attachments(attrs, [:banner])
end
end
12 changes: 12 additions & 0 deletions lib/atomic/uploaders/banner.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule Atomic.Uploaders.Banner do
@moduledoc """
Uploader for department banners.
"""
use Atomic.Uploader

alias Atomic.Organizations.Department

def storage_dir(_version, {_file, %Department{} = scope}) do
"uploads/atomic/departments/#{scope.id}/banner"
end
end
1 change: 0 additions & 1 deletion lib/atomic_web.ex
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ defmodule AtomicWeb do
# Import LiveView and .heex helpers (live_render, live_patch, <.form>, etc)
import Phoenix.LiveView.Helpers
import Phoenix.Component
import AtomicWeb.LiveHelpers

# Import commonly used components
unquote(components())
Expand Down
10 changes: 9 additions & 1 deletion lib/atomic_web/components/avatar.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ defmodule AtomicWeb.Components.Avatar do

attr :name, :string, required: true, doc: "The name of the entity associated with the avatar."

attr :auto_generate_initials, :boolean,
default: true,
doc: "Whether to automatically generate the initials from the name."

attr :type, :atom,
values: [:user, :organization, :company],
default: :user,
Expand Down Expand Up @@ -42,7 +46,11 @@ defmodule AtomicWeb.Components.Avatar do
<%= if @src do %>
<img src={@src} class={"atomic-avatar--#{assigns.type} h-full w-full"} />
<% else %>
<%= extract_initials(@name) %>
<%= if @auto_generate_initials do %>
<%= extract_initials(@name) %>
<% else %>
<%= @name %>
<% end %>
<% end %>
</span>
"""
Expand Down
Loading

0 comments on commit 083b397

Please sign in to comment.