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

Enhancement/2074 allow registering module setup components #2129

Merged
merged 16 commits into from
Oct 29, 2020

Conversation

caseymorrisus
Copy link
Contributor

Summary

Addresses issue #2074

Relevant technical choices

  • Created DefaultModuleSetup component
  • Added registerModule action with setupComponent argument with DefaultModuleSetup as the default value
  • Refactored SetupWrapper to be a functional component and grab module data from registry via getModule
  • Update modules to register components via registerModule rather than using a filter via googlesitekit.ModuleSetup-${ slug }
  • Fixed stories to account for modules coming from the store

Checklist

  • My code is tested and passes existing unit tests.
  • My code has an appropriate set of unit tests which all pass.
  • My code is backward-compatible with WordPress 4.7 and PHP 5.6.
  • My code follows the WordPress coding standards.
  • My code has proper inline documentation.
  • I have added a QA Brief on the issue linked above.
  • I have signed the Contributor License Agreement (see https://cla.developers.google.com/).

@google-cla google-cla bot added the cla: yes label Oct 5, 2020
@caseymorrisus
Copy link
Contributor Author

Tests pass locally, failing on server due to flaky tests therefore I am moving this out of draft as I cannot manually re-run Travis CI jobs without dummy commits. Whoever ends up reviewing this will need to re-run Travis to get checks to pass.

@caseymorrisus caseymorrisus marked this pull request as ready for review October 7, 2020 02:25
Copy link
Collaborator

@eugene-manuilov eugene-manuilov left a comment

Choose a reason for hiding this comment

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

Nice work, @caseymorrisus! Left a few comments for you. Could you, please, address it?

assets/js/components/setup/setup-wrapper.js Outdated Show resolved Hide resolved
assets/js/components/setup/setup-wrapper.js Outdated Show resolved Hide resolved
assets/js/components/setup/setup-wrapper.js Outdated Show resolved Hide resolved
assets/js/components/setup/setup-wrapper.js Outdated Show resolved Hide resolved
Copy link
Collaborator

@eugene-manuilov eugene-manuilov left a comment

Choose a reason for hiding this comment

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

@caseymorrisus LGTM! Just left a final suggestion, let's update it and I'll approve this PR.

eugene-manuilov
eugene-manuilov previously approved these changes Oct 8, 2020
@eugene-manuilov
Copy link
Collaborator

@caseymorrisus I have approved this PR, but could you please resolve merge conflicts?

eugene-manuilov
eugene-manuilov previously approved these changes Oct 8, 2020
Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

The production code mostly LGTM, but this seems to break some Tag Manager stories.

*/
import Button from '../../../components/button';

export default function DefaultModuleSetup( { finishSetup, module = {} } ) {
Copy link
Member

Choose a reason for hiding this comment

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

I think we should use minimal props here like we usually do and only pass the moduleSlug which is sufficient to identify the module. Then this component can look up the module object to get module.name from the datastore.

Comment on lines 53 to 56
module: PropTypes.shape( {
name: PropTypes.string,
slug: PropTypes.string,
} ),
Copy link
Member

Choose a reason for hiding this comment

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

See above. Passing a slug is more straightforward here, I think it's a bit odd to expect an object here, especially since the shape provided here is not the full module object - it shouldn't depend too much on the implementation of the component, let's require the module slug, from there we can get anything else we could possibly need via the datastore.

@@ -221,6 +223,7 @@ const baseActions = {
* @param {number} [settings.order] Optional. Numeric indicator for module order. Default 10.
* @param {string} [settings.homepage] Optional. Module homepage URL. Default empty string.
* @param {WPElement} [settings.settingsComponent] React component to render the settings panel. Default is the DefaultModuleSettings component.
* @param {WPElement} [settings.setupComponent] React component to render the setuppanel. Default is the DefaultModuleSetup component.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* @param {WPElement} [settings.setupComponent] React component to render the setuppanel. Default is the DefaultModuleSetup component.
* @param {WPElement} [settings.setupComponent] React component to render the setup panel. Default is the DefaultModuleSetup component.

{
setupComponent: SetupMain,
},
);
Copy link
Member

Choose a reason for hiding this comment

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

Super-nitpick, but maybe we should put the registerModule call above the widget registrations, just because module registration is the more general step. Of course this doesn't technically change anything, but without module registration widget registration is mostly useless (most widgets only are active if their respective module is registered and active).

This also applies to the other similar files.

.addDecorator( ( storyFn ) => {
global._googlesitekitLegacyData.setup.moduleToSetup = 'adsense';
const registry = createTestRegistry();
registry.dispatch( CORE_MODULES ).receiveGetModules( [
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be worth switching this and similar calls to using the new provideModules utility function.

Comment on lines 51 to 57
registry.dispatch( CORE_MODULES ).receiveGetModules( [
{
slug: 'tagmanager',
active: true,
connected: true,
},
] );
Copy link
Member

Choose a reason for hiding this comment

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

See above.

@@ -21,37 +21,22 @@
*/
Copy link
Member

Choose a reason for hiding this comment

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

Something here seems to mess up several Tag Manager setup stories, e.g.:
Screenshot 2020-10-12 at 15 44 19

@@ -96,77 +68,75 @@ class SetupWrapper extends Component {
delay( function() {
global.location.replace( redirectURL );
}, 500, 'later' );
}, [] );
Copy link
Member

Choose a reason for hiding this comment

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

I think here we should pass moduleToSetup from above as callback dependency and then use it in the callback, instead of relying on the same global again, which may in theory cause inconsistent callbacks.

}
export default function SetupWrapper() {
const settingsPageURL = useSelect( ( select ) => select( CORE_SITE ).getAdminURL( 'googlesitekit-settings' ) );
const { moduleToSetup } = global._googlesitekitLegacyData.setup;
Copy link
Member

Choose a reason for hiding this comment

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

This was explicitly not required as part of the ACs, but maybe it would be worth moving this legacy dependency out of this component and require it as a prop instead (moduleSlug). This would for example simplify the Storybook configuration so that we no longer need to mess with the global there which is error-prone.

We could instead do the global._googlesitekitLegacyData.setup.moduleToSetup lookup in the components using SetupWrapper and pass the value as prop, so that at least this component is fully refactored (let's not worry about the other ones):

  • DashboardSplashApp
  • GoogleSitekitDashboard
  • GoogleSitekitModule

@caseymorrisus
Copy link
Contributor Author

@felixarntz Failed CI tests have been confirmed to pass (multiple times) locally. Please re-run tests when re-reviewing to verify.

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

@caseymorrisus Against the ACs, this is good to go. However, based on some changes in the approach we decided on for the related #1623, I suggested some changes here (see specific comments). @aaemnnosttv What do you think about my alternative approach suggested here?

@@ -230,6 +233,7 @@ const baseActions = {
order,
homepage,
settingsComponent = DefaultModuleSettings,
setupComponent = DefaultModuleSetup,
Copy link
Member

Choose a reason for hiding this comment

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

Revisiting this, we may want to diverge from the ACs here in that there should not be any default value for the setupComponent argument. Per #1623, this will be changed for the settingsComponent replacements as well. Providing a default here prevents us from checking whether the module has a setup component attached or not - which will come in handy in the future, e.g. when we need to determine whether we need to link to the module setup screen or the regular module page (linking to the setup screen when there is no setup component would not make sense). There is currently some hard-coded exception in place for PageSpeed Insights (which doesn't require a setup) for that very reason - which we can eliminate by checking whether the module has a setup component.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, I think that makes sense. A DefaultModuleSetup component should be capable of setting up the module, but setup is very module-specific so I don't think it's possible to have such a thing in our case as we can't really assume anything about how every module works to have a generic setup component.

setupComponent can default to null if not passed and is what I have in #1623 for settings components so far (almost ready for review, but you can see it here: https://github.com/google/site-kit-wp/pull/2202/files#diff-51079bbb133e20fa794c0e1fd5fd30b551dda818e0cfe0ba4162502670cf133a)

@@ -221,6 +223,7 @@ const baseActions = {
* @param {number} [settings.order] Optional. Numeric indicator for module order. Default 10.
* @param {string} [settings.homepage] Optional. Module homepage URL. Default empty string.
* @param {WPElement} [settings.settingsComponent] React component to render the settings panel. Default is the DefaultModuleSettings component.
* @param {WPElement} [settings.setupComponent] React component to render the setup panel. Default is the DefaultModuleSetup component.
Copy link
Member

Choose a reason for hiding this comment

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

Based on my above comment, this could then say "Default none.".

@@ -59,6 +60,7 @@ const moduleDefaults = {
order: 10,
icon: null,
settingsComponent: DefaultModuleSettings,
setupComponent: DefaultModuleSetup,
Copy link
Member

Choose a reason for hiding this comment

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

See above, the default should be undefined.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I chose to go with null for the settings components to indicate that it is intentionally empty as we do elsewhere rather than undefined which is more of an initial state or unresolved value. Perhaps we're not consistent with this, but both values should work for our needs. If you would prefer to use undefined instead, that's an easy change to make for me.

'googlesitekit-settings',
{}
);
const { setupComponent: SetupComponent } = module;
Copy link
Member

Choose a reason for hiding this comment

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

Based on my above comment, we could either remove the DefaultModuleSetup component entirely (it strictly isn't needed), or we could use it here internally to render it if SetupComponent is undefined. Since this screen would in the future never be linked to if there is no setupComponent, it may also be okay just rendering nothing in that case.

aaemnnosttv added a commit that referenced this pull request Oct 27, 2020
Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

Awesome work!

@felixarntz felixarntz merged commit 893f6c6 into develop Oct 29, 2020
@felixarntz felixarntz deleted the enhancement/2074-register-module-setup-components branch October 29, 2020 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants