summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/applet.js6
-rw-r--r--client/chart/constants.js33
-rw-r--r--client/chart/countriesByYear.chart.js (renamed from client/chart/chart.container.js)38
-rw-r--r--client/chart/index.js6
-rw-r--r--client/chart/pie.charts.js167
5 files changed, 211 insertions, 39 deletions
diff --git a/client/applet.js b/client/applet.js
index cd73925c..21e1e4fa 100644
--- a/client/applet.js
+++ b/client/applet.js
@@ -4,7 +4,7 @@ import { Container as FaceSearchContainer } from './faceSearch'
import { Container as FaceAnalysisContainer } from './faceAnalysis'
import { Container as NameSearchContainer } from './nameSearch'
import { Container as DatasetListContainer } from './datasetList'
-import { Container as ChartContainer } from './chart'
+import { CountriesByYear, PieCharts } from './chart'
export default class Applet extends Component {
render() {
@@ -19,7 +19,9 @@ export default class Applet extends Component {
case 'dataset_list':
return <DatasetListContainer {...this.props} />
case 'chart':
- return <ChartContainer {...this.props} />
+ return <CountriesByYear {...this.props} />
+ case 'piechart':
+ return <PieCharts {...this.props} />
default:
return <pre style={{ color: '#0f0' }}>{'Megapixels'}</pre>
}
diff --git a/client/chart/constants.js b/client/chart/constants.js
new file mode 100644
index 00000000..295b9232
--- /dev/null
+++ b/client/chart/constants.js
@@ -0,0 +1,33 @@
+export const rainbow = [
+ '#9e0142',
+ '#d53e4f',
+ '#f46d43',
+ '#fdae61',
+ '#fee08b',
+ '#ffffbf',
+ '#e6f598',
+ '#abdda4',
+ '#66c2a5',
+ '#3288bd',
+ '#5e4fa2',
+ // '#888888',
+]
+
+export const colorblindSafeRainbow = [
+ '#a50026',
+ '#d73027',
+ '#f46d43',
+ '#fdae61',
+ '#fee090',
+ '#ffffbf',
+ '#e0f3f8',
+ '#abd9e9',
+ '#74add1',
+ '#4575b4',
+ '#313695',
+ // '#888888',
+]
+
+export const topCountryCount = 10
+
+export const otherCountriesLabel = 'Other Countries'
diff --git a/client/chart/chart.container.js b/client/chart/countriesByYear.chart.js
index aa80100e..c846fd0f 100644
--- a/client/chart/chart.container.js
+++ b/client/chart/countriesByYear.chart.js
@@ -6,41 +6,9 @@ import C3Chart from 'react-c3js'
import 'c3/c3.css'
import './chart.css'
-const rainbow = [
- '#9e0142',
- '#d53e4f',
- '#f46d43',
- '#fdae61',
- '#fee08b',
- '#ffffbf',
- '#e6f598',
- '#abdda4',
- '#66c2a5',
- '#3288bd',
- '#5e4fa2',
- // '#888888',
-]
+import { rainbow, colorblindSafeRainbow, topCountryCount, otherCountriesLabel } from './constants'
-const colorblindSafeRainbow = [
- '#a50026',
- '#d73027',
- '#f46d43',
- '#fdae61',
- '#fee090',
- '#ffffbf',
- '#e0f3f8',
- '#abd9e9',
- '#74add1',
- '#4575b4',
- '#313695',
- // '#888888',
-]
-
-const topCountryCount = 10
-
-const otherCountriesLabel = 'Other Countries'
-
-class ChartContainer extends Component {
+class CountriesByYearChart extends Component {
render() {
const { payload } = this.props
const { paper, citations } = payload.data
@@ -196,4 +164,4 @@ class ChartContainer extends Component {
}
}
-export default ChartContainer
+export default CountriesByYearChart
diff --git a/client/chart/index.js b/client/chart/index.js
index e9d3322d..27650020 100644
--- a/client/chart/index.js
+++ b/client/chart/index.js
@@ -1,5 +1,7 @@
-import Container from './chart.container'
+import CountriesByYear from './countriesByYear.chart'
+import PieCharts from './pie.charts'
export {
- Container,
+ CountriesByYear,
+ PieCharts,
}
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