UNPKG

strapi-plugin-content-manager

Version:

A powerful UI to easily manage your data.

159 lines (135 loc) 4.58 kB
/** * * SelectOne * */ import React from 'react'; import Select from 'react-select'; import PropTypes from 'prop-types'; import 'react-select/dist/react-select.css'; import { cloneDeep, map, includes, isArray, isNull, isUndefined, isFunction, get, findIndex } from 'lodash'; import request from 'utils/request'; import templateObject from 'utils/templateObject'; import styles from './styles.scss'; class SelectOne extends React.Component { // eslint-disable-line react/prefer-stateless-function constructor(props) { super(props); this.state = { isLoading: true, options: [], toSkip: 0, }; } componentDidMount() { this.getOptions(''); } componentDidUpdate(prevProps, prevState) { if (prevState.toSkip !== this.state.toSkip) { this.getOptions(''); } } getOptions = (query) => { const params = { _limit: 20, _start: this.state.toSkip, source: this.props.relation.plugin || 'content-manager', }; // Set `query` parameter if necessary if (query) { delete params._limit; delete params._start; params[`${this.props.relation.displayedAttribute}_contains`] = query; } // Request URL const requestUrlSuffix = query && get(this.props.record, [this.props.relation.alias]) ? get(this.props.record, [this.props.relation.alias]) : ''; const requestUrl = `/content-manager/explorer/${this.props.relation.model || this.props.relation.collection}/${requestUrlSuffix}`; // Call our request helper (see 'utils/request') return request(requestUrl, { method: 'GET', params, }) .then(response => { const options = isArray(response) ? map(response, item => ({ value: item, label: templateObject({ mainField: this.props.relation.displayedAttribute }, item).mainField, })) : [{ value: response, label: templateObject({ mainField: this.props.relation.displayedAttribute }, response).mainField, }]; const newOptions = cloneDeep(this.state.options); options.map(option => { // Don't add the values when searching if (findIndex(newOptions, o => o.value.id === option.value.id) === -1) { return newOptions.push(option); } }); return this.setState({ options: newOptions, isLoading: false, }); }) .catch(() => { strapi.notification.error('content-manager.notification.error.relationship.fetch'); }); } handleChange = (value) => { const target = { name: `record.${this.props.relation.alias}`, value, type: 'select', }; this.props.setRecordAttribute({ target }); } handleBottomScroll = () => { this.setState(prevState => { return { toSkip: prevState.toSkip + 20, }; }); } handleInputChange = (value) => { const clonedOptions = this.state.options; const filteredValues = clonedOptions.filter(data => includes(data.label, value)); if (filteredValues.length === 0) { return this.getOptions(value); } } render() { const description = this.props.relation.description ? <p>{this.props.relation.description}</p> : ''; const value = get(this.props.record, this.props.relation.alias); /* eslint-disable jsx-a11y/label-has-for */ return ( <div className={`form-group ${styles.selectOne}`}> <label htmlFor={this.props.relation.alias}>{this.props.relation.alias}</label> {description} <Select onChange={this.handleChange} options={this.state.options} isLoading={this.state.isLoading} onMenuScrollToBottom={this.handleBottomScroll} onInputChange={this.handleInputChange} onSelectResetsInput={false} simpleValue value={isNull(value) || isUndefined(value) ? null : { value: isFunction(value.toJS) ? value.toJS() : value, label: templateObject({ mainField: this.props.relation.displayedAttribute }, isFunction(value.toJS) ? value.toJS() : value).mainField || (isFunction(value.toJS) ? get(value.toJS(), 'id') : get(value, 'id')), }} /> </div> ); /* eslint-disable jsx-a11y/label-has-for */ } } SelectOne.propTypes = { record: PropTypes.oneOfType([ PropTypes.object, PropTypes.bool, ]).isRequired, relation: PropTypes.object.isRequired, setRecordAttribute: PropTypes.func.isRequired, }; export default SelectOne;