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

All 1.1 #129

Open
wants to merge 160 commits into
base: all-1.0
Choose a base branch
from
Open

All 1.1 #129

wants to merge 160 commits into from

Conversation

gouravmore
Copy link
Member

@gouravmore gouravmore commented Jul 30, 2024

Summary by CodeRabbit

  • New Features

    • Introduced multiple GitHub Actions workflows for streamlined deployment to AWS S3 for both production and development environments.
    • Added a login page component with state management for user credentials and validation.
    • Created a custom React hook for audio detection that enhances audio input monitoring capabilities.
  • Bug Fixes

    • Enhanced equality checks throughout various components to ensure strict type comparisons, reducing potential bugs in logical flow.
  • Documentation

    • Added new CSS styles specifically for the login page to improve user interface design.
  • Chores

    • Cleaned up unused imports and variables across multiple components to enhance code maintainability.

deechavhan098 and others added 30 commits April 2, 2024 16:32
IssueId #215702 fix: Mozhigal | Progress not appearing correctly for …
Bug #217137  fix: Added postMessage in pratice for send the charLengt…
IssueId #219606 feat: on submit should call the learnerai API call in…
gouravmore and others added 23 commits June 20, 2024 17:02
Issue #219845 fix: branch update for test-rig prod
Issueid #221626 fix: Implement AuthGuard for Route Protection in React
IssueId #223082 feat: Create Log Out Button in Test-Rig [React]
IssueId #223082 feat: Create Log Out Button in Test-Rig [React]
Task #224175 fix: Sonar Cloud Fixes for all-learner-ai-app
Copy link

coderabbitai bot commented Jul 30, 2024

Walkthrough

This update introduces a series of enhancements focused on the deployment workflows, code quality, and the user experience within the application. New GitHub Actions workflows have been established for continuous deployment of the application across different environments, while significant code improvements enhance maintainability and user interactions. The addition of new components and styling, alongside refactoring for better state management and error handling, contribute to a more robust and user-friendly application.

Changes

File(s) Change Summary
.github/workflows/*.yml New workflows for deployment targeting different branches, integrating AWS S3 and CloudFront for production environments.
.husky/* Added pre-commit hooks and a .gitignore to manage Git hooks and exclude unnecessary files.
.prettierrc, eslintrc.json, package.json Introduced Prettier and ESLint configurations to enhance code formatting and linting processes; updated dependencies.
src/App.js, src/components/*, src/utils/* Various components refactored for improved state management, logic clarity, and enhanced functionality.
src/views/* New login and practice components introduced, enhancing user authentication and interactivity within the application.
src/utils/constants.js, src/utils/urlConstants.json Updated API endpoint paths and logic for handling arrays and languages.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LoginPage
    participant Api
    participant App

    User->>LoginPage: Enter credentials
    LoginPage->>Api: POST request for virtual ID
    Api-->>LoginPage: Return virtual ID
    LoginPage->>User: Store credentials
    LoginPage->>App: Navigate to Discover Start
Loading

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

sonarcloud bot commented Jul 30, 2024

Quality Gate Failed Quality Gate failed

Failed conditions
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarCloud

Catch issues before they fail your Quality Gate with our IDE extension SonarLint

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Outside diff range, codebase verification and nitpick comments (2)
.github/workflows/all-prod-rig.yml (1)

1-1: Consider renaming the workflow for consistency.

The workflow name "ALL rig prod Deployment" could be more consistent with other workflows. Consider renaming it to "ALL Production Deployment".

.github/workflows/all-app-sandbox.yml (1)

1-1: Consider renaming the workflow for consistency.

The workflow name "ALL sandbox prod Deployment" could be more consistent with other workflows. Consider renaming it to "ALL Sandbox Deployment".

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between b045345 and d5e75a1.

Files ignored due to path filters (1)
  • src/assets/images/logout.svg is excluded by !**/*.svg
Files selected for processing (42)
  • .github/workflows/all-app-sandbox.yml (1 hunks)
  • .github/workflows/all-dev-rig.yml (1 hunks)
  • .github/workflows/all-dev-tn.yml (1 hunks)
  • .github/workflows/all-prod-rig.yml (1 hunks)
  • .github/workflows/all-prod-tn.yml (1 hunks)
  • .husky/.gitignore (1 hunks)
  • .husky/pre-commit (1 hunks)
  • .prettierrc (1 hunks)
  • eslintrc.json (1 hunks)
  • package.json (3 hunks)
  • src/App.js (3 hunks)
  • src/components/Assesment/Assesment.jsx (19 hunks)
  • src/components/AssesmentEnd/AssesmentEnd.jsx (9 hunks)
  • src/components/DiscoverEnd/DiscoverEnd.jsx (2 hunks)
  • src/components/DiscoverSentance/DiscoverSentance.jsx (12 hunks)
  • src/components/Layouts.jsx/MainLayout.jsx (15 hunks)
  • src/components/Mechanism/WordsOrImage.jsx (8 hunks)
  • src/components/Practice/Mechanics1.jsx (1 hunks)
  • src/components/Practice/Mechanics3.jsx (16 hunks)
  • src/components/Practice/Mechanics4.jsx (9 hunks)
  • src/components/Practice/Mechanics5.jsx (3 hunks)
  • src/index.css (2 hunks)
  • src/routes/index.js (3 hunks)
  • src/services/callTelemetryIntract.js (1 hunks)
  • src/services/telementryService.js (4 hunks)
  • src/services/telemetryService.js (1 hunks)
  • src/services/utilService.js (1 hunks)
  • src/store/sagas/handlers/user.handler.js (1 hunks)
  • src/utils/AudioCompare.js (1 hunks)
  • src/utils/RecordVoiceVisualizer.jsx (1 hunks)
  • src/utils/VoiceAnalyser.js (6 hunks)
  • src/utils/constants.js (4 hunks)
  • src/utils/urlConstants.json (1 hunks)
  • src/utils/useAudioDetection.jsx (1 hunks)
  • src/views/AppContent/AppContent.jsx (1 hunks)
  • src/views/HomePage/HomePage.jsx (2 hunks)
  • src/views/LoginPage/LoginPage.css (1 hunks)
  • src/views/LoginPage/LoginPage.jsx (1 hunks)
  • src/views/LoginPage/index.jsx (1 hunks)
  • src/views/Practice/Practice.jsx (30 hunks)
  • src/views/PracticeRedirectPage/PracticeRedirectPage.jsx (1 hunks)
  • src/views/index.js (1 hunks)
Files skipped from review due to trivial changes (16)
  • .husky/.gitignore
  • .husky/pre-commit
  • .prettierrc
  • src/components/Practice/Mechanics1.jsx
  • src/components/Practice/Mechanics5.jsx
  • src/index.css
  • src/services/callTelemetryIntract.js
  • src/services/telemetryService.js
  • src/services/utilService.js
  • src/store/sagas/handlers/user.handler.js
  • src/utils/RecordVoiceVisualizer.jsx
  • src/views/HomePage/HomePage.jsx
  • src/views/LoginPage/LoginPage.css
  • src/views/LoginPage/index.jsx
  • src/views/PracticeRedirectPage/PracticeRedirectPage.jsx
  • src/views/index.js
Additional comments not posted (143)
src/utils/constants.js (3)

Line range hint 14-14:
Good change to enhance type safety.

Changing the equality checks from loose equality (==) to strict equality (===) ensures that comparisons do not inadvertently coerce values.


Line range hint 16-16:
Potential issue with uninitialized variable skew.

Declaring skew without an initial value might lead to undefined behavior if it is not properly initialized before use.

Ensure that skew is properly initialized before it is used.


18-18: Verify the logic for filtering AllLanguages.

Ensure that the logic for filtering AllLanguages based on appLanguages is correct and that the environment variables are properly parsed.

eslintrc.json (4)

7-7: Good addition of the "prettier" plugin.

Adding the "prettier" plugin allows for the enforcement of Prettier's formatting rules alongside ESLint's linting rules.


15-15: Good addition of the "prettier/prettier" rule.

This rule will treat violations of Prettier's formatting as errors, ensuring that code adheres to both linting and formatting standards.


18-18: Good update to ecmaVersion.

Updating the ecmaVersion to 2021 aligns with the ECMAScript 2021 specification, allowing for the use of the latest JavaScript features.


25-25: Good addition of "es2021": true in env.

Adding "es2021": true indicates support for ECMAScript 2021 features.

src/utils/urlConstants.json (6)

4-4: Verify the new path for GET_MILESTONE.

Ensure that the new path "scores/getMilestone/user" is correctly handled in the application.


6-6: Verify the new path for GET_ASSESSMENT.

Ensure that the new path "v1/content/getAssessment" is correctly handled in the application.


9-9: Verify the new path for GET_SET_RESULT.

Ensure that the new path "scores/getSetResult" is correctly handled in the application.


10-10: Verify the new path for GET_PAGINATION.

Ensure that the new path "v1/content/pagination" is correctly handled in the application.


11-11: Verify the new path for UPDATE_LEARNER_PROFILE.

Ensure that the new path "scores/updateLearnerProfile" is correctly handled in the application.


12-12: Verify the new path for GET_CONTENT.

Ensure that the new path "scores/GetContent" is correctly handled in the application.

src/views/AppContent/AppContent.jsx (2)

2-10: Simplified state management by accessing virtualId from localStorage.

The change reduces dependency on Redux, which can enhance performance and reduce complexity. Ensure that localStorage access is reliable and consider potential edge cases where localStorage might not be available (e.g., in server-side rendering scenarios).


17-18: Commented out unused hooks useNavigate and useLocation.

These hooks are currently not needed. Ensure that this change does not affect any navigation logic or state management elsewhere in the application.

src/routes/index.js (3)

43-43: Added new route /level-page.

Ensure that the component reviews.HomePage is correctly implemented and integrated.


57-60: Added variables virtualId and isLogin for login state determination.

Ensure that the environment variable REACT_APP_IS_IN_APP_AUTHORISATION is correctly set and that localStorage access is reliable.


62-92: Implemented conditional routing logic based on login state.

The logic dynamically assigns routes based on the presence of virtualId and the login state. Ensure that all edge cases are handled, such as transitions between login states and potential issues with localStorage.

src/views/LoginPage/LoginPage.jsx (5)

1-7: Imported necessary libraries and components.

Ensure that all imports are necessary and correctly implemented. The CSS file LoginPage.css should be reviewed to ensure it does not introduce any issues.


8-12: Initialized state variables for username and password.

The state initialization is correct and follows best practices.


13-37: Implemented form submission logic with validation and API call.

The form submission logic includes validation, clearing localStorage, making an API call, and handling success and error cases. Ensure that the API endpoint and environment variables are correctly configured.


39-66: Rendered login form with input fields and submit button.

The form rendering is correct and follows best practices. Ensure that the CSS classes used are correctly defined in LoginPage.css.


67-80: Exported LoginPage component as default export.

The export statement is correct.

package.json (8)

90-90: Verify the reason for downgrading eslint version.

Downgrading eslint from ^8.46.0 to ^7.32.0 might reintroduce bugs or remove features. Ensure this change is intentional and verify compatibility.


91-91: LGTM! Addition of prettier.

The addition of prettier for code formatting is a good practice.


92-92: LGTM! Addition of eslint-config-prettier.

This package ensures that ESLint and Prettier work together without conflicts.


93-93: LGTM! Addition of eslint-plugin-prettier.

This plugin integrates Prettier into the ESLint workflow.


94-94: LGTM! Addition of husky.

Husky helps enforce code quality checks by managing Git hooks.


95-95: LGTM! Addition of lint-staged.

This package ensures that only staged files are linted and formatted, improving the pre-commit workflow.


99-103: LGTM! Addition of lint-staged configuration.

The configuration ensures that JavaScript and JSX files in the src directory are properly linted and formatted before commits.


105-108: LGTM! Addition of husky configuration.

The configuration ensures that the lint-staged command runs during the pre-commit hook, enforcing code quality checks.

src/utils/useAudioDetection.jsx (3)

79-86: LGTM! useEffect hook for cleanup.

The useEffect hook is well-structured and correctly cleans up the audio context when the component unmounts.


3-91: LGTM! useAudioDetection custom hook.

The custom hook is well-structured and follows best practices.


57-77: Add null checks before disconnecting nodes.

Although the function is well-structured, adding null checks before disconnecting nodes can prevent potential errors.

+    if (scriptProcessorRef.current) {
+      scriptProcessorRef.current.disconnect();
+    }
+    if (analyserRef.current) {
+      analyserRef.current.disconnect();
+    }
+    if (microphoneRef.current) {
+      microphoneRef.current.disconnect();
+    }
+    if (audioContextRef.current) {
+      audioContextRef.current.close();
+      audioContextRef.current = null;
+    }

Likely invalid or redundant comment.

src/App.js (3)

14-14: LGTM! Use of useRef for ranonce.

Using useRef for ranonce ensures that its value persists across renders without causing re-renders.


17-22: LGTM! Simplified initialization logic for did.

The simplified control flow reduces redundancy and improves readability.


53-57: LGTM! ranonce check before starting event.

The ranonce check ensures that the event is started only once, preventing unnecessary re-executions of the effect.

.github/workflows/all-dev-tn.yml (6)

1-6: Verify the branch name.

Ensure that "test" is the intended branch for deployment.


8-11: Verify the environment name.

Ensure that "all-dev-rig" is the intended environment for deployment.


13-25: Verify the Node.js version.

Ensure that Node.js version 16 is compatible with the application.


26-30: Verify AWS credentials configuration.

Ensure that the AWS credentials are correctly configured in the repository settings.


31-67: Verify environment variables.

Ensure that the environment variables used during the build process are correctly configured.


68-81: Verify Cloudfront invalidation configuration.

Ensure that the secrets used for Cloudfront invalidation are correctly configured in the repository settings.

.github/workflows/all-prod-tn.yml (6)

1-6: Verify the branch name.

Ensure that "test" is the intended branch for deployment.


8-11: Verify the environment name.

Ensure that "all-dev-rig" is the intended environment for deployment.


13-25: Verify the Node.js version.

Ensure that Node.js version 16 is compatible with the application.


26-30: Verify AWS credentials configuration.

Ensure that the AWS credentials are correctly configured in the repository settings.


31-67: Verify environment variables.

Ensure that the environment variables used during the build process are correctly configured.


68-81: Verify Cloudfront invalidation configuration.

Ensure that the secrets used for Cloudfront invalidation are correctly configured in the repository settings.

.github/workflows/all-dev-rig.yml (6)

1-6: Verify the branch name.

Ensure that "all-1.2.1" is the intended branch for deployment.


8-11: Verify the environment name.

Ensure that "all-dev-rig" is the intended environment for deployment.


13-25: Verify the Node.js version.

Ensure that Node.js version 18 is compatible with the application.


26-31: Verify AWS credentials configuration.

Ensure that the AWS credentials are correctly configured in the repository settings.


33-82: Verify environment variables.

Ensure that the environment variables used during the build process are correctly configured.


84-97: Verify Cloudfront invalidation configuration.

Ensure that the secrets used for Cloudfront invalidation are correctly configured in the repository settings.

.github/workflows/all-prod-rig.yml (11)

3-7: Verify the branch name for deployment.

Ensure that the branch name test-rig-1.1-prod is correct and intended for production deployment.


8-12: LGTM!

The job configuration looks good.


14-15: LGTM!

The step for checking out the code looks good.


17-20: LGTM!

The step for setting up Node.js looks good.


27-31: LGTM!

The step for configuring AWS credentials looks good.


33-36: LGTM!

The step for cleaning up node_modules and package-lock.json looks good.


38-39: LGTM!

The step for installing dependencies looks good.


41-42: LGTM!

The step for running Husky install looks good.


44-79: Ensure environment variables are set correctly.

Verify that all environment variables used in the build step are correctly set and have appropriate values.


81-82: LGTM!

The step for deploying to the S3 bucket looks good.


90-97: LGTM!

The step for CloudFront invalidation looks good.

.github/workflows/all-app-sandbox.yml (11)

3-7: Verify the branch name for deployment.

Ensure that the branch name all-1.1-appliance-prod is correct and intended for sandbox deployment.


8-12: LGTM!

The job configuration looks good.


14-15: LGTM!

The step for checking out the code looks good.


17-20: LGTM!

The step for setting up Node.js looks good.


27-31: LGTM!

The step for configuring AWS credentials looks good.


33-36: LGTM!

The step for cleaning up node_modules and package-lock.json looks good.


38-39: LGTM!

The step for installing dependencies looks good.


41-42: LGTM!

The step for running Husky install looks good.


44-79: Ensure environment variables are set correctly.

Verify that all environment variables used in the build step are correctly set and have appropriate values.


81-82: LGTM!

The step for deploying to the S3 bucket looks good.


90-97: LGTM!

The step for CloudFront invalidation looks good.

src/components/DiscoverEnd/DiscoverEnd.jsx (2)

55-65: LGTM!

The new function handleProfileBack is well-structured and includes error handling.


135-135: LGTM!

The onClick event handler is correctly updated to use the new handleProfileBack function.

src/utils/AudioCompare.js (7)

1-8: LGTM!

The imports and component declaration are correct.


9-13: LGTM!

The state management and custom hook usage are correct.


24-27: LGTM!

The resetRecording function is correct.


29-35: LGTM!

The handleMic function is correct.


37-41: LGTM!

The handleStop function is correct.


77-135: LGTM!

The rendering logic is correct.


138-138: LGTM!

The export statement is correct.

src/components/Mechanism/WordsOrImage.jsx (4)

48-49: LGTM!

The new props isNextButtonCalled and setIsNextButtonCalled have been added correctly.


93-93: LGTM!

The new prop setIsNextButtonCalled is passed to MainLayout correctly.


104-115: LGTM!

The conditional rendering for type has been updated to use stricter type checking correctly.


Line range hint 245-261: LGTM!

The new props isNextButtonCalled and setIsNextButtonCalled are passed to VoiceAnalyser correctly.

src/components/Practice/Mechanics4.jsx (4)

5-10: LGTM!

The removal of unused imports related to audio files and useSound hook is correct.


51-51: LGTM!

The initial state setup for words based on the type prop is correct.


75-87: LGTM!

The commenting out of audio playback logic using useSound is correct.


Line range hint 91-271: LGTM!

The equality checks and conditional rendering logic have been updated correctly.

Tools
Biome

[error] 169-186: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

src/services/telementryService.js (4)

6-6: Good use of let for block scoping.

Changing var to let for contentSessionId improves variable scoping and prevents potential issues with variable hoisting.


13-13: Good use of let for block scoping.

Changing var to let for userDetails improves variable scoping and prevents potential issues with variable hoisting.


75-75: Good addition of dspec property.

Adding the dspec property to capture the user agent string in the telemetry data is a useful enhancement.


94-114: LGTM! But verify the function usage in the codebase.

The new Log function is a valuable addition for logging telemetry data. Ensure that all function calls to Log are correctly implemented.

Verification successful

Let's verify the usage of the Log function in the identified files to ensure it matches the new signature.


Verified: Function usage matches the new signature

The Log function is used correctly in the following files:

  • src/views/Practice/Practice.jsx
  • src/components/DiscoverSentance/DiscoverSentance.jsx

The parameters passed to the Log function in both instances match the expected signature (context, pageid, telemetryMode).

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all function calls to `Log` match the new signature.

# Test: Search for the function usage. Expect: Only occurrences of the new signature.
rg --type js -A 5 $'Log'

Length of output: 8807


Script:

#!/bin/bash
# Extract lines around the usage of the `Log` function in the identified files.

# Extract lines from Practice.jsx
rg 'Log' -A 5 src/views/Practice/Practice.jsx

# Extract lines from DiscoverSentance.jsx
rg 'Log' -A 5 src/components/DiscoverSentance/DiscoverSentance.jsx

Length of output: 1275

src/components/AssesmentEnd/AssesmentEnd.jsx (5)

42-42: Good use of let for reassignment.

Changing const to let for sessionId allows for reassignment if the session ID is not initially present.


89-89: Good use of strict equality.

Changing == to === for newLevel and previousLevel enhances type safety by ensuring both value and type are considered.


109-109: Good use of strict equality.

Changing == to === for newLevel and previousLevel enhances type safety by ensuring both value and type are considered.


137-140: Good conditional positioning.

The conditional setting of the bottom and left properties based on the equality check for newLevel and previousLevel improves the control flow.


311-311: Good use of strict equality.

Changing == to === for newLevel and previousLevel enhances type safety by ensuring both value and type are considered.

src/components/DiscoverSentance/DiscoverSentance.jsx (5)

16-16: Good import of Log function.

Importing the Log function from telementryService is necessary for the new logging functionality in the component.


38-38: Good addition of state variable.

Introducing the isNextButtonCalled state variable helps manage the component's state more effectively during transitions.


51-51: Good use of strict equality.

Changing == to === for currentQuestion enhances type safety by ensuring both value and type are considered.


103-103: Good use of environment variable for flexible routing.

Checking the REACT_APP_IS_APP_IFRAME environment variable in the send function allows for more flexible routing depending on the context.


166-167: Good use of Log function for telemetry data.

Integrating the Log function to log telemetry data enhances telemetry data tracking in the component.

src/components/Practice/Mechanics3.jsx (4)

61-61: Good practice: Use strict equality check.

Changing == to === ensures strict type checking, which is a best practice in JavaScript.


99-99: Good practice: Remove commented-out code.

Removing commented-out code improves code readability and cleanliness.


Line range hint 104-118: Good practice: Use strict equality checks.

Changing == to === ensures strict type checking, which is a best practice in JavaScript.


135-138: Good practice: Use strict equality check.

Changing == to === ensures strict type checking, which is a best practice in JavaScript.

src/utils/VoiceAnalyser.js (6)

171-171: Verify the impact of commenting out setLoader(true).

Commenting out setLoader(true) might affect the loading state during audio processing. Ensure that this change does not introduce any issues.


192-201: Enhancement: Add useEffect hook for props.isNextButtonCalled.

This change enhances the component's responsiveness to prop changes by initiating a fetch operation with the base64 audio data if it's available.


204-206: Enhancement: Adjust useEffect hook for props.setIsNextButtonCalled.

This change ensures the prop is managed more effectively by resetting it to false when recordedAudioBase64 is not empty.


291-291: Enhancement: Add language parameter to handlePercentageForLife.

This change introduces language-dependent behavior in determining the percentage calculations, particularly capping the total syllables at 50 for English.


403-421: Enhancement: Update fetchASROutput to handle various states and play audio.

This change enhances the feedback mechanism in the user interface by playing audio based on the state of lives lost.


Line range hint 428-502: Enhancement: Refine handlePercentageForLife logic.

This change refines the logic for calculating the total syllables and determining the number of lives lost, enhancing the component's functionality.

src/components/Assesment/Assesment.jsx (7)

7-11: Enhancement: Add necessary imports for logout feature and tooltip.

These imports are necessary for the new logout feature and tooltip functionality.


22-22: Enhancement: Add useNavigate import.

This import is necessary for navigation functionality within the component.


94-96: Good practice: Use strict equality check.

Changing == to === ensures strict type checking, which is a best practice in JavaScript.


174-175: Improvement: Minor formatting adjustments.

These adjustments improve code readability without altering functionality.


346-350: Enhancement: Update handleProfileBack function for better navigation logic.

This change improves navigation logic by handling different application states more effectively.


357-361: Enhancement: Add handleLogout function.

This change introduces a logout feature, enhancing the functionality of the component.


Line range hint 363-535: Enhancement: Add styled components and tooltip for logout button.

These changes enhance the user experience by providing a styled logout button with a tooltip.

src/views/Practice/Practice.jsx (12)

59-60: State Management Enhancements Approved

The new state variables fluency and isNextButtonCalled improve the explicit representation and tracking of the component's state.


69-71: Browser Check Function Approved

The isFirefox function correctly checks if the browser is Firefox.


72-75: Initialization Logic Approved

The useEffect hook correctly initializes livesData when startShowCase is true.


Line range hint 89-97: Practice Step Completion Logic Approved

The useEffect hook correctly handles actions when a practice step is completed.


Line range hint 98-101: Showcase Session Initialization Approved

The useEffect hook correctly sets a unique sub-session ID when isShowCase is true.


116-125: Voice Text Handling Approved

The useEffect hook provides user-friendly error messages and handles success states appropriately for voiceText.


Line range hint 133-137: Score Posting Logic Approved

The send function correctly posts a score message to the parent window when the app is in an iframe.


156-156: Fluency Check Logic Approved

The checkFluency function correctly sets the fluency state based on content type and fluency score.


Line range hint 158-582: Next Step Handling Logic Approved

The handleNext function includes comprehensive logic for progressing to the next practice step or handling game over states, with robust error handling and state updates.


Line range hint 600-707: Word Highlighting Logic Approved

The highlightWords function effectively highlights matched words in a sentence, enhancing the user experience.


710-714: Message Length Posting Logic Approved

The useEffect hook correctly posts message lengths to the parent window when the app is in an iframe.


Line range hint 726-876: Dynamic Mechanic Rendering Approved

The renderMechanics function dynamically renders different components based on the mechanism state, enhancing flexibility and maintainability.

src/components/Layouts.jsx/MainLayout.jsx (6)

1-1: Import Statement Adjustments Approved

The removal of unused imports improves code maintainability and reduces potential clutter.


104-104: UI Simplification Approved

Commenting out the showScore prop suggests a simplification of the UI or preparation for further modifications.


202-204: Strict Equality Checks Approved

Updating comparison operators to === enhances type safety and ensures consistent behavior.


270-282: Styling Updates Approved

The updates to the sx prop improve the component's responsiveness and visual presentation.


546-552: Conditional Behavior Enhancement Approved

The modification to the onClick handler for the NextButton adds a layer of conditional behavior, enhancing the application's flow control.


715-733: Percentage Display Adjustment Approved

The adjustment ensures the percentage display does not show negative values, preventing potential UI issues.

Comment on lines +12 to +55
const startDetection = async () => {
try {
// Initialize audio context and analyser
audioContextRef.current = new (window.AudioContext || window.webkitAudioContext)();
analyserRef.current = audioContextRef.current.createAnalyser();
analyserRef.current.fftSize = 2048;

// Get user media
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
microphoneRef.current = audioContextRef.current.createMediaStreamSource(stream);

// Create script processor
scriptProcessorRef.current = audioContextRef.current.createScriptProcessor(1024, 1, 1);

// Connect nodes
microphoneRef.current.connect(analyserRef.current);
analyserRef.current.connect(scriptProcessorRef.current);
scriptProcessorRef.current.connect(audioContextRef.current.destination);

// Process audio data
scriptProcessorRef.current.onaudioprocess = (event) => {
const inputData = event.inputBuffer.getChannelData(0);
const inputDataLength = inputData.length;
let total = 0;

for (let i = 0; i < inputDataLength; i++) {
total += Math.abs(inputData[i]);
}

const average = total / inputDataLength;
const currentIsSilent = average < 0.04; // Threshold for silence

if (!currentIsSilent) {
setAudioDetected(true);
}

setIsSilent(currentIsSilent);
};

setIsRunning(true);
} catch (error) {
console.error('Error accessing microphone:', error);
}
};
Copy link

Choose a reason for hiding this comment

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

Add error handling for all operations.

The startDetection function lacks error handling for some operations, such as creating the script processor and connecting nodes.

+    if (!audioContextRef.current) {
+      console.error('Error initializing audio context');
+      return;
+    }
+    if (!analyserRef.current) {
+      console.error('Error creating analyser');
+      return;
+    }
+    if (!microphoneRef.current) {
+      console.error('Error accessing microphone');
+      return;
+    }
+    if (!scriptProcessorRef.current) {
+      console.error('Error creating script processor');
+      return;
+    }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const startDetection = async () => {
try {
// Initialize audio context and analyser
audioContextRef.current = new (window.AudioContext || window.webkitAudioContext)();
analyserRef.current = audioContextRef.current.createAnalyser();
analyserRef.current.fftSize = 2048;
// Get user media
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
microphoneRef.current = audioContextRef.current.createMediaStreamSource(stream);
// Create script processor
scriptProcessorRef.current = audioContextRef.current.createScriptProcessor(1024, 1, 1);
// Connect nodes
microphoneRef.current.connect(analyserRef.current);
analyserRef.current.connect(scriptProcessorRef.current);
scriptProcessorRef.current.connect(audioContextRef.current.destination);
// Process audio data
scriptProcessorRef.current.onaudioprocess = (event) => {
const inputData = event.inputBuffer.getChannelData(0);
const inputDataLength = inputData.length;
let total = 0;
for (let i = 0; i < inputDataLength; i++) {
total += Math.abs(inputData[i]);
}
const average = total / inputDataLength;
const currentIsSilent = average < 0.04; // Threshold for silence
if (!currentIsSilent) {
setAudioDetected(true);
}
setIsSilent(currentIsSilent);
};
setIsRunning(true);
} catch (error) {
console.error('Error accessing microphone:', error);
}
};
const startDetection = async () => {
try {
// Initialize audio context and analyser
audioContextRef.current = new (window.AudioContext || window.webkitAudioContext)();
analyserRef.current = audioContextRef.current.createAnalyser();
analyserRef.current.fftSize = 2048;
if (!audioContextRef.current) {
console.error('Error initializing audio context');
return;
}
if (!analyserRef.current) {
console.error('Error creating analyser');
return;
}
// Get user media
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
microphoneRef.current = audioContextRef.current.createMediaStreamSource(stream);
if (!microphoneRef.current) {
console.error('Error accessing microphone');
return;
}
// Create script processor
scriptProcessorRef.current = audioContextRef.current.createScriptProcessor(1024, 1, 1);
if (!scriptProcessorRef.current) {
console.error('Error creating script processor');
return;
}
// Connect nodes
microphoneRef.current.connect(analyserRef.current);
analyserRef.current.connect(scriptProcessorRef.current);
scriptProcessorRef.current.connect(audioContextRef.current.destination);
// Process audio data
scriptProcessorRef.current.onaudioprocess = (event) => {
const inputData = event.inputBuffer.getChannelData(0);
const inputDataLength = inputData.length;
let total = 0;
for (let i = 0; i < inputDataLength; i++) {
total += Math.abs(inputData[i]);
}
const average = total / inputDataLength;
const currentIsSilent = average < 0.04; // Threshold for silence
if (!currentIsSilent) {
setAudioDetected(true);
}
setIsSilent(currentIsSilent);
};
setIsRunning(true);
} catch (error) {
console.error('Error accessing microphone:', error);
}
};

Comment on lines +22 to +25
- name: Install AWS CLI
run: |
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y awscli
Copy link

Choose a reason for hiding this comment

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

Optimize the AWS CLI installation step.

Consider combining the apt-get update and apt-get install commands to reduce the number of layers in the Docker image.

- sudo DEBIAN_FRONTEND=noninteractive apt-get update
- sudo DEBIAN_FRONTEND=noninteractive apt-get install -y awscli
+ sudo DEBIAN_FRONTEND=noninteractive apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y awscli
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Install AWS CLI
run: |
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y awscli
- name: Install AWS CLI
run: |
sudo DEBIAN_FRONTEND=noninteractive apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y awscli

Comment on lines +84 to +88
- name: Debug Environment Variables
run: |
echo "REACT_APP_AWS_S3_BUCKET_NAME: $REACT_APP_AWS_S3_BUCKET_NAME"
echo "AWS_REGION: $AWS_REGION"
echo "secrate": ${{ vars.REACT_APP_AWS_S3_BUCKET_NAME }}
Copy link

Choose a reason for hiding this comment

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

Remove sensitive information from debug logs.

Avoid printing sensitive information such as environment variables in the debug logs.

- echo "secrate": ${{ vars.REACT_APP_AWS_S3_BUCKET_NAME }}
+ echo "REACT_APP_AWS_S3_BUCKET_NAME: [REDACTED]"
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Debug Environment Variables
run: |
echo "REACT_APP_AWS_S3_BUCKET_NAME: $REACT_APP_AWS_S3_BUCKET_NAME"
echo "AWS_REGION: $AWS_REGION"
echo "secrate": ${{ vars.REACT_APP_AWS_S3_BUCKET_NAME }}
- name: Debug Environment Variables
run: |
echo "REACT_APP_AWS_S3_BUCKET_NAME: $REACT_APP_AWS_S3_BUCKET_NAME"
echo "AWS_REGION: $AWS_REGION"
echo "REACT_APP_AWS_S3_BUCKET_NAME: [REDACTED]"

Comment on lines +17 to +22
var did;
if (localStorage.getItem('fpDetails_v2') !== null) {
let fpDetails_v2 = localStorage.getItem('fpDetails_v2');
var did = fpDetails_v2.result;
did = fpDetails_v2.result;
} else {
var did = localStorage.getItem('did');
did = localStorage.getItem('did');
Copy link

Choose a reason for hiding this comment

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

Use let or const instead of var.

Using var can lead to unexpected behavior due to its function scope. Use let or const for block scope.

-    var did;
+    let did;
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var did;
if (localStorage.getItem('fpDetails_v2') !== null) {
let fpDetails_v2 = localStorage.getItem('fpDetails_v2');
var did = fpDetails_v2.result;
did = fpDetails_v2.result;
} else {
var did = localStorage.getItem('did');
did = localStorage.getItem('did');
let did;
if (localStorage.getItem('fpDetails_v2') !== null) {
let fpDetails_v2 = localStorage.getItem('fpDetails_v2');
did = fpDetails_v2.result;
} else {
did = localStorage.getItem('did');

Comment on lines +22 to +25
- name: Install AWS CLI
run: |
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y awscli
Copy link

Choose a reason for hiding this comment

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

Optimize the AWS CLI installation step.

Consider combining the apt-get update and apt-get install commands to reduce the number of layers in the Docker image.

- sudo DEBIAN_FRONTEND=noninteractive apt-get update
- sudo DEBIAN_FRONTEND=noninteractive apt-get install -y awscli
+ sudo DEBIAN_FRONTEND=noninteractive apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y awscli
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Install AWS CLI
run: |
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y awscli
- name: Install AWS CLI
run: |
sudo DEBIAN_FRONTEND=noninteractive apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y awscli

Comment on lines +15 to +22
const controlAudio = async (status) => {
if (status === "recording") {
await startDetection();
} else {
document.getElementById("startaudio_compair").click();
stopDetection();
}
setStatus(status);
};
Copy link

Choose a reason for hiding this comment

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

Add error handling for async operations.

The controlAudio function is correct but ensure proper error handling for async operations.

-  const controlAudio = async (status) => {
-    if (status === "recording") {
-      await startDetection();
-    } else {
-      stopDetection();
-    }
-    setStatus(status);
-  };
+  const controlAudio = async (status) => {
+    try {
+      if (status === "recording") {
+        await startDetection();
+      } else {
+        stopDetection();
+      }
+      setStatus(status);
+    } catch (error) {
+      console.error("Error controlling audio:", error);
+    }
+  };
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const controlAudio = async (status) => {
if (status === "recording") {
await startDetection();
} else {
document.getElementById("startaudio_compair").click();
stopDetection();
}
setStatus(status);
};
const controlAudio = async (status) => {
try {
if (status === "recording") {
await startDetection();
} else {
stopDetection();
}
setStatus(status);
} catch (error) {
console.error("Error controlling audio:", error);
}
};

Comment on lines +84 to +88
- name: Debug Environment Variables
run: |
echo "REACT_APP_AWS_S3_BUCKET_NAME: $REACT_APP_AWS_S3_BUCKET_NAME"
echo "AWS_REGION: $AWS_REGION"
echo "secrate": ${{ vars.REACT_APP_AWS_S3_BUCKET_NAME }}
Copy link

Choose a reason for hiding this comment

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

Remove sensitive information from debug logs.

Avoid printing sensitive information such as environment variables in the debug logs.

- echo "secrate": ${{ vars.REACT_APP_AWS_S3_BUCKET_NAME }}
+ echo "REACT_APP_AWS_S3_BUCKET_NAME: [REDACTED]"
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Debug Environment Variables
run: |
echo "REACT_APP_AWS_S3_BUCKET_NAME: $REACT_APP_AWS_S3_BUCKET_NAME"
echo "AWS_REGION: $AWS_REGION"
echo "secrate": ${{ vars.REACT_APP_AWS_S3_BUCKET_NAME }}
- name: Debug Environment Variables
run: |
echo "REACT_APP_AWS_S3_BUCKET_NAME: $REACT_APP_AWS_S3_BUCKET_NAME"
echo "AWS_REGION: $AWS_REGION"
echo "REACT_APP_AWS_S3_BUCKET_NAME: [REDACTED]"

Comment on lines +44 to +75
const audioProps = {
audioType,
status,
audioSrc,
timeslice: 1000,
startCallback: (e) => {
setAudioSrc("");
setRecordingInitialized(true);
props.setRecordedAudio("");
},
pauseCallback: (e) => {},
stopCallback: (e) => {
const temp_audioSrc = window.URL.createObjectURL(e);
setAudioSrc(temp_audioSrc);
if (!audioDetected) {
props?.setOpenMessageDialog({
message: "Please Speak Louder and Clear",
isError: true,
});
},
pauseCallback: (e) => {},
stopCallback: (e) => {
let temp_audioSrc = window.URL.createObjectURL(e);
this.setState({
audioSrc: temp_audioSrc,
});

if (!this.props.isAudioPreprocessing) {
this.props.setRecordedAudio(temp_audioSrc);
} else {
if (this.state.soundDetected) {
this.props.setRecordedAudio(temp_audioSrc);
} else {
// this.props.setRecordedAudio(temp_audioSrc);
this.props?.setOpenMessageDialog({
message: "Please Speak Louder and Clear",
isError: true,
});
}
if (props.setEnableNext) {
props.setEnableNext(false);
}
} else {
props.setRecordedAudio(temp_audioSrc);
}
setRecordingInitialized(false);
},
onRecordCallback: (e) => {},
errorCallback: (err) => {},
backgroundColor: "hsla(0, 100%, 0%, 0)",
strokeColor: "#73DD24",
};
Copy link

Choose a reason for hiding this comment

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

Add error handling in callbacks.

The audioProps object is correct but ensure proper error handling in callbacks.

-  const audioProps = {
-    audioType,
-    status,
-    audioSrc,
-    timeslice: 1000,
-    startCallback: (e) => {
-      setAudioSrc("");
-      setRecordingInitialized(true);
-      props.setRecordedAudio("");
-    },
-    pauseCallback: (e) => {},
-    stopCallback: (e) => {
-      const temp_audioSrc = window.URL.createObjectURL(e);
-      setAudioSrc(temp_audioSrc);
-      if (!audioDetected) {
-        props?.setOpenMessageDialog({
-          message: "Please Speak Louder and Clear",
-          isError: true,
-        });
-        if (props.setEnableNext) {
-          props.setEnableNext(false);
-        }
-      } else {
-        props.setRecordedAudio(temp_audioSrc);
-      }
-      setRecordingInitialized(false);
-    },
-    onRecordCallback: (e) => {},
-    errorCallback: (err) => {},
-    backgroundColor: "hsla(0, 100%, 0%, 0)",
-    strokeColor: "#73DD24",
-  };
+  const audioProps = {
+    audioType,
+    status,
+    audioSrc,
+    timeslice: 1000,
+    startCallback: (e) => {
+      try {
+        setAudioSrc("");
+        setRecordingInitialized(true);
+        props.setRecordedAudio("");
+      } catch (error) {
+        console.error("Error in startCallback:", error);
+      }
+    },
+    pauseCallback: (e) => {},
+    stopCallback: (e) => {
+      try {
+        const temp_audioSrc = window.URL.createObjectURL(e);
+        setAudioSrc(temp_audioSrc);
+        if (!audioDetected) {
+          props?.setOpenMessageDialog({
+            message: "Please Speak Louder and Clear",
+            isError: true,
+          });
+          if (props.setEnableNext) {
+            props.setEnableNext(false);
+          }
+        } else {
+          props.setRecordedAudio(temp_audioSrc);
+        }
+        setRecordingInitialized(false);
+      } catch (error) {
+        console.error("Error in stopCallback:", error);
+      }
+    },
+    onRecordCallback: (e) => {},
+    errorCallback: (err) => {
+      console.error("Error in audioProps:", err);
+    },
+    backgroundColor: "hsla(0, 100%, 0%, 0)",
+    strokeColor: "#73DD24",
+  };
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const audioProps = {
audioType,
status,
audioSrc,
timeslice: 1000,
startCallback: (e) => {
setAudioSrc("");
setRecordingInitialized(true);
props.setRecordedAudio("");
},
pauseCallback: (e) => {},
stopCallback: (e) => {
const temp_audioSrc = window.URL.createObjectURL(e);
setAudioSrc(temp_audioSrc);
if (!audioDetected) {
props?.setOpenMessageDialog({
message: "Please Speak Louder and Clear",
isError: true,
});
},
pauseCallback: (e) => {},
stopCallback: (e) => {
let temp_audioSrc = window.URL.createObjectURL(e);
this.setState({
audioSrc: temp_audioSrc,
});
if (!this.props.isAudioPreprocessing) {
this.props.setRecordedAudio(temp_audioSrc);
} else {
if (this.state.soundDetected) {
this.props.setRecordedAudio(temp_audioSrc);
} else {
// this.props.setRecordedAudio(temp_audioSrc);
this.props?.setOpenMessageDialog({
message: "Please Speak Louder and Clear",
isError: true,
});
}
if (props.setEnableNext) {
props.setEnableNext(false);
}
} else {
props.setRecordedAudio(temp_audioSrc);
}
setRecordingInitialized(false);
},
onRecordCallback: (e) => {},
errorCallback: (err) => {},
backgroundColor: "hsla(0, 100%, 0%, 0)",
strokeColor: "#73DD24",
};
const audioProps = {
audioType,
status,
audioSrc,
timeslice: 1000,
startCallback: (e) => {
try {
setAudioSrc("");
setRecordingInitialized(true);
props.setRecordedAudio("");
} catch (error) {
console.error("Error in startCallback:", error);
}
},
pauseCallback: (e) => {},
stopCallback: (e) => {
try {
const temp_audioSrc = window.URL.createObjectURL(e);
setAudioSrc(temp_audioSrc);
if (!audioDetected) {
props?.setOpenMessageDialog({
message: "Please Speak Louder and Clear",
isError: true,
});
if (props.setEnableNext) {
props.setEnableNext(false);
}
} else {
props.setRecordedAudio(temp_audioSrc);
}
setRecordingInitialized(false);
} catch (error) {
console.error("Error in stopCallback:", error);
}
},
onRecordCallback: (e) => {},
errorCallback: (err) => {
console.error("Error in audioProps:", err);
},
backgroundColor: "hsla(0, 100%, 0%, 0)",
strokeColor: "#73DD24",
};

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.

4 participants