fix(list-widget): fix single field usage in list widget (#1395)

This commit is contained in:
Brian Macdonald 2018-08-24 17:39:35 -04:00 committed by Shawn Erquhart
parent f58db5fb08
commit 06d3650fac
5 changed files with 60 additions and 34 deletions

View File

@ -22,9 +22,10 @@ const PreviewPaneFrame = styled(Frame)`
`; `;
export default class PreviewPane extends React.Component { export default class PreviewPane extends React.Component {
getWidget = (field, value, props) => { getWidget = (field, value, props, idx = null) => {
const { fieldsMetaData, getAsset, entry } = props; const { fieldsMetaData, getAsset, entry } = props;
const widget = resolveWidget(field.get('widget')); const widget = resolveWidget(field.get('widget'));
const key = idx ? field.get('name') + '_' + idx : field.get('name');
/** /**
* Use an HOC to provide conditional updates for all previews. * Use an HOC to provide conditional updates for all previews.
@ -32,7 +33,7 @@ export default class PreviewPane extends React.Component {
return !widget.preview ? null : ( return !widget.preview ? null : (
<PreviewHOC <PreviewHOC
previewComponent={widget.preview} previewComponent={widget.preview}
key={field.get('name')} key={key}
field={field} field={field}
getAsset={getAsset} getAsset={getAsset}
value={value && Map.isMap(value) ? value.get(field.get('name')) : value} value={value && Map.isMap(value) ? value.get(field.get('name')) : value}
@ -68,11 +69,16 @@ export default class PreviewPane extends React.Component {
let field = fields && fields.find(f => f.get('name') === name); let field = fields && fields.find(f => f.get('name') === name);
let value = values && values.get(field.get('name')); let value = values && values.get(field.get('name'));
let nestedFields = field.get('fields'); let nestedFields = field.get('fields');
let singleField = field.get('field');
if (nestedFields) { if (nestedFields) {
field = field.set('fields', this.getNestedWidgets(nestedFields, value)); field = field.set('fields', this.getNestedWidgets(nestedFields, value));
} }
if (singleField) {
field = field.set('field', this.getSingleNested(singleField, value));
}
const labelledWidgets = ['string', 'text', 'number']; const labelledWidgets = ['string', 'text', 'number'];
if (Object.keys(this.inferedFields).indexOf(name) !== -1) { if (Object.keys(this.inferedFields).indexOf(name) !== -1) {
value = this.inferedFields[name].defaultPreview(value); value = this.inferedFields[name].defaultPreview(value);
@ -103,6 +109,13 @@ export default class PreviewPane extends React.Component {
return this.widgetsForNestedFields(fields, values); return this.widgetsForNestedFields(fields, values);
}; };
getSingleNested = (field, values) => {
if (List.isList(values)) {
return values.map((value, idx) => this.getWidget(field, value, this.props, idx));
}
return this.getWidget(field, values, this.props);
};
/** /**
* Use widgetFor as a mapping function for recursive widget retrieval * Use widgetFor as a mapping function for recursive widget retrieval
*/ */

View File

@ -28,30 +28,34 @@ const TopBarButton = styled.button`
const TopBarButtonSpan = TopBarButton.withComponent('span'); const TopBarButtonSpan = TopBarButton.withComponent('span');
const DragIcon = styled(TopBarButtonSpan)` const DragIconContainer = styled(TopBarButtonSpan)`
width: 100%; width: 100%;
cursor: move; cursor: move;
`; `;
const ListItemTopBar = ({ className, collapsed, onCollapseToggle, onRemove, dragHandleHOC }) => ( const ListItemTopBar = ({ className, collapsed, onCollapseToggle, onRemove, dragHandleHOC }) => {
<TopBar className={className}> const DragHandle = dragHandleHOC(() => (
{onCollapseToggle ? ( <DragIconContainer>
<TopBarButton onClick={onCollapseToggle}> <Icon type="drag-handle" size="small" />
<Icon type="chevron" size="small" direction={collapsed ? 'right' : 'down'} /> </DragIconContainer>
</TopBarButton> ));
) : null}
{dragHandleHOC ? ( return (
<DragIcon> <TopBar className={className}>
<Icon type="drag-handle" size="small" /> {onCollapseToggle ? (
</DragIcon> <TopBarButton onClick={onCollapseToggle}>
) : null} <Icon type="chevron" size="small" direction={collapsed ? 'right' : 'down'} />
{onRemove ? ( </TopBarButton>
<TopBarButton onClick={onRemove}> ) : null}
<Icon type="close" size="small" /> {dragHandleHOC ? <DragHandle dragHandleHOC={dragHandleHOC} /> : null}
</TopBarButton> {onRemove ? (
) : null} <TopBarButton onClick={onRemove}>
</TopBar> <Icon type="close" size="small" />
); </TopBarButton>
) : null}
</TopBar>
);
};
const StyledListItemTopBar = styled(ListItemTopBar)` const StyledListItemTopBar = styled(ListItemTopBar)`
display: flex; display: flex;

View File

@ -159,16 +159,17 @@ export default class ListControl extends React.Component {
return (fieldName, newValue, newMetadata) => { return (fieldName, newValue, newMetadata) => {
const { value, metadata, onChange, field } = this.props; const { value, metadata, onChange, field } = this.props;
const collectionName = field.get('name'); const collectionName = field.get('name');
const newObjectValue = this.getObjectValue(index).set(fieldName, newValue); const newObjectValue =
const parsedValue = this.getValueType() === valueTypes.MULTIPLE
this.getValueType() === valueTypes.SINGLE ? newObjectValue.first() : newObjectValue; ? this.getObjectValue(index).set(fieldName, newValue)
: newValue;
const parsedMetadata = { const parsedMetadata = {
[collectionName]: Object.assign( [collectionName]: Object.assign(
metadata ? metadata.toJS() : {}, metadata ? metadata.toJS() : {},
newMetadata ? newMetadata[collectionName] : {}, newMetadata ? newMetadata[collectionName] : {},
), ),
}; };
onChange(value.set(index, parsedValue), parsedMetadata); onChange(value.set(index, newObjectValue), parsedMetadata);
}; };
} }
@ -177,9 +178,10 @@ export default class ListControl extends React.Component {
const { itemsCollapsed } = this.state; const { itemsCollapsed } = this.state;
const { value, metadata, onChange, field } = this.props; const { value, metadata, onChange, field } = this.props;
const collectionName = field.get('name'); const collectionName = field.get('name');
const parsedMetadata = metadata && { const isSingleField = this.valueType === valueTypes.SINGLE;
[collectionName]: metadata.removeIn(value.get(index).valueSeq()),
}; const metadataRemovePath = isSingleField ? value.get(index) : value.get(index).valueSeq();
const parsedMetadata = metadata && { [collectionName]: metadata.removeIn(metadataRemovePath) };
this.setState({ itemsCollapsed: itemsCollapsed.delete(index) }); this.setState({ itemsCollapsed: itemsCollapsed.delete(index) });

View File

@ -62,13 +62,20 @@ export default class ObjectControl extends Component {
this.setState({ collapsed: !this.state.collapsed }); this.setState({ collapsed: !this.state.collapsed });
}; };
renderFields = (multiFields, singleField) => {
if (multiFields) {
return multiFields.map((f, idx) => this.controlFor(f, idx));
}
return this.controlFor(singleField);
};
render() { render() {
const { field, forID, classNameWrapper, forList } = this.props; const { field, forID, classNameWrapper, forList } = this.props;
const { collapsed } = this.state; const { collapsed } = this.state;
const multiFields = field.get('fields'); const multiFields = field.get('fields');
const singleField = field.get('field'); const singleField = field.get('field');
if (multiFields) { if (multiFields || singleField) {
return ( return (
<div <div
id={forID} id={forID}
@ -82,11 +89,9 @@ export default class ObjectControl extends Component {
onCollapseToggle={this.handleCollapseToggle} onCollapseToggle={this.handleCollapseToggle}
/> />
)} )}
{collapsed ? null : multiFields.map((f, idx) => this.controlFor(f, idx))} {collapsed ? null : this.renderFields(multiFields, singleField)}
</div> </div>
); );
} else if (singleField) {
return this.controlFor(singleField);
} }
return <h3>No field(s) defined for this widget</h3>; return <h3>No field(s) defined for this widget</h3>;

View File

@ -3,7 +3,9 @@ import PropTypes from 'prop-types';
import { WidgetPreviewContainer } from 'netlify-cms-ui-default'; import { WidgetPreviewContainer } from 'netlify-cms-ui-default';
const ObjectPreview = ({ field }) => ( const ObjectPreview = ({ field }) => (
<WidgetPreviewContainer>{(field && field.get('fields')) || null}</WidgetPreviewContainer> <WidgetPreviewContainer>
{(field && field.get('fields')) || field.get('field') || null}
</WidgetPreviewContainer>
); );
ObjectPreview.propTypes = { ObjectPreview.propTypes = {