diff options
Diffstat (limited to 'client/chart/pie.charts.js')
| -rw-r--r-- | client/chart/pie.charts.js | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/client/chart/pie.charts.js b/client/chart/pie.charts.js new file mode 100644 index 00000000..998d6758 --- /dev/null +++ b/client/chart/pie.charts.js @@ -0,0 +1,167 @@ +import React, { Component } from 'react' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' +import { toArray } from '../util' +import C3Chart from 'react-c3js' +import 'c3/c3.css' +import './chart.css' + +import { rainbow, colorblindSafeRainbow, topCountryCount, otherCountriesLabel } from './constants' + +class PieCharts extends Component { + render() { + const { payload } = this.props + const { paper, citations } = payload.data + if (!citations.length) return null + const years = {} + const countries = {} + citations.forEach(citation => { + let { year, addresses } = citation + if (!year || !parseInt(year)) return + year = parseInt(year) + years[year] = years[year] || {} + addresses.forEach(address => { + const { country } = address + if (!country) return + if (!(country in countries)) { + countries[country] = 1 + } else { + countries[country] += 1 + } + if (country in years[year]) { + years[year][country] += 1 + } else { + years[year][country] = 1 + countries[country] = true + } + }) + }) + let yearList = Object.keys(years).map(year => parseInt(year)).sort() + for (let i = yearList[0]; i < yearList[-1]; i++) { + if (!(i in years)) { + years[i] = {} + } + } + yearList = Object.keys(years).map(year => parseInt(year)).sort() + + Object.keys(countries).forEach(country => { + yearList.forEach(year => { + if (!(country in years[year])) years[year][country] = 0 + }) + }) + + // figure out the top N countries in the dataset + const countriesByCount = Object.keys(countries).sort((a,b) => countries[b] - countries[a]) + // console.log(countriesByCount) + let topCountries = countriesByCount.slice(0, topCountryCount) + let otherCountries = countriesByCount.slice(topCountryCount) + + let citationCountsByYear = + [ ['x'].concat(yearList.map(year => String(year))) ] + .concat( + topCountries + .map(country => + [country] + .concat( + yearList + .map(year => years[year][country]) + ) + ) + ) + + citationCountsByYear.push( + [otherCountriesLabel].concat( + yearList.map(year => otherCountries.reduce((a,b) => (a + years[year][b]), 0)) + ) + ) + + let maxCitationsInAYear = 0 + let currentSum = 0 + // for each year... + for (let j = 1; j < citationCountsByYear[0].length; j++) { + // for each country + currentSum = 0 + for (let i = 1; i < citationCountsByYear.length; i++) { + currentSum += citationCountsByYear[i][j] + } + maxCitationsInAYear = Math.max(currentSum, maxCitationsInAYear) + } + + let ticks = [] + for (let i = 0; i < maxCitationsInAYear; i += 50) { + ticks.push(i) + } + if (ticks[ticks.length - 1] < maxCitationsInAYear) { + ticks.push('') + } + + const colorPattern = rainbow + + return ( + <div className='chart'> + <C3Chart + data={{ + x: 'x', + columns: citationCountsByYear, + type: 'bar', + groups: [ topCountries.concat(otherCountriesLabel) ], + }} + axis={{ + x: { + type: 'category' // this needed to load string x value + }, + y: { + show: false, + }, + y2: { + tick: { + values: ticks, + }, + default: [ 0, maxCitationsInAYear * 286 / 261 ], + show: true, + } + }} + legend={{ + position: 'right' + }} + color={{ + pattern: colorPattern + }} + tooltip={{ + contents: function (d, defaultTitleFormat, defaultValueFormat, color) { + const countriesByYearLookup = years[yearList[d[0].x]] + let countriesByYear = Object.keys(countriesByYearLookup).map(country => [country, countriesByYearLookup[country]]).sort((a,b) => b[1] - a[1]) + let topCountriesForThisYear = countriesByYear.slice(0, topCountryCount) + let bottomTotal = countriesByYear.slice(topCountryCount).reduce((a,b) => (a + b[1]), 0) + // console.log(topCountriesForThisYear) + topCountriesForThisYear.push([otherCountriesLabel, bottomTotal]) + const tableRows = topCountriesForThisYear.filter(pair => !!pair[1]).map(([country, total]) => { + let colorIndex = topCountries.indexOf(country) + if (colorIndex < 0) colorIndex = colorPattern.length - 1 + const color = colorPattern[ colorIndex ] + return [ + "<tr>", + "<td>", + "<span style='background-color:" + color + "' class='swatch'></span>", + country, + "</td>", + "<td>", + total, + "</td>", + "</tr>", + ].join('') + }) + return [ + "<table class='c3-tooltip'>", + ...tableRows, + "</table>", + ].join('') + } + }} + /> + </div> + ) + } +} + +export default PieCharts |
