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

Prioritize Override in Boolean Filter #45261

Merged
merged 10 commits into from Apr 1, 2022
Merged

Conversation

epeach
Copy link

@epeach epeach commented Mar 10, 2022

We got feedback that our override filter wasn't working. https://studio.code.org/s/dance?songfilter=on. This should turn the filter on for students regardless of their age or whether they are signed in.

The boolean logic we were using was filterOff = signedInOver13 || signedOutOver13AndNotFiltered. Even when we were filtering (signedOutOver13AndNoteFiltered = false), if a student was signed in and over 13 (signedInOver13 = true), we would still turn the filterOff (filterOff = true || false = true). So this might have never worked in this case, but because we are running into issues with signedInOver13 at the moment (#45233), this case is particularly relevant now.

To fix, I separated how we are tracking the override with it's own session storage token, rather than tagging it on the to the age token. Now, regardless of user_type or under13, if the override is on, we have the filter on. If the filter is off, we then go into the rest of the boolean logic that looks at user_type and under13.

PR Checklist:

  • Tests provide adequate coverage
  • Privacy and Security impacts have been assessed
  • Code is well-commented
  • New features are translatable or updates will not break translations
  • Relevant documentation has been added or updated
  • User impact is well-understood and desirable
  • Pull Request is labeled appropriately
  • Follow-up work items (including potential tech debt) are tracked and linked

@epeach epeach requested a review from a team March 10, 2022 22:35
@epeach epeach changed the base branch from staging to dance-party-filtering-update March 11, 2022 20:31
@epeach epeach requested a review from a team as a code owner March 11, 2022 20:31
@breville
Copy link
Member

breville commented Mar 16, 2022

First, I made a matrix to help understand what's fixed here and elsewhere:

                          override                 no override

signed in < 13            broken (3)               broken (2)
signed in 13+             broken (1)               works (no filter)

signed out < 13           works (filter)           works (filter)
signed out 13+            works (filter)           works (no filter)

(1) Will be fixed by this PR
(2) Will be fixed by https://github.com/code-dot-org/code-dot-org/pull/45233
(3) Interestingly will be fixed by either PR

Base automatically changed from dance-party-filtering-update to staging March 17, 2022 20:38
@epeach
Copy link
Author

epeach commented Mar 17, 2022

@breville - PTAL - thanks!

@@ -48,7 +49,8 @@ class AgeDialog extends Component {
// If the song filter override has been turned on, set session storage
// Dialog won't render
if (queryString.parse(window.location.search).songfilter === 'on') {
this.setManualFilter();
this.props.storage.setItem(SONG_FILTER_SESSION_KEY, true);
Copy link
Member

Choose a reason for hiding this comment

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

Do we actually want this choice to remain in place for the session? What if the user wants to turn the filter override off again? I thought that relying on the URL parameter for each page load could be more appropriate.

Copy link
Author

@epeach epeach Mar 18, 2022

Choose a reason for hiding this comment

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

I lean towards making it hard to turn the filter off. When the student goes through the "run -> success -> continue" path and is navigated to the next page through the success dialog, the url parameter is dropped. Storing the filter in the session cookie will ensure that if a teacher wants to enforce the filter in their classroom and directs students to "studio.code.org/s/dance/lessons/1/levels/1?songfilter=on" and ask them to play through the tutorial, the filter will remain on for tutorial. I believe the '?songfilter=off' part was cut from the original spec so that students wouldn't have an easy time of turning the filter off if they've been directed to turn it on.

Copy link
Member

Choose a reason for hiding this comment

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

I see. If we are changing the existing behavior it seems worth capturing that in the PR description. I'm a bit concerned about subsequent students on shared computers getting confused, but I guess we use session storage for the signed-out age selector so this is at least consistent.

Copy link
Author

@epeach epeach Mar 18, 2022

Choose a reason for hiding this comment

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

I don't believe the original intended behavior has changed in regards to whether the filter override lives in a session. Previously, in setManualFilter, we were storing the override in the AGE_DIALOG_SESSION_KEY. This is also where we were storing whether a signed out user was over/under 13. This PR splits that behavior into two session keys, so we can more accurately differentiate between signedIn with/out override and signedOut with/out override.

@breville
Copy link
Member

breville commented Mar 18, 2022

I found the code for filtering rather confusing and wonder if it might be worth a small tidy-up while here. The PR description inadvertently alludes to this complexity as it uses psuedo-variables such as signedOutOver13AndNotFiltered which are more descriptive than what the code actually contains.

I ended up having to make the table above to help think through each case.

Some ideas to simplify:

  • Rename setFilterStatus to something like getInitialFilterStatus. With its current name, it's not clear what its return value means.
  • Consider avoiding the use of negative variable names, specifically filterOff, which requires inverting thinking about positive cases.
  • Having a songFilterOn function and a filterOff variable is another example of having to repeatedly invert thinking.

@epeach
Copy link
Author

epeach commented Mar 18, 2022

@breville - PTAL - thanks! I updated some of the variables/function name to simplify logic and added extra comments. I think it reads better now, but let me know if you agree!

@epeach
Copy link
Author

epeach commented Mar 23, 2022

@breville - PTAL - thanks! Broke out that utils function and added a test, plus overall clean up.

apps/src/dance/songs.js Outdated Show resolved Hide resolved
@breville
Copy link
Member

It looks like the age filter UI test is failing for the last few commits.

@epeach
Copy link
Author

epeach commented Mar 24, 2022

@breville - PTAL - fixed the tests - thanks!

Comment on lines 100 to 104
// If user is signed out, query session key to determine age.
// Return false (no filter), if user is over 13.
if (userType === 'unknown') {
return !signedOutOver13();
}
Copy link
Member

Choose a reason for hiding this comment

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

Slightly confused by the comment & code layout here. Presumably userType === 'unknown' checks whether a user is signed out, and signedOutOver13() queries the session key? It could be worth shuffling a little to make these things more clear, e.g.

    // If user is signed out...
    if (userType === 'unknown') {
      // ...call signedOutOver13() to query session key to determine age.
      // Return false (no filter), if user is over 13.
      return !signedOutOver13();
    }

I think there's a second issue here: signedOutOver13() should probably be able to return true if the user is signed out and over 13, but it sounds like it isn't able to determine whether the user is signed out, so we have to wrap with this extra check first? It seems weird to split that logic across two places, and means the function isn't able to do everything you'd expect it could.

Copy link
Author

Choose a reason for hiding this comment

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

Interesting point on the second issue. After reflecting on it, I realized that the function name currently infers a lot, so I updated the name to more accurately represent what it does - not if the user has selected over13 in the age dialog - ageDialogSelectedOver13.

return !signedOutOver13();
}

// User is signed in (student or teacher) and the filter is off.
Copy link
Member

Choose a reason for hiding this comment

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

By "filter is off" do we mean that the "filter override is not turned on"?

}

// User is signed in (student or teacher) and the filter is off.
// Return true (filterOn) if the user is under 13. Teachers assumed over13.
Copy link
Member

Choose a reason for hiding this comment

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

super nit: I'd replace "filterOn" with something like "filter should be turned on" since a function doesn't need to know about specific variables outside of its scope.

@breville
Copy link
Member

Thanks for doing the extra work to build getFilteredSongKeys. The accompanying unit testing looks great.

@epeach
Copy link
Author

epeach commented Mar 31, 2022

@breville - PTAL - thanks!

Copy link
Member

@breville breville 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!

@epeach epeach merged commit 391fdb3 into staging Apr 1, 2022
@epeach epeach deleted the dance-party-filter-override branch April 1, 2022 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants