diff --git a/src/containers/input/FieldTextInputContainer.jsx b/src/containers/input/FieldTextInputContainer.jsx index c25e5f9d..05fb0759 100644 --- a/src/containers/input/FieldTextInputContainer.jsx +++ b/src/containers/input/FieldTextInputContainer.jsx @@ -1,7 +1,10 @@ import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { components as inputComponents } from 'cspace-input'; -import { injectIntl, intlShape } from 'react-intl'; +import { injectIntl, intlShape, defineMessages } from 'react-intl'; +import get from 'lodash/get'; +import { NS_PREFIX } from '../../constants/xmlNames'; +import { configKey } from '../../helpers/configHelpers'; import { formatRecordTypeSourceField } from '../../helpers/formatHelpers'; import withConfig from '../../enhancers/withConfig'; import withCsid from '../../enhancers/withCsid'; @@ -16,18 +19,67 @@ const propTypes = { value: PropTypes.string, }; +const messages = defineMessages({ + listItem: { + id: 'fieldTextInput.listItem', + description: 'Item in a group list', + defaultMessage: '{groupList} #{index} — {listItem}', + }, +}); + +export const getFirstChild = (recordType, partName, fieldName, { config }) => { + const recordTypeConfig = config.recordTypes[recordType]; + const partDescriptor = get(recordTypeConfig, ['fields', 'document', `${NS_PREFIX}:${partName}`]); + if (!partDescriptor) { + return fieldName; + } + + let updatedField = fieldName; + const fieldDescriptor = partDescriptor[fieldName]; + if (fieldDescriptor) { + updatedField = Object.keys(fieldDescriptor).filter((key) => key !== configKey); + } + + return updatedField; +}; + export const formatHumanReadable = (type, value, context) => { let formatted; // the key is created with schema:fieldName:listIndex // we have 3 outcomes -- an array of index 1 (unqualified), 2 (qualified), or 3 (qualified list) + // for qualified lists, use the child key if available // see: AuditDocumentHandler.java const parts = value.split(':'); + const [partName, fieldName] = parts; if (parts.length === 2) { - formatted = formatRecordTypeSourceField(type, value, context); + let searchField = fieldName; + + // capture either the last field or the full name of the group list + const groupRegex = /(?\w+GroupList)$/; + const fieldRegex = /(?\w+)\/(?\d+)\/(?\w+\/?)+$/; + + const match = fieldRegex.exec(fieldName); + if (match) { + const { intl } = context; + const groupChild = getFirstChild(type, partName, match.groups.groupList, context); + const formattedGroup = formatRecordTypeSourceField(type, `${partName}:${groupChild}`, context); + const formattedListItem = formatRecordTypeSourceField(type, `${partName}:${match.groups.field}`, context); + return intl.formatMessage(messages.listItem, { + groupList: formattedGroup, + index: match.groups.index, + listItem: formattedListItem, + }); + } + + if (groupRegex.exec(fieldName)) { + searchField = getFirstChild(type, partName, fieldName, context); + } + + formatted = formatRecordTypeSourceField(type, `${partName}:${searchField}`, context); } else if (parts.length === 3) { - // todo: get child of the key - formatted = formatRecordTypeSourceField(type, `${parts[0]}:${parts[1]}`, context); + const childName = getFirstChild(type, partName, fieldName, context); + formatted = formatRecordTypeSourceField(type, `${partName}:${childName}`, context); } else { formatted = value; } diff --git a/test/specs/containers/input/FieldTextInputContainer.spec.jsx b/test/specs/containers/input/FieldTextInputContainer.spec.jsx index 8df4a154..24f77a7c 100644 --- a/test/specs/containers/input/FieldTextInputContainer.spec.jsx +++ b/test/specs/containers/input/FieldTextInputContainer.spec.jsx @@ -18,12 +18,51 @@ const intl = { const recordType = 'collectionobject'; const objectNumberConfig = { - messages: defineMessages({ - name: { - id: 'field.collectionobjects_common.objectNumber.name', - defaultMessage: 'Identification number', + [configKey]: { + messages: defineMessages({ + name: { + id: 'field.collectionobjects_common.objectNumber.name', + defaultMessage: 'Identification number', + }, + }), + }, +}; + +const commentsConfig = { + comment: { + [configKey]: { + messages: defineMessages({ + name: { + id: 'field.collectionobjects_common.comment.name', + defaultMessage: 'Comment', + }, + }), + }, + }, +}; + +const titleGroupListConfig = { + titleGroup: { + [configKey]: { + messages: defineMessages({ + name: { + id: 'field.collectionobjects_common.titleGroup.name', + defaultMessage: 'Title', + }, + }), + + }, + titleLanguage: { + [configKey]: { + messages: defineMessages({ + name: { + id: 'field.collectionobjects_common.titleLanguage.name', + defaultMessage: 'Title language', + }, + }), + }, }, - }), + }, }; const config = { @@ -32,9 +71,9 @@ const config = { fields: { document: { 'ns2:collectionobjects_common': { - objectNumber: { - [configKey]: objectNumberConfig, - }, + objectNumber: objectNumberConfig, + comments: commentsConfig, + titleGroupList: titleGroupListConfig, }, }, }, @@ -43,12 +82,31 @@ const config = { }; describe('FieldTextInputContainer', () => { - it('should return human readable input when available', () => { + it('should return the default message for fields', () => { const field = 'collectionobjects_common:objectNumber'; const formatted = formatHumanReadable(recordType, field, { intl, config }); formatted.should.equal('Identification number'); }); + it('should return the child message for lists', () => { + const field = 'collectionobjects_common:comments:03E8'; + const formatted = formatHumanReadable(recordType, field, { intl, config }); + formatted.should.equal('Comment'); + }); + + it('should return the group message for GroupLists', () => { + const field = 'collectionobjects_common:titleGroupList'; + const formatted = formatHumanReadable(recordType, field, { intl, config }); + formatted.should.equal('Title'); + }); + + it('should return the group, index, and item for GroupList items', () => { + const field = 'collectionobjects_common:titleGroupList/0/titleLanguage'; + const formatted = formatHumanReadable(recordType, field, { intl, config }); + // would be nice to have an actual intl fill this in + formatted.should.equal('{groupList} #{index} — {listItem}'); + }); + it('should return the field when formatting is not available', () => { const field = 'collectionspace_core:uri'; const formatted = formatHumanReadable(recordType, field, { intl, config });