giseldo/neodataset huggingface dataset:
App graceful shutdown

Add a graceful shutdown handler to `app.ts` or `main.ts` following [this pattern](https://hackernoon.com/graceful-shutdown-in-nodejs-2f8f59d1c357). Include a `setTimeout(5 seconds)` before disconnecting from mongo/closing the process so events can finish.

## Tasks
- [x] Code review
- [x] Staging smoke tests
- [x] Merge to main
- [x] Deploy to prod

## Smoke tests
- [x] Student/volunteer can login
- [x] Student/volunteer can make/join session
- [x] Student/volunteer can use whiteboard and chat in session
- [x] Events finish running before process quits
  - connect via telepresence
  - make fake events that set timeouts and log distinct messages
  - log before entering graceful shutdown waiting period and again after right before shutdown
  - end a session and quickly close the server manually
  - ensure event logs are done before shutdown message

Story points: 1.0
Remove Merkury

Remove the Merkury package and replace it's use with Node event emitter

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Events (end session) still work

Story points: 1.0
Create reusable toast component

Create a re-usable toast component with full testing with [storybook](https://gitlab.com/upchieve/subway/-/wikis/Writing-components-with-Storybook).

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Approval from grace
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session

Story points: 2.0
Implement local storage key and browser toast

If a user visits the site from safari desktop check their local storage for a key representing whether or not we've shown them a toast recommending them to use chrome/firefox. If the key is not set then show them the toast. This should work from ANYWHERE in the app (not logged in, sign up flow, dashboard, etc)

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Toast appears only on safari desktop
- [ ] Toast does not appear after being seen once
- [ ] Toast appears anywhere in app
  - dashboard
  - session
  - sign up
  - login page
  - profile

Story points: 2.0
Update unleash-client and move frontend to unleash-proxy-client

Update unleash-client npm package to latest (3.10.1) and install unleash-proxy-client (1.5.2). Update frontend code to utilize unleash-proxy-client instead of unleash-client (basically just initializing the client). Find the proxy address in the pulumi code.

## Tasks
- [x] Code review
- [x] Staging smoke tests
- [x] Merge to main
- [x] Deploy to prod
- [x] Make almanac/wiki page for feature flagging

## Smoke tests
- [x] Student/volunteer can login
- [x] Student/volunteer can make/join session
- [x] Student/volunteer can use whiteboard and chat in session
- [x] Verify the existing feature flags are still working (front and back)

Story points: 1.0
Createjob to send gates invite email

Write email job that can be scheduled for 2pm eastern the following day that sends the gates invite email given a day and student. Reach out the programs for the sendgrid template id

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Email is sent the next day at 2pm eastern

Story points: 2.0
Refactor reportSession to have side effects be part of the metric trigger actions

Refactor `SessionService.processReportSessionMetric` to use the metric processor pattern from `USMService/index` by having reportSession emit `session-reported`, registering a metrics preparation step as listener on `session-reported`, emitting `reported-processors-ready`, registering the opName factory functions on `reported-processors-ready`.

## Tasks
- [x] Code review
- [x] Staging smoke tests
- [x] Merge to main
- [x] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [x] Student/volunteer can make/join session
- [x] Student/volunteer can use whiteboard and chat in session
- [x] Reported sessions have their metrics tick up
  - check if works when session is reported AFTER it ends

Story points: 2.0
Refactor EndSession to add past sessionto users instead of offloading to event

Waiting until we compute session metrics to add the past-session makes it difficult to rely on the `session-ended` event for a reliable view into the session/users. If we think of adding the past session as an atomic operation that must happen when a session ends then it makes sense to just do it sequentially not as a separate, asynchronous event.

Be sure to update any `past-session-added` listeners to listen to new parent events with the correct payload. Update the [event graph](https://lucid.app/lucidchart/627f889e-6edc-49a4-857a-e8a5db4daf95/edit?shared=true&page=0_0#) and push to j-max repo.

## Tasks
- [ ] Code review
- [x] Staging smoke tests
- [ ] Merge to main
- [ ] Update event graph
- [ ] Deploy to prod

## Smoke tests
- [x] Student/volunteer can login
- [x] Student/volunteer can make/join session
- [x] Student/volunteer can use whiteboard and chat in session
- [x] Past session gets added correctly
- [x] Past session side effects are completed correctly

Story points: 2.0
Add Gates modal to student dashboard

Re-use the pattern from student dashboard first session congrats modal for deciding how to show the modal/compose the components in the view. Coordinate with Grace to confirm current modal design is fine. Copy is in requirements doc. Will need a network call to check/update state of `hasSeenGatesModal` product flag endpoint.

Put this modal behind a feature flag for `gates-study`

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Pop up modal shows when appropriate

Story points: 2.0
Endpoint to update hasSeenGatesModal product flag

Implement in a new `ProductFlagsRouter` with post endpoint `api/v2/flags/gates` that reads the user id from `req.user` (requires authentication)

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Can manually hit endpoint with authenticated cookie

Story points: 1.0
update end session logic to set GatesQualified on product flag object

Add an event listener to `session-ended` that checks if the student qualifies for the gates survey and sets that flag on their ProductFlag object

Implement in a new `GatesStudyService` following the [architecture ](https://gitlab.com/upchieve/subway/-/wikis/Backend-Architecture)

Create a feature flag for the gates study

Follow the gates study scenarios written here: https://gitlab.com/upchieve/whoop-whoop/-/blob/main/tests/gates-study/qualification.feature

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] gates qualified function properly run when session-ended

Story points: 1.0
Create UserProductFlags repo and backfill

Model should be of shape as follows. Also include getter/create functions to be used by app/backfill script. Backfill objects to all users; can default fields to false.
```
{
  gatesQualified: Boolean,
}
```

## Tasks
- [ ] Code review
- [ ] Run backfill script against staging
- [ ] Merge to main
- [ ] Deploy to prod
- [ ] Run backfill script against prod

Story points: 2.0
Frontend: add current grade form to open student sign up view

Follow wireframe (#884 ) and include grade in registration payload. Options for grade are 9-12 and other

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Sign up an open student with grade

Story points: 1.0
Update registerOpenStudent route to require a grade parameter

Save the grade as part of the new student object. Only do this for the open student sign up. Validate is 9-12 or other

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [x] Student/volunteer can login
- [x] Student/volunteer can make/join session
- [x] Student/volunteer can use whiteboard and chat in session
- [x] Manually hit the endpoint with a grade set

Story points: 1.0
backend: eligibility/school/partner endpoint  to update partner status

Follow pattern of school/approval to update this boolean field. Also update swagger doc

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Can hit endpoint manually to change partner status of school (postman replace cookie with admin account)

Story points: 1.0
Frontend: toggle switch for school.isPartner to AdminSchoolDetail

Will need to make network call when toggling switch to new endpoint (#875). Reuse pattern from the approved status toggler

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Toggle makes network call

Story points: 1.0
ReportService changes - Usage and Session Report

Bug in the usage report:

Students who do not have an `approvedHighschool` do not show up on the usage report. The [$unwind stage here](https://gitlab.com/upchieve/subway/-/blob/85a44e19401ee90df1cdeb78c873523c791d3b76/server/services/ReportService.ts#L493) removes the document if the provided path, `highschool`, in our case, is null, missing, or an empty array. 

Possible steps for a solution:
1. set `preserveNullAndEmptyArrays` to `true` in the `$unwind` stage
2. remove the subsequent `match` stage so that we can match documents that do not have a high school 
3. In the projection stage, add the high school name using a `$cond` see https://docs.mongodb.com/manual/reference/operator/aggregation/cond/

-----

There are also additional changes that need to be made to the usage and session report that mainly revolve around inconsistency with date formats. Since we're now running some of these reports locally, we need to make sure that we are consistently pulling the correct data for these reports

TODO:
- Make necessary changes to the reports so the data is pulled at a consistent date range regardless of local machine timezone
- This [snippet of code](https://gitlab.com/upchieve/subway/-/blob/85a44e19401ee90df1cdeb78c873523c791d3b76/server/services/ReportService.ts#L340) adds a day to `sessionRangeTo` and similarly, does it to `joinedBefore`. The behavior of the date ranges should be startDate - endDate (not inclusive). This includes making any necessary updates to the date values that are sent from the client to ensure that the reports are generating correctly with the proper date values


## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session

Story points: 1.0
Change undefined hours tutored to show 0 instead of --

![image](/uploads/7d3b5eea61baa678ad191d110b2b8130/image.png) that's a nono

## Tasks
- [x] Code review
- [x] Staging smoke tests
- [x] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [x] Student/volunteer can login
- [x] Student/volunteer can make/join session
- [x] Student/volunteer can use whiteboard and chat in session
- [x] Volunteer dashboard shows 0 instead of --

Story points: 0.0
Bug: the banner for not making a session for 5 more minutes is broken

The object interface for this banner was changed when we made the banned student banner. Need to fix the interface so that this shows up again.

## Tasks
- [x] Code review
- [x] Staging smoke tests
- [x] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [x] Student/volunteer can login
- [x] Student/volunteer can make/join session
- [x] Student/volunteer can use whiteboard and chat in session
- [x] All banners appear at correct time

Story points: 1.0
Bug: notify tutors resend doesn’t work if there’s less than 15 notifications

If we are resending notifications because 6 minutes has passed, but we haven’t notified 15 people, then we are trying to look up an undefined notification and it fails. We need to reference the number of unique volunteers we have notified rather than the hardcoded value of 15.

## Tasks
- [x] Code review
- [x] Staging smoke tests
- [x] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [x] Student/volunteer can login
- [x] Student/volunteer can make/join session
- [x] Student/volunteer can use whiteboard and chat in session

Story points: 1.0
Student referral signup is broken

When a referred student enters their information on /sign-up/student, the Continue button does nothing. We have no new referred signups after April 8th, 2021, so a commit that got deployed around then is probably the culprit.

## Tasks
- [x] Code review
- [x] Staging smoke tests
- [x] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [x] Student/volunteer can login
- [x] Student/volunteer can make/join session
- [x] Student/volunteer can use whiteboard and chat in session
- [x] Student referral sign up works

Story points: 2.0
Fix backend tests so they complete in CI

## Goals
1. Fix the memory leak so the full test suite actually finishes
  - try to remove the force exit and instead detect open handles
  - make sure individual test suites close themselves
2. Parallelize the tests so the memory usage is spread out (and they run faster)
  - make sure tests don't READ or WRITE anything in the db besides what they instantiated

If the issue title can be accomplished with just #1 then we're good otherwise (or if you have more time) try 2

## Tasks
- [ ] Code review
- [ ] Merge to main

## Smoke test
- [ ] CI test runners complete and pass

Story points: 5.0
Determine which missing zwibbler handlers are needed

The [zwibbler protocol](https://docs.google.com/document/d/1X3_fzFqPUzTbPqF2GrYlSveWuv_L-xX7Cc69j13i6PY/edit) specifies many different message types that we have no implemented and ignore. We could have even implemented handlers incorrectly and need to check this logic

Produce a summary document outlining what the message types are and the status of our current handlers

## Tasks
- [ ] Summary document
- [ ] Review with tech team

Story points: 2.0
Complete and test Websockt PubSub implementation

Check out MR !807 for the first draft implementation. Complete it's prod-ready implementation via code reviews and deploy to all staging environments to smoke test as below.

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Usual Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use all whiteboard tools
  - [ ] upload photo
  - [ ] change pen/color
  - [ ] write text
  - [ ] shapes

## Special smoke tests
- Deploy 2 copies
  - [ ] create 2 sessions with different student/volunteer (main staging)
    - Student/volunteer can use all whiteboard tools
  - [ ] student connects to fern.upchieve, volunteer to trey.upchieve
    - Student/volunteer can use all whiteboard tools
  - [ ] Kill pod while in session and bring back up
    - Student/volunteer can reconnect to whiteboard (might require some refreshes)

Story points: 3.0
Convert backend to strict typescript

We are going to all work collaboratively on a single feature branch cut from main head at start time. We'll work on a single working copy via pair programming and multi-user text editors. Once a noticeable chunk of progress has been made on the conversion we'll commit the single working copy to the branch and continue working. Once we reach 0 errors we can merge the branch to main WITHOUT SQUASHING.

As we develop we'll have multiple pairs of eyes on every change and can turn off strict mode to run tests to ensure no bugs are introduced.

## Tasks
- [x] 0 typescript errors
- [x] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] all of them

Story points: 13.0
Change final feedback question copy

The feedback question on both student and volunteer post-session survey should be updated to the following copy with the email hyperlinked to app.upchieve.org:
```
Question text: Do you have any other feedback you’d like to share with UPchieve?
Help text: This can be about the website, about your coach, about the services/features UPchieve provides, about any technical issues you encountered, etc. We read every single comment, but if you need to connect with UPchieve staff about a question or concern please email us directly. 
```

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session

Story points: 0.0
Add reporting data to session review views

For reported sessions we want to see the report reason and report message in the session review view

Check out `src/views/Admin/AdminSessionDetail.vue`. The hydrated session includes necessary reporting data on the object. There is no exact copy for formatting so up to your discretion.

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Reported session have report message and reason shown

Story points: 2.0
Refactor endSession/saveFeedback to event architecture

The first step to moving to the new event based architecture is to refactor `SessionService.endSession` and `FeedbackService.saveFeedback` to emit events that a session/feedback has been saved.

endSession especially needs much of it's internal logic refactored to move side effects into subroutines registered as listeners for the `session-ended` event.

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Ending a session still produces the same result and side effects
- [ ] Saving a feedback still produces the same result and side effects

Story points: 3.0
Create UserSessionMetricsService

The UserSessionMetrics service should expose 2 core functions:
1. takes a session and updates the metrics objects for any involved users
2. takes a user and computes their historical metrics


~~Both these functions are ideally idempotent~~

Both functions will need a way to fill `MetricData` for each session.

The first function is attached to an event that a session has ended and should somehow be on a delay (3 minutes) to allow time for feedback forms to have been submitted

The second function is run by a script to backfill session metrics. The script should have a downgrade function to delete all USMs so we can retry if anything goes wrong

Also need to remove existing flagging logic to avoid double flagging

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Service computes metrics correctly

Story points: 3.0
Create metric events and corresponding actions/conditions

Create a set of `MetricEvents` objects with `condition` and `action` methods. The condition method reads a UserSessionMetrics object and determines whether or not the event applies and the action method should be called. The action method executes any consequences of the event such as sending an email. The event conditions/actions should correspond to the epic's rules/examples.

## Tasks
- [x] Code review
- [x] Staging smoke tests
- [x] Merge to main
- [x] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] MetricEvent conditions/actionsm atch rules/examples for epic

Story points: 2.0
Backfill UserSessionMetrics

Write a script that backfills all users' UserSessionMetrics objects using the new service. The script is ideally idempotent and includes a downgrade function

## Tasks
- [ ] Code review
- [ ] Merge to main
- [ ] Deploy to prod
- [ ] Run backfill script

## Smoke tests
- [ ] Script creates correct session metrics objects for all users

Story points: 1.0
Create UserSessionMetrics type

Create a `UserSessionMetrics` model that tracks basic session metrics like has the user been ghosted, have they been reported, session ratings, etc. Exact fields are up to discretion so long as they fulfill needs of epic rules/examples. Model is metrics aggregator so we can easily add any missing metrics in the future.

## Tasks
- [x] Code review
- [x] Merge to main

Story points: 1.0
Update sessions to review filter

Include the new `session.toReview` and `session.reviewed` fields in the sessionToReview filtering and remove the old checks for volunteer/student reviewed.

Update frontend where old fields are searched/set and collapse that code to just the 'reviewed'

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session
- [ ] Properly flagged session still show up in session review

Story points: 2.0
Update Session model and backfill

Add `session.toReview` and `session.reviewed` to the session schema and backfill session objects in DB to have these fields. Set the `toReview` field to true if `session.reviewedStudent` or `session.reviewedVolunteer` are false for sessions from the past 30 days otherwise always false . Set `reviewed` to true if either was true otherwise always false.

## Tasks
- [ ] Code review
- [ ] Staging smoke tests
- [ ] Merge to main
- [ ] Deploy to prod
- [ ] Run backfill script

## Smoke tests
- [ ] Student/volunteer can login
- [ ] Student/volunteer can make/join session
- [ ] Student/volunteer can use whiteboard and chat in session

Story points: 1.0