fix(widget-relation): set initial metadata value (#4182)

This commit is contained in:
Bartholomew 2020-08-30 17:34:22 +01:00 committed by GitHub
parent 8d693caebd
commit 4a510f3a9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 49 deletions

View File

@ -73,7 +73,6 @@ function getSelectedValue({ value, options, isMultiple }) {
}
export default class RelationControl extends React.Component {
didInitialSearch = false;
mounted = false;
state = {
@ -106,17 +105,19 @@ export default class RelationControl extends React.Component {
// if the field has a previous value perform an initial search based on the value field
// this is required since each search is limited by optionsLength so the selected value
// might not show up on the search
const { forID, field, value, query } = this.props;
const { forID, field, value, query, onChange } = this.props;
const collection = field.get('collection');
const file = field.get('file');
const initialSearchValues = this.isMultiple() ? getSelectedOptions(value) : [value];
const initialSearchValues = value && (this.isMultiple() ? getSelectedOptions(value) : [value]);
if (initialSearchValues && initialSearchValues.length > 0) {
const metadata = {};
const allOptions = await Promise.all(
initialSearchValues.map((v, index) => {
return query(forID, collection, [field.get('valueField')], v, file, 1).then(
({ payload }) => {
const hits = payload.response?.hits || [];
const options = this.parseHitOptions(hits);
metadata[v] = hits[0]?.data;
return { options, index };
},
);
@ -127,6 +128,13 @@ export default class RelationControl extends React.Component {
...sortBy(allOptions, ({ index }) => index).map(({ options }) => options),
);
this.mounted && this.setState({ initialOptions });
//set metadata
onChange(value, {
[field.get('name')]: {
[field.get('collection')]: metadata,
},
});
}
}
@ -134,33 +142,6 @@ export default class RelationControl extends React.Component {
this.mounted = false;
}
componentDidUpdate(prevProps) {
/**
* Load extra post data into the store after first query.
*/
if (this.didInitialSearch) return;
const { value, field, forID, queryHits, onChange } = this.props;
if (queryHits !== prevProps.queryHits && queryHits.get(forID)) {
this.didInitialSearch = true;
const valueField = field.get('valueField');
const hits = queryHits.get(forID);
if (value) {
const listValue = List.isList(value) ? value : List([value]);
listValue.forEach(val => {
const hit = hits.find(hit => this.parseNestedFields(hit, valueField) === val);
if (hit) {
onChange(value, {
[field.get('name')]: {
[field.get('collection')]: { [val]: hit.data },
},
});
}
});
}
}
}
handleChange = selectedOption => {
const { onChange, field } = this.props;
let value;

View File

@ -1,6 +1,5 @@
import React from 'react';
import { fromJS, Map } from 'immutable';
import { last } from 'lodash';
import { render, fireEvent, waitFor } from '@testing-library/react';
import { NetlifyCmsWidgetRelation } from '../';
@ -85,6 +84,10 @@ const generateHits = length => {
collection: 'posts',
data: { title: 'YAML post', slug: 'post-yaml', body: 'Body yaml' },
},
{
collection: 'posts',
data: { title: 'JSON post', slug: 'post-json', body: 'Body json' },
},
];
};
@ -166,12 +169,14 @@ class RelationController extends React.Component {
hits = nestedFileCollectionHits;
} else if (file === 'simple_file') {
hits = simpleFileCollectionHits;
} else if (term === 'YAML') {
hits = [last(queryHits)];
} else if (term === 'Nested') {
} else if (term === 'JSON post') {
hits = [queryHits[queryHits.length - 1]];
} else if (term === 'YAML' || term === 'YAML post') {
hits = [queryHits[queryHits.length - 2]];
} else if (term === 'Deeply nested') {
} else if (term === 'Nested') {
hits = [queryHits[queryHits.length - 3]];
} else if (term === 'Deeply nested') {
hits = [queryHits[queryHits.length - 4]];
}
hits = hits.slice(0, optionsLength);
@ -411,24 +416,23 @@ describe('Relation widget', () => {
it('should update metadata for initial preview', async () => {
const field = fromJS({ ...fieldConfig, multiple: true });
const value = fromJS(['Post # 1', 'Post # 2']);
const { getByText, onChangeSpy, setQueryHitsSpy } = setup({ field, value });
const metadata1 = {
post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
const value = fromJS(['YAML post', 'JSON post']);
const { getByText, onChangeSpy } = setup({ field, value });
const metadata = {
post: {
posts: {
'YAML post': { title: 'YAML post', slug: 'post-yaml', body: 'Body yaml' },
'JSON post': { title: 'JSON post', slug: 'post-json', body: 'Body json' },
},
},
};
const metadata2 = {
post: { posts: { 'Post # 2': { title: 'Post # 2', slug: 'post-number-2' } } },
};
setQueryHitsSpy(generateHits(2));
await waitFor(() => {
expect(getByText('Post # 1 post-number-1')).toBeInTheDocument();
expect(getByText('Post # 2 post-number-2')).toBeInTheDocument();
expect(getByText('YAML post post-yaml')).toBeInTheDocument();
expect(getByText('JSON post post-json')).toBeInTheDocument();
expect(onChangeSpy).toHaveBeenCalledTimes(2);
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata1);
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata2);
expect(onChangeSpy).toHaveBeenCalledTimes(1);
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata);
});
});
});