summaryrefslogtreecommitdiff
path: root/scraper/client
diff options
context:
space:
mode:
Diffstat (limited to 'scraper/client')
-rw-r--r--scraper/client/common/autocomplete.component.js118
-rw-r--r--scraper/client/common/autocomplete.css39
-rw-r--r--scraper/client/common/common.css2
-rw-r--r--scraper/client/common/index.js1
-rw-r--r--scraper/client/paper/paper.address.js110
-rw-r--r--scraper/client/paper/paper.css15
6 files changed, 215 insertions, 70 deletions
diff --git a/scraper/client/common/autocomplete.component.js b/scraper/client/common/autocomplete.component.js
index 12419cf1..03039b1c 100644
--- a/scraper/client/common/autocomplete.component.js
+++ b/scraper/client/common/autocomplete.component.js
@@ -47,29 +47,33 @@ class Autocomplete extends Component {
this.handleCancel = this.handleCancel.bind(this)
}
- componentWillMount() {
+ componentDidMount() {
// build index based on what's in the hierarchy
- const { nodes } = this.props.hierarchy
+ const { entities, lookup } = this.props.institutions
let index = []
this.index = index
- Object.keys(nodes).forEach(key => {
- const node = nodes[key]
- if (!key || !node || !node.name || !node.parent) return
- let { name } = node
- let prefixName = name
- if (node.is_attribute) {
- const parent = nodes[node.parent]
- if (parent) {
- prefixName = parent.name + " (" + name + ")"
- }
- }
- index.push([sanitizeForAutocomplete(prefixName), name, node.id])
- node.synonyms
- .split("\n")
- .map(word => word = word.trim())
- .filter(word => !!word)
- .forEach(word => index.push([prefixName, name, node.id]))
+ Object.keys(entities).forEach(name => {
+ if (!name) return
+ index.push([sanitizeForAutocomplete(name), name])
+ })
+ Object.keys(lookup).forEach(name => {
+ if (!name) return
+ index.push([sanitizeForAutocomplete(name), lookup[name]])
})
+ // console.log(index)
+ // node.synonyms
+ // .split("\n")
+ // .map(word => word = word.trim())
+ // .filter(word => !!word)
+ // .forEach(word => index.push([prefixName, name, node.id]))
+ }
+
+ componentDidUpdate(oldProps) {
+ if (this.props.vetting !== oldProps.vetting) {
+ this.handleChange({ target: { value: this.props.vetting }})
+ } else if (this.props.value !== oldProps.value) {
+ this.handleChange({ target: { value: this.props.value }})
+ }
}
handleKeyDown(e) {
@@ -101,6 +105,7 @@ class Autocomplete extends Component {
default:
break
}
+ return null
}
handleChange(e) {
@@ -115,31 +120,42 @@ class Autocomplete extends Component {
})
return
}
- const re = new RegExp(value)
- let matches = []
let seen = {}
- this.index.forEach(pair => {
- if (seen[pair[2]]) return
- if (pair[0].match(re)) {
- seen[pair[2]] = true
- if (pair[1].indexOf(value) === 0) {
- matches.unshift(pair[2])
- } else {
- matches.push(pair[2])
+ let matches = []
+ value.split(' ').forEach(word => {
+ const re = new RegExp(word)
+ this.index.forEach(([synonym, term]) => {
+ if (synonym.match(re)) {
+ if (synonym.indexOf(value) === 0) {
+ if (term in seen) {
+ seen[term] += 4
+ } else {
+ seen[term] = 4
+ }
+ } else if (term in seen) {
+ seen[term] += 1
+ } else {
+ seen[term] = 1
+ }
}
- }
+ })
+ matches = Object.keys(seen)
+ .map(term => [seen[term], term])
+ .sort((a, b) => {
+ return b[0] - a[0]
+ })
+ .slice(0, 100)
+ .map(pair => pair[1])
})
this.setState({
q,
selected: 0,
- matches: matches.slice(0, 10),
+ matches,
})
}
- handleSelect(id) {
- const { nodes } = this.props.hierarchy
- const node = nodes[id]
- if (this.props.onSelect) this.props.onSelect(node)
+ handleSelect(name) {
+ if (this.props.onSelect) this.props.onSelect(name)
this.setState({ q: "", selected: 0, matches: [] })
}
@@ -149,28 +165,14 @@ class Autocomplete extends Component {
}
render() {
- // const suggestions = this.state.suggestions.map((suggestion))
- const { nodes } = this.props.hierarchy
const { q, selected } = this.state
const matches = this.state.matches.map((match, i) => {
- const node = nodes[match]
- const parent = nodes[node.parent]
- let label
- if (node.is_attribute) {
- label = (
- <span>
- {formatLabel(parent.name, q)}
- {' '}<small>{'('}{formatLabel(node.name, q)}{')'}</small>
- </span>
- )
- } else {
- label = formatLabel(node.name, q)
- }
+ const label = formatLabel(match, q)
return (
<div
key={i}
className={selected === i ? 'selected' : ''}
- onClick={() => this.handleSelect(node.id)}
+ onClick={() => this.handleSelect(match)}
onMouseEnter={() => this.setState({ selected: i })}
>
{label}
@@ -185,14 +187,17 @@ class Autocomplete extends Component {
value={this.state.q}
onKeyDown={this.handleKeyDown}
onChange={this.handleChange}
- autoFocus
+ autoFocus={this.props.autoFocus}
autoCapitalize="off"
autoComplete="off"
- placeholder="Start typing a name"
+ placeholder={this.props.placeholder}
+ ref={ref => this._el = ref}
/>
- <div className="matches">
- {matches}
- </div>
+ {!!matches.length &&
+ <div className="matches">
+ {matches}
+ </div>
+ }
</div>
)
}
@@ -200,6 +205,7 @@ class Autocomplete extends Component {
const mapStateToProps = (state, ownProps) => ({
onSelect: ownProps.onSelect,
+ institutions: state.api.institutions,
})
const mapDispatchToProps = (dispatch) => ({
diff --git a/scraper/client/common/autocomplete.css b/scraper/client/common/autocomplete.css
new file mode 100644
index 00000000..ac90ea72
--- /dev/null
+++ b/scraper/client/common/autocomplete.css
@@ -0,0 +1,39 @@
+.autocomplete {
+ position: relative;
+ margin-bottom: 4px;
+}
+.autocomplete input[type=text],
+.autocomplete .matches {
+ width: 400px;
+}
+.autocomplete div {
+ background: white;
+ cursor: pointer;
+}
+.autocomplete .matches {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ border: 1px solid #888;
+ max-height: 220px;
+ overflow-y: auto;
+ z-index: 1;
+}
+.autocomplete .matches div {
+ padding: 3px;
+}
+.autocomplete .matches div:nth-child(even) {
+ background: #eee;
+}
+.autocomplete .matches div:nth-child(odd) {
+ background: #fff;
+}
+.autocomplete .matches div:nth-child(even).selected,
+.autocomplete .matches div:nth-child(odd).selected {
+ color: #fff;
+ background: #000;
+ cursor: pointer;
+}
+.autocomplete .selected {
+ background: rgba(128,128,128,0.2);
+} \ No newline at end of file
diff --git a/scraper/client/common/common.css b/scraper/client/common/common.css
index b014541a..fb31aefb 100644
--- a/scraper/client/common/common.css
+++ b/scraper/client/common/common.css
@@ -7,7 +7,7 @@ html,body {
}
body {
font-family: Helvetica, sans-serif;
- font-weight: 300;
+ color: #333;
}
h1 {
diff --git a/scraper/client/common/index.js b/scraper/client/common/index.js
index 8ced56b3..8925aae0 100644
--- a/scraper/client/common/index.js
+++ b/scraper/client/common/index.js
@@ -5,6 +5,7 @@ import Gate from './gate.component'
import Autocomplete from './autocomplete.component'
import { TableObject, TableArray, TableTuples, TableRow, TableCell } from './table.component'
import './common.css'
+import './autocomplete.css'
export {
Header,
diff --git a/scraper/client/paper/paper.address.js b/scraper/client/paper/paper.address.js
index 6d02c3db..0da353c9 100644
--- a/scraper/client/paper/paper.address.js
+++ b/scraper/client/paper/paper.address.js
@@ -49,7 +49,7 @@ class PaperAddress extends Component {
citation,
})
} else {
- console.log(paper)
+ // console.log(paper)
const citation = this.getCitation(sha256)
this.setState({
citation,
@@ -71,29 +71,115 @@ class PaperAddress extends Component {
if (!citation) {
citation = (paperInfo.citations || []).find(f => f.id === sha256)
}
- console.log(sha256, citation)
+ // console.log(sha256, citation)
return citation
}
+ save() {
+ console.log(this.state)
+ }
+
render() {
- // if (!this.props.match.params.key) return null
- // if (this.props.api.address.loading) return <Loader />
- // if (!this.props.api.paperInfo.dataset) return <div className='paperInfo'>Metadata not found</div>
- let { paperInfo, unknownCitations } = this.props.api
- if (paperInfo.loading || unknownCitations.loading) return <Loader />
+ let { institutions, paperInfo, unknownCitations } = this.props.api
+ if (institutions.loading || paperInfo.loading || unknownCitations.loading) return <Loader />
console.log(this.state)
+ console.log(institutions)
const { citation } = this.state
if (!citation) {
return <div>Citation not found in this paper</div>
- }
+ }console.log(this)
return (
<div className='form'>
<h3>{citation.title}</h3>
<div className='gray'>{citation.id}</div>
- {this.state.institution_1}
- {/*
- <iframe className='pdfViewer' src={citation.pdf} />
- */}
+
+ <div className='param'>
+ <input
+ className='vetting'
+ type='text'
+ placeholder='Paste Institution #1'
+ onChange={e => this.setState({
+ institution_1_vetting: e.target.value,
+ })}
+ />
+ <Autocomplete
+ autoFocus
+ placeholder='Institution #1'
+ value={this.state.institution_1}
+ vetting={this.state.institution_1_vetting}
+ onSelect={value => {
+ this.setState({ institution_1: value })
+ // this.institution_2._el.focus()
+ }}
+ ref={ref => this.institution_1 = ref}
+ />
+ </div>
+
+ <div className='param'>
+ <input
+ className='vetting'
+ type='text'
+ placeholder='Paste Institution #2'
+ onChange={e => this.setState({
+ institution_2_vetting: e.target.value,
+ })}
+ />
+ <Autocomplete
+ placeholder='Institution #2'
+ value={this.state.institution_2}
+ onSelect={value => {
+ this.setState({ institution_2: value })
+ }}
+ ref={ref => this.institution_2 = ref}
+ />
+ </div>
+
+ <div className='param'>
+ <input
+ className='vetting'
+ type='text'
+ placeholder='Paste Institution #3'
+ onChange={e => this.setState({
+ institution_3_vetting: e.target.value,
+ })}
+ />
+ <Autocomplete
+ placeholder='Institution #3'
+ value={this.state.institution_3}
+ onSelect={value => {
+ this.setState({ institution_3: value })
+ // this.institution_4._el.focus()
+ }}
+ ref={ref => this.institution_3 = ref}
+ />
+ </div>
+
+ <div className='param'>
+ <input
+ className='vetting'
+ type='text'
+ placeholder='Paste Institution #4'
+ onChange={e => this.setState({
+ institution_4_vetting: e.target.value,
+ })}
+ />
+ <Autocomplete
+ placeholder='Institution #4'
+ value={this.state.institution_4}
+ onSelect={value => {
+ this.setState({ institution_4: value })
+ this.button.focus()
+ }}
+ ref={ref => this.institution_4 = ref}
+ />
+ </div>
+
+ <button
+ className='btn btn-primary'
+ onClick={this.save.bind(this)}
+ ref={ref => this.button = ref}
+ >Save Institutions</button>
+ <iframe className='pdfViewer' src={citation.pdf} />
</div>
)
}
diff --git a/scraper/client/paper/paper.css b/scraper/client/paper/paper.css
index 0977dcb3..c10d21df 100644
--- a/scraper/client/paper/paper.css
+++ b/scraper/client/paper/paper.css
@@ -18,12 +18,25 @@
.type {
color: #888;
}
+
.gray {
padding: 3px;
}
+
+.param {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: flex-start;
+}
+.vetting {
+ width: 250px;
+ margin-right: 10px;
+}
+
iframe.pdfViewer {
margin: 10px 0;
width: 100%;
- height: 50vh;
+ height: 75vh;
border: 1px solid black;
} \ No newline at end of file