-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add unsubscribe #152
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
base: main
Are you sure you want to change the base?
Changes from all commits
f993036
352e396
9211d0b
3faba26
abc1074
c819789
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -308,7 +308,7 @@ defmodule Admin.Notifications do | |
|
|
||
| @type audience :: %{name: String.t(), email: String.t(), lang: String.t()} | ||
| @spec get_target_audience(Scope.t(), String.t(), Keyword.t()) :: | ||
| {:ok, [audience]} | {:error, String.t()} | ||
| {:ok, [audience], %{total: integer, excluded: integer}} | {:error, String.t()} | ||
| @doc """ | ||
| Get the target audience for a notification. | ||
|
|
||
|
|
@@ -331,34 +331,51 @@ defmodule Admin.Notifications do | |
| def get_target_audience(scope, target_audience, opts \\ []) | ||
|
|
||
| def get_target_audience(%Scope{} = _scope, "active", opts) do | ||
| audience = | ||
| {audience, meta} = | ||
| Accounts.get_active_members() | ||
| |> Enum.map(&%{name: &1.name, email: &1.email, lang: &1.lang}) | ||
| |> Enum.map( | ||
| &%{ | ||
| id: &1.id, | ||
| name: &1.name, | ||
| email: &1.email, | ||
| lang: &1.lang, | ||
| marketing_emails_subscribed_at: &1.marketing_emails_subscribed_at | ||
| } | ||
| ) | ||
| |> filter_audience_with_options(opts) | ||
|
|
||
| {:ok, audience} | ||
| {:ok, audience, meta} | ||
| end | ||
|
|
||
| def get_target_audience(%Scope{} = _scope, "french", opts) do | ||
| audience = | ||
| {audience, meta} = | ||
| Accounts.get_members_by_language("fr") | ||
| |> Enum.map(&%{name: &1.name, email: &1.email, lang: &1.lang}) | ||
| |> Enum.map( | ||
| &%{ | ||
| id: &1.id, | ||
| name: &1.name, | ||
| email: &1.email, | ||
| lang: &1.lang, | ||
| marketing_emails_subscribed_at: &1.marketing_emails_subscribed_at | ||
| } | ||
| ) | ||
| |> filter_audience_with_options(opts) | ||
|
|
||
| {:ok, audience} | ||
| {:ok, audience, meta} | ||
| end | ||
|
|
||
| def get_target_audience(%Scope{} = _scope, "graasp_team", opts) do | ||
| audience = | ||
| {audience, meta} = | ||
| Accounts.list_users() | ||
| |> Enum.map(&%{name: &1.name, email: &1.email, lang: &1.language}) | ||
| |> Enum.map(&%{id: &1.id, name: &1.name, email: &1.email, lang: &1.language}) | ||
| |> filter_audience_with_options(opts) | ||
|
|
||
| {:ok, audience} | ||
| {:ok, audience, meta} | ||
| end | ||
|
|
||
| # support legacy audience, this is what the pervious audience is converted to. | ||
| def get_target_audience(%Scope{} = _scope, "custom", _opts), do: {:ok, []} | ||
| def get_target_audience(%Scope{} = _scope, "custom", _opts), | ||
| do: {:ok, [], %{total: 0, excluded: 0}} | ||
|
|
||
| def get_target_audience(%Scope{} = _scope, target_audience, _opts) do | ||
| Logger.error("Invalid target audience: #{target_audience}") | ||
|
|
@@ -367,7 +384,15 @@ defmodule Admin.Notifications do | |
|
|
||
| defp filter_audience_with_options(audience, opts) do | ||
| only_langs = Keyword.get(opts, :only_langs, Admin.Languages.all_values()) |> MapSet.new() | ||
| audience |> Enum.filter(fn user -> MapSet.member?(only_langs, user.lang) end) | ||
|
|
||
| filtered_audience = | ||
| audience | ||
| |> Enum.filter(fn user -> | ||
| MapSet.member?(only_langs, user.lang) and user.marketing_emails_subscribed_at != nil | ||
| end) | ||
|
|
||
| {filtered_audience, | ||
| %{total: length(audience), excluded: length(audience) - length(filtered_audience)}} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider to have a variable for |
||
| end | ||
|
|
||
| def create_pixel(%Scope{} = scope, %Admin.Notifications.Notification{} = notification) do | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| defmodule AdminWeb.AccountController do | ||
| use AdminWeb, :controller | ||
|
|
||
| alias Admin.Accounts | ||
|
|
||
| def marketing_emails_unsubscribe(conn, %{"account_id" => account_id}) do | ||
| account = Accounts.get_member!(account_id) | ||
| {:ok, account} = Accounts.member_marketing_emails(account, false) | ||
|
|
||
| conn | ||
| |> put_flash(:info, "Unsubscribed from marketing emails") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. translate? |
||
| |> render(:marketing_subscription, | ||
| page_title: "Unsubscribed from Marketing Emails", | ||
| account: account | ||
| ) | ||
| end | ||
|
|
||
| def marketing_emails_subscribe(conn, %{"account_id" => account_id}) do | ||
| account = Accounts.get_member!(account_id) | ||
| {:ok, account} = Accounts.member_marketing_emails(account, true) | ||
|
|
||
| conn | ||
| |> put_flash(:info, "Subscribed to marketing emails") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. translate? |
||
| |> render(:marketing_subscription, | ||
| page_title: "Subscribed to Marketing Emails", | ||
| account: account | ||
| ) | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| defmodule AdminWeb.AccountHTML do | ||
| use AdminWeb, :html | ||
|
|
||
| embed_templates "account_html/*" | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| <Layouts.simple flash={@flash} current_scope={@current_scope}> | ||
| <div class="flex flex-col items-center mx-auto max-w-screen-md p-8 gap-2 mt-8"> | ||
| <div class="prose"> | ||
| <h1>{@page_title}</h1> | ||
| <%= if is_nil(@account.marketing_emails_subscribed_at) do %> | ||
| <p> | ||
| <.icon name="hero-check-circle" class="size-6 text-success mr-2" />You have successfully unsubscribed from marketing emails. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we avoid the mention of marketing? Like using news or updates instead? |
||
| </p> | ||
| <p> | ||
| You can subscribe to marketing emails via your account settings or with the button below. | ||
| </p> | ||
| <% else %> | ||
| <p> | ||
| <.icon name="hero-check-circle" class="size-6 text-success mr-2" />You have successfully subscribed to marketing emails. | ||
| </p> | ||
| <% end %> | ||
| </div> | ||
|
|
||
| <.link class="btn btn-primary" href={~p"/accounts/#{@account.id}/marketing/subscribe"}> | ||
| Subscribe to Marketing Emails | ||
| </.link> | ||
| </div> | ||
| </Layouts.simple> | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -58,6 +58,7 @@ defmodule AdminWeb.EmailTemplates do | |||||
| attr :name, :string, required: true | ||||||
| attr :message, :string, required: true, doc: "The primary message of the email" | ||||||
| attr :pixel, :string, doc: "The tracking pixel" | ||||||
| attr :account, :string, doc: "The account (for emails targetting graasp members)" | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| attr :button_text, :string, doc: "The text of the button" | ||||||
| attr :button_url, :string, doc: "The URL of the button" | ||||||
| def call_to_action(assigns) | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about the name of this function, should it include a mention for "update"?