fix(netlify-cms-core): fix fields metadata for objects and lists (#2011)
This commit is contained in:
parent
ff73175244
commit
2d1d1c13df
@ -137,13 +137,13 @@
|
|||||||
const RelationKitchenSinkPostPreview = createClass({
|
const RelationKitchenSinkPostPreview = createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
// When a post is selected from the relation field, all of it's data
|
// When a post is selected from the relation field, all of it's data
|
||||||
// will be available in the metadata nested under the collection name,
|
// will be available in the field's metadata nested under the collection
|
||||||
// and then further nested under the value specified in `valueField`.
|
// name, and then further nested under the value specified in `valueField`.
|
||||||
// In this case, the post would be nested under "posts" and then under
|
// In this case, the post would be nested under "posts" and then under
|
||||||
// the title of the selected post, since our `valueField` in the config
|
// the title of the selected post, since our `valueField` in the config
|
||||||
// is "title".
|
// is "title".
|
||||||
const postValue = this.props.entry.getIn(['data', 'post']);
|
const { value, fieldsMetaData } = this.props;
|
||||||
const post = this.props.fieldsMetaData.getIn(['posts', postValue]);
|
const post = fieldsMetaData && fieldsMetaData.getIn(['posts', value]);
|
||||||
const style = { border: '2px solid #ccc', borderRadius: '8px', padding: '20px' };
|
const style = { border: '2px solid #ccc', borderRadius: '8px', padding: '20px' };
|
||||||
return post ? h('div', { style: style },
|
return post ? h('div', { style: style },
|
||||||
h('h2', {}, 'Related Post'),
|
h('h2', {}, 'Related Post'),
|
||||||
|
@ -195,7 +195,7 @@ export default class Widget extends Component {
|
|||||||
*/
|
*/
|
||||||
onChangeObject = (fieldName, newValue, newMetadata) => {
|
onChangeObject = (fieldName, newValue, newMetadata) => {
|
||||||
const newObjectValue = this.getObjectValue().set(fieldName, newValue);
|
const newObjectValue = this.getObjectValue().set(fieldName, newValue);
|
||||||
return this.props.onChange(newObjectValue, newMetadata);
|
return this.props.onChange(newObjectValue, { [this.props.field.get('name')]: newMetadata });
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -22,8 +22,8 @@ const PreviewPaneFrame = styled(Frame)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export default class PreviewPane extends React.Component {
|
export default class PreviewPane extends React.Component {
|
||||||
getWidget = (field, value, props, idx = null) => {
|
getWidget = (field, value, metadata, props, idx = null) => {
|
||||||
const { fieldsMetaData, getAsset, entry } = props;
|
const { 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');
|
const key = idx ? field.get('name') + '_' + idx : field.get('name');
|
||||||
|
|
||||||
@ -37,9 +37,8 @@ export default class PreviewPane extends React.Component {
|
|||||||
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}
|
||||||
metadata={fieldsMetaData && fieldsMetaData.get(field.get('name'))}
|
|
||||||
entry={entry}
|
entry={entry}
|
||||||
fieldsMetaData={fieldsMetaData}
|
fieldsMetaData={metadata}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -63,20 +62,26 @@ export default class PreviewPane extends React.Component {
|
|||||||
* object and list type fields. Used internally to retrieve widgets, and also
|
* object and list type fields. Used internally to retrieve widgets, and also
|
||||||
* exposed for use in custom preview templates.
|
* exposed for use in custom preview templates.
|
||||||
*/
|
*/
|
||||||
widgetFor = (name, fields = this.props.fields, values = this.props.entry.get('data')) => {
|
widgetFor = (
|
||||||
|
name,
|
||||||
|
fields = this.props.fields,
|
||||||
|
values = this.props.entry.get('data'),
|
||||||
|
fieldsMetaData = this.props.fieldsMetaData,
|
||||||
|
) => {
|
||||||
// We retrieve the field by name so that this function can also be used in
|
// We retrieve the field by name so that this function can also be used in
|
||||||
// custom preview templates, where the field object can't be passed in.
|
// custom preview templates, where the field object can't be passed in.
|
||||||
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');
|
let singleField = field.get('field');
|
||||||
|
let metadata = fieldsMetaData && fieldsMetaData.get(field.get('name'), Map());
|
||||||
|
|
||||||
if (nestedFields) {
|
if (nestedFields) {
|
||||||
field = field.set('fields', this.getNestedWidgets(nestedFields, value));
|
field = field.set('fields', this.getNestedWidgets(nestedFields, value, metadata));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (singleField) {
|
if (singleField) {
|
||||||
field = field.set('field', this.getSingleNested(singleField, value));
|
field = field.set('field', this.getSingleNested(singleField, value, metadata));
|
||||||
}
|
}
|
||||||
|
|
||||||
const labelledWidgets = ['string', 'text', 'number'];
|
const labelledWidgets = ['string', 'text', 'number'];
|
||||||
@ -94,33 +99,35 @@ export default class PreviewPane extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value ? this.getWidget(field, value, this.props) : null;
|
return value ? this.getWidget(field, value, metadata, this.props) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves widgets for nested fields (children of object/list fields)
|
* Retrieves widgets for nested fields (children of object/list fields)
|
||||||
*/
|
*/
|
||||||
getNestedWidgets = (fields, values) => {
|
getNestedWidgets = (fields, values, fieldsMetaData) => {
|
||||||
// Fields nested within a list field will be paired with a List of value Maps.
|
// Fields nested within a list field will be paired with a List of value Maps.
|
||||||
if (List.isList(values)) {
|
if (List.isList(values)) {
|
||||||
return values.map(value => this.widgetsForNestedFields(fields, value));
|
return values.map(value => this.widgetsForNestedFields(fields, value, fieldsMetaData));
|
||||||
}
|
}
|
||||||
// Fields nested within an object field will be paired with a single Map of values.
|
// Fields nested within an object field will be paired with a single Map of values.
|
||||||
return this.widgetsForNestedFields(fields, values);
|
return this.widgetsForNestedFields(fields, values, fieldsMetaData);
|
||||||
};
|
};
|
||||||
|
|
||||||
getSingleNested = (field, values) => {
|
getSingleNested = (field, values, fieldsMetaData) => {
|
||||||
if (List.isList(values)) {
|
if (List.isList(values)) {
|
||||||
return values.map((value, idx) => this.getWidget(field, value, this.props, idx));
|
return values.map((value, idx) =>
|
||||||
|
this.getWidget(field, value, fieldsMetaData.get(field.get('name')), this.props, idx),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return this.getWidget(field, values, this.props);
|
return this.getWidget(field, values, fieldsMetaData.get(field.get('name')), this.props);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use widgetFor as a mapping function for recursive widget retrieval
|
* Use widgetFor as a mapping function for recursive widget retrieval
|
||||||
*/
|
*/
|
||||||
widgetsForNestedFields = (fields, values) => {
|
widgetsForNestedFields = (fields, values, fieldsMetaData) => {
|
||||||
return fields.map(field => this.widgetFor(field.get('name'), fields, values));
|
return fields.map(field => this.widgetFor(field.get('name'), fields, values, fieldsMetaData));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,10 +137,11 @@ export default class PreviewPane extends React.Component {
|
|||||||
* TODO: see if widgetFor can now provide this functionality for preview templates
|
* TODO: see if widgetFor can now provide this functionality for preview templates
|
||||||
*/
|
*/
|
||||||
widgetsFor = name => {
|
widgetsFor = name => {
|
||||||
const { fields, entry } = this.props;
|
const { fields, entry, fieldsMetaData } = this.props;
|
||||||
const field = fields.find(f => f.get('name') === name);
|
const field = fields.find(f => f.get('name') === name);
|
||||||
const nestedFields = field && field.get('fields');
|
const nestedFields = field && field.get('fields');
|
||||||
const value = entry.getIn(['data', field.get('name')]);
|
const value = entry.getIn(['data', field.get('name')]);
|
||||||
|
const metadata = fieldsMetaData.get(field.get('name'), Map());
|
||||||
|
|
||||||
if (List.isList(value)) {
|
if (List.isList(value)) {
|
||||||
return value.map(val => {
|
return value.map(val => {
|
||||||
@ -142,7 +150,7 @@ export default class PreviewPane extends React.Component {
|
|||||||
Map(
|
Map(
|
||||||
nestedFields.map((f, i) => [
|
nestedFields.map((f, i) => [
|
||||||
f.get('name'),
|
f.get('name'),
|
||||||
<div key={i}>{this.getWidget(f, val, this.props)}</div>,
|
<div key={i}>{this.getWidget(f, val, metadata.get(f.get('name')), this.props)}</div>,
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
return Map({ data: val, widgets });
|
return Map({ data: val, widgets });
|
||||||
@ -153,7 +161,12 @@ export default class PreviewPane extends React.Component {
|
|||||||
data: value,
|
data: value,
|
||||||
widgets:
|
widgets:
|
||||||
nestedFields &&
|
nestedFields &&
|
||||||
Map(nestedFields.map(f => [f.get('name'), this.getWidget(f, value, this.props)])),
|
Map(
|
||||||
|
nestedFields.map(f => [
|
||||||
|
f.get('name'),
|
||||||
|
this.getWidget(f, value, metadata.get(f.get('name')), this.props),
|
||||||
|
]),
|
||||||
|
),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -201,10 +201,7 @@ export default class ListControl extends React.Component {
|
|||||||
? this.getObjectValue(index).set(fieldName, newValue)
|
? this.getObjectValue(index).set(fieldName, newValue)
|
||||||
: newValue;
|
: newValue;
|
||||||
const parsedMetadata = {
|
const parsedMetadata = {
|
||||||
[collectionName]: Object.assign(
|
[collectionName]: Object.assign(metadata ? metadata.toJS() : {}, newMetadata || {}),
|
||||||
metadata ? metadata.toJS() : {},
|
|
||||||
newMetadata ? newMetadata[collectionName] : {},
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
onChange(value.set(index, newObjectValue), parsedMetadata);
|
onChange(value.set(index, newObjectValue), parsedMetadata);
|
||||||
};
|
};
|
||||||
@ -283,6 +280,7 @@ export default class ListControl extends React.Component {
|
|||||||
classNameWrapper,
|
classNameWrapper,
|
||||||
editorControl,
|
editorControl,
|
||||||
onValidateObject,
|
onValidateObject,
|
||||||
|
metadata,
|
||||||
clearFieldErrors,
|
clearFieldErrors,
|
||||||
fieldsErrors,
|
fieldsErrors,
|
||||||
controlRef,
|
controlRef,
|
||||||
@ -320,6 +318,7 @@ export default class ListControl extends React.Component {
|
|||||||
onChangeObject={this.handleChangeFor(index)}
|
onChangeObject={this.handleChangeFor(index)}
|
||||||
editorControl={editorControl}
|
editorControl={editorControl}
|
||||||
resolveWidget={resolveWidget}
|
resolveWidget={resolveWidget}
|
||||||
|
metadata={metadata}
|
||||||
forList
|
forList
|
||||||
onValidateObject={onValidateObject}
|
onValidateObject={onValidateObject}
|
||||||
clearFieldErrors={clearFieldErrors}
|
clearFieldErrors={clearFieldErrors}
|
||||||
|
@ -69,6 +69,7 @@ export default class ObjectControl extends Component {
|
|||||||
onChangeObject,
|
onChangeObject,
|
||||||
onValidateObject,
|
onValidateObject,
|
||||||
clearFieldErrors,
|
clearFieldErrors,
|
||||||
|
metadata,
|
||||||
fieldsErrors,
|
fieldsErrors,
|
||||||
editorControl: EditorControl,
|
editorControl: EditorControl,
|
||||||
controlRef,
|
controlRef,
|
||||||
@ -87,6 +88,7 @@ export default class ObjectControl extends Component {
|
|||||||
value={fieldValue}
|
value={fieldValue}
|
||||||
onChange={onChangeObject}
|
onChange={onChangeObject}
|
||||||
clearFieldErrors={clearFieldErrors}
|
clearFieldErrors={clearFieldErrors}
|
||||||
|
fieldsMetaData={metadata}
|
||||||
fieldsErrors={fieldsErrors}
|
fieldsErrors={fieldsErrors}
|
||||||
onValidate={onValidateObject}
|
onValidate={onValidateObject}
|
||||||
processControlRef={controlRef && controlRef.bind(this)}
|
processControlRef={controlRef && controlRef.bind(this)}
|
||||||
|
@ -95,7 +95,9 @@ export default class RelationControl extends React.Component {
|
|||||||
if (suggestion && suggestion.length === 1) {
|
if (suggestion && suggestion.length === 1) {
|
||||||
const val = this.getSuggestionValue(suggestion[0]);
|
const val = this.getSuggestionValue(suggestion[0]);
|
||||||
this.props.onChange(val, {
|
this.props.onChange(val, {
|
||||||
[this.props.field.get('collection')]: { [val]: suggestion[0].data },
|
[this.props.field.get('name')]: {
|
||||||
|
[this.props.field.get('collection')]: { [val]: suggestion[0].data },
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,7 +110,9 @@ export default class RelationControl extends React.Component {
|
|||||||
onSuggestionSelected = (event, { suggestion }) => {
|
onSuggestionSelected = (event, { suggestion }) => {
|
||||||
const value = this.getSuggestionValue(suggestion);
|
const value = this.getSuggestionValue(suggestion);
|
||||||
this.props.onChange(value, {
|
this.props.onChange(value, {
|
||||||
[this.props.field.get('collection')]: { [value]: suggestion.data },
|
[this.props.field.get('name')]: {
|
||||||
|
[this.props.field.get('collection')]: { [value]: suggestion.data },
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user