google / site-kit-wp

Site Kit is a one-stop solution for WordPress users to use everything Google has to offer to make them successful on the web.
https://sitekit.withgoogle.com
Apache License 2.0
1.25k stars 291 forks source link

Implement `googlesitekit_user_input_state` flag to detect and store whether user input is required #2042

Closed felixarntz closed 4 years ago

felixarntz commented 4 years ago

Depending on whether a user is connecting to Site Kit or whether a user is returning to Site Kit after having already used a previous version of the plugin, the way they should be exposed to the new user input screen should behave differently. This issue is about implementing the necessary logic to determine the user's state regarding user input.


Do not alter or remove anything below. The following sections will be managed by moderators only.

Acceptance criteria

Note that this won't do anything user-facing via the above implementation, which is on purpose because the final pieces can only be implemented once everything is ready to be launched in production. For example, setting the new user setting to "required" or "dismissed" will happen later.

Implementation Brief

Step 1

Step 2

In the Authentication class:

Step 3

In the core/user datastore (user-info.js file):

QA Brief

Changelog entry

eugene-manuilov commented 4 years ago

@felixarntz, IB is added. I know that you don't want to set the user input state to required yet, but I think it still makes sense to do it in the admin_init hook to prevent invoking user input settings endpoint on every page load. I have added it to IB.

felixarntz commented 4 years ago

@eugene-manuilov I think it's okay for the user input endpoint to be invoked because the results are cached. It would only fire a request once a week (or otherwise when the data expired). Whether the value is required or not shouldn't affect that at all, this check is only done for knowing whether the value should be set to completed or not (completed is not the opposite of required here). Potentially we could explore using another flag value like missing (both missing and required would mean that the settings are not completed, with different nuance), that way we would only need to check the user input settings data if the value is empty. What do you think?

Regarding the IB specifically:

If yes, sets user_input_state setting to completed, otherwise required.

See above, this is not correct - only completed should be set, otherwise nothing, or if we introduce missing, then missing should be set. required is set once somebody with empty or missing starts the setup flow (should not happen here though).

VALUE_DISMISSED with dismissed value.

This should not be a possible value, dismissal is purely handled on the client. We might want to replace this with VALUE_MISSING though, see above, to only run the admin_init check for the one case where the setting is not initialized.

Step 4

  • Update the GoogleSitekitDashboard component in the assets/js/googlesitekit-dashboard.js file to retrieve userInputState value using the useSelect hook.
  • Check if userInputState equals to required and redirect the user to the googlesitekit-user-input screen using getAdminURL selector from the core/site datastore.

This redirect should happen server-side (e.g. in Screens class), we shouldn't need to first start loading JS, which might cause some flashing of the dashboard and would also easily allow avoiding the redirect via DevTools etc.

eugene-manuilov commented 4 years ago

@felixarntz I have updated IB to address your feedback. As to the missing flag, I think we don't need it because it is the same thing as an empty value in the user input state setting.

This redirect should happen server-side (e.g. in Screens class), we shouldn't need to first start loading JS, which might cause some flashing of the dashboard and would also easily allow avoiding the redirect via DevTools etc.

Ok, updated IB to make the redirect in the Authentication class since it has everything required to do it.

felixarntz commented 4 years ago

@eugene-manuilov

As to the missing flag, I think we don't need it because it is the same thing as an empty value in the user input state setting.

Right, it's kind of the same, the reason I brought it up for consideration is that it would allow us to not check user input settings if missing was set. Basically:

We don't need to add it, but may be worth it.

eugene-manuilov commented 4 years ago

@felixarntz I think it is worth adding missing value because it will remove a need to send unnecessary requests to the proxy server. IB is updated.

felixarntz commented 4 years ago

@eugene-manuilov

Checks the current value of the user input state setting and returns if it equals to completed or missing;

It should return if it's any non-empty value (just for the uninitialized state it should get user input settings to check it)

Sends a GET request to the REST_Routes::REST_ROOT . '/core/user/data/user-input-settings' endpoint

Let's not send a REST request when we're already in PHP (even though we could do that internally). We should be able to use the User_Input_Settings class directly.

Add another admin_init hook to redirect the user to the googlesitekit-user-input page if the current page is googlesitekit-dashboard and the user input state setting equals to required.

Maybe we should do this in the initialization callback for the googlesitekit-dashboard screen, within Screens class?

eugene-manuilov commented 4 years ago

It should return if it's any non-empty value (just for the uninitialized state it should get user input settings to check it)

Yep, makes sense, updated.

Let's not send a REST request when we're already in PHP (even though we could do that internally). We should be able to use the User_Input_Settings class directly.

Maybe we should do this in the initialization callback for the googlesitekit-dashboard screen, within Screens class?

I would avoid doing it because it requires re-instantiating User_Input_Settings and User_Input_State classes with their dependencies in Screens and Authentication classes. It'll make the codebase slightly more complicated and a bit more coupled which is worse than calling the rest_do_request function and adding another admin_init hook. If we had a dependency injection, we would easily do what you suggest because we could get User_Input_Settings and User_Input_State objects from a DI container without creating duplicates. But for now, I think it worth doing it as it states in the IB now.

Let me know what you think about it. If you still want to move it, I can update the IB.

felixarntz commented 4 years ago

@eugene-manuilov I think it would make sense to instantiate User_Input_Settings in the constructor of Authentication and assign it to a class property, similar to how most other general authentication-related classes are instantiated there. I'd prefer to avoid making an internal REST request, and with this approach, which is already established, we don't have to re-instantiate the classes.

Let's then keep the redirection in an admin_init hook within Authentication like you suggested, relying on $this->user_input_settings as well.

eugene-manuilov commented 4 years ago

@felixarntz ok, updated.

felixarntz commented 4 years ago

IB ✅

aaemnnosttv commented 4 years ago

QA

I tested this a fair bit and found that everything works as expected. QA ✅

Regarding the constraint on possible values for googlesitekit_user_input_state, this seems to be better implemented using a sanitize callback (get_sanitize_callback in User_Input_State) rather than only in User_Input_State::set. That way the logic applies more globally, e.g. setting via REST or CLI as well.

This follows the IB and does work as expected so I can't say it's a QA failure but a suggested enhancement that would be quick to do. Thoughts @felixarntz ?

felixarntz commented 4 years ago

@aaemnnosttv Good catch! Let's open a follow-up issue for that.

aaemnnosttv commented 4 years ago

@felixarntz I opened https://github.com/google/site-kit-wp/issues/2323 as a follow-up.

Moving this one forward to approval 👍