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

close #874 - implement selection of previous iterations for reviewer and user #923

Merged
merged 13 commits into from
Jul 4, 2021

Conversation

Ulisseus
Copy link
Collaborator

@Ulisseus Ulisseus commented Jun 30, 2021

This PR is very big, but unfortunately I cannot break it down into smaller pieces, everything is tightly coupled together. I could try to separate changes for reviewer and student pages but it would lead to weird temporary components and helpers which would be overwritten by the very next pr. The initial pr would be about the same size minus a few files.

Main changes are in ReviewCard and ChallengeMaterial components. I'd suggest starting review with ReviewCard, it's shorter and a bit easier to read.

ReviewCard

Currently we're using GetSubmissions query to fetch all open submission for the specified lesson. This PR adds additional query GetPreviousSubmissions which is triggered for every ReviewCard component once it mounts. It's non-blocking data fetching, so render speed will be exactly the same as before.

Is it possible to fetch everything in one query? I don't know, I guess some sql wizard could have done it, but Prisma doesn't support subqueries yet, and the raw sql would be really big and clunky to maintain.

There are two new states - index and submission. Submission is the current selected submission and index is its index in getPreviousSubmissionQuery data.

The initial component got too big, so I split it in two. Review buttons are now in their own ReviewButtons component, their functionality is the same.

ChallengeMaterial

ChallengeQuestionCard component also got too big. Diff rendering is now done in a separate component - ChallengeQuestionCardDisplay.

Again, there are two new states - index and submission. But unlike ReviewCard there are two useEffects too. One is for updating data after receiving getPreviousSubmissions query and changing current index just like in ReviewCard. Another one is for resetting index when user clicks on different challenge.

updateCache

Both components use the same updateCache helper function which updates getPreviousQuery client side.

For people who are not familiar with updating client cache in apollo. Only server side is updated when you use a mutation, so you need to manually override cache in order to reflect current state of component. Once you do this all updated queries-hooks are triggered which results in rerendering. It's a data loop of sorts.

DiffView

This component had a lot of different props but they all were parts of submissions type. So istead of adding another one I simply passed the whole submission. GeneralStatus is total status of submission (for example, you could have five iterations from getPreviousSubmissions query - 'needMoreWork', 'overwritten', 'overwritten', 'needMoreWork', 'Open') with generalStatus 'Open'.

CommentBox

Again, the same generalStatus. Also, I choose to show comments even on rejected submissions, hiding them makes no sense when you can select previous submissions. Adding comments is disabled when generalStatus isn't 'Open' though.

Test file changes

I added new dummy data file - getPreviousSubmissionsData. We should unify our test data someday, currently most tests use their own data. It makes test files harder to read but more importantly if you update any grapql type you need to update every test mock (grapqh enforces types even in tests).


Vercel (I created test submission under js0, do not comment on students previous iterations yet, users won't be able to see your messages).

@vercel
Copy link

vercel bot commented Jun 30, 2021

@Ulisseus is attempting to deploy a commit to a Personal Account owned by @garageScript on Vercel.

@garageScript first needs to authorize it.

@codecov
Copy link

codecov bot commented Jun 30, 2021

Codecov Report

Merging #923 (4af51cc) into master (17e6818) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master      #923   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          112       112           
  Lines         1921      1957   +36     
  Branches       475       486   +11     
=========================================
+ Hits          1921      1957   +36     
Impacted Files Coverage Δ
components/SelectIteration.tsx 100.00% <ø> (ø)
graphql/queryResolvers/getPreviousSubmissions.ts 100.00% <ø> (ø)
helpers/controllers/userInfoController.ts 100.00% <ø> (ø)
components/ChallengeMaterial.tsx 100.00% <100.00%> (ø)
components/CommentBox.tsx 100.00% <100.00%> (ø)
components/DiffView.tsx 100.00% <100.00%> (ø)
components/ReviewCard.tsx 100.00% <100.00%> (ø)
helpers/updateCache.ts 100.00% <100.00%> (ø)

@vercel
Copy link

vercel bot commented Jun 30, 2021

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/c0d3/c0d3-app/KLp3ZFB6rq4HTFUQDMu6UzvDz93Q
✅ Preview: https://c0d3-app-git-fork-ulisseus-iterations-review-c0d3.vercel.app

useEffect(() => {
if (data?.getPreviousSubmissions) {
setPreviousSubmissions(data)
/*istanbul ignore else*/
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 spent quite a lot of time trying to trigger this else case but to no avail. I couldn't get the final rerender from updating the cache in tests no matter what.

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've managed to finally trigger that branch by hardcoding comment for every cache update. I guess it's better than completely ignoring it.

const comments =
currentChallenge.submission &&
currentChallenge.submission.comments?.filter(comment => !comment.line)
submission && submission.comments?.filter(comment => !comment.line)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you remove the submission && .... and just do submission?.comments?.filter(comment => !comment.line)

Copy link
Collaborator

@anthonykhoa anthonykhoa Jun 30, 2021

Choose a reason for hiding this comment

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

Since we are using lodash, I think it is better to use _.get lodash function to maintain codebase consistency. With lodash, I don't think this repo needs to use the ?. operator.

_.get(submission, 'comments', []).filter(...)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Tom is right, looking at this part I am not sure why I needed submissions&& check in the first place.

Chaining ? feels more natural than using lodash in this case. If anything we should start replacing _.get with ? operators everywhere.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed on using the coalescing chain. It is more natural and works better with typescript. Lodash uses a string for the property which may cause bugs if the name changes for some reason.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ya I would vote moving to the coalescing operator when possible. A quick global search on the project for _.get( returns 40 hits in 13 files, seems like we should be able to refactor it out of the codebase at some point in the future.
* This could be a very jr. opinion, as I haven't seen how bad projects can get when the consistency slowly gets destroyed with promises of future refactoring.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed on sprint Honeydew to use and replace _.get with the coalescing chain operator ?..

@Ulisseus
Copy link
Collaborator Author

There is something off with rejection comment on vercel preview, the last open submission should not have rejection message. I'll check it tomorrow, this is not the intended behavior.

@ggwadera
Copy link
Collaborator

ggwadera commented Jun 30, 2021

As a small suggestion, please add a screenshot of the new or changed component when you're working on front-end code. It's easier to grasp what the PR is about this way. I know that there is the storybook preview but it's easier if you have a little screenshot on your description.

That said, I think the current styling has way too much whitespace, and that weird box around it.

image

Maybe the submissions selector could go on the top right, after the challenge name, and make it a little smaller and the boxes more close together. Also that Iteration 3 of 4 text is kinda redundant since it's the same information as the boxes display.

By the way, the review comment editor is still shown for past iterations. I think it could be hidden to avoid any confusion that could happen, like someone submitting a review thinking the submission is wrong but the newest one is correct.

@Ulisseus
Copy link
Collaborator Author

please add a screenshot of the new or changed component when you're working on front-end code

Maybe I should have added general layout with this component. But storybook enforces types, so it's rather cumbersome creating all these dummy files according to proper type definitions.

Anyways, selection counter is now in the top right corner. And accept/reject buttons are hidden for previous submissions (check updated vercel).
counter

username!
)

const { data, loading, error } = useGetPreviousSubmissionsQuery({
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not reduce this query to only get the past submissions ids and then fetch them on demand by its id? Querying them all here with the diff will increase the loading time when opening the review page (meaning the full screen loading spinner).

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 am not sure how it should work. GetPreviousSubmisisons query doesn't affect fullscreen loading spinner at all.

Current fetching order is:

  • getApp query (it should be in client's cache, and if this is not the case user is being redirected)
  • getSubmission query fetches all open submissions for this lesson (this is what actually hidden behind fullscreen loading spinner)
  • Review page is rendered. getPreviousSubmissions query starts, select iteration in the top right corner is showing "Loading submissions...".
  • getPreviousSubmissions returns and submission selection is fully rendered. So it doesn't affect loading spinner duration at all, it only increases time to final render but most users probably won't mind it (nobody notices a small component in the top right corner).

Alternatives:

  • Fetch everything in one query. First, I don't know how to do it (it's not possible in prisma and raw sql would be really big). Second, and more important this would actually increase loading spinner duration while reducing time to final render. This tradeoff would lead to bad UX in my opinion, why wait for full data when you can render it bit by bit and making page look more responsive?

  • Use lazy loading. This again would be a worse UX. When you click on iteration you need to wait for query to return. Why not fetch it on first render while user is focused on reading initial diff?

Come to think about it, we need to get rid of fullscreen spinners someday. Nothing here prevents rendering of NavBar, Footer and Lesson components. Maybe even add a template loading submission just like youtube does it with gray rectangles.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah you're right, my mistake. We'll have to see how it will work out with big files like on JS6, the submission selector could take a longer time to load since it will have to fetch the entire submissions.

Come to think about it, we need to get rid of fullscreen spinners someday. Nothing here prevents rendering of NavBar, Footer and Lesson components. Maybe even add a template loading submission just like youtube does it with gray rectangles.

Yes having a skeleton placeholder would be ideal.

@ggwadera
Copy link
Collaborator

ggwadera commented Jul 3, 2021

Accepted submissions without comment are not showing who was the reviewer.

image

Should look like this one but without the approval comment text.

image

@Ulisseus
Copy link
Collaborator Author

Ulisseus commented Jul 3, 2021

Accepted submissions without comment are not showing who was the reviewer.

It should work correctly even without a comment. Did you check the old preview? Oh, I forgot to update vercel link in the first message.

review

I need to work more on these review cards though. Maybe add another one for resubmission. And refactor them into separate component to use in challenge page.

But this PR is too big already, so I'd rather make another one for these changes.

@ggwadera ggwadera merged commit 5f5988d into garageScript:master Jul 4, 2021
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.

5 participants