summaryrefslogtreecommitdiff
path: root/scraper
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2019-04-02 19:03:06 +0200
committerJules Laplace <julescarbon@gmail.com>2019-04-02 19:03:06 +0200
commit77e2b579bc42b6c36f82dba246561293049e73f8 (patch)
tree2ae0a2474dcc84f43e6753a0718866a7f0e75375 /scraper
parent4f9d68e6b546559bd80c93b2de3a42f554589d24 (diff)
adding chart... whole verify app working nicer
Diffstat (limited to 'scraper')
-rw-r--r--scraper/client/app.js1
-rw-r--r--scraper/client/common/header.component.js9
-rw-r--r--scraper/client/common/table.component.js3
-rw-r--r--scraper/client/paper/citationList.component.js33
-rw-r--r--scraper/client/paper/index.js2
-rw-r--r--scraper/client/paper/paper.chart.js83
-rw-r--r--scraper/client/paper/paper.citations.js6
-rw-r--r--scraper/client/paper/paper.css21
-rw-r--r--scraper/client/paper/paper.info.js32
-rw-r--r--scraper/client/paper/paper.manager.js35
-rw-r--r--scraper/client/paper/paper.unknown.js41
11 files changed, 185 insertions, 81 deletions
diff --git a/scraper/client/app.js b/scraper/client/app.js
index b449d0d0..366d4098 100644
--- a/scraper/client/app.js
+++ b/scraper/client/app.js
@@ -17,7 +17,6 @@ export default class App extends Component {
<Switch>
<Route exact path="/paper/:key/" component={Paper.Info} />
<Route exact path="/paper/:key/citations/" component={Paper.Citations} />
- <Route exact path="/paper/:key/unknown/" component={Paper.UnknownCitations} />
<Route exact path="/paper/:key/info/" component={Paper.Info} />
<Route exact path="/paper/:key/random/" component={Paper.Random} />
<Route exact path="/paper/:key/address/:sha256" component={Paper.Address} />
diff --git a/scraper/client/common/header.component.js b/scraper/client/common/header.component.js
index 2f084979..c9825aab 100644
--- a/scraper/client/common/header.component.js
+++ b/scraper/client/common/header.component.js
@@ -1,5 +1,5 @@
import React, { Component } from 'react'
-// import { NavLink } from 'react-router-dom'
+import { Link } from 'react-router-dom'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
@@ -34,10 +34,9 @@ class Header extends Component {
{dataset &&
<div>
{dataset.name_full}{' - '}
- <a href={"/paper/" + dataset.key + "/info"}>Info</a>{' - '}
- <a href={"/paper/" + dataset.key + "/citations/"}>Citations</a>{' - '}
- <a href={"/paper/" + dataset.key + "/unknown/"}>Unknown</a>{' - '}
- <a href={"/paper/" + dataset.key + "/random/"}>Random</a>
+ <Link to={"/paper/" + dataset.key + "/info"}>Info</Link>{' - '}
+ <Link to={"/paper/" + dataset.key + "/citations/"}>Citations</Link>{' - '}
+ <Link to={"/paper/" + dataset.key + "/random/"}>Random</Link>
</div>
}
</section>
diff --git a/scraper/client/common/table.component.js b/scraper/client/common/table.component.js
index 96b62835..121c9841 100644
--- a/scraper/client/common/table.component.js
+++ b/scraper/client/common/table.component.js
@@ -118,6 +118,9 @@ export function TableCell({ value }) {
value = <TableObject nested tag={''} object={value} />
}
}
+ if (value && typeof value === 'string' && value.indexOf('http') === 0) {
+ value = <a href={value} target="_blank" rel="nofollower noopener">{value}</a>
+ }
return (
<td>{value}</td>
)
diff --git a/scraper/client/paper/citationList.component.js b/scraper/client/paper/citationList.component.js
index be8528bf..002c0dcb 100644
--- a/scraper/client/paper/citationList.component.js
+++ b/scraper/client/paper/citationList.component.js
@@ -9,38 +9,31 @@ import { TableObject, Loader } from '../common'
import { USES_DATASET } from '../types'
class CitationList extends Component {
- componentDidMount() {
- const { citations, api } = this.props
- const { paperInfo, unknownCitations, verifications } = api
- const { dataset } = paperInfo
- if (!dataset || !citations || !verifications[dataset.key]) {
- this.props.actions.setSortedCitations([])
- return
- }
- let verifiedLookup = verifications[dataset.key] || {}
- const sortedCitations = citations.map(citation => [
- citation.title,
- verifiedLookup[citation.id] ? verifiedLookup[citation.id].uses_dataset : USES_DATASET.NO_DATA,
- citation.pdf.length,
- citation
- ])
- .sort((a,b) => (b[1] - a[1] || b[2] - a[2] || (a[0].localeCompare(b[0]))))
- .map(tup => tup[3])
- this.props.actions.setSortedCitations(sortedCitations)
+ state = {
+ filter: USES_DATASET.YES,
}
render() {
const { citations, title, api } = this.props
const { paperInfo, unknownCitations, verifications, sortedCitations } = api
const { dataset } = paperInfo
+ const { filter } = this.state
if (!dataset || !citations || !verifications[dataset.key]) return <Loader />
let verifiedLookup = verifications[dataset.key] || {}
- // console.log(verifications)
+ let filteredCitations = sortedCitations.filter(citation => (
+ citation.verified === filter
+ ))
return (
<div className='citations'>
<h2>{title}</h2>
+ <div className='filter_buttons'>
+ <span className='verified' onClick={() => this.setState({ filter: USES_DATASET.YES })}>uses dataset</span>
+ <span className='unverified' onClick={() => this.setState({ filter: USES_DATASET.NO })}>{"doesn't use dataset"}</span>
+ <span className='not_enough_info' onClick={() => this.setState({ filter: USES_DATASET.UNKNOWN })}>{'not enough information'}</span>
+ <span className='unknown' onClick={() => this.setState({ filter: USES_DATASET.NO_DATA })}>{'unverified'}</span>
+ </div>
<ul>
- {(sortedCitations || []).map((citation, i) => {
+ {(filteredCitations || []).map((citation, i) => {
let cite = { ...citation }
cite.id = {
_raw: true,
diff --git a/scraper/client/paper/index.js b/scraper/client/paper/index.js
index 99672684..9346234a 100644
--- a/scraper/client/paper/index.js
+++ b/scraper/client/paper/index.js
@@ -1,7 +1,6 @@
import Manager from './paper.manager'
import Info from './paper.info'
import Citations from './paper.citations'
-import UnknownCitations from './paper.unknown'
import Random from './paper.random'
import Address from './paper.address'
import Verify from './paper.verify'
@@ -13,7 +12,6 @@ export {
Manager,
Info,
Citations,
- UnknownCitations,
Random,
Address,
Verify,
diff --git a/scraper/client/paper/paper.chart.js b/scraper/client/paper/paper.chart.js
new file mode 100644
index 00000000..01d8d0e8
--- /dev/null
+++ b/scraper/client/paper/paper.chart.js
@@ -0,0 +1,83 @@
+import React, { Component } from 'react'
+import { bindActionCreators } from 'redux'
+import { connect } from 'react-redux'
+import { toArray, toTuples } from '../util'
+import C3Chart from 'react-c3js'
+import 'c3/c3.css'
+
+class PaperChart extends Component {
+ render() {
+ const { rows, title } = this.props
+ if (!rows.length) return null
+ const colorPattern = [
+ "#00b200",
+ "#ff0000",
+ "#e0c200",
+ "#dddddd",
+ ]
+
+ return (
+ <div className='chart'>
+ <div>
+ <C3Chart
+ data={{
+ columns: rows,
+ type: 'pie',
+ }}
+ color={{
+ pattern: colorPattern,
+ }}
+ tooltip={{
+ format: {
+ value: value => value,
+ }
+ }}
+ size={{
+ height: rows.length < 4 ? 316 : 336,
+ }}
+ />
+ <span className='chartCaption'>{title}</span>
+ </div>
+ </div>
+ )
+ }
+}
+
+/*
+ legend={{
+ position: 'right'
+ }}
+ 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('')
+ }
+ }}
+*/
+
+export default PaperChart
diff --git a/scraper/client/paper/paper.citations.js b/scraper/client/paper/paper.citations.js
index f0e9ea26..c3a9cc61 100644
--- a/scraper/client/paper/paper.citations.js
+++ b/scraper/client/paper/paper.citations.js
@@ -11,12 +11,6 @@ import { USES_DATASET } from '../types'
import CitationList from './citationList.component'
class PaperCitations extends Component {
- componentDidUpdate(prevProps) {
- if (this.props.api.paperInfo.dataset !== prevProps.api.paperInfo.dataset) {
- this.props.actions.getVerificationsDataset(this.props.api.paperInfo.dataset.key)
- }
- }
-
render() {
const { paperInfo, unknownCitations, verifications } = this.props.api
const { dataset, citations } = paperInfo
diff --git a/scraper/client/paper/paper.css b/scraper/client/paper/paper.css
index 21df2df1..914077b6 100644
--- a/scraper/client/paper/paper.css
+++ b/scraper/client/paper/paper.css
@@ -12,6 +12,20 @@
width: 100%;
}
+.filter_buttons {
+ margin-left: 5px;
+ margin-bottom: 10px;
+}
+.filter_buttons span {
+ margin-right: 10px;
+ cursor: pointer;
+ opacity: 0.8;
+ transition: opacity 0.2;
+}
+.filter_buttons span:hover {
+ opacity: 1;
+}
+
.citations {
padding:40px;
}
@@ -82,6 +96,13 @@
padding:4px;
font-size:12px;
}
+.chartCaption {
+ display: block;
+ width: 100%;
+ font-size: 12px;
+ color: #333;
+ text-align: center;
+}
.param {
display: flex;
diff --git a/scraper/client/paper/paper.info.js b/scraper/client/paper/paper.info.js
index b4fe54ba..25f4472f 100644
--- a/scraper/client/paper/paper.info.js
+++ b/scraper/client/paper/paper.info.js
@@ -3,17 +3,40 @@ import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as actions from '../actions'
-
import { TableObject } from '../common'
+import { USES_DATASET } from '../types'
+
+import PaperChart from './paper.chart'
class PaperInfo extends Component {
render() {
- const { paperInfo, unknownCitations } = this.props.api
+ const { paperInfo, sortedCitations, unknownCitations } = this.props.api
const { dataset, paper, address } = paperInfo
if (!dataset) return null
+
+ let counts = {}
+ const citationLabels = ['Uses Dataset', 'Doesn\'t Use Dataset', 'Not Enough Information', 'Unknown']
+ const citationCountOrder = [ USES_DATASET.YES, USES_DATASET.NO, USES_DATASET.UNKNOWN, USES_DATASET.NO_DATA ]
+ citationCountOrder.forEach(v => counts[v] = 0)
+
+ sortedCitations.forEach(c => counts[c.verified] += 1)
+
+ let citationCounts = {}
+ let citationRows = []
+ citationCountOrder.forEach((v, i) => {
+ const count = counts[v]
+ const label = citationLabels[i]
+ citationCounts[label] = count
+ citationRows.push([ label, count ])
+ })
+
return (
<div className='paperInfo'>
<h2>{dataset.name_full}</h2>
+ <PaperChart
+ rows={citationRows}
+ title={'Dataset coverage'}
+ />
<TableObject summary
tag="Dataset"
object={dataset}
@@ -43,10 +66,7 @@ class PaperInfo extends Component {
/>
<TableObject summary
tag="Citations"
- object={{
- 'geocoded': paperInfo.citations.length,
- 'unknown': unknownCitations.citations ? unknownCitations.citations.length : 'Loading',
- }}
+ object={citationCounts}
/>
</div>
)
diff --git a/scraper/client/paper/paper.manager.js b/scraper/client/paper/paper.manager.js
index 2ac03b01..8b25b1cc 100644
--- a/scraper/client/paper/paper.manager.js
+++ b/scraper/client/paper/paper.manager.js
@@ -3,6 +3,7 @@ import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as actions from '../actions'
+import { USES_DATASET } from '../types'
import { Loader } from '../common'
@@ -15,6 +16,40 @@ class PaperManager extends Component {
if (this.props.match.params.key !== oldProps.match.params.key) {
this.props.actions.getPaperInfo(this.props.match.params.key)
}
+ console.log('whoms?')
+ if (this.props.api.paperInfo.dataset !== oldProps.api.paperInfo.dataset && this.props.api.paperInfo.dataset && this.props.api.paperInfo.dataset.key) {
+ console.log('vert?')
+ this.props.actions.getVerificationsDataset(this.props.api.paperInfo.dataset.key)
+ }
+ if (this.props.api.verifications !== oldProps.api.verifications && this.props.api.paperInfo.dataset) {
+ console.log('updated?')
+ this.updateSortedCitations()
+ }
+ }
+
+ updateSortedCitations() {
+ const { api } = this.props
+ const { paperInfo, unknownCitations, verifications } = api
+ const { dataset } = paperInfo
+ if (!dataset || !paperInfo.citations || !unknownCitations.citations || !verifications[dataset.key]) {
+ this.props.actions.setSortedCitations([])
+ return
+ }
+ const citations = paperInfo.citations.concat(unknownCitations.citations)
+ let verifiedLookup = verifications[dataset.key] || {}
+ const sortedCitations = citations.map(citation => [
+ citation.title,
+ verifiedLookup[citation.id] ? verifiedLookup[citation.id].uses_dataset : USES_DATASET.NO_DATA,
+ citation.pdf.length,
+ citation
+ ])
+ .sort((a,b) => (b[1] - a[1] || b[2] - a[2] || (a[0].localeCompare(b[0]))))
+ .map(tup => ({
+ ...tup[3],
+ verified: tup[1],
+ }))
+ console.log('updated')
+ this.props.actions.setSortedCitations(sortedCitations)
}
render() {
diff --git a/scraper/client/paper/paper.unknown.js b/scraper/client/paper/paper.unknown.js
deleted file mode 100644
index 876ac144..00000000
--- a/scraper/client/paper/paper.unknown.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import React, { Component } from 'react'
-import { bindActionCreators } from 'redux'
-import { connect } from 'react-redux'
-import { Link } from 'react-router-dom'
-
-import * as actions from '../actions'
-
-import { Loader } from '../common'
-import { USES_DATASET } from '../types'
-
-import CitationList from './citationList.component'
-
-class PaperUnknown extends Component {
- componentDidUpdate(prevProps) {
- if (this.props.api.paperInfo.dataset !== prevProps.api.paperInfo.dataset) {
- this.props.actions.getVerificationsDataset(this.props.api.paperInfo.dataset.key)
- }
- }
-
- render() {
- const { paperInfo, unknownCitations, verifications } = this.props.api
- const { dataset, citations } = paperInfo
- if (!dataset || !citations || !verifications[dataset.key]) return <Loader />
-
- return (
- <CitationList
- title={dataset.name_full + ': Unknown Citations'}
- citations={unknownCitations.citations}
- />
- )
- }
-}
-
-const mapStateToProps = state => ({
- api: state.api
-})
-const mapDispatchToProps = dispatch => ({
- actions: bindActionCreators({ ...actions }, dispatch),
-})
-
-export default connect(mapStateToProps, mapDispatchToProps)(PaperUnknown)