static-cms/src/components/Widgets/ObjectControl.js

92 lines
3.1 KiB
JavaScript
Raw Normal View History

import PropTypes from 'prop-types';
import React, { Component } from 'react';
2016-10-28 04:51:37 +02:00
import { Map } from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ControlHOC from './ControlHOC';
2016-10-28 04:51:37 +02:00
import { resolveWidget } from '../Widgets';
export default class ObjectControl extends Component {
static propTypes = {
onChange: PropTypes.func.isRequired,
onOpenMediaLibrary: PropTypes.func.isRequired,
mediaPaths: ImmutablePropTypes.map.isRequired,
2017-01-10 22:23:22 -02:00
onAddAsset: PropTypes.func.isRequired,
2017-03-15 14:30:41 -04:00
onRemoveAsset: PropTypes.func.isRequired,
2017-01-10 22:23:22 -02:00
getAsset: PropTypes.func.isRequired,
value: PropTypes.oneOfType([
PropTypes.node,
PropTypes.object,
PropTypes.bool,
]),
2017-01-16 16:52:59 -02:00
field: PropTypes.object,
forID: PropTypes.string,
2017-03-15 14:30:41 -04:00
className: PropTypes.string,
2016-10-28 04:51:37 +02:00
};
2017-09-25 14:19:24 -04:00
/**
* In case the `onChange` function is frozen by a child widget implementation,
* e.g. when debounced, always get the latest object value instead of usin
* `this.props.value` directly.
*/
getObjectValue = () => this.props.value || Map();
/*
* Always update so that each nested widget has the option to update. This is
* required because ControlHOC provides a default `shouldComponentUpdate`
* which only updates if the value changes, but every widget must be allowed
* to override this.
*/
shouldComponentUpdate() {
return true;
}
onChange = (fieldName, newValue, newMetadata) => {
const newObjectValue = this.getObjectValue().set(fieldName, newValue);
return this.props.onChange(newObjectValue, newMetadata);
};
2017-09-25 14:19:24 -04:00
2016-10-28 04:51:37 +02:00
controlFor(field) {
const { onAddAsset, onOpenMediaLibrary, mediaPaths, onRemoveAsset, getAsset, value, onChange } = this.props;
if (field.get('widget') === 'hidden') {
return null;
}
2016-10-28 04:51:37 +02:00
const widget = resolveWidget(field.get('widget') || 'string');
const fieldValue = value && Map.isMap(value) ? value.get(field.get('name')) : value;
2016-10-28 04:51:37 +02:00
return (<div className="nc-controlPane-widget" key={field.get('name')}>
<div className="nc-controlPane-control" key={field.get('name')}>
<label className="nc-controlPane-label" htmlFor={field.get('name')}>{field.get('label')}</label>
<ControlHOC
controlComponent={widget.control}
field={field}
value={fieldValue}
onChange={this.onChange.bind(this, field.get('name'))}
mediaPaths={mediaPaths}
onOpenMediaLibrary={onOpenMediaLibrary}
onAddAsset={onAddAsset}
onRemoveAsset={onRemoveAsset}
getAsset={getAsset}
forID={field.get('name')}
/>
2016-10-28 04:51:37 +02:00
</div>
2016-10-28 10:21:13 +02:00
</div>);
2016-10-28 04:51:37 +02:00
}
render() {
const { field, forID } = this.props;
const multiFields = field.get('fields');
const singleField = field.get('field');
2017-03-15 14:30:41 -04:00
const className = this.props.className || '';
2016-10-28 04:51:37 +02:00
if (multiFields) {
return (<div id={forID} className={`${ className } nc-objectControl-root`}>
2017-03-15 14:30:41 -04:00
{multiFields.map(f => this.controlFor(f))}
</div>);
} else if (singleField) {
return this.controlFor(singleField);
2016-10-28 04:51:37 +02:00
}
return <h3>No field(s) defined for this widget</h3>;
2016-10-28 04:51:37 +02:00
}
}