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

WIP: HackStack added to Teacher Dashboard #7437

Merged
merged 15 commits into from
May 30, 2024
Merged

Conversation

adamkecskes
Copy link
Collaborator

@adamkecskes adamkecskes commented May 10, 2024

AI PR: https://github.com/codecombat/ai/pull/244
Backend PR: https://github.com/codecombat/codecombat-server/pull/914

teacher student
teacher-ai student-ai

Summary by CodeRabbit

  • New Features

    • Introduced AI scenario fetching based on various criteria.
    • Added state management and actions for AI projects in classroom settings.
    • Enabled management of released AI scenarios.
  • Enhancements

    • Updated campaign and course IDs including new seasons and their details.
    • Added new properties to schemas for AI projects and classrooms.
    • Enhanced teacher dashboard components with new props and updated logic.
  • Localization

    • Updated key-value pairs for improved translations and messages.

Copy link

coderabbitai bot commented May 24, 2024

Walkthrough

Recent updates introduce new functionalities and enhancements across various modules, primarily focusing on AI scenarios and projects. These changes include new API functions, state management updates, schema modifications, and UI enhancements for the teacher dashboard. Additionally, new campaign IDs, course IDs, and seasons have been added to the utility functions, reflecting the evolving landscape of AI tools and educational content.

Changes

File Path Change Summary
app/core/api/ai_scenarios.js Added functions for fetching AI scenarios based on different criteria.
app/core/store/modules/aiProjects.js Introduced state management, mutations, getters, and actions for managing AI projects.
app/core/store/modules/aiScenarios.js Added state management, getters, mutations, and actions for fetching released scenarios.
app/core/store/modules/teacherDashboard.js Added new functions and updated dispatch calls for AI projects and scenarios management.
app/core/utils.js Added new campaign and course IDs, updated season details, and added AI tool mappings.
app/locale/en.js Added and modified key-value pairs for various UI texts.
app/schemas/models/ai_project.schema.js Added wrongChoices property to the AIProjectSchema.
app/schemas/models/classroom.schema.js Added lockedScenarioLevels property to the ClassroomSchema.
.../teacher-dashboard/BaseSingleClass/index.vue Updated props, computed properties, and methods for handling HACKSTACK course instances.
.../teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue Updated prop, method, template, and CSS for TableModuleHeader.vue.

Poem

In the realm of code, where logic thrives,
AI scenarios and projects now arrive.
With schemas enhanced and dashboards bright,
Courses and seasons set alight.
Teachers guide with newfound grace,
As students embark on a learning race.
🐇✨


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 Configration 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

@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: 12

Outside diff range and nitpick comments (14)
ozaria/site/store/TeacherDashboardPanel.js (1)

Line range hint 371-371: Optimize array operations by using .flatMap() instead of .map().flat().

-          ...(content.goals || []), ...(content.additionalGoals || []).map(({ goals }) => goals).flat()
+          ...(content.goals || []), ...(content.additionalGoals || []).flatMap(({ goals }) => goals)
ozaria/site/components/teacher-dashboard/BaseSingleClass/index.vue (1)

49-51: Add a description for the defaultCourseId prop.

It's good practice to include a comment describing the purpose and usage of each prop, especially for new ones like defaultCourseId. This helps maintainability and understanding for other developers.

app/core/Router.js (4)

Line range hint 30-30: Consider replacing the delete operator with setting window.alreadyLoadedView to null or undefined.

This can help improve performance as delete can have a negative impact on object performance in JavaScript.

Also applies to: 47-47, 56-56, 60-60, 65-65


Line range hint 152-152: Simplify computed expressions to enhance readability and potentially improve performance.

For example, instead of using string literals for paths or keys, consider using constants or direct references if applicable.

Also applies to: 233-233, 274-274, 278-278, 282-282, 286-286, 290-290, 294-294, 302-302, 316-316


Line range hint 71-73: Consider removing unnecessary else clauses to simplify control flow.

This can make the code cleaner and easier to follow, especially in complex conditional structures.

Also applies to: 236-245, 342-347


Line range hint 242-242: Use template literals instead of string concatenation for better readability and modern JavaScript practices.

- window.location.href = 'https://docs.google.com/presentation/d/' + someVariable + '/edit?usp=sharing'
+ window.location.href = `https://docs.google.com/presentation/d/${someVariable}/edit?usp=sharing`
app/core/utils.js (8)

Line range hint 14-15: Declare variables separately for better readability and maintainability.

- let campaignIDs, compare, courseIDs, courseModules, courseModuleInfo, courseModuleLevels, coursesWithProjects, CSCourseIDs, freeCampaignIds, hourOfCodeOptions, injectCSS, internalCampaignIds, left, orderedCourseIDs, otherCourseIDs, otherOrderedCourseIDs, replaceText, slugify, WDCourseIDs
+ let campaignIDs;
+ let compare;
+ let courseIDs;
+ let courseModules;
+ let courseModuleInfo;
+ let courseModuleLevels;
+ let coursesWithProjects;
+ let CSCourseIDs;
+ let freeCampaignIds;
+ let hourOfCodeOptions;
+ let injectCSS;
+ let internalCampaignIds;
+ let left;
+ let orderedCourseIDs;
+ let otherCourseIDs;
+ let otherOrderedCourseIDs;
+ let replaceText;
+ let slugify;
+ let WDCourseIDs;

Line range hint 16-16: Avoid assignments within expressions for clarity and to prevent unintended side effects.

- const product = ((left = typeof COCO_PRODUCT !== 'undefined' && COCO_PRODUCT !== null ? COCO_PRODUCT : __guard__(typeof process !== 'undefined' && process !== null ? process.env : undefined, x => x.COCO_PRODUCT))) != null ? left : 'codecombat'
+ let left = typeof COCO_PRODUCT !== 'undefined' && COCO_PRODUCT !== null ? COCO_PRODUCT : __guard__(typeof process !== 'undefined' && process !== null ? process.env : undefined, x => x.COCO_PRODUCT);
+ const product = left != null ? left : 'codecombat';

- const shaTag = ((left = typeof SHA_TAG !== 'undefined' && SHA_TAG !== null ? SHA_TAG : __guard__(typeof process !== 'undefined' && process !== null ? process.env : undefined, x => x.SHA_TAG))) != null ? left : 'unknown'
+ left = typeof SHA_TAG !== 'undefined' && SHA_TAG !== null ? SHA_TAG : __guard__(typeof process !== 'undefined' && process !== null ? process.env : undefined, x => x.SHA_TAG);
+ const shaTag = left != null ? left : 'unknown';

Also applies to: 17-17


Line range hint 25-25: Use optional chaining to simplify null checks.

- if (global && global._ && global._.str && global._.str.slugify) {
+ if (global?._?.str?.slugify) {

- } else if (_ && _.string && _.string.slugify) {
+ } else if (_?.string?.slugify) {

Also applies to: 29-29


Line range hint 43-47: These else clauses can be omitted because previous branches break early, simplifying the control flow.

- } else {
-   // IE has no __proto__. TODO: does this even work? At most it doesn't crash.
-   obj = Object.getPrototypeOf(obj)
- }

Also applies to: 45-47


Line range hint 40-48: Convert this function expression to an arrow function for better readability and to take advantage of lexical this.

- const combineAncestralObject = function (obj, propertyName) {
+ const combineAncestralObject = (obj, propertyName) => {

Line range hint 55-55: Use template literals for string concatenation to improve readability.

- return $.i18n.t('general.player') + ' ' + (Math.abs(hashString(id)) % 10000)
+ return `${$.i18n.t('general.player')} ${Math.abs(hashString(id)) % 10000}`;

Line range hint 50-60: Convert these function expressions to arrow functions to improve readability and consistency.

- var clone = function (obj) {
+ const clone = (obj) => {

Also applies to: 62-67, 69-76, 78-94, 98-112, 194-202, 204-207, 209-214


Line range hint 1104-1104: Avoid assignments within expressions to enhance clarity and maintainability.

- return (done = function (success) {
+ const done = function (success) {
+ return done;
Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between a6a6f5c and 393bffc.
Files selected for processing (29)
  • app/core/Router.js (1 hunks)
  • app/core/api/ai_projects.js (1 hunks)
  • app/core/api/ai_scenarios.js (1 hunks)
  • app/core/api/index.js (1 hunks)
  • app/core/store/index.js (1 hunks)
  • app/core/store/modules/aiProjects.js (1 hunks)
  • app/core/store/modules/aiScenarios.js (1 hunks)
  • app/core/store/modules/courseInstances.js (1 hunks)
  • app/core/store/modules/teacherDashboard.js (2 hunks)
  • app/core/urls.js (2 hunks)
  • app/core/utils.js (4 hunks)
  • app/core/vueRouter.js (1 hunks)
  • app/locale/en.js (2 hunks)
  • app/models/ClassroomLib.js (1 hunks)
  • app/schemas/models/ai_project.schema.js (1 hunks)
  • app/schemas/models/classroom.schema.js (1 hunks)
  • app/templates/courses/courses-view.pug (2 hunks)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/index.vue (8 hunks)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/LockOrSkip.vue (8 hunks)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableClassFrame.vue (1 hunks)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleGrid.vue (3 hunks)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue (5 hunks)
  • ozaria/site/components/teacher-dashboard/Panel/components/AiProject.vue (1 hunks)
  • ozaria/site/components/teacher-dashboard/Panel/components/AiScenario.stories.js (1 hunks)
  • ozaria/site/components/teacher-dashboard/Panel/components/AiScenario.vue (1 hunks)
  • ozaria/site/components/teacher-dashboard/Panel/index.vue (5 hunks)
  • ozaria/site/components/teacher-dashboard/common/SecondaryTeacherNavigation.vue (4 hunks)
  • ozaria/site/store/BaseSingleClass.js (1 hunks)
  • ozaria/site/store/TeacherDashboardPanel.js (5 hunks)
Files skipped from review due to trivial changes (2)
  • app/core/api/index.js
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleGrid.vue
Additional Context Used
Biome (86)
app/core/Router.js (20)

30-30: Avoid the delete operator which can impact performance.


41-41: Using this in a static context can be confusing.


47-47: Avoid the delete operator which can impact performance.


56-56: Avoid the delete operator which can impact performance.


60-60: Avoid the delete operator which can impact performance.


65-65: Avoid the delete operator which can impact performance.


71-73: This else clause can be omitted because previous branches break early.


152-152: The computed expression can be simplified without the use of a string literal.


233-233: The computed expression can be simplified without the use of a string literal.


236-245: This else clause can be omitted because previous branches break early.


242-242: Template literals are preferred over string concatenation.


274-274: The computed expression can be simplified without the use of a string literal.


278-278: The computed expression can be simplified without the use of a string literal.


282-282: The computed expression can be simplified without the use of a string literal.


286-286: The computed expression can be simplified without the use of a string literal.


290-290: The computed expression can be simplified without the use of a string literal.


294-294: The computed expression can be simplified without the use of a string literal.


302-302: The computed expression can be simplified without the use of a string literal.


316-316: The computed expression can be simplified without the use of a string literal.


342-347: This else clause can be omitted because previous branches break early.

app/core/api/ai_scenarios.js (4)

13-13: Template literals are preferred over string concatenation.


5-5: Reassigning a function parameter is confusing.


10-10: Reassigning a function parameter is confusing.


19-19: Reassigning a function parameter is confusing.

app/core/store/index.js (4)

24-24: The assignment should not be in an expression.


28-28: The assignment should not be in an expression.


30-30: The assignment should not be in an expression.


46-46: This property value named classrooms is later overwritten by an object member with the same name.

app/core/store/modules/aiProjects.js (4)

58-58: Change to an optional chain.


61-61: Change to an optional chain.


80-80: Template literals are preferred over string concatenation.


113-113: Change to an optional chain.

app/core/store/modules/aiScenarios.js (2)

20-20: Prefer for...of instead of forEach.


26-26: Reassigning a function parameter is confusing.

app/core/store/modules/courseInstances.js (8)

25-25: Use === instead of ==.
== is only allowed when comparing against null


88-88: Template literals are preferred over string concatenation.


125-125: Template literals are preferred over string concatenation.


195-199: This function expression can be turned into an arrow function.


204-207: This function expression can be turned into an arrow function.


256-256: The catch clause that only rethrows the original error is redundant.


263-263: Do not use template literals if interpolation and special-character handling are not needed.


290-297: Prefer for...of instead of forEach.

app/core/store/modules/teacherDashboard.js (15)

83-85: This else clause can be omitted because previous branches break early.


90-92: This else clause can be omitted because previous branches break early.


97-99: This else clause can be omitted because previous branches break early.


111-113: This else clause can be omitted because previous branches break early.


127-137: This else clause can be omitted because previous branches break early.


135-135: Change to an optional chain.


167-169: This else clause can be omitted because previous branches break early.


174-176: This else clause can be omitted because previous branches break early.


250-250: Change to an optional chain.


251-256: Prefer for...of instead of forEach.


253-253: Change to an optional chain.


357-360: Prefer for...of instead of forEach.


399-401: Prefer for...of instead of forEach.


419-419: Change to an optional chain.


423-423: Change to an optional chain.

app/core/utils.js (20)

14-15: Declare variables separately


16-16: The assignment should not be in an expression.


17-17: The assignment should not be in an expression.


25-25: Change to an optional chain.


29-29: Change to an optional chain.


43-47: This else clause can be omitted because previous branches break early.


45-47: This else clause can be omitted because previous branches break early.


40-48: This function expression can be turned into an arrow function.


55-55: Template literals are preferred over string concatenation.


50-60: This function expression can be turned into an arrow function.


66-66: Template literals are preferred over string concatenation.


62-67: This function expression can be turned into an arrow function.


69-76: This function expression can be turned into an arrow function.


78-94: This function expression can be turned into an arrow function.


98-112: This function expression can be turned into an arrow function.


194-202: This function expression can be turned into an arrow function.


204-207: This function expression can be turned into an arrow function.


212-212: The assignment should not be in an expression.


209-214: This function expression can be turned into an arrow function.


1104-1104: The assignment should not be in an expression.

app/core/vueRouter.js (5)

114-116: This else clause can be omitted because previous branches break early.


124-126: This else clause can be omitted because previous branches break early.


134-136: This else clause can be omitted because previous branches break early.


231-233: This else clause can be omitted because previous branches break early.


245-247: This else clause can be omitted because previous branches break early.

app/locale/en.js (1)

606-606: Do not add then to an object.

app/models/ClassroomLib.js (1)

52-54: Prefer for...of instead of forEach.

ozaria/site/store/TeacherDashboardPanel.js (2)

313-313: Declare variables separately


371-371: The call chain .map().flat() can be replaced with a single .flatMap() call.

Additional comments not posted (36)
app/core/api/ai_projects.js (1)

5-5: Ensure lodash or underscore is available for _.merge.

Verification successful

Lodash is imported in various parts of the project and is listed as a dependency in package.json. Therefore, the use of _.merge in app/core/api/ai_projects.js should not cause any runtime issues.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify lodash or underscore is imported or available globally.

# Test: Search for lodash or underscore import in the project.
rg --type js 'require(.lodash.|.underscore.)'

Length of output: 47



Script:

#!/bin/bash
# Description: Verify lodash or underscore is imported or available globally.

# Test 1: Search for lodash or underscore ES6 imports in the project.
rg --type js "import .* from ['\"]lodash['\"]"
rg --type js "import .* from ['\"]underscore['\"]"

# Test 2: Check if lodash or underscore is listed in package.json dependencies.
jq '.dependencies | has("lodash") or has("underscore")' package.json

Length of output: 2339

ozaria/site/components/teacher-dashboard/Panel/components/AiScenario.vue (1)

1-38: The component structure and logic are well-implemented.

ozaria/site/components/teacher-dashboard/Panel/components/AiScenario.stories.js (1)

1-56: Storybook configuration for AiScenario is correctly set up.

ozaria/site/components/teacher-dashboard/Panel/components/AiProject.vue (1)

1-64: The AiProject component is well-implemented with efficient use of computed properties.

app/core/urls.js (1)

51-53: LGTM! The new URL handling for the HACKSTACK course is correctly implemented.

app/core/store/index.js (1)

78-80: LGTM! The addition of lowUsageUsers, aiScenarios, and aiProjects modules to the Vuex store is correctly implemented.

app/models/ClassroomLib.js (1)

40-42: LGTM! The addition of lockedScenarioLevels to the student lock map is correctly implemented.

ozaria/site/components/teacher-dashboard/Panel/index.vue (4)

4-4: Ensure AiScenario component is properly imported and used.

Also applies to: 24-25


Line range hint 4-114: Overall, the integration of the AiScenario component and related changes appear to be well-implemented. Ensure all related data and methods are correctly set up in the Vuex store and other parts of the application.


36-37: Confirm that panelProjectContent is correctly defined and used in Vuex store.

Verification successful

The panelProjectContent is defined and used in the Vuex store as well as in the Vue component. Here are the relevant locations:

  • Vuex Store Definition and Usage:

    • ozaria/site/store/TeacherDashboardPanel.js
      • panelProjectContent: undefined
      • state.panelProjectContent = projectContentObject
      • state.panelProjectContent = undefined
      • panelProjectContent (state) { return state.panelProjectContent }
  • Vue Component Usage:

    • ozaria/site/components/teacher-dashboard/Panel/index.vue
      • panelProjectContent: 'teacherDashboardPanel/panelProjectContent'
      • v-if="panelProjectContent && panelProjectContent.aiScenario"
      • :ai-scenario="panelProjectContent.aiScenario"
      • :ai-projects="panelProjectContent.aiProjects"

The panelProjectContent is correctly defined in the Vuex store and mapped in the Vue component.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the Vuex store configuration for `panelProjectContent`.

# Test: Search for the Vuex store configuration. Expect: Definition of `panelProjectContent`.
rg --type vue $'panelProjectContent'

Length of output: 63



Script:

#!/bin/bash
# Description: Verify the Vuex store configuration for `panelProjectContent`.

# Test: Search for the Vuex store configuration. Expect: Definition of `panelProjectContent`.
rg 'panelProjectContent'

Length of output: 922


110-114: Check the conditional rendering logic and data bindings for ai-scenario component to ensure they align with the intended functionality.

Verification successful

The panelProjectContent is defined and managed within ozaria/site/store/TeacherDashboardPanel.js. The state includes panelProjectContent, and there are mutations and actions to set and manage this state. The panelProjectContent is used to store project-related data, including aiScenario and aiProjects.

The conditional rendering and data bindings for the ai-scenario component in the template are correctly aligned with the state management in the store.

  • The panelProjectContent is properly defined in the state.
  • The mutations and actions ensure that panelProjectContent is set and managed correctly.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the data bindings and conditions for rendering `ai-scenario`.

# Test: Search for the usage of `panelProjectContent.aiScenario` and `panelProjectContent.aiProjects`. Expect: Proper checks and data handling.
rg --type vue $'panelProjectContent.aiScenario|panelProjectContent.aiProjects'

Length of output: 107



Script:

#!/bin/bash
# Description: Verify the data bindings and conditions for rendering `ai-scenario`.

# Test: Search for the usage of `panelProjectContent.aiScenario` and `panelProjectContent.aiProjects` within .vue files.
fd -e vue -x rg 'panelProjectContent\.aiScenario|panelProjectContent\.aiProjects' {}

Length of output: 265



Script:

#!/bin/bash
# Description: Verify the definition and management of `panelProjectContent`.

# Test: Search for the definition and usage of `panelProjectContent` within the script section of .vue files.
fd -e vue -x rg 'panelProjectContent' {}

Length of output: 290



Script:

#!/bin/bash
# Description: Verify the content and structure of 'teacherDashboardPanel/panelProjectContent'.

# Test: Locate and display the content of 'teacherDashboardPanel/panelProjectContent'.
fd -e js -e ts -e vue -x rg 'teacherDashboardPanel/panelProjectContent' {}

Length of output: 147



Script:

#!/bin/bash
# Description: Locate and display the content of 'panelProjectContent'.

# Locate the file 'panelProjectContent'.
fd -e js -e ts -e vue -g '*panelProjectContent*'

# Display the content of the located file.
fd -e js -e ts -e vue -g '*panelProjectContent*' -x cat {}

Length of output: 113



Script:

#!/bin/bash
# Description: Search for the definition or export of 'panelProjectContent' across all files.

# Search for 'panelProjectContent' across all files to locate its definition or export.
rg 'panelProjectContent'

Length of output: 922



Script:

#!/bin/bash
# Description: Display the content of `ozaria/site/store/TeacherDashboardPanel.js` to verify the data structure and handling of `panelProjectContent`.

# Display the content of `ozaria/site/store/TeacherDashboardPanel.js`.
cat ozaria/site/store/TeacherDashboardPanel.js

Length of output: 17941

ozaria/site/components/teacher-dashboard/BaseSingleClass/table/LockOrSkip.vue (4)

173-176: Check the conditional rendering and event handling for LevelAccessStatusButton based on isHackStack. Ensure that the correct actions are triggered on button clicks and that the conditions are accurately evaluated.

Also applies to: 179-181, 203-210, 216-223


Line range hint 40-241: Overall, the integration of the new scenario access controls and related changes appear to be well-implemented. Ensure all related data and methods are correctly set up in the Vuex store and other parts of the application.


162-162: Ensure that the conditional text interpolation based on isHackStack is correctly implemented. Verify that the translations for these conditions are defined in the localization files.

Also applies to: 167-167

Verification successful

The localization entries for the conditional text based on isHackStack are correctly defined in the localization files. The keys edit_student_access_title and edit_student_access_title_scenarios as well as edit_student_access_subtitle and edit_student_access_subtitle_scenarios are present and properly defined.

  • app/locale/en.js
    • edit_student_access_title: 'Edit Student Access to Levels'
    • edit_student_access_title_scenarios: 'Edit Student Access to Projects'
    • edit_student_access_subtitle: 'You have selected __levels__ levels for __students__ students.'
    • edit_student_access_subtitle_scenarios: 'You have selected __levels__ projects for __students__ students.'

These definitions ensure that the conditional rendering based on isHackStack will work as intended.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the localization entries for conditional text based on `isHackStack`.

# Test: Search for the localization entries related to `isHackStack`. Expect: Proper definitions in localization files.
rg --type vue $'edit_student_access_title|edit_student_access_subtitle'

Length of output: 100



Script:

#!/bin/bash
# Description: Verify the localization entries for conditional text based on `isHackStack`.

# Test: Search for the localization entries related to `isHackStack`. Expect: Proper definitions in localization files.
rg 'edit_student_access_title|edit_student_access_subtitle'

Length of output: 14325


63-64: Check the logic for determining if the current course is HACKSTACK. Ensure that utils.courseIDs.HACKSTACK is correctly defined and used.

ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue (2)

96-98: Check the logic for dynamically setting CSS variables based on the length of listOfContent. Ensure that the calculations for --columnWidth are accurate and meet the design requirements.


55-58: Ensure that the moduleHeadingImage property is properly defined and used within the component. Verify that it is passed correctly and handled appropriately in the template.

Verification successful

The moduleHeadingImage property is properly defined and used within the TableModuleHeader.vue component. It is referenced in the template with v-if and :src bindings, ensuring it is conditionally rendered and used as an image source.

  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue:
    • Line defining moduleHeadingImage property.
    • Line using v-if="moduleHeadingImage".
    • Line using :src="moduleHeadingImage".
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the handling of `moduleHeadingImage` property.

# Test: Search for the usage of `moduleHeadingImage`. Expect: Proper handling of the property.
rg --type vue $'moduleHeadingImage'

Length of output: 62



Script:

#!/bin/bash
# Description: Verify the handling of `moduleHeadingImage` property.

# Test: Search for the usage of `moduleHeadingImage`. Expect: Proper handling of the property.
rg 'moduleHeadingImage'

Length of output: 372

app/core/store/modules/courseInstances.js (1)

93-102: Refactor the string concatenation to use template literals for better readability and consistency with modern JavaScript practices.

- noty({ text: 'Fetch course instances failure: ' + e, type: 'error', layout: 'topCenter', timeout: 2000 })
+ noty({ text: `Fetch course instances failure: ${e}`, type: 'error', layout: 'topCenter', timeout: 2000 })

Likely invalid or redundant comment.

ozaria/site/components/teacher-dashboard/common/SecondaryTeacherNavigation.vue (4)

31-33: Add a new computed property for HackStack classes tab selection.

This computed property checks if the current route starts with '/teachers/hackstack-classes', which is consistent with the routing pattern used in other parts of the dashboard.


55-57: Add a new computed property to determine visibility of the HackStack option.

This property uses me.isInternal() to determine if the HackStack option should be shown, aligning with the intended access control for internal users.


78-81: Add a method to set the current classroom and course ID for HackStack.

This method correctly commits to the Vuex store the selected classroom ID and sets the course ID to HackStack, ensuring that the state is updated appropriately when a HackStack class is selected.


314-354: Implement a new dropdown menu for HackStack classes in the navigation.

The implementation includes a conditional rendering based on showHackStack, a dropdown toggle, and a list of classrooms. Each classroom link correctly sets the HackStack classroom upon click, which is a good use of Vue's reactivity system.

ozaria/site/store/TeacherDashboardPanel.js (5)

209-210: Ensure proper initialization of new state properties.


229-231: Ensure new mutations are correctly setting state properties.


256-257: Resetting state properties should ensure all related properties are correctly set to their initial values.


293-296: Ensure new getters are correctly retrieving state properties.


476-486: Ensure new actions are correctly dispatching and committing mutations.

ozaria/site/store/BaseSingleClass.js (1)

328-410: Ensure new actions are correctly dispatching and committing mutations.

app/core/store/modules/teacherDashboard.js (2)

152-157: Ensure new getters are correctly retrieving AI projects for the current classroom.


426-431: Ensure new actions are correctly fetching AI projects and scenarios for the current classroom.

app/core/vueRouter.js (1)

211-218: New route for HackStack classes added correctly.

Verification successful

The new route for HackStack classes is correctly added and integrated. The component BaseSingleClass and the utility utils.courseIDs.HACKSTACK are referenced appropriately in the codebase, indicating proper usage and integration.

  • BaseSingleClass is used in multiple files, including test files and other components.
  • utils.courseIDs.HACKSTACK is referenced in various components and utility files.

This confirms that the new route and its associated components and utilities are well-integrated into the application.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the integration of the new HackStack route with the rest of the application.

# Test: Search for the usage of the new route in the application. Expect: Proper integration and usage.
rg --type vue $'hackstack-classes/:classroomId'

Length of output: 74



Script:

#!/bin/bash
# Description: Verify the integration of the new HackStack route with the rest of the application.

# Test: Search for the usage of the new route in the application. Expect: Proper integration and usage.
rg 'hackstack-classes/:classroomId'

Length of output: 111



Script:

#!/bin/bash
# Description: Verify the integration of the new HackStack route by checking related components and utilities.

# Test 1: Search for the usage of the component `BaseSingleClass` in the application.
rg 'BaseSingleClass'

# Test 2: Search for the usage of `utils.courseIDs.HACKSTACK` in the application.
rg 'utils.courseIDs.HACKSTACK'

Length of output: 3502

app/templates/courses/courses-view.pug (1)

Line range hint 195-210: Conditional rendering for HackStack courses implemented correctly.

Verification successful

The search for the conditional rendering logic courseInstance.get('courseID') !== view.utils.courseIDs.HACKSTACK in Pug files only returned the instance within app/templates/courses/courses-view.pug. This indicates that the new conditional rendering logic is isolated to this file and does not affect other parts of the application.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the impact of the new conditional rendering on other functionalities.

# Test: Search for the usage of the conditional rendering in the application. Expect: No adverse impact on other functionalities.
rg --type pug $'courseInstance.get(\'courseID\') !== view.utils.courseIDs.HACKSTACK'

Length of output: 117



Script:

#!/bin/bash
# Description: Verify the impact of the new conditional rendering on other functionalities.

# Find all Pug files and search for the usage of the conditional rendering in the application.
fd -e pug -x rg 'courseInstance.get\(\'courseID\'\) !== view.utils.courseIDs.HACKSTACK' {}

Length of output: 93



Script:

#!/bin/bash
# Description: Verify the impact of the new conditional rendering on other functionalities.

# Find all Pug files and search for the usage of the conditional rendering in the application.
fd -e pug -x rg "courseInstance.get\('courseID'\) !== view.utils.courseIDs.HACKSTACK" {}

Length of output: 186

ozaria/site/components/teacher-dashboard/BaseSingleClass/index.vue (1)

Line range hint 66-79: Ensure proper handling of aiScenarios in the computed property.

The computed property aiScenarios directly accesses the Vuex store. Verify that the store is properly initialized with the aiScenarios module and that the getter getScenarios is correctly implemented to avoid runtime errors.

Verification successful

The Vuex store is properly initialized with the aiScenarios module, and the getScenarios getter is correctly implemented.

  • app/core/store/index.js: aiScenarios module is required.
  • app/core/store/modules/aiScenarios.js: getScenarios getter is defined.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the Vuex store initialization and getter implementation for `aiScenarios`.

# Test: Search for the Vuex store configuration and `aiScenarios` getter.
rg --type vue $'store/index.js'
rg --type vue $'getScenarios'

Length of output: 115



Script:

#!/bin/bash
# Description: Verify the Vuex store initialization and getter implementation for `aiScenarios`.

# Test: Search for the Vuex store configuration and `aiScenarios` getter.
rg 'aiScenarios' --glob '*store*.js'
rg 'getScenarios' --glob '*store*.js'

Length of output: 372



Script:

#!/bin/bash
# Description: Verify the Vuex store initialization and getter implementation for `aiScenarios`.

# Locate store files
store_files=$(fd store)

# Search for `aiScenarios` in the located store files
rg 'aiScenarios' $store_files

# Search for `getScenarios` in the located store files
rg 'getScenarios' $store_files

Length of output: 1253

app/core/Router.js (1)

455-455: New route addition for HackStack in the Teacher Dashboard looks good.

Ensure that the SingletonAppVueComponentView is properly configured to handle the classroomID parameter.

app/locale/en.js (2)

464-465: New localization entries for AI features are clear and consistent with the PR objectives.


2784-2786: New localization keys for managing student access to projects are correctly implemented and align with the new functionalities.

@@ -395,6 +492,8 @@ export default {
beforeRouteUpdate (to, from, next) {
this.closePanel()
this.clearSelectedStudents()
this.setClassroomId(to.params.classroomId)
this.setSelectedCourseIdCurrentClassroom({ courseId: utils.courseIDs.HACKSTACK })
Copy link

Choose a reason for hiding this comment

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

Set the selected course ID based on route parameters.

The course ID is hardcoded to HACKSTACK in the beforeRouteUpdate method. This should be dynamic based on the route parameters to ensure flexibility and correctness.

- this.setSelectedCourseIdCurrentClassroom({ courseId: utils.courseIDs.HACKSTACK })
+ this.setSelectedCourseIdCurrentClassroom({ courseId: to.params.courseId || utils.courseIDs.HACKSTACK })

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.

Suggested change
this.setSelectedCourseIdCurrentClassroom({ courseId: utils.courseIDs.HACKSTACK })
this.setSelectedCourseIdCurrentClassroom({ courseId: to.params.courseId || utils.courseIDs.HACKSTACK })

Comment on lines 89 to 172
if (selectedCourseId === utils.courseIDs.HACKSTACK) {
const hackStackModuleNames = this.aiScenarios.reduce((acc, scenario) => {
acc.add(scenario.tool)
return acc
}, new Set())

const hackStackModels = [...hackStackModuleNames].map((moduleName, key) => {
const moduleNum = key + 1
const classSummaryProgress = []
const moduleScenarios = (this.aiScenarios || [])
.filter(scenario => scenario.tool === moduleName)

return {
moduleNum,
displayName: moduleName,
displayLogo: utils.aiToolToImage[moduleName] || null,
contentList: moduleScenarios
.map((scenario, index) => {
return {
displayName: scenario.name,
type: 'challengelvl',
_id: scenario._id,
tooltipName: `${index + 1}: ${scenario.name}`,
description: '',
contentKey: scenario._id,
normalizedOriginal: scenario._id,
normalizedType: 'challengelvl',
contentLevelSlug: scenario.slug,
isPractice: false
}
}),
studentSessions: this.students.reduce((studentSessions, student) => {
studentSessions[student._id] = moduleScenarios
.map((aiScenario, index) => {
const details = {}
classSummaryProgress[index] = classSummaryProgress[index] || { status: 'assigned', border: '' }
// const summary = classSummaryProgress[index]
const aiProjects = this.aiProjectsMapByUser[student._id]?.[aiScenario._id]
if (aiProjects) {
details.status = 'progress'
classSummaryProgress[index].status = 'progress'

details.clickHandler = () => {
this.showPanelProjectContent({
header: 'HackStack Project',
student,
classroomId: this.classroomId, // TODO remove and use classroomId from teacherDashboard vuex
selectedCourseId: this.selectedCourseId,
moduleNum,
aiScenario,
aiProjects
})
}

if (aiProjects.some(scenario => scenario.actionQueue.length === 0)) {
details.status = 'complete'
}
}
const isLocked = ClassroomLib.isModifierActiveForStudent(this.classroom, student._id, this.selectedCourseId, aiScenario._id, 'lockedScenario')
const isPlayable = !isLocked

return {
status: 'assigned',
normalizedType: 'challengelvl',
isLocked,
isSkipped: false,
lockDate: null,
lastLockDate: null,
original: aiScenario._id,
normalizedOriginal: aiScenario._id,
isOptional: false,
isPlayable,
isPractice: false,
...details
}
})

return studentSessions
}, {}),
classSummaryProgress
}
})

return hackStackModels
Copy link

Choose a reason for hiding this comment

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

Review the logic for handling HACKSTACK course instances.

The logic within the modules computed property is quite complex, especially the part handling HACKSTACK course instances. Consider refactoring this into smaller, more manageable functions or even a separate component to improve readability and maintainability.

- if (selectedCourseId === utils.courseIDs.HACKSTACK) {
+ if (this.isHackStackCourse(selectedCourseId)) {

And then define a method isHackStackCourse that encapsulates the condition.


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.

Suggested change
if (selectedCourseId === utils.courseIDs.HACKSTACK) {
const hackStackModuleNames = this.aiScenarios.reduce((acc, scenario) => {
acc.add(scenario.tool)
return acc
}, new Set())
const hackStackModels = [...hackStackModuleNames].map((moduleName, key) => {
const moduleNum = key + 1
const classSummaryProgress = []
const moduleScenarios = (this.aiScenarios || [])
.filter(scenario => scenario.tool === moduleName)
return {
moduleNum,
displayName: moduleName,
displayLogo: utils.aiToolToImage[moduleName] || null,
contentList: moduleScenarios
.map((scenario, index) => {
return {
displayName: scenario.name,
type: 'challengelvl',
_id: scenario._id,
tooltipName: `${index + 1}: ${scenario.name}`,
description: '',
contentKey: scenario._id,
normalizedOriginal: scenario._id,
normalizedType: 'challengelvl',
contentLevelSlug: scenario.slug,
isPractice: false
}
}),
studentSessions: this.students.reduce((studentSessions, student) => {
studentSessions[student._id] = moduleScenarios
.map((aiScenario, index) => {
const details = {}
classSummaryProgress[index] = classSummaryProgress[index] || { status: 'assigned', border: '' }
// const summary = classSummaryProgress[index]
const aiProjects = this.aiProjectsMapByUser[student._id]?.[aiScenario._id]
if (aiProjects) {
details.status = 'progress'
classSummaryProgress[index].status = 'progress'
details.clickHandler = () => {
this.showPanelProjectContent({
header: 'HackStack Project',
student,
classroomId: this.classroomId, // TODO remove and use classroomId from teacherDashboard vuex
selectedCourseId: this.selectedCourseId,
moduleNum,
aiScenario,
aiProjects
})
}
if (aiProjects.some(scenario => scenario.actionQueue.length === 0)) {
details.status = 'complete'
}
}
const isLocked = ClassroomLib.isModifierActiveForStudent(this.classroom, student._id, this.selectedCourseId, aiScenario._id, 'lockedScenario')
const isPlayable = !isLocked
return {
status: 'assigned',
normalizedType: 'challengelvl',
isLocked,
isSkipped: false,
lockDate: null,
lastLockDate: null,
original: aiScenario._id,
normalizedOriginal: aiScenario._id,
isOptional: false,
isPlayable,
isPractice: false,
...details
}
})
return studentSessions
}, {}),
classSummaryProgress
}
})
return hackStackModels
if (this.isHackStackCourse(selectedCourseId)) {
const hackStackModuleNames = this.aiScenarios.reduce((acc, scenario) => {
acc.add(scenario.tool)
return acc
}, new Set())
const hackStackModels = [...hackStackModuleNames].map((moduleName, key) => {
const moduleNum = key + 1
const classSummaryProgress = []
const moduleScenarios = (this.aiScenarios || [])
.filter(scenario => scenario.tool === moduleName)
return {
moduleNum,
displayName: moduleName,
displayLogo: utils.aiToolToImage[moduleName] || null,
contentList: moduleScenarios
.map((scenario, index) => {
return {
displayName: scenario.name,
type: 'challengelvl',
_id: scenario._id,
tooltipName: `${index + 1}: ${scenario.name}`,
description: '',
contentKey: scenario._id,
normalizedOriginal: scenario._id,
normalizedType: 'challengelvl',
contentLevelSlug: scenario.slug,
isPractice: false
}
}),
studentSessions: this.students.reduce((studentSessions, student) => {
studentSessions[student._id] = moduleScenarios
.map((aiScenario, index) => {
const details = {}
classSummaryProgress[index] = classSummaryProgress[index] || { status: 'assigned', border: '' }
// const summary = classSummaryProgress[index]
const aiProjects = this.aiProjectsMapByUser[student._id]?.[aiScenario._id]
if (aiProjects) {
details.status = 'progress'
classSummaryProgress[index].status = 'progress'
details.clickHandler = () => {
this.showPanelProjectContent({
header: 'HackStack Project',
student,
classroomId: this.classroomId, // TODO remove and use classroomId from teacherDashboard vuex
selectedCourseId: this.selectedCourseId,
moduleNum,
aiScenario,
aiProjects
})
}
if (aiProjects.some(scenario => scenario.actionQueue.length === 0)) {
details.status = 'complete'
}
}
const isLocked = ClassroomLib.isModifierActiveForStudent(this.classroom, student._id, this.selectedCourseId, aiScenario._id, 'lockedScenario')
const isPlayable = !isLocked
return {
status: 'assigned',
normalizedType: 'challengelvl',
isLocked,
isSkipped: false,
lockDate: null,
lastLockDate: null,
original: aiScenario._id,
normalizedOriginal: aiScenario._id,
isOptional: false,
isPlayable,
isPractice: false,
...details
}
})
return studentSessions
}, {}),
classSummaryProgress
}
})
return hackStackModels

Comment on lines +478 to +480
if (this.defaultCourseId) {
this.setSelectedCourseId({ courseId: this.defaultCourseId })
}
Copy link

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The search results indicate that there is no specific validation logic for defaultCourseId or course IDs in general within the codebase. The only occurrences of defaultCourseId are in the file ozaria/site/components/teacher-dashboard/BaseSingleClass/index.vue, where it is being set directly without validation.

To ensure the integrity of the defaultCourseId, it is crucial to implement validation logic to verify that the ID corresponds to a valid course in the system before setting it.

  • File: ozaria/site/components/teacher-dashboard/BaseSingleClass/index.vue
  • Lines: 478-480

Action Required:

Implement validation logic to ensure defaultCourseId is valid before setting it.

Analysis chain

Validate the defaultCourseId before setting it.

The defaultCourseId is being set without any validation. Ensure that this ID corresponds to a valid course in the system to prevent errors.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the validity of `defaultCourseId`.

# Test: Search for the course validation logic.
rg --type vue $'validateCourseId'

Length of output: 60



Script:

#!/bin/bash
# Description: Verify the validity of `defaultCourseId`.

# Test: Search for the course validation logic across all files.
rg 'validateCourseId'

# Test: Search for any validation logic related to course IDs.
rg 'validate.*CourseId'

Length of output: 47



Script:

#!/bin/bash
# Description: Verify the usage and validation of `defaultCourseId`.

# Test: Search for the usage of `defaultCourseId` in the codebase.
rg 'defaultCourseId'

# Test: Search for general validation functions that might be used for IDs.
rg 'validate'

Length of output: 16710

Comment on lines 46 to 56
wrongChoices: {
type: 'array',
items: {
type: 'object',
properties: {
actionMessageId: { type: 'string' },
choiceIndex: { type: 'number' },
answerIndex: { type: 'number' }
}
}
}
Copy link

Choose a reason for hiding this comment

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

Add a description to the wrongChoices property to enhance schema clarity.

  wrongChoices: {
+   description: 'List of incorrect choices made in the project',
    type: 'array',
    items: {
      type: 'object',
      properties: {
        actionMessageId: { type: 'string' },
        choiceIndex: { type: 'number' },
        answerIndex: { type: 'number' }
      }
    }
  }

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.

Suggested change
wrongChoices: {
type: 'array',
items: {
type: 'object',
properties: {
actionMessageId: { type: 'string' },
choiceIndex: { type: 'number' },
answerIndex: { type: 'number' }
}
}
}
wrongChoices: {
description: 'List of incorrect choices made in the project',
type: 'array',
items: {
type: 'object',
properties: {
actionMessageId: { type: 'string' },
choiceIndex: { type: 'number' },
answerIndex: { type: 'number' }
}
}
}

dispatch('computeAiProjectMapForClassroom', classroom._id)
} catch (e) {
console.log(e)
noty({ text: 'Fetch ai projects failure' + e, type: 'error' })
Copy link

Choose a reason for hiding this comment

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

Use template literals for string concatenation to improve readability.

-        noty({ text: 'Fetch ai projects failure' + e, type: 'error' })
+        noty({ text: `Fetch ai projects failure: ${e}`, type: '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.

Suggested change
noty({ text: 'Fetch ai projects failure' + e, type: 'error' })
noty({ text: `Fetch ai projects failure: ${e}`, type: 'error' })


mutations: {
addScenarios (state, scenarios) {
scenarios.forEach(c => Vue.set(state.byId, c._id, c))
Copy link

Choose a reason for hiding this comment

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

Consider using for...of for better readability and performance.

- scenarios.forEach(c => Vue.set(state.byId, c._id, c))
+ for (const scenario of scenarios) {
+   Vue.set(state.byId, scenario._id, scenario)
+ }

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.

Suggested change
scenarios.forEach(c => Vue.set(state.byId, c._id, c))
for (const scenario of scenarios) {
Vue.set(state.byId, scenario._id, scenario)
}

if (options == null) { options = {} }
let url = '/db/ai_scenario'
if (other) {
url = '/' + other + url
Copy link

Choose a reason for hiding this comment

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

Use template literals for better readability and performance.

- url = '/' + other + url
+ url = `/${other}${url}`

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.

Suggested change
url = '/' + other + url
url = `/${other}${url}`


module.exports = {
get ({ courseID }, options) {
if (options == null) { options = {} }
Copy link

Choose a reason for hiding this comment

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

Avoid reassigning function parameters to maintain code clarity.

- if (options == null) { options = {} }
+ const effectiveOptions = options || {}

Also applies to: 10-10, 19-19


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.

Suggested change
if (options == null) { options = {} }
const effectiveOptions = options || {}

Comment on lines +120 to +123
v-for="({ displayName, contentList, classSummaryProgress, displayLogo, moduleNum }) of modules"

:key="`${displayName}`"
:module-heading-image="displayLogo"
Copy link

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The displayLogo property is not defined or used in the TableModuleHeader.vue component. Please ensure that this property is properly passed and handled within the component.

  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue
Analysis chain

Ensure that the displayLogo property is properly defined and used within the TableModuleHeader component. Verify that it is passed correctly and handled appropriately in the child component.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the handling of `displayLogo` property in `TableModuleHeader`.

# Test: Search for the usage of `displayLogo` in `TableModuleHeader`. Expect: Proper handling of the property.
rg --type vue $'displayLogo'

Length of output: 55



Script:

#!/bin/bash
# Locate the TableModuleHeader component file
fd TableModuleHeader.vue

# Assuming the file is found, search for the usage of displayLogo within it
fd TableModuleHeader.vue --exec rg 'displayLogo' {}

Length of output: 165



Script:

#!/bin/bash
# Search for the definition and usage of the displayLogo prop in TableModuleHeader.vue
ast-grep --lang vue --pattern 'props: { displayLogo: $_ }' ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue
ast-grep --lang vue --pattern '$_ = this.displayLogo' ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue

Length of output: 500



Script:

#!/bin/bash
# Search for the definition of the displayLogo prop in TableModuleHeader.vue
rg 'props:.*displayLogo' ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue

# Search for the usage of displayLogo within the template or script sections of TableModuleHeader.vue
rg 'displayLogo' ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue

Length of output: 213

Comment on lines +40 to +41
LOCK_SCENARIO: { modifiers: ['lockedScenario'], value: true },
UNLOCK_SCENARIO: { modifiers: ['lockedScenario'], value: false },
Copy link

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The absence of any results from the search in the Vuex store modules indicates that LOCK_SCENARIO and UNLOCK_SCENARIO are not defined in the Vuex store. This confirms that these actions are not properly integrated with Vuex, which is a significant issue.

  • The actions LOCK_SCENARIO and UNLOCK_SCENARIO are used in the LockOrSkip.vue component but are not defined in the Vuex store.

This needs to be addressed to ensure proper functionality.

  • Define LOCK_SCENARIO and UNLOCK_SCENARIO in the Vuex store.
  • Ensure these actions are correctly integrated and used across the application.
Analysis chain

Confirm that the new actions LOCK_SCENARIO and UNLOCK_SCENARIO are correctly defined and used. Ensure that they are properly integrated with Vuex and other parts of the application.

Also applies to: 97-97, 138-141


The search results indicate that LOCK_SCENARIO and UNLOCK_SCENARIO are used within the Vue component, but there is no evidence of their definitions or integration with Vuex. To ensure these actions are correctly defined and integrated, we need to verify their definitions in the Vuex store and their usage across the codebase.


The search results show that LOCK_SCENARIO and UNLOCK_SCENARIO are used within the LockOrSkip.vue component, but there is no evidence of their definitions in the Vuex store. This suggests that these actions might not be properly defined or integrated with Vuex.

To confirm this, we need to search for their definitions in the Vuex store modules.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the definition and usage of `LOCK_SCENARIO` and `UNLOCK_SCENARIO`.

# Test: Search for the Vuex actions `LOCK_SCENARIO` and `UNLOCK_SCENARIO`. Expect: Proper definition and usage.
rg --type vue $'LOCK_SCENARIO|UNLOCK_SCENARIO'

Length of output: 75



Script:

#!/bin/bash
# Description: Verify the definition and usage of `LOCK_SCENARIO` and `UNLOCK_SCENARIO`.

# Locate all .vue files and search for the Vuex actions `LOCK_SCENARIO` and `UNLOCK_SCENARIO`.
fd -e vue -x rg 'LOCK_SCENARIO|UNLOCK_SCENARIO' {}

Length of output: 512



Script:

#!/bin/bash
# Description: Verify the definition of `LOCK_SCENARIO` and `UNLOCK_SCENARIO` in the Vuex store.

# Search for the definitions of `LOCK_SCENARIO` and `UNLOCK_SCENARIO` in JavaScript and TypeScript files.
rg 'LOCK_SCENARIO|UNLOCK_SCENARIO' --type js --type ts

Length of output: 1060



Script:

#!/bin/bash
# Description: Verify the definition of `LOCK_SCENARIO` and `UNLOCK_SCENARIO` in Vuex store modules.

# Search for the definitions of `LOCK_SCENARIO` and `UNLOCK_SCENARIO` in Vuex store modules.
rg 'LOCK_SCENARIO|UNLOCK_SCENARIO' --type js --type ts --glob '**/store/**/*.js' --glob '**/store/**/*.ts'

Length of output: 108

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: 0

Outside diff range and nitpick comments (1)
ozaria/site/components/teacher-dashboard/BaseSingleClass/table/CellStudent.vue (1)

40-42: Consider adding a comment explaining why HACKSTACK courses always return false.

This helps maintain code clarity and aids future developers in understanding the special case handling for the HACKSTACK course.

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between 393bffc and 98bb22b.
Files selected for processing (5)
  • app/locale/en.js (4 hunks)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/index.vue (8 hunks)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/CellStudent.vue (2 hunks)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue (8 hunks)
  • ozaria/site/components/teacher-dashboard/Panel/components/AiProject.vue (1 hunks)
Files skipped from review as they are similar to previous changes (3)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/index.vue
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue
  • ozaria/site/components/teacher-dashboard/Panel/components/AiProject.vue
Additional Context Used
Biome (1)
app/locale/en.js (1)

606-606: Do not add then to an object.

Additional comments not posted (4)
app/locale/en.js (4)

464-465: Descriptions for educational tools and the new entry for 'AI HackStack' are clear and relevant.


2786-2788: New keys for managing student access to projects are well-defined and consistent with the expanded functionality.


4594-4595: Addition of keys for tracking failed attempts enhances monitoring of student performance.


5889-5890: The description for 'claude-description' and the new 'locked' key are appropriate and useful additions.

Copy link
Contributor

@mrfinch mrfinch left a comment

Choose a reason for hiding this comment

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

I feel lot of coderabbitai comments are correct for our context and should be fixed. I have upvoted ones I think we should fix.

@@ -2270,7 +2273,15 @@ const getModuleNumberForLevelName = function (courseId, levelName) {
return moduleNumberByLevelName[levelName] && Number(moduleNumberByLevelName[levelName])
}

module.exports.aiToolToImage = {
Copy link
Contributor

Choose a reason for hiding this comment

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

why module.exports here instead of const?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

because actually I don't really see the point of defining const and later add everything to export object again. I think, it is much cleaner this way. It happened to me many times that I defined a new const in utils, and thought it'll be accessible at utils.myVarName, and then I had to come back and add it to exports...

if (options == null) { options = {} }
if (options.data == null) { options.data = {} }
if (me.isInternal()) {
options.data.fetchInternal = true // will fetch 'released', 'beta', and 'internalRelease' courses
Copy link
Contributor

Choose a reason for hiding this comment

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

does scenario api handle this?

},

computeAiProjectCompletionByUserForClassroom ({ commit, state }, classroomId) {
// todo
Copy link
Contributor

Choose a reason for hiding this comment

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

what todo?

@@ -417,9 +423,12 @@ export default {
project: (options.data || {}).levelSessions
}
fetchPromises.push(dispatch('levelSessions/fetchForClassroomMembers', { classroom, options: levelSessionOptions }, { root: true }))
fetchPromises.push(dispatch('aiProjects/fetchForClassroomMembers', { classroom }, { root: true }))
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm guessing the architecture is like this where we fetch all even if the course selected is not HS, correct?
Something we should optimize later? We should create a list of such things to tackle later.

{ season: 11, slug: 'solar-skirmish', type: 'regular', start: new Date('2024-05-01T00:00:00.000-07:00'), end: new Date('2024-09-01T00:00:00.000-07:00'), results: new Date('2024-09-14T07:00:00.000-07:00'), levelOriginal: '661f6cf6525db0fb41870360', tournament: '66311a29856d99556fa14326', image: '/file/db/level/661f6cf6525db0fb41870360/SolarSkirmishBanner.png' },
{ season: 10, slug: 'fierce-forces', type: 'regular', start: new Date('2024-01-01T00:00:00.000-08:00'), end: new Date('2024-05-01T00:00:00.000-07:00'), results: new Date('2024-05-10T07:00:00.000-07:00'), levelOriginal: '6576ff2b1457f600193d2cc9', image: '/file/db/level/6576ff2b1457f600193d2cc9/FierceForcesBannerNew.png' },
{ season: 10, slug: 'anti-gravity', type: 'championship', start: new Date('2024-04-01T00:00:00.000-07:00'), end: new Date('2024-05-01T00:00:00.000-07:00'), results: new Date('2024-05-10T07:00:00.000-07:00'), levelOriginal: '65f2618f757a82bcc90b7c9e', image: '/file/db/level/65f2618f757a82bcc90b7c9e/AntiGravityBanner.png' },
{ season: 11, slug: 'solar-skirmish', type: 'regular', start: new Date('2024-05-01T00:00:00.000-07:00'), end: new Date('2024-09-01T00:00:00.000-07:00'), results: new Date('2024-09-14T07:00:00.000-07:00'), levelOriginal: '', image: '' },
Copy link
Contributor

Choose a reason for hiding this comment

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

by mistake?

Comment on lines 97 to 99
lockedScenarioLevels: c.object({
additionalProperties: ['boolean', c.stringDate()]
}),
Copy link
Contributor

Choose a reason for hiding this comment

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

any reason we can't reuse existing schema by using level-ids but id will be of scenario instead
based on course? Doesn't make a big difference though but want to understand the reason for separation as we will need to do something for other products going forward and I don't want too many locked keys option.

Also, a good idea to have it on course-instace itself?

isPractice: false
}
}),
studentSessions: this.students.reduce((studentSessions, student) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

can we instead use functions and make it more readable? I'm not a fan of functions with 50 lines

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: 5

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between 98bb22b and c2a672f.
Files selected for processing (10)
  • app/core/api/ai_scenarios.js (1 hunks)
  • app/core/store/modules/aiProjects.js (1 hunks)
  • app/core/store/modules/aiScenarios.js (1 hunks)
  • app/core/store/modules/teacherDashboard.js (2 hunks)
  • app/core/utils.js (4 hunks)
  • app/locale/en.js (4 hunks)
  • app/schemas/models/ai_project.schema.js (1 hunks)
  • app/schemas/models/classroom.schema.js (1 hunks)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/index.vue (10 hunks)
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue (7 hunks)
Files skipped from review as they are similar to previous changes (5)
  • app/core/store/modules/aiScenarios.js
  • app/schemas/models/ai_project.schema.js
  • app/schemas/models/classroom.schema.js
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/index.vue
  • ozaria/site/components/teacher-dashboard/BaseSingleClass/table/TableModuleHeader.vue
Additional Context Used
Biome (41)
app/core/api/ai_scenarios.js (2)

10-10: Reassigning a function parameter is confusing.


19-19: Reassigning a function parameter is confusing.

app/core/store/modules/aiProjects.js (3)

58-58: Change to an optional chain.


61-61: Change to an optional chain.


112-112: Change to an optional chain.

app/core/store/modules/teacherDashboard.js (15)

83-85: This else clause can be omitted because previous branches break early.


90-92: This else clause can be omitted because previous branches break early.


97-99: This else clause can be omitted because previous branches break early.


111-113: This else clause can be omitted because previous branches break early.


127-137: This else clause can be omitted because previous branches break early.


135-135: Change to an optional chain.


167-169: This else clause can be omitted because previous branches break early.


174-176: This else clause can be omitted because previous branches break early.


250-250: Change to an optional chain.


251-256: Prefer for...of instead of forEach.


253-253: Change to an optional chain.


357-360: Prefer for...of instead of forEach.


399-401: Prefer for...of instead of forEach.


419-419: Change to an optional chain.


423-423: Change to an optional chain.

app/core/utils.js (20)

14-15: Declare variables separately


16-16: The assignment should not be in an expression.


17-17: The assignment should not be in an expression.


25-25: Change to an optional chain.


29-29: Change to an optional chain.


43-47: This else clause can be omitted because previous branches break early.


45-47: This else clause can be omitted because previous branches break early.


40-48: This function expression can be turned into an arrow function.


55-55: Template literals are preferred over string concatenation.


50-60: This function expression can be turned into an arrow function.


66-66: Template literals are preferred over string concatenation.


62-67: This function expression can be turned into an arrow function.


69-76: This function expression can be turned into an arrow function.


78-94: This function expression can be turned into an arrow function.


98-112: This function expression can be turned into an arrow function.


194-202: This function expression can be turned into an arrow function.


204-207: This function expression can be turned into an arrow function.


212-212: The assignment should not be in an expression.


209-214: This function expression can be turned into an arrow function.


1104-1104: The assignment should not be in an expression.

app/locale/en.js (1)

606-606: Do not add then to an object.

Additional comments not posted (12)
app/core/api/ai_scenarios.js (1)

4-7: LGTM! The function implementation for fetching specific AI scenarios based on courseID is clear and concise.

app/core/store/modules/aiProjects.js (3)

6-13: The state structure for managing AI projects by classroom is well-defined and organized.


15-54: The mutations for managing AI projects state are implemented correctly, ensuring reactivity with Vue.set.


65-130: The actions for fetching and managing AI projects are well-implemented with proper error handling and state management.

app/core/store/modules/teacherDashboard.js (4)

Line range hint 1-20: The state definition for the teacher dashboard is well-structured and clear.


Line range hint 21-43: The mutations for managing the teacher dashboard state are implemented correctly, including the use of localStorage for persistence.


Line range hint 152-434: The actions for managing data fetching and state updates in the teacher dashboard are well-implemented with proper error handling and state management.


152-157: Consider using optional chaining to safely access nested properties.

- return rootGetters['aiProjects/getAiProjectsMapForClassroom'](state.classroomId) || {}
+ return rootGetters['aiProjects/getAiProjectsMapForClassroom'](state.classroomId)?

Likely invalid or redundant comment.

app/core/utils.js (1)

2355-2359: Consider using export instead of module.exports for consistency with ES6 modules.

- module.exports.aiToolToImage = {
+ export const aiToolToImage = {
  'gpt-4-turbo-preview': '/images/ai/ChatGPT.svg',
  'stable-diffusion-xl': '/images/ai/Stable_Diffusion.png',
  'dall-e-3': '/images/ai/DALL-E.webp',
}

Likely invalid or redundant comment.

app/locale/en.js (3)

464-465: The new key-value pairs for descriptions and learning options are clear and contextually appropriate.


4594-4595: The addition of key-value pairs for 'Failed Attempts' and 'No Failed Attempts' is relevant and useful for providing feedback in an educational setting.


5889-5891: The descriptions for AI tools and the addition of the 'LOCKED' status are accurate and enhance the user interface by providing clear information and access control.

Comment on lines +2786 to +2788
edit_student_access_title_scenarios: 'Edit Student Access to Projects',
edit_student_access_subtitle: 'You have selected __levels__ levels for __students__ students.',
edit_student_access_subtitle_scenarios: 'You have selected __levels__ projects for __students__ students.',
Copy link

Choose a reason for hiding this comment

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

The updates to titles and subtitles for student access are well-aligned with the new functionalities. Consider using "projects" instead of "levels" in the subtitle for consistency.

- You have selected __levels__ projects for __students__ students.
+ You have selected __projects__ projects for __students__ students.

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.

Suggested change
edit_student_access_title_scenarios: 'Edit Student Access to Projects',
edit_student_access_subtitle: 'You have selected __levels__ levels for __students__ students.',
edit_student_access_subtitle_scenarios: 'You have selected __levels__ projects for __students__ students.',
edit_student_access_title_scenarios: 'Edit Student Access to Projects',
edit_student_access_subtitle: 'You have selected __levels__ levels for __students__ students.',
edit_student_access_subtitle_scenarios: 'You have selected __projects__ projects for __students__ students.',

Comment on lines 2361 to 2363

module.exports = {
...module.exports,
Copy link

Choose a reason for hiding this comment

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

Consider destructuring module.exports at the top of the export statement to improve readability.

- module.exports = {
+ export default {
  ...module.exports,
  activeAndPastArenas,
  activeArenas,
  addIntroLevelContent,
  addressesIncludeAdministrativeRegion,
  ageBrackets,
  ageBracketsChina,
  ageOfConsent,
  ageToBracket,
  allowedLanguages,
  anonymizingUser,
  arenas,
  bracketToAge,
  campaignIDs,
  capitalizeFirstLetter,
  capitalLanguages,
  clanHeroes,
  clone,
  combineAncestralObject,
  commentStarts,
  countries,
  countryCodeToFlagEmoji,
  countryCodeToName,
  countryNameToCode,
  courseAcronyms,
  courseIDs,
  allCourseIDs,
  allFreeCourseIDs,
  courseModules,
  courseModuleInfo,
  courseModuleLevels,
  courseNumericalStatus,
  coursesWithProjects,
  CSCourseIDs,
  WDCourseIDs,
  createLevelNumberMap,
  downTheChain,
  extractPlayerCodeTag,
  freeAccessLevels,
  findNextAssessmentForLevel,
  findNextLevel,
  formatDollarValue,
  formatStudentLicenseStatusDate,
  formatStudentSingleLicenseStatusDate,
  freeCampaignIds,
  functionCreators,
  getApiClientIdFromEmail,
  getByPath,
  getCourseBundlePrice,
  getCoursePraise,
  getDocumentSearchString,
  getModuleNumberForLevelName,
  getPrepaidCodeAmount,
  getProduct,
  getProductName,
  getQueryVariable,
  getQueryVariables,
  getScreenRefreshRate,
  getSponsoredSubsAmount,
  getUTCDay,
  getAnonymizationStatus,
  getCorrectName,
  grayscale,
  hexToHSL,
  hourOfCodeOptions,
  hslToHex,
  i18n,
  inEU,
  injectCSS,
  internalCampaignIds,
  isID,
  isRegionalSubscription,
  isSmokeTestEmail,
  isValidEmail,
  keepDoingUntil,
  kindaEqual,
  markdownToPlainText,
  needsPractice,
  normalizeFunc,
  objectIdToDate,
  orderedCourseIDs,
  orgKindString,
  pathToUrl,
  petThangIDs,
  premiumContent,
  registerHocProgressModalCheck,
  replaceText,
  round,
  AILeagueSeasons,
  sortCourses,
  sortOtherCourses,
  sortCoursesByAcronyms,
  stripIndentation,
  teamSpells,
  titleize,
  usStateCodes,
  userAgent,
  videoLevels,
  vueNonReactiveInstall,
  yearsSinceMonth,
  CODECOMBAT,
  OZARIA,
  CODECOMBAT_CHINA,
  OZARIA_CHINA,
  isOldBrowser,
  isChinaOldBrowser,
  isCodeCombat,
  isOzaria,
  supportEmail,
  tournamentSortFn,
  cocoBaseURL,
  ozBaseURL,
  useWebsocket,
  getProductUrl,
  shaTag
}

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.

Suggested change
module.exports = {
...module.exports,
export default {
...module.exports,
activeAndPastArenas,
activeArenas,
addIntroLevelContent,
addressesIncludeAdministrativeRegion,
ageBrackets,
ageBracketsChina,
ageOfConsent,
ageToBracket,
allowedLanguages,
anonymizingUser,
arenas,
bracketToAge,
campaignIDs,
capitalizeFirstLetter,
capitalLanguages,
clanHeroes,
clone,
combineAncestralObject,
commentStarts,
countries,
countryCodeToFlagEmoji,
countryCodeToName,
countryNameToCode,
courseAcronyms,
courseIDs,
allCourseIDs,
allFreeCourseIDs,
courseModules,
courseModuleInfo,
courseModuleLevels,
courseNumericalStatus,
coursesWithProjects,
CSCourseIDs,
WDCourseIDs,
createLevelNumberMap,
downTheChain,
extractPlayerCodeTag,
freeAccessLevels,
findNextAssessmentForLevel,
findNextLevel,
formatDollarValue,
formatStudentLicenseStatusDate,
formatStudentSingleLicenseStatusDate,
freeCampaignIds,
functionCreators,
getApiClientIdFromEmail,
getByPath,
getCourseBundlePrice,
getCoursePraise,
getDocumentSearchString,
getModuleNumberForLevelName,
getPrepaidCodeAmount,
getProduct,
getProductName,
getQueryVariable,
getQueryVariables,
getScreenRefreshRate,
getSponsoredSubsAmount,
getUTCDay,
getAnonymizationStatus,
getCorrectName,
grayscale,
hexToHSL,
hourOfCodeOptions,
hslToHex,
i18n,
inEU,
injectCSS,
internalCampaignIds,
isID,
isRegionalSubscription,
isSmokeTestEmail,
isValidEmail,
keepDoingUntil,
kindaEqual,
markdownToPlainText,
needsPractice,
normalizeFunc,
objectIdToDate,
orderedCourseIDs,
orgKindString,
pathToUrl,
petThangIDs,
premiumContent,
registerHocProgressModalCheck,
replaceText,
round,
AILeagueSeasons,
sortCourses,
sortOtherCourses,
sortCoursesByAcronyms,
stripIndentation,
teamSpells,
titleize,
usStateCodes,
userAgent,
videoLevels,
vueNonReactiveInstall,
yearsSinceMonth,
CODECOMBAT,
OZARIA,
CODECOMBAT_CHINA,
OZARIA_CHINA,
isOldBrowser,
isChinaOldBrowser,
isCodeCombat,
isOzaria,
supportEmail,
tournamentSortFn,
cocoBaseURL,
ozBaseURL,
useWebsocket,
getProductUrl,
shaTag
}

Comment on lines +10 to +15
if (options == null) { options = {} }
let url = '/db/ai_scenario'
if (other) {
url = `/${other}${url}`
}
return fetchJson(url, options)
Copy link

Choose a reason for hiding this comment

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

Avoid reassigning function parameters to maintain code clarity.

- if (options == null) { options = {} }
+ const effectiveOptions = options || {}

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.

Suggested change
if (options == null) { options = {} }
let url = '/db/ai_scenario'
if (other) {
url = `/${other}${url}`
}
return fetchJson(url, options)
const effectiveOptions = options || {}
let url = '/db/ai_scenario'
if (other) {
url = `/${other}${url}`
}
return fetchJson(url, effectiveOptions)

Comment on lines +19 to +30
if (options == null) { options = {} }
if (options.data == null) { options.data = {} }
const results = await fetchJson('/db/ai_scenario', options)

const phases = ['released']
if (me.isInternal()) {
phases.push('beta')
}

const filteredScenarios = results.filter(scenario => phases.includes(scenario.releasePhase))
return filteredScenarios
}
Copy link

Choose a reason for hiding this comment

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

Avoid reassigning function parameters to maintain code clarity.

- if (options == null) { options = {} }
+ const effectiveOptions = options || {}

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.

Suggested change
if (options == null) { options = {} }
if (options.data == null) { options.data = {} }
const results = await fetchJson('/db/ai_scenario', options)
const phases = ['released']
if (me.isInternal()) {
phases.push('beta')
}
const filteredScenarios = results.filter(scenario => phases.includes(scenario.releasePhase))
return filteredScenarios
}
const effectiveOptions = options || {}
if (effectiveOptions.data == null) { effectiveOptions.data = {} }
const results = await fetchJson('/db/ai_scenario', effectiveOptions)
const phases = ['released']
if (me.isInternal()) {
phases.push('beta')
}
const filteredScenarios = results.filter(scenario => phases.includes(scenario.releasePhase))
return filteredScenarios

Comment on lines +57 to +62
getAiProjectsMapForClassroom: (state) => (classroom) => {
return (state.aiProjectsByClassroom[classroom] || {}).aiProjectMapByUser
},
getSessionsForClassroom: (state) => (classroom) => {
return (state.aiProjectsByClassroom[classroom] || {}).projects
},
Copy link

Choose a reason for hiding this comment

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

Consider using optional chaining to safely access nested properties.

- return (state.aiProjectsByClassroom[classroom] || {}).aiProjectMapByUser
+ return state.aiProjectsByClassroom[classroom]?.aiProjectMapByUser

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.

Suggested change
getAiProjectsMapForClassroom: (state) => (classroom) => {
return (state.aiProjectsByClassroom[classroom] || {}).aiProjectMapByUser
},
getSessionsForClassroom: (state) => (classroom) => {
return (state.aiProjectsByClassroom[classroom] || {}).projects
},
getAiProjectsMapForClassroom: (state) => (classroom) => {
return state.aiProjectsByClassroom[classroom]?.aiProjectMapByUser
},
getSessionsForClassroom: (state) => (classroom) => {
return (state.aiProjectsByClassroom[classroom] || {}).projects
},

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: 1

Outside diff range and nitpick comments (2)
app/core/utils.js (2)

Line range hint 14-15: Declare variables separately for clarity.

- let campaignIDs, compare, courseIDs, courseModules, courseModuleInfo, courseModuleLevels, coursesWithProjects, CSCourseIDs, freeCampaignIds, hourOfCodeOptions, injectCSS, internalCampaignIds, left, orderedCourseIDs, otherCourseIDs, otherOrderedCourseIDs, replaceText, slugify, WDCourseIDs
+ let campaignIDs;
+ let compare;
+ let courseIDs;
+ let courseModules;
+ let courseModuleInfo;
+ let courseModuleLevels;
+ let coursesWithProjects;
+ let CSCourseIDs;
+ let freeCampaignIds;
+ let hourOfCodeOptions;
+ let injectCSS;
+ let internalCampaignIds;
+ let left;
+ let orderedCourseIDs;
+ let otherCourseIDs;
+ let otherOrderedCourseIDs;
+ let replaceText;
+ let slugify;
+ let WDCourseIDs;

This change improves readability and makes it easier to track the declaration and initialization of each variable separately.


Line range hint 16-17: Avoid assignments within expressions for clarity.

- const product = ((left = typeof COCO_PRODUCT !== 'undefined' && COCO_PRODUCT !== null ? COCO_PRODUCT : __guard__(typeof process !== 'undefined' && process !== null ? process.env : undefined, x => x.COCO_PRODUCT))) != null ? left : 'codecombat'
- const shaTag = ((left = typeof SHA_TAG !== 'undefined' && SHA_TAG !== null ? SHA_TAG : __guard__(typeof process !== 'undefined' && process !== null ? process.env : undefined, x => x.SHA_TAG))) != null ? left : 'unknown'
+ let left;
+ const product = ((left = typeof COCO_PRODUCT !== 'undefined' && COCO_PRODUCT !== null ? COCO_PRODUCT : __guard__(typeof process !== 'undefined' && process !== null ? process.env : undefined, x => x.COCO_PRODUCT))) != null ? left : 'codecombat';
+ const shaTag = ((left = typeof SHA_TAG !== 'undefined' && SHA_TAG !== null ? SHA_TAG : __guard__(typeof process !== 'undefined' && process !== null ? process.env : undefined, x => x.SHA_TAG))) != null ? left : 'unknown';

Separating the assignment from the expression improves the readability and maintainability of the code.

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between c2a672f and 5d18100.
Files selected for processing (1)
  • app/core/utils.js (5 hunks)
Additional Context Used
Biome (20)
app/core/utils.js (20)

14-15: Declare variables separately


16-16: The assignment should not be in an expression.


17-17: The assignment should not be in an expression.


25-25: Change to an optional chain.


29-29: Change to an optional chain.


43-47: This else clause can be omitted because previous branches break early.


45-47: This else clause can be omitted because previous branches break early.


40-48: This function expression can be turned into an arrow function.


55-55: Template literals are preferred over string concatenation.


50-60: This function expression can be turned into an arrow function.


66-66: Template literals are preferred over string concatenation.


62-67: This function expression can be turned into an arrow function.


69-76: This function expression can be turned into an arrow function.


78-94: This function expression can be turned into an arrow function.


98-112: This function expression can be turned into an arrow function.


194-202: This function expression can be turned into an arrow function.


204-207: This function expression can be turned into an arrow function.


212-212: The assignment should not be in an expression.


209-214: This function expression can be turned into an arrow function.


1104-1104: The assignment should not be in an expression.

Comment on lines +2355 to +2359
module.exports.aiToolToImage = {
'gpt-4-turbo-preview': '/images/ai/ChatGPT.svg',
'stable-diffusion-xl': '/images/ai/Stable_Diffusion.png',
'dall-e-3': '/images/ai/DALL-E.webp',
}
Copy link

Choose a reason for hiding this comment

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

Add documentation for new AI tool mappings.

It's important to maintain documentation for new mappings added to aiToolToImage. This helps other developers understand the purpose and usage of these mappings. Consider adding comments above these lines explaining each AI tool and its corresponding image.

@mrfinch mrfinch merged commit 0571926 into master May 30, 2024
2 checks passed
@mrfinch mrfinch deleted the adamk/dt-hackstack-wip branch May 30, 2024 09:06
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.

None yet

2 participants