-
Notifications
You must be signed in to change notification settings - Fork 274
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
Enhancement/2074 allow registering module setup components #2129
Conversation
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. |
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.
Nice work, @caseymorrisus! Left a few comments for you. Could you, please, address it?
assets/js/googlesitekit/modules/components/DefaultModuleSetup.js
Outdated
Show resolved
Hide resolved
assets/js/googlesitekit/modules/components/DefaultModuleSetup.js
Outdated
Show resolved
Hide resolved
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.
@caseymorrisus LGTM! Just left a final suggestion, let's update it and I'll approve this PR.
assets/js/googlesitekit/modules/components/DefaultModuleSetup.js
Outdated
Show resolved
Hide resolved
@caseymorrisus I have approved this PR, but could you please resolve merge conflicts? |
…unctional component, and add registerModule action.
08e6898
to
6657420
Compare
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.
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 = {} } ) { |
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 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.
module: PropTypes.shape( { | ||
name: PropTypes.string, | ||
slug: PropTypes.string, | ||
} ), |
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.
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. |
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.
* @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. |
assets/js/modules/adsense/index.js
Outdated
{ | ||
setupComponent: SetupMain, | ||
}, | ||
); |
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.
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( [ |
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 it would be worth switching this and similar calls to using the new provideModules
utility function.
registry.dispatch( CORE_MODULES ).receiveGetModules( [ | ||
{ | ||
slug: 'tagmanager', | ||
active: true, | ||
connected: true, | ||
}, | ||
] ); |
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.
See above.
@@ -21,37 +21,22 @@ | |||
*/ |
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.
@@ -96,77 +68,75 @@ class SetupWrapper extends Component { | |||
delay( function() { | |||
global.location.replace( redirectURL ); | |||
}, 500, 'later' ); | |||
}, [] ); |
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 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; |
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 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
@felixarntz Failed CI tests have been confirmed to pass (multiple times) locally. Please re-run tests when re-reviewing to verify. |
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.
@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, |
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.
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.
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 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. |
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.
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, |
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.
See above, the default should be undefined
.
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 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; |
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.
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.
…r if setup component does not exist.
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.
Awesome work!
Summary
Addresses issue #2074
Relevant technical choices
DefaultModuleSetup
componentregisterModule
action withsetupComponent
argument withDefaultModuleSetup
as the default valueSetupWrapper
to be a functional component and grab module data from registry viagetModule
registerModule
rather than using a filter viagooglesitekit.ModuleSetup-${ slug }
Checklist