Skip to content
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

Merged
merged 41 commits into from
May 9, 2017

Conversation

mcsf
Copy link
Member

@mcsf mcsf commented Apr 13, 2017

Do not merge Yay!

This PR seeks to identity pinpointable pain points for project Remove SitesList by starting from Layout, requesting all sites via QuerySites, and going down from there. Points of interest include my-sites/controllers, navigation, site switching.

  • QuerySites in layout.
  • Refactor my-sites controller functions.
  • Figure out once cases.
  • Implement site search.
  • Enable persistence of sites.
  • Restore recent sites view in selectors.
  • Fix undefined navigation.
  • Figure out logic for loading / not found / single selected / all selected.
  • Update once cases. (Signup and domain management remain.)
  • Site Preview, avoid regressions

@matticbot
Copy link
Contributor

@mcsf mcsf assigned mcsf, ehg and mtias Apr 13, 2017
@matticbot matticbot added the [Size] L Large sized issue label Apr 13, 2017
@mcsf mcsf mentioned this pull request Apr 14, 2017
@mcsf mcsf force-pushed the try/layout-query-sites branch 2 times, most recently from ef4f080 to 6f6fe46 Compare April 14, 2017 15:36
@matticbot matticbot added [Size] XL Probably needs to be broken down into multiple smaller issues and removed [Size] L Large sized issue labels Apr 14, 2017
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 );
Copy link
Contributor

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.

Copy link
Member Author

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WIP at #13123

@mcsf mcsf force-pushed the try/layout-query-sites branch from 6f6fe46 to 14bbd1f Compare April 15, 2017 14:48
@mcsf
Copy link
Member Author

mcsf commented Apr 15, 2017

Refactored on top of some selector additions. my-sites/controller is the current focus of this. So far, in that module, everything seems to have been replaced with Redux selections and action dispatches, except:

@mcsf mcsf changed the title Add QuerySites in Layout and shift from sitesFactory to Redux sites Exploration: Top-down removal of SitesList, starting from Layout Apr 15, 2017
@mcsf mcsf force-pushed the try/layout-query-sites branch from 14bbd1f to 5ec97fa Compare April 17, 2017 16:42
}
// @FIXME don't use sitesFactory
//if ( config.isEnabled( 'keyboard-shortcuts' ) ) {
// require( 'lib/keyboard-shortcuts/global' )( sitesFactory() );
Copy link
Member

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being fixed in #13206

Copy link
Contributor

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;
Copy link
Member

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 );
Copy link
Member

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?

Copy link
Member Author

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 />
Copy link
Contributor

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...

Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Member

@gziolo gziolo Apr 25, 2017

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 ...

Copy link
Contributor

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

Copy link
Contributor

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? ^^

mcsf added 12 commits May 9, 2017 14:25
…omizable"

This reverts commit d180acc, reversing
changes made to 78d8f29.
* 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.
@mcsf mcsf force-pushed the try/layout-query-sites branch from bb4ecb7 to 698aa74 Compare May 9, 2017 13:29
@mcsf mcsf merged commit ef40e66 into master May 9, 2017
@matticbot matticbot removed the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label May 9, 2017
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 ),
Copy link
Contributor

@blowery blowery May 9, 2017

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...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

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

@mcsf mcsf deleted the try/layout-query-sites branch May 9, 2017 14:38
jsnajdr added a commit that referenced this pull request Jan 10, 2018
…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
jsnajdr added a commit that referenced this pull request Jan 10, 2018
…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
rclations pushed a commit to rclations/wp-calypso that referenced this pull request Jan 12, 2018
…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
@scinos scinos mentioned this pull request Sep 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Sites [Size] XL Probably needs to be broken down into multiple smaller issues State [Status] Needs Rebase
Projects
None yet
Development

Successfully merging this pull request may close these issues.