Update signups aggressively as they occur (realtime), and fix some affiliate and jamtrack flows
This commit is contained in:
parent
39dfbadbd8
commit
aa9555aa1e
|
|
@ -37,3 +37,4 @@ cd jam-ui
|
|||
npm run start
|
||||
|
||||
This will open it in a borwser window at http://beta.jamkazam.local:3000. Of course for it to work you also need Rails (web) app and websocket app (websocket-gateway) running.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@ output
|
|||
node_modules
|
||||
public
|
||||
jam_track_tracks_for_jam_ui*
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
if [ -n "$1" ]; then
|
||||
SAVE_TO="$1"
|
||||
else
|
||||
SAVE_TO=`pwd`
|
||||
SAVE_TO=/tmp
|
||||
fi
|
||||
|
||||
echo "Saving to $SAVE_TO"
|
||||
|
|
@ -16,9 +16,10 @@ psql jam -c "COPY( select id, original_artist, name , original_artist_slug, name
|
|||
# dump all artists
|
||||
psql jam -c "COPY( select original_artist, original_artist_slug, ('https://www.jamkazam.com/backing-tracks/' || original_artist_slug ) as \"URL\" FROM jam_tracks group by original_artist, original_artist_slug) TO '$SAVE_TO/jam_tracks_for_jam_ui_artists.$USER.csv' with CSV HEADER;"
|
||||
|
||||
psql jam -c "COPY( select id, part, instrument_id, (select description from instruments where id = instrument_id) as instrument_description, track_type, position, preview_mp3_url, preview_url as preview_ogg_url, preview_acc_url from jam_track_tracks) TO '$SAVE_TO/jam_track_tracks_for_jam_ui.$USER.csv' with CSV HEADER;"
|
||||
psql jam -c "COPY( select id, part, instrument_id, (select description from instruments where id = instrument_id) as instrument_description, track_type, position, preview_mp3_url, preview_url as preview_ogg_url, preview_aac_url from jam_track_tracks) TO '$SAVE_TO/jam_track_tracks_for_jam_ui.$USER.csv' with CSV HEADER;"
|
||||
|
||||
echo "Moving personal files to $SAVE_TO"
|
||||
sudo mv $SAVE_TO/jam_tracks_for_jam_ui.$USER.csv .
|
||||
sudo mv $SAVE_TO/jam_tracks_for_jam_ui_artists.$USER.csv .
|
||||
sudo mv $SAVE_TO/jam_track_tracks_for_jam_ui.$USER.csv .
|
||||
echo "Moving personal files to jamtracks-for-env"
|
||||
mkdir -p jamtracks-for-env
|
||||
sudo mv $SAVE_TO/jam_tracks_for_jam_ui.$USER.csv jamtracks-for-env
|
||||
sudo mv $SAVE_TO/jam_tracks_for_jam_ui_artists.$USER.csv jamtracks-for-env
|
||||
sudo mv $SAVE_TO/jam_track_tracks_for_jam_ui.$USER.csv jamtracks-for-env
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -9,7 +9,7 @@ const JKAffiliateSignup = ({signup}) => {
|
|||
{greaterThan.sm ? (
|
||||
<tr>
|
||||
<td>{signup.month}</td>
|
||||
<td className="text-center">{signup.visits}</td>
|
||||
{/*<td className="text-center">{signup.visits}</td>*/}
|
||||
<td className="text-center">{signup.signups}</td>
|
||||
</tr>
|
||||
) : (
|
||||
|
|
@ -17,11 +17,11 @@ const JKAffiliateSignup = ({signup}) => {
|
|||
<Row className="mb-1">
|
||||
<Col>{signup.month}</Col>
|
||||
</Row>
|
||||
<Row className="mb-1">
|
||||
{/*<Row className="mb-1">
|
||||
<Col>
|
||||
<small>Visits: {signup.visits}</small>
|
||||
</Col>
|
||||
</Row>
|
||||
</Row>*/}
|
||||
<Row className="mb-1">
|
||||
<Col>
|
||||
<small>Signups: {signup.signups}</small>
|
||||
|
|
|
|||
|
|
@ -6,15 +6,16 @@ import JKAffiliateSignup from './JKAffiliateSignup';
|
|||
const JKAffiliateSignupsList = ({ signups, nextPage, loading, stepForward }) => {
|
||||
const { t } = useTranslation('affiliate');
|
||||
return (
|
||||
<div>
|
||||
<Table striped bordered className="fs--1" data-testid="affiliateSignupList">
|
||||
<thead className="bg-200 text-900">
|
||||
<tr>
|
||||
<th width="35%" scope="col">
|
||||
{t('signups.list.header.date')}
|
||||
</th>
|
||||
<th width="35%" scope="col" className="text-center">
|
||||
{/* <th width="35%" scope="col" className="text-center">
|
||||
{t('signups.list.header.visits')}
|
||||
</th>
|
||||
</th> */}
|
||||
<th scope="col" className="text-center">
|
||||
{t('signups.list.header.signups')}
|
||||
</th>
|
||||
|
|
@ -25,10 +26,11 @@ const JKAffiliateSignupsList = ({ signups, nextPage, loading, stepForward }) =>
|
|||
<JKAffiliateSignup key={index} signup={signup} />
|
||||
))}
|
||||
</tbody>
|
||||
<div>
|
||||
</Table>
|
||||
<div>
|
||||
{nextPage && nextPage > 0 && !loading && <button onClick={stepForward}>{t('signups.load_more')}</button>}
|
||||
</div>
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ const ArtistBodyComponent = ({
|
|||
window.removeEventListener("resize", updateHeight);
|
||||
window.removeEventListener("resize", checkOverflow);
|
||||
}
|
||||
});
|
||||
}, [currentUser, jamTrack, jamTrackLoading]);
|
||||
|
||||
// This was a different approach to allow you to listen to different songs inline
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ const BodyComponent = ({
|
|||
const {addToCart} = useJamTrackShopping()
|
||||
const { currentUser } = useAuth();
|
||||
|
||||
console.log(`loading jamtrack with slug ${slug}`)
|
||||
|
||||
const isLoggedIn = () => {
|
||||
return currentUser != null
|
||||
}
|
||||
|
|
@ -46,7 +48,7 @@ const BodyComponent = ({
|
|||
const ctaClick = () => {
|
||||
const addJamTrackToCart = async () => {
|
||||
try {
|
||||
await addToCart(jamTrack);
|
||||
await addToCart(jamTrack, true);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
alert("Unable to add JamTrack to your cart.");
|
||||
|
|
@ -60,7 +62,7 @@ const BodyComponent = ({
|
|||
} else {
|
||||
console.log("no user")
|
||||
// redirect to the signup screen with the jamtrack & artist params set
|
||||
window.location.href = "/auth/signup?artist=" + encodeURIComponent(artist) + '&jamtrack=' + encodeURIComponent(slug)
|
||||
window.location.href = "/auth/signup?jamtrack=" + encodeURIComponent(slug)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -105,6 +107,7 @@ const BodyComponent = ({
|
|||
//coming to signup page after clicking on jamtrack or artist
|
||||
useEffect(() => {
|
||||
|
||||
console.log("useEffect, currentUser", currentUser)
|
||||
updateHeight(); // Run after initial render
|
||||
|
||||
window.addEventListener("resize", updateHeight); // Listen to resize
|
||||
|
|
@ -172,7 +175,7 @@ const BodyComponent = ({
|
|||
|
||||
return () => window.removeEventListener("resize", updateHeight);
|
||||
|
||||
});
|
||||
}, [currentUser, jamTrack, jamTrackLoading]);
|
||||
|
||||
return (
|
||||
<div className="jamtrack-landing-body">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React, {useContext, useEffect} from "react";
|
||||
import { BrowserRouter as Router, ReactDOM } from "react-router-dom";
|
||||
|
||||
import UserAuth from '../../context/UserAuth';
|
||||
import JKJamTracksLandingBody from "./JKJamTracksLandingBody";
|
||||
import AppContext from "../../context/Context";
|
||||
import {useResponsive} from "@farfetch/react-context-responsive";
|
||||
|
|
@ -47,10 +48,12 @@ const TemplatePage = ({ id, plan_code, slug, artist, song, location}) => {
|
|||
<Logo at="navbar-top" id="topLogo" width={240}/>
|
||||
</Navbar>
|
||||
<div className={`pt-3 row ${paddingClass}`}>
|
||||
<BrowserQueryProvider>
|
||||
<JKJamTracksLandingBody id={id} plan_code={plan_code} slug={slug} song={song} artist={artist}
|
||||
<UserAuth path={location}>
|
||||
<BrowserQueryProvider>
|
||||
<JKJamTracksLandingBody id={id} plan_code={plan_code} slug={slug} song={song} artist={artist}
|
||||
provided_jam_track={null}/>
|
||||
</BrowserQueryProvider>
|
||||
</BrowserQueryProvider>
|
||||
</UserAuth>
|
||||
</div>
|
||||
{/* <div className='px-6 row'> */}
|
||||
<Footer/>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const ProfileDropdown = () => {
|
|||
});
|
||||
setCurrentUser(null);
|
||||
await logout();
|
||||
window.location.href = "/";
|
||||
window.location.href = "/auth/login";
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ const useJamTrackShopping = () => {
|
|||
const { t } = useTranslation('jamtracks');
|
||||
const history = useHistory();
|
||||
|
||||
const addToCart = async (jamTrack) => {
|
||||
// forceReload means to navigate 'forcefully' using window.location.href, because
|
||||
// most likely coming from a landing page, which is not a part of the SPA
|
||||
const addToCart = async (jamTrack, forceReload = false) => {
|
||||
if (!currentUser) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -32,13 +34,25 @@ const useJamTrackShopping = () => {
|
|||
if (purchadeResp.ok) {
|
||||
const userResp = await updateUser(currentUser.id);
|
||||
if (userResp.ok) {
|
||||
history.push('/checkout/success?free=yes&jamtrackId=' + jamTrack.id);
|
||||
const checkoutPath = '/checkout/success?free=yes&jamtrackId=' + jamTrack.id;
|
||||
if (forceReload) {
|
||||
window.location.href = checkoutPath;
|
||||
}
|
||||
else {
|
||||
history.push(checkoutPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { //if this is a paid jamtrack
|
||||
toast.success(t('search.list.add_success_alert'));
|
||||
history.push('/shopping-cart');
|
||||
const shoppingCartPath = '/shopping-cart';
|
||||
if (forceReload) {
|
||||
window.location.href = shoppingCartPath;
|
||||
}
|
||||
else {
|
||||
history.push(shoppingCartPath);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@ const Layout = () => {
|
|||
//see if there is affiliate in query string and save it as cookie
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const affiliate = urlParams.get('affiliate');
|
||||
|
||||
const maxAge = 24 * 3600; // 1 day
|
||||
if (affiliate) {
|
||||
console.log(`affiliate found ${affiliate} ${process.env.REACT_APP_COOKIE_DOMAIN}`);
|
||||
document.cookie = `affiliate_visitor=${affiliate}; path=/; max-age=${maxAge}; domain=${process.env.REACT_APP_COOKIE_DOMAIN}`;
|
||||
}
|
||||
}, []);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useContext } from 'react'
|
||||
import React, { useContext, useEffect } from 'react'
|
||||
import PublicRoutes from './JKPublicRoutes';
|
||||
import UserAuth from '../context/UserAuth';
|
||||
import { BrowserQueryProvider } from '../context/BrowserQuery';
|
||||
import Logo from '../components/navbar/Logo';
|
||||
import AppContext from "../context/Context";
|
||||
|
|
@ -8,7 +9,7 @@ import { Navbar } from 'reactstrap';
|
|||
import Footer from '../components/footer/JKFooter';
|
||||
import {useResponsive} from "@farfetch/react-context-responsive";
|
||||
|
||||
const JKPublicLayout = () => {
|
||||
const JKPublicLayout = ({ location }) => {
|
||||
|
||||
const {
|
||||
isFluid,
|
||||
|
|
@ -31,9 +32,12 @@ const JKPublicLayout = () => {
|
|||
<Logo at="navbar-top" id="topLogo" width={240} />
|
||||
</Navbar>
|
||||
<div className={`pt-3 row ${paddingClass}`}>
|
||||
<UserAuth path={location.pathname}>
|
||||
|
||||
<BrowserQueryProvider>
|
||||
<PublicRoutes />
|
||||
</BrowserQueryProvider>
|
||||
</UserAuth>
|
||||
</div>
|
||||
{/* <div className='px-6 row'> */}
|
||||
<Footer />
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
# subtract the total quantity from the freebie quantity, to see how much we should attribute to them
|
||||
real_quantity = product_info[:quantity].to_i - product_info[:marked_for_redeem].to_i
|
||||
|
||||
{fee_in_cents: (rate * product_info[:real_price]).round}
|
||||
# if shopping_cart.is_lesson?
|
||||
# applicable_rate = lesson_rate
|
||||
# else
|
||||
|
|
@ -161,7 +162,7 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
# end
|
||||
#{fee_in_cents: (product_info[:price] * 100 * real_quantity * applicable_rate.to_f).round}
|
||||
|
||||
{ fee_in_cents: (real_quantity * jamtrack_share_in_cents.to_f).round}
|
||||
# { fee_in_cents: (real_quantity * jamtrack_share_in_cents.to_f).round}
|
||||
else
|
||||
false
|
||||
end
|
||||
|
|
@ -227,7 +228,8 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
tally_monthly_payments(quarter_info[:year], quarter_info[:quarter])
|
||||
tally_quarterly_payments(quarter_info[:year], quarter_info[:quarter])
|
||||
|
||||
tally_traffic_totals(GenericState.affiliate_tallied_at, day)
|
||||
# we aren't tracking visits anymore, so we don't need to tally_traffic_totals
|
||||
#tally_traffic_totals(GenericState.affiliate_tallied_at, day)
|
||||
|
||||
tally_partner_totals
|
||||
|
||||
|
|
@ -437,6 +439,34 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
close_months(year, quarter)
|
||||
end
|
||||
|
||||
# This was added because the tally_traffic_totals runs once a day, which is not often enough to get a fresh count of signups
|
||||
# so as users sign up, we increment the signups count for the day
|
||||
# jam=# \d affiliate_traffic_totals
|
||||
# Table "public.affiliate_traffic_totals"
|
||||
# Column | Type | Modifiers
|
||||
#----------------------+-----------------------------+------------------------
|
||||
# day | date | not null
|
||||
# signups | integer | not null default 0
|
||||
# visits | integer | not null default 0
|
||||
# affiliate_partner_id | integer | not null
|
||||
# created_at | timestamp without time zone | not null default now()
|
||||
|
||||
def self.increment_signups(user)
|
||||
sql = "SELECT count(day) as count FROM affiliate_traffic_totals WHERE day = '#{user.created_at.to_date}' AND affiliate_partner_id = #{user.affiliate_referral_id}"
|
||||
count = ActiveRecord::Base.connection.execute(sql)
|
||||
if count.count > 0 && count[0]['count'].to_i && count[0]['count'].to_i > 0
|
||||
sql = %{
|
||||
UPDATE affiliate_traffic_totals SET signups = signups + 1 WHERE day = '#{user.created_at.to_date}' AND affiliate_partner_id = #{user.affiliate_referral_id}
|
||||
}
|
||||
else
|
||||
sql = %{
|
||||
INSERT INTO affiliate_traffic_totals (day, signups, visits, affiliate_partner_id) VALUES ('#{user.created_at.to_date}', 1, 0, #{user.affiliate_referral_id})
|
||||
}
|
||||
end
|
||||
ActiveRecord::Base.connection.execute(sql)
|
||||
|
||||
end
|
||||
|
||||
def self.tally_partner_totals
|
||||
sql = %{
|
||||
UPDATE affiliate_partners SET
|
||||
|
|
@ -460,6 +490,8 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
return
|
||||
end
|
||||
|
||||
# Because we now increment_signups, as users sign up, it's possible this row already exists. however, if there were no signups and only visits, there may still not be a row here.
|
||||
# So we need to insert the rows, and if they already exist, the INSERT will be a no-op, as long as we also update this statement to not fail if the row already exists.
|
||||
sql = %{
|
||||
INSERT INTO affiliate_traffic_totals(SELECT day, 0, 0, ap.id FROM affiliate_partners AS ap CROSS JOIN (select (generate_series('#{start_date}', '#{end_date - 1}', '1 day'::interval))::date as day) AS lurp)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1865,6 +1865,9 @@ module JamRuby
|
|||
|
||||
if user.affiliate_referral = AffiliatePartner.find_by_id(affiliate_referral_id)
|
||||
user.save
|
||||
if !user.errors.any?
|
||||
AffiliatePartner.increment_signups(user)
|
||||
end
|
||||
end if affiliate_referral_id.present?
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue