Merged in VRFS-5512-jamtrack-landing-pages-2 (pull request #55)

Getting in the artist pages

* Add in artist pages

* Update bitbucket yml to push on both develop
This commit is contained in:
Seth Call 2025-03-03 13:18:54 +00:00 committed by Nuwan
parent 8cafb23b3e
commit b04bb0c55b
28 changed files with 18831 additions and 16132 deletions

View File

@ -2,7 +2,7 @@ image: node:14.21.3
pipelines:
branches:
seth/VRFS-5512-jamtrack-landing-pages:
develop:
- step:
name: Build Staging
script:
@ -41,44 +41,57 @@ pipelines:
S3_BUCKET: "jamkazam-ui/stg/js"
LOCAL_PATH: "jam-ui/build/js"
EXTRA_ARGS: "--content-type text/javascript"
- step:
name: Deploy to staging - invalidate cloudfront distribution
deployment: staging
script:
- pipe: atlassian/aws-cloudfront-invalidate:0.10.1
variables:
DISTRIBUTION_ID: "E2AQIC9RSON94Q" # ESQDIABYLT0RV
develop:
- step:
name: Build Staging
script:
- cd jam-ui
- npm install
- CI=false REACT_APP_ORIGIN=staging.jamkazam.com REACT_APP_CLIENT_BASE_URL=https://staging.jamkazam.com REACT_APP_API_BASE_URL=https://staging.jamkazam.com/api REACT_APP_BITBUCKET_BUILD_NUMBER=$BITBUCKET_BUILD_NUMBER REACT_APP_BITBUCKET_COMMIT=$BITBUCKET_COMMIT npm run build
artifacts:
- jam-ui/build/**
- step:
name: Deploy to staging
deployment: staging
script:
- pipe: atlassian/aws-s3-deploy:1.6.2
variables:
S3_BUCKET: "jamkazam-ui/stg"
LOCAL_PATH: "jam-ui/build"
# - step:
# name: Deploy to staging - invalidate cloudfront distribution
# deployment: staging
# script:
# - pipe: atlassian/aws-cloudfront-invalidate:0.10.1
# variables:
# DISTRIBUTION_ID: "E2AQIC9RSON94Q" # ESQDIABYLT0RV
- step:
name: Build Production
script:
- cd jam-ui
- pushd jam-ui
- npm install
- CI=false REACT_APP_ORIGIN=jamkazam.com REACT_APP_CLIENT_BASE_URL=https://www.jamkazam.com REACT_APP_API_BASE_URL=https://www.jamkazam.com/api REACT_APP_BITBUCKET_BUILD_NUMBER=$BITBUCKET_BUILD_NUMBER REACT_APP_BITBUCKET_COMMIT=$BITBUCKET_COMMIT npm run build
- popd
- pushd jam-ui/cicd
- npm install
- NODE_ENV=production ENVIRONMENT=production ./generate.sh
- popd
- cd jam-ui
- NODE_ENV=production CI=false REACT_APP_ORIGIN=jamkazam.com REACT_APP_CLIENT_BASE_URL=https://www.jamkazam.com REACT_APP_API_BASE_URL=https://www.jamkazam.com/api REACT_APP_BITBUCKET_BUILD_NUMBER=$BITBUCKET_BUILD_NUMBER REACT_APP_BITBUCKET_COMMIT=$BITBUCKET_COMMIT npm run build
artifacts:
- jam-ui/build/**
- step:
name: Deploy to production
deployment: production
name: Deploy to production - SPA
script:
- pipe: atlassian/aws-s3-deploy:1.1.0
- pipe: atlassian/aws-s3-deploy:1.6.2
variables:
S3_BUCKET: "jamkazam-ui/prd"
LOCAL_PATH: "jam-ui/build"
EXTRA_ARGS: "--exclude=*backing-tracks/*"
- step:
name: Deploy to production - backing-tracks
script:
- pipe: atlassian/aws-s3-deploy:1.6.2
variables:
S3_BUCKET: "jamkazam-ui/prd/backing-tracks"
LOCAL_PATH: "jam-ui/build/backing-tracks"
EXTRA_ARGS: "--exclude=*.js --content-type text/html"
- step:
name: Deploy to production - backing-tracks js
script:
- pipe: atlassian/aws-s3-deploy:1.6.2
variables:
S3_BUCKET: "jamkazam-ui/prd/js"
LOCAL_PATH: "jam-ui/build/js"
EXTRA_ARGS: "--content-type text/javascript"
#- step:
# name: Deploy to production - invalidate cloudfront distribution
# deployment: production
# script:
# - pipe: atlassian/aws-cloudfront-invalidate:0.10.1
# variables:
# DISTRIBUTION_ID: "ESQDIABYLT0RV"

View File

@ -2,3 +2,4 @@ build
output
node_modules
public
jam_track_tracks_for_jam_ui*

View File

@ -5,6 +5,7 @@ import React from "react";
import ReactDOM from "react-dom";
import Main from "../src/Main.js"
import TemplatePage from "../src/components/jamtracks/JKJamTracksLandingTemplatePage.js"
import ArtistTemplatePage from "../src/components/jamtracks/JKJamTracksArtistLandingTemplatePage.js"
import '../src/helpers/initFA';
import '../src/i18n/config';
@ -12,14 +13,7 @@ const rootElement = document.getElementById("root");
// Ensure props are passed correctly (or fetch from the server)
const props = window.jamtrack_data ? window.jamtrack_data : {
id: rootElement.dataset.id,
plan_code: rootElement.dataset.plan_code,
slug: rootElement.dataset.slug,
artist: rootElement.dataset.artist,
song: rootElement.dataset.song,
location: window.location.pathname,
};
const props = window.jamtrack_data;
console.log('init', props, rootElement);
@ -28,7 +22,7 @@ console.log('init', props, rootElement);
ReactDOM.render(
<Main>
<TemplatePage {...props} />
{props.song ? <TemplatePage {...props} /> : <ArtistTemplatePage {...props} /> }
</Main>, rootElement
);

View File

@ -9,11 +9,16 @@ fi
echo "Saving to $SAVE_TO"
psql jam -c "COPY( select id, original_artist, name , original_artist_slug, name_slug, plan_code, slug, ('https://www.jamkazam.com/backing-tracks/' || original_artist_slug || '/' || name_slug) as \"URL\", (select name from jam_track_licensors l where l.id = licensor_id) as \"Licensor\", vendor_id as \"Vendor ID\" FROM jam_tracks) TO '$SAVE_TO/jam_tracks_for_jam_ui.$USER.csv' with CSV HEADER;"
psql jam -c "COPY( select id, original_artist, name , original_artist_slug, name_slug, plan_code, slug, allow_free, ('https://www.jamkazam.com/backing-tracks/' || original_artist_slug || '/' || name_slug) as \"URL\", (select name from jam_track_licensors l where l.id = licensor_id) as \"Licensor\", vendor_id as \"Vendor ID\" FROM jam_tracks) TO '$SAVE_TO/jam_tracks_for_jam_ui.$USER.csv' with CSV HEADER;"
//https://jamkazam-public.s3.amazonaws.com
# 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;"
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 .

View File

@ -0,0 +1,39 @@
#!/bin/bash
# Ensure the correct number of arguments
if [ "$#" -lt 2 ]; then
echo "Usage: $0 <save_to_path> <server_env>"
exit 1
fi
SAVE_TO="$1"
server_env="$2"
# Validate server_env
if [ "$server_env" != "staging" ] && [ "$server_env" != "production" ]; then
echo "Error: server_env must be either 'staging' or 'production'"
exit 1
fi
# Determine SSH target
if [ "$server_env" == "staging" ]; then
SSH_TARGET="jam@int.jamkazam.com"
else
SSH_TARGET="jam@db.jamkazam.com"
fi
echo "Saving to $SAVE_TO on $server_env"
# Run psql commands remotely
ssh $SSH_TARGET "psql jam -c \"COPY( select id, original_artist, name, original_artist_slug, name_slug, plan_code, slug, allow_free, ('https://www.jamkazam.com/backing-tracks/' || original_artist_slug || '/' || name_slug) as \"URL\", (select name from jam_track_licensors l where l.id = licensor_id) as \"Licensor\" FROM jam_tracks order by id::int) TO '$SAVE_TO/jam_tracks_for_jam_ui.$server_env.csv' with CSV HEADER;\""
ssh $SSH_TARGET "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 order by original_artist) TO '$SAVE_TO/jam_tracks_for_jam_ui_artists.$server_env.csv' with CSV HEADER;\""
ssh $SSH_TARGET "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 order by jam_track_id::int) TO '$SAVE_TO/jam_track_tracks_for_jam_ui.$server_env.csv' with CSV HEADER;\""
# Move files locally from the remote server
scp $SSH_TARGET:"$SAVE_TO/jam_tracks_for_jam_ui.$server_env.csv" jamtracks-for-env
scp $SSH_TARGET:"$SAVE_TO/jam_tracks_for_jam_ui_artists.$server_env.csv" jamtracks-for-env
scp $SSH_TARGET:"$SAVE_TO/jam_track_tracks_for_jam_ui.$server_env.csv" jamtracks-for-env
echo "Files moved successfully to local machine"

View File

@ -5,8 +5,40 @@ const React = require("react");
const dotenv = require("dotenv");
const ReactDOMServer = require("react-dom/server");
const TemplatePageModule = require("./build/components/jamtracks/JKJamTracksLandingTemplatePage");
const ArtistTemplatePageModule = require("./build/components/jamtracks/JKJamTracksArtistLandingTemplatePage");
var csvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui.${process.env.USER}.csv`
var artistCsvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui_artists.${process.env.USER}.csv`
/**
* Loads a CSV file into an array of objects.
* @param {string} csvPath - The path to the CSV file.
* @returns {Promise<Array<Object>>} - A promise that resolves with the parsed CSV data.
*/
const load_csv = (csvPath) => {
return new Promise((resolve, reject) => {
const results = [];
fs.createReadStream(csvPath)
.pipe(csv())
.on('data', (data) => results.push(data))
.on('end', () => resolve(results))
.on('error', (error) => reject(error));
});
};
/**
* Finds all songs for a given artist based on the original_artist_slug
* and sorts them alphabetically by the `slug` field.
* @param {string} artistSlug - The original_artist_slug to match.
* @param {Array<Object>} songsCsv - The songs CSV data.
* @returns {Array<Object>} - A sorted array of matching song objects.
*/
const collect_songs_for_artist = (artistSlug, songsCsv) => {
return songsCsv
.filter((song) => song.original_artist_slug === artistSlug)
.sort((a, b) => a.slug.localeCompare(b.slug)); // Sort alphabetically by slug
};
var csvFilePath = `jam_tracks_for_jam_ui.${process.env.USER}.csv`
const init = () => {
const node_env = process.env.NODE_ENV || 'development';
@ -15,10 +47,12 @@ const init = () => {
console.log(dotenv.config({ path: `../.env.${environment}` }));
if (environment === "production" || environment === "staging") {
csvFilePath = `jam_tracks_for_jam_ui.${environment}.csv`;
csvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui.${environment}.csv`;
artistCsvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui_artists.${environment}.csv`;
}
console.log("using csv file", csvFilePath);
console.log("Song csv file", csvFilePath);
console.log("Artist csv file", artistCsvFilePath);
if (!process.env.PUBLIC_URL) {
console.log("setting public url", process.env.REACT_APP_BASE_URL);
@ -31,7 +65,7 @@ const init = () => {
console.log("init done successfully")
}
const generatePages = async (render) => {
const generateSongPages = async (render) => {
const rows = [];
const OUTPUT_DIR = path.join(__dirname, "..", "public", "backing-tracks");
@ -53,7 +87,7 @@ const generatePages = async (render) => {
for (const row of rows) {
// id, original_artist, name, original_artist_slug, name_slug, plan_code, slug, URL, licensor, vendor_id
const { id, original_artist, name, original_artist_slug, name_slug, plan_code, slug } = row;
const { id, original_artist, name, original_artist_slug, name_slug, plan_code, slug, allow_free } = row;
const artist = original_artist;
const song = name;
const location = `/backing-tracks/${original_artist_slug}/${name_slug}`;
@ -132,8 +166,7 @@ const generatePages = async (render) => {
fs.mkdirSync(ARTIST_DIR, { recursive: false });
}
console.log("process.env.NODE_ENV=", process.env.NODE_ENV);
const finalOutputPath = process.env.NODE_ENV === "development" ? `${name_slug}.html` : name_slug;
const finalOutputPath = process.env.NODE_ENV === "development" ? `${name_slug}.html` : `${name_slug}.html`;
const outputFilePath = path.join(ARTIST_DIR, finalOutputPath);
fs.writeFileSync(outputFilePath, fullHtml);
console.log(`Generated: ${outputFilePath}`);
@ -143,10 +176,112 @@ const generatePages = async (render) => {
});
};
const generateArtistPages = async (render) => {
const rows = [];
const OUTPUT_DIR = path.join(__dirname, "..", "public", "backing-tracks");
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
}
console.log("generatPages starting")
const TemplatePage = TemplatePageModule.default;
const songs_csv = await load_csv(csvFilePath);
fs.createReadStream(artistCsvFilePath)
.pipe(csv())
.on("data", (row) => rows.push(row))
.on("end", async () => {
console.log(`Processing ${rows.length} rows...`);
for (const row of rows) {
const { original_artist, original_artist_slug, url } = row;
const artist = original_artist;
const matchingSongs = collect_songs_for_artist(original_artist_slug, songs_csv);
console.log(`Found ${matchingSongs.length} songs for ${artist}`);
const location = `/backing-tracks/${original_artist_slug}`;
const fullPath = process.env.REACT_APP_BASE_URL + location;
const logoPath = process.env.REACT_APP_BASE_URL + "/favicon.svg";
console.log(`Generating ${artist}`);
const songs = matchingSongs.map((song) => {
return {
name: song.name,
plan_code: song.plan_code,
url: process.env.REACT_APP_BASE_URL + "/backing-tracks/" + song.original_artist_slug + "/" + song.name_slug
}
});
const html = render
? ReactDOMServer.renderToStaticMarkup(
React.createElement(ArtistTemplatePage, { artist, original_artist_slug, location })
)
: "";
const fullHtml = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="shortcut icon" href="/favicon.svg">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${artist} - Free Backing Track</title>
<link rel="stylesheet" href="${process.env.REACT_APP_BASE_URL}/css/theme.css">
<meta name="description" content="Get a free ${artist} backing track, plus free tools to mute any part, slow down for practice, record yourself, more">
<meta name="keywords" content="Backing Track, ${artist}, Instrumental">
<meta name="author" content="JamKazam">
<!-- Open Graph (Facebook, LinkedIn, etc.) -->
<meta property="og:title" content="${artist} | Free Backing Track">
<meta property="og:description" content="Get a free ${artist} backing track, plus free tools to mute any part, slow down for practice, record yourself, more">
<meta property="og:image" content="${logoPath}">
<meta property="og:url" content="${fullPath}">
<meta property="og:type" content="music.song">
<!-- Twitter Cards -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="${artist} | Free Backing Track">
<meta name="twitter:description" content="Get a free ${artist} backing track, plus free tools to mute any part, slow down for practice, record yourself, more">
<meta name="twitter:image" content="${logoPath}">
<!-- Canonical URL -->
<link rel="canonical" href="${fullPath}" />
<script>
window.jamtrack_data = {
artist: "${artist}",
original_artist_slug: "${original_artist_slug}",
location: "${location}",
songs: ${JSON.stringify(songs)}
}
</script>
</head>
<body>
<div id="root">${html}</div>
<script src="/js/client-hydrate.bundle.js"></script>
</body>
</html>`;
const finalOutputPath = process.env.NODE_ENV === "development" ? `${original_artist_slug}.html` : `${original_artist_slug}.html`;
const outputFilePath = path.join(OUTPUT_DIR, finalOutputPath);
fs.writeFileSync(outputFilePath, fullHtml);
console.log(`Generated: ${outputFilePath}`);
}
console.log("All pages generated!");
});
};
let render = false;
if (process.argv.length > 2) {
render = process.argv[2] === "true" || process.argv[2] === "yes" || process.argv[2] === "1";
}
init()
generatePages(render);
generateSongPages(render);
generateArtistPages(render);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,3 +15,7 @@
box-shadow: none !important;
border: solid 1px #eee;
}
.jk-blue-color {
color: rgb(64,124,222);
}

View File

@ -1,3 +1,7 @@
.preview-region.card {
max-height:25rem;
}
.content-row.landing-page {
display: flex;
justify-content: space-between;
@ -68,15 +72,53 @@
}
.top-region-container {
display: grid;
grid-template-columns: 60% 40%;
gap: 3rem; /* Adds spacing between them */
//display: grid;
//grid-template-columns: 50% calc(50% - 3rem);
//gap: 3rem; /* Adds spacing between them */
display: flex;
align-items: start;
gap: 3rem;
.free {
width: 50%;
}
.free, .limited {
// flex: 1; /* Both elements take equal width */
}
.limited {
width:calc(50% - 3rem);
overflow: auto; /* Enables scrolling if needed */
max-height: 0; /* JavaScript will update this */
}
}
.jamtrack-listing-header {
margin:0;
font-size:1rem;
}
.jamtrack-listing-item {
margin-bottom: 0rem;
}
.jamtrack-listing-container {
margin: .2rem 0 2.5rem 0;
max-height:8.5rem;
overflow: auto;
border-style: solid;
border-color: #616e80;
border-width: 1px 0 1px 0;
scrollbar-gutter: stable;
}
.preview-region {
.spinner-border {
float: right;
margin-top: -25px;
}
/* Make it respect the height of the parent */
max-height: 100%; /* Ensures it doesn't exceed parent height */
overflow: auto; /* Enables scrolling if content overflows */
@ -141,6 +183,16 @@
gap:0;
}
.free {
width: auto !important;
}
.limited {
width:auto !important;
overflow: auto; /* Enables scrolling if needed */
max-height: auto; /* JavaScript will update this */
}
#root {
h2 {
margin-top: 1.5rem;

View File

@ -67,6 +67,13 @@ const JKJamTrackTrack = ({ track, duration = null }) => {
trackSound.pause();
setIsPlaying(false);
}
if (trackSound) {
if (isPlaying) {
trackSound.pause();
}
}
}, [currentPlayTrackId]);
const togglePlay = () => {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
import React from 'react'
import { useParams, Link } from 'react-router-dom';
import JKJamTracksArtistLandingBody from './JKJamTracksArtistLandingBody';
// This page is not the real entry point into a jamtracks landing page,
// as deployed to a server. This is here to facilitate development of the
// landing page when running locally.
// Note: the real entry point is the JKJamTracksLandingTemplatePage component,
// which is used only during build time when generate statice pages as files.
const JKJamTracksArtistLanding = () => {
const { original_artist_slug } = useParams();
return (
<div>
<JKJamTracksArtistLandingBody original_artist_slug={original_artist_slug} />
</div>
)
}
export default JKJamTracksArtistLanding

View File

@ -0,0 +1,55 @@
import React, {useContext} from "react";
import { BrowserRouter as Router, ReactDOM } from "react-router-dom";
import JKJamTracksArtistLandingBody from "./JKJamTracksArtistLandingBody";
import AppContext from "../../context/Context";
import {useResponsive} from "@farfetch/react-context-responsive";
import {Navbar} from "reactstrap";
import {topNavbarBreakpoint} from "../../config";
import Logo from "../navbar/Logo";
import {BrowserQueryProvider} from "../../context/BrowserQuery";
import Footer from "../footer/JKFooter";
const ArtistTemplatePage = ({ original_artist_slug, artist, songs}) => {
console.log('ArtistTemplatePage', original_artist_slug, artist);
const {
isFluid,
isTopNav,
} = useContext(AppContext);
const { greaterThan } = useResponsive();
const paddingClass = greaterThan.sm ? "px-6" : "px-1";
return (
<Router location={location} context={{}}>
<div className={isFluid ? 'container-fluid' : 'container'}>
<div className="content">
<Navbar
light
color="white"
className={`navbar-glass fs--1 font-weight-semi-bold row navbar-top sticky-kit mb-3 py-3 ${paddingClass}`}
expand={isTopNav && topNavbarBreakpoint}
>
<Logo at="navbar-top" id="topLogo" width={240}/>
</Navbar>
<div className={`pt-3 row ${paddingClass}`}>
<BrowserQueryProvider>
<JKJamTracksArtistLandingBody artist={artist} original_artist_slug={original_artist_slug} songs={songs}
provided_jam_track={null}/>
</BrowserQueryProvider>
</div>
{/* <div className='px-6 row'> */}
<Footer/>
{/* </div> */}
</div>
</div>
</Router>
);
};
export default ArtistTemplatePage;

View File

@ -1,4 +1,4 @@
import React, {useEffect, useState} from "react";
import React, {useEffect, useState, useRef} from "react";
import ReactDOM from "react-dom";
import {getCurrentUser, getJamTrackPublic} from '../../helpers/rest';
import JKJamTrackPreview from './JKJamTrackPreview';
@ -68,13 +68,47 @@ const BodyComponent = ({
addJamTrackToCart()
}
}
const ConditionalLoader = () => {
if (jamTrack == null) {
return <div className="spinner-border ml-2" role="status">
<span className="sr-only">Loading...</span>
</div>
}
return null;
}
const CtaButton = () => {
const btnText = hasFreeJamTrack() ? "Claim Free Backing Track" : "Add To Cart"
return <button onClick={ctaClick} className="btn btn-primary claim-free-backing-track">{btnText}</button>
};
const freeRef = useRef(null);
const limitedRef = useRef(null);
// Function to sync height
const updateHeight = () => {
// Matches when width >= 1000px - check in _landing.scss for the matching 999px rule
const isWideScreen = window.matchMedia("(min-width: 1000px)").matches;
if (!isWideScreen) {
// Reset the height when inactive
if (limitedRef.current) limitedRef.current.style.maxHeight = "unset";
return; // Do nothing if screen width < 999px
}
if (freeRef.current && limitedRef.current) {
limitedRef.current.style.maxHeight = `${freeRef.current.offsetHeight}px`;
}
};
//coming to signup page after clicking on jamtrack or artist
useEffect(() => {
updateHeight(); // Run after initial render
window.addEventListener("resize", updateHeight); // Listen to resize
const jamtrack_api_options = {plan_code: plan_code}
console.log(`jamtrack properties id=${id} plan_code=${plan_code} slug=${slug} artist=${artist} song=${song}`)
@ -136,10 +170,12 @@ const BodyComponent = ({
fetchJamTrack();
}
return () => window.removeEventListener("resize", updateHeight);
});
return (
<div>
<div className="jamtrack-landing-body">
<UserAuth path={"/"}>
<AppDataProvider>
<JamTrackPreviewProvider>
@ -148,7 +184,7 @@ const BodyComponent = ({
<h1 className="top-title">Free {song} By {artist} Backing Track</h1>
<div className="top-region-container">
<div className="region mb-4 top-explanation-region">
<div className="region mb-4 top-explanation-region free" ref={freeRef}>
<p>Our JamTracks take backing tracks to another level. Click the play icons in the
Preview box
to hear the full backing track mix and each of its parts. You can use our free
@ -173,9 +209,9 @@ const BodyComponent = ({
who love our backing tracks!</p>
</div>
</div>
<div className="region mb-4 preview-region card">
<div className="region mb-4 preview-region card limited" ref={limitedRef}>
<div className="card-header bg-light">
<h2>Preview Backing Track</h2>
<h2>Preview Backing Track</h2>{ConditionalLoader()}
<p>{artist} - {song}</p>
</div>
<div className="card-body bg-white">
@ -183,7 +219,6 @@ const BodyComponent = ({
Click the play buttons below to preview the master mix and 20-second samples
of each fully isolated part of the backing track.
</p>
{jamTrack != null && <JKJamTrackPreview jamTrack={jamTrack} columns={false}
initialJamTracksShowCount={100}/>}
@ -524,9 +559,7 @@ use their favorite plugins to power their percussive audio.</span></p>
</div>
</div>
<div className="center-children">
<button className="btn btn-primary claim-free-backing-track">Claim Free Backing
Track
</button>
<CtaButton/>
</div>
</div>
</div>

View File

@ -1,4 +1,4 @@
import React, { useContext } from 'react'
import React, { useContext } from 'react'
import PublicRoutes from './JKPublicRoutes';
import { BrowserQueryProvider } from '../context/BrowserQuery';
import Logo from '../components/navbar/Logo';

View File

@ -10,7 +10,8 @@ import JKForum from '../components/public/help/JKForum';
import JKUnsubscribe from '../components/public/JKUnsubscribe';
import JKDownloads from '../components/public/JKDownloads';
import JKDownloadsLegacy from '../components/public/JKDownloadsLegacy';
import JKJamTracksLanding from '../components/jamtracks/JKJamTracksLanding';
import JKJamTracksLanding from '../components/jamtracks/JKJamTracksLandingDev';
import JKJamTracksArtistLanding from '../components/jamtracks/JKJamTracksArtistLandingDev';
const JKPublicRoutes = ({ match: { url } }) => (
@ -24,7 +25,7 @@ const JKPublicRoutes = ({ match: { url } }) => (
<Route path={`${url}/downloads`} exact component={JKDownloads} />
<Route path={`${url}/downloads-legacy`} exact component={JKDownloadsLegacy} />
<Route path={`${url}/backing-tracks/:artist/:song`} component={JKJamTracksLanding} />
<Route path={`${url}/backing-tracks/:artist`} component={JKJamTracksLanding} />
<Route path={`${url}/backing-tracks/:artist`} component={JKJamTracksArtistLanding} />
{/*Redirect*/}
<Redirect to="/errors/404" />