Skip to content

Commit

Permalink
Merge pull request #380 from datacite/feature_relatedID
Browse files Browse the repository at this point in the history
Feature related identifier field
  • Loading branch information
kjgarza authored Mar 26, 2020
2 parents 9a3b7c1 + 5043ba9 commit 5008039
Show file tree
Hide file tree
Showing 24 changed files with 1,844 additions and 40 deletions.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ CDN_URL=https://assets.test.datacite.org
JWT_PUBLIC_KEY=-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxWfFGoaO4d9s7OoW34UD\nbEbFdh1FrAXT5QmWVocZIP0Y+1KtNGNjpRpazlSWeSMFuswoDG/cKiJX3BQkP7fw\nbHCujQoNpQqznsI8rRJYZh/L+THxjY7OEoFg7QohqnEHRr9YW4wPzh+I0xj2puVr\ngyQzREYckeBUEJnS2uXdiZ32LzbiH4pE+wwZNVQv0BbadnTc2mJWMaEcUfuh0Qko\nxIVpPwTCzyD4kMriETe+/AOw/2DEwbNJakh8N2ySMhXbso/zHxStEw2YesJkNJWG\n+aG5ApSbwTba8DVHKvTgCsE1d+1tHFyeruTxPIfamwA/VkVBuUpYR7CmJaoNuk1e\nKwIDAQAB\n-----END PUBLIC KEY-----\n
SENTRY_DSN=https://[email protected]/1420435
TRACKING_ID=UA-22806196-13
STAFF_ADMIN_PASSWORD=
ORGANIZATION_ADMIN_PASSWORD=
CONSORTIUM_ADMIN_PASSWORD=
CLIENT_ADMIN_PASSWORD=
225 changes: 225 additions & 0 deletions app/components/doi-related-identifier.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
/* eslint-disable no-useless-escape */
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { isURL, isISBN } from 'validator';

const relationTypeList = [
'Cites',
'IsCitedBy',
'Compiles',
'IsCompiledBy',
'Continues',
'IsContinuedBy',
'Describes',
'IsDescribedBy',
'Documents',
'IsDocumentedBy',
'IsDerivedFrom',
'IsSourceOf',
'HasMetadata',
'IsMetadataFor',
'HasPart',
'IsPartOf',
'IsSupplementedBy',
'IsSupplementTo',
'Obsoletes',
'IsObsoletedBy',
'References',
'IsReferencedBy',
'Requires',
'IsRequiredBy',
'Reviews',
'IsReviewedBy',
'HasVersion',
'IsVersionOf',
'IsNewVersionOf',
'IsPreviousVersionOf',
'IsVariantFormOf',
'IsOriginalFormOf',
'IsIdenticalTo',
];

const relatedIdentifierTypeList = [
'ARK',
'arXiv',
'bibcode',
'DOI',
'EAN13',
'EISSN',
'Handle',
'IGSN',
'ISBN',
'ISSN',
'ISTC',
'LISSN',
'LSID',
'PMID',
'PURL',
'UPC',
'URL',
'URN',
'w3id',
];

const resourceTypeGeneralList = [
'Audiovisual',
'Collection',
'DataPaper',
'Dataset',
'Event',
'Image',
'InteractiveResource',
'Model',
'PhysicalObject',
'Service',
'Software',
'Sound',
'Text',
'Workflow',
'Other',
];

export default Component.extend({
store: service(),
relationTypeList,
relationTypes: relationTypeList,
relatedIdentifierTypeList,
relatedIdentifierTypes: relatedIdentifierTypeList,
controlledIdentifierType: false,
isMetadataRelationType: false,
isMetadataRelationTypes: [ 'HasMetadata', 'IsMetadataFor' ],
resourceTypeGeneralList,
resourceTypesGeneral: resourceTypeGeneralList,

didReceiveAttrs() {
this._super(...arguments);

if (relatedIdentifierTypeList.includes(this.fragment.get('relatedIdentifierType'))) {
this.set('controlledIdentifierType', true);
} else {
this.set('controlledIdentifierType', false);
}
if (this.isMetadataRelationTypes.includes(this.fragment.get('relationType'))) {
this.set('isMetadataRelationType', true);
} else {
this.set('isMetadataRelationType', false);
}
},
updateRelatedIdentifier(value) {
const ark = /^ark:\/[0-9]{5}\/\S+$/;
const lsid = /^[uU][rR][nN]:[lL][sS][iI][dD]:(A-Za-z0-9][A-Za-z0-9()+,-.=@;$_!*'"%]):(A-Za-z0-9][A-Za-z0-9()+,-.=@;$_!*'"%]):(A-Za-z0-9][A-Za-z0-9()+,-.=@;$_!*'"%])[:]?(A-Za-z0-9][A-Za-z0-9()+,-.=@;$_!*'"%])?$/;
const purl = /^http?:\/\/(purl\.oclc\.org\/)/;
const arxiv = /^(arXiv:)(\d{4}.\d{4,5}|[a-z\-]+(\.[A-Z]{2})?\/\d{7})(v\d+)?/;
const doi = /^(10\.\d{4,5}\/.+)/;
const bibcode = /\d{4}[A-Za-z\.\&]{5}[\w\.]{4}[ELPQ-Z\.][\d\.]{4}[A-Z]/;
const urn = /^urn:[a-z0-9][a-z0-9-]{0,31}:[a-z0-9()+,\-.:=@;$_!*'%/?#]/;

switch (true) {
case value == null:
this.fragment.set('relatedIdentifier', null);
this.fragment.set('relatedIdentifierType', null);
this.set('controlledIdentifierType', false);
break;
case ark.test(value):
this.fragment.set('relatedIdentifier', value);
this.fragment.set('relatedIdentifierType', 'ARK');
this.set('controlledIdentifierType', true);
break;
case arxiv.test(value):
this.fragment.set('relatedIdentifier', value);
this.fragment.set('relatedIdentifierType', 'arXiv');
this.set('controlledIdentifierType', true);
break;
case doi.test(value):
this.fragment.set('relatedIdentifier', value);
this.fragment.set('relatedIdentifierType', 'DOI');
this.set('controlledIdentifierType', true);
break;
case bibcode.test(value):
this.fragment.set('relatedIdentifier', value);
this.fragment.set('relatedIdentifierType', 'bibcode');
this.set('controlledIdentifierType', true);
break;
case lsid.test(value):
this.fragment.set('relatedIdentifier', value);
this.fragment.set('relatedIdentifierType', 'LSID');
this.set('controlledIdentifierType', true);
break;
case purl.test(value):
this.fragment.set('relatedIdentifier', value);
this.fragment.set('relatedIdentifierType', 'PURL');
this.set('controlledIdentifierType', true);
break;
case urn.test(value):
this.fragment.set('relatedIdentifier', value);
this.fragment.set('relatedIdentifierType', 'URN');
this.set('controlledIdentifierType', true);
break;
case isISBN(value):
this.fragment.set('relatedIdentifier', value);
this.fragment.set('relatedIdentifierType', 'ISBN');
this.set('controlledIdentifierType', true);
break;
// // EAN currently not supported https://github.com/validatorjs/validator.js/issues/797
// case isEAN(value):
// this.fragment.set('relatedIdentifier', value);
// this.fragment.set('relatedIdentifierType', 'EAN13');
// this.set('controlledIdentifierType', true);
// break;
case isURL(value):
this.fragment.set('relatedIdentifier', value);
this.fragment.set('relatedIdentifierType', 'URL');
this.set('controlledIdentifierType', true);
break;
default:
// // Clears the relatedIdentifierType in case the user changes the relatedIdentifier after selecting it once before.
this.fragment.set('relatedIdentifier', value);
this.fragment.set('relatedIdentifierType', null);
this.set('controlledIdentifierType', false);
break;
}
},
selectRelationType(relationType) {
if (this.isMetadataRelationTypes.includes(relationType)) {
this.set('isMetadataRelationType', true);
} else {
this.set('isMetadataRelationType', false);
}
this.fragment.set('relationType', relationType);
this.set('relationTypes', relationTypeList);
},
selectRelatedIdentifierType(relatedIdentifierType) {
this.fragment.set('relatedIdentifierType', relatedIdentifierType);
this.set('relatedIdentifierTypes', relatedIdentifierTypeList);
},
selectResourceTypeGeneral(resourceTypeGeneral) {
this.fragment.set('resourceTypeGeneral', resourceTypeGeneral);
this.set('resourceTypesGeneral', resourceTypeGeneralList);
},
actions: {
updateRelatedIdentifier(value) {
this.updateRelatedIdentifier(value.trim());
},
updateRelatedMetadataScheme(value) {
this.fragment.set('relatedMetadataScheme', value);
},
updateSchemeURI(value) {
this.fragment.set('schemeUri', value);
},
updateSchemeType(value) {
this.fragment.set('schemeType', value);
},
selectRelationType(relationType) {
this.selectRelationType(relationType);
},
selectRelatedIdentifierType(relatedIdentifierType) {
this.selectRelatedIdentifierType(relatedIdentifierType);
},
selectResourceTypeGeneral(resourceTypeGeneral) {
this.selectResourceTypeGeneral(resourceTypeGeneral);
},
deleteRelatedIdentifier() {
this.model.get('relatedIdentifiers').removeObject(this.fragment);
},
},
});
21 changes: 21 additions & 0 deletions app/components/doi-related-identifiers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Component from '@ember/component';

export default Component.extend({
// validationClass: null,

didReceiveAttrs() {
this._super(...arguments);

if (!this.model.get('relatedIdentifiers')) {
this.model.set('relatedIdentifiers', []);
}
if (this.model.get('relatedIdentifiers').length == 0) {
this.model.get('relatedIdentifiers').createFragment();
}
},
actions: {
addRelatedIdentifier() {
this.model.get('relatedIdentifiers').createFragment();
},
},
});
5 changes: 5 additions & 0 deletions app/helpers/doi-form-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ export function doiFormErrors([ model ]) {
errorAttributes = errorAttributes.concat(subject.validations.errors.mapBy('attribute'));
});
}
if (model.relatedIdentifiers) {
model.relatedIdentifiers.forEach((relatedIdentifier) => {
errorAttributes = errorAttributes.concat(relatedIdentifier.validations.errors.mapBy('attribute'));
});
}
}

return errorAttributes.map(function(attribute) {
Expand Down
2 changes: 1 addition & 1 deletion app/models/doi.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export default DS.Model.extend(Validations, {
dates: DS.attr(),
language: DS.attr('string'),
types: DS.attr(),
relatedIdentifiers: DS.attr(),
relatedIdentifiers: fragmentArray('relatedIdentifier', { defaultValue: [] }),
sizes: DS.attr(),
formats: DS.attr(),
version: DS.attr('string'),
Expand Down
77 changes: 77 additions & 0 deletions app/models/related-identifier.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import DS from 'ember-data';
import Fragment from 'ember-data-model-fragments/fragment';
import { validator, buildValidations } from 'ember-cp-validations';
import { computed } from '@ember/object';

const Validations = buildValidations({
schemeUri: [
validator('url-format', {
allowBlank: true,
require_tld: false,
message: 'Please enter a valid URL.',
}),
],
relatedIdentifier: [
validator('url-format', {
allowBlank: true,
message: 'Please enter a valid URL.',
isWarning: computed('model.state', function() {
return this.model.get('state') === 'draft';
}),
disabled: computed('model.relatedIdentifierType', function() {
return ![ 'PURL','URL' ].includes(this.model.get('relatedIdentifierType'));
}),
}),
validator('identifier-format', {
allowBlank: true,
dependentKeys: [ 'model.relatedIdentifierType' ],
message: 'Please enter a valid Related Identifier.',
isWarning: computed('model.state', function() {
return this.model.get('state') === 'draft';
}),
}),
],
relatedIdentifierType: [
validator('presence', {
presence: true,
isWarning: computed('model.state', function() {
return this.model.get('state') === 'draft';
}),
disabled: computed('model.relatedIdentifier', function() {
return this.model.get('relatedIdentifier') == null;
}),
}),
],
relationType: [
validator('presence', {
presence: true,
isWarning: computed('model.state', function() {
return this.model.get('state') === 'draft';
}),
disabled: computed('model.relatedIdentifier', function() {
return this.model.get('relatedIdentifier') == null;
}),
}),
],
resourceTypeGeneral: [
validator('presence', {
presence: true,
isWarning: computed('model.state', function() {
return this.model.get('state') === 'draft';
}),
disabled: computed('model.relatedIdentifier', function() {
return this.model.get('relatedIdentifier') == null;
}),
}),
],
});

export default Fragment.extend(Validations, {
relatedIdentifier: DS.attr('string', { defaultValue: null }),
relatedIdentifierType: DS.attr('string', { defaultValue: null }),
relationType: DS.attr('string', { defaultValue: null }),
relatedMetadataScheme: DS.attr('string', { defaultValue: null }),
schemeUri: DS.attr('string', { defaultValue: null }),
schemeType: DS.attr('string', { defaultValue: null }),
resourceTypeGeneral: DS.attr('string', { defaultValue: null }),
});
2 changes: 1 addition & 1 deletion app/serializers/doi.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default ApplicationSerializer.extend({
// contributors: { serialize: false },
dates: { serialize: false },
// language: { serialize: false },
relatedIdentifiers: { serialize: false },
// relatedIdentifiers: { serialize: false },
sizes: { serialize: false },
formats: { serialize: false },
version: { serialize: false },
Expand Down
Loading

0 comments on commit 5008039

Please sign in to comment.