diff --git a/src/shared/components/challenge-detail/MMDashboard/Graph/index.jsx b/src/shared/components/challenge-detail/MMDashboard/Graph/index.jsx index 9c0a395eb..359f51121 100644 --- a/src/shared/components/challenge-detail/MMDashboard/Graph/index.jsx +++ b/src/shared/components/challenge-detail/MMDashboard/Graph/index.jsx @@ -26,33 +26,41 @@ export default function Graph({ statisticsData, baseline, awardLine }) { }); }); - const pointDatas = _.map(flatData, (data) => { - let color; - let isSelected = false; - if (point) { - isSelected = point.customData.handle === data.handle; - if (isSelected) { - color = getHighlightedColor(data.rating || 0); + const pointDatas = _.chain(flatData) + .map((data) => { + let color; + let isSelected = false; + if (point) { + isSelected = point.customData.handle === data.handle; + if (isSelected) { + color = getHighlightedColor(data.rating || 0); + } else { + color = getUnSelectedColors(data.rating || 0); + } } else { - color = getUnSelectedColors(data.rating || 0); + color = data.ratingColor || getRatingColor(data.rating || 0); } - } else { - color = data.ratingColor || getRatingColor(data.rating || 0); - } - return { - x: moment(data.created || data.createdAt).valueOf(), - y: _.max([0, data.score ? (parseFloat(data.score)) : 0]), - name: data.handle, - color, - customData: data, - marker: { - enabled: true, - width: 'circle', - radius: isSelected ? 6 : 4, - }, - className: !isSelected && point ? styles.selectedPoint : '', - }; - }); + + const score = parseFloat(data.score); + const x = moment(data.created || data.createdAt).valueOf(); + const y = _.max([0, Number.isFinite(score) ? score : 0]); + + return { + x, + y, + name: data.handle, + color, + customData: data, + marker: { + enabled: true, + width: 'circle', + radius: isSelected ? 6 : 4, + }, + className: !isSelected && point ? styles.selectedPoint : '', + }; + }) + .filter(pointData => Number.isFinite(pointData.x) && Number.isFinite(pointData.y)) + .value(); const options = { plotOptions: { @@ -79,6 +87,7 @@ export default function Graph({ statisticsData, baseline, awardLine }) { series: [ { data: pointDatas, + turboThreshold: 0, pointStart: moment(_.min(dates)).valueOf(), pointInterval: 24 * 3600 * 1000, backgroundColor: 'rgb(51,51,51)', diff --git a/src/shared/containers/challenge-detail/index.jsx b/src/shared/containers/challenge-detail/index.jsx index 3b972b09e..a10e0e7be 100644 --- a/src/shared/containers/challenge-detail/index.jsx +++ b/src/shared/containers/challenge-detail/index.jsx @@ -134,6 +134,14 @@ export function getDisplayWinners(challenge = {}) { }); } +function hasRenderableStatisticsData(statisticsData) { + return Array.isArray(statisticsData) + && statisticsData.some(entry => ( + Array.isArray(_.get(entry, 'submissions')) + && _.get(entry, 'submissions.length', 0) > 0 + )); +} + /** * Given challenge details object, it returns the URL of the image to be used in * OpenGraph (i.e. in social sharing posts). @@ -349,9 +357,8 @@ class ChallengeDetailPageContainer extends React.Component { const previousToken = _.get(auth, 'tokenV3'); const nextToken = _.get(nextProps, 'auth.tokenV3'); - const hasStatisticsData = Array.isArray(statisticsData) && statisticsData.length > 0; - const nextHasStatisticsData = Array.isArray(nextProps.statisticsData) - && nextProps.statisticsData.length > 0; + const hasStatisticsData = hasRenderableStatisticsData(statisticsData); + const nextHasStatisticsData = hasRenderableStatisticsData(nextProps.statisticsData); const enteringMmDashboard = selectedTab !== DETAIL_TABS.MM_DASHBOARD && nextProps.selectedTab === DETAIL_TABS.MM_DASHBOARD; const tokenBecameAvailable = !previousToken && !!nextToken; @@ -737,7 +744,7 @@ class ChallengeDetailPageContainer extends React.Component { } { !isEmpty && selectedTab === DETAIL_TABS.MM_DASHBOARD - && (!statisticsData || statisticsData.length === 0) + && !hasRenderableStatisticsData(statisticsData) && (