sending weekly email to users about new users joined in

This commit is contained in:
Nuwan 2023-01-24 09:53:04 +05:30
parent f75d2c8c46
commit 1e988931a4
14 changed files with 192 additions and 25 deletions

1
.ruby-version Normal file
View File

@ -0,0 +1 @@
2.4.1

View File

@ -448,6 +448,31 @@ describe('Friends page with data', () => {
}); });
}); });
describe('coming from email links', () => {
it.only("opens details sidebar", () => {
cy.visit('/friends?open=details&id=1');
showSidePanelContent();
});
it.only("opens chat window", () => {
cy.visit('/friends?open=message&id=1');
cy.get('[data-testid=textMessageModal]')
.should('be.visible')
cy.contains('Send Message to Test User1').should('exist');
});
it.only("sends friend request", () => {
cy.intercept('GET', /\S+\/profile\S+/, { fixture: 'person' });
cy.intercept('POST', /\S+\/friend_requests/, { statusCode: 201, body: { ok: true } });
cy.visit('/friends?open=connect&id=1');
cy.get('[data-testid=profileSidePanel]')
.find('[data-testid=connect]')
.should('be.disabled');
cy.contains('Success! Your friend request has been sent to Test User1.');
});
})
describe('filter', () => { describe('filter', () => {
const fillFilterForm = () => { const fillFilterForm = () => {
//cy.get('[data-testid=btnUpdateSearch]').click(); //cy.get('[data-testid=btnUpdateSearch]').click();
@ -582,4 +607,6 @@ describe('Friends page with data', () => {
}); });
}); });
}); });

View File

@ -0,0 +1,23 @@
/// <reference types="cypress" />
describe('Unsubscribe from email link', () => {
beforeEach(() =>{
cy.intercept('POST', /\S+\/unsubscribe_user_match\/\S+/, { statusCode: 200, body: { ok: true } });
})
it("redirect to home page if tok is not provided", () => {
cy.visit('/unsubscribe');
cy.location('pathname').should('eq', '/');
});
it.only("show unsubscribed message", () => {
cy.visit('/unsubscribe?tok=123');
cy.location('search')
.should('equal', '?tok=123')
.then((s) => new URLSearchParams(s))
.invoke('get', 'tok')
.should('equal', '123')
cy.contains("successfully unsubscribed")
});
})

View File

@ -1,19 +1,64 @@
import React from 'react'; import React, { useEffect, useState } from 'react';
import { Card, CardBody } from 'reactstrap'; import { Card, CardBody, CardText, CardTitle } from 'reactstrap';
import FalconCardHeader from '../common/FalconCardHeader';
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useBrowserQuery } from '../../context/BrowserQuery';
import { useHistory } from "react-router-dom";
const unsubscribeFromNewUsersWeeklyEmail = (token) => {
const baseUrl = process.env.REACT_APP_LEGACY_BASE_URL
return new Promise((resolve, reject) => {
fetch(`${baseUrl}/unsubscribe_user_match/${token}`,
{ method: 'POST' }
).then(response => {
if (response.ok) {
resolve(response);
} else {
reject(response)
}
})
})
}
function JKUnsubscribe() { function JKUnsubscribe() {
const {t} = useTranslation() const {t} = useTranslation()
const queryObj = useBrowserQuery();
const history = useHistory()
const [success, setSuccess] = useState(false)
useEffect(() => {
const token = queryObj.get('tok')
if(token){
unsubscribeFromNewUsersWeeklyEmail(token)
.then((resp) => {
if(resp.ok){
setSuccess(true)
}
})
.catch(error => console.error(error))
}else{
history.push('/')
}
}, [])
return ( return (
<Card>
<FalconCardHeader title={t('page_title', {ns: 'unsubscribe'})} titleClass="font-weight-semi-bold" />
<CardBody className="pt-0">
<p className="text-muted">Unsubscribe from weekly email</p>
<Card color={ success ? 'success' : 'light' } style={{ width: '25rem', margin: '2rem auto' }}>
<CardBody>
<CardTitle className="mb-2">Unsubscribe From Weekly Email</CardTitle>
<CardText>
{
success?
'You have successfully unsubscribed from weekly emails on newly joined musicians having low internet latency to you.' :
'Unsubscribing...'
}
</CardText>
</CardBody> </CardBody>
</Card> </Card>
) )
} }

View File

@ -1 +1,29 @@
EMAIL BODY HERE: <%#= @musicians_data.inspect -%> <% if !@user.anonymous? %>
Hi <%= @user.first_name %>,
<% end %>
The following musicians have joined JamKazam within the last week and have low internet latency to you that will support enjoyable sessions. If you'd like to make more musical connections, we encourage you to use the links below to send these new users a welcome message and perhaps arrange a session to play together.
<%
@musicians_data.each do | data | -%>
<%
musicians = data[:musicians]
latencies = data[:latencies]
musicians.each do |musician|
latency = latencies.find{|l| l[:user_id] == musician.id }
-%>
<%= musician.first_name %> <%= musician.last_name %>
Latency To You: <%= latency_info(latency) %>
Last Active On: <%= musician.last_active_timestamp %> ago
<% musician.musician_instruments.each do |mi| -%>
<%= mi.description %> <%= @instrument_proficiencies[mi.proficiency_level.to_s.to_sym] %>
<% end -%>
View Profile: <%= APP_CONFIG.spa_origin -%>/friends?id=<%= musician.id %>&open=details
Send Message: <%= APP_CONFIG.spa_origin -%>/friends?id=<%= musician.id %>&open=message
Send Friend Request: <%= APP_CONFIG.spa_origin -%>/friends?id=<%= musician.id %>&open=connect
<% end -%>
<% end -%>
To find great musical matches across the entire JamKazam commiunity and make new connections, use the link below to access our musician search feature. This let you filter JamKazammers by latency, instruments, skill level, genre interests, last active day and more.
Search JamKazam Musicians: <%= APP_CONFIG.spa_origin -%>/friends

View File

@ -33,6 +33,6 @@
<p style="text-decoration:none;"> <p style="text-decoration:none;">
You are receiving this email because you created a JamKazam account with the email address <%= @user.email -%> You are receiving this email because you created a JamKazam account with the email address <%= @user.email -%>
</p> </p>
<p><a href="<%= APP_CONFIG.spa_origin -%>/unsubscribe/<%= @user.unsubscribe_token %>">Unsubscribe from this weekly new musician notification</a></p> <p><a href="<%= APP_CONFIG.spa_origin -%>/unsubscribe?tok=<%= @user.unsubscribe_token %>">Unsubscribe from this weekly new musician notification</a></p>
</footer> </footer>
</html> </html>

View File

@ -0,0 +1,11 @@
<% if @batch_body %>
<%= Nokogiri::HTML(@batch_body).text %>
<% else %>
<%= yield %>
<% end %>
<% unless @user.nil? || @suppress_user_has_account_footer == true %>
This email was sent to you because you have an account at JamKazam / https://www.jamkazam.com. To unsubscribe: https://www.jamkazam.com/unsubscribe/<%=@user.unsubscribe_token%>.
<% end %>
Copyright <%= Time.now.year %> JamKazam, Inc. All rights reserved.

View File

@ -42,9 +42,8 @@ module JamRuby
AdminMailer.ugly({to: APP_CONFIG.user_match_monitoring_email, AdminMailer.ugly({to: APP_CONFIG.user_match_monitoring_email,
subject:"Weekly user match email sending job started.", subject:"Weekly user match email sending job started.",
body: "#{email_sending.sent_user_ids.any?? "This is resuming. It was originally started at #{email_sending.created_at} and has been sent to #{email_sending.sent_user_ids.size} user(s) so far." : "This job was started at #{email_sending.created_at}" }. It will send to total of #{ recipients.size } users."}).deliver_now body: "#{email_sending.sent_user_ids.any?? "This job is resuming. It was originally started at #{email_sending.created_at} and has been sent to #{email_sending.sent_user_ids.size} user(s) so far." : "This job was started at #{email_sending.created_at}" }. It will send to total of #{ recipients.size } users."}).deliver_now
debugger
recipients.each do |user| recipients.each do |user|
ip_address = user.last_jam_addr.blank?? '127.0.0.1' : IPAddr.new(user.last_jam_addr, Socket::AF_INET).to_s ip_address = user.last_jam_addr.blank?? '127.0.0.1' : IPAddr.new(user.last_jam_addr, Socket::AF_INET).to_s
@ -64,9 +63,9 @@ module JamRuby
UserMailer.new_musicians_match(user, matched_musician_data).deliver_now UserMailer.new_musicians_match(user, matched_musician_data).deliver_now
#user.update_column(:user_match_email_sent_at, Time.now) user.update_column(:user_match_email_sent_at, Time.now)
#email_sending.sent_user_ids.push(user.id) email_sending.sent_user_ids.push(user.id)
#email_sending.save! email_sending.save!
end end
end end

View File

@ -35,7 +35,7 @@ describe EmailNewMusicianMatch do
JamRuby::EmailNewMusicianMatch.send_new_musicians JamRuby::EmailNewMusicianMatch.send_new_musicians
end end
fit "does not sent to whom have not been opted to receive emails" do it "does not sent to whom have not been opted to receive emails" do
JamRuby::EmailNewMusicianMatch.send_new_musicians JamRuby::EmailNewMusicianMatch.send_new_musicians
ActionMailer::Base.deliveries.map{|d| d['to'].to_s }.include?("david@example.com").should be_falsey ActionMailer::Base.deliveries.map{|d| d['to'].to_s }.include?("david@example.com").should be_falsey
end end
@ -46,10 +46,9 @@ describe EmailNewMusicianMatch do
JamRuby::EmailNewMusicianMatch.send_new_musicians JamRuby::EmailNewMusicianMatch.send_new_musicians
end end
it "delivers to priority recipients first" do fit "delivers to priority recipients first" do
JamRuby::EmailNewMusicianMatch.send_new_musicians JamRuby::EmailNewMusicianMatch.send_new_musicians
raise ActionMailer::Base.deliveries.map{|d| d['to'].to_s }.inspect #.include?("seth@example.com").should be_truthy ActionMailer::Base.deliveries[1]['to'].to_s.should == "seth@jamkazam.com" #NOTE: the first email is sent to user_match_monitoring_email. The second email should be sent to the first priority user in the priority user list
#ActionMailer::Base.deliveries[1]['to'].to_s.should == "seth@jamkazam.com" #NOTE: the first email is sent to user_match_monitoring_email. The second email should be sent to the first priority user in the priority user list
end end
describe "halfway done job" do describe "halfway done job" do

View File

@ -12,11 +12,11 @@ describe UserMailer do
let(:user) { FactoryGirl.create(:user) } let(:user) { FactoryGirl.create(:user) }
before(:each) do before(:each) do
stub_const("APP_CONFIG", app_config) #stub_const("APP_CONFIG", app_config)
UserMailer.deliveries.clear UserMailer.deliveries.clear
end end
describe "should send confirm email" do describe "should send confirm email", focus: true do
let (:mail) { UserMailer.deliveries[0] } let (:mail) { UserMailer.deliveries[0] }
let (:signup_confirmation_url) { "/confirm" } let (:signup_confirmation_url) { "/confirm" }
@ -180,7 +180,16 @@ describe UserMailer do
end end
end end
describe "sends new musicians email" do
let(:mail) { UserMailer.deliveries[0] }
before(:each) do
UserMailer.new_musicians_match(user, []).deliver_now
end
it { UserMailer.deliveries.length.should == 1 }
it { mail['from'].to_s.should == UserMailer::DEFAULT_SENDER }
it { mail['to'].to_s.should == user.email }
it { mail.multipart?.should == true } # because we send plain + html
end
# describe "sends new musicians email" do # describe "sends new musicians email" do

View File

@ -445,6 +445,16 @@ JS
render text: 'You have been unsubscribed.' render text: 'You have been unsubscribed.'
end end
def unsubscribe_user_match
if params[:user_token].present? && @user = User.read_access_token(params[:user_token])
@user.subscribe_email_for_user_match = false
@user.save!
render json: { head: :ok }
else
render json: { status: :unprocessable_entity }
end
end
private private
def _render(action) def _render(action)

View File

@ -145,6 +145,7 @@ Rails.application.routes.draw do
get '/reset_password_complete' => 'users#reset_password_complete', :as => 'reset_password_complete' get '/reset_password_complete' => 'users#reset_password_complete', :as => 'reset_password_complete'
match '/unsubscribe/:user_token' => 'users#unsubscribe', via: [:get, :post] match '/unsubscribe/:user_token' => 'users#unsubscribe', via: [:get, :post]
match '/unsubscribe_user_match/:user_token' => 'users#unsubscribe_user_match', via: [:post]
# email update # email update
get '/confirm_email' => 'users#finalize_update_email', :as => 'confirm_email' # NOTE: if you change this, you break outstanding email changes because links in user inboxes are broken get '/confirm_email' => 'users#finalize_update_email', :as => 'confirm_email' # NOTE: if you change this, you break outstanding email changes because links in user inboxes are broken

View File

@ -28,6 +28,20 @@ describe UsersController, :type => :api do
user.subscribe_email.should eql false user.subscribe_email.should eql false
end end
fit "unsubscribe_user_match" do
user.subscribe_email_for_user_match.should eql false #default value is false
user.subscribe_email_for_user_match = true #we make it true here for this test
user.save!
get '/unsubscribe_user_match/' + user.unsubscribe_token
expect(last_response).to have_http_status(200)
user.reload
user.subscribe_email_for_user_match.should eql false
end
describe "track_origin" do describe "track_origin" do
describe "logged out" do describe "logged out" do