diff --git a/__tests__/components/editor/InputLookupQA.test.js b/__tests__/components/editor/InputLookupQA.test.js
index 8e071e337..00a798312 100644
--- a/__tests__/components/editor/InputLookupQA.test.js
+++ b/__tests__/components/editor/InputLookupQA.test.js
@@ -1,6 +1,8 @@
// Copyright 2018 Stanford University see Apache2.txt for license
+import 'jsdom-global/register'
import React from 'react'
import { shallow } from 'enzyme'
+import { mount } from "enzyme"
import InputLookup from '../../../src/components/editor/InputLookupQA'
const plProps = {
@@ -23,7 +25,37 @@ const plProps = {
"propertyURI": "http://id.loc.gov/ontologies/bflc/target",
"propertyLabel": "Name Lookup"
}
-}
+};
+const p2Props = {
+ "propertyTemplate":
+ {
+ "mandatory": "false",
+ "repeatable": "true",
+ "type": "lookup",
+ "resourceTemplates": [],
+ "valueConstraint": {
+ "valueTemplateRefs": [],
+ "useValuesFrom": [
+ 'lookupQaLocNames',
+ 'lookupQaLocSubjects'
+ ],
+ "valueDataType": {
+ "dataTypeURI": "http://id.loc.gov/ontologies/bibframe/Agent"
+ },
+ "defaults": []
+ },
+ "propertyURI": "http://id.loc.gov/ontologies/bflc/target",
+ "propertyLabel": "Name Lookup"
+ }
+};
+
+const multipleResults = [{"authLabel":"Person",
+ "authURI":"PersonURI",
+ "body":[{"uri":"puri","label":"plabel"}]},
+ {"authLabel":"Subject",
+ "authURI":"SubjectURI",
+ "body":[{"uri":"suri","label":"slabel"}]
+ }];
describe('', () => {
// our mock formData function to replace the one provided by mapDispatchToProps
@@ -82,4 +114,35 @@ describe('', () => {
const propertyRemark = wrapper.find('label > PropertyRemark')
expect(propertyRemark).toBeTruthy()
})
+
+ //Institute wrapper with multiple lookup options
+ const multipleWrapper = shallow()
+ it('should pass multiple lookup results in state with search event', () => {
+ const event = (wrap) => {
+ wrap.setState({options: multipleResults})
+ }
+ multipleWrapper.find('#lookupComponent').simulate('search', event(multipleWrapper))
+ expect(multipleWrapper.state().options[0]).toEqual(multipleResults[0])
+ expect(multipleWrapper.state().options[1]).toEqual(multipleResults[1])
+
+ })
+ //Headers expected
+
+ it('should show menu headers with lookup source labels and values in the dropdown when provided results', () => {
+ const instance = multipleWrapper.instance();
+ const menuWrapper = shallow(instance.renderMenuFunc(multipleResults, p2Props));
+ const menuChildrenNumber = menuWrapper.children().length;
+ //One top level menu component
+ expect(menuWrapper.find('ul').length).toEqual(1);
+ //Four children, with two headings and two items
+ expect(menuChildrenNumber).toEqual(4);
+ expect(menuWrapper.childAt(0).html()).toEqual("
");
+ expect(menuWrapper.childAt(1).childAt(0).text()).toEqual("plabel");
+ expect(menuWrapper.childAt(2).html()).toEqual("");
+ expect(menuWrapper.childAt(3).childAt(0).text()).toEqual("slabel");
+ })
+
+
+
+
})
diff --git a/package-lock.json b/package-lock.json
index 8abe39ad0..10665a10c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6327,7 +6327,8 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -6351,13 +6352,15 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -6374,19 +6377,22 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -6517,7 +6523,8 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -6531,6 +6538,7 @@
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -6547,6 +6555,7 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -6555,13 +6564,15 @@
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"minipass": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz",
"integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -6582,6 +6593,7 @@
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -6670,7 +6682,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -6684,6 +6697,7 @@
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -6779,7 +6793,8 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -6821,6 +6836,7 @@
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -6842,6 +6858,7 @@
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -6890,13 +6907,15 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"yallist": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
"integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
diff --git a/src/components/editor/InputLookupQA.jsx b/src/components/editor/InputLookupQA.jsx
index 414ef31b2..179a54397 100644
--- a/src/components/editor/InputLookupQA.jsx
+++ b/src/components/editor/InputLookupQA.jsx
@@ -1,102 +1,200 @@
// Copyright 2018 Stanford University see Apache2.txt for license
import React, { Component } from 'react'
-import { asyncContainer, Typeahead } from 'react-bootstrap-typeahead'
+import { asyncContainer, Typeahead, Menu, MenuItem } from 'react-bootstrap-typeahead'
import PropTypes from 'prop-types'
import Swagger from 'swagger-client'
import { connect } from 'react-redux'
import { changeSelections } from '../../actions/index'
-const AsyncTypeahead = asyncContainer(Typeahead)
+const AsyncTypeahead = asyncContainer( Typeahead )
class InputLookupQA extends Component {
- constructor(props) {
- super(props)
- this.state = {
- isLoading: false
- }
- }
-
- render() {
- let isMandatory, isRepeatable, authority, subauthority, language
- try {
- isMandatory = JSON.parse(this.props.propertyTemplate.mandatory)
- isRepeatable = JSON.parse(this.props.propertyTemplate.repeatable)
- authority = this.props.lookupConfig.value.authority
- subauthority = this.props.lookupConfig.value.authority
- language = this.props.lookupConfig.value.language
- } catch (error) {
- console.log(`Problem with properties fetched from resource template: ${error}`)
+ constructor( props ) {
+ super( props )
+ this.state = {
+ isLoading: false
+ }
}
- const typeaheadProps = {
- required: isMandatory,
- multiple: isRepeatable,
- placeholder: this.props.propertyTemplate.propertyLabel,
- useCache: true,
- isLoading: this.state.isLoading,
- options: this.state.options,
- selected: this.state.selected,
- delay: 300
- }
+ //Render menu function to be used by typeahead
+ renderMenuFunc = ( results, menuProps ) => {
+ //Returning results per each promise
+ //If error is returned, it will be used to display for that source
+ const items = [];
+ let r, i, authLabel, resultsLength, authURI, headerKey, result;
+ resultsLength = results.length;
+ let idx = 0;
+ for ( i = 0; i < resultsLength; i++ ) {
+ result = results[i];
+ authLabel = result.authLabel;
+ authURI = result.authURI;
+ headerKey = authURI + "-header";
+ //Add header only if more than one authority request
+ if ( resultsLength > 1 )
+ items.push(
+ {authLabel}
+ );
+ //For this authority, display results
+ if ( "isError" in result ) {
+ //if error, then get error from within result and display that message
+ let errorMessage = "An error occurred in retrieving results";
+ let errorHeaderKey = headerKey + "-error";
+ items.push(
+ {errorMessage}
+ );
+ } else {
+ //if not error, print out items for result
+ r = result.body;
+ r.forEach( function( result ) {
+ items.push( );
+ idx++;
+ } );
+ //if the length of results is zero we need to show that as well
+ if ( r.length == 0 ) {
+ let noResultsMessage = "No results for this lookup";
+ let noResultsHeaderKey = headerKey + "-noResults";
+ items.push(
+ {noResultsMessage}
+ );
+ }
- return (
-
-
{
- this.setState({isLoading: true});
- Swagger({ url: "src/lib/apidoc.json" }).then((client) => {
- client
- .apis
- .SearchQuery
- .GET_searchAuthority({
- q: query,
- vocab: authority,
- subauthority: subauthority,
- maxRecords: 8,
- lang: language
- })
- .then(response => this.setState({
- isLoading: false,
- options: response.body
- }))
- }).catch(() => { return false })
- }}
- onChange={selected => {
- let payload = {
- id: this.props.propertyTemplate.propertyURI,
- items: selected,
- rtId: this.props.rtId
- }
- this.props.handleSelectedChange(payload)
}
- }
- {...typeaheadProps}
- />
-
- )
- }
+ }
+
+ return (
+
+ )
+ }
+
+ render() {
+
+ let isMandatory, isRepeatable, authority, subauthority, language
+ const lookupConfigs = this.props.lookupConfig
+
+ try {
+ isMandatory = JSON.parse( this.props.propertyTemplate.mandatory )
+ isRepeatable = JSON.parse( this.props.propertyTemplate.repeatable )
+ } catch ( error ) {
+ console.log( `Problem with properties fetched from resource template: ${error}` )
+ }
+ const typeaheadProps = {
+ required: isMandatory,
+ multiple: isRepeatable,
+ placeholder: this.props.propertyTemplate.propertyLabel,
+ useCache: true,
+ isLoading: this.state.isLoading,
+ options: this.state.options,
+ selected: this.state.selected,
+ delay: 300
+ }
+
+ return (
+
+
{
+ return ( this.renderMenuFunc( results, menuProps ) );
+ }
+ }
+
+
+ onSearch={query => {
+ this.setState( { isLoading: true } );
+ Swagger( { url: "src/lib/apidoc.json" } ).then(( client ) => {
+ //create array of promises based on the lookup config array that is sent in
+ let lookupPromises = lookupConfigs.map( lookupConfig => {
+ authority = lookupConfig.value.authority;
+ subauthority = lookupConfig.value.authority;
+ language = lookupConfig.value.language;
+ //return the 'promise'
+ //Since we don't want promise.all to fail if
+ //one of the lookups fails, we want a catch statement
+ //at this level which will then return the error
+ return client
+ .apis
+ .SearchQuery
+ .GET_searchAuthority( {
+ q: query,
+ vocab: authority,
+ subauthority: subauthority,
+ maxRecords: 8,
+ lang: language
+ } )
+ .catch( function( err ) {
+ console.error( "Error in executing lookup against source", err );
+ //return information along with the error in its own object
+ return { "isError": true, "errorObject": err };
+ } );
+
+ } );
+
+ Promise.all( lookupPromises ).then(( values ) => {
+
+ let valuesLength = values.length;
+ let i;
+ for ( i = 0; i < valuesLength; i++ ) {
+ //If undefined, add info - note if error, error object returned in object
+ //which allows attaching label and uri for authority
+ if ( values[i] ) {
+ values[i]["authLabel"] = lookupConfigs[i].value.label;
+ values[i]["authURI"] = lookupConfigs[i].value.uri;
+ }
+ }
+
+ this.setState( {
+ isLoading: false,
+ options: values
+ } )
+ }
+ )
+ } ).catch(() => { return false } )
+ }}
+ onChange={selected => {
+ let payload = {
+ id: this.props.propertyTemplate.propertyURI,
+ items: selected,
+ rtId: this.props.rtId
+ }
+ this.props.handleSelectedChange( payload )
+ }
+ }
+ {...typeaheadProps}
+
+ filterBy={() => {
+ /** Currently don't want any default filtering as we want all the results returned from QA, also we are passing in a complex object **/
+ /* Your own filtering code goes here. */
+ return true;
+ }}
+ />
+
+ )
+ }
}
InputLookupQA.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
+ 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
}
-const mapStatetoProps = (state) => {
- let result = Object.assign({},state)
- return result
+const mapStatetoProps = ( state ) => {
+ let result = Object.assign( {}, state )
+ return result
}
-const mapDispatchtoProps = dispatch => ({
- handleSelectedChange(selected){
- dispatch(changeSelections(selected))
- }
-})
+const mapDispatchtoProps = dispatch => ( {
+ handleSelectedChange( selected ) {
+ dispatch( changeSelections( selected ) )
+ }
+} )
-export default connect(mapStatetoProps, mapDispatchtoProps)(InputLookupQA)
+export default connect( mapStatetoProps, mapDispatchtoProps )( InputLookupQA )
diff --git a/src/components/editor/ResourceTemplateForm.jsx b/src/components/editor/ResourceTemplateForm.jsx
index 66dc62795..23e7b408f 100644
--- a/src/components/editor/ResourceTemplateForm.jsx
+++ b/src/components/editor/ResourceTemplateForm.jsx
@@ -1,6 +1,6 @@
// Copyright 2018 Stanford University see Apache2.txt for license
-import React, {Component} from 'react'
+import React, { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import shortid from 'shortid'
@@ -10,262 +10,278 @@ import InputLookupQA from './InputLookupQA'
import PropertyPanel from './PropertyPanel'
import PropertyResourceTemplate from './PropertyResourceTemplate'
import lookupConfig from '../../../static/spoofedFilesFromServer/fromSinopiaServer/lookupConfig.json'
-import {getLD, setItems, removeAllContent} from '../../actions/index'
+import { getLD, setItems, removeAllContent } from '../../actions/index'
import { getResourceTemplate } from '../../sinopiaServer'
-const N3 = require('n3')
+const N3 = require( 'n3' )
const { DataFactory } = N3
const { blankNode } = DataFactory
// renders the input form for a ResourceTemplate
class ResourceTemplateForm extends Component {
- constructor(props) {
- super(props)
- this.defaultValues()
- this.state = {
- showRdf: false,
- rdfOuterSubject: this.makeSubject(),
- inputs: {}
+ constructor( props ) {
+ super( props )
+ this.defaultValues()
+ this.state = {
+ showRdf: false,
+ rdfOuterSubject: this.makeSubject(),
+ inputs: {}
+ }
}
- }
- defaultValues = () => {
- this.props.propertyTemplates.map( (pt) =>{
- if (pt.mandatory == undefined) pt.mandatory = "true"
- if (pt.repeatable == undefined) pt.repeatable = "false"
- if (pt.editable == undefined) pt.editable = "true"
- })
- }
+ defaultValues = () => {
+ this.props.propertyTemplates.map(( pt ) => {
+ if ( pt.mandatory == undefined ) pt.mandatory = "true"
+ if ( pt.repeatable == undefined ) pt.repeatable = "false"
+ if ( pt.editable == undefined ) pt.editable = "true"
+ } )
+ }
- makeSubject = () => {
- // in the future we will return a blank node or an IRI (using namedNode in the DataFactory ^^)...
- // return namedNode('http://example.com')
- return blankNode()
- }
+ makeSubject = () => {
+ // in the future we will return a blank node or an IRI (using namedNode in the DataFactory ^^)...
+ // return namedNode('http://example.com')
+ return blankNode()
+ }
- rdfClose = () => {
- this.setState( { showRdf: false } )
- }
+ rdfClose = () => {
+ this.setState( { showRdf: false } )
+ }
- // TODO: deal with more than one default value?
- defaultsForLiteral = (content, predicate) => {
- return [{
- content: content,
- id: 0,
- bnode: this.state.rdfOuterSubject,
- propPredicate: predicate
- }]
- }
+ // TODO: deal with more than one default value?
+ defaultsForLiteral = ( content, predicate ) => {
+ return [{
+ content: content,
+ id: 0,
+ bnode: this.state.rdfOuterSubject,
+ propPredicate: predicate
+ }]
+ }
- setDefaultsForLiteralWithPayLoad = (button, propURI, propPredicate, defaults, rtid) => {
- let useUri
- propPredicate !== undefined ? useUri = propPredicate : useUri = propURI
+ setDefaultsForLiteralWithPayLoad = ( button, propURI, propPredicate, defaults, rtid ) => {
+ let useUri
+ propPredicate !== undefined ? useUri = propPredicate : useUri = propURI
- const payload = {
- id: button,
- uri: useUri,
- items: defaults,
- rtId: rtid
- }
+ const payload = {
+ id: button,
+ uri: useUri,
+ items: defaults,
+ rtId: rtid
+ }
- if (defaults != undefined) {
- this.props.handleMyItemsChange(payload)
+ if ( defaults != undefined ) {
+ this.props.handleMyItemsChange( payload )
+ }
}
- }
- getContentForModalButton = (rtId) => {
- let content
- let resourceTemplate = getResourceTemplate(rtId)
- const pt = resourceTemplate.propertyTemplates[0]
- if (this.isLiteralWithDefaultValue(pt)) {
- content = pt.valueConstraint.defaults[0].defaultLiteral
+ getContentForModalButton = ( rtId ) => {
+ let content
+ let resourceTemplate = getResourceTemplate( rtId )
+ const pt = resourceTemplate.propertyTemplates[0]
+ if ( this.isLiteralWithDefaultValue( pt ) ) {
+ content = pt.valueConstraint.defaults[0].defaultLiteral
+ }
+ return content
}
- return content
- }
- // Note: rtIds is expected to be an array of length at least one
- resourceTemplateFields = (rtIds) => {
- const rtProperties = []
- rtIds.map((rtId, i) => {
- rtProperties.push()
- if ((rtIds.length - i) > 1) {
- rtProperties.push(
)
- }
- })
- return rtProperties
- }
+ // Note: rtIds is expected to be an array of length at least one
+ resourceTemplateFields = ( rtIds ) => {
+ const rtProperties = []
+ rtIds.map(( rtId, i ) => {
+ rtProperties.push( )
+ if ( ( rtIds.length - i ) > 1 ) {
+ rtProperties.push(
)
+ }
+ } )
+ return rtProperties
+ }
- defaultValues = () => {
- this.props.propertyTemplates.map((pt) => {
- if (pt.mandatory == undefined) pt.mandatory = "true"
- if (pt.repeatable == undefined) pt.repeatable = "false"
- if (pt.editable == undefined) pt.editable = "true"
- })
- }
+ defaultValues = () => {
+ this.props.propertyTemplates.map(( pt ) => {
+ if ( pt.mandatory == undefined ) pt.mandatory = "true"
+ if ( pt.repeatable == undefined ) pt.repeatable = "false"
+ if ( pt.editable == undefined ) pt.editable = "true"
+ } )
+ }
- isLiteralWithDefaultValue = (pt) => {
- return Boolean(
- pt.type === 'literal' &&
- pt.valueConstraint !== undefined &&
- pt.valueConstraint.defaults !== undefined &&
- pt.valueConstraint.defaults.length > 0
- )
- }
+ isLiteralWithDefaultValue = ( pt ) => {
+ return Boolean(
+ pt.type === 'literal' &&
+ pt.valueConstraint !== undefined &&
+ pt.valueConstraint.defaults !== undefined &&
+ pt.valueConstraint.defaults.length > 0
+ )
+ }
- isResourceWithValueTemplateRef = (pt) => {
- return Boolean(
- pt.type === 'resource' &&
- pt.valueConstraint != null &&
- pt.valueConstraint.valueTemplateRefs != null &&
- pt.valueConstraint.valueTemplateRefs.length > 0
- )
- }
+ isResourceWithValueTemplateRef = ( pt ) => {
+ return Boolean(
+ pt.type === 'resource' &&
+ pt.valueConstraint != null &&
+ pt.valueConstraint.valueTemplateRefs != null &&
+ pt.valueConstraint.valueTemplateRefs.length > 0
+ )
+ }
- setInputs() {
- let inputs = {}
- inputs['literals'] = this.props.literals
- inputs['lookups'] = this.props.lookups
- inputs['rtId'] = this.props.rtId
- inputs['resourceURI'] = this.props.resourceTemplate.resourceURI
- inputs['linkedNode'] = this.state.rdfOuterSubject
- return inputs
- }
+ setInputs() {
+ let inputs = {}
+ inputs['literals'] = this.props.literals
+ inputs['lookups'] = this.props.lookups
+ inputs['rtId'] = this.props.rtId
+ inputs['resourceURI'] = this.props.resourceTemplate.resourceURI
+ inputs['linkedNode'] = this.state.rdfOuterSubject
+ return inputs
+ }
- handleTrashValue = (buttonIndex) => {
- this.props.handleRemoveAllContent(buttonIndex)
- }
+ handleTrashValue = ( buttonIndex ) => {
+ this.props.handleRemoveAllContent( buttonIndex )
+ }
- renderValueForButton(buttonValue, buttonIndex) {
- if (buttonValue != undefined) {
- return (
-
-
-
-
-
- )
+ renderValueForButton( buttonValue, buttonIndex ) {
+ if ( buttonValue != undefined ) {
+ return (
+
+
+
+
+
+ )
+ }
}
- }
- render() {
+ render() {
- if (this.props.propertyTemplates.length === 0 || this.props.propertyTemplates[0] === {}) {
- return There are no propertyTemplates - probably an error.
- } else {
- return (
-
+ if ( this.props.propertyTemplates.length === 0 || this.props.propertyTemplates[0] === {} ) {
+ return
There are no propertyTemplates - probably an error.
+ } else {
+ return (
+
+
+
+ )
+ }
}
- }
}
ResourceTemplateForm.propTypes = {
- literals: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
- lookups: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
- handleGenerateLD: PropTypes.func,
- propertyTemplates: PropTypes.arrayOf(PropTypes.object).isRequired,
- resourceTemplate: PropTypes.object.isRequired,
- rtId: PropTypes.string,
- parentResourceTemplate: PropTypes.string,
- rdfOuterSubject: PropTypes.object,
- propPredicate: PropTypes.string,
- buttonID: PropTypes.number,
- generateLD: PropTypes.object.isRequired,
- handleMyItemsChange: PropTypes.func,
- handleRemoveAllContent: PropTypes.func
+ literals: PropTypes.oneOfType( [PropTypes.array, PropTypes.object] ),
+ lookups: PropTypes.oneOfType( [PropTypes.array, PropTypes.object] ),
+ handleGenerateLD: PropTypes.func,
+ propertyTemplates: PropTypes.arrayOf( PropTypes.object ).isRequired,
+ resourceTemplate: PropTypes.object.isRequired,
+ rtId: PropTypes.string,
+ parentResourceTemplate: PropTypes.string,
+ rdfOuterSubject: PropTypes.object,
+ propPredicate: PropTypes.string,
+ buttonID: PropTypes.number,
+ generateLD: PropTypes.object.isRequired,
+ handleMyItemsChange: PropTypes.func,
+ handleRemoveAllContent: PropTypes.func
}
-const mapStateToProps = (state) => {
- return {
- literals: state.literal,
- lookups: state.lookups,
- generateLD: state.generateLD
- }
+const mapStateToProps = ( state ) => {
+ return {
+ literals: state.literal,
+ lookups: state.lookups,
+ generateLD: state.generateLD
+ }
}
-const mapDispatchToProps = dispatch => ({
- handleMyItemsChange(user_input){
- dispatch(setItems(user_input))
- },
- handleRemoveAllContent(id){
- dispatch(removeAllContent(id))
- },
- handleGenerateLD(inputs){
- dispatch(getLD(inputs))
- }
-})
+const mapDispatchToProps = dispatch => ( {
+ handleMyItemsChange( user_input ) {
+ dispatch( setItems( user_input ) )
+ },
+ handleRemoveAllContent( id ) {
+ dispatch( removeAllContent( id ) )
+ },
+ handleGenerateLD( inputs ) {
+ dispatch( getLD( inputs ) )
+ }
+} )
-export default connect(mapStateToProps, mapDispatchToProps)(ResourceTemplateForm)
+export default connect( mapStateToProps, mapDispatchToProps )( ResourceTemplateForm)
\ No newline at end of file
diff --git a/src/styles/main.css b/src/styles/main.css
index 2fcc99baa..f4a3e671b 100644
--- a/src/styles/main.css
+++ b/src/styles/main.css
@@ -171,3 +171,14 @@ input.rbt-input-main {
.editor-navtabs a {
color: #2F2424;
}
+
+/** For lookup menu headers **/
+.dropdown-header {
+ font-weight:800;
+ color:#333;
+ background-color:#d3d3d3;
+}
+.dropdown-empty, .dropdown-error {
+ font-weight:400;
+ color: #999999;
+}
\ No newline at end of file
diff --git a/static/spoofedFilesFromServer/fromSinopiaServer/resourceTemplates/MonographInstance.json b/static/spoofedFilesFromServer/fromSinopiaServer/resourceTemplates/MonographInstance.json
index a8059117d..c148b63bc 100644
--- a/static/spoofedFilesFromServer/fromSinopiaServer/resourceTemplates/MonographInstance.json
+++ b/static/spoofedFilesFromServer/fromSinopiaServer/resourceTemplates/MonographInstance.json
@@ -168,7 +168,8 @@
"valueConstraint": {
"valueTemplateRefs": [],
"useValuesFrom": [
- "urn:ld4p:qa:names:person"
+ "urn:ld4p:qa:names:person",
+ "urn:ld4p:qa:subjects:person"
],
"valueDataType": {
"dataTypeURI": "http://id.loc.gov/ontologies/bibframe/Agent"