diff --git a/client/lib/states-list/README.md b/client/lib/states-list/README.md deleted file mode 100644 index 1635da44cdf374..00000000000000 --- a/client/lib/states-list/README.md +++ /dev/null @@ -1,28 +0,0 @@ -States List -============== - -The `states-list` module provides access to localized list of states as returned from the REST API. These lists are ordered alphabetically. - -## Usage - -The list of supported states for domain registrations can be retrieved with: - -```js -var statesList = require( 'lib/states-list' ).forDomainRegistrations(); -``` - -## Methods - -The following public methods are available: - -### `fetchForCountry( countryCode )` - -This fetches the corresponding list of states from the server. The list is cached in the store upon retrieval. - -### `getByCountry( countryCode )` - -This retrieves the list of states as a set of key and value pairs. The list is loaded from the store and then fetched once from the server to update any stale data. - -### `hasLoadedFromServer()` - -This determines whether the list of states has already been loaded from the server or not. diff --git a/client/lib/states-list/index.js b/client/lib/states-list/index.js deleted file mode 100644 index 7387c19be349ba..00000000000000 --- a/client/lib/states-list/index.js +++ /dev/null @@ -1,152 +0,0 @@ -/** - * External dependencies - */ -var debug = require( 'debug' )( 'calypso:StatesList' ), - inherits = require( 'inherits' ), - isEmpty = require( 'lodash/isEmpty' ), - store = require( 'store' ); - -/** - * Internal dependencies - */ -var Emitter = require( 'lib/mixins/emitter' ), - wpcom = require( 'lib/wp' ).undocumented(); - -/** - * Initializes a new list of states. - * - * @constructor - * @param {string} key - key used to identify this list in the store or the debug messages - */ -function StatesList( key ) { - if ( ! ( this instanceof StatesList ) ) { - return new StatesList( key ); - } - - this.key = key + 'StatesList'; - this.initialized = false; -} - -/** - * Adds event capabilities to this list of states. - */ -Emitter( StatesList.prototype ); - -/** - * Fetches the list of states for the specified country from the server. - * - * @param {string} countryCode - country code - */ -StatesList.prototype.fetchForCountry = function( countryCode ) { - if ( ! this.isFetching && ! isEmpty( countryCode ) ) { - debug( 'Fetching ' + this.key + ' for ' + countryCode + ' from api' ); - - this.isFetching = true; - - // Sends a request to the API endpoint defined in the subclass - this.requestFromEndpoint( countryCode, function( error, data ) { - var statesList; - - if ( error ) { - debug( 'Unable to fetch ' + this.key + ' for ' + countryCode + ' from api', error ); - - return; - } - - statesList = data; - - debug( this.key + ' for ' + countryCode + ' fetched from api successfully:', statesList ); - - if ( ! this.initialized ) { - var statesLists = {}; - statesLists[ countryCode ] = statesList; - - this.initialize( statesLists ); - } else { - this.data[ countryCode ] = statesList; - } - - this.isFetching = false; - - this.emit( 'change' ); - - store.set( this.key, this.data ); - }.bind( this ) ); - } -}; - -/** - * Retrieves the list of states as a set of key and value pairs. This list will be loaded from the store and then - * fetched once from the server to update any stale data. - * - * @param {string} countryCode - country code - * @returns {object} the list of states - */ -StatesList.prototype.getByCountry = function( countryCode ) { - var data; - - if ( ! this.data ) { - data = store.get( this.key ); - - if ( data ) { - debug( 'Loaded ' + this.key + ' from store', data ); - - this.initialize( data ); - } else { - this.data = {}; - } - - this.fetchForCountry( countryCode ); - } else if ( ! ( countryCode in this.data ) ) { - this.fetchForCountry( countryCode ); - } - - if ( countryCode in this.data ) { - return this.data[ countryCode ]; - } else { - return null; - } -}; - -/** - * Determines whether this list of states has already been loaded from the server or not. - * - * @return {boolean} true if this list of states has been loaded, false otherwise - */ -StatesList.prototype.hasLoadedFromServer = function() { - return this.initialized; -}; - -/** - * Initializes this list of states with the specified data. - * - * @param {object} data - data - */ -StatesList.prototype.initialize = function( data ) { - this.data = data; - - this.initialized = true; -}; - -/** - * Initializes a new list of states for domain registrations. - * - * @constructor - */ -function DomainRegistrationStatesList() { - StatesList.call( this, 'DomainRegistration' ); -} - -inherits( DomainRegistrationStatesList, StatesList ); - -DomainRegistrationStatesList.prototype.requestFromEndpoint = function( countryCode, fn ) { - return wpcom.getDomainRegistrationSupportedStates( countryCode, fn ); -}; - -var domainRegistrationStatesList = new DomainRegistrationStatesList(); - -module.exports = { - forDomainRegistrations: function() { - return domainRegistrationStatesList; - } -}; diff --git a/client/my-sites/upgrades/checkout/domain-details-form.jsx b/client/my-sites/upgrades/checkout/domain-details-form.jsx index c4150f454489b2..4da04edbf67d89 100644 --- a/client/my-sites/upgrades/checkout/domain-details-form.jsx +++ b/client/my-sites/upgrades/checkout/domain-details-form.jsx @@ -16,7 +16,6 @@ import PrivacyProtection from './privacy-protection'; import PaymentBox from './payment-box'; import { cartItems } from 'lib/cart-values'; import { forDomainRegistrations as countriesListForDomainRegistrations } from 'lib/countries-list'; -import { forDomainRegistrations as statesListForDomainRegistrations } from 'lib/states-list'; import analytics from 'lib/analytics'; import formState from 'lib/form-state'; import { addPrivacyToAllDomains, removePrivacyFromAllDomains, setDomainDetails } from 'lib/upgrades/actions'; @@ -24,8 +23,7 @@ import FormButton from 'components/forms/form-button'; // Cannot convert to ES6 import const wpcom = require( 'lib/wp' ).undocumented(), - countriesList = countriesListForDomainRegistrations(), - statesList = statesListForDomainRegistrations(); + countriesList = countriesListForDomainRegistrations(); export default React.createClass( { displayName: 'DomainDetailsForm', @@ -238,7 +236,6 @@ export default React.createClass( { diff --git a/client/my-sites/upgrades/components/form/state-select.jsx b/client/my-sites/upgrades/components/form/state-select.jsx index bcc246c3503223..3eeb6ad2b8b6f9 100644 --- a/client/my-sites/upgrades/components/form/state-select.jsx +++ b/client/my-sites/upgrades/components/form/state-select.jsx @@ -1,32 +1,39 @@ /** * External dependencies */ -const React = require( 'react' ), - classNames = require( 'classnames' ), - isEmpty = require( 'lodash/isEmpty' ), - ReactDom = require( 'react-dom' ), - observe = require( 'lib/mixins/data-observe' ); +import React, { Component, PropTypes } from 'react'; +import classNames from 'classnames'; +import { connect } from 'react-redux'; +import { isEmpty } from 'lodash'; +import { localize } from 'i18n-calypso'; +import ReactDom from 'react-dom'; /** * Internal dependencies */ -const analytics = require( 'lib/analytics' ), - FormLabel = require( 'components/forms/form-label' ), - FormSelect = require( 'components/forms/form-select' ), - FormInputValidation = require( 'components/forms/form-input-validation' ), - scrollIntoViewport = require( 'lib/scroll-into-viewport' ), - Input = require( './input' ); +import FormLabel from 'components/forms/form-label'; +import FormSelect from 'components/forms/form-select'; +import FormInputValidation from 'components/forms/form-input-validation'; +import { getCountryStates } from 'state/country-states/selectors'; +import Input from './input'; +import QueryCountryStates from 'components/data/query-country-states'; +import { recordGoogleEvent } from 'state/analytics/actions'; +import scrollIntoViewport from 'lib/scroll-into-viewport'; -module.exports = React.createClass( { - displayName: 'StateSelect', +class StateSelect extends Component { + static instances = 0; - mixins: [ observe( 'statesList' ) ], + componentWillMount() { + this.instance = ++this.constructor.instances; + } + + recordStateSelectClick = () => { + const { eventFormName, recordGoogleEvent: recordEvent } = this.props; - recordStateSelectClick: function() { - if ( this.props.eventFormName ) { - analytics.ga.recordEvent( 'Upgrades', `Clicked ${ this.props.eventFormName } State Select` ); + if ( eventFormName ) { + recordEvent( 'Upgrades', `Clicked ${ eventFormName } State Select` ); } - }, + }; focus() { const node = ReactDom.findDOMNode( this.refs.input ); @@ -36,47 +43,58 @@ module.exports = React.createClass( { } else { this.refs.state.focus(); } - }, - - render: function() { - const classes = classNames( this.props.additionalClasses, 'state' ), - statesList = this.props.statesList.getByCountry( this.props.countryCode ); - let options = []; - - if ( isEmpty( statesList ) ) { - return ( - - ); - } - - options.push( { key: '', label: this.translate( 'Select State' ), disabled: 'disabled' } ); + } - options = options.concat( statesList.map( function( state ) { - if ( ! state.code ) { - return { key: '--', label: '', disabled: 'disabled' }; - } - return { key: state.code, label: state.name }; - } ) ); + render() { + const classes = classNames( this.props.additionalClasses, 'state' ); return ( -
-
- { this.props.label } - - { options.map( function( option ) { - return ; - } ) } - -
+
+ { this.props.countryCode && } + { isEmpty( this.props.countryStates ) + ? + :
+ { this.props.label } + + + + { this.props.countryStates.map( ( state ) => + + ) } + +
+ } { this.props.errorMessage && }
); } -} ); +} + +StateSelect.propTypes = { + additionalClasses: PropTypes.string, + countryCode: PropTypes.string, + countryStates: PropTypes.array, + disabled: PropTypes.bool, + errorMessage: PropTypes.string, + eventFormName: PropTypes.string, + isError: PropTypes.bool, + label: PropTypes.string, + name: PropTypes.string, + onChange: PropTypes.func, + value: PropTypes.string, +}; + +export default connect( + ( state, { countryCode } ) => ( { + countryStates: countryCode ? getCountryStates( state, countryCode ) : [] + } ), + { recordGoogleEvent } +)( localize( StateSelect ) ); diff --git a/client/my-sites/upgrades/domain-management/edit-contact-info/form-card.jsx b/client/my-sites/upgrades/domain-management/edit-contact-info/form-card.jsx index 5b6dfa5e108ac2..128e1ed1526ba8 100644 --- a/client/my-sites/upgrades/domain-management/edit-contact-info/form-card.jsx +++ b/client/my-sites/upgrades/domain-management/edit-contact-info/form-card.jsx @@ -22,7 +22,6 @@ const Card = require( 'components/card' ), formState = require( 'lib/form-state' ), notices = require( 'notices' ), paths = require( 'my-sites/upgrades/paths' ), - statesList = require( 'lib/states-list' ).forDomainRegistrations(), upgradesActions = require( 'lib/upgrades/actions' ), wpcom = require( 'lib/wp' ).undocumented(), successNotice = require( 'state/notices/actions' ).successNotice; @@ -177,7 +176,6 @@ const EditContactInfoFormCard = React.createClass( { } ) } { this.getField( FormStateSelect, { countryCode: formState.getFieldValue( this.state.form, 'countryCode' ), - statesList, name: 'state', label: this.translate( 'State', { context: 'Domain Edit Contact Info form.',