Skip to content

Commit

Permalink
Merge pull request #209 from LD4P/input-lookup
Browse files Browse the repository at this point in the history
Adds Input lookup component
  • Loading branch information
ndushay committed Dec 4, 2018
2 parents 569f4c4 + c509512 commit b01e480
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 4 deletions.
3 changes: 1 addition & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ module.exports = {
"jsx-a11y/label-has-for": "warn", // see #173
"no-console": "warn",
"no-extra-semi": "off", // because it isn't that important
"react/prop-types": "warn", // see #175
"jsx-a11y/no-onchange": "warn"
"react/prop-types": "warn" // see #175
},
overrides: [
{
Expand Down
54 changes: 54 additions & 0 deletions __tests__/components/editor/InputLookup.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2018 Stanford University see Apache2.txt for license
import React from 'react'
import { shallow } from 'enzyme'
import InputLookup from '../../../src/components/editor/InputLookup'

const plProps = {
"propertyTemplate":
{
"mandatory": "false",
"repeatable": "true",
"type": "lookup",
"resourceTemplates": [],
"valueConstraint": {
"valueTemplateRefs": [],
"useValuesFrom": [
'lookupQaLocNames'
],
"valueDataType": {
"dataTypeURI": "http://id.loc.gov/ontologies/bibframe/Agent"
},
"defaults": []
},
"propertyURI": "http://id.loc.gov/ontologies/bflc/target",
"propertyLabel": "Name Lookup"
}
}

describe('<InputLookup />', () => {
const wrapper = shallow(<InputLookup {...plProps} />)

it('uses the propertyLabel from the template as the form control label', () => {
expect(wrapper.find('label').text()).toMatch('Name Lookup')
})

it('sets the typeahead component required attribute according to the mandatory property from the template', () => {
expect(wrapper.find('#lookupComponent').props().required).toBeFalsy()
})

it('sets the typeahead component multiple attribute according to the repeatable property from the template', () => {
expect(wrapper.find('#lookupComponent').props().multiple).toBeTruthy()
})

it('sets the typeahead component placeholder attribute to be the propertyLabel', () => {
expect(wrapper.find('#lookupComponent').props().placeholder).toBe('Name Lookup')
})

it('should call the onChange event and set the state with the selected option', () => {
const event = (wrap) => {
wrap.setState({options: ["{uri: 'URI', label: 'LABEL'}"]})
}
wrapper.find('#lookupComponent').simulate('change', event(wrapper))
expect(wrapper.state().options[0]).toBe("{uri: 'URI', label: 'LABEL'}")
})
})
12 changes: 12 additions & 0 deletions __tests__/components/editor/InputResource.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,16 @@ describe('<InputResource />', () => {
it('sets the typeahead component multiple attribute according to the repeatable value from the template', () => {
expect(wrapper.find('#targetComponent').props().multiple).toBe(true)
})

it('sets the typeahead component placeholder attribute', () => {
expect(wrapper.find('#targetComponent').props().placeholder).toMatch('Frequency (RDA 2.14)')
})

it('should call the onChange event and set the state with the selected option', () => {
const event = (wrap) => {
wrap.setState({options: ["{uri: 'URI', label: 'LABEL'}"]})
}
wrapper.find('#targetComponent').simulate('change', event(wrapper))
expect(wrapper.state().options[0]).toBe("{uri: 'URI', label: 'LABEL'}")
})
})
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import React, { Component } from 'react'
import { hot } from 'react-hot-loader'
import 'react-bootstrap-typeahead/css/Typeahead.css'
import HomePage from './HomePage'
import '../styles/main.css'
import Editor from './editor/Editor'
Expand Down
65 changes: 65 additions & 0 deletions src/components/editor/InputLookup.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2018 Stanford University see Apache2.txt for license
import React, {Component} from 'react'
import {asyncContainer, Typeahead} from 'react-bootstrap-typeahead'
import PropTypes from 'prop-types'

const AsyncTypeahead = asyncContainer(Typeahead)

class InputLookup extends Component {
constructor(props) {
super(props)
this.state = {
isLoading: true
}
}

render() {
const lookup_url = this.props.propertyTemplate.valueConstraint.useValuesFrom[0]
const isRequired = JSON.parse(this.props.propertyTemplate.mandatory)
const isRepeatable = JSON.parse(this.props.propertyTemplate.repeatable)

return (
<div>
<label htmlFor="lookupComponent">{this.props.propertyTemplate.propertyLabel}
<AsyncTypeahead
id="lookupComponent"
required={isRequired}
multiple={isRepeatable}
placeholder={this.props.propertyTemplate.propertyLabel}
useCache={true}
isLoading={this.state.isLoading}
onSearch={query => {
this.setState({isLoading: true});
//TODO: this fetch function will be replaced with a swagger API call function (#197):
fetch(`${lookup_url}?q=${query}&maxRecords=6`)
.then(resp => resp.json())
.then(json => this.setState({
isLoading: false,
options: json
}))
}}
onChange={selected => {
this.setState({selected})
}
}
options={this.state.options}
selected={this.state.selected}
/>
</label>
</div>
)
}
}

InputLookup.propTypes = {
propertyTemplate: PropTypes.shape({
propertyLabel: PropTypes.string,
mandatory: PropTypes.oneOfType([ PropTypes.string, PropTypes.bool]),
repeatable: PropTypes.oneOfType([ PropTypes.string, PropTypes.bool]),
valueConstraint: PropTypes.shape({
useValuesFrom: PropTypes.oneOfType([ PropTypes.string, PropTypes.array])
})
}).isRequired
}

export default InputLookup
5 changes: 4 additions & 1 deletion src/components/editor/ResourceTemplateForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ButtonGroup from 'react-bootstrap/lib/ButtonGroup'
import ButtonToolbar from 'react-bootstrap/lib/ButtonToolbar'
import InputLiteral from './InputLiteral'
import InputResource from './InputResource'
import InputLookup from './InputLookup'
import ModalToggle from './ModalToggle'
const { getResourceTemplate } = require('../../sinopiaServerSpoof.js')

Expand Down Expand Up @@ -77,7 +78,9 @@ class ResourceTemplateForm extends Component {
}
}
else if (pt.type == 'lookup'){
return (<p key={index}><b>{pt.propertyLabel}</b>: <i>lookup</i> type</p>)
return(
<InputLookup propertyTemplate = {pt} key = {index} />
)
}
})}
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,6 @@ a.editor-help-resources {
font-size: 1.3em;
color: #2F2424;
}
input.rbt-input-main {
min-width: 300px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,24 @@
"mandatory": "false",
"remark": "http://access.rdatoolkit.org/3.3.html"
},
{
"mandatory": "false",
"repeatable": "true",
"type": "lookup",
"resourceTemplates": [],
"valueConstraint": {
"valueTemplateRefs": [],
"useValuesFrom": [
"https://lookup.ld4l.org/authorities/search/linked_data/locnames_ld4l_cache/person"
],
"valueDataType": {
"dataTypeURI": "http://id.loc.gov/ontologies/bibframe/Agent"
},
"defaults": []
},
"propertyURI": "http://id.loc.gov/ontologies/bflc/target",
"propertyLabel": "LOC Names: locnames_ld4l_cache/person"
},
{
"propertyURI": "http://id.loc.gov/ontologies/bflc/target",
"propertyLabel": "Frequency (RDA 2.14)",
Expand Down

0 comments on commit b01e480

Please sign in to comment.