Merge pull request #833 from matrix-org/luke/improve-country-dd
Improve country dropdown UX and expose +prefixpull/21833/head
						commit
						4207bf31f2
					
				| 
						 | 
				
			
			@ -114,8 +114,11 @@ export default class Dropdown extends React.Component {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    componentWillReceiveProps(nextProps) {
 | 
			
		||||
        if (!nextProps.children || nextProps.children.length === 0) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        this._reindexChildren(nextProps.children);
 | 
			
		||||
        const firstChild = React.Children.toArray(nextProps.children)[0];
 | 
			
		||||
        const firstChild = nextProps.children[0];
 | 
			
		||||
        this.setState({
 | 
			
		||||
            highlightedOption: firstChild ? firstChild.key : null,
 | 
			
		||||
        });
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,7 @@ export default class CountryDropdown extends React.Component {
 | 
			
		|||
    constructor(props) {
 | 
			
		||||
        super(props);
 | 
			
		||||
        this._onSearchChange = this._onSearchChange.bind(this);
 | 
			
		||||
        this._onOptionChange = this._onOptionChange.bind(this);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            searchQuery: '',
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +49,7 @@ export default class CountryDropdown extends React.Component {
 | 
			
		|||
            // If no value is given, we start with the first
 | 
			
		||||
            // country selected, but our parent component
 | 
			
		||||
            // doesn't know this, therefore we do this.
 | 
			
		||||
            this.props.onOptionChange(COUNTRIES[0].iso2);
 | 
			
		||||
            this.props.onOptionChange(COUNTRIES[0]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +59,10 @@ export default class CountryDropdown extends React.Component {
 | 
			
		|||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onOptionChange(iso2) {
 | 
			
		||||
        this.props.onOptionChange(COUNTRIES_BY_ISO2[iso2]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _flagImgForIso2(iso2) {
 | 
			
		||||
        // Unicode Regional Indicator Symbol letter 'A'
 | 
			
		||||
        const RIS_A = 0x1F1E6;
 | 
			
		||||
| 
						 | 
				
			
			@ -102,9 +107,11 @@ export default class CountryDropdown extends React.Component {
 | 
			
		|||
        // values between mounting and the initial value propgating
 | 
			
		||||
        const value = this.props.value || COUNTRIES[0].iso2;
 | 
			
		||||
 | 
			
		||||
        const getShortOption = this.props.isSmall ? this._flagImgForIso2 : undefined;
 | 
			
		||||
 | 
			
		||||
        return <Dropdown className={this.props.className}
 | 
			
		||||
            onOptionChange={this.props.onOptionChange} onSearchChange={this._onSearchChange}
 | 
			
		||||
            menuWidth={298} getShortOption={this._flagImgForIso2}
 | 
			
		||||
            onOptionChange={this._onOptionChange} onSearchChange={this._onSearchChange}
 | 
			
		||||
            menuWidth={298} getShortOption={getShortOption}
 | 
			
		||||
            value={value} searchEnabled={true}
 | 
			
		||||
        >
 | 
			
		||||
            {options}
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +121,7 @@ export default class CountryDropdown extends React.Component {
 | 
			
		|||
 | 
			
		||||
CountryDropdown.propTypes = {
 | 
			
		||||
    className: React.PropTypes.string,
 | 
			
		||||
    isSmall: React.PropTypes.bool,
 | 
			
		||||
    onOptionChange: React.PropTypes.func.isRequired,
 | 
			
		||||
    value: React.PropTypes.string,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,8 +90,11 @@ class PasswordLogin extends React.Component {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    onPhoneCountryChanged(country) {
 | 
			
		||||
        this.setState({phoneCountry: country});
 | 
			
		||||
        this.props.onPhoneCountryChanged(country);
 | 
			
		||||
        this.setState({
 | 
			
		||||
            phoneCountry: country.iso2,
 | 
			
		||||
            phonePrefix: country.prefix,
 | 
			
		||||
        });
 | 
			
		||||
        this.props.onPhoneCountryChanged(country.iso2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onPhoneNumberChanged(ev) {
 | 
			
		||||
| 
						 | 
				
			
			@ -121,16 +124,17 @@ class PasswordLogin extends React.Component {
 | 
			
		|||
                const mxidInputClasses = classNames({
 | 
			
		||||
                    "mx_Login_field": true,
 | 
			
		||||
                    "mx_Login_username": true,
 | 
			
		||||
                    "mx_Login_field_has_prefix": true,
 | 
			
		||||
                    "mx_Login_field_has_suffix": Boolean(this.props.hsDomain),
 | 
			
		||||
                });
 | 
			
		||||
                let suffix = null;
 | 
			
		||||
                if (this.props.hsDomain) {
 | 
			
		||||
                    suffix = <div className="mx_Login_username_suffix">
 | 
			
		||||
                    suffix = <div className="mx_Login_field_suffix">
 | 
			
		||||
                        :{this.props.hsDomain}
 | 
			
		||||
                    </div>;
 | 
			
		||||
                }
 | 
			
		||||
                return <div className="mx_Login_username_group">
 | 
			
		||||
                    <div className="mx_Login_username_prefix">@</div>
 | 
			
		||||
                return <div className="mx_Login_field_group">
 | 
			
		||||
                    <div className="mx_Login_field_prefix">@</div>
 | 
			
		||||
                    <input
 | 
			
		||||
                        className={mxidInputClasses}
 | 
			
		||||
                        key="username_input"
 | 
			
		||||
| 
						 | 
				
			
			@ -145,6 +149,7 @@ class PasswordLogin extends React.Component {
 | 
			
		|||
                </div>;
 | 
			
		||||
            case PasswordLogin.LOGIN_FIELD_PHONE:
 | 
			
		||||
                const CountryDropdown = sdk.getComponent('views.login.CountryDropdown');
 | 
			
		||||
                const prefix = this.state.phonePrefix;
 | 
			
		||||
                return <div className="mx_Login_phoneSection">
 | 
			
		||||
                    <CountryDropdown
 | 
			
		||||
                        className="mx_Login_phoneCountry"
 | 
			
		||||
| 
						 | 
				
			
			@ -152,8 +157,10 @@ class PasswordLogin extends React.Component {
 | 
			
		|||
                        onOptionChange={this.onPhoneCountryChanged}
 | 
			
		||||
                        value={this.state.phoneCountry}
 | 
			
		||||
                    />
 | 
			
		||||
                    <div className="mx_Login_field_group">
 | 
			
		||||
                        <div className="mx_Login_field_prefix">+{prefix}</div>
 | 
			
		||||
                        <input
 | 
			
		||||
                        className="mx_Login_phoneNumberField mx_Login_field"
 | 
			
		||||
                            className="mx_Login_phoneNumberField mx_Login_field mx_Login_field_has_prefix"
 | 
			
		||||
                            ref="phoneNumber"
 | 
			
		||||
                            key="phone_input"
 | 
			
		||||
                            type="text"
 | 
			
		||||
| 
						 | 
				
			
			@ -163,6 +170,7 @@ class PasswordLogin extends React.Component {
 | 
			
		|||
                            value={this.state.phoneNumber}
 | 
			
		||||
                            autoFocus
 | 
			
		||||
                        />
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -270,7 +270,8 @@ module.exports = React.createClass({
 | 
			
		|||
 | 
			
		||||
    _onPhoneCountryChange(newVal) {
 | 
			
		||||
        this.setState({
 | 
			
		||||
            phoneCountry: newVal,
 | 
			
		||||
            phoneCountry: newVal.iso2,
 | 
			
		||||
            phonePrefix: newVal.prefix,
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -316,16 +317,22 @@ module.exports = React.createClass({
 | 
			
		|||
                    className="mx_Login_phoneCountry"
 | 
			
		||||
                    value={this.state.phoneCountry}
 | 
			
		||||
                />
 | 
			
		||||
                <div className="mx_Login_field_group">
 | 
			
		||||
                    <div className="mx_Login_field_prefix">+{this.state.phonePrefix}</div>
 | 
			
		||||
                    <input type="text" ref="phoneNumber"
 | 
			
		||||
                        placeholder="Mobile phone number (optional)"
 | 
			
		||||
                        defaultValue={this.props.defaultPhoneNumber}
 | 
			
		||||
                        className={this._classForField(
 | 
			
		||||
                        FIELD_PHONE_NUMBER, 'mx_Login_phoneNumberField', 'mx_Login_field'
 | 
			
		||||
                            FIELD_PHONE_NUMBER,
 | 
			
		||||
                            'mx_Login_phoneNumberField',
 | 
			
		||||
                            'mx_Login_field',
 | 
			
		||||
                            'mx_Login_field_has_prefix'
 | 
			
		||||
                        )}
 | 
			
		||||
                        onBlur={function() {self.validateField(FIELD_PHONE_NUMBER);}}
 | 
			
		||||
                        value={self.state.phoneNumber}
 | 
			
		||||
                    />
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        const registerButton = (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,7 +50,7 @@ export default WithMatrixClient(React.createClass({
 | 
			
		|||
    },
 | 
			
		||||
 | 
			
		||||
    _onPhoneCountryChange: function(phoneCountry) {
 | 
			
		||||
        this.setState({ phoneCountry: phoneCountry });
 | 
			
		||||
        this.setState({ phoneCountry: phoneCountry.iso2 });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onPhoneNumberChange: function(ev) {
 | 
			
		||||
| 
						 | 
				
			
			@ -149,10 +149,11 @@ export default WithMatrixClient(React.createClass({
 | 
			
		|||
                <div className="mx_UserSettings_profileLabelCell">
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className="mx_UserSettings_profileInputCell">
 | 
			
		||||
                    <div className="mx_Login_phoneSection">
 | 
			
		||||
                    <div className="mx_UserSettings_phoneSection">
 | 
			
		||||
                        <CountryDropdown onOptionChange={this._onPhoneCountryChange}
 | 
			
		||||
                            className="mx_Login_phoneCountry"
 | 
			
		||||
                            className="mx_UserSettings_phoneCountry"
 | 
			
		||||
                            value={this.state.phoneCountry}
 | 
			
		||||
                            isSmall={true}
 | 
			
		||||
                        />
 | 
			
		||||
                        <input type="text"
 | 
			
		||||
                            ref={this._collectAddMsisdnInput}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue