-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Framework: Remove sites-list from ProfileLinksAddWordPress #14758
Conversation
return ( | ||
<form> | ||
<p> | ||
{ | ||
this.translate( | ||
translate( | ||
'You have no public sites on WordPress.com yet, but if you like you ' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi! I've found a possible matching string that has already been translated 21 times:
translate( 'You have no public sites on WordPress.com yet, but if you like you can create one now. You may also add self-hosted WordPress sites here after installing {{jetpackLink}}Jetpack{{/jetpackLink}} on them.' )
ES Score: 18
Help me improve these suggestions: react with 👎 if the suggestion doesn't make any sense, or with 👍 if it's a particularly good one (even if not implemented).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I'm not changing the string, @a8ci18n?
> | ||
{ this.translate( 'Add Site', 'Add Sites', { count: checkedCount } ) } | ||
{ translate( 'Add Site', 'Add Sites', { count: checkedCount } ) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😞 85 existing translations will be lost with this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I'm not changing the string, @a8ci18n?
* @param {Object} state Global state tree | ||
* @return {Array} Site objects | ||
*/ | ||
export default function getPublicSites( state ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is probably worth memoizing with createSelector
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, done in dc84197.
|
||
export default connect( | ||
( state ) => ( { | ||
sites: keyBy( getSites( state ), 'ID' ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. There might be a way.
this.props.sites
seems to only be used to obtain name
and URL
in preparation of the call to this.props.userProfileLinks.addProfileLinks
. In that case, I would define an action creator:
// pseudo-code-ish
const addProfileLinks = ( inputs ) => ( dispatch, getState ) => {
const links = inputs
.filter( isSiteInput )
.map( toSiteId )
.map( getSite( getState(), _ ) )
.map( pick( _, [ 'name', 'URL' ] ) );
if ( links.length ) userProfileLinks.addProfileLinks( links );
};
If not, at the very least you should cache this selection, since keyBy
could potentially process a large number of sites and, more importantly, will always return a new reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
title: site.name, | ||
value: site.URL | ||
} ); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[obviously besides the scope of this PR] May I just say that I hate that we still have these data libraries like UserProfileLinks
? :/ It took me a while to realize why we were duplicating site state into links
, that this is actually an action "dispatch" in disguise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree completely. It's a very obsolete pattern that we should consider refactoring in a future PR.
@@ -157,84 +157,94 @@ export default React.createClass( { | |||
<Site | |||
site={ site } | |||
indicator={ false } | |||
onSelect={ this.onSelect.bind( this, inputName ) } /> | |||
onSelect={ this.onSelect( inputName ) } /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this is still an instance of function binding within render
. No cheating! 😄
The core problem is that we want to assign/bind (not necessarily in the Function#bind
sense) a particular site/input to an event handler (onSelect
). There are several ways to deal with it. One, which might make the most sense here, is to refactor the <li>
node into a component — e.g.:
class AddableSite extends PureComponent {
inputName = `site-${ site.ID }`
onSelect = this.props.onSelect.bind( null, inputName )
render() {
return <li>…<Site site={ site } onSelect={ this.onSelect } … />…</li>;
}
}
// …
renderAddableSites() {
return this.props.publicSites.map( ( site ) =>
this.props.userProfileLinks.isSiteInProfileLinks( site )
? null
: <AddableSite site={ site } />;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point there, addressed in 8613691.
|
||
export default connect( | ||
( state ) => ( { | ||
sites: keyBy( getSites( state ), 'ID' ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. There might be a way.
this.props.sites
seems to only be used to obtain name
and URL
in preparation of the call to this.props.userProfileLinks.addProfileLinks
. In that case, I would define an action creator:
// pseudo-code-ish
const addProfileLinks = ( inputs ) => ( dispatch, getState ) => {
const links = inputs
.filter( isSiteInput )
.map( toSiteId )
.map( getSite( getState(), _ ) )
.map( pick( _, [ 'name', 'URL' ] ) );
if ( links.length ) userProfileLinks.addProfileLinks( links );
};
If not, at the very least you should cache this selection, since keyBy
could potentially process a large number of sites and, more importantly, will always return a new reference.
* @param {Object} state Global state tree | ||
* @return {Array} Site objects | ||
*/ | ||
export default function getPublicSites( state ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please. :)
67b36f1
to
901bdac
Compare
checked: false, | ||
}; | ||
|
||
inputName = `site-${ this.props.site.ID }`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this update properly outside of render? I feel like this won't be correct if we pass another site/onSelect to this component
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work?
onSelect = ( event ) => {
this.props.onSelect( event, `site-${ this.props.site.ID }` );
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That shouldn't be a problem, because we're mounting one ProfileLinksAddWordPressSite
instance for each site anyway. But it's a nice improvement, so I've addressed in f65e2af.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than the note I left, things look good 👍
Thanks! I've addressed your recommendation @gwwar, do you have any other tips before we 🚢 ? |
|
f65e2af
to
debc1c5
Compare
This PR removes the
sites-list
usage from theProfileLinksAddWordPress
component. It also ES6ifies the component and introduces a straightforwardgetPublicSites
selector that we need in order to allow only public sites to be added as profile links.To test: