send weekly email to users about new musicians

This commit is contained in:
Nuwan 2023-01-20 04:50:27 +05:30
parent fad3b73d67
commit f75d2c8c46
28 changed files with 282 additions and 74 deletions

View File

@ -2,7 +2,7 @@
const showSidePanelContent = () => {
cy.get('[data-testid=profileSidePanel] h4').should('have.text', 'Test User1');
cy.get('[data-testid=profileSidePanel] .modal-body p').within(() => {
cy.get('[data-testid=profileSidePanel] .modal-body p').first().within(() => {
cy.contains('Location: Denver, CO, US')
.and('contain', 'Skill Level: Professional')
.and('contain', 'Joined JamKazam: 08-26-2021')
@ -11,7 +11,7 @@ const showSidePanelContent = () => {
cy.get('.latency-badge').contains('UNKNOWN');
});
cy.get('[data-testid=profileSidePanel] .modal-body').within(() => {
cy.get('[data-testid=profileSidePanel] .modal-body').first().within(() => {
cy.get('[data-testid=biography]').contains('Biography of Test User1');
//instruments
@ -139,9 +139,10 @@ describe('Friends page with data', () => {
it('click profile name', () => {
//open side panel by clicking name
cy.get('[data-testid=peopleListTable]').within(() => {
cy.contains('Test User1').click();
});
cy.get('[data-testid=peopleListTable]').find('.person-link').first().within(() => {
cy.contains("Test User1").click()
})
//cy.get('[data-testid=peopleListTable]').find('.person-link').first().click()
showSidePanelContent();
closeSidePanel();
});
@ -260,12 +261,13 @@ describe('Friends page with data', () => {
//it.skip('click message button', () => {});
it('paginate', () => {
it.skip('paginate', () => {
cy.get('[data-testid=peopleSwiper] .swiper-button-prev').should('have.class', 'swiper-button-disabled');
for (let i = 0; i < 19; i++) {
cy.get('[data-testid=peopleSwiper] .swiper-button-next').click();
cy.wait(500);
}
cy.wait(500);
cy.get('[data-testid=peopleSwiper] .swiper-button-next').should('have.class', 'swiper-button-disabled');
});
@ -341,11 +343,11 @@ describe('Friends page with data', () => {
cy.contains('Send a message').should('exist');
});
it('is disabled for non friends', () => {
it('is not disabled for non friends', () => {
cy.get('[data-testid=peopleListTable] > tbody tr')
.eq(1)
.find('[data-testid=message]')
.should('be.disabled');
.should('not.be.disabled');
//cy.contains('You can message this user once you are friends').should('exist')
});

View File

@ -26,6 +26,7 @@ import JKPrivacy from '../page/JKPrivacy';
import JKPeopleFilter from '../page/JKPeopleFilter';
import JKNotifications from '../page/JKNotifications';
import JKMessageModal from '../profile/JKMessageModal';
import JKUnsubscribe from '../page/JKUnsubscribe';
import JKMusicSessions from '../page/JKMusicSessions';
import JKNewMusicSession from '../page/JKNewMusicSession';
@ -177,6 +178,7 @@ function JKDashboardMain() {
<Route path="/" exact component={HomePage} />
<Route path="/privacy" component={JKPrivacy} />
<Route path="/help" component={JKHelp} />
<Route path="/unsubscribe" exact component={JKUnsubscribe} />
<PrivateRoute path="/friends" component={JKPeopleFilter} />
<PrivateRoute path="/sessions/new" component={JKNewMusicSession} />
<PrivateRoute path="/sessions" component={JKMusicSessions} />

View File

@ -22,7 +22,6 @@ const JKPeople = ({ className, onPageChange }) => {
useEffect(() => {
try {
console.log("DEBUG======", page, hasNext);
onPageChange(page, hasNext)
} catch (error) {
console.log('Error fetching people', error);

View File

@ -27,8 +27,6 @@ const JKPeopleList = ({ people, goNextPage, hasNext, isLoading }) => {
</tbody>
</Table>
{hasNext && (
<Button color="primary" outline={true} onClick={() => goNextPage()} disabled={isLoading} data-testid="paginate-next-page">
{isLoading ? <span>Loading...</span> : <span>Load More</span>}

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Row, Col } from 'reactstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@ -8,6 +8,7 @@ import { fetchPerson } from '../../store/features/peopleSlice';
import { useDispatch, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import { useResponsive } from '@farfetch/react-context-responsive';
import { useBrowserQuery } from '../../context/BrowserQuery';
import JKProfileSidePanel from '../profile/JKProfileSidePanel';
import JKProfileAvatar from '../profile/JKProfileAvatar';
@ -28,22 +29,36 @@ const JKPerson = props => {
const { greaterThan } = useResponsive()
const toggleMoreDetails = async e => {
if(e)
e.preventDefault();
try {
await dispatch(fetchPerson({ userId: id })).unwrap();
} catch (error) {
console.log(error);
}
setShowSidePanel(prev => !prev);
};
const queryString = useBrowserQuery();
useEffect(() => {
const openWin = queryString.get('open');
const userId = queryString.get('id')
//showing user more details if directly reqested to do so
//by query string params (coming from weekly new user match email link)
if(openWin && userId && userId === id){
if(openWin === 'details' || openWin === 'connect'){
toggleMoreDetails()
}
}
}, [])
return (
<>
{greaterThan.sm ? (
<tr className="align-middle" key={`people-list-item-${id}`}>
<td className="text-nowrap">
<a href="/#" onClick={toggleMoreDetails} className="d-flex align-items-center mb-1 fs-0">
<a href="/#" onClick={toggleMoreDetails} className="d-flex align-items-center mb-1 fs-0 person-link">
<div className="avatar avatar-xl">
<JKProfileAvatar url={photo_url} />
</div>

View File

@ -0,0 +1,20 @@
import React from 'react';
import { Card, CardBody } from 'reactstrap';
import FalconCardHeader from '../common/FalconCardHeader';
import { useTranslation } from "react-i18next";
function JKUnsubscribe() {
const {t} = useTranslation()
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>
)
}
export default JKUnsubscribe

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { addFriend as connect, removeFriend as disconnect } from '../../helpers/rest';
import { toast } from 'react-toastify';
import { Modal, ModalBody, ModalHeader, ModalFooter, Button } from 'reactstrap';
import { useBrowserQuery } from '../../context/BrowserQuery';
const JKConnectButton = props => {
const { user, currentUser, addContent, removeContent, cssClasses } = props;
@ -15,6 +16,21 @@ const JKConnectButton = props => {
setPendingFriendRequest(user.pending_friend_request);
}, [user]);
const queryString = useBrowserQuery();
useEffect(() => {
const openWin = queryString.get('open');
const userId = queryString.get('id')
//sending friend request if directly reqested to do so
//by query string params (coming from weekly new user match email link)
if(openWin && userId && userId === user.id && !user.isFriend && !user.pending_friend_request){
if(openWin === 'connect'){
addFriend();
}
}
}, [])
const addFriend = () => {
setShowConfirmModal(!showConfirmModal);
setPendingFriendRequest(true);

View File

@ -1,21 +1,38 @@
import React, { useState, useEffect } from 'react';
import { Button, Tooltip } from "reactstrap";
import JKMessageModal from './JKMessageModal';
import { useBrowserQuery } from '../../context/BrowserQuery';
const JKMessageButton = props => {
const { currentUser, user, cssClasses, children, size, color, outline } = props;
const [showModal, setShowModal] = useState(false);
const [isFriend, setIsFriend] = useState(false);
//const [isFriend, setIsFriend] = useState(false);
const [pendingFriendRequest, setPendingFriendRequest] = useState(false);
const [tooltipOpen, setTooltipOpen] = useState(false);
const toggleTooltip = () => setTooltipOpen(!tooltipOpen);
useEffect(() => {
setIsFriend(user.is_friend);
//setIsFriend(user.is_friend);
setPendingFriendRequest(user.pending_friend_request);
}, [user]);
const queryString = useBrowserQuery();
useEffect(() => {
const openWin = queryString.get('open');
const userId = queryString.get('id')
//openning chat window if directly reqested to do so
//by query string params (coming from weekly new user match email link)
if(openWin && userId && userId === user.id){
if(openWin === 'message'){
setShowModal(!showModal)
}
}
}, [])
return (
<>
<JKMessageModal show={showModal} setShow={setShowModal} user={user} currentUser={currentUser} />
@ -27,7 +44,7 @@ const JKMessageButton = props => {
outline={outline}
className={cssClasses}
data-testid="message"
disabled={!isFriend}
//disabled={!isFriend}
>
{children}
</Button>
@ -37,9 +54,10 @@ const JKMessageButton = props => {
target={"text-message-user-" + user.id}
toggle={toggleTooltip}
>
{
{/* {
isFriend ? 'Send a message' : 'You can message this user once you are friends'
}
} */}
Send a message
</Tooltip>
</>
);

View File

@ -0,0 +1,21 @@
import React from 'react'
import { useLocation } from "react-router-dom";
const BrowserQueryContext = React.createContext(null)
export const BrowserQueryProvider = ({children}) => {
function useQuery() {
return new URLSearchParams(useLocation().search);
}
const queryObj = useQuery();
return(
<BrowserQueryContext.Provider value={ queryObj }>
{ children }
</BrowserQueryContext.Provider>
)
}
export const useBrowserQuery = () => React.useContext(BrowserQueryContext)

View File

@ -6,12 +6,14 @@ import homeTranslationsEN from './locales/en/home.json'
import peopleTranslationsEN from './locales/en/people.json'
import authTranslationsEN from './locales/en/auth.json'
import sessTranslationsEN from './locales/en/sessions.json'
import unsubscribeTranslationsEN from './locales/en/unsubscribe.json'
import commonTranslationsES from './locales/es/common.json'
import homeTranslationsES from './locales/es/home.json'
import peopleTranslationsES from './locales/es/people.json'
import authTranslationsES from './locales/es/auth.json'
import sessTranslationsES from './locales/es/sessions.json'
import unsubscribeTranslationsES from './locales/es/unsubscribe.json'
i18n.use(initReactI18next).init({
fallbackLng: 'en',
@ -24,6 +26,7 @@ i18n.use(initReactI18next).init({
people: peopleTranslationsEN,
auth: authTranslationsEN,
sessions: sessTranslationsEN,
unsubscribe: unsubscribeTranslationsEN,
},
es: {
//translations: require('./locales/es/translations.json')
@ -32,6 +35,7 @@ i18n.use(initReactI18next).init({
people: peopleTranslationsES,
auth: authTranslationsES,
sessions: sessTranslationsES,
unsubscribe: unsubscribeTranslationsES,
}
},
//ns: ['translations'],

View File

@ -0,0 +1,3 @@
{
"page_title": "Unsubscribe"
}

View File

@ -0,0 +1,3 @@
{
"page_title": "Unsubscribe"
}

View File

@ -1,8 +1,9 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, createContext } from 'react';
import PropTypes from 'prop-types';
import DashboardMain from '../components/dashboard/JKDashboardMain';
import UserAuth from '../context/UserAuth';
import { BrowserQueryProvider } from '../context/BrowserQuery';
const DashboardLayout = ({ location }) => {
useEffect(() => {
@ -11,7 +12,9 @@ const DashboardLayout = ({ location }) => {
return (
<UserAuth path={location.pathname}>
<BrowserQueryProvider>
<DashboardMain />
</BrowserQueryProvider>
</UserAuth>
);
};

View File

@ -3,4 +3,30 @@ module MailerHelper
@vars = Hash.new unless @vars
@vars[arg1] = arg2[0]
end
def latency_info(latency_data)
latency_scores = {
good: { label: 'GOOD', min: 0, max: 40 },
fair: { label: 'FAIR', min: 40, max: 60 },
high: { label: 'HIGH', min: 60, max: 10000000 },
me: { label: 'ME', min: -1, max: -1 },
unknown: { label: 'UNKNOWN', min: -2, max: -2 }
}
total_latency = latency_data[:ars_internet_latency].round + latency_data[:audio_latency].round;
lbl = if (total_latency >= latency_scores[:good][:min] && total_latency <= latency_scores[:good][:max])
latency_scores[:good][:label]
elsif (total_latency > latency_scores[:fair][:min] && total_latency <= latency_scores[:fair][:max])
latency_scores[:fair][:label]
elsif (total_latency > latency_scores[:fair][:min] && total_latency <= latency_scores[:fair][:max])
latency_scores[:fair][:label]
elsif (total_latency > latency_scores[:high][:min])
latency_scores[:high][:label]
else
latency_scores[:unknown][:label]
end
lbl
end
end

View File

@ -10,6 +10,8 @@ module JamRuby
include SendGrid
include MailerHelper
helper MailerHelper
layout "user_mailer"
DEFAULT_SENDER = "JamKazam <noreply@jamkazam.com>"
@ -401,6 +403,11 @@ module JamRuby
def new_musicians_match(user, musicians_data)
@user, @musicians_data = user, musicians_data
@instrument_proficiencies = {
'1': 'Beginner',
'2': 'Intermediate',
'3': 'Expert'
}
sendgrid_recipients([user.email])
sendgrid_substitute('@USERID', [user.id])
sendgrid_unique_args :type => "new_musicians_match"

View File

@ -6,6 +6,28 @@
background-color: #fff;
font-size: 1.2rem;
}
.logo{
display: flex;
justify-content: center;
margin-bottom: 1em;
}
.search-btn{
display: flex;
justify-content: center;
}
.search-btn a{
color: #fff;
background-color: #2c7be5;
border-color: #2c7be5;
border: 1px solid transparent;
padding: 0.3125rem 1rem;
line-height: 2.5;
font-size: 1em;
border-radius: 0.25rem;
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}
.row {
display: flex;
@ -32,13 +54,21 @@
flex-grow: 1;
}
</style>
<section class="container">
<div class="logo">
<img src="<%= image_url("JK_Logo_blue-2021.png", host: APP_CONFIG.action_mailer.assets_host ) -%>" alt="JamKazam Logo" />
</div>
<p>
Hi <%= @user.first_name -%>,
</p>
<p>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.</p>
<% @musicians_data.each do | data | -%>
<p>
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.
</p>
<%
@musicians_data.each do | data | -%>
<%
musicians = data[:musicians]
latencies = data[:latencies]
@ -47,26 +77,35 @@
-%>
<div class="row">
<div class="photo">
photo
<%= image_tag musician.photo_url.blank?? "avatar.png" : musician.photo_url, height: '32', width: '32', host: APP_CONFIG.action_mailer.assets_host -%>
</div>
<div class="details">
<div><strong><%= musician.first_name %> <%= musician.last_name %></strong></div>
<div>Latency To You: <%= latency[:ars_total_latency] %></div>
<div>Last Active On: </div>
<div>Latency To You: <%= latency_info(latency) %></div>
<div>Last Active On: <%= musician.last_active_timestamp %> ago</div>
</div>
<div class="instruments">
<% musician.instruments.each do |instrument| -%>
<% musician.musician_instruments.each do |mi| -%>
<div>
<%= instrument.description %><%= instrument.inspect %>
<%= mi.description %>:&nbsp;<%= @instrument_proficiencies[mi.proficiency_level.to_s.to_sym] %>
</div>
<% end -%>
</div>
<div class="links">
<div><a href="<%= APP_CONFIG.spa_origin %>">View Profile</a></div>
<div><a href="<%= APP_CONFIG.spa_origin %>">Send Message</a></div>
<div><a href="<%= APP_CONFIG.spa_origin %>">Send Friend Request</a></div>
<div><a href="<%= APP_CONFIG.spa_origin -%>/friends?id=<%= musician.id %>&open=details" target="_blank">View Profile</a></div>
<div><a href="<%= APP_CONFIG.spa_origin -%>/friends?id=<%= musician.id %>&open=message" target="_blank">Send Message</a></div>
<div><a href="<%= APP_CONFIG.spa_origin -%>/friends?id=<%= musician.id %>&open=connect" target="_blank">Send Friend Request</a></div>
</div>
</div>
<% end -%>
<% end -%>
<br />
<p>
To find great musical matches across the entire JamKazam commiunity and make new connections, use the button below to access our musician search feature.
This let you filter JamKazammers by latency, instruments, skill level, genre interests, last active day and more.
</p>
<br />
<div class="search-btn">
<a class="button" href="<%= APP_CONFIG.spa_origin -%>/friends" target="_blank">Search JamKazam Musicians</a>
</div>
</section>

View File

@ -13,8 +13,11 @@
margin-bottom:0px;
line-height:140%;
}
a {
color: lightblue !important;
footer{
text-align: center;
padding-top: 1em;
color: #5e6e82;
}
</style>
@ -23,4 +26,13 @@
<body bgcolor="#eee" >
<%= yield -%>
<body>
<footer>
<p>
Copyright &copy; <%= Time.now.year %> JamKazam, Inc. All rights reserved.
</p>
<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>
</footer>
</html>

View File

@ -3,7 +3,7 @@ module JamRuby
PER_PAGE = 20
JOINED_WITHIN_DAYS = "7"
ACTIVE_WITHIN_DAYS = "7"
ACTIVE_WITHIN_DAYS = "30"
PRIORITY_RECIPIENTS = %w(seth@jamkazam.com david@jamkazam.com peter@jamkazam.com nuwan@jamkazam.com)
@ -26,6 +26,7 @@ module JamRuby
limit: PER_PAGE
}
begin
email_sending = UserMatchEmailSending.most_recent
@ -33,37 +34,39 @@ module JamRuby
email_sending = UserMatchEmailSending.create
end
AdminMailer.ugly({to: APP_CONFIG.user_match_monitoring_email,
subject:"Weekly user match email sending started.",
body: "#{email_sending.sent_user_ids.any?? "Weekly email sending 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." : "Weekly email sending was started at #{email_sending.created_at}" }"}).deliver_now
priority_recipients = User.where(email: PRIORITY_RECIPIENTS).where("users.subscribe_email = ? OR users.subscribe_email_for_user_match = ?", true, true)
user_recipients = User.where("users.subscribe_email = ? OR users.subscribe_email_for_user_match = ?", true, true).where.not(id: email_sending.sent_user_ids).order("updated_at DESC, last_jam_updated_at DESC")
recipients = (priority_recipients + user_recipients).uniq
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
debugger
recipients.each do |user|
ip = '127.0.0.1' #TODO: get this from user data?
ip_address = user.last_jam_addr.blank?? '127.0.0.1' : IPAddr.new(user.last_jam_addr, Socket::AF_INET).to_s
matched_musician_data = []
nextOffset = 0
while !nextOffset.nil? && nextOffset >= 0 do
params.merge!({ offset: nextOffset })
results, latency_data, nextOffset = JamRuby::MusicianFilter.filter(user, ip, params)
results, latency_data, nextOffset = JamRuby::MusicianFilter.filter(user, ip_address, params)
matched_musician_data << [{ musicians: results, latencies: latency_data }] if results && results.size > 0
end
#debugger
if matched_musician_data.size > 0
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
@ -74,7 +77,7 @@ module JamRuby
AdminMailer.ugly({
to: APP_CONFIG.user_match_monitoring_email,
subject:"Weekly user match email sending completed.",
body: "Weekly email sending job was completed at #{Time.now}. It was sent to #{email_sending.sent_user_ids.size} user(s)"
body: "Weekly email sending job was completed at #{Time.now}. It was sent to #{email_sending.sent_user_ids.size} user(s)."
}).deliver_now
rescue => exception

View File

@ -2936,10 +2936,17 @@ module JamRuby
def recurly_link_to_account
"https://#{APP_CONFIG.recurly_subdomain}.recurly.com/accounts/#{id}"
end
def recurly_link_to_subscription
"https://#{APP_CONFIG.recurly_subdomain}.recurly.com/subscriptions/#{recurly_subscription_id}"
end
def last_active_timestamp
if updated_at || last_jam_updated_at
[updated_at, last_jam_updated_at].compact.max.to_i
end
end
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64

View File

@ -35,9 +35,9 @@ describe EmailNewMusicianMatch do
JamRuby::EmailNewMusicianMatch.send_new_musicians
end
it "does not sent to whom have not been opted to receive emails" do
ActionMailer::Base.deliveries.map{|d| d['to'].to_s }.include?("david@example.com").should be_falsey
fit "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
it "delivers the new musicians notification email" do
@ -46,9 +46,10 @@ describe EmailNewMusicianMatch do
JamRuby::EmailNewMusicianMatch.send_new_musicians
end
fit "delivers to priority recipients first" do
it "delivers to priority recipients first" do
JamRuby::EmailNewMusicianMatch.send_new_musicians
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
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
end
describe "halfway done job" do

View File

@ -526,8 +526,8 @@ describe "RenderMailers" do
describe "New Musician Match email" do
let(:user) { FactoryGirl.create(:user) }
let(:user1) { FactoryGirl.create(:user) }
let(:user2) { FactoryGirl.create(:user) }
let(:user1) { FactoryGirl.create(:user, first_name: 'David', last_name: 'Macmillan', updated_at: 2.day.ago.to_i) }
let(:user2) { FactoryGirl.create(:user, first_name: 'Tom', last_name: 'Cluff', last_jam_updated_at: 1.days.ago.to_i) }
let(:matched_musician_data){
[
{
@ -541,6 +541,7 @@ describe "RenderMailers" do
}
before(:each) do
User.delete_all
ActionMailer::Base.deliveries.clear
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -25,7 +25,7 @@ node :is_blank_filter do |foo|
end
child(:results => :musicians) {
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score, :is_friend, :is_following, :pending_friend_request
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score, :is_friend, :is_following, :pending_friend_request, :last_active_timestamp
# node :is_friend do |musician|
# @search.is_friend?(musician)
@ -82,11 +82,11 @@ child(:results => :musicians) {
end if @latency_data
end
node :last_active_timestamp do |musician|
if musician.updated_at || musician.last_jam_updated_at
[musician.updated_at, musician.last_jam_updated_at].compact.max.to_i
end
end
# node :last_active_timestamp do |musician|
# if musician.updated_at || musician.last_jam_updated_at
# [musician.updated_at, musician.last_jam_updated_at].compact.max.to_i
# end
# end
child :genres => :genres do
attributes :genre_id, :description

View File

@ -24,7 +24,7 @@ if @search.is_a?(BaseSearch)
end
child(:results => :musicians) {
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score, :last_active_timestamp
node :is_friend do |musician|
@search.is_friend?(musician)
@ -72,11 +72,11 @@ if @search.is_a?(BaseSearch)
end if @latency_data
end
node :last_active_timestamp do |musician|
if musician.updated_at || musician.last_jam_updated_at
[musician.updated_at, musician.last_jam_updated_at].compact.max.to_i
end
end
# node :last_active_timestamp do |musician|
# if musician.updated_at || musician.last_jam_updated_at
# [musician.updated_at, musician.last_jam_updated_at].compact.max.to_i
# end
# end
child :genres => :genres do
attributes :genre_id, :description

View File

@ -1,7 +1,7 @@
object @profile
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :location, :online, :photo_url, :musician, :gender, :birth_date, :internet_service_provider, :friend_count, :liker_count, :like_count, :follower_count, :following_count, :recording_count, :session_count, :biography, :favorite_count, :audio_latency, :upcoming_session_count, :age, :website, :skill_level, :concert_count, :studio_session_count, :virtual_band, :virtual_band_commitment, :traditional_band, :traditional_band_commitment, :traditional_band_touring, :paid_sessions, :paid_sessions_hourly_rate,
:paid_sessions_daily_rate, :free_sessions, :cowriting, :cowriting_purpose, :subscribe_email, :is_a_teacher, :is_a_student
:paid_sessions_daily_rate, :free_sessions, :cowriting, :cowriting_purpose, :subscribe_email, :is_a_teacher, :is_a_student, :last_active_timestamp
child :online_presences => :online_presences do
attributes :id, :service_type, :username
@ -32,11 +32,11 @@ child :musician_instruments => :instruments do
attributes :description, :proficiency_level, :priority, :instrument_id
end
node :last_active_timestamp do |user|
if user.updated_at || user.last_jam_updated_at
[user.updated_at, user.last_jam_updated_at].compact.max.to_i
end
end
# node :last_active_timestamp do |user|
# if user.updated_at || user.last_jam_updated_at
# [user.updated_at, user.last_jam_updated_at].compact.max.to_i
# end
# end
node :created_at_timestamp do |user|
user.created_at.to_i

View File

@ -515,7 +515,7 @@ if defined?(Bundler)
config.latency_data_host = "http://localhost:4001"
config.latency_data_host_auth_code = "c2VydmVyOnBhc3N3b3Jk"
config.manual_override_installer_ends_with = "JamKazam-1.0.3776.dmg"
config.spa_origin = "http://beta.jamkazam.local:3000"
config.spa_origin = "http://beta.jamkazam.local:4000"
config.user_match_monitoring_email = "user_match_monitoring_email@jamkazam.com"
end
end

View File

@ -120,4 +120,7 @@ SampleApp::Application.configure do
config.spa_origin = "http://beta.jamkazam.local:4000"
config.session_cookie_domain = ".jamkazam.local"
config.action_controller.asset_host = 'http://localhost:3000'
config.action_mailer.asset_host = config.action_controller.asset_host
end

View File

@ -65,6 +65,11 @@ NewMusicianEmailer:
class: "JamRuby::NewMusicianEmailer"
description: "Sends weekly emails of new users with good latency"
NewMusicianMatchEmailer:
cron: "0 2 * * 6"
class: "JamRuby::NewMusicianMatchEmailer"
description: "Sends weekly emails of new users with good latency - (User latency data from neo4j)"
MusicSessionScheduler:
cron: "0 * * * *"
class: "JamRuby::MusicSessionScheduler"