diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2019-02-13 21:21:20 +0100 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2019-02-13 21:21:20 +0100 |
| commit | 21d179c762d87e0790206fe59b08ffd49bb4a53b (patch) | |
| tree | 2e1183aec6a34cd85e3358e7240a5aa1731e5d6d /scraper | |
| parent | 5c176ce457f195dfad15d0c7d01d36fc2f9fdbdd (diff) | |
autocompleting
Diffstat (limited to 'scraper')
| -rw-r--r-- | scraper/client/common/autocomplete.component.js | 118 | ||||
| -rw-r--r-- | scraper/client/common/autocomplete.css | 39 | ||||
| -rw-r--r-- | scraper/client/common/common.css | 2 | ||||
| -rw-r--r-- | scraper/client/common/index.js | 1 | ||||
| -rw-r--r-- | scraper/client/paper/paper.address.js | 110 | ||||
| -rw-r--r-- | scraper/client/paper/paper.css | 15 | ||||
| -rw-r--r-- | scraper/reports/geocode_papers.html | 26 |
7 files changed, 215 insertions, 96 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 diff --git a/scraper/reports/geocode_papers.html b/scraper/reports/geocode_papers.html index 84ffe356..2dca6e45 100644 --- a/scraper/reports/geocode_papers.html +++ b/scraper/reports/geocode_papers.html @@ -2,32 +2,6 @@ <html> <head> <title>Geocode PDFs</title> -<style> -html,body { margin: 0; padding: 0; width: 100%; height: 100%; } -.autocomplete div { - background: white; -} -.autocomplete .matches { - border: 1px solid #888; - max-height: 220px; - overflow-y: auto; -} -.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; -} -</style> </head> <body> <div id="container"> |
