Code Monkey home page Code Monkey logo

resume-classifier's Introduction


ArminC AutoExec

SFU Open-source Development Club
Fall 2023 Project

Resume Evaluator Software Service using Naive Bayes Classifiers

CreditsStorybookTestingDevelopment SetupProduction Setup

Live demo



The SWE Resume Evaluator is a Software-as-a-Service (SaaS) web application that automatically classifies and assesses users' resumes to determine their suitability for software engineering roles, such as SWE, ML, and QA engineers.

Naive Bayes classifier is used for natural language processing.

Credits

Project Lead Jusung Park @Pentaminum

Developer Kathy Cho @heyj0jo
Developer Seunghwan Kim @SHKim331
Developer Tommy (Kanggeon) Oh @TommyOh0428
Developer Daniel Pham @dp357

Designer Gripen Chan @GripenANM

Storybook

A Storybook server is provided to allow browsing the components used in this project.

npm run storybook

Testing

Run Jest and React-Testing-Library tests on React code.

npm run test

Run server-side API testing code.

cd server
npm run test

resume-classifier's People

Contributors

jiin-kim109 avatar pentaminum avatar heyj0jo avatar dp357 avatar gripenanm avatar jpa118 avatar tommyoh0428 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

resume-classifier's Issues

Dropzone

Description:

The Dropzone component supports users to upload their file with a simple drag and drop method.

Check it out in our wireframe:
Image

The Dropzone consists of the three components

  • Dropzone box with dotted border
  • Manual upload button
  • "Drag file to window" text

You may use an external library to implement the Dropzone component. Please ensure that your chosen library is well-maintained and has a sufficient number of community supporters.

An example Dropzone can be found at:
https://yuvaleros.github.io/material-ui-dropzone/

Image

The Dropzone component should support the following props:
onSubmit(filepath: string) Default: (fp) => null
Type: function
Invoked when a file is uploaded to the dropzone via drag and drop or via the upload button. It calls the provided function with an argument of the local file path to the uploaded file.

Acceptance Critiera:

  • Add a Dropzone component to src/components/.
  • Define prop types using the PropTypes package.
  • Write a JSDoc comment on the component, illustrating what the component is about and the props it supports.
  • Write a test with Jest and RTL to verify its rendering. You must use Jest Mocking in order to test OnSubmit props.

Resume data collection

Description:

This project ticket does not involve coding tasks but focuses on data collection.

The objective is to gather resume data in PDF format from various sources.
The collected resumes will be stored in the python/resume_data/ directory, with the exception of the python/resume_data/bt_SWE directory, which should be excluded for now.

While focusing on gathering real-world resumes, template resumes are acceptable.

Acceptance Criteria:

  • Collect at least 30 resumes for each category: ML (Machine Learning), QA (Quality Assurance), and SWE (Software Engineering) in addition to the resumes we already have.
  • Ensure that no two resumes are identical.

Firebase Authentication

If you'd like to assign this ticket to yourself, please inform @jiin-kim109 to obtain the Firebase credentials and admin permission on the Firebase dashboard.

Description

For fast-paced development, we will be using Firebase as our authentication service provider. With the Firebase-provided SDK, your task is to implement an authentication API endpoint in Express.js.

Firebase Config

import { initializeApp } from "firebase/app";
const firebaseConfig = {
  apiKey: "SEALED",
  authDomain: "SEALED",
  projectId: "SEALED",
  storageBucket: "SEALED",
  messagingSenderId: "SEALED",
  appId: "SEALED"
};
const app = initializeApp(firebaseConfig);

Do not directly embed the Firebase credentials in your code. Rename .env.example file to .env and fill the credentials in there. Use dotenv library to retrieve credential data from .env file locally.
https://www.npmjs.com/package/dotenv

This API should expose the following endpoints to users:

POST /auth/signup

API Details

Request Header

{}

Request Body

{
    username: string
    email: string
    password: string
}

Response Header

{}

Response Body
success - status 200

json
{
    message: "ok",
    status: 200,
    user_token: string
}

failed - status 400

json
{
    message: [Error_message],
    status: 400
}

POST /auth/login

API Details

Request Header

Authentication: Bearer [user_token]

Request Body

{}

Response Header

{}

Response Body
success - status 200

{
    message: "ok",
    status: 200
}

failed - status 400

{
    message: [Error_message],
    status: 400
}

Create a server/auth/ directory and a file auth.js in it. Implement the authentication APIs above and router in app.js. Each API should follow the data type schema above. For example, if user gives a number to the username or email field, the response should be a failed response with status code 400, and a message indicates that the values to the fields have failed on validation.

Response should always come with message (string) and status (number). Additional fields can be added as /auth/signup response if needed.

You can refer to the following articles for the signup feature:
https://dev.to/deepakshisood/authentication-using-firebase-for-expressjs-2l48

For the login feature using an Authentication Bearer header, you can check out:
https://medium.com/@harunrst11/id-token-authentication-with-firebase-node-js-explained-github-9ff86578ed89

Acceptance Criteria

  • Implement the /auth route and /auth/signup and /auth/login APIs. Implement an ExpressJS router in app.js. Use Postman for local testing.

  • Ensure that the APIs support and provide responses as illustrated above. Test the features with Firebase dashboard to ensure the creation of a new user and authentication via JWT token work.

  • Each data field for the POST requests should undergo validation before processing. This means that if a user enters a number in the username field, the client should receive a response with a status code of 400 and a message indicating which field failed validation.

  • The email field should be validated to ensure the string value follows an email format (e.g., name@domain).

  • If an email is already signed up, and a user already exists in Firebase, the API should respond with a 400 status code and a message indicating that a user has already signed up.

  • The password should be at least 8 characters long.

  • The username should be equal to or more than 4 characters long and must contain at least one alphabet character.

  • Usernames cannot be duplicated.

  • Write a Jest Unit Test for each of the endpoint. Check this article for Jest tests with Express JS.
    https://www.albertgao.xyz/2017/05/24/how-to-test-expressjs-with-jest-and-supertest/

  • Do not directly embed the Firebase credentials in your code. Rename .env.example file to .env and fill the credentials in there. Use dotenv library to retrieve credential data from .env file locally.

PDF preview component

Description:

The PdfPreview component is a component that shows a preview for a pdf file. The component should automatically expand to the full width and height of its wrapping parent component.

Image

You can use react-pdf or any other relevant libraries for this feature, such as
https://www.npmjs.com/package/react-pdf

The feature you need to implement is that it should be able to expand and fill the parent's width and height. That means, if the wrapping div has a width of 300px and a height of 300px, the PDF viewer should expand to 300px by 300px, excluding the padding.

Acceptance Critiera:

  • Add a PdfViewer component to src/components/.
  • The component should allow width and height values to be passed through its props.
  • Define prop types using the PropTypes package.
  • Write a JSDoc comment on the component, illustrating its characteristics and the props it supports.
  • You don't need to test the PDF viewer feature if you are already using a PDF viewer library.
  • Write a test with Jest and RTL to verify that it expands to the width and height of the wrapping element.

Stop Words Removal

Description:

Create a py file under python/ that takes a user input for a file path to local csv file and outputs a single csv file.

The .py script should perform the following procedures:

  1. Take a user input indicating a file path to a local pdf file. Using a Python IO, load the information into a pandas dataframe.
  • If a file is not a csv file, raise an exception
  • You will need to create a sample csv file, containing two columns: {'Tokens': a list of tokens(string) and 'Job_cat': job category}, under python/resources/ for testing.
  1. Read all the rows from the csv file
  • read the column 'Tokens' and remove all the stop words using any python library you want
  • You can either modify the dataframe itself or create a new dataframe
  1. Export a single csv file, containing all information in the modified(or new) dataframe, under resources/
  • use any reasonable name for the file -> must be different from the original csv file

example:

Image

Acceptance Criteria:

  • the function exports a csv file with the same column names as the input file
    1. Tokens (stop words removed)
    2. Job_cat (no change)
  • Manually create a sample csv file that could be used in testing under python/resources/

Reporting Page Score

Description:


The reporting page must not directly fetch the API response data from the backend. Ticket #36 should handle the request and response, and storing the result in a React context. The reporting page should utilize the state provided by the created React context.

Image

  1. Set the loading status to True
  2. req/res from backend
  3. Store the API response in a context (dispatch data to a context).
  4. Navigate to the reporting page.
  5. The reporting page retrieves the state from the context.

Our assumption is that ticket #36 has already implemented steps 1 to 4. Therefore, all the requirements outlined below should commence from step 5.

However, this does not necessarily imply that using the React context in this type of situation is always ideal. React Router (page switching library) offers props delivery features between pages. In some cases, it may be beneficial to utilize props instead of establishing a global state using React Context. This ticket is designed in this manner because it can be a good practice to explore global state management via React context.


Notice that the API response format illustrated below is different from ticket #30, you may need to modify server/src/resume and server/src/tests/resume to match the response format. Please make sure

cd server
npm run test

passes after the modification. You may also need to reference the PR of ticket #36 and modify accordingly to retrieve appropriate state value from the global React context created by the ticket #36 .


Using the expected response API format, complete the reporting page.

There should be 2 classifiers in the backend,

  • 1st classifier - Accountant, Designer, HR, IT(SWE, ML, QA integrated)
  • 2nd classifier - SWE, ML, QA

Case 1. The provided resume belongs to any job category other than IT.

Expected response API example:

 job_matches: {
          "is_IT": "False",
          "job_name": "Accountant",
          "similarity": 5
}

Example reporting page for the JSON format above

Image

if "is_IT" == False:

  • Matching job: job_name
  • Resume Score: similarity
  • Any way to show "Invalid"
  • Job description in the placeholder below(Wikipedia)

Case 2. The provided resume belongs to any category in IT.

Expected response API example:

 job_matches: {
          "is_IT": "True",
          "job_name": "Software Engineer",
          "similarity": 90
}

Example reporting page for the JSON format above:

Image

if "is_IT" == True:

  • Matching job: job_name
  • Resume Score: similarity
  • Score bar (follow the design above, however, you can make your own design if you want)
  • Job description in the placeholder below(Wikipedia)

Acceptance Criteria:

  • Takes response API
  • Two different pages for each case(is_IT == True / False)
  • Clear INVALID sign for is_IT == False case
  • Matching job is the job in "job_name"
  • Resume score is the similarity
  • Job Description
  • Write a JSDoc comment on the component illustrating what this component is about.
  • Write a test with Jest and RTL to verify its rendering

Drag and Drop Indicator

Description:

Just like the modal component, the File Drag and Drop Indicator component should show up the indicator and darken (reducing opacity) the entire screen when a user drags a file to the screen.

indicator box wireframe:
Image

DnD indicator box example in discord:

Image

Note that the indicator is currently a static component, but there will be another ticket in future that will make this indicator component works as the same as the Dropzone and the upload button.

The effect should be erased when a user releases the file. Only the effect but no prop is required as this component is static for now.

The component consists of the two features

  • Background darkening effect
  • static drag and drop indicator box with fixed height and width when a user drag their file to any point of the window.

Acceptance Criteria:

  • Dragging into any part of the screen will show up the indicator(does not need to be inside the drag and drop box)

  • Whenever the indicator shows up, the background should be darkened

  • Add the component to src/components/[LOCATION].

  • Write a JSDoc comment on the component, illustrating its characteristics.

  • Write a test with Jest and RTL to verify its rendering.

Dataset Merge

Description:

Create a py file under python/ that outputs a single csv file.

The .py script should perform the following procedures:

  1. Take a directory path for resources/resume_data
  2. Using a Python IO, load all files for each category directory and perform pdf2Token to them
  3. Store them into a single pandas dataframe
  • the dataframe contains 2 columns:
    1. Tokens: A string list of tokens derived by pdf2Token
    2. Job_cat: job category for the tokens ex) if the pdf's name was ML_1.pdf -> "ML"
  1. Export a single csv file, containing all information in the pd dataframe, under resources/
  • use any reasonable name for the file

example pd dataframe:
Image

Acceptance Criteria:

  • Utilize the function pdf2Token by importing python/helper/df2Tokens.py

  • the function exports a csv file

  • job_category matches

  • If needed, you can modify the arguments of "pdf2Token" function

resume API

Description:
Before you get started, navigate to the server folder and check the Swagger documentation. There, you'll get an overview of how the API should behave.

cd server
npm run start
// open your browser and type http://localhost:3000/api-docs

All backend work should be done inside the server folder. Please be cautious about entering backend-related commands outside of the server folder, as the server folder is an independent module and contains its own package.json file.

If you're not familiar with HTTP Method, check:
https://velog.io/@yh20studio/CS-Http-Method-%EB%9E%80-GET-POST-PUT-DELETE

Resume API receives a request with a PDF file payload from the user's frontend and returns the processing result from the Naive Bayes classifiers. The returned information contains the top N most matching resume sub-categories (e.g., software developer, business analyst, QA engineer, etc.) and a numeric value indicating the strength of the match.

Image

Example response payload would be something as follows,

{
    category_matches: {
        1: {
            "category_id": 1234,
            "category_name": "software engineer",
            "weight_sum": 87
         },
        2: {
            "category_id": 2222,
            "category_name": "business analyst",
            "weight_sum": 35
        }
    }
}

Likely Resume API is consisting of the following endpoints,
POST /resume - send a resume file to the server and requests for evaluation

However, we do not currently have a Python preprocessor that handles PDF files yet. The goal of this ticket is to implement only the communication between React and Express.js. The React frontend should make an API call to the Resume API with a PDF file attached. Express.js receives the request and the PDF file but sends back only a sample result.

Image

This means, you can simply define the resume API request and response and follows,
POST /resume
request

    user_id: "sample_user_id",
    resume: [PDF FILE]

response

    message: "ok",
    status: 200,
    category_matches: {
        1: {
            "category_id": 1234,
            "category_name": "software engineer",
            "weight_sum": 87
         },
        2: {
            "category_id": 2222,
            "category_name": "business analyst",
            "weight_sum": 35
        }
    }

Please note that the implementation of the API is entirely up to you, but it is recommended to include message and status code field in your API response:
200

    message: "ok",
    status: 200

400

    message: "[ERROR MESSAGE",
    status: 400

To know more about the HTTP status code, please check the following:
https://sanghaklee.tistory.com/61

What you will be implementing is:

  1. Resume API request and response format.
    Tutorials:
    https://velog.io/@ongsim123/node.js-express-server
    https://expressjs.com/ko/starter/hello-world.html

You can conveniently test your API with Postman during the development.
Postman: https://dev-cini.tistory.com/7
Postman & Express JS: https://roughroad.tistory.com/153
Sign Up API example: https://github.com/sfuSwSo/swe-resume-evaluator/blob/main/server/src/routers/auth/index.js

  1. Make Express.js and the Resume API capable of receiving a PDF file from the frontend.
    Please refer to the following tutorial.
    https://velog.io/@nahye/multer%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-React-Node.js-%ED%8C%8C%EC%9D%BC-%EC%97%85%EB%A1%9C%EB%93%9C-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0
    If it involves creating a directory for saving uploaded PDF files, please make sure to add the directory path to .gitignore so that it won't be pushed to the remote repository.

  2. Documentation using Swagger
    Tutorial:
    https://joooohee.tistory.com/10
    Check the example swagger documentation:
    https://github.com/sfuSwSo/swe-resume-evaluator/blob/main/server/src/routers/auth/index.js
    Other Swagger macros and fields:
    https://swagger.io/docs/specification/describing-parameters/

  3. Unit test using supertest
    Tutorial:
    https://inpa.tistory.com/entry/JEST-%F0%9F%93%9A-supertest-api-%EC%9A%94%EC%B2%AD%ED%85%8C%EC%8A%A4%ED%8A%B8
    Example:
    https://github.com/sfuSwSo/swe-resume-evaluator/blob/main/server/src/__tests__/auth/auth.test.js

Acceptance Criteria:

  1. Resume API request and response. While the API sends back a sample response, it should be capable of handling a resume file transferred from the frontend.
  2. Swagger documentation. The new api should appear at localhost:3000/api-docs
  3. Unit testing. No mocking is likely required for this ticket.

Modal component

Description:

The Modal component is a reusable component with a fixed width and height that darkens the background. The width, height, and inner components are supposed to be passed through props.

The example usage of the modal component in our wireframe is as follows:

This ticket is not asking for the login buttons and other components inside the modal as in the wireframe below! You are only required to make it empty box but exposes a children prop so external components can be injected into the modal box.
Image

The modal consists of the three components

  • Background darkening effect
  • Modal box
  • Modal closing button within the modal box

The components should support the following features using any of React hooks, contexts, state, and props

  1. Allow the external components to determine the status of the modal component, whether it is closed or open.
    e.g.
    isOn Prop
    Type: boolean
    Determines whether the modal is on or off. If true is passed, the modal should be visible; otherwise, it should be hidden.

  2. Allow the external components to specify the width of the modal component.
    e.g.
    width Prop
    Type: numeric
    Determines the modal width

  3. Allow the external components to specify the height of the modal component.
    e.g.
    height Prop
    Type: numeric
    Determines the modal height

  4. Allow the external components to pass a callback that is invoked when the modal is about to close (become invisible) by pressing the close button.
    e.g.
    OnClose Prop
    Type: function
    Invoked when a modal is closed by the user.

  5. Allow the external components to decide whether the modal should be closed and show the same effect as when the user clicks the close button (means onClose should be invoked), when a user clicks outside the modal box (background).
    e.g.
    shouldCloseWhenOuterClicked
    _Type: boolean)
    If true is passed, the modal is closed and displays the same effect as when the user clicks the outer (dark) area, similar to pressing the close button.

  6. Allow the external components to pass child components via the children prop, which are intended to be placed within the modal box (You are free to apply margin to the modal box or padding around these inner components depending on your styling).
    e.g.
    children
    Type: Element[]
    inner components to be injected inside the modal should be passed as children and placed within the modal box when it's opened.
    https://react.dev/reference/react/Children

You can refer the following tutorial of implementing a modal component in React:
https://www.digitalocean.com/community/tutorials/react-modal-component

Acceptance Critiera:

  • Add a modal component to src/components/.
  • The component should support the required features listed above using any of React hooks, contexts, state, and props.
  • Define prop types using the PropTypes package.
  • Write a JSDoc comment on the component, illustrating its characteristics and the props it supports.
  • Write a test with Jest and RTL to verify its rendering. You must use Jest Mocking and RTL User Event in order to test OnClose and shouldCloseWhenOuterClicked props.

Logo component

Description:

The Logo component is a reusable logo image component with fixed-pixel width and height. The component should allow width and height values to be passed through its props.

Please add a logo component to the src/components/ directory. Refer to the image below to see where the logo component will be used:

Image

The logo should not be dependent on its parent or sibling components; instead, it should have a fixed width and height provided via its props.

Add the logo component temporarily to the src/containers/MainPage.jsx component. We will relocate the component later.

Acceptance Critiera:

  • Add a logo component to src/components/.
  • The component should allow width and height values to be passed through its props.
  • Define prop types using the PropTypes package.
  • Write a JSDoc comment on the component, illustrating its characteristics and the props it supports.
  • Write a test with Jest and RTL to verify its rendering and its ability to set size based on its props values.

NLP preprocessing model

Description:

Create a py file under python/ that creates a machine-learning model(classifier) with resume datasets.

Create 2 classifiers:

  • 1st classifier - Accountant, Designer, HR, IT(SWE, ML, QA integrated)
  • 2nd classifier - SWE, ML, QA

The .py script should perform the following procedures:

classifier 1

  1. Use the CSV file fst_data in resources/resume_data
  2. Load all the resume data and split them into training, validation, and testing sets (6:2:2 ratio)
  3. Train the model and validate the accuracy.
  4. Test the model to have at least 70% accuracy.
  5. Make the model take a data input: { tokens: [tokens], cat: category }
  • The model returns the closest job category
  • The model also returns the similarity to IT category

classifier 2

  1. Use the CSV file snd_data in resources/resume_data
  2. Load all the resume data and split them into training, validation, and testing sets (6:2:2 ratio)
  3. Train the model and validate the accuracy.
  4. Test the model to have at least 70% accuracy.
  5. Make the model take a data input: { tokens: [tokens], cat: category }
  • The model returns the closest job category
  • The model also returns the similarity to the closest job category

Acceptance Criteria:

  • Utilize all the functions from helper python files from python/helper/

  • create a py file with functions for 2 models

  • create a function to use the model to produce the expected output for any data input with a certain format

  • If needed, you can modify all the functions of helper py files

ReportScore component

Description:

The ReportScore component is a simple reporting box that shows up in the report page. The component should automatically expand to the full width of its wrapping parent component with the fixed height.

Reporting page wireframe:
Image

Figma prototype:
Image

For now, just use the texts and features in the prototype as fixed values.

The component consists of the two features

  • ReportScore box with fixed height and the width that fills the parent component's width
  • Texts and designs in prototype

Acceptance Criteria:

  • The Report Box contatins the texts in the prototype design
  • Add the component to src/components/[LOCATION].
  • Write a JSDoc comment on the component, illustrating its characteristics.
  • Write a test with Jest and RTL to verify its rendering.

Data Files Name Change

Description:

Create a py file under python/ that organize the files resources/resume_data/.

The .py script should perform the following procedures:

  1. Using a Python IO, load all pdf files from each category directory to memory.

  2. Change their names representing category type + order.
    ex) under Accountant directory, all the file names should be Accountant_1, Accountant_2, ....

Acceptance Criteria:

  • The .py script should change the name of all files in all category directories into category_# format without any duplicates
  • Do not modify the files in resources/resume_data yet, the data files are not completely ready

Dynamically generate .env in Github Action workflow during the deployment.

Description:
Our .env file contains important credentials used for Firebase access and potentially other backend services. However, including the .env file in the remote repository is not advisable, as anonymous readers could access secure credentials, posing a potential security threat.

Developers typically obtain the .env file and its credentials from the project lead. The application requires the .env file during its initialization stage to connect with services like Firebase. This means, however, the GitHub Action will fail because it lacks the .env file in its remote environment, unlike individual developers who have it in their local setup.

To learn more about GitHub Actions and CI/CD, visit:
https://www.youtube.com/watch?v=URmeTqglS58
https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs

One solution to this issue is dynamically creating the .env file during the deployment. This way, when a node server boots up, it can operate with a generated .env file. GitHub supports a secret management feature called GitHub Secrets. To view the secrets in GitHub Secrets in our repository, navigate to the 'Settings' tab. On the left-hand side of the menu, you'll be able to find the 'Secrets' or 'Actions'.

The GitHub workflow can fetch the values of GitHub Secrets while it's running. Check out the following article to see how it works:
https://github.com/Azure/actions-workflow-samples/blob/master/assets/create-secrets-for-GitHub-workflows.md

Your task is straightforward. Since we have the .env.example file in the repository containing the names of the secret keys, you need to edit the .github/workflows/node.js.yml file and populate the values in GitHub Secrets corresponding to the keys in the .env.example file. After that, rename .env.example to .env before initiating the server app.

Below is an example code snippet you can refer to for editing the workflow:

- name: Create and populate .Renviron file
        env:
          AWS_HOST: ${{ secrets.AWS_HOST }}
          AWS_PORT: ${{ secrets.AWS_PORT }}
          AWS_PW: ${{ secrets.AWS_PW }}
          AWS_USER: ${{ secrets.AWS_USER }}
          DBNAME: ${{ secrets.DBNAME }}
        run: |
          touch .Renviron
          echo aws_host="$AWS_HOST" >> .Renviron
          echo aws_port="$AWS_PORT" >> .Renviron
          echo aws_pw="$AWS_PW" >> .Renviron
          echo aws_user="$AWS_USER" >> .Renviron
          echo dbname="$DBNAME" >> .Renviron

Acceptance Critieria:

  • modify .github/worfklows/node.js.yml to create .env file during the deployment. Scretes are provided in the Github Scretes. Find the matching keys in .env.example file, fill the values, and rename it.

  • Our Github Action is currently failing due to the missing env file during the workflow. The issue should be resolved if this ticket is completed correctly. You may make a multiple push to test Github Action runs.

Term and Condition component

Description:

This ticket includes modifications for other web pages.

  1. The Term of Condition component
  • contains only the title & text from our figma design

Image

  1. new MainPage with evaluate button
  • remove the upload box from the current mainpage
  • follow our figma design
  • add the "Evaluate your Resume" button below the logo

Image

  1. TermAndCondition page, Guidlines page, File Upload page
  • follow our figma design for each page
  • TermAndCondition page will use the Term of Condition Component
  • Guidlines page will use the Guideline component
  • File Upload page will use the upload box and dropdown components

Image

Image

  1. Back and Next buttons
  • Back and Next buttons for each page using our figma design
  • page transition via the buttons

Acceptance Criteria:

  • The Term and Condition Component
  • Back and Next buttons with page transition
  • 3 different pages + 1 new main page design
  • Write a JSDoc comment on the component illustrating what this component is about.
  • Write a test with Jest and RTL to verify its rendering

Main Page transition to Reporting Page

Description:

The transition event between the main page and the reporting page occurs when a user uploads a file or drags a file onto the screen.

  1. Initially, the website hides the logo and the dropzone component, and displays the progressText to show the loading status. ✅

  2. it sends the user's resume to our server to request an evaluation. (Note that this task is outside the scope of this ticket.) ❌

  3. Once the website receives the result from the server, it transitions to the reporting page. ✅

Since we haven't created the backend for resume processing, you can simulate the loading using a simple JavaScript "timeout" function.

The goal of this ticket is to implement the above steps so that the transition event is established when a resume is uploaded. You will be using the "React Router" library, which is already installed. The following tutorials will guide you through the process:
https://carmack-kim.tistory.com/127
https://ui.dev/react-router-url-parameters

Image

Acceptance Criteria:

  • The user should be routed to the reporting page when they upload a PDF file, following the above procedures.
  • Write a clear code and modules for loading procedure so that later on we can add the communication login between the backend on the top of it.
  • Write a test with Jest and RTL to verify the routing and rendering.

Resume processing

Description:
Now that we have our backend Resume API (ticket #30), it's time to build communication between our frontend and backend.

When a user uploads a resume PDF file to the drop zone, it should initiate an API call to the resume API. As implemented in #19, this action should promptly display the ProgressText component while awaiting the API response. Once the frontend receives the API response, it should navigate the user to the reporting page. Plus, the API response data should be dispatched to a React context so that it can be shared with the reporting page.

To summarize,

  1. Modify the Dropzone and DragNDrop components so that they initiate an API call when a user uploads an appropriate PDF file. Instead of directly implementing the API invocation logic in the Dropzone or MainPage, it is recommended to separate it to a custom hook (you may create a "hooks/" directory). Pass the hook's high-level function from the page to the component as a callback.

https://medium.com/@nelson_examiner/building-custom-react-hooks-for-calling-apis-ab82a6b45ff
e.g.

// useEmployees.ts

import { useCallback, useState } from "react"
import { Employee } from "../utils/types"
import { useCustomFetch } from "./useCustomFetch"
import { EmployeeResult } from "./types"

export function useEmployees(): EmployeeResult {
  const { fetchWithCache, loading } = useCustomFetch()
  const [employees, setEmployees] = useState<Employee[] | null>(null)

  const fetchAll = useCallback(async () => {
    const employeesData = await fetchWithCache<Employee[]>("employees")
    setEmployees(employeesData)
  }, [fetchWithCache])

  const invalidateData = useCallback(() => {
    setEmployees(null)
  }, [])

  return { data: employees, loading, fetchAll, invalidateData }
}
  1. Create a React Context
    Create a React context so that the reporting page can subscribe to the API response.

  2. Navigates to the reporting page after the dispatch

  3. Unit testing

Testing this API call should be conducted using MSW. You won't be testing the real backend API every time you run the test suites. Instead, you will set up a mock API response server called MSW and test them out.

Unit testing with MSW:
https://jskim1991.medium.com/react-unit-testing-apis-with-mock-service-works-msw-ca112ceddde9

Acceptance Criteria:

1 API call made after a file upload on the dropzone
2. page transition to the reporting page
3. reporting page can subscribe the response data via React Context
4. Write a custom hook implementing API invocation logic.

ProgressText component

Description:
The ProgressText component is a static component that has no props or actions but only animation and a fixed width and height. It will be used solely for visual purposes.

In our wireframe, the ProgressTexts component appears when a user uploads a resume and the website starts its processing.
Image

Refer to the following as an example,
https://gifyu.com/image/S6zkn

The component animates to switch to the next text for display. Since we don't have a high-level prototype yet, it is up to you how to style it. The requirements are:

  • Rotating Texts
  • Animation

You can leave the texts empty or use random words.

Acceptance Criteria:

  • Add the Guidelines component to src/components/.
  • Write a JSDoc comment on the component illustrating what this component is about.
  • Write a test with Jest and RTL to verify its rendering.

Login/Signup

Description:

It's time to implement our login/signup feature.

The sequence of the login/signup feature is as follows: when a user clicks the profile button, a login/signup modal pops up. A user can either register a new account or, if they already have an existing account, they can log in. Once this process is completed, the modal closes, and the user's email is displayed (no logout feature yet).

Image


Signup Implementation:

Ticket #9 has implemented the Auth API. Please check server/src/routers/auth for details. The API enables the creation of a new user profile based on the input provided in the API request. The project owner will provide the Firebase credentials for testing purposes.

To sign up, the frontend should invoke the signup API following the specified API request format. You can find details about the API request format in the API documentation.

To access the API documentation, follow these steps:

cd server
npm start
// Enter 'localhost:3000/api-docs' in your browser

Login Implementation:

It is a common sense that backend provides two APIs to support both signup and login actions. However, Firebase uniquely recommends using a Firebase SDK directly in frontend to log a user in.

Check the following article to know more about Firebase login details:
https://velog.io/@zmin9/React-Firebase-Authentication-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EC%9D%B4%EB%A9%94%EC%9D%BC-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85%EB%A1%9C%EA%B7%B8%EC%9D%B8

Note that the above article insists that storing Firebase config in an environment variable is safer than storing it directly in the code, but this is not true. The author knows nothing. No 'Security through obscurity". It is perfectly safe to store configuration information directly in the code for Firebase.

import { initializeApp } from "firebase/app";
const firebaseConfig = {
  apiKey: "AIzaSyDEiCc0MSg2DKOWf7VyddnR8hKKaZRv0VQ",
  authDomain: "swe-resume-evaluator.firebaseapp.com",
  projectId: "swe-resume-evaluator",
  storageBucket: "swe-resume-evaluator.appspot.com",
  messagingSenderId: "845126642164",
  appId: "1:845126642164:web:0f826814f676d3f878f1a1"
};
const app = initializeApp(firebaseConfig);

Login Persistency:

The login status should persist even when users navigate between different pages or close and reopen the tab. In most cases, developers implement the following sequences:

  1. Upon login or signup, the backend responds with a user token that can be used for login instead of using email and password.
  2. The frontend stores the token in the browser's local storage (or cookie). This allows the frontend application to access the browser's local storage and retrieve the token even after the tab is closed and reopened.
  3. Whenever a user browses different pages requiring authentication, the frontend automatically uses the token instead of requiring users to re-enter their email and password.
  4. The token has an expiration. In the case where step 3 is initiated but the token has expired, the frontend either refreshes the token or redirects the user to the login page.

https://bo5mi.tistory.com/188

Firebase supports convenient persistent login functions:
https://velog.io/@sunohvoiin/Auth-Firebase-Auth-세션로컬-스토리지-사용하기

Acceptance Criteria:

UploadStep component

Description:

The UploadStep Component is a responsive component that takes props from each webpage(Terms and conditions page, Guidelines page, uploading page) and shows the upload step from 1 to 3.

Design for the step bar:

First page: Terms and Conditions page (default bar)
Image

Second page: Guidelines page

  • check mark for the first section of the bar
  • highlights for the second section of the bar

Image

Third page: uploading page

  • check marks for the first and second sections of the bar
  • highlights for the last section of the bar

Image

Follow the design for the UploadStep bar.
The step bar does not necessarily need the check marks for the sections before the current page. However, the step bar somehow has to indicate the current section.

Acceptance Criteria:

  • The Upload step bar with a reasonable design(similar to the given Figma design)
  • The step bar indicates the current section(page) and the completed sections
  • Write a JSDoc comment on the component illustrating what this component is about.
  • Write a test with Jest and RTL to verify its rendering

Login/Signup view within the modal

Description:
The Login/Signup views within the modal are individual static views within the modal.

In our wireframe, the Login/Signup views appear in the modal when a user clicks the login button in the header.

Follow this image:

Image

For now, both Login and Signup views have no functionality, so style the views within the modal as the following image and make all the features static.

The only reactive feature is the text button for the change of views.
The "Sign up" text button at the very bottom in the Login view modal should lead to the Signup view.
The "Login" text button at the very bottom in the Signup view modal should lead to the Login view.

Acceptance Criteria:

  • The login button in the header leads to the login view
  • Add Text buttons at the bottom for each view that leads to another
  • Write a JSDoc comment on the component illustrating what this component is about.
  • Write a test with Jest and RTL to verify its rendering

Drag and Drop Issue

Description:

Currently, the mask from the drag-and-drop component is preventing most buttons from user interactions.

Resolve the issue and make both DnD and buttons work.


Acceptance Criteria:

  • DnD works
  • All user interactions available, all buttons work as expected

PDF to tokens

Description:

Create a py file under python/ that takes a user input for a file path to local pdf and outputs a list of tokens.

The .py script should perform the following procedures:

  1. Take a user input indicating a file path to a local pdf file. Using a Python IO, load a pdf file to memory.
  • If a file is not a pdf file, raise an exception.
  • User input should be given as an argument to a function. This means you must write and export a function that takes a user input as its argument.
  • A sample resume pdf file is given under python/resources/sample_resume.pdf
  1. Read all the lines from the pdf file and convert them into a raw string.

  2. Tokenize the raw string and export (return).

How to tokenize:
reference: https://spacy.io/api/token

example:
Image

ex) The PDF file contains a sentence "I'm a man."
-> [ "I", "'m", "a", "man", "." ]

Acceptance Criteria:

  • the function returns a list of tokens(string)
  • the token contains all strings in the pdf dile

Guidelines

Description:
The Guidelines component is a static component that has no props or actions. It will be used solely for visual purposes.

In our wireframe, the Guidelines component will be placed below the dropzone component. It provides guidance to users before they upload their resumes.

Image

Refer the following as an example,
Image

The component consists of

  • Title
    e.g. "Guidelines for uploading your resume"
  • Header text
    e.g. "To make sure we analyze your resume correctly and generate the right recommendations, please ensure that the resume you upload meets the following guidelines"
  • Wrapper box
  • Guidelines

Unfortunately, we don't have a high-level prototype on Figma, so it is hard to define the detailed styling at this moment. Therefore, this ticket only expects the existence of the above four components, and the rest of the styling will be up to the assignee.

Acceptance Critiera:

  • Add the Guidelines component to src/components/.
  • Write a JSDoc comment on the component illustrating what this component is about.
  • Write a test with Jest and RTL to verify its rendering.

Footer Hyperlink

Description:

This ticket is required to add hyperlinks and a page transition under text buttons in the footer.

Implement the following text buttons:

  1. "Terms of Service": leave this button as it is for now
  2. "About us" button: add a hyperlink to our club GitHub page https://github.com/sfuSwSo
  3. "2023 SFU OS Development Club" button: refresh the page and page transition to the main page

Image


Acceptance criteria:

  • hyperlink to club GitHub page from "about us" button
  • refreshing to the main page from "2023 SFU OS Development Club"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.