summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/chart/pie.charts.js2
-rw-r--r--client/index.js32
-rw-r--r--client/map/index.js302
-rw-r--r--client/table/citations.table.js10
4 files changed, 202 insertions, 144 deletions
diff --git a/client/chart/pie.charts.js b/client/chart/pie.charts.js
index c3b94b7b..939e9262 100644
--- a/client/chart/pie.charts.js
+++ b/client/chart/pie.charts.js
@@ -17,7 +17,7 @@ class PieCharts extends Component {
render() {
const { payload } = this.props
const { paper, citations } = payload.data
- console.log(this.props)
+ // console.log(this.props)
if (!citations.length) return null
const countries = {}
diff --git a/client/index.js b/client/index.js
index c003a8b3..1a80e74f 100644
--- a/client/index.js
+++ b/client/index.js
@@ -2,7 +2,7 @@ import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import { Provider } from 'react-redux'
-import 'waypoints/lib/noframework.waypoints.min.js';
+import 'waypoints/lib/noframework.waypoints.min.js'
import { toArray } from './util'
import Applet from './applet'
@@ -62,7 +62,7 @@ function runApplets() {
let payload
try {
payload = JSON.parse(el.dataset.payload)
- console.log(payload)
+ // console.log(payload)
} catch (e) {
return null
}
@@ -106,7 +106,7 @@ function runApplets() {
}
payload.dataset = dataset
payload.url = url
- console.log(payload)
+ // console.log(payload)
return [el, payload]
}).filter(a => !!a)
const withDataset = applets.map(a => a[1].dataset ? a[1] : null).filter(a => !!a)
@@ -122,20 +122,20 @@ function runApplets() {
function buildWaypoints() {
const element = document.querySelector('.content section:nth-child(2)')
- if (element) {
- var waypoint = new Waypoint({
- element,
- handler: function(direction) {
- if (direction === 'down') {
- document.body.classList.add('scrolled')
- } else {
- document.body.classList.remove('scrolled')
- }
- // console.log(direction)
- // console.log('Scrolled to waypoint!')
+ if (!element) return null
+ let waypoint = new Waypoint({
+ element,
+ handler: function(direction) {
+ if (direction === 'down') {
+ document.body.classList.add('scrolled')
+ } else {
+ document.body.classList.remove('scrolled')
}
- })
- }
+ // console.log(direction)
+ // console.log('Scrolled to waypoint!')
+ }
+ })
+ return waypoint
}
function main() {
diff --git a/client/map/index.js b/client/map/index.js
index 29fc2286..4492a69a 100644
--- a/client/map/index.js
+++ b/client/map/index.js
@@ -28,7 +28,9 @@ const arcStyles = {
},
}
+const buttonOrder = ['edu', 'company', 'gov']
const sortOrder = ['edu', 'company', 'gov', 'mil']
+const typeScores = { all: 0, edu: 1, company: 2, gov: 3, mil: 3 }
const redDot = L.icon({
iconUrl: '/assets/img/reddot.png',
@@ -37,145 +39,199 @@ const redDot = L.icon({
popupAnchor: [0, -5] // point from which the popup should open relative to the iconAnchor
})
-function addMarker(map, latlng, citations) {
- const marker = L.marker(latlng, { icon: redDot }).addTo(map)
- let message = citations.map(citation => {
- const { title, addresses, year, pdf, doi } = citation
- let rec = [
- "<b>", title, "</b>",
- ]
- if (pdf && pdf.length) {
- rec.unshift("<a href='" + pdf[0] + "' target='_blank'>")
- rec.push("</a>")
- }
- else if (doi && doi.length) {
- rec.unshift("<a href='" + doi[0] + "' target='_blank'>")
- rec.push("</a>")
+class Map {
+ constructor(el, data) {
+ let { paper, citations } = data
+ this.el = el
+ this.paper = paper
+ this.markers = []
+ this.arcs = []
+ this.filter = typeScores.all
+
+ if (paper.addresses && paper.addresses.length) {
+ this.source = [
+ paper.addresses[0].lat,
+ paper.addresses[0].lng
+ ].map(n => (parseFloat(n) || 0))
+ } else {
+ console.error("No address found for root paper")
+ this.source = [0, 0]
+ // console.log(data)
}
- if (year) {
- rec.push(" (" + year + ")")
+
+ // group papers by address
+ this.citationsByAddress = {}
+ this.citations = citations
+ this.citations.forEach(citation => {
+ if (!citation.addresses) {
+ return
+ }
+ citation.addresses.forEach(address => {
+ if (!(address.name in this.citationsByAddress)) {
+ this.citationsByAddress[address.name] = { address, citations: [] }
+ }
+ this.citationsByAddress[address.name].citations.push(citation)
+ })
+ })
+ this.build()
+ this.bind()
+ this.buildMarkers()
+ this.rootMarker.openPopup()
+ }
+
+ build() {
+ this.map = L.map(this.el).setView([25, 0], 2)
+ L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
+ attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
+ '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
+ 'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
+ maxZoom: 18,
+ id: 'mapbox.dark',
+ style: 'mapbox://styles/mapbox/dark-v9',
+ accessToken: 'pk.eyJ1IjoiZmFuc2FsY3kiLCJhIjoiY2pvN3I1czJwMHF5NDNrbWRoMWpteHlrdCJ9.kMpM5syQUhVjKkn1iVx9fg'
+ }).addTo(this.map)
+ }
+
+ bind() {
+ // a transparent div to cover the map, so normal scroll events will not be eaten by leaflet
+ const mapCover = document.createElement("div")
+ mapCover.classList.add("map_cover")
+ mapCover.innerHTML = "<div class='cover_message'>Click here to explore the map</div>"
+ mapCover.querySelector('div').addEventListener('click', () => {
+ this.map.scrollWheelZoom.enable()
+ if (mapCover.parentNode === this.el) {
+ this.el.removeChild(mapCover)
+ }
+ })
+ mapCover.querySelector('div').addEventListener('touchstart', (e) => {
+ e.preventDefault()
+ })
+ mapCover.querySelector('div').addEventListener('tap', () => {
+ this.map.scrollWheelZoom.enable()
+ if (mapCover.parentNode === this.el) {
+ this.el.removeChild(mapCover)
+ }
+ })
+ function stopPropagation(e) {
+ e.stopPropagation()
}
- const addressString = addresses.map(addr => addr.name).join('<br/>')
- rec.push("<br>")
- rec.push(addressString)
- return rec.join("")
- })
+ mapCover.addEventListener('mousewheel', stopPropagation, true)
+ mapCover.addEventListener('DOMMouseScroll', stopPropagation, true)
- marker.bindPopup(message.join('<br><br>'))
- return marker
-}
+ this.map.scrollWheelZoom.disable()
+ this.map.on('focus', () => {
+ this.map.scrollWheelZoom.enable()
+ if (mapCover.parentNode === this.el) {
+ this.el.removeChild(mapCover)
+ }
+ })
+ this.map.on('blur', () => {
+ this.map.scrollWheelZoom.disable()
+ // el.appendChild(mapCover)
+ })
-function addArc(map, src, dest, arcStyle) {
- L.bezier({
- path: [
- [
- { lat: src[0], lng: src[1] },
- { lat: dest[0], lng: dest[1] },
- ],
- ]
- }, arcStyle).addTo(map)
-}
+ this.el.appendChild(mapCover)
-export default function append(el, payload) {
- const { data } = payload
- if (!data) return
- let { paper, citations } = data
- let source = [0, 0]
+ buttonOrder.forEach(type => {
+ const typeClass = type.substr(0, 3)
+ const el = document.querySelector('.map-legend .' + typeClass)
+ el.addEventListener('click', () => {
+ console.log(el)
+ this.filterMarkers(el, type)
+ })
+ })
+ }
- let map = L.map(el).setView([25, 0], 2)
- L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
- attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
- '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
- 'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
- maxZoom: 18,
- id: 'mapbox.dark',
- style: 'mapbox://styles/mapbox/dark-v9',
- accessToken: 'pk.eyJ1IjoiZmFuc2FsY3kiLCJhIjoiY2pvN3I1czJwMHF5NDNrbWRoMWpteHlrdCJ9.kMpM5syQUhVjKkn1iVx9fg'
- }).addTo(map)
+ filterMarkers(el, type) {
+ const active = document.querySelector('.map-legend .active')
+ if (active) active.classList.remove('active')
+ const newFilter = typeScores[type]
+ if (this.filter === newFilter) {
+ this.filter = typeScores.all
+ } else {
+ this.filter = newFilter
+ el.classList.add('active')
+ }
+ this.buildMarkers()
+ }
- if (paper.addresses && paper.addresses.length) {
- source = [paper.addresses[0].lat, paper.addresses[0].lng].map(n => (parseFloat(n) || 0))
- } else {
- console.error("No address found for root paper")
- // console.log(data)
+ resetMarkers() {
+ this.arcs.forEach(arc => arc.remove())
+ this.markers.forEach(marker => marker.remove())
+ this.markers = []
+ this.arcs = []
}
- // group papers by address
- let citationsByAddress = {}
- citations.forEach(citation => {
- if (!citation.addresses) {
+ buildMarkers() {
+ this.resetMarkers()
+ Object.keys(this.citationsByAddress).map(name => {
+ const { citations: citationList, address } = this.citationsByAddress[name]
+ if (this.filter && typeScores[address.type] !== this.filter) return
+ // console.log(name, citationsByAddress[name])
// console.log(citation)
- return
- }
- // console.log(citation)
- citation.addresses.forEach(address => {
- if (!(address.name in citationsByAddress)) {
- citationsByAddress[address.name] = { address, citations: []}
+ const latlng = [address.lat, address.lng].map(n => parseFloat(n))
+ if (Number.isNaN(latlng[0]) || Number.isNaN(latlng[1])) return
+ this.addMarker(latlng, citationList)
+ const style = { ...arcStyles[address.type] }
+ let weight = Math.min(citationList.length, 5)
+ let opacity = 0.5 + Math.min(citationList.length / 5, 0.5)
+ if (address.type !== 'edu') {
+ weight += 1
+ opacity = 1
}
- citationsByAddress[address.name].citations.push(citation)
+ style.weight = String(weight)
+ style.opacity = opacity
+ this.addArc(this.source, latlng, style)
})
- })
- Object.keys(citationsByAddress).map(name => {
- const { citations: citationList, address: citationAddress } = citationsByAddress[name]
- // console.log(name, citationsByAddress[name])
- // console.log(citation)
- const latlng = [citationAddress.lat, citationAddress.lng].map(n => parseFloat(n))
- if (Number.isNaN(latlng[0]) || Number.isNaN(latlng[1])) return
- addMarker(map, latlng, citationList)
- const style = { ...arcStyles[citationAddress.type] }
- let weight = Math.min(citationList.length, 5)
- let opacity = 0.5 + Math.min(citationList.length / 5, 0.5)
- if (citationAddress.type !== 'edu') {
- weight += 1
- opacity = 1
- }
- style.weight = String(weight)
- style.opacity = opacity
- addArc(map, source, latlng, style)
- })
-
- // console.log(paper)
+ this.rootMarker = this.addMarker(this.source, [this.paper])
+ }
- const rootMarker = addMarker(map, source, [paper])
- rootMarker.openPopup()
+ addMarker(latlng, citations) {
+ const marker = L.marker(latlng, { icon: redDot }).addTo(this.map)
+ let message = citations.map(citation => {
+ const { title, addresses, year, pdf, doi } = citation
+ let rec = [
+ "<b>", title, "</b>",
+ ]
+ if (pdf && pdf.length) {
+ rec.unshift("<a href='" + pdf[0] + "' target='_blank'>")
+ rec.push("</a>")
+ }
+ else if (doi && doi.length) {
+ rec.unshift("<a href='" + doi[0] + "' target='_blank'>")
+ rec.push("</a>")
+ }
+ if (year) {
+ rec.push(" (" + year + ")")
+ }
+ const addressString = addresses.map(addr => addr.name).join('<br/>')
+ rec.push("<br>")
+ rec.push(addressString)
+ return rec.join("")
+ })
- // a transparent div to cover the map, so normal scroll events will not be eaten by leaflet
- const mapCover = document.createElement("div")
- mapCover.classList.add("map_cover")
- mapCover.innerHTML = "<div class='cover_message'>Click here to explore the map</div>"
- mapCover.querySelector('div').addEventListener('click', () => {
- map.scrollWheelZoom.enable()
- if (mapCover.parentNode === el) {
- el.removeChild(mapCover)
- }
- })
- mapCover.querySelector('div').addEventListener('touchstart', (e) => {
- e.preventDefault()
- })
- mapCover.querySelector('div').addEventListener('tap', () => {
- map.scrollWheelZoom.enable()
- if (mapCover.parentNode === el) {
- el.removeChild(mapCover)
- }
- })
- function stopPropagation(e) {
- e.stopPropagation()
+ marker.bindPopup(message.join('<br><br>'))
+ this.markers.push(marker)
+ return marker
}
- mapCover.addEventListener('mousewheel', stopPropagation, true)
- mapCover.addEventListener('DOMMouseScroll', stopPropagation, true)
- map.scrollWheelZoom.disable()
- map.on('focus', () => {
- map.scrollWheelZoom.enable()
- if (mapCover.parentNode === el) {
- el.removeChild(mapCover)
- }
- })
- map.on('blur', () => {
- map.scrollWheelZoom.disable()
- // el.appendChild(mapCover)
- })
+ addArc(src, dest, arcStyle) {
+ const arc = L.bezier({
+ path: [
+ [
+ { lat: src[0], lng: src[1] },
+ { lat: dest[0], lng: dest[1] },
+ ],
+ ]
+ }, arcStyle).addTo(this.map)
+ this.arcs.push(arc)
+ }
+}
- el.appendChild(mapCover)
+export default function append(el, payload) {
+ const { data } = payload
+ if (!data) return
+ let mapContainer = new Map(el, data)
+ return mapContainer
}
diff --git a/client/table/citations.table.js b/client/table/citations.table.js
index 178cc65b..8fe46b69 100644
--- a/client/table/citations.table.js
+++ b/client/table/citations.table.js
@@ -24,18 +24,20 @@ class CitationsTable extends Component {
filteredCitations: [],
}
- componentDidMount(){
+ componentDidMount() {
this.updateCitations()
}
- componentDidUpdate(oldProps){
+
+ componentDidUpdate(oldProps) {
if (this.props.payload.data.citations !== oldProps.payload.data.citations) {
this.updateCitations()
}
}
- updateCitations(){
+
+ updateCitations() {
const { paper, citations } = this.props.payload.data
if (!citations.length) this.setState({ formattedCitations: [] })
- console.log(citations.filter(a => a.title.match('Coarse')))
+ // console.log(citations.filter(a => a.title.match('Coarse')))
const formattedCitations = citations.sort((a,b) => a.title.localeCompare(b.title)).map(citation => {
const pdf_link = (citation.pdf && citation.pdf.length)
? citation.pdf[0]