-
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
Exploration: Top-down removal of SitesList, starting from Layout #13094
Conversation
ef4f080
to
6f6fe46
Compare
client/my-sites/controller.js
Outdated
const siteID = route.getSiteFragment( context.path ); | ||
const basePath = route.sectionify( context.path ); | ||
const currentUser = user.get(); | ||
const hasOneSite = currentUser.visible_site_count === 1; | ||
const allSitesPath = route.sectionify( context.path ); | ||
const primaryId = getPrimarySiteId( state ); | ||
const primary = getSite( state, primaryId ) || ''; | ||
const hasInitialized = !! getSites( 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.
Is the intention here to wait for fresh data, or is persisted data fine? This will be true if we have some sites in indexedDB.
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.
Indeed — this has to be solved some other way.
const site = this.props.getSiteBySlug( slug ); | ||
console.warn( 'getSiteBySlug', site, slug ); | ||
|
||
// @FIXME move to selector |
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.
WIP at #13123
6f6fe46
to
14bbd1f
Compare
Refactored on top of some selector additions.
|
14bbd1f
to
5ec97fa
Compare
client/boot/project/wordpress-com.js
Outdated
} | ||
// @FIXME don't use sitesFactory | ||
//if ( config.isEnabled( 'keyboard-shortcuts' ) ) { | ||
// require( 'lib/keyboard-shortcuts/global' )( sitesFactory() ); |
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.
fwiw, I'd be ok with disabling this if it becomes a blocker.
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.
Being fixed in #13206
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.
It's merged 👍
@@ -118,7 +133,8 @@ const SiteSelector = React.createClass( { | |||
highlightedIndex = this.state.highlightedIndex; | |||
} else if ( this.lastMouseHover ) { | |||
debug( `restoring highlight from last mouse hover (${ this.lastMouseHover })` ); | |||
highlightedSite = this.props.sites.getSite( this.lastMouseHover ) || this.lastMouseHover; | |||
// @FIXME | |||
highlightedSite = this.props.getSiteBySlug( this.lastMouseHover ) || this.lastMouseHover; |
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.
This is all really odd and hard to read, but let's push any bigger refactoring (lastMouseHover
being a slug) for after sites-list is done.
const site = getRawSite( state, siteId ) || | ||
// Support for non-ID site retrieval | ||
// Replaces SitesList#getSite | ||
getSiteBySlug( state, siteId ); |
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.
Should this be done in getRawSite
instead?
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 would be a circular dependency between getRawSite
and getSiteBySlug
via getSiteSlug
.
@@ -143,6 +143,7 @@ Layout = React.createClass( { | |||
return ( | |||
<div className={ sectionClass }> | |||
<DocumentHead /> | |||
<QuerySites allSites /> |
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.
Instead of Layout
, should this maybe live in my-sites/sidebar
(and use selectedSiteId
in single-site mode there)? That'd seem a bit more fine-grained to me. Not all sections need (all) sites data...
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.
I think the motivation was to be more preemptive in fetching sites data, despite not all sections requiring it. For now, I'd be inclined to leave it in Layout
, but I don't feel strongly about either.
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.
We use sites data for sites popover in every section and in the masterbar, that was the main reason. Also, because it replaces fetching we were doing at controller level.
If we need to exclude from a certain section, we can do the checks needed in Layout. But I'm fine with this. Sites is pretty instrumental for the whole calypso experience.
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.
Yes, it makes sense. Sooner or later all logged in sections need sites list ...
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.
If we're adding this to layout can we clean up other usages of <QuerySites allSites />
in
- client/my-sites/plugins/plugin.jsx
- client/my-sites/stats/overview.jsx
- client/signup/jetpack-connect/index.jsx
- client/signup/jetpack-connect/authorize-form.jsx
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.
@mcsf could we clean up these? ^^
5ec97fa
to
5fba283
Compare
* Import was kept, as `sites` is passed as props in one controller. To be fixed in a separate PR.
- :-( - Aims to fix regressions found, notably around flows in `/domains`
This mimics the behavior that used to be in place with `sites.initialized`. Without it, render jumps may happen as we default to a site-less view then correct to a site-specific one.
Component logic expects non-number `count`, e.g. when no site is selected. This eliminates React type warnings.
One of the async jobs of fetchSitesAndUser is to trigger a `fetch` on `lib/sites-list`, wait for changes to that structure, check for the local availability of data for the new site, then either continue or retrigger a fetch. This commit ports that behavior to our Redux data layer.
Before #13094, this behavior was ensured by the `acceptInvite` action creator, which dispatches old Flux actions that `lib/sites-list` listens to in order to call a `sync` on itself.
bb4ecb7
to
698aa74
Compare
showRecentSites: get( user, 'visible_site_count', 0 ) > 11, | ||
recentSites: getPreference( state, 'recentSites' ), | ||
siteCount: get( user, 'site_count', 0 ), | ||
visibleSiteCount: visibleSiteCount, | ||
getSite: getSite.bind( null, 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.
isn't this going to make the component effectively impure? every time connect runs, this will be a different function and shallowEquals will fail...
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.
ah, you covered this later on in https://github.com/Automattic/wp-calypso/pull/13094/files#r112195983
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.
@blowery: correct, and it's been a priority of mine to tackle these. There were other such occurrences that we got rid of in the meantime, but this one stayed. Now that this is merged, it unblocks some other work around SiteSelector
, Site
, etc., which seeks to make more parts only care about site IDs and not need to satisfy as much data. /cc @ockham
…at all Fixes a bug where `SiteSelector` would show a placeholder instead of list of visible sites, even when the sites list data are available. The `isRequestingMissingSites` selector returns `true` when there is an outstanding request for the sites data and the local data are detected as not-fresh, i.e., the local site count is different from the server site count, as revealed by the `user.site_count` property. In such a case, a placeholder is shown instead of showing the available local list. This is a regression introduced in #13094, when `sites-list` was removed from the component. The condition to show the placeholder used to be `! sites.initialized`, which is much weaker than `isRequestingMissingSites`. The `sites-list` could be initialized from local storage data and be requesting an update from the server, without affecting the `initialized` flag. This patch replaces the `isRequestingMissingSites` selector with `hasLoadedSites`, which is more appropriate here. It also fixes the `disabled` condition for the `Search` component. It used to be `! this.props.sites`, but `this.props.sites` is always truthy, because the `getSites` selector returns an empty object when there are no site data. This could happen when the sites list data were detected as not-fresh
…at all Fixes a bug where `SiteSelector` would show a placeholder instead of list of visible sites, even when the sites list data are available. The `isRequestingMissingSites` selector returns `true` when there is an outstanding request for the sites data and the local data are detected as not-fresh, i.e., the local site count is different from the server site count, as revealed by the `user.site_count` property. In such a case, a placeholder is shown instead of showing the available local list. This is a regression introduced in #13094, when `sites-list` was removed from the component. The condition to show the placeholder used to be `! sites.initialized`, which is much weaker than `isRequestingMissingSites`. The `sites-list` could be initialized from local storage data and be requesting an update from the server, without affecting the `initialized` flag. This patch replaces the `isRequestingMissingSites` selector with `hasLoadedSites`, which is more appropriate here. It also fixes the `disabled` condition for the `Search` component. It used to be `! this.props.sites`, but `this.props.sites` is always truthy, because the `getSites` selector returns an empty object when there are no site data. This could happen when the sites list data were detected as not-fresh
…at all Fixes a bug where `SiteSelector` would show a placeholder instead of list of visible sites, even when the sites list data are available. The `isRequestingMissingSites` selector returns `true` when there is an outstanding request for the sites data and the local data are detected as not-fresh, i.e., the local site count is different from the server site count, as revealed by the `user.site_count` property. In such a case, a placeholder is shown instead of showing the available local list. This is a regression introduced in Automattic#13094, when `sites-list` was removed from the component. The condition to show the placeholder used to be `! sites.initialized`, which is much weaker than `isRequestingMissingSites`. The `sites-list` could be initialized from local storage data and be requesting an update from the server, without affecting the `initialized` flag. This patch replaces the `isRequestingMissingSites` selector with `hasLoadedSites`, which is more appropriate here. It also fixes the `disabled` condition for the `Search` component. It used to be `! this.props.sites`, but `this.props.sites` is always truthy, because the `getSites` selector returns an empty object when there are no site data. This could happen when the sites list data were detected as not-fresh
Do not mergeYay!This PR seeks to identity pinpointable pain points for project Remove SitesList by starting from
Layout
, requesting all sites viaQuerySites
, and going down from there. Points of interest includemy-sites/controllers
, navigation, site switching.QuerySites
in layout.once
cases.once
cases. (Signup and domain management remain.)