CountryCodePicker.tsx 5.61 KB
Newer Older
1 2 3 4
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {Field} from 'redux-form';
Oleksii Savran's avatar
I18n  
Oleksii Savran committed
5
import { translate } from 'react-i18next';
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

// Model
import VocabularyTerm from 'model/vocabulary/VocabularyTerm';
// Service
import GeoService from 'service/GeoService';
// actions
import {autocompleteGeoTerm} from 'vocabulary/actions/dashboard';
// ui
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import Input from '@material-ui/core/Input';
import TextField from '@material-ui/core/TextField';
import FormControl from 'ui/common/forms/FormControl';
import Select from '@material-ui/core/Select';

interface ISelectCountryCodeInternal extends React.ClassAttributes<any> {
    input: any;
    listVocabularyTerms: VocabularyTerm[];
    autocomplete: (term: string) => Promise<VocabularyTerm[]>;
    label: string;
    meta?: any;
Oleksii Savran's avatar
I18n  
Oleksii Savran committed
27
    t: any;
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
}

class SelectCountryInternal extends React.Component<ISelectCountryCodeInternal, any> {

    protected handleInputChange = (event) => {
        this.setState({searchText: event.target.value});
        this.props.autocomplete(event.target.value).then((suggestions) => {
            this.setState({suggestions});
        });
    }
    protected handleClick = (event) => {
        this.setState({open: true, anchorEl: event.currentTarget});
    }
    protected handleRequestClose = () => {
        this.setState({open: false});
    }
    protected select = (value) => (event) => {
        const {input} = this.props;
        const countryCodeTerm = this.state.suggestions.find((dl) => dl.code === value);
        if (countryCodeTerm) {
            input.onChange(countryCodeTerm.code);
            this.setState({
                open: false,
                pickerList: {code: countryCodeTerm.code, title: countryCodeTerm.title},
            });
        } else {
            input.onChange('');
            this.setState({
                open: false,
                pickerList: null,
            });
        }
    }

    private constructor(props, context) {
        super(props, context);
        this.state = {
            pickerList: null,
            open: false,
            anchorEl: null,
            searchText: '',
            suggestions: [],
        };
    }

    public componentWillMount() {
        if (this.props.input.value) {
Maxym Borodenko's avatar
Maxym Borodenko committed
75
            this.setState({pickerList: {code: this.props.input.value}});
76 77 78 79
        }
    }

    public componentWillReceiveProps(nextProps) {
Maxym Borodenko's avatar
Maxym Borodenko committed
80 81 82 83
        if (! nextProps.input.value) {
            return this.setState({pickerList: null});
        }
        if (nextProps.input.value !== this.props.input.value) {
84 85 86 87 88 89 90 91 92 93 94 95 96
            const code = nextProps.input.value;
            const countryCodeTerm = this.state.suggestions.find((dl) => dl.code === code);
            if (countryCodeTerm) {
                this.setState({pickerList: {code: countryCodeTerm.code, title: countryCodeTerm.title}});
            } else {
                GeoService.get(code).then((dl) => {
                    this.setState({pickerList: {code: dl.code, title: dl.title}});
                });
            }
        }
    }

    public render() {
Oleksii Savran's avatar
I18n  
Oleksii Savran committed
97
        const {label, meta, t} = this.props;
98 99 100 101 102 103 104 105 106 107 108 109
        const inputValue = this.state.pickerList && this.state.pickerList.code ? this.state.pickerList.code : '';
        return (
            <FormControl fullWidth meta={ meta } label={ label }>
                <Select
                    onClick={ this.handleClick }
                    value={ inputValue }
                    input={ <Input/> }
                    MenuProps={ {
                        open: false,
                    } }
                >
                    {
Maxym Borodenko's avatar
Maxym Borodenko committed
110
                        this.state.pickerList ? <MenuItem value={ inputValue }>{ this.state.pickerList.code }</MenuItem> : null
111 112 113 114 115 116 117 118 119 120
                    }
                </Select>
                <Menu
                    anchorEl={ this.state.anchorEl }
                    open={ this.state.open }
                    onClose={ this.handleRequestClose }
                >
                    <MenuItem>
                        <TextField fullWidth
                                   value={ this.state.searchText }
Oleksii Savran's avatar
I18n  
Oleksii Savran committed
121
                                   label={ t('datasets.dashboard.p.stepper.location.search') }
122 123 124 125 126
                                   onChange={ this.handleInputChange }
                        />
                    </MenuItem>
                    {
                        this.state.suggestions.map((cCT, index) => (
Maxym Borodenko's avatar
Maxym Borodenko committed
127
                            <MenuItem onClick={ this.select(cCT.code) } key={ `country-iso3-${index}` }>{ `${cCT.code} - ${cCT.title}` }</MenuItem>
128 129 130 131 132 133 134 135 136 137 138 139 140
                        ))
                    }
                </Menu>
            </FormControl>
        );
    }
}

interface ICountryCodePicker extends React.ClassAttributes<any> {
    input: any;
    label: string;
    className?: string;
    autocomplete: (term: string) => Promise<VocabularyTerm[]>;
Oleksii Savran's avatar
I18n  
Oleksii Savran committed
141
    t: any;
142 143 144 145 146
}

class CountryCodePicker extends React.Component<ICountryCodePicker, any> {

    public render() {
Oleksii Savran's avatar
I18n  
Oleksii Savran committed
147
        const {input: {name}, label, className, autocomplete, t} = this.props;
148 149 150 151 152 153 154 155

        return (
            <div className={ className }>
                <Field
                    name={ name }
                    component={ SelectCountryInternal }
                    label={ label }
                    autocomplete={ autocomplete }
Oleksii Savran's avatar
I18n  
Oleksii Savran committed
156
                    t={ t }
157 158 159 160 161 162 163 164 165 166
                />
            </div>
        );
    }
}

const mapDispatchToProps = (dispatch) => bindActionCreators({
    autocomplete: autocompleteGeoTerm,
}, dispatch);

Oleksii Savran's avatar
I18n  
Oleksii Savran committed
167
export default translate()(connect(null, mapDispatchToProps)(CountryCodePicker));