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:
parent
8cafb23b3e
commit
b04bb0c55b
|
|
@ -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"
|
||||
|
|
@ -2,3 +2,4 @@ build
|
|||
output
|
||||
node_modules
|
||||
public
|
||||
jam_track_tracks_for_jam_ui*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 .
|
||||
|
|
@ -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"
|
||||
|
|
@ -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 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
|
|
@ -15,3 +15,7 @@
|
|||
box-shadow: none !important;
|
||||
border: solid 1px #eee;
|
||||
}
|
||||
|
||||
.jk-blue-color {
|
||||
color: rgb(64,124,222);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue