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

Add DOJO exercise filtering checkbox #2383

Merged
merged 9 commits into from
Oct 1, 2022
Merged

Add DOJO exercise filtering checkbox #2383

merged 9 commits into from
Oct 1, 2022

Conversation

bryanjenningz
Copy link
Collaborator

Changes:

  • Add DOJO exercise filter checkbox which shows which exercise previews get displayed and which exercises you will solve when you press the SOLVE EXERCISES button
  • Add INCORRECT state to ExercisePreview component (so now there are 3 states: NOT ANSWERED, INCORRECT, ANSWERED)
  • Make it so if you submit an answer with an empty string in the input box, it will make it so the exercise is NOT ANSWERED (this makes it easier to test exercises because you can set ANSWERED or INCORRECT exercises to NOT ANSWERED now)
  • Move React state down to the Exercise component
  • Only show the SOLVE EXERCISES button if there is at least 1 exercise

How to test:

  • Create a DOJO module at /admin/lessons/js0/modules
  • Create DOJO exercises at /curriculum/js0/mentor
  • Go to /exercises/js0
  • Answer exercises correctly, incorrectly, and leave them empty when submitting, then go back and see how the previews look
  • Toggle the exercise filtering checkbox to make sure it works correctly

Desktop unchecked:
desktop-unchecked

Desktop checked:
desktop-checked

Mobile unchecked:
mobile-unchecked

Mobile checked:
mobile-checked

This pull request is related to #2253 and #2251

@vercel
Copy link

vercel bot commented Oct 1, 2022

@bryanjenningz is attempting to deploy a commit to the c0d3-prod Team on Vercel.

A member of the Team first needs to authorize it.

@vercel
Copy link

vercel bot commented Oct 1, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
c0d3-app ✅ Ready (Inspect) Visit Preview Oct 1, 2022 at 11:40PM (UTC)

@codecov
Copy link

codecov bot commented Oct 1, 2022

Codecov Report

Merging #2383 (4159728) into master (a854ae2) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master     #2383   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          184       184           
  Lines         3239      3270   +31     
  Branches       856       861    +5     
=========================================
+ Hits          3239      3270   +31     
Impacted Files Coverage Δ
...onents/ExercisePreviewCard/ExercisePreviewCard.tsx 100.00% <ø> (ø)
pages/exercises/[lessonSlug].tsx 100.00% <100.00%> (ø)

<Exercise
key={exerciseIndex}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I removed key here because we want the Exercise component to not rerender since the Exercise component now holds more state which we don't want to reset by rerendering.

Another way I could have implemented this would be to keep userAnswers and localUserAnswers at the same level here and then only pass down localUserAnswers to the Exercise component.

Both ways work, but I chose to keep localUserAnswers at the Exercise component level.

submitUserAnswer={(userAnswer: string) => {
setUserAnswers({ ...userAnswers, [exercise.id]: userAnswer })
exercises={currentExercises}
userAnswers={userAnswers}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The userAnswers prop here only gets used to initialize the localUserAnswers state in the Exercise component. Maybe a better name for this prop would be initUserAnswers or initLocalUserAnswers.

onExit={localUserAnswers => {
setUserAnswers({ ...userAnswers, ...localUserAnswers })
setSolvingExercise(false)
}}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

onExit gets called when we exit the Exercise component and go back to the ExerciseList view mode. The userAnswers gets updated only after we exit the Exercise component because if we don't want userAnswers changing which would change currentExercises which could cause the exercise that gets shown in the Exercise component to change in a way we don't want.

addExerciseSubmission({
variables: { exerciseId: exercise.id, userAnswer }
variables: { exerciseId, userAnswer }
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We no longer update the userAnswers locally after each submit. Instead, we update the server exercise submissions and we update the localUserAnswers because we don't want updating userAnswers to change the currentExercises which would cause a rerender in a buggy way when the exercise filtering checkbox is checked (e.g. if we only show incomplete exercises then we complete an exercise, then we would increment the exercise index and the exercises array would be shorter by 1 after that exercise got complete, so to avoid this we don't update userAnswers until after the user exits the Exercise component).


return (
<div className={`mx-auto ${styles.exercise__container}`}>
<button
className="btn ps-0 d-flex align-items-center"
onClick={() => setExerciseIndex(-1)}
onClick={() => onExit(localUserAnswers)}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We pass all the localUserAnswers so that the parent component can update userAnswers to reflect the current state.

onClick={() => {
setExerciseIndex(i => i - 1)
setAnswerShown(false)
setMessage(Message.EMPTY)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The reason why we now have to set the message to EMPTY and set the answer to be not shown is because we are no longer completely rerendering the Exercise component (it never gets completely rerendered now because we removed key prop and because we don't update any parent state until after we exit the Exercise component).

SOLVE EXERCISES
</NewButton>
</div>
)}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The SOLVE EXERCISES button only shows if there are exercises left. So if the user completes all the exercises and then checks the exercise filtering checkbox, there will be no exercises left, so this button is not shown.

Maybe we can also add a message in the empty exercise list body like "Congratulations! You finished all the exercises!" and then maybe we can add a button that says "Go to the next lesson" or something similar.

Copy link
Member

@flacial flacial left a comment

Choose a reason for hiding this comment

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

Looks good!

@bryanjenningz bryanjenningz merged commit 14e6751 into garageScript:master Oct 1, 2022
@bryanjenningz bryanjenningz deleted the add-dojo-exercise-filtering branch October 1, 2022 23:43
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.

2 participants