mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Added a random order and a limit of 5 to the Recommendations modal (#17958)
refs https://github.com/TryGhost/Product/issues/3815 - recommendations are rendered in a random order, using Fisher-Yates shuffle - only 5 recommendations are rendered by default, the other ones are hidden behind a "Show all" button - recommendations are fetched all at once from the backend, as we assume there won't be more than 100-ish recommendations per publication
This commit is contained in:
parent
dd4e27a729
commit
a017596a1d
1 changed files with 48 additions and 8 deletions
|
@ -1,5 +1,5 @@
|
|||
import AppContext from '../../AppContext';
|
||||
import {useContext} from 'react';
|
||||
import {useContext, useState, useEffect} from 'react';
|
||||
|
||||
export const RecommendationsPageStyles = `
|
||||
.gh-portal-recommendation-item {
|
||||
|
@ -32,6 +32,24 @@ export const RecommendationsPageStyles = `
|
|||
}
|
||||
`;
|
||||
|
||||
const shuffleRecommendations = (array) => {
|
||||
let currentIndex = array.length;
|
||||
let randomIndex;
|
||||
|
||||
// While there remain elements to shuffle...
|
||||
while (currentIndex > 0) {
|
||||
// Pick a remaining element...
|
||||
randomIndex = Math.floor(Math.random() * currentIndex);
|
||||
currentIndex -= 1;
|
||||
|
||||
// And swap it with the current element.
|
||||
[array[currentIndex], array[randomIndex]] = [
|
||||
array[randomIndex], array[currentIndex]];
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
const RecommendationItem = ({title, url, reason, favicon}) => {
|
||||
const {t} = useContext(AppContext);
|
||||
|
||||
|
@ -54,7 +72,27 @@ const RecommendationItem = ({title, url, reason, favicon}) => {
|
|||
const RecommendationsPage = () => {
|
||||
const {site, t} = useContext(AppContext);
|
||||
const {title, icon} = site;
|
||||
const recommendations = site.recommendations || [];
|
||||
const {recommendations_enabled: recommendationsEnabled = false} = site;
|
||||
const {recommendations = []} = site;
|
||||
|
||||
// Show 5 recommendations by default
|
||||
const [numToShow, setNumToShow] = useState(5);
|
||||
|
||||
// Show recommendations in a random order
|
||||
const [shuffledRecommendations, setShuffledRecommendations] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// Shuffle the array once when the component mounts
|
||||
setShuffledRecommendations(shuffleRecommendations([...recommendations]));
|
||||
}, [recommendations]);
|
||||
|
||||
const showAllRecommendations = () => {
|
||||
setNumToShow(recommendations.length);
|
||||
};
|
||||
|
||||
if (!recommendationsEnabled || recommendations.length < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='gh-portal-content with-footer'>
|
||||
|
@ -65,16 +103,18 @@ const RecommendationsPage = () => {
|
|||
<p className="gh-portal-recommendations-description">{t(`Here are a few other sites ${title} thinks you may enjoy.`)}</p>
|
||||
|
||||
<div className="gh-portal-list">
|
||||
{recommendations.map((recommendation, index) => (
|
||||
{shuffledRecommendations.slice(0, numToShow).map((recommendation, index) => (
|
||||
<RecommendationItem key={index} {...recommendation} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<footer className='gh-portal-action-footer'>
|
||||
<button className='gh-portal-btn gh-portal-center' style={{width: '100%'}}>
|
||||
<span>{t('Show all')}</span>
|
||||
</button>
|
||||
</footer>
|
||||
{numToShow < recommendations.length && (
|
||||
<footer className='gh-portal-action-footer'>
|
||||
<button className='gh-portal-btn gh-portal-center' style={{width: '100%'}} onClick={showAllRecommendations}>
|
||||
<span>{t('Show all')}</span>
|
||||
</button>
|
||||
</footer>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue