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', () => {
const fillFilterForm = () => {
//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 { Card, CardBody } from 'reactstrap';
import FalconCardHeader from '../common/FalconCardHeader';
import React, { useEffect, useState } from 'react';
import { Card, CardBody, CardText, CardTitle } from 'reactstrap';
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() {
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 (
<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>
</CardBody>
</Card>
<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>
</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;">
You are receiving this email because you created a JamKazam account with the email address <%= @user.email -%>
</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>
</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,
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|
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
#user.update_column(:user_match_email_sent_at, Time.now)
#email_sending.sent_user_ids.push(user.id)
#email_sending.save!
user.update_column(:user_match_email_sent_at, Time.now)
email_sending.sent_user_ids.push(user.id)
email_sending.save!
end
end

View File

@ -35,7 +35,7 @@ describe EmailNewMusicianMatch do
JamRuby::EmailNewMusicianMatch.send_new_musicians
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
ActionMailer::Base.deliveries.map{|d| d['to'].to_s }.include?("david@example.com").should be_falsey
end
@ -46,10 +46,9 @@ describe EmailNewMusicianMatch do
JamRuby::EmailNewMusicianMatch.send_new_musicians
end
it "delivers to priority recipients first" do
fit "delivers to priority recipients first" do
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
describe "halfway done job" do

View File

@ -12,11 +12,11 @@ describe UserMailer do
let(:user) { FactoryGirl.create(:user) }
before(:each) do
stub_const("APP_CONFIG", app_config)
#stub_const("APP_CONFIG", app_config)
UserMailer.deliveries.clear
end
describe "should send confirm email" do
describe "should send confirm email", focus: true do
let (:mail) { UserMailer.deliveries[0] }
let (:signup_confirmation_url) { "/confirm" }
@ -180,7 +180,16 @@ describe UserMailer do
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

View File

@ -445,6 +445,16 @@ JS
render text: 'You have been unsubscribed.'
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
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'
match '/unsubscribe/:user_token' => 'users#unsubscribe', via: [:get, :post]
match '/unsubscribe_user_match/:user_token' => 'users#unsubscribe_user_match', via: [:post]
# 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

View File

@ -28,6 +28,20 @@ describe UsersController, :type => :api do
user.subscribe_email.should eql false
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 "logged out" do