| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| import React, { PureComponent } from 'react'; |
| import { Select, Spin } from 'antd'; |
| import debounce from 'lodash.debounce'; |
| import request from '../../../utils/request'; |
| |
| const { Option } = Select; |
| |
| export default class Search extends PureComponent { |
| constructor(props) { |
| super(props); |
| this.lastFetchId = 0; |
| this.originFetchServer = this.fetchServer; |
| this.fetchServer = debounce(this.fetchServer, 800); |
| } |
| |
| state = { |
| data: [], |
| fetching: false, |
| }; |
| |
| componentDidMount() { |
| if (this.props.variables && Object.keys(this.props.variables).length > 0) { |
| this.originFetchServer('', this.props.value.key); |
| } |
| } |
| |
| componentDidUpdate(prevProps) { |
| if (prevProps.variables !== this.props.variables) { |
| this.originFetchServer('', this.props.value.key); |
| } |
| } |
| |
| fetchServer = (value, key) => { |
| if (value === undefined) { |
| return; |
| } |
| const { url, query, variables = {}, transform } = this.props; |
| this.lastFetchId += 1; |
| const fetchId = this.lastFetchId; |
| this.setState({ data: [], fetching: true }); |
| request(`/api${url}`, { |
| method: 'POST', |
| body: { |
| variables: { |
| ...variables, |
| keyword: value, |
| }, |
| query, |
| }, |
| }).then(body => { |
| if (!body.data || fetchId !== this.lastFetchId) { |
| // for fetch callback order |
| return; |
| } |
| const list = body.data[Object.keys(body.data)[0]]; |
| this.setState({ data: transform ? list.map(transform) : list, fetching: false }); |
| if (this.state.data.length < 1) { |
| return; |
| } |
| if (!key) { |
| this.handleSelect(this.state.data[0]); |
| return; |
| } |
| const option = this.state.data.find(_ => _.key === key); |
| if (!option) { |
| this.handleSelect(this.state.data[0]); |
| } |
| }); |
| }; |
| |
| handleSelect = value => { |
| const { onSelect } = this.props; |
| const selected = this.state.data.find(_ => _.key === value.key); |
| onSelect(selected); |
| }; |
| |
| render() { |
| const { placeholder, value } = this.props; |
| return ( |
| <Select |
| showSearch |
| style={{ width: 600 }} |
| placeholder={placeholder} |
| notFoundContent={this.state.fetching ? <Spin size="small" /> : null} |
| filterOption={false} |
| labelInValue |
| onSelect={this.handleSelect.bind(this)} |
| onSearch={this.fetchServer} |
| value={value} |
| > |
| {this.state.data.map(_ => { |
| return ( |
| <Option key={_.key} value={_.key}> |
| {_.label} |
| </Option> |
| ); |
| })} |
| </Select> |
| ); |
| } |
| } |