diff --git a/components/ChallengeStatus/ChallengeStatus.jsx b/components/ChallengeStatus/ChallengeStatus.jsx index 3e10b9aa5..a8ec92605 100644 --- a/components/ChallengeStatus/ChallengeStatus.jsx +++ b/components/ChallengeStatus/ChallengeStatus.jsx @@ -1,7 +1,5 @@ import React, { Component, PropTypes } from 'react'; -import fetch from 'isomorphic-fetch'; import moment from 'moment'; -import _ from 'lodash'; import LeaderboardAvatar from '../LeaderboardAvatar/LeaderboardAvatar'; import ChallengeProgressBar from '../ChallengeProgressBar/ChallengeProgressBar'; import ProgressBarTooltip from '../ChallengeCard/Tooltips/ProgressBarTooltip'; @@ -15,7 +13,6 @@ import './ChallengeStatus.scss'; // Constants const ID_LENGTH = 6; const MAX_VISIBLE_WINNERS = 3; -const MOCK_PHOTO = 'https://acrobatusers.com/assets/images/template/author_generic.jpg'; const STALLED_MSG = 'Stalled'; const DRAFT_MSG = 'In Draft'; const STALLED_TIME_LEFT_MSG = 'Challenge is currently on hold'; @@ -149,13 +146,15 @@ const getTimeToGo = (start, end) => { * Returns an user profile object as expected by the UserAvatarTooltip * @param {String} handle */ -function getSampleProfile(user) { - const { handle } = user; +function getProfile(user) { + const { handle, placement } = user; + const photoLink = user.photoURL || `i/m/${handle}.jpeg`; return { handle, + placement, country: '', memberSince: '', - photoLink: `i/m/${handle}.jpeg`, + photoLink, ratingSummary: [], }; } @@ -173,9 +172,7 @@ class ChallengeStatus extends Component { DS_CHALLENGE_URL, FORUM_URL, }; - this.handleHover = this.handleHover.bind(this); - this.getDevelopmentWinners = this.getDevelopmentWinners.bind(this); - this.getDesignWinners = this.getDesignWinners.bind(this); + this.registrantsLink = this.registrantsLink.bind(this); } @@ -183,18 +180,40 @@ class ChallengeStatus extends Component { const { challenge } = this.props; const { DS_CHALLENGE_URL, CHALLENGE_URL } = this.state; const { id, track } = challenge; + const challengeURL = track === 'DATA_SCIENCE' ? DS_CHALLENGE_URL : CHALLENGE_URL; - const leaderboard = this.state.winners && this.state.winners.map(winner => ( -
- - - -
- )); + let winners = challenge.winners && challenge.winners.filter(winner => winner.type === 'final') + .map(winner => ({ + handle: winner.handle, + position: winner.placement, + photoURL: winner.photoURL || `${this.props.MAIN_URL}/i/m/${winner.handle}.jpeg`, + })); + + if (winners && winners.length > MAX_VISIBLE_WINNERS) { + const lastItem = { + handle: `+${winners.length - MAX_VISIBLE_WINNERS}`, + isLastItem: true, + }; + winners = winners.slice(0, MAX_VISIBLE_WINNERS); + winners.push(lastItem); + } + + const leaderboard = winners && winners.map((winner) => { + if (winner.isLastItem) { + return ; + } + const userProfile = getProfile(winner); + return ( +
+ + + +
); + }); return leaderboard || ( - - Winners - ); + + Results + ); } renderRegisterButton() { @@ -334,16 +353,15 @@ class ChallengeStatus extends Component {
{this.renderLeaderboard()} - + {challenge.numRegistrants} - + - {challenge.numSubmissions} @@ -360,86 +378,6 @@ class ChallengeStatus extends Component { ); } - getDevelopmentWinners(challengeId) { - return new Promise((resolve, reject) => { - fetch(`${this.props.config.API_URL_V2}/develop/challenges/${challengeId}`) - .then(res => res.json()) - .then((data) => { - let winners = data.submissions.filter(sub => sub.placement) - .map(winner => ({ - handle: winner.handle, - position: winner.placement, - photoURL: MOCK_PHOTO, - })); - winners = _.uniqWith(winners, _.isEqual); - if (winners.length > MAX_VISIBLE_WINNERS) { - const lastItem = { - handle: `+${winners.length - MAX_VISIBLE_WINNERS}`, - }; - winners = winners.slice(0, MAX_VISIBLE_WINNERS); - winners.push(lastItem); - } - resolve(winners); - }) - .catch(err => reject(err)); - }); - } - - getDesignWinners(challengeId) { - return new Promise((resolve, reject) => { - fetch(`${this.props.config.API_URL_V2}/design/challenges/result/${challengeId}`) - .then(res => res.json()) - .then((data) => { - let winners = data.results.filter(sub => sub.placement) - .map(winner => ({ - handle: winner.handle, - position: winner.placement, - photoURL: MOCK_PHOTO, - })); - winners = _.uniqWith(winners, _.isEqual); - if (winners.length > MAX_VISIBLE_WINNERS) { - const lastItem = { - handle: `+${winners.length - MAX_VISIBLE_WINNERS}`, - }; - winners = winners.slice(0, MAX_VISIBLE_WINNERS); - winners.push(lastItem); - } - resolve(winners); - }) - .catch(err => reject(err)); - }); - } - - - getWinners(challengeType, challengeId) { - switch (challengeType) { - case 'develop': - return this.getDevelopmentWinners(challengeId); - case 'design': - return this.getDesignWinners(challengeId); - default: - return this.getDevelopmentWinners(challengeId); - } - } - - /** - * Get the list of winners when the user hovers - * over the status - */ - handleHover() { - if (!this.state.winners) { - const { challenge } = this.props; - const { id, track } = challenge; - - // We don't have the API for data science challenge - if (track === 'DATA_SCIENCE') { - return; - } - const results = this.getWinners(track.toLowerCase(), id); - results.then(winners => this.setState({ winners })); - } - } - render() { const { challenge } = this.props; const status = challenge.status === 'COMPLETED' ? 'completed' : ''; @@ -456,12 +394,14 @@ ChallengeStatus.defaultProps = { config: {}, detailLink: '', sampleWinnerProfile: undefined, + MAIN_URL: process.env.MAIN_URL, }; ChallengeStatus.propTypes = { challenge: PropTypes.object, config: PropTypes.object, detailLink: PropTypes.string, + MAIN_URL: PropTypes.string, }; export default ChallengeStatus; diff --git a/components/LeaderboardAvatar/LeaderboardAvatar.jsx b/components/LeaderboardAvatar/LeaderboardAvatar.jsx index 403b670d2..d790f8bbb 100644 --- a/components/LeaderboardAvatar/LeaderboardAvatar.jsx +++ b/components/LeaderboardAvatar/LeaderboardAvatar.jsx @@ -1,28 +1,50 @@ -import React from 'react' +import React, { Component } from 'react' import './LeaderboardAvatar.scss' // Constants const VISIBLE_CHARACTERS = 3 +const MOCK_PHOTO = 'https://acrobatusers.com/assets/images/template/author_generic.jpg' -function LeaderboardAvatar ({member, domain}) { - return ( - - {member.photoURL ? : member.handle.slice(0, VISIBLE_CHARACTERS)} - - {member.position} - - - ) +class LeaderboardAvatar extends Component { + constructor(props) { + super(props) + this.state = { + member: props.member, + } + this.handleError = this.handleError.bind(this) + } + + handleError() { + const { member } = this.state + member.photoURL = MOCK_PHOTO + this.setState({ member }) + } + + render() { + const { domain, url } = this.props + const { member } = this.state + const targetURL = url ? url : `//${domain}/members/${member.handle}` + return ( + + {member.photoURL ? : member.handle.slice(0, VISIBLE_CHARACTERS)} + + {member.position} + + + ) + } } LeaderboardAvatar.propTypes = { member: React.PropTypes.object, domain: React.PropTypes.string, + url: React.PropTypes.string, } LeaderboardAvatar.defaultProps = { member: {}, domain: process.env.domain, + url: '' } export default LeaderboardAvatar