cspace-ui
Version:
CollectionSpace user interface for browsers
199 lines (193 loc) • 7.91 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = Field;
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _reactIntl = require("react-intl");
var _immutable = _interopRequireDefault(require("immutable"));
var _get = _interopRequireDefault(require("lodash/get"));
var _warning = _interopRequireDefault(require("warning"));
var _cspaceInput = require("cspace-input");
var _configHelpers = require("../../helpers/configHelpers");
var _configContextInputs = require("../../helpers/configContextInputs");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
const {
getPath,
pathPropType
} = _cspaceInput.helpers.pathHelpers;
const {
Label
} = _cspaceInput.components;
const renderLabel = (fieldDescriptor, providedLabelMessage, computeContext, props) => {
const fieldConfig = fieldDescriptor[_configHelpers.configKey];
const message = providedLabelMessage || (0, _get.default)(fieldConfig, ['messages', 'name']);
if (!message) {
return null;
}
const configuredProps = {};
if ('required' in fieldConfig) {
configuredProps.required = (0, _configHelpers.isFieldRequired)(computeContext);
}
const viewReadOnly = (0, _configHelpers.isFieldViewReadOnly)(computeContext);
if (typeof viewReadOnly !== 'undefined') {
configuredProps.readOnly = viewReadOnly;
}
return /*#__PURE__*/_react.default.createElement(Label, _extends({}, props, configuredProps), /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, message));
};
const propTypes = {
labelMessage: _propTypes.default.shape({
id: _propTypes.default.string,
defaultMessage: _propTypes.default.string
}),
viewType: _propTypes.default.string,
// Code in this component doesn't use these props, but the propTypes need to exist, because
// users of this component may check for them to determine if those props should be passed.
// We want to receive all the props that our base components may need, and then we'll handle
// distributing them to the base components that accept them.
/* eslint-disable react/no-unused-prop-types */
name: _propTypes.default.string,
// The value prop will be validated by the base component, so allow anything here.
// eslint-disable-next-line react/forbid-prop-types
value: _propTypes.default.any,
parentPath: _propTypes.default.arrayOf(_propTypes.default.string),
subpath: pathPropType,
tabular: _propTypes.default.bool,
label: _propTypes.default.node,
readOnly: _propTypes.default.bool,
onAddInstance: _propTypes.default.func,
onCommit: _propTypes.default.func,
onMoveInstance: _propTypes.default.func,
onRemoveInstance: _propTypes.default.func,
onSortInstances: _propTypes.default.func
/* eslint-enable react/no-unused-prop-types */
};
const contextTypes = {
config: _propTypes.default.shape({
recordTypes: _propTypes.default.object
}),
formName: _propTypes.default.string,
intl: _reactIntl.intlShape,
recordData: _propTypes.default.instanceOf(_immutable.default.Map),
recordType: _propTypes.default.string,
recordTypeConfig: _propTypes.default.shape({
fields: _propTypes.default.object
}),
roleNames: _propTypes.default.instanceOf(_immutable.default.List),
subrecordData: _propTypes.default.instanceOf(_immutable.default.Map)
};
function Field(props, context) {
const {
config,
formName,
intl,
recordData,
recordType,
roleNames,
subrecordData,
recordTypeConfig: contextRecordTypeConfig
} = context;
const {
labelMessage,
viewType
} = props;
const recordTypeConfig = contextRecordTypeConfig || (0, _get.default)(config, ['recordTypes', recordType]);
const fullPath = getPath(props);
// Filter out numeric parts of the path, since they indicate repeating instances that won't be
// present in the field descriptor.
const path = (0, _configHelpers.dataPathToFieldDescriptorPath)(fullPath);
const fields = (0, _get.default)(recordTypeConfig, 'fields');
process.env.NODE_ENV !== "production" ? (0, _warning.default)(fields, `No field descriptor found for the record type ${recordType}. The field with path ${path} will not be rendered.`) : void 0;
if (!fields) {
return null;
}
const field = (0, _get.default)(fields, path);
process.env.NODE_ENV !== "production" ? (0, _warning.default)(field, `The path ${path} is not present in the field descriptors for the record type ${recordType}. The field will not be rendered.`) : void 0;
if (!field) {
return null;
}
const fieldConfig = field[_configHelpers.configKey];
const isSearch = viewType === 'search';
const viewConfig = isSearch ? fieldConfig.searchView || fieldConfig.view : fieldConfig.view;
let BaseComponent = viewConfig.type;
if (isSearch && !fieldConfig.searchView && BaseComponent === _configContextInputs.StructuredDateInput) {
// If a search view was not explicitly configured, and the view is a StructuredDateInput,
// automatically make the search view a DateInput.
BaseComponent = _configContextInputs.DateInput;
}
const configuredProps = viewConfig.props || {};
const providedProps = {};
// FIXME: Do this without looking at the base component propTypes, so that propTypes can be
// removed in production builds.
// eslint-disable-next-line react/forbid-foreign-prop-types
const basePropTypes = BaseComponent.propTypes;
Object.keys(props).forEach(propName => {
if (propName in basePropTypes) {
// eslint-disable-next-line react/destructuring-assignment
providedProps[propName] = props[propName];
}
});
const computeContext = {
isSearch,
path,
recordData,
subrecordData,
fieldDescriptor: field,
recordType,
form: formName,
roleNames
};
const effectiveReadOnly = providedProps.readOnly || (0, _configHelpers.isFieldViewReadOnly)(computeContext);
const computedProps = {};
if (fieldConfig.repeating && viewType !== 'search') {
computedProps.repeating = fieldConfig.repeating;
}
if ('label' in basePropTypes) {
computedProps.label = renderLabel(field, labelMessage, computeContext, {
readOnly: effectiveReadOnly
});
}
if ('formatValue' in basePropTypes) {
const valueMessage = (0, _get.default)(fieldConfig, ['messages', 'value']);
if (valueMessage) {
computedProps.formatValue = value => intl.formatMessage(valueMessage, {
value
});
}
}
if ('renderChildInputLabel' in basePropTypes) {
computedProps.renderChildInputLabel = childInput => {
const childName = childInput.props.name;
const childLabelMessage = childInput.props.labelMessage;
const childField = field[childName];
const childComputeContext = {
path: [...path, childName],
recordData,
subrecordData,
fieldDescriptor: childField,
recordType,
form: formName,
roleNames
};
return childField && renderLabel(childField, childLabelMessage, childComputeContext, {
key: childName,
readOnly: effectiveReadOnly
});
};
}
if ('viewType' in basePropTypes) {
computedProps.viewType = viewType;
}
const effectiveProps = {
...computedProps,
...configuredProps,
...providedProps,
readOnly: effectiveReadOnly
};
return /*#__PURE__*/_react.default.createElement(BaseComponent, effectiveProps);
}
Field.contextTypes = contextTypes;
Field.propTypes = propTypes;
Field.toJSON = () => 'Field';