Skip to content

Commit

Permalink
Sites: Use Redux state preference for recent sites (#7478)
Browse files Browse the repository at this point in the history
* Sites: Use Redux state preference for recent sites

* SItes: Map recent sites over sites keyed by ID

Splice does not work as intended when inserting indices out of order.

* Framework: Render controller elements with store context

* Sites: Render connected site selector as pure

Sites object can change internally, which can be monitored via observe
mixin until we’ve migrated to Redux-based state

* State: Remove unused recentlySelectedSiteIds reducer
  • Loading branch information
aduth authored Aug 19, 2016
1 parent e3e623a commit ae9a102
Show file tree
Hide file tree
Showing 14 changed files with 151 additions and 180 deletions.
110 changes: 60 additions & 50 deletions client/components/site-selector/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
*/
import React from 'react';
import ReactDom from 'react-dom';
import { connect } from 'react-redux';
import page from 'page';
import classNames from 'classnames';
import { filter, size, keyBy, map, includes } from 'lodash';

/**
* Internal dependencies
*/
import { getPreference } from 'state/preferences/selectors';
import observe from 'lib/mixins/data-observe';
import AllSites from 'my-sites/all-sites';
import analytics from 'lib/analytics';
import Button from 'components/button';
Expand All @@ -18,13 +22,12 @@ import SitePlaceholder from 'blocks/site/placeholder';
import Search from 'components/search';
import userModule from 'lib/user';
import config from 'config';
import PreferencesData from 'components/data/preferences-data';

const user = userModule();
const noop = () => {};

export default React.createClass( {
displayName: 'SiteSelector',
const SiteSelector = React.createClass( {
mixins: [ observe( 'sites' ) ],

propTypes: {
sites: React.PropTypes.object,
Expand Down Expand Up @@ -149,9 +152,12 @@ export default React.createClass( {
if ( this.state.search ) {
sites = this.props.sites.search( this.state.search );
} else {
sites = this.shouldShowGroups()
? this.props.sites.getVisibleAndNotRecent()
: this.props.sites.getVisible();
sites = this.props.sites.getVisible();

const { recentSites } = this.props;
if ( this.shouldShowGroups() && size( recentSites ) ) {
sites = filter( sites, ( { ID: siteId } ) => ! includes( recentSites, siteId ) );
}
}

if ( this.props.filter ) {
Expand Down Expand Up @@ -222,38 +228,38 @@ export default React.createClass( {
},

renderRecentSites() {
const sites = this.props.sites.getRecentlySelected();

if ( ! sites || this.state.search || ! this.shouldShowGroups() ) {
return null;
if ( this.state.search || ! this.shouldShowGroups() ) {
return;
}

const recentSites = sites.map( function( site ) {
var siteHref;

if ( this.props.siteBasePath ) {
siteHref = this.getSiteBasePath( site ) + '/' + site.slug;
}

const isSelected = this.isSelected( site );
const sitesById = keyBy( this.props.sites.get(), 'ID' );

return (
<Site
site={ site }
href={ siteHref }
key={ 'site-' + site.ID }
indicator={ this.props.indicator }
onSelect={ this.onSiteSelect.bind( this, site.slug ) }
isSelected={ isSelected }
/>
);
}, this );

if ( ! recentSites ) {
return null;
}

return <div className="site-selector__recent">{ recentSites }</div>;
return (
<div className="site-selector__recent">
{ map( this.props.recentSites, ( siteId ) => {
const site = sitesById[ siteId ];
if ( ! site ) {
return;
}

let siteHref;
if ( this.props.siteBasePath ) {
siteHref = this.getSiteBasePath( site ) + '/' + site.slug;
}

return (
<Site
site={ site }
href={ siteHref }
key={ 'site-' + site.ID }
indicator={ this.props.indicator }
onSelect={ this.onSiteSelect.bind( this, site.slug ) }
isSelected={ this.isSelected( site ) }
/>
);
} ) }
</div>
);
},

render() {
Expand All @@ -263,22 +269,26 @@ export default React.createClass( {
} );

return (
<PreferencesData>
<div className={ selectorClass }>
<Search
ref="siteSearch"
onSearch={ this.onSearch }
autoFocus={ this.props.autoFocus }
disabled={ ! this.props.sites.initialized }
onSearchClose={ this.props.onClose }
/>
<div className="site-selector__sites" ref="selector">
{ this.renderAllSites() }
{ this.renderSites() }
</div>
{ this.props.showAddNewSite && this.addNewSite() }
<div className={ selectorClass }>
<Search
ref="siteSearch"
onSearch={ this.onSearch }
autoFocus={ this.props.autoFocus }
disabled={ ! this.props.sites.initialized }
onSearchClose={ this.props.onClose }
/>
<div className="site-selector__sites" ref="selector">
{ this.renderAllSites() }
{ this.renderSites() }
</div>
</PreferencesData>
{ this.props.showAddNewSite && this.addNewSite() }
</div>
);
}
} );

export default connect( ( state ) => {
return {
recentSites: getPreference( state, 'recentSites' )
};
} )( SiteSelector );
4 changes: 4 additions & 0 deletions client/components/site-selector/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,8 @@

.site-selector__recent {
border-bottom: 1px solid lighten( $gray, 30% );

&:empty {
border-bottom-width: 0;
}
}
69 changes: 0 additions & 69 deletions client/lib/sites-list/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ var wpcom = require( 'lib/wp' ),
Searchable = require( 'lib/mixins/searchable' ),
Emitter = require( 'lib/mixins/emitter' ),
isPlan = require( 'lib/products-values' ).isPlan,
PreferencesActions = require( 'lib/preferences/actions' ),
PreferencesStore = require( 'lib/preferences/store' ),
user = require( 'lib/user' )(),
userUtils = require( 'lib/user/utils' );

/**
Expand All @@ -38,7 +35,6 @@ function SitesList() {
this.selected = null;
this.lastSelected = null;
this.propagateChange = this.propagateChange.bind( this );
this.recentlySelected = PreferencesStore.get( 'recentSites' ) || [];
}

/**
Expand Down Expand Up @@ -382,55 +378,6 @@ SitesList.prototype.isSelected = function( site ) {
return this.selected === site.slug;
};

/**
* Set recently selected site
*
* @param {number} Site ID
* @api private
*/
SitesList.prototype.setRecentlySelectedSite = function( siteID ) {
if ( ! this.recentlySelected || this.recentlySelected.length === 0 ) {
this.recentlySelected = PreferencesStore.get( 'recentSites' ) || [];
}

if ( ! siteID || ! this.initialized ) {
return;
}

const index = this.recentlySelected.indexOf( siteID );

// do not add duplicates
if ( index !== -1 ) {
this.recentlySelected.splice( index, 1 );
}

this.recentlySelected.unshift( siteID );

const sites = this.recentlySelected.slice( 0, 3 );
PreferencesActions.set( 'recentSites', sites );

this.emit( 'change' );
};

SitesList.prototype.getRecentlySelected = function() {
this.recentlySelected = PreferencesStore.get( 'recentSites' ) || [];

if ( ! this.recentlySelected.length || ! this.initialized ) {
return false;
}

let sites = [];

this.recentlySelected.forEach( function( id, index ) {
sites[ index ] = this.get().filter( function( site ) {
return id === site.ID;
}, this )[ 0 ];
}, this );

// remove undefined sites
return sites.filter( site => site );
};

/**
* Get a single site object from a numeric ID or domain ID
*
Expand Down Expand Up @@ -519,22 +466,6 @@ SitesList.prototype.getVisible = function() {
}, this );
};

/**
* Get sites that are marked as visible and not recently selected
*
* @api public
**/
SitesList.prototype.getVisibleAndNotRecent = function() {
this.recentlySelected = PreferencesStore.get( 'recentSites' ) || [];
return this.get().filter( function( site ) {
if ( user.get().visible_site_count < 12 ) {
return site.visible === true;
}

return site.visible === true && this.recentlySelected && this.recentlySelected.indexOf( site.ID ) === -1;
}, this );
};

SitesList.prototype.getUpgradeable = function() {
return this.get().filter( function( site ) {
return site.isUpgradeable();
Expand Down
7 changes: 4 additions & 3 deletions client/mailing-lists/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
* External Dependencies
*/
import omit from 'lodash/omit';
import ReactDom from 'react-dom';
import React from 'react';
import { setSection } from 'state/ui/actions';

/**
* Internal Dependencies
*/
import MainComponent from './main';
import { renderWithReduxStore } from 'lib/react-helpers';

export default {
unsubscribe( context ) {
Expand All @@ -18,14 +18,15 @@ export default {
hasSidebar: false
} ) );

ReactDom.render(
renderWithReduxStore(
React.createElement( MainComponent, {
email: context.query.email,
category: context.query.category,
hmac: context.query.hmac,
context: omit( context.query, [ 'email', 'category', 'hmac' ] )
} ),
document.getElementById( 'primary' )
document.getElementById( 'primary' ),
context.store
);
}
};
Loading

0 comments on commit ae9a102

Please sign in to comment.