diff options
| -rw-r--r-- | client/chart/constants.js | 45 | ||||
| -rw-r--r-- | client/chart/singlePie.chart.js | 22 | ||||
| -rw-r--r-- | client/index.js | 9 | ||||
| -rw-r--r-- | client/table/citations.table.js | 6 | ||||
| -rw-r--r-- | client/table/file.table.js | 60 | ||||
| -rw-r--r-- | client/table/tabulator.css | 12 | ||||
| -rw-r--r-- | site/content/_drafts_/lfw/index.md | 2 | ||||
| -rw-r--r-- | site/content/pages/research/_introduction/index.md | 2 | ||||
| -rw-r--r-- | site/content/pages/research/munich_security_conference/index.md | 4 | ||||
| -rw-r--r-- | site/content/pages/test/csv.md | 2 |
10 files changed, 112 insertions, 52 deletions
diff --git a/client/chart/constants.js b/client/chart/constants.js index 6fe94433..0f23f06b 100644 --- a/client/chart/constants.js +++ b/client/chart/constants.js @@ -48,12 +48,35 @@ export const colorblindSafeRainbow = [ // '#888888', ] +export const categoryRainbow = [ + '#5e4fa2', + '#66c2a5', + '#d53e4f', + '#f46d43', + '#9e0142', + '#3288bd', + '#fee08b', + '#abdda4', + '#e6f598', + '#fdae61', + '#ffffbf', + // '#888888', +] + export const institutionColors = [ '#f2f293', // edu (yellow) '#3264f6', // company (blue) '#f30000', // gov/mil (red) ] +export const colorTable = { + rainbow, + bigRainbow, + colorblindSafeRainbow, + institutionColors, + categoryRainbow, +} + /* stuff for a 'countries' legend */ export const topCountryCount = 10 @@ -63,20 +86,20 @@ export const otherCountriesLabel = 'Other Countries' /* institution tuples, labels and templates */ export const initialInstitutionLookup = { - 'edu': 0, - 'company': 0, - 'gov': 0, + edu: 0, + company: 0, + gov: 0, } export const institutionOrder = { - 'edu': 0, - 'company': 1, - 'gov': 2, + edu: 0, + company: 1, + gov: 2, } export const institutionLabels = { - 'edu': 'Academic', - 'company': 'Commercial', - 'gov': 'Military / Government', - 'mil': 'Military / Government', -}
\ No newline at end of file + edu: 'Academic', + company: 'Commercial', + gov: 'Military / Government', + mil: 'Military / Government', +} diff --git a/client/chart/singlePie.chart.js b/client/chart/singlePie.chart.js index ed2da582..2e770bd7 100644 --- a/client/chart/singlePie.chart.js +++ b/client/chart/singlePie.chart.js @@ -6,33 +6,24 @@ import 'c3/c3.css' import './chart.css' import { - rainbow, bigRainbow + rainbow, bigRainbow, colorTable } from './constants' class SinglePieChart extends Component { state = { keys: [], data: [], - fields: {}, } componentDidMount() { const { payload } = this.props - console.log(payload) - console.log(payload.fields) - const fields = {} - payload.fields.forEach(field => { - const [k, v] = field.split(': ') - fields[k] = v - }) - fetch(payload.url, { mode: 'cors' }) .then(r => r.text()) .then(text => { try { const keys = text.split('\n')[0].split(',').map(s => s.trim().replace(/"/, '')) const data = csv.toJSON(text, { headers: { included: true } }) - this.setState({ keys, data, fields }) + this.setState({ keys, data }) } catch (e) { console.error("error making json:", payload.url) console.error(e) @@ -41,8 +32,9 @@ class SinglePieChart extends Component { } render() { - const { keys, data, fields } = this.state - console.log(keys, data) + const { fields } = this.props.payload + const { keys, data } = this.state + // console.log(keys, data) const [labelField, numberField] = keys if (!data.length) return null @@ -63,6 +55,8 @@ class SinglePieChart extends Component { const height = chartRows.length < 6 ? 316 : chartRows.length < 10 ? 336 : 356 + const pattern = colorTable[fields.Colors] || (chartRows.length < 10 ? rainbow : bigRainbow) + return ( <div className='chart'> <div> @@ -72,7 +66,7 @@ class SinglePieChart extends Component { type: 'pie', }} color={{ - pattern: chartRows.length < 10 ? rainbow : bigRainbow, + pattern, }} tooltip={{ format: { diff --git a/client/index.js b/client/index.js index 835d859c..9644ba5c 100644 --- a/client/index.js +++ b/client/index.js @@ -73,6 +73,15 @@ function runApplets() { let opt = null payload.cmd = cmd payload.partz = cmdPartz + const fields = {} + if (payload.fields) { + payload.fields.forEach(field => { + const [k, v] = field.split(': ') + fields[k] = v + }) + } + payload.fields = fields + if (payload.cmd === 'load_file' || payload.cmd === 'single_pie_chart') { payload.url = 'https://nyc3.digitaloceanspaces.com/megapixels/v1' + cmdPartz.shift() return [el, payload] diff --git a/client/table/citations.table.js b/client/table/citations.table.js index ef5ab0b5..c1c71906 100644 --- a/client/table/citations.table.js +++ b/client/table/citations.table.js @@ -1,11 +1,9 @@ import React, { Component } from 'react' -import { bindActionCreators } from 'redux' -import { connect } from 'react-redux' import { ReactTabulator } from 'react-tabulator' import { saveAs } from 'file-saver' import { Loader } from '../common' -import { toArray, toTuples, domainFromUrl } from '../util' +import { domainFromUrl } from '../util' export const citationsColumns = [ { title: 'Title', field: 'title', sorter: 'string' }, @@ -111,7 +109,7 @@ class CitationsTable extends Component { value={this.state.q} onChange={e => this.updateFilter(e.target.value)} className='q' - placeholder='Enter text to search citations...' + placeholder='Enter text to search citations' /> <span className='download' onClick={() => this.download()}>Download CSV</span> </div> diff --git a/client/table/file.table.js b/client/table/file.table.js index c880810a..c195b09d 100644 --- a/client/table/file.table.js +++ b/client/table/file.table.js @@ -1,17 +1,17 @@ import React, { Component } from 'react' -import { bindActionCreators } from 'redux' -import { connect } from 'react-redux' import { ReactTabulator } from 'react-tabulator' import csv from 'parse-csv' -import { toArray, toTuples, domainFromUrl } from '../util' +import { domainFromUrl } from '../util' import { Loader } from '../common' class FileTable extends Component { state = { keys: [], data: [], + filteredData: [], columns: [], + q: '', } componentDidMount() { @@ -25,7 +25,7 @@ class FileTable extends Component { const data = csv.toJSON(text, { headers: { included: true } }) // console.log(data) const columns = this.getColumns(keys, data, payload.fields) - this.setState({ keys, data, columns }) + this.setState({ keys, data, filteredData: data, columns }) } catch (e) { console.error("error making json:", payload.url) console.error(e) @@ -34,10 +34,11 @@ class FileTable extends Component { } getColumns(keys, data, fields) { - let titles = fields.length ? fields[0].split(', ') : keys + let titles = fields.Headings ? fields.Headings.split(', ') : keys // let numberFields = [] let columns = keys.map((field, i) => { const title = titles[i] || field + let widthGrow = 1 if (field.match('url')) { let textField = field.replace('url', 'label') data.forEach(el => el[textField] = domainFromUrl(el[field])) @@ -49,31 +50,60 @@ class FileTable extends Component { sorter: 'string' } } + if (title === 'Embassy') { + widthGrow = 2 + } switch (field) { case 'images': case 'year': return { title, field: field.toLowerCase(), sorter: 'number' } default: - return { title, field: field.toLowerCase(), sorter: 'string' } + return { title, field: field.toLowerCase(), sorter: 'string', widthGrow } } }) return columns } + updateFilter(q) { + const { keys, data } = this.state + if (!q.length) { + this.setState({ q, filteredData: data }) + } else { + let qRe = new RegExp('(' + q.replace(/\s+/g, ' ').trim().replace(' ', '|') + ')', 'gi') + let filteredData = data.filter(row => keys.some(key => row[key].match(qRe))) + this.setState({ q, filteredData }) + } + } + render() { + const { payload } = this.props + const { q, columns, data, filteredData } = this.state if (!this.state.data.length) { return <Loader /> } + const fn = payload.url.split('/').pop() return ( - <ReactTabulator - columns={this.state.columns} - data={this.state.data} - options={{ - height: Math.min(37 * this.state.data.length + 29, 311), - layout: 'fitColumns', - placeholder: 'No Data Set', - }} - /> + <div className='citationBrowser'> + <div className='citationHeader'> + <input + type="text" + value={q} + onChange={e => this.updateFilter(e.target.value)} + className='q' + placeholder='Enter text to search data' + /> + <a className='download' href={payload.url} filename={fn}>Download CSV</a> + </div> + <ReactTabulator + columns={columns} + data={filteredData} + options={{ + height: Math.min(37 * data.length + 29, 311), + layout: 'fitColumns', + placeholder: 'No Data Set', + }} + /> + </div> ) } } diff --git a/client/table/tabulator.css b/client/table/tabulator.css index 95768976..0ea81974 100644 --- a/client/table/tabulator.css +++ b/client/table/tabulator.css @@ -40,7 +40,7 @@ max-width: 400px; margin-bottom: 10px; background-image: url(/assets/img/icon-search.png); - background-position: 380px center; + background-position: 378px center; background-repeat: no-repeat; box-shadow: 0px 2px 4px rgba(0,0,0,0.2); border: 0; @@ -53,17 +53,21 @@ align-items: flex-start; justify-content: space-between; } -span.download { +.download { display: block; font-size: 13px; color: #ddd; cursor: pointer; background: #333; - padding: 5px 8px; + padding: 5px 8px 5px 8px; border-radius: 5px; transition: all 0.2s; + border: 0 !important; } -.desktop span.download:hover { +.content a.download { + padding: 5px 8px 5px 8px; +} +.desktop .download:hover { color: #fff; background: #666; }
\ No newline at end of file diff --git a/site/content/_drafts_/lfw/index.md b/site/content/_drafts_/lfw/index.md index ad43e2dd..a5d6bd18 100644 --- a/site/content/_drafts_/lfw/index.md +++ b/site/content/_drafts_/lfw/index.md @@ -54,7 +54,7 @@ Add a paragraph about how usage extends far beyond academia into research center ``` load_file assets/lfw_commercial_use.csv -name_display, company_url, example_url, country, description +Headings: name_display, company_url, example_url, country, description ``` diff --git a/site/content/pages/research/_introduction/index.md b/site/content/pages/research/_introduction/index.md index 7e839fe7..bdf1c1b0 100644 --- a/site/content/pages/research/_introduction/index.md +++ b/site/content/pages/research/_introduction/index.md @@ -37,7 +37,7 @@ Add info from the AI Traps talk ``` load_file /site/research/00_introduction/assets/summary_countries_top.csv -country, Xcitations +Headings: country, Xcitations ``` Paragraph text to test css formatting. Paragraph text to test css formatting. Paragraph text to test css formatting. Paragraph text to test css formatting. Paragraph text to test css formatting. diff --git a/site/content/pages/research/munich_security_conference/index.md b/site/content/pages/research/munich_security_conference/index.md index 6a1b84e9..3c4d7f08 100644 --- a/site/content/pages/research/munich_security_conference/index.md +++ b/site/content/pages/research/munich_security_conference/index.md @@ -115,6 +115,7 @@ single_pie_chart /site/research/munich_security_conference/assets/megapixels_ori Caption: Sources of Face Training Data Top: 5 OtherLabel: Other Countries +Colors: categoryRainbow ``` =========== @@ -124,6 +125,7 @@ single_pie_chart /site/research/munich_security_conference/assets/embassy_counts Caption: Dataset sources Top: 4 OtherLabel: Other +Colors: categoryRainbow ``` === end columns @@ -134,7 +136,7 @@ OtherLabel: Other ``` load_file /site/research/munich_security_conference/assets/embassy_counts_public.csv -Images, Dataset, Embassy, Flickr ID, URL, Guest, Host +Headings: Images, Dataset, Embassy, Flickr ID, URL, Guest, Host ``` diff --git a/site/content/pages/test/csv.md b/site/content/pages/test/csv.md index 85f714b4..ef3327f8 100644 --- a/site/content/pages/test/csv.md +++ b/site/content/pages/test/csv.md @@ -16,5 +16,5 @@ authors: Megapixels ``` load_file /site/test/assets/test.csv -Name, Images, Year, Gender, Description, URL +Headings: Name, Images, Year, Gender, Description, URL ``` |
