diff --git a/src/plugins/recordTypes/dutyofcare/advancedSearch.js b/src/plugins/recordTypes/dutyofcare/advancedSearch.js new file mode 100644 index 00000000..77dace22 --- /dev/null +++ b/src/plugins/recordTypes/dutyofcare/advancedSearch.js @@ -0,0 +1,21 @@ +export default (configContext) => { + const { + OP_CONTAIN, + } = configContext.searchOperators; + + const { + defaultAdvancedSearchBooleanOp, + extensions, + } = configContext.config; + + return { + op: defaultAdvancedSearchBooleanOp, + value: [ + { + op: OP_CONTAIN, + path: 'ns2:dutyofcares_common/dutyOfCareNumber', + }, + ...extensions.core.advancedSearch, + ], + }; +}; diff --git a/src/plugins/recordTypes/dutyofcare/columns.js b/src/plugins/recordTypes/dutyofcare/columns.js new file mode 100644 index 00000000..3b41edd3 --- /dev/null +++ b/src/plugins/recordTypes/dutyofcare/columns.js @@ -0,0 +1,46 @@ +import { defineMessages } from 'react-intl'; + +export default (configContext) => { + const { + formatTimestamp, + } = configContext.formatHelpers; + + return { + default: { + dutyOfCareNumber: { + messages: defineMessages({ + label: { + id: 'column.dutyofcare.default.dutyOfCareNumber', + defaultMessage: 'Duty of care number', + }, + }), + order: 10, + sortBy: 'dutyofcares_common:dutyOfCareNumber', + width: 200, + }, + title: { + messages: defineMessages({ + label: { + id: 'column.dutyofcare.default.title', + defaultMessage: 'Title', + }, + }), + order: 20, + sortBy: 'dutyofcares_common:title', + width: 200, + }, + updatedAt: { + formatValue: formatTimestamp, + messages: defineMessages({ + label: { + id: 'column.dutyofcare.default.updatedAt', + defaultMessage: 'Updated', + }, + }), + order: 30, + sortBy: 'collectionspace_core:updatedAt', + width: 150, + }, + }, + }; +}; diff --git a/src/plugins/recordTypes/dutyofcare/fields.js b/src/plugins/recordTypes/dutyofcare/fields.js new file mode 100644 index 00000000..eeaffd10 --- /dev/null +++ b/src/plugins/recordTypes/dutyofcare/fields.js @@ -0,0 +1,333 @@ +import { defineMessages } from 'react-intl'; + +export default (configContext) => { + const { + AutocompleteInput, + CompoundInput, + DateInput, + IDGeneratorInput, + TextInput, + TermPickerInput, + } = configContext.inputComponents; + + const { + configKey: config, + } = configContext.configHelpers; + + const { + DATA_TYPE_DATE, + } = configContext.dataTypes; + + const { + extensions, + } = configContext.config; + + const { + validateNotInUse, + } = configContext.validationHelpers; + + return { + document: { + [config]: { + view: { + type: CompoundInput, + props: { + defaultChildSubpath: 'ns2:dutyofcares_common', + }, + }, + }, + ...extensions.core.fields, + 'ns2:dutyofcares_common': { + [config]: { + service: { + ns: 'http://collectionspace.org/services/dutyofcare', + }, + }, + dutyOfCareNumber: { + [config]: { + cloneable: false, + messages: defineMessages({ + inUse: { + id: 'field.dutyofcares_common.dutyOfCareNumber.inUse', + defaultMessage: 'The identification number {value} is in use by another record.', + }, + name: { + id: 'field.dutyofcares_common.dutyOfCareNumber.name', + defaultMessage: 'Duty of care number', + }, + }), + required: true, + searchView: { + type: TextInput, + }, + validate: (validationContext) => validateNotInUse({ + configContext, + validationContext, + fieldName: 'dutyofcares_common:dutyOfCareNumber', + }), + view: { + type: IDGeneratorInput, + props: { + source: 'dutyofcare', + }, + }, + }, + }, + originationDate: { + [config]: { + dataType: DATA_TYPE_DATE, + messages: defineMessages({ + name: { + id: 'field.dutyofcares_common.originationDate.name', + defaultMessage: 'Origination date', + }, + }), + view: { + type: DateInput, + }, + }, + }, + title: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.dutyofcares_common.title.name', + defaultMessage: 'Title', + }, + }), + view: { + type: TextInput, + }, + }, + }, + notes: { + [config]: { + view: { + type: CompoundInput, + }, + }, + note: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.dutyofcares_common.note.name', + defaultMessage: 'Note', + }, + }), + repeating: true, + view: { + type: TextInput, + props: { + multiline: true, + }, + }, + }, + }, + }, + detailGroupList: { + [config]: { + view: { + type: CompoundInput, + }, + }, + detailGroup: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.dutyofcares_common.detailGroup.name', + defaultMessage: 'Duty of care detail', + }, + }), + repeating: true, + view: { + type: CompoundInput, + }, + }, + detailType: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.dutyofcares_common.detailType.fullName', + defaultMessage: 'Duty of care detail type', + }, + name: { + id: 'field.dutyofcares_common.detailType.name', + defaultMessage: 'Type', + }, + }), + view: { + type: TermPickerInput, + props: { + source: 'nagpratype', + }, + }, + }, + }, + detailLevel: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.dutyofcares_common.detailLevel.fullName', + defaultMessage: 'Duty of care detail level', + }, + name: { + id: 'field.dutyofcares_common.detailLevel.name', + defaultMessage: 'Level', + }, + }), + view: { + type: TermPickerInput, + props: { + source: 'nagpralevel', + }, + }, + }, + }, + detailDeterminedBy: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.dutyofcares_common.detailDeterminedBy.fullName', + defaultMessage: 'Duty of care detail determined by', + }, + name: { + id: 'field.dutyofcares_common.detailDeterminedBy.name', + defaultMessage: 'Determined by', + }, + }), + view: { + type: AutocompleteInput, + props: { + source: 'person/local,organization/local', + }, + }, + }, + }, + detailDeterminationDate: { + [config]: { + dataType: DATA_TYPE_DATE, + messages: defineMessages({ + fullName: { + id: 'field.dutyofcares_common.detailDeterminationDate.fullName', + defaultMessage: 'Duty of care detail determination date', + }, + name: { + id: 'field.dutyofcares_common.detailDeterminationDate.name', + defaultMessage: 'Determination date', + }, + }), + view: { + type: DateInput, + }, + }, + }, + detailNote: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.dutyofcares_common.detailNote.fullName', + defaultMessage: 'Duty of care detail note', + }, + name: { + id: 'field.dutyofcares_common.detailNote.name', + defaultMessage: 'Note', + }, + }), + view: { + type: TextInput, + props: { + multiline: true, + }, + }, + }, + }, + }, + }, + partiesInvolvedGroupList: { + [config]: { + view: { + type: CompoundInput, + }, + }, + partiesInvolvedGroup: { + [config]: { + messages: defineMessages({ + name: { + id: 'field.dutyofcares_common.partiesInvolvedGroup.name', + defaultMessage: 'Party involved', + }, + }), + repeating: true, + view: { + type: CompoundInput, + props: { + tabular: true, + }, + }, + }, + involvedParty: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.dutyofcares_common.involvedParty.fullName', + defaultMessage: 'Party involved name', + }, + name: { + id: 'field.dutyofcares_common.involvedParty.name', + defaultMessage: 'Name', + }, + }), + view: { + type: AutocompleteInput, + props: { + source: 'person/local', + }, + }, + }, + }, + involvedOnBehalfOf: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.dutyofcares_common.involvedOnBehalfOf.fullName', + defaultMessage: 'Party involved on behalf of', + }, + name: { + id: 'field.dutyofcares_common.involvedOnBehalfOf.name', + defaultMessage: 'On behalf of', + }, + }), + view: { + type: AutocompleteInput, + props: { + source: 'organization/local', + }, + }, + }, + }, + involvedRole: { + [config]: { + messages: defineMessages({ + fullName: { + id: 'field.dutyofcares_common.involvedRole.fullName', + defaultMessage: 'Party involved roles', + }, + name: { + id: 'field.dutyofcares_common.involvedRole.name', + defaultMessage: 'Role', + }, + }), + view: { + type: TermPickerInput, + props: { + source: 'nagprainvolvedrole', + }, + }, + }, + }, + }, + }, + }, + }, + }; +}; diff --git a/src/plugins/recordTypes/dutyofcare/forms/default.jsx b/src/plugins/recordTypes/dutyofcare/forms/default.jsx new file mode 100644 index 00000000..f41cf2c3 --- /dev/null +++ b/src/plugins/recordTypes/dutyofcare/forms/default.jsx @@ -0,0 +1,69 @@ +import { defineMessages } from 'react-intl'; + +const template = (configContext) => { + const { + React, + } = configContext.lib; + + const { + Col, + Cols, + Panel, + Row, + } = configContext.layoutComponents; + + const { + Field, + } = configContext.recordComponents; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default (configContext) => ({ + messages: defineMessages({ + name: { + id: 'form.dutyofcare.default.name', + defaultMessage: 'Standard Template', + }, + }), + template: template(configContext), +}); diff --git a/src/plugins/recordTypes/dutyofcare/forms/index.js b/src/plugins/recordTypes/dutyofcare/forms/index.js new file mode 100644 index 00000000..b04a0c7d --- /dev/null +++ b/src/plugins/recordTypes/dutyofcare/forms/index.js @@ -0,0 +1,5 @@ +import defaultForm from './default'; + +export default (configContext) => ({ + default: defaultForm(configContext), +}); diff --git a/src/plugins/recordTypes/dutyofcare/idGenerators.js b/src/plugins/recordTypes/dutyofcare/idGenerators.js new file mode 100644 index 00000000..098a2f6b --- /dev/null +++ b/src/plugins/recordTypes/dutyofcare/idGenerators.js @@ -0,0 +1,13 @@ +import { defineMessages } from 'react-intl'; + +export default { + dutyofcare: { + csid: '6205cfe5-d144-4e89-b641-0e8e4b356f34', + messages: defineMessages({ + type: { + id: 'idGenerator.dutyofcare.type', + defaultMessage: 'Duty of care', + }, + }), + }, +}; diff --git a/src/plugins/recordTypes/dutyofcare/index.js b/src/plugins/recordTypes/dutyofcare/index.js new file mode 100644 index 00000000..240e75bc --- /dev/null +++ b/src/plugins/recordTypes/dutyofcare/index.js @@ -0,0 +1,23 @@ +import advancedSearch from './advancedSearch'; +import columns from './columns'; +import fields from './fields'; +import forms from './forms'; +import idGenerators from './idGenerators'; +import messages from './messages'; +import serviceConfig from './serviceConfig'; +import title from './title'; + +export default () => (configContext) => ({ + idGenerators, + recordTypes: { + dutyofcare: { + messages, + serviceConfig, + advancedSearch: advancedSearch(configContext), + columns: columns(configContext), + fields: fields(configContext), + forms: forms(configContext), + title: title(configContext), + }, + }, +}); diff --git a/src/plugins/recordTypes/dutyofcare/messages.js b/src/plugins/recordTypes/dutyofcare/messages.js new file mode 100644 index 00000000..415e1efc --- /dev/null +++ b/src/plugins/recordTypes/dutyofcare/messages.js @@ -0,0 +1,22 @@ +import { defineMessages } from 'react-intl'; + +export default { + record: defineMessages({ + name: { + id: 'record.dutyofcare.name', + description: 'The name of the record type', + defaultMessage: 'Duty of Care', + }, + collectionName: { + id: 'record.dutyofcare.collectionName', + description: 'The name of a collection of records of the type.', + defaultMessage: 'Duty of Cares', + }, + }), + panel: defineMessages({ + info: { + id: 'panel.dutyofcare.info', + defaultMessage: 'Duty of Care Information', + }, + }), +}; diff --git a/src/plugins/recordTypes/dutyofcare/serviceConfig.js b/src/plugins/recordTypes/dutyofcare/serviceConfig.js new file mode 100644 index 00000000..c7a2bcc8 --- /dev/null +++ b/src/plugins/recordTypes/dutyofcare/serviceConfig.js @@ -0,0 +1,8 @@ +export default { + serviceName: 'Dutyofcare', + servicePath: 'dutyofcares', + serviceType: 'procedure', + + objectName: 'Dutyofcare', + documentName: 'Dutyofcares', +}; diff --git a/src/plugins/recordTypes/dutyofcare/title.js b/src/plugins/recordTypes/dutyofcare/title.js new file mode 100644 index 00000000..db131636 --- /dev/null +++ b/src/plugins/recordTypes/dutyofcare/title.js @@ -0,0 +1,20 @@ +export default (configContext) => (data) => { + const { + getPart, + } = configContext.recordDataHelpers; + + if (!data) { + return ''; + } + + const common = getPart(data, 'dutyofcares_common'); + + if (!common) { + return ''; + } + + const referenceNumber = common.get('dutyOfCareNumber'); + const title = common.get('title'); + + return [referenceNumber, title].filter((part) => !!part).join(' – '); +}; diff --git a/src/plugins/recordTypes/index.js b/src/plugins/recordTypes/index.js index 8d6a9244..03b2b5fe 100644 --- a/src/plugins/recordTypes/index.js +++ b/src/plugins/recordTypes/index.js @@ -14,6 +14,7 @@ import concept from './concept'; import conditioncheck from './conditioncheck'; import conservation from './conservation'; import contact from './contact'; +import dutyofcare from './dutyofcare'; import exhibition from './exhibition'; import exxport from './export'; import group from './group'; @@ -60,6 +61,7 @@ export default [ conditioncheck, conservation, contact, + dutyofcare, exhibition, exxport, group, diff --git a/test/specs/plugins/recordTypes/dutyofcare/advancedSearch.spec.js b/test/specs/plugins/recordTypes/dutyofcare/advancedSearch.spec.js new file mode 100644 index 00000000..72f961a5 --- /dev/null +++ b/test/specs/plugins/recordTypes/dutyofcare/advancedSearch.spec.js @@ -0,0 +1,16 @@ +import createConfigContext from '../../../../../src/helpers/createConfigContext'; +import advancedSearch from '../../../../../src/plugins/recordTypes/dutyofcare/advancedSearch'; + +chai.should(); + +describe('dutyofcare record advanced search', () => { + const configContext = createConfigContext(); + + it('should contain a top level property `op`', () => { + advancedSearch(configContext).should.have.property('op'); + }); + + it('should contain a top level property `value` that is an array', () => { + advancedSearch(configContext).should.have.property('value').that.is.an('array'); + }); +}); diff --git a/test/specs/plugins/recordTypes/dutyofcare/columns.spec.js b/test/specs/plugins/recordTypes/dutyofcare/columns.spec.js new file mode 100644 index 00000000..875e3f2f --- /dev/null +++ b/test/specs/plugins/recordTypes/dutyofcare/columns.spec.js @@ -0,0 +1,15 @@ +import dutyOfCareRecordTypePluginFactory from '../../../../../src/plugins/recordTypes/dutyofcare'; +import createColumns from '../../../../../src/plugins/recordTypes/dutyofcare/columns'; +import createConfigContext from '../../../../../src/helpers/createConfigContext'; + +chai.should(); + +describe('dutyofcare record columns', () => { + const dutyOfCareRecordTypePlugin = dutyOfCareRecordTypePluginFactory({}); + const configContext = createConfigContext(dutyOfCareRecordTypePlugin); + const columns = createColumns(configContext); + + it('should have the correct shape', () => { + columns.should.have.property('default').that.is.an('object'); + }); +}); diff --git a/test/specs/plugins/recordTypes/dutyofcare/forms/default.spec.js b/test/specs/plugins/recordTypes/dutyofcare/forms/default.spec.js new file mode 100644 index 00000000..c6ef9193 --- /dev/null +++ b/test/specs/plugins/recordTypes/dutyofcare/forms/default.spec.js @@ -0,0 +1,14 @@ +import Field from '../../../../../../src/components/record/Field'; +import form from '../../../../../../src/plugins/recordTypes/dutyofcare/forms/default'; +import createConfigContext from '../../../../../../src/helpers/createConfigContext'; + +chai.should(); + +describe('dutyofcare record default form', () => { + it('should be a Field', () => { + const configContext = createConfigContext(); + const { template } = form(configContext); + + template.type.should.equal(Field); + }); +}); diff --git a/test/specs/plugins/recordTypes/dutyofcare/index.spec.js b/test/specs/plugins/recordTypes/dutyofcare/index.spec.js new file mode 100644 index 00000000..926f3b27 --- /dev/null +++ b/test/specs/plugins/recordTypes/dutyofcare/index.spec.js @@ -0,0 +1,29 @@ +import dutyOfCareRecordTypePluginFactory from '../../../../../src/plugins/recordTypes/dutyofcare'; +import createConfigContext from '../../../../../src/helpers/createConfigContext'; + +chai.should(); + +describe('dutyofcare record plugin', () => { + const config = {}; + const dutyOfCareRecordTypePlugin = dutyOfCareRecordTypePluginFactory(config); + const configContext = createConfigContext(dutyOfCareRecordTypePlugin); + + it('should have the correct shape', () => { + const pluginConfiguration = dutyOfCareRecordTypePlugin(configContext); + + const { + recordTypes, + } = pluginConfiguration; + + recordTypes.should.have.property('dutyofcare'); + + const dutyOfCareRecordType = recordTypes.dutyofcare; + + dutyOfCareRecordType.should.have.property('title').that.is.a('function'); + dutyOfCareRecordType.should.have.property('forms').that.is.an('object'); + dutyOfCareRecordType.should.have.property('messages').that.is.an('object'); + dutyOfCareRecordType.should.have.property('serviceConfig').that.is.an('object'); + + dutyOfCareRecordType.title().should.be.a('string'); + }); +}); diff --git a/test/specs/plugins/recordTypes/dutyofcare/messages.spec.js b/test/specs/plugins/recordTypes/dutyofcare/messages.spec.js new file mode 100644 index 00000000..6b9b4819 --- /dev/null +++ b/test/specs/plugins/recordTypes/dutyofcare/messages.spec.js @@ -0,0 +1,17 @@ +import messages from '../../../../../src/plugins/recordTypes/dutyofcare/messages'; + +chai.should(); + +describe('dutyofcare record messages', () => { + it('should contain properties with an id and defaultMessage properties', () => { + messages.should.be.an('object'); + + Object.keys(messages).forEach((dutyOfCareNmae) => { + const dutyOfCareMessages = messages[dutyOfCareNmae]; + + Object.keys(dutyOfCareMessages).forEach((name) => { + dutyOfCareMessages[name].should.contain.all.keys(['id', 'defaultMessage']); + }); + }); + }); +}); diff --git a/test/specs/plugins/recordTypes/dutyofcare/serviceConfig.spec.js b/test/specs/plugins/recordTypes/dutyofcare/serviceConfig.spec.js new file mode 100644 index 00000000..f77a42cc --- /dev/null +++ b/test/specs/plugins/recordTypes/dutyofcare/serviceConfig.spec.js @@ -0,0 +1,13 @@ +import serviceConfig from '../../../../../src/plugins/recordTypes/dutyofcare/serviceConfig'; + +chai.should(); + +describe('dutyofcare record serviceConfig', () => { + it('should have a servicePath property', () => { + serviceConfig.should.have.property('servicePath').that.is.a('string'); + serviceConfig.should.have.property('serviceName').that.is.a('string'); + serviceConfig.should.have.property('serviceType').that.is.a('string'); + serviceConfig.should.have.property('objectName').that.is.a('string'); + serviceConfig.should.have.property('documentName').that.is.a('string'); + }); +}); diff --git a/test/specs/plugins/recordTypes/dutyofcare/title.spec.js b/test/specs/plugins/recordTypes/dutyofcare/title.spec.js new file mode 100644 index 00000000..6141ecb2 --- /dev/null +++ b/test/specs/plugins/recordTypes/dutyofcare/title.spec.js @@ -0,0 +1,64 @@ +import Immutable from 'immutable'; +import createTitleGetter from '../../../../../src/plugins/recordTypes/dutyofcare/title'; +import createConfigContext from '../../../../../src/helpers/createConfigContext'; + +chai.should(); + +describe('dutyofcare record title', () => { + const configContext = createConfigContext(); + const title = createTitleGetter(configContext); + + it('should return the dutyofcare number and title when both are present', () => { + const data = Immutable.fromJS({ + document: { + 'ns2:dutyofcares_common': { + dutyOfCareNumber: 'DC', + title: 'Title', + }, + }, + }); + + title(data).should.equal('DC – Title'); + }); + + it('should return the dutyofcare number only when the title is missing', () => { + const data = Immutable.fromJS({ + document: { + 'ns2:dutyofcares_common': { + dutyOfCareNumber: 'DC', + }, + }, + }); + + title(data).should.equal('DC'); + }); + + it('should return the title only when the dutyofcare number is missing', () => { + const data = Immutable.fromJS({ + document: { + 'ns2:dutyofcares_common': { + title: 'Title', + }, + }, + }); + + title(data).should.equal('Title'); + }); + + it('should return an empty string if no document is passed', () => { + title(null).should.equal(''); + title(undefined).should.equal(''); + }); + + it('should return an empty string if the common part is not present', () => { + const data = Immutable.fromJS({ + document: { + 'ns2:dutyofcares_extension': { + dutyofcareAltTitle: 'Alt dutyofcare title', + }, + }, + }); + + title(data).should.equal(''); + }); +});