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

Color Schemes: Add Color Scheme Picker to Account Settings #17259

Merged
merged 8 commits into from
Sep 7, 2017

Conversation

frontdevde
Copy link
Contributor

@frontdevde frontdevde commented Aug 16, 2017

This PR is part of a series of PRs aiming to provide support for Color Schemes in Calypso.
This PR focuses on integrating the Color Scheme Picker (PR #17200) in the Account Settings.

ezgif com-video-to-gif

Notable additions in this PR:

  • This PR adds support for nested settings to UserSettings (/lib/user-settings).
  • The feature flag 'me/account/color-scheme-picker' is introduced.
  • The ColorSchemePicker component is added to the me/account/ page.

Considerations

The ColorSchemePicker by default connects to/via state/preferences/. I initially contemplated using the same approach for the integration on me/account/ but during development realized how deeply integrated with /lib/user-settings the whole page is (via form-base). In order to not having to duplicate all the functionality on that page, I then decided to add support for nested settings to /lib/user-settings instead. This way there's hardly any overhead involved in integrating the ColorSchemePicker on the Account Settings page.

How to test

Visit https://calypso.live/?branch=add/color-schemes/account-me-integration or test locally.
Navigate to the Accounts Settings page and scroll down to the Admin Color Scheme section.

Suggestions as to what to test

  • Is the color scheme selection being persisted when saved and dropped when not?
  • Do all combinations of different Account Settings changes work as expected?
  • Double check other parts of the app making use of (/lib/user-settings).

Note

This PR currently compares its changes to PR #17200 which in turn compares to PR #17157. This is so the changes can be easily identified. This PR will be pointed at master once PR #17200 and #17157 have been merged.

For a more detailed description of the feature, the chosen approach and its advantages feel free to check out my post on the subject: p4TIVU-75d-p2 (internal reference).

@frontdevde frontdevde self-assigned this Aug 16, 2017
@frontdevde frontdevde requested a review from ehg August 16, 2017 23:03
@matticbot matticbot added OSS Citizen [Size] L Large sized issue labels Aug 16, 2017
@frontdevde frontdevde added [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. and removed [Status] In Progress labels Aug 16, 2017
@frontdevde frontdevde requested a review from spen August 16, 2017 23:37
@frontdevde frontdevde added the [Status] Needs Design Review Add this when you'd like to get a review / feedback from the Design team on your PR label Aug 17, 2017
@frontdevde frontdevde added the [Feature] User & Account Settings (/me) Settings and tools for managing your WordPress.com user account. label Aug 18, 2017
@folletto
Copy link
Contributor

Design wise it's good.

In the future we'll have a separate section for this, but as a first PR this is good: 👍

@folletto folletto removed the [Status] Needs Design Review Add this when you'd like to get a review / feedback from the Design team on your PR label Aug 21, 2017
@Automattic Automattic deleted a comment from matticbot Aug 21, 2017
@frontdevde frontdevde force-pushed the add/color-schemes/color-scheme-picker branch from 7d5578b to 25c9550 Compare August 22, 2017 18:54
@spen
Copy link
Contributor

spen commented Aug 23, 2017

Adding the [Status] Blocked / Hold label until #17200 is merged to master :)

@@ -1,16 +1,9 @@
/**
* External dependencies
*/
import { assign, isEmpty, keys, merge, has, get, set, unset } from 'lodash';
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
Contributor Author

Choose a reason for hiding this comment

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

Before I comment on the other comments below:
Thanks for your review, highly appreciated! 💯

unset( settings, settingName );

const settingKeys = settingName.split( '.' );
if ( settingKeys.length > 1 ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think to using ! isEmpty( settingKeys ) here? I feel that would be in keeping with the rest of the checks in this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, ! isEmpty( settingKeys ) would be true though even if there is only one setting key. We only want to continue if there is more than one key e.g. ["calypso_settings", "colorScheme"].

Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh my bad! For some reason I was reading/treating this as settingKeys.length >= 1!

const parentKey = settingKeys.join( '.' );
//if parent is empty, call function again
if ( parentKey && isEmpty( get( settings, parentKey ) ) ) {
deleteUnsavedSetting( settings, parentKey, true );
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be because it's late, but I think I'm missing the need to recurse here - is this to cover strings that represent nested settings, similar to _.gets usage?
So something like the following would work?:

deleteUnsavedSetting( userSettings, 'preferences.colorTheme' )
console.log( userSettings.preferences.colorTheme );
// undefined

Or something else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the idea behind the update to user settings is to support nested settings like 'preferences.colorTheme'. The current way of deletion only deleted the key but resulted in an empty parent key in this.unsavedSettings. As hasUnsavedUserSettings only checks for isEmpty, it would return true despite no settings being unsaved. Therefore we have to ensure to remove potentially empty parent keys.

e.g. {calypso_preferences: { colorScheme: "dark" }
=> {calypso_preferences: { } }
=> { }

@@ -156,8 +173,8 @@ UserSettings.prototype.cancelPendingEmailChange = function( callback ) {
*/
UserSettings.prototype.getOriginalSetting = function( settingName ) {
var setting = null;
if ( this.settings && this.settings[ settingName ] ) {
setting = this.settings[ settingName ];
if ( this.settings && get( this.settings, settingName ) ) {
Copy link
Contributor

@spen spen Aug 23, 2017

Choose a reason for hiding this comment

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

This may be outside the scope of this PR but I believe theres an issue here (before & after the change).
I think we could quite easily fix that here though, if you don't mind?

Here's a quick demo showing the issue... basically any falsey value would be replaced with null:

https://runkit.com/spen/599cd633888c48001253cc1d

I think something like so should do the trick:

getOriginalSetting = settingName =>
  has( this.settings, settingName )
    ? get( this.settings, settingName )
    : null;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Commenting for continuity: As per our discussion in Slack, we'll address this one outside the scope of this PR in order to isolate any potential side effects.

Copy link
Contributor

Choose a reason for hiding this comment

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

Just a note on the code example I gave above - that can be squished down further:

getOriginalSetting = settingName => get( this.settings, settingName, null );

setting = ( 'undefined' !== typeof this.unsavedSettings[ settingName ] )
? this.unsavedSettings[ settingName ]
: this.settings[ settingName ];
if ( this.settings && 'undefined' !== typeof get( this.settings, settingName ) ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a suggestion here, FFTI as it's not necessarily in scope for this PR...

_.isUndefined could be useful here, but I think _.has would be even more useful.

If IIRC we could squish these checks down like so:

if ( this.settings && 'undefined' !== typeof get( this.settings, settingName ) ) {
// >>
if ( ! has( this.settings, settingName ) ) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that should work. 👍
Just without the !, as it's checking for not undefined:
if ( has( this.settings, settingName ) ) {

'user_login' !== settingName
) {
debug( 'Removing ' + settingName + ' from changed settings.' );
delete this.unsavedSettings[ settingName ];
deleteUnsavedSetting( this.unsavedSettings, settingName );
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a fan of the functional-izing here 🙂 👍

if ( settingName in this.unsavedSettings ) {
delete this.unsavedSettings[ settingName ];

if ( has( this.unsavedSettings, settingName ) ) {
Copy link
Contributor

@spen spen Aug 23, 2017

Choose a reason for hiding this comment

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

This check might also be a candidate for this.isSettingUnsaved.

: this.settings[ settingName ];
if ( this.settings && 'undefined' !== typeof get( this.settings, settingName ) ) {
setting =
'undefined' !== typeof get( this.unsavedSettings, settingName )
Copy link
Contributor

Choose a reason for hiding this comment

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

I could be wrong here, but we may be able to use this.isSettingUnsaved here - if so that might help with readability :)

@@ -529,6 +534,14 @@ const Account = React.createClass( {

{ this.communityTranslator() }

{ config.isEnabled( 'me/account/color-scheme-picker' ) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

I see that we're only enabling in development in this PR, so this is not a huge issue but to err on the side of caution what do you think to merging #17310 first and including the check in this PR? (See: #17310 (review))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Commenting for continuity: As per our discussion in Slack just now, we're going to leave the PR order as is to ensure we have a good test case for the feature detection in #17310. We're aiming to merge the PRs in quick succession.

@frontdevde frontdevde changed the base branch from add/color-schemes/color-scheme-picker to master August 30, 2017 17:32
@matticbot
Copy link
Contributor

@frontdevde This PR needs a rebase

@frontdevde frontdevde force-pushed the add/color-schemes/account-me-integration branch from 0608b5a to c2fa9e4 Compare August 30, 2017 17:53
@matticbot matticbot added [Size] M Medium sized issue and removed [Size] L Large sized issue labels Aug 30, 2017
@matticbot matticbot added [Size] L Large sized issue [Status] Needs Rebase and removed [Size] M Medium sized issue labels Aug 30, 2017
@matticbot
Copy link
Contributor

@frontdevde This PR needs a rebase

@frontdevde frontdevde force-pushed the add/color-schemes/account-me-integration branch from 3ec9837 to abcd2df Compare September 4, 2017 15:54
Copy link
Contributor

@spen spen left a comment

Choose a reason for hiding this comment

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

Looking great :D

this.updateUserSetting( 'calypso_preferences.colorScheme', colorScheme );
const settingName = 'calypso_preferences.colorScheme';

// set a fallback color scheme if no default value is provided by the API
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd be tempted to mention that this is a bit of a hack, allowing us to use this.props.userSettings.updateSetting without an existing value and mention the behaviour we see without forcing this default.
In the TODO, it may also be worth explicitly mentioning that the intention is to remove this line.
What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done 👍


// set a fallback color scheme if no default value is provided by the API
// TODO: ideally the default value should be provided on the API side
update( this.props.userSettings.settings, settingName, value => value || 'default' );
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems to do the trick! I'm seeing the button become active when making selections, then the option saved is persisted :)

@frontdevde frontdevde force-pushed the add/color-schemes/account-me-integration branch from abcd2df to 29c0814 Compare September 6, 2017 12:27
updateColorScheme( colorScheme ) {
const settingName = 'calypso_preferences.colorScheme';

// Set a fallback color scheme if no default value is provided by the API.
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 👍 👍 :)

@matticbot
Copy link
Contributor

@frontdevde This PR needs a rebase

@frontdevde frontdevde force-pushed the add/color-schemes/account-me-integration branch from 29c0814 to 05a43d9 Compare September 7, 2017 10:25
@spen spen merged commit 98e98d1 into master Sep 7, 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 Sep 7, 2017
@alisterscott alisterscott deleted the add/color-schemes/account-me-integration branch February 1, 2018 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] User & Account Settings (/me) Settings and tools for managing your WordPress.com user account. OSS Citizen [Size] L Large sized issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants