Skip to content

Commit 6e708a2

Browse files
committed
Add project user request email
1 parent f90220e commit 6e708a2

File tree

12 files changed

+239
-10
lines changed

12 files changed

+239
-10
lines changed

config/dev.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ config :code_corps,
6262
postmark_forgot_password_template: "123",
6363
postmark_organization_invite_email_template: "123",
6464
postmark_project_acceptance_template: "123",
65+
postmark_project_request_template: "123",
6566
postmark_receipt_template: "123"
6667

6768
# If the dev environment has no CLOUDEX_API_KEY set, we want the app

config/prod.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ config :code_corps,
6363
postmark_forgot_password_template: "1989483",
6464
postmark_organization_invite_email_template: "3441863",
6565
postmark_project_acceptance_template: "1447041",
66+
postmark_project_request_template: "4017262",
6667
postmark_receipt_template: "1255222"
6768

6869
# ## SSL Support

config/remote-development.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ config :code_corps, CodeCorps.Mailer,
4545
config :code_corps,
4646
postmark_forgot_password_template: "123",
4747
postmark_project_acceptance_template: "123",
48+
postmark_project_request_template: "123",
4849
postmark_receipt_template: "123"
4950

5051
# ## SSL Support

config/staging.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ config :code_corps,
6262
postmark_forgot_password_template: "1989481",
6363
postmark_organization_invite_email_template: "3442401",
6464
postmark_project_acceptance_template: "1447022",
65+
postmark_project_request_template: "4017261",
6566
postmark_receipt_template: "1252361"
6667

6768
# ## SSL Support

config/test.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ config :code_corps, CodeCorps.Mailer,
6767
config :code_corps,
6868
postmark_forgot_password_template: "123",
6969
postmark_project_acceptance_template: "123",
70+
postmark_project_request_template: "123",
7071
postmark_receipt_template: "123"
7172

7273
config :code_corps, :cloudex, CloudexTest

emails/project_user_acceptance.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@
6060
</p>
6161
<p>Go check out the project and see what you can do to get started.
6262
</p>
63-
</tr>
64-
</td>
63+
</td>
64+
</tr>
6565
</table>
6666
<table class="body-signature">
6767
<tr>

emails/project_user_request.html

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2+
<html xmlns="http://www.w3.org/1999/xhtml">
3+
<head>
4+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6+
<title>{{user_first_name}} wants to join {{project_title}}</title>
7+
<!--
8+
Make sure you copy the styles from styles.css into the email template in Postmark before saving there.
9+
10+
<style type="text/css" rel="stylesheet" media="all">
11+
</style>
12+
-->
13+
<link rel="stylesheet" type="text/css" href="styles.css" media="screen" />
14+
</head>
15+
<body>
16+
<span class="preheader">Head over to the app to process their request.</span>
17+
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0">
18+
<tr>
19+
<td align="center">
20+
<table class="email-content" width="100%" cellpadding="0" cellspacing="0">
21+
<tr>
22+
<td class="email-masthead" width="100%" cellpadding="0" cellspacing="0">
23+
<table class="email-masthead_inner" align="center" width="570" cellpadding="0" cellspacing="0">
24+
<tr>
25+
<td>
26+
<a href="https://www.codecorps.org">
27+
<img src="https://d3pgew4wbk2vb1.cloudfront.net/emails/images/logo-small@2x.png" class="email-masthead_logo" />
28+
</a>
29+
</td>
30+
</tr>
31+
</table>
32+
</td>
33+
</tr>
34+
<!-- Email Body -->
35+
<tr>
36+
<td class="email-body" width="100%" cellpadding="0" cellspacing="0">
37+
<table class="email-body_inner" align="center" width="570" cellpadding="0" cellspacing="0">
38+
<!-- Body content -->
39+
<tr>
40+
<td class="content-cell">
41+
<table class="donation" width="100%" cellpadding="0" cellspacing="0">
42+
<tr>
43+
<td>
44+
<ul class="joined_images center">
45+
<li class="photo">
46+
<img src="{{project_logo_url}}" width="70" height="70" />
47+
</li>
48+
<li class="icon">
49+
<img src="https://d3pgew4wbk2vb1.cloudfront.net/emails/images/requested-email@2x.png" width="25" height="70" />
50+
</li>
51+
<li class="photo">
52+
<img src="{{user_image_url}}" width="70" height="70" />
53+
</li>
54+
</ul>
55+
<p>
56+
Hi {{project_title}} team,
57+
</p>
58+
<p class="project-membership--requested">
59+
<strong>{{user_first_name}}</strong> just requested to join {{project_title}}.
60+
</p>
61+
<p>
62+
You can head over to <a href="{{contributors_url}}">your project's contributors page</a> to process their request.
63+
</p>
64+
<p>
65+
Take a look at the skills they bring and think about how you can integrate them into your project.
66+
</p>
67+
<p>
68+
We also recommend reading GitHub's guides for <a href="https://opensource.guide/building-community/#setting-your-project-up-for-success">how to build a welcoming open source community</a>.
69+
</p>
70+
</td>
71+
</tr>
72+
</table>
73+
<table class="body-signature">
74+
<tr>
75+
<td>
76+
<p>
77+
Cheers,
78+
<br><strong>The Code Corps Team</strong>
79+
</p>
80+
<p class="center small">
81+
Questions? Feedback?
82+
<br>Visit our <strong><a href="https://help.codecorps.org">Help Center</a></strong> or just reply to this email.</p>
83+
</td>
84+
</tr>
85+
</table>
86+
</td>
87+
</tr>
88+
</table>
89+
</td>
90+
</tr>
91+
<tr>
92+
<td>
93+
<table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0">
94+
<tr>
95+
<td class="content-cell" align="center">
96+
<p class="sub align-center">
97+
Code Corps PBC
98+
<br>4166 Wilson Ave #1
99+
<br>San Diego, CA 92104
100+
</p>
101+
</td>
102+
</tr>
103+
</table>
104+
</td>
105+
</tr>
106+
</table>
107+
</td>
108+
</tr>
109+
</table>
110+
</body>
111+
</html>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
defmodule CodeCorps.Emails.ProjectUserRequestEmail do
2+
import Bamboo.Email, only: [to: 2]
3+
import Bamboo.PostmarkHelper
4+
import Ecto.Query
5+
6+
alias CodeCorps.{Project, ProjectUser, Repo, User, WebClient}
7+
alias CodeCorps.Emails.BaseEmail
8+
alias CodeCorps.Presenters.ImagePresenter
9+
10+
@spec create(ProjectUser.t) :: Bamboo.Email.t
11+
def create(%ProjectUser{project: project, user: user}) do
12+
BaseEmail.create
13+
|> to(project |> get_owners_emails())
14+
|> template(template_id(), build_model(project, user))
15+
end
16+
17+
@spec build_model(Project.t, User.t) :: map
18+
defp build_model(%Project{} = project, %User{} = user) do
19+
%{
20+
contributors_url: project |> preload() |> url(),
21+
project_logo_url: ImagePresenter.large(project),
22+
project_title: project.title,
23+
subject: "#{user.first_name} wants to join #{project.title}",
24+
user_first_name: user.first_name,
25+
user_image_url: ImagePresenter.large(user)
26+
}
27+
end
28+
29+
@spec preload(Project.t) :: Project.t
30+
defp preload(%Project{} = project), do: project |> Repo.preload(:organization)
31+
32+
@spec url(Project.t) :: String.t
33+
defp url(project) do
34+
WebClient.url()
35+
|> URI.merge(project.organization.slug <> "/" <> project.slug <> "/settings/contributors")
36+
|> URI.to_string
37+
end
38+
39+
@spec template_id :: String.t
40+
defp template_id, do: Application.get_env(:code_corps, :postmark_project_request_template)
41+
42+
@spec get_owners_emails(Project.t) :: list(String.t)
43+
defp get_owners_emails(%Project{} = project) do
44+
project |> get_owners() |> Enum.map(&extract_email/1)
45+
end
46+
47+
@spec extract_email(User.t) :: String.t
48+
defp extract_email(%User{email: email}), do: email
49+
50+
@spec get_owners(Project.t) :: list(User.t)
51+
defp get_owners(%Project{id: project_id}) do
52+
query = from u in User,
53+
join: pu in ProjectUser, on: u.id == pu.user_id,
54+
where: pu.project_id == ^project_id,
55+
where: pu.role == "owner"
56+
57+
query |> Repo.all()
58+
end
59+
end

lib/code_corps_web/controllers/project_user_controller.ex

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ defmodule CodeCorpsWeb.ProjectUserController do
77
action_fallback CodeCorpsWeb.FallbackController
88
plug CodeCorpsWeb.Plug.DataToAttributes
99
plug CodeCorpsWeb.Plug.IdsToIntegers
10-
10+
1111
@preloads [:project, :user]
1212

1313
@spec index(Conn.t, map) :: Conn.t
@@ -28,7 +28,8 @@ defmodule CodeCorpsWeb.ProjectUserController do
2828
def create(%Conn{} = conn, %{} = params) do
2929
with %User{} = current_user <- conn |> Guardian.Plug.current_resource,
3030
{:ok, :authorized} <- current_user |> Policy.authorize(:create, %ProjectUser{}, params),
31-
{:ok, %ProjectUser{} = project_user} <- %ProjectUser{} |> ProjectUser.create_changeset(params) |> Repo.insert
31+
{:ok, %ProjectUser{} = project_user} <- %ProjectUser{} |> ProjectUser.create_changeset(params) |> Repo.insert,
32+
_ <- maybe_send_create_email(project_user)
3233
do
3334
conn |> put_status(:created) |> render("show.json-api", data: project_user)
3435
end
@@ -40,7 +41,7 @@ defmodule CodeCorpsWeb.ProjectUserController do
4041
%User{} = current_user <- conn |> Guardian.Plug.current_resource,
4142
{:ok, :authorized} <- current_user |> Policy.authorize(:update, project_user, params),
4243
{:ok, %ProjectUser{} = updated_project_user} <- project_user |> ProjectUser.update_changeset(params) |> Repo.update,
43-
_ <- maybe_send_email(updated_project_user, project_user)
44+
_ <- maybe_send_update_email(updated_project_user, project_user)
4445
do
4546
conn |> render("show.json-api", data: project_user)
4647
end
@@ -57,18 +58,34 @@ defmodule CodeCorpsWeb.ProjectUserController do
5758
end
5859
end
5960

60-
defp maybe_send_email(%ProjectUser{role: updated_role} = project_user, %ProjectUser{role: previous_role}) do
61+
@spec maybe_send_create_email(ProjectUser.t) :: Bamboo.Email.t | nil
62+
defp maybe_send_create_email(%ProjectUser{role: "pending"} = project_user) do
63+
send_request_email(project_user)
64+
end
65+
defp maybe_send_create_email(_), do: nil
66+
67+
@spec send_request_email(ProjectUser.t) :: Bamboo.Email.t
68+
defp send_request_email(project_user) do
69+
project_user
70+
|> Repo.preload(@preloads)
71+
|> Emails.ProjectUserRequestEmail.create()
72+
|> Mailer.deliver_now()
73+
end
74+
75+
@spec maybe_send_update_email(ProjectUser.t, ProjectUser.t) :: Bamboo.Email.t | nil
76+
defp maybe_send_update_email(%ProjectUser{role: updated_role} = project_user, %ProjectUser{role: previous_role}) do
6177
case {updated_role, previous_role} do
62-
{"contributor", "pending"} ->
78+
{"contributor", "pending"} ->
6379
send_acceptance_email(project_user)
6480
_ -> nil
6581
end
6682
end
67-
83+
84+
@spec send_acceptance_email(ProjectUser.t) :: Bamboo.Email.t
6885
defp send_acceptance_email(project_user) do
6986
project_user
7087
|> Repo.preload(@preloads)
7188
|> Emails.ProjectUserAcceptanceEmail.create()
7289
|> Mailer.deliver_now()
7390
end
74-
end
91+
end

test/lib/code_corps/emails/project_user_acceptance_email_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ defmodule CodeCorps.Emails.ProjectUserAcceptanceEmailTest do
44

55
alias CodeCorps.Emails.ProjectUserAcceptanceEmail
66

7-
test "receipt email works" do
7+
test "acceptance email works" do
88
%{project: project, user: user} = project_user = insert(:project_user)
99

1010
email = ProjectUserAcceptanceEmail.create(project_user)

0 commit comments

Comments
 (0)