From dd945a23eab0d27424ccea8b44059350c851844d Mon Sep 17 00:00:00 2001 From: djhi Date: Thu, 16 Feb 2017 18:01:06 +0100 Subject: [PATCH 1/2] Format e2e + display in edit view --- src/app/e2e/home_published.js | 15 ++-- src/app/e2e/home_published.json | 31 ++++++- src/app/e2e/home_published_julia.js | 28 ++++-- src/app/e2e/sample_csv.csv | 12 +-- .../DatasetCharacteristicItem.js | 21 +++++ .../DatasetCharacteristicsView.js | 6 +- src/app/js/dataset/DefaultColumn.js | 65 +++----------- src/app/js/dataset/DefaultColumn.spec.js | 38 +------- src/app/js/formats/Format.js | 88 +++++++++++++------ src/app/js/formats/Format.spec.js | 72 +++++++++++++++ src/app/js/lib/Property.js | 30 ++++--- src/app/js/lib/PropertyEdition.js | 6 +- src/app/js/publication/index.js | 8 ++ src/app/js/resource/DetailProperties.js | 12 +-- src/app/js/resource/DetailProperties.spec.js | 18 ++-- 15 files changed, 280 insertions(+), 170 deletions(-) create mode 100644 src/app/js/characteristic/DatasetCharacteristicItem.js create mode 100644 src/app/js/formats/Format.spec.js diff --git a/src/app/e2e/home_published.js b/src/app/e2e/home_published.js index 618102b23..389de49a1 100644 --- a/src/app/e2e/home_published.js +++ b/src/app/e2e/home_published.js @@ -6,9 +6,8 @@ import { clear, loadFixtures } from '../../common/tests/fixtures'; import fixtures from './home_published.json'; import { inputElementIsFocusable, elementIsClicked } from '../../common/tests/conditions'; - describe('Home page with published data', function homePublishedDataTests() { - this.timeout(10000); + this.timeout(100000); const DEFAULT_WAIT_TIMEOUT = 9000; // A bit less than mocha's timeout to get explicit errors from selenium before(async () => { @@ -45,7 +44,7 @@ describe('Home page with published data', function homePublishedDataTests() { await driver.wait(until.elementLocated(By.css('.dataset')), DEFAULT_WAIT_TIMEOUT); const headers = await driver.findElements(By.css('.dataset table th')); const headersText = await Promise.all(headers.map(h => h.getText())); - expect(headersText).toEqual(['uri', 'fullname', 'email']); + expect(headersText).toEqual(['uri', 'fullname', 'email', 'best_friend_of']); const tds = await driver.findElements(By.css('.dataset table tbody td')); const tdsText = await Promise.all(tds.map(td => td.getText())); @@ -70,11 +69,17 @@ describe('Home page with published data', function homePublishedDataTests() { const fullnameValue = await driver.findElement(By.css('.detail .property:nth-child(2) dd')); await driver.wait(until.elementTextIs(fullnameValue, 'PEREGRIN.TOOK'), DEFAULT_WAIT_TIMEOUT); - const mailLabel = await driver.findElement(By.css('.detail .property:last-child dt')); + const mailLabel = await driver.findElement(By.css('.detail .property:nth-child(3) dt')); await driver.wait(until.elementTextIs(mailLabel, 'email\nhttp://uri4uri.net/vocab'), DEFAULT_WAIT_TIMEOUT); - const mailValue = await driver.findElement(By.css('.detail .property:last-child dd')); + const mailValue = await driver.findElement(By.css('.detail .property:nth-child(3) dd')); await driver.wait(until.elementTextIs(mailValue, 'peregrin.took@shire.net'), DEFAULT_WAIT_TIMEOUT); + + const bestFriendLabel = await driver.findElement(By.css('.detail .property:last-child dt')); + await driver.wait(until.elementTextIs(bestFriendLabel, 'best_friend_of\nhttp://www.w3.org/ns/person'), DEFAULT_WAIT_TIMEOUT); + + const bestFriendValue = await driver.findElement(By.css('.detail .property:last-child dd')); + await driver.wait(until.elementTextIs(bestFriendValue, 'MERIADOC.BRANDYBUCK'), DEFAULT_WAIT_TIMEOUT); }); it('should allow to add field resource properties', async () => { diff --git a/src/app/e2e/home_published.json b/src/app/e2e/home_published.json index 3f60c30fa..d79a66cc5 100644 --- a/src/app/e2e/home_published.json +++ b/src/app/e2e/home_published.json @@ -32,6 +32,25 @@ "transformers" : [ { "operation" : "COLUMN", "args" : [ { "name" : "column", "type" : "column", "value" : "author" } ] } ], "cover" : "dataset", "scheme" : "http://www.w3.org/ns/person" + }, { + "name" : "best_friend_of", + "label" : "Best Friend Of", + "transformers" : [ { + "operation" : "LINK", + "args" : [ + { "name" : "reference", "type" : "column", "value" : "best_friend_of" }, + { "name" : "identifier", "type" : "column", "value" : "id" } + ] + }], + "cover" : "collection", + "scheme" : "http://www.w3.org/ns/person", + "format": { + "name": "uri", + "args": { + "type": "column", + "value": "fullname" + } + } }], "publishedCharacteristic": [ { "movie": "LOTR" , "author": "Peter Jackson" } @@ -41,14 +60,16 @@ "uri" : "1", "versions": [{ "fullname" : "PEREGRIN.TOOK", - "email" : "peregrin.took@shire.net" + "email" : "peregrin.took@shire.net", + "best_friend_of": "5" }] }, { "uri" : "2", "versions": [{ "fullname" : "SAMSAGET.GAMGIE", - "email" : "samsaget.gamgie@shire.net" + "email" : "samsaget.gamgie@shire.net", + "best_friend_of": "4" }] }, { @@ -62,14 +83,16 @@ "uri" : "4", "versions": [{ "fullname" : "FRODO.BAGGINS", - "email" : "frodo.saquet@shire.net" + "email" : "frodo.saquet@shire.net", + "best_friend_of": "2" }] }, { "uri" : "5", "versions": [{ "fullname" : "MERIADOC.BRANDYBUCK", - "email" : "meriadoc.brandybuck@shire.net" + "email" : "meriadoc.brandybuck@shire.net", + "best_friend_of": "1" }] } ] diff --git a/src/app/e2e/home_published_julia.js b/src/app/e2e/home_published_julia.js index b9c250094..02a87b1ea 100644 --- a/src/app/e2e/home_published_julia.js +++ b/src/app/e2e/home_published_julia.js @@ -75,11 +75,17 @@ describe('Home page with published data when logged as Julia', function homePubl const fullnameValue = await driver.findElement(By.css('.detail .property:nth-child(2) dd')); expect(await fullnameValue.getText()).toEqual('PEREGRIN.TOOK'); - const mailLabel = await driver.findElement(By.css('.detail .property:last-child dt')); - expect(await mailLabel.getText()).toEqual('email\nhttp://uri4uri.net/vocab'); + const mailLabel = await driver.findElement(By.css('.detail .property:nth-child(3) dt')); + await driver.wait(until.elementTextIs(mailLabel, 'email\nhttp://uri4uri.net/vocab'), DEFAULT_WAIT_TIMEOUT); - const mailValue = await driver.findElement(By.css('.detail .property:last-child dd')); - expect(await mailValue.getText()).toEqual('peregrin.took@shire.net'); + const mailValue = await driver.findElement(By.css('.detail .property:nth-child(3) dd')); + await driver.wait(until.elementTextIs(mailValue, 'peregrin.took@shire.net'), DEFAULT_WAIT_TIMEOUT); + + const bestFriendLabel = await driver.findElement(By.css('.detail .property:last-child dt')); + await driver.wait(until.elementTextIs(bestFriendLabel, 'best_friend_of\nhttp://www.w3.org/ns/person'), DEFAULT_WAIT_TIMEOUT); + + const bestFriendValue = await driver.findElement(By.css('.detail .property:last-child dd')); + await driver.wait(until.elementTextIs(bestFriendValue, 'MERIADOC.BRANDYBUCK'), DEFAULT_WAIT_TIMEOUT); }); it('should allow to edit resource properties', async () => { @@ -104,11 +110,17 @@ describe('Home page with published data when logged as Julia', function homePubl const fullnameValue = await driver.findElement(By.css('.detail .property:nth-child(2) dd')); expect(await fullnameValue.getText()).toEqual('PEREGRIN.TOOK'); - const mailLabel = await driver.findElement(By.css('.detail .property:last-child dt')); - expect(await mailLabel.getText()).toEqual('email\nhttp://uri4uri.net/vocab'); + const mailLabel = await driver.findElement(By.css('.detail .property:nth-child(3) dt')); + await driver.wait(until.elementTextIs(mailLabel, 'email\nhttp://uri4uri.net/vocab'), DEFAULT_WAIT_TIMEOUT); + + const mailValue = await driver.findElement(By.css('.detail .property:nth-child(3) dd')); + await driver.wait(until.elementTextIs(mailValue, 'peregrin.took@gondor.net'), DEFAULT_WAIT_TIMEOUT); + + const bestFriendLabel = await driver.findElement(By.css('.detail .property:last-child dt')); + await driver.wait(until.elementTextIs(bestFriendLabel, 'best_friend_of\nhttp://www.w3.org/ns/person'), DEFAULT_WAIT_TIMEOUT); - const mailValue = await driver.findElement(By.css('.detail .property:last-child dd')); - expect(await mailValue.getText()).toEqual('peregrin.took@gondor.net'); + const bestFriendValue = await driver.findElement(By.css('.detail .property:last-child dd')); + await driver.wait(until.elementTextIs(bestFriendValue, 'MERIADOC.BRANDYBUCK'), DEFAULT_WAIT_TIMEOUT); }); it('should go to hide page', async () => { diff --git a/src/app/e2e/sample_csv.csv b/src/app/e2e/sample_csv.csv index a64fa4fc3..0eededa30 100644 --- a/src/app/e2e/sample_csv.csv +++ b/src/app/e2e/sample_csv.csv @@ -1,6 +1,6 @@ -"id";"uid";"name";"mail";"movie"; -"1";"frodo.baggins";"BAGGINS";"frodo.saquet@shire.net";"LOTR"; -"3";"bilbon.baggins";"BAGGINS";"bilbon.saquet@shire.net";"LOTR"; -"7";"samsaget.gamgie";"GAMGIE";"samsaget.gamgie@shire.net";"LOTR"; -"8";"peregrin.took";"TOOK";"peregrin.took@shire.net";"LOTR"; -"9";"meriadoc.brandybuck";"BRANDYBUCK";"meriadoc.brandybuck@shire.net";"LOTR"; +"id";"uid";"name";"mail";"movie" +"1";"frodo.baggins";"BAGGINS";"frodo.saquet@shire.net";"LOTR" +"3";"bilbon.baggins";"BAGGINS";"bilbon.saquet@shire.net";"LOTR" +"7";"samsaget.gamgie";"GAMGIE";"samsaget.gamgie@shire.net";"LOTR" +"8";"peregrin.took";"TOOK";"peregrin.took@shire.net";"LOTR" +"9";"meriadoc.brandybuck";"BRANDYBUCK";"meriadoc.brandybuck@shire.net";"LOTR" diff --git a/src/app/js/characteristic/DatasetCharacteristicItem.js b/src/app/js/characteristic/DatasetCharacteristicItem.js new file mode 100644 index 000000000..e0a6a0d8c --- /dev/null +++ b/src/app/js/characteristic/DatasetCharacteristicItem.js @@ -0,0 +1,21 @@ +import React, { PropTypes } from 'react'; +import { connect } from 'react-redux'; +import Property from '../lib/Property'; +import { getFieldByName } from '../publication'; +import { field as fieldPropTypes } from '../propTypes'; + +const DatasetCharacteristicItemComponent = ({ resource, field }) => ( + +); + +DatasetCharacteristicItemComponent.propTypes = { + resource: PropTypes.object.isRequired, // eslint-disable-line + field: fieldPropTypes.isRequired, +}; + +const mapStateToProps = (state, { characteristic: { name, scheme, value } }) => ({ + field: getFieldByName(state, name), + resource: { name, scheme, [name]: value }, +}); + +export default connect(mapStateToProps)(DatasetCharacteristicItemComponent); diff --git a/src/app/js/characteristic/DatasetCharacteristicsView.js b/src/app/js/characteristic/DatasetCharacteristicsView.js index 29f06b31a..5e52849c6 100644 --- a/src/app/js/characteristic/DatasetCharacteristicsView.js +++ b/src/app/js/characteristic/DatasetCharacteristicsView.js @@ -18,7 +18,7 @@ import { toggleCharacteristicsEdition as toggleCharacteristicsEditionAction, } from './'; -import Property from '../lib/Property'; +import DatasetCharacteristicItem from './DatasetCharacteristicItem'; const styles = { container: { @@ -38,8 +38,8 @@ const DatasetCharacteristics = ({ title={polyglot.t('dataset_characteristics')} /> - {characteristics.map(({ name, value, scheme }) => ( - + {characteristics.map(characteristic => ( + ))} {canEdit && diff --git a/src/app/js/dataset/DefaultColumn.js b/src/app/js/dataset/DefaultColumn.js index fa1fe1802..26ce2bcb1 100644 --- a/src/app/js/dataset/DefaultColumn.js +++ b/src/app/js/dataset/DefaultColumn.js @@ -1,62 +1,23 @@ -import React, { Component, PropTypes } from 'react'; -import { connect } from 'react-redux'; -import compose from 'recompose/compose'; -import withHandlers from 'recompose/withHandlers'; -import withState from 'recompose/withState'; +import React, { PropTypes } from 'react'; import { TableRowColumn } from 'material-ui/Table'; import Format from '../formats/Format'; -import fetchByUri from '../lib/fetchByUri'; -import { getToken } from '../user'; import { field as fieldPropTypes } from '../propTypes'; -export class DatasetColumnComponent extends Component { - componentWillMount() { - const { column, resource } = this.props; - const linkTransformer = column.transformers && column.transformers.find(t => t.operation === 'LINK'); - if (linkTransformer) { - const uri = resource[linkTransformer.args.find(a => a.name === 'reference').value]; - this.props.fetchLinkedResource(uri); - } - } - - render() { - const { column, columns, linkedResource, resource } = this.props; - - return ( - - - - ); - } -} - -DatasetColumnComponent.propTypes = { +const DatasetColumn = ({ column, columns, resource }) => ( + + + +); + +DatasetColumn.propTypes = { column: fieldPropTypes.isRequired, columns: PropTypes.arrayOf(fieldPropTypes).isRequired, - fetchLinkedResource: PropTypes.func.isRequired, - linkedResource: PropTypes.object, // eslint-disable-line resource: PropTypes.object.isRequired, // eslint-disable-line }; -const mapStateToProps = state => ({ - token: getToken(state), -}); - -export default compose( - connect(mapStateToProps), - withState('linkedResource', 'setLinkedResource', null), - withHandlers({ - fetchLinkedResource: ({ setLinkedResource, token }) => uri => - fetchByUri(uri, token) - .then((linkedResource) => { - setLinkedResource(linkedResource); - }), - }), -)(DatasetColumnComponent); - +export default DatasetColumn; diff --git a/src/app/js/dataset/DefaultColumn.spec.js b/src/app/js/dataset/DefaultColumn.spec.js index 8a5761ba9..1576d46f7 100644 --- a/src/app/js/dataset/DefaultColumn.spec.js +++ b/src/app/js/dataset/DefaultColumn.spec.js @@ -1,9 +1,9 @@ import React from 'react'; -import expect, { createSpy } from 'expect'; +import expect from 'expect'; import { shallow } from 'enzyme'; import { TableRowColumn } from 'material-ui/Table'; -import { DatasetColumnComponent as DefaultColumn } from './DefaultColumn'; +import DefaultColumn from './DefaultColumn'; import Format from '../formats/Format'; describe('', () => { @@ -15,42 +15,11 @@ describe('', () => { const resource = { a_name: 'a_value', - reference_value: 'referenced_resource', }; - const fetchLinkedResource = createSpy(); - - - it('calls fetchLinkedResource on mount if column has a LINK transformer', () => { - const linkedColumn = { - name: 'linked', - label: 'Linked', - transformers: [ - { - operation: 'LINK', - args: [ - { name: 'reference', value: 'reference_value' }, - { name: 'identifier', value: 'identifier_value' }, - ], - }, - ], - }; - shallow(); - - expect(fetchLinkedResource).toHaveBeenCalledWith('referenced_resource'); - }); - - const linkedResource = { linked: true }; const wrapper = shallow(); @@ -60,14 +29,13 @@ describe('', () => { expect(element.prop('className')).toEqual('dataset-a_name'); }); - it('renders a Format with correct props when no linkedResource is supplied', () => { + it('renders a Format with correct props', () => { const element = wrapper.find(Format); expect(element.props()).toEqual({ field: column, fields: columns, resource, - linkedResource, }); }); }); diff --git a/src/app/js/formats/Format.js b/src/app/js/formats/Format.js index 04ee5a2c2..6e6e98333 100644 --- a/src/app/js/formats/Format.js +++ b/src/app/js/formats/Format.js @@ -1,40 +1,58 @@ -import React, { PropTypes } from 'react'; +import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; +import compose from 'recompose/compose'; +import withHandlers from 'recompose/withHandlers'; +import withState from 'recompose/withState'; import DefaultFormat from './DefaultFormat'; import { getResourceLastVersion } from '../resource'; +import fetchByUri from '../lib/fetchByUri'; import { field as fieldPropTypes } from '../propTypes'; +import { getToken } from '../user'; -import uri from './uri'; +import uriFormat from './uri'; -const Format = ({ field, fields, linkedResource, rawLinkedResource, resource }) => { - let Component = DefaultFormat; +export class FormatComponent extends Component { + componentWillMount() { + const { field, resource } = this.props; + const linkTransformer = field.transformers && field.transformers.find(t => t.operation === 'LINK'); - if (field.format && field.format.name) { - switch (field.format.name) { - case 'uri': - Component = uri.Component; - break; - - default: - Component = DefaultFormat; - break; + if (linkTransformer) { + const uri = resource[linkTransformer.args.find(a => a.name === 'reference').value]; + this.props.fetchLinkedResource(uri); } } - return ( - - ); -}; + render() { + const { field, fields, linkedResource, rawLinkedResource, resource } = this.props; + let ViewComponent = DefaultFormat; + if (field.format && field.format.name) { + switch (field.format.name) { + case 'uri': + ViewComponent = uriFormat.Component; + break; -Format.propTypes = { + default: + ViewComponent = DefaultFormat; + break; + } + } + + return ( + + ); + } +} + +FormatComponent.propTypes = { + fetchLinkedResource: PropTypes.func.isRequired, field: fieldPropTypes.isRequired, fields: PropTypes.arrayOf(fieldPropTypes).isRequired, linkedResource: PropTypes.object, // eslint-disable-line @@ -42,9 +60,25 @@ Format.propTypes = { resource: PropTypes.object, // eslint-disable-line }; -const mapStateToProps = (state, { linkedResource }) => ({ +const preMapStateToProps = state => ({ + token: getToken(state), +}); + +const postMapStateToProps = (state, { linkedResource }) => ({ linkedResource: linkedResource ? getResourceLastVersion(state, linkedResource) : null, rawLinkedResource: linkedResource, }); - -export default connect(mapStateToProps)(Format); +// http://localhost:3010/#/resource?uri=1 +export default compose( + connect(preMapStateToProps), + withState('linkedResource', 'setLinkedResource', null), + withHandlers({ + fetchLinkedResource: ({ setLinkedResource, token }) => uri => { + return fetchByUri(uri, token) + .then((linkedResource) => { + setLinkedResource(linkedResource); + }); + }, + }), + connect(postMapStateToProps), +)(FormatComponent); diff --git a/src/app/js/formats/Format.spec.js b/src/app/js/formats/Format.spec.js new file mode 100644 index 000000000..931ba1ae6 --- /dev/null +++ b/src/app/js/formats/Format.spec.js @@ -0,0 +1,72 @@ +import React from 'react'; +import expect, { createSpy } from 'expect'; +import { shallow } from 'enzyme'; +import UriView from './uri/Component'; + +import { FormatComponent as Format } from './Format'; + +describe('', () => { + const field = { name: 'a_name', label: 'Foo', format: { name: 'uri' } }; + const fields = [ + field, + { name: 'another_name', label: 'Foo2' }, + ]; + + const resource = { + a_name: 'a_value', + reference_value: 'referenced_resource', + }; + + const rawLinkedResource = { + versions: [resource], + }; + + const fetchLinkedResource = createSpy(); + + + it('calls fetchLinkedResource on mount if column has a LINK transformer', () => { + const linkedField = { + name: 'linked', + label: 'Linked', + transformers: [ + { + operation: 'LINK', + args: [ + { name: 'reference', value: 'reference_value' }, + { name: 'identifier', value: 'identifier_value' }, + ], + }, + ], + }; + shallow(); + + expect(fetchLinkedResource).toHaveBeenCalledWith('referenced_resource'); + }); + + const linkedResource = { linked: true }; + const wrapper = shallow(); + + it('renders an UriView with correct props when no linkedResource is supplied', () => { + const element = wrapper.find(UriView); + + expect(element.props()).toEqual({ + field, + fields, + resource, + linkedResource, + rawLinkedResource, + }); + }); +}); diff --git a/src/app/js/lib/Property.js b/src/app/js/lib/Property.js index f5fd0ee3e..75045a44d 100644 --- a/src/app/js/lib/Property.js +++ b/src/app/js/lib/Property.js @@ -8,6 +8,8 @@ import { getResourceContributorsByField, } from '../resource'; import { property as propertyPropTypes } from '../propTypes'; +import { getCollectionFields } from '../publication'; +import Format from '../formats/Format'; const styles = { container: unValidated => ({ @@ -25,20 +27,26 @@ const styles = { }, }; -const PropertyComponent = ({ name, value, scheme, contributors, unValidatedFields, p: polyglot }) => ( -
+const PropertyComponent = ({ field, fields, resource, contributors, unValidatedFields, p: polyglot }) => ( +
-
{name}
-
{scheme}
- { contributors[name] ? +
{field.name}
+
{field.scheme}
+ { contributors[field.name] ?
- {polyglot.t('contributed_by', { name: contributors[name] })} + {polyglot.t('contributed_by', { name: contributors[field.name] })}
: null }
-
{value}
+
+ +
); @@ -47,14 +55,10 @@ PropertyComponent.propTypes = propertyPropTypes; const mapStateToProps = state => ({ unValidatedFields: getResourceUnvalidatedFields(state), contributors: getResourceContributorsByField(state), + fields: getCollectionFields(state), }); -const mapDispatchToProps = {}; - export default compose( translate, - connect( - mapStateToProps, - mapDispatchToProps, - ), + connect(mapStateToProps), )(PropertyComponent); diff --git a/src/app/js/lib/PropertyEdition.js b/src/app/js/lib/PropertyEdition.js index 505364654..de1dfa78d 100644 --- a/src/app/js/lib/PropertyEdition.js +++ b/src/app/js/lib/PropertyEdition.js @@ -22,7 +22,7 @@ const styles = { }, }; -const Property = ({ name, onChange, scheme, value }) => ( +const PropertyEdition = ({ name, onChange, scheme, value }) => (
{name}
@@ -39,9 +39,9 @@ const Property = ({ name, onChange, scheme, value }) => (
); -Property.propTypes = propertyPropTypes; +PropertyEdition.propTypes = propertyPropTypes; export default withHandlers({ onChange: ({ name, onSetNewCharacteristicValue }) => (event, value) => onSetNewCharacteristicValue({ name, value }), -})(Property); +})(PropertyEdition); diff --git a/src/app/js/publication/index.js b/src/app/js/publication/index.js index c9eba06a9..51bb8cc4a 100644 --- a/src/app/js/publication/index.js +++ b/src/app/js/publication/index.js @@ -56,6 +56,14 @@ export const getCollectionFields = createSelector( fields => fields.filter(f => f.cover === COVER_COLLECTION), ); +const getFieldNameFromParams = (state, params) => params; + +export const getFieldByName = createSelector( + getFields, + getFieldNameFromParams, + (fields, name) => fields.find(f => f.name === name), +); + export const getContributionFields = createSelector( getFields, fields => fields.filter(f => f.contribution), diff --git a/src/app/js/resource/DetailProperties.js b/src/app/js/resource/DetailProperties.js index 6cbee43a0..588d366f5 100644 --- a/src/app/js/resource/DetailProperties.js +++ b/src/app/js/resource/DetailProperties.js @@ -13,15 +13,11 @@ import Property from '../lib/Property'; export const DetailPropertiesComponent = ({ resource, collectionFields, documentFields }) => ( - {collectionFields.map(({ name, scheme }) => ( - + {collectionFields.map(field => ( + ))} - {documentFields.filter(({ name }) => !!resource[name]).map(({ name, scheme }) => ( - + {documentFields.filter(({ name }) => !!resource[name]).map(field => ( + ))} ); diff --git a/src/app/js/resource/DetailProperties.spec.js b/src/app/js/resource/DetailProperties.spec.js index 99597ca66..6f6825505 100644 --- a/src/app/js/resource/DetailProperties.spec.js +++ b/src/app/js/resource/DetailProperties.spec.js @@ -32,16 +32,22 @@ describe('DetailPropertiesComponent', () => { properties.forEach((element, index) => { if (index === 2) { expect(element.props()).toEqual({ - name: 'contribution1', - value: `value${index + 1}`, - scheme: `scheme${index + 1}`, + field: { name: 'contribution1', scheme: 'scheme3' }, + resource: { + field1: 'value1', + field2: 'value2', + contribution1: 'value3', + }, }); return; } expect(element.props()).toEqual({ - name: `field${index + 1}`, - value: `value${index + 1}`, - scheme: `scheme${index + 1}`, + field: { name: `field${index + 1}`, scheme: `scheme${index + 1}` }, + resource: { + field1: 'value1', + field2: 'value2', + contribution1: 'value3', + }, }); }); }); From 398c997ce40478b95e2a45ada0c1e4462d143b2c Mon Sep 17 00:00:00 2001 From: djhi Date: Thu, 16 Feb 2017 18:18:02 +0100 Subject: [PATCH 2/2] review --- .../DatasetCharacteristicItem.js | 6 +++--- src/app/js/lib/Property.js | 18 +++++++++++++++--- src/app/js/propTypes.js | 6 ++++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/app/js/characteristic/DatasetCharacteristicItem.js b/src/app/js/characteristic/DatasetCharacteristicItem.js index e0a6a0d8c..a817b5463 100644 --- a/src/app/js/characteristic/DatasetCharacteristicItem.js +++ b/src/app/js/characteristic/DatasetCharacteristicItem.js @@ -1,15 +1,15 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; import { connect } from 'react-redux'; import Property from '../lib/Property'; import { getFieldByName } from '../publication'; -import { field as fieldPropTypes } from '../propTypes'; +import { field as fieldPropTypes, resource as resourcePropTypes } from '../propTypes'; const DatasetCharacteristicItemComponent = ({ resource, field }) => ( ); DatasetCharacteristicItemComponent.propTypes = { - resource: PropTypes.object.isRequired, // eslint-disable-line + resource: resourcePropTypes.isRequired, field: fieldPropTypes.isRequired, }; diff --git a/src/app/js/lib/Property.js b/src/app/js/lib/Property.js index 75045a44d..8e6cb544e 100644 --- a/src/app/js/lib/Property.js +++ b/src/app/js/lib/Property.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { PropTypes } from 'react'; import { connect } from 'react-redux'; import compose from 'recompose/compose'; import translate from 'redux-polyglot/translate'; @@ -7,7 +7,12 @@ import { getResourceUnvalidatedFields, getResourceContributorsByField, } from '../resource'; -import { property as propertyPropTypes } from '../propTypes'; +import { + contributor as contributorPropTypes, + field as fieldPropTypes, + polyglot as polyglotPropTypes, + resource as resourcePropTypes, +} from '../propTypes'; import { getCollectionFields } from '../publication'; import Format from '../formats/Format'; @@ -50,7 +55,14 @@ const PropertyComponent = ({ field, fields, resource, contributors, unValidatedF
); -PropertyComponent.propTypes = propertyPropTypes; +PropertyComponent.propTypes = { + contributors: PropTypes.arrayOf(contributorPropTypes).isRequired, + field: fieldPropTypes.isRequired, + fields: PropTypes.arrayOf(fieldPropTypes).isRequired, + p: polyglotPropTypes.isRequired, + resource: resourcePropTypes.isRequired, + unValidatedFields: PropTypes.arrayOf(PropTypes.string).isRequired, +}; const mapStateToProps = state => ({ unValidatedFields: getResourceUnvalidatedFields(state), diff --git a/src/app/js/propTypes.js b/src/app/js/propTypes.js index 24f13fdfa..26f89e3fc 100644 --- a/src/app/js/propTypes.js +++ b/src/app/js/propTypes.js @@ -14,6 +14,12 @@ export const field = PropTypes.shape({ scheme: PropTypes.string, }); +export const resource = PropTypes.shape({ + uri: PropTypes.string.isRequired, +}); + +export const contributor = PropTypes.object; + export const property = PropTypes.shape({ name: PropTypes.string.isRequired, value: PropTypes.any.isRequired,