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: add CVs #455

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 26 additions & 1 deletion lib/atomic/accounts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,24 @@ defmodule Atomic.Accounts do
|> Repo.update()
end

@doc """
Updates the user cv.

## Examples

iex> update_user_cv(user, %{cv: ...})
{:ok, %User{}}

iex> update_user_cv(user, %{cv: ...})
{:error, %Ecto.Changeset{}}

"""
def update_user_cv(%User{} = user, attrs \\ %{}) do
user
|> User.cv_changeset(attrs)
|> Repo.update()
end

@doc """
Updates the user.

Expand All @@ -484,10 +502,17 @@ defmodule Atomic.Accounts do
{:error, %Ecto.Changeset{}}

"""
def update_user(%User{} = user, attrs \\ %{}, _after_save \\ &{:ok, &1}) do
def update_user(
%User{} = user,
attrs \\ %{},
after_save_cv \\ &{:ok, &1},
after_save_image \\ &{:ok, &1}
) do
user
|> User.changeset(attrs)
|> Repo.update()
|> after_save(after_save_cv)
|> after_save(after_save_image)
end

@doc """
Expand Down
15 changes: 14 additions & 1 deletion lib/atomic/accounts/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule Atomic.Accounts.User do
alias Atomic.Accounts.Course
alias Atomic.Activities.ActivityEnrollment
alias Atomic.Organizations.{Membership, Organization}
alias Atomic.Uploaders.ProfilePicture
alias Atomic.Uploaders.{CV, ProfilePicture}

@required_fields ~w(email password)a
@optional_fields ~w(name slug role phone_number confirmed_at course_id current_organization_id)a
Expand All @@ -26,6 +26,7 @@ defmodule Atomic.Accounts.User do

field :phone_number, :string
field :profile_picture, ProfilePicture.Type
field :cv, CV.Type
field :role, Ecto.Enum, values: @roles, default: :student
belongs_to :course, Course
belongs_to :current_organization, Organization
Expand Down Expand Up @@ -60,12 +61,24 @@ defmodule Atomic.Accounts.User do
|> validate_password(opts)
end

@doc """
A user changeset for updating the user's profile picture.
"""
def picture_changeset(user, attrs) do
user
|> cast(attrs, @required_fields ++ @optional_fields)
|> cast_attachments(attrs, [:profile_picture])
end

@doc """
A user changeset for updating the user's CV.
"""
def cv_changeset(user, attrs) do
user
|> cast(attrs, @required_fields ++ @optional_fields)
|> cast_attachments(attrs, [:cv])
end

@doc """
A user changeset for updating the user.
"""
Expand Down
2 changes: 1 addition & 1 deletion lib/atomic/uploader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Atomic.Uploader do
"""

@versions [:original, :medium, :thumb]
@extensions_whitelist ~w(.svg .jpg .jpeg .png)
@extensions_whitelist ~w(.svg .jpg .jpeg .png .pdf .docx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should handle CV in this module. It defines functions to apply image transformations which do not make sense in a PDF or DOCX file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should i break this logic in this PR, or should i refactor the code in another?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one


defmacro __using__(_) do
quote do
Expand Down
11 changes: 11 additions & 0 deletions lib/atomic/uploaders/cv.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule Atomic.Uploaders.CV do
@moduledoc """
Uploader for CVs.
"""
use Atomic.Uploader
alias Atomic.Accounts.User

def storage_dir(_version, {_file, %User{} = scope}) do
"uploads/atomic/user_cvs/#{scope.id}"
end
end
61 changes: 45 additions & 16 deletions lib/atomic_web/live/profile_live/form_component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ defmodule AtomicWeb.ProfileLive.FormComponent do

alias Atomic.Accounts

@extensions_whitelist ~w(.jpg .jpeg .gif .png)
@extensions_whitelist ~w(.jpg .jpeg .gif .png .pdf .docx)

@impl true
def mount(socket) do
{:ok,
socket
|> allow_upload(:cv, accept: @extensions_whitelist, max_entries: 1)
|> allow_upload(:picture, accept: @extensions_whitelist, max_entries: 1)}
end

Expand Down Expand Up @@ -54,6 +55,7 @@ defmodule AtomicWeb.ProfileLive.FormComponent do
case Accounts.update_user(
user,
Map.put(user_params, "email", user.email),
&consume_cv_data(socket, &1),
&consume_image_data(socket, &1)
) do
{:ok, _user} ->
Expand All @@ -68,21 +70,48 @@ defmodule AtomicWeb.ProfileLive.FormComponent do
end

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

_errors ->
{:ok, user}
if Map.has_key?(socket.assigns.uploads, :image) do
consume_uploaded_entries(socket, :image, fn %{path: path}, entry ->
Accounts.update_user_picture(user, %{
"image" => %Plug.Upload{
content_type: entry.client_type,
filename: entry.client_name,
path: path
}
})
end)
|> case do
[{:ok, user}] ->
{:ok, user}

_errors ->
{:ok, user}
end
end

{:ok, user}
end

defp consume_cv_data(socket, user) do
if Map.has_key?(socket.assigns.uploads, :cv) do
consume_uploaded_entries(socket, :cv, fn %{path: path}, entry ->
Accounts.update_user_cv(user, %{
"cv" => %Plug.Upload{
content_type: entry.client_type,
filename: entry.client_name,
path: path
}
})
end)
|> case do
[{:ok, user}] ->
{:ok, user}

_errors ->
{:ok, user}
end
end

{:ok, user}
end
end
4 changes: 4 additions & 0 deletions lib/atomic_web/live/profile_live/form_component.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
) %>
<div class="flex flex-col text-sm w-full sm:w-96 text-red-600"><%= error_tag(f, :phone_number) %></div>
</div>
<div class="flex flex-col justify-center">
<%= label(f, :Upload_CV, class: "mb-1 text-sm font-medium text-gray-700") %>
<.live_file_input upload={@uploads.cv} class="" />
</div>
</div>
<.live_file_input upload={@uploads.picture} class="hidden" />
<a onclick={"document.getElementById('#{@uploads.picture.ref}').click()"}>
Expand Down
Binary file added priv/fake/teste_cv.pdf
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ defmodule Atomic.Repo.Migrations.CreateUsersAuthTables do
add :hashed_password, :string, null: false
add :confirmed_at, :naive_datetime
add :profile_picture, :string
add :cv, :string
MarioRodrigues10 marked this conversation as resolved.
Show resolved Hide resolved
add :role, :string, null: false, default: "student"

add :current_organization_id,
Expand Down
16 changes: 16 additions & 0 deletions test/atomic/accounts_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -511,4 +511,20 @@ defmodule Atomic.AccountsTest do
refute inspect(%User{password: "123456"}) =~ "password: \"123456\""
end
end

describe "upload CV" do
test "uploads a CV" do
user = insert(:user)

cv = %Plug.Upload{
content_type: "application/pdf",
filename: "teste_cv.pdf",
path: "priv/fake/teste_cv.pdf"
}

{:ok, user} = Accounts.update_user_cv(user, %{"cv" => cv})
assert user.cv
assert cv.filename == user.cv.file_name
end
end
end
Loading