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

317 iterating compliance store in db #336

Conversation

MuhammadKhalilzadeh
Copy link
Collaborator

@MuhammadKhalilzadeh MuhammadKhalilzadeh commented Dec 12, 2024

@HarshP4585
The iteration through controls is mostly done.
Please go through the code and fix parts that do not match on the server-side

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced dropdown options for "Approver," "Owner," and "Reviewer" fields with specific labels.
    • Introduced a new controlCategory property to various components for improved data handling.
    • Added API integration for saving controls and managing control categories.
  • Bug Fixes

    • Improved content formatting in feedback submissions.
  • Documentation

    • Added a new TypeScript file defining the structure for control requests.
  • Chores

    • Introduced mock data files for control categories and controls, facilitating testing and development.

@MuhammadKhalilzadeh MuhammadKhalilzadeh added frontend Frontend related tasks/issues backend Backend related tasks/issues team work and collaboration labels Dec 12, 2024
@MuhammadKhalilzadeh MuhammadKhalilzadeh self-assigned this Dec 12, 2024
Copy link

coderabbitai bot commented Dec 12, 2024

Walkthrough

The pull request introduces several changes across multiple components and files in the codebase. Key modifications include updates to dropdown options in the DropDowns component, enhancements to the Field and NewControlPane components for styling and functionality, and the introduction of new properties in various components to support control categories. Additionally, new utility functions and a mock database for control categories are created to facilitate CRUD operations. These changes aim to improve data handling and user interface elements related to compliance tracking and control management.

Changes

File Change Summary
Clients/src/presentation/components/Inputs/Dropdowns/index.tsx Updated dropdown options for "Approver," "Owner," and "Reviewer" fields with specific labels.
Clients/src/presentation/components/Inputs/Field/index.tsx Added className to TextField, modified inputProps for vertical overflow, and reformatted error handling logic.
Clients/src/presentation/components/Modals/ComplianceFeedback/ComplianceFeedback.tsx Modified handleContentChange to format content before passing to callback, removing leading/trailing <p> tags.
Clients/src/presentation/components/Modals/Controlpane/NewControlPane.tsx Added numbering and controlCategory props, modified handleSave to be asynchronous, and updated modal title display.
Clients/src/presentation/components/Table/AccordionTable/index.tsx Added controlCategory prop, updated id and numbering props for NewControlPane.
Clients/src/presentation/pages/ComplianceTracker/NewComplianceTracker.tsx Passed controlCategory to AccordionTable in renderAccordion.
Clients/src/presentation/pages/ComplianceTracker/controls.req.structure.ts Introduced a new TypeScript file defining the structure for control requests.
Servers/controllers/assessment.ctrl.ts Modified saveAnswers to send a success response after saving answers in mock data scenario.
Servers/controllers/control.ctrl.ts Updated createControl to simplify createNewSubcontrolQuery function call and removed commented-out mock logic.
Servers/controllers/controlCategory.ctrl.ts Introduced functions for managing control categories (CRUD operations).
Servers/controllers/project.ctrl.ts Added saveControls function to handle saving control categories and controls for a project.
Servers/controllers/subcontrol.ctrl.ts Updated createNewSubcontrol to include controlIdFK as a parameter.
Servers/mocks/controlCategory.mock.data.ts Created mock data for control categories with predefined entries.
Servers/mocks/tools/control.mock.db.ts Modified createMockControl to construct a new control object with specific properties.
Servers/mocks/tools/controlCategory.mock.db.ts Introduced a mock database for control categories with CRUD functions.
Servers/models/controlCategory.model.ts Added ControlCategory type definition.
Servers/routes/controlCategory.route.ts Created a new router for control category CRUD operations.
Servers/routes/project.route.ts Added a new route for saving controls.
Servers/utils/controlCategory.util.ts Introduced utility functions for managing control categories in the database.
Servers/utils/subControl.utils.ts Updated createNewSubcontrolQuery to accept controlId as a separate parameter.

Possibly related PRs

🐰 "In the fields where options grow,
Dropdowns now with names to show.
Controls and categories, all in line,
With mock data ready, everything's fine.
A leap in structure, clear and bright,
Compliance tracking, a joyful sight!" 🐇✨


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>, please review it.
    • 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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @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 using 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 generate docstrings to generate docstrings for this PR. (Experiment)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

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

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

🧹 Outside diff range and nitpick comments (16)
Servers/controllers/controlCategory.ctrl.ts (1)

28-28: Simplify boolean condition checks

You can simplify if (MOCKDATA_ON === true) to if (MOCKDATA_ON).

Apply this diff:

- if (MOCKDATA_ON === true) {
+ if (MOCKDATA_ON) {

Also applies to: 65-65, 85-85, 109-109

Servers/controllers/project.ctrl.ts (1)

241-241: Avoid using console.log in production code

Using console.log can clutter the console and may expose sensitive data. Use a proper logging library with appropriate log levels.

Remove or replace console.log statements:

- console.log("subcontrolToSave : ", subcontrolToSave);

Also applies to: 283-283

Servers/routes/project.route.ts (2)

9-9: Ensure consistent route organization and uncomment authentication

The authentication middleware is commented out. If authentication is required, consider uncommenting it. Additionally, the new route /saveControls should be appropriately placed and documented.

Uncomment authenticateJWT if needed and organize the routes for better readability.

Also applies to: 21-21


Line range hint 263-263: Fix incorrect HTTP method comment

In line 21, the comment indicates // POSTs, but the route for /saveControls is added after this comment. Ensure that comments accurately reflect the code structure.

Move the comment if necessary to include the new POST route.

Servers/utils/controlCategory.util.ts (1)

1-52: Consider implementing database transactions

For data consistency, consider implementing database transactions when multiple operations need to be performed atomically. This is especially important in a compliance system.

Would you like me to provide an example implementation using transactions?

Servers/utils/subControl.utils.ts (2)

Line range hint 42-52: Validate input parameters before database operation

Add validation for required fields and data types before executing the database query to prevent invalid data from being stored.

+  // Validate required fields
+  if (!controlId || !subcontrol.status || !subcontrol.owner) {
+    throw new Error('Missing required fields: controlId, status, and owner are mandatory');
+  }
+
+  // Validate date format
+  if (subcontrol.dueDate && !(subcontrol.dueDate instanceof Date)) {
+    throw new Error('Invalid date format for dueDate');
+  }
+
   const result = await pool.query(
     `INSERT INTO subcontrols (...) VALUES (...) RETURNING *`,
     [
       controlId,
       subcontrol.status,
       // ...
     ]
   );

Line range hint 20-109: Consider implementing database constraints

To ensure data integrity, consider adding database constraints for:

  1. Foreign key relationship between subcontrols and controls
  2. Required fields (status, owner)
  3. Valid status values using ENUM or CHECK constraints

Would you like me to provide the SQL statements for adding these constraints?

Clients/src/presentation/pages/ComplianceTracker/controls.req.structure.ts (1)

41-43: Replace hardcoded IDs with placeholder comments.

Using specific IDs in example data could be misleading. Consider using more generic placeholders.

-  projectId: 1234, // id of the project that the control category is related to
-  controlCategoryTitle: "AI literacy",
-  controlCategoryId: 1, // After control Category is created id will be saved in a const
+  projectId: 0, // Example project ID
+  controlCategoryTitle: "Example Category",
+  controlCategoryId: 0, // Example category ID
Clients/src/presentation/components/Table/AccordionTable/index.tsx (3)

Line range hint 97-108: Remove console.log and update OnSave implementation.

The OnSave callback contains a console.log statement and a commented-out function call.

-                OnSave={() => {
-                  console.log("Save clicked");
-                  // fetchComplianceTracker();
-                }}
+                OnSave={async () => {
+                  try {
+                    await fetchComplianceTracker();
+                  } catch (error) {
+                    // Handle error appropriately
+                    console.error('Failed to save:', error);
+                  }
+                }}

Line range hint 166-166: Update useMemo dependencies for tableBody.

The useMemo dependencies array is missing the newly added controlCategory prop.

-    [rows, modalOpen, selectedRow, getProgressColor, theme.palette.grey, id]
+    [rows, modalOpen, selectedRow, getProgressColor, theme.palette.grey, id, controlCategory]

Line range hint 13-32: Consider splitting component responsibilities.

The AccordionTable component handles multiple responsibilities including table rendering, modal management, and progress calculation. Consider splitting these into separate components for better maintainability.

Would you like me to provide an example of how to split this component into smaller, more focused components?

Servers/controllers/control.ctrl.ts (2)

Line range hint 124-138: Consider wrapping DB operations in a transaction.

Multiple database operations are performed in sequence. If any operation fails, the database could be left in an inconsistent state.

Consider wrapping the operations in a transaction:

- mainLoop: for (const controlGroup of controlGroups) {
+ const transaction = await prisma.$transaction(async (tx) => {
+   mainLoop: for (const controlGroup of controlGroups) {
      // ... existing code ...
+   }
+ });

Line range hint 124-143: Consider optimizing nested loops performance.

The current implementation uses triple-nested loops which could be inefficient for large datasets.

Consider using batch operations or reducing nesting:

+ const flattenedControls = controlGroups.flatMap(group => 
+   group.control.flatMap(ctrl => 
+     ctrl.controls.map(control => ({
+       control,
+       subControls: control.subControls
+     }))
+   )
+ );
+ 
+ for (const { control, subControls } of flattenedControls) {
+   // Process control and subControls
+ }
Servers/controllers/assessment.ctrl.ts (2)

Line range hint 229-270: Add error handling in non-mock path.

The non-mock path lacks try-catch blocks and proper error handling.

Add error handling:

} else {
+  try {
     // first get all assessments
     const assessments = await getAllAssessmentsQuery();
     // ... existing code ...
+    return res.status(200).json(STATUS_CODE[200]({ message: "Answers saved" }));
+  } catch (error) {
+    return res.status(500).json(STATUS_CODE[500]((error as Error).message));
+  }
}

Line range hint 229-270: Add input validation.

The function lacks validation for required fields and data structure.

Add validation before processing:

if (!req.body.topic || !req.body.subtopic || !Array.isArray(req.body.subtopic)) {
  return res.status(400).json(STATUS_CODE[400]({ 
    message: "Invalid request body structure" 
  }));
}
Clients/src/presentation/components/Modals/Controlpane/NewControlPane.tsx (1)

51-51: Add prop validation and documentation

The new props lack proper documentation and validation.

Add prop types validation and JSDoc comments:

+/**
+ * @param {Object} props
+ * @param {string} props.numbering - The control numbering in format X.Y
+ * @param {string} props.controlCategory - The category of the control
+ */
 const NewControlPane = ({
   id,
   numbering,
   isOpen,
   handleClose,
   title,
   content,
   subControls,
   controlCategory,
   OnSave,
 }: {
   id: string;
-  numbering: string;
+  numbering: string; // Format: X.Y where X and Y are numbers
   isOpen: boolean;
   handleClose: () => void;
   title: string;
   content: string;
   subControls: any[];
-  controlCategory: string;
+  controlCategory: string; // Must be one of the valid control categories
   OnSave?: (state: State) => void;
 }) => {
+  // Validate numbering format
+  if (!/^\d+\.\d+$/.test(numbering)) {
+    console.warn('Invalid numbering format. Expected X.Y where X and Y are numbers');
+  }

Also applies to: 57-57, 61-61, 67-67

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 65af1ec and baeef19.

📒 Files selected for processing (20)
  • Clients/src/presentation/components/Inputs/Dropdowns/index.tsx (3 hunks)
  • Clients/src/presentation/components/Inputs/Field/index.tsx (4 hunks)
  • Clients/src/presentation/components/Modals/ComplianceFeedback/ComplianceFeedback.tsx (1 hunks)
  • Clients/src/presentation/components/Modals/Controlpane/NewControlPane.tsx (5 hunks)
  • Clients/src/presentation/components/Table/AccordionTable/index.tsx (3 hunks)
  • Clients/src/presentation/pages/ComplianceTracker/NewComplianceTracker.tsx (1 hunks)
  • Clients/src/presentation/pages/ComplianceTracker/controls.req.structure.ts (1 hunks)
  • Servers/controllers/assessment.ctrl.ts (1 hunks)
  • Servers/controllers/control.ctrl.ts (1 hunks)
  • Servers/controllers/controlCategory.ctrl.ts (1 hunks)
  • Servers/controllers/project.ctrl.ts (2 hunks)
  • Servers/controllers/subcontrol.ctrl.ts (1 hunks)
  • Servers/mocks/controlCategory.mock.data.ts (1 hunks)
  • Servers/mocks/tools/control.mock.db.ts (1 hunks)
  • Servers/mocks/tools/controlCategory.mock.db.ts (1 hunks)
  • Servers/models/controlCategory.model.ts (1 hunks)
  • Servers/routes/controlCategory.route.ts (1 hunks)
  • Servers/routes/project.route.ts (2 hunks)
  • Servers/utils/controlCategory.util.ts (1 hunks)
  • Servers/utils/subControl.utils.ts (1 hunks)
🔇 Additional comments (11)
Servers/controllers/project.ctrl.ts (1)

263-263: ⚠️ Potential issue

Fix incorrect property assignment

In the real database operation, the projectId is incorrectly set to controlCategoryId. This should be controlCategoryId instead.

Apply this diff to correct the assignment:

- projectId: controlCategoryId, // now must be replaced with controlCategoryId
+ controlCategoryId: controlCategoryId,

Likely invalid or redundant comment.

Servers/models/controlCategory.model.ts (1)

1-5: LGTM!

The definition of the ControlCategory type is clear and follows TypeScript conventions.

Servers/mocks/tools/control.mock.db.ts (1)

13-24: ⚠️ Potential issue

Multiple issues in control creation logic

  1. Confusing property mapping: projectId is being used for controlCategoryId
  2. Deprecated controlGroup field is still included
  3. Deep nesting in newControl.control structure is error-prone
  4. Lacks type safety
+interface CreateControlInput {
+  status: string;
+  approver: string;
+  riskReview: string;
+  owner: string;
+  reviewer: string;
+  description: string;
+  date: Date;
+  controlCategoryId: number;
+}

-export const createMockControl = (newControl: any): object => {
+export const createMockControl = (input: CreateControlInput): Control => {
   const newControlToSave = {
     id: mockControls.length + 1,
-    status: newControl.control.status,
-    approver: newControl.control.approver,
-    riskReview: newControl.control.riskReview,
-    owner: newControl.control.owner,
-    reviewer: newControl.control.reviewer,
-    implementationDetails: newControl.control.description,
-    dueDate: newControl.control.date,
-    projectId: newControl.controlCategoryId, // it will be controlCategoryId
-    controlGroup: newControl.controlGroup, // This field must be removed in anywhere
+    status: input.status,
+    approver: input.approver,
+    riskReview: input.riskReview,
+    owner: input.owner,
+    reviewer: input.reviewer,
+    implementationDetails: input.description,
+    dueDate: input.date,
+    controlCategoryId: input.controlCategoryId,
   };

Let's verify the removal of controlGroup field across the codebase:

Servers/utils/subControl.utils.ts (1)

20-34: 🛠️ Refactor suggestion

Replace console.log with proper logging

Production code should use a proper logging system instead of console.log for better observability and log management.

+import { Logger } from '../utils/logger';  // Implement or import a logger
+
 export const createNewSubcontrolQuery = async (
   controlId: number,
   subcontrol: {
     status: string;
     approver: string;
     riskReview: string;
     owner: string;
     reviewer: string;
     dueDate: Date;
     implementationDetails: string;
     evidence: string;
     attachment: string;
     feedback: string;
   }
 ): Promise<Subcontrol> => {
-  console.log("createNewSubcontrol", subcontrol);
+  Logger.info('Creating new subcontrol', { controlId, ...subcontrol });

Likely invalid or redundant comment.

Clients/src/presentation/components/Modals/ComplianceFeedback/ComplianceFeedback.tsx (1)

50-57: 🛠️ Refactor suggestion

Review content transformation logic

The current implementation has potential issues:

  1. Prepending a space (" " + content) seems unnecessary and could cause formatting issues
  2. Removing paragraph tags might break rich text formatting, especially if the content is meant to be rendered as HTML later

Consider this alternative implementation:

-      target: {
-        value:
-          " " +
-          content
-            .replace(/^<p>/, "")
-            .replace(/<\/p>$/, "")
-            .trim(),
+      target: {
+        value: content.trim()
+      },

Let's verify how this content is used downstream:

✅ Verification successful

Keep the current content transformation logic

After analyzing the code, the current implementation should be maintained because:

  1. The component uses a RichTextEditor component that provides HTML content
  2. The space prefix and p-tag removal are intentional as the content is used in a form context where the transformed value is stored in the parent component's state (NewControlPane.tsx) for both evidence and feedback fields
  3. The transformation is consistent with how the data is handled in the parent component, which expects plain text input values
  • The content is properly managed in the parent component's state through the onChange handlers for both evidence and feedback sections
  • The transformation maintains consistency between the rich text editor's HTML output and the form's expected plain text input
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of this transformed content
rg -l "ComplianceFeedback.*onChange" 

Length of output: 38


Script:

#!/bin/bash
# Let's try a broader search to understand the component and its usage
rg -A 5 "ComplianceFeedback" 

# Also search for the handleContentChange function
ast-grep --pattern 'handleContentChange = ($$$) => { $$$ }'

# Let's also check if there are any HTML renderers or rich text editors in use
rg -l "dangerouslySetInnerHTML|contentEditable"

Length of output: 815


Script:

#!/bin/bash
# Let's look at the ComplianceFeedback component implementation
cat "Clients/src/presentation/components/Modals/ComplianceFeedback/ComplianceFeedback.tsx"

# Also check NewControlPane for how ComplianceFeedback is used
cat "Clients/src/presentation/components/Modals/Controlpane/NewControlPane.tsx"

Length of output: 13463

Clients/src/presentation/pages/ComplianceTracker/NewComplianceTracker.tsx (1)

86-86: Verify AccordionTable's handling of controlCategory prop

The addition of controlCategory prop improves context passing, but we should verify its implementation in AccordionTable.

Let's check the AccordionTable implementation:

✅ Verification successful

controlCategory prop is properly implemented in AccordionTable

The AccordionTable component correctly:

  • Accepts controlCategory as a required string prop in its interface
  • Passes it down to the NewControlPane component when a row is clicked
  • Uses proper TypeScript typing and prop drilling
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check how controlCategory is used in AccordionTable
ast-grep --pattern 'interface $interface {
  $$$
  controlCategory?: string;
  $$$
}'

# Check for any potential prop drilling
rg -A 5 "controlCategory.*={.*}" 

Length of output: 246


Script:

#!/bin/bash
# Search for AccordionTable component definition and props interface
ast-grep --pattern 'interface $interface {
  $$$
}'

# Search for controlCategory usage
rg "controlCategory" -A 3

# Find AccordionTable component definition
ast-grep --pattern 'const AccordionTable = ($props) => {
  $$$
}'

Length of output: 15477


Script:

#!/bin/bash
# Let's find the AccordionTable component and its props interface more specifically
ast-grep --pattern 'interface $interface {
  $$$
  controlCategory: string;
  $$$
}'

# Find the component implementation
ast-grep --pattern 'const AccordionTable: React.FC<$_> = ({
  $$$
  controlCategory,
  $$$
}) => {
  $$$
}'

# Check for any usage of controlCategory in AccordionTable component
rg -l "controlCategory" "Clients/src/presentation/components/Table/AccordionTable/"

Length of output: 345


Script:

#!/bin/bash
# Let's examine the full content of AccordionTable to see how controlCategory is used
cat Clients/src/presentation/components/Table/AccordionTable/index.tsx

Length of output: 5490

Servers/controllers/control.ctrl.ts (1)

125-126: LGTM! Parameter passing improvement.

The separation of controlId and subControl parameters improves code clarity and maintainability.

Clients/src/presentation/components/Inputs/Field/index.tsx (3)

101-103: LGTM! Improved error state styling.

The border styling for error states now properly uses theme values and maintains consistency.


222-222: LGTM! Typography size adjustment.

The font size adjustment for error messages improves readability.


165-165: Verify overflow behavior for multiline inputs.

The addition of overflowY: "auto" might affect the appearance of multiline inputs.

✅ Verification successful

The overflow behavior for multiline inputs is correctly implemented

Looking at the Field component implementation, I can see that:

  1. The component handles multiline inputs specifically when type="description" (line 151)
  2. For description type, it sets multiline={true} and rows={4} (lines 151-152)
  3. The overflowY: "auto" style is applied to the input element, which is the correct behavior for multiline inputs as it allows scrolling when content exceeds the 4-row height
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of Field component with description type
ast-grep --pattern 'Field type="description"'

Length of output: 47


Script:

#!/bin/bash
# Search for Field component usage with multiline or textarea attributes
rg -U "Field.*?(multiline|textarea)" -A 3

# Also search for Field component with type prop
rg -U "Field.*?type=" -A 3

# Look for the Field component implementation to understand its behavior
ast-grep --pattern 'const Field = $_'

Length of output: 16174

Clients/src/presentation/components/Modals/Controlpane/NewControlPane.tsx (1)

213-213: Verify numbering format consistency

The numbering format is used in multiple places. Ensure it follows a consistent pattern across the application.

Also applies to: 279-279

✅ Verification successful

Numbering format is consistent across the codebase

The numbering format follows a consistent hierarchical pattern using dot notation:

  • Base level: {numbering}
  • Nested level: ${numbering}.${id}

This is consistently implemented in both the AccordionTable and NewControlPane components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other uses of numbering prop in the codebase
rg -l "numbering.*string" src/
rg "numbering\}" src/

Length of output: 146


Script:

#!/bin/bash
# Search for other uses of numbering prop in the codebase
rg -l "numbering.*string" Clients/src/
rg "numbering\}" Clients/src/

# Also search for similar patterns to understand the format
rg -A 2 "numbering" Clients/src/

Length of output: 2033

const controlCategories = await getAllControlCategoriesQuery();
return res.status(200).json(controlCategories);
} catch (error) {
return res.status(500).json(STATUS_CODE[500]((error as Error).message));
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid exposing internal error messages to clients

Returning detailed error messages to clients can reveal sensitive information. Instead, log the error on the server and return a generic message.

Apply this diff to improve error handling:

- return res.status(500).json(STATUS_CODE[500]((error as Error).message));
+ console.error(error);
+ return res.status(500).json(STATUS_CODE[500]("Internal Server Error"));

Also applies to: 54-54, 74-74, 99-99, 119-119

Comment on lines +44 to +45
const controlCategoryId = parseInt(req.params.id);
if (MOCKDATA_ON === true) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Validate and sanitize input parameters

Ensure that controlCategoryId parsed from req.params.id is a valid number before proceeding.

Add validation to handle invalid IDs:

const controlCategoryId = parseInt(req.params.id);
+ if (isNaN(controlCategoryId)) {
+   return res.status(400).json(STATUS_CODE[400]("Invalid control category ID"));
+ }

Also applies to: 83-84, 107-108

Comment on lines +46 to +48
const controlCategory = getMockControlCategoryById(controlCategoryId);
return res.status(200).json(controlCategory);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle cases where resources are not found

When fetching, updating, or deleting a control category, return a 404 status if the resource does not exist.

Add checks to handle not-found scenarios:

// After fetching the control category
if (!controlCategory) {
  return res.status(404).json(STATUS_CODE[404]("Control Category not found"));
}

Also applies to: 50-52, 86-90, 92-96, 110-112, 114-116

res: Response
): Promise<any> {
try {
const newControlCategory: ControlCategory = req.body;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Validate request body data

Ensure required fields are present in req.body before creating or updating a control category.

Add validation for required fields:

const newControlCategory: ControlCategory = req.body;
+ if (!newControlCategory.projectId || !newControlCategory.name) {
+   return res.status(400).json(STATUS_CODE[400]("Missing required fields: projectId and name"));
+ }

Also applies to: 84-84

Comment on lines +261 to +272
const control: any = await createNewControlQuery({
// controlCategoryId: controlCategory.id,
projectId: controlCategoryId, // now must be replaced with controlCategoryId
// title: req.body.control.title,
status: req.body.control.status,
approver: req.body.control.approver,
riskReview: req.body.control.riskReview,
owner: req.body.control.owner,
reviewer: req.body.control.reviewer,
dueDate: req.body.control.date,
implementationDetails: req.body.control.description,
});
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ensure consistency in property names

There is inconsistency in property names between mock data and real database operations, such as contrlTitle vs. controlTitle. Also, some properties are commented out or may not match the expected database schema.

Review and align the property names to match the database schema and ensure all necessary fields are included.

Comment on lines +104 to +108
const controlIdFK = req.body.controlId;
const newSubcontrol = await createNewSubcontrolQuery(
controlIdFK,
subcontrol
);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add type checking and validation for controlIdFK.

The extraction of controlIdFK lacks type checking and validation, which could lead to runtime errors.

-      const controlIdFK = req.body.controlId;
+      const controlIdFK = Number(req.body.controlId);
+      if (!controlIdFK || isNaN(controlIdFK)) {
+        return res.status(400).json(STATUS_CODE[400]('Invalid control ID'));
+      }
       const newSubcontrol = await createNewSubcontrolQuery(
         controlIdFK,
         subcontrol
       );
📝 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 controlIdFK = req.body.controlId;
const newSubcontrol = await createNewSubcontrolQuery(
controlIdFK,
subcontrol
);
const controlIdFK = Number(req.body.controlId);
if (!controlIdFK || isNaN(controlIdFK)) {
return res.status(400).json(STATUS_CODE[400]('Invalid control ID'));
}
const newSubcontrol = await createNewSubcontrolQuery(
controlIdFK,
subcontrol
);

@@ -219,6 +219,7 @@ export async function saveAnswers(req: Request, res: Response): Promise<any> {
createMockQuestion(subtopicId, question);
}
}
res.status(200).json(STATUS_CODE[200]({ message: "Answers saved" }));
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential "headers already sent" error.

The code attempts to send multiple responses in the mock data path.

Remove the redundant status setting:

  res.status(200).json(STATUS_CODE[200]({ message: "Answers saved" }));
} catch (error) {
  return res.status(500).json(STATUS_CODE[500]((error as Error).message));
}
- res.status(200);

Also applies to: 224-226

@@ -14,6 +14,7 @@ import DropDowns from "../../Inputs/Dropdowns";
import { useState } from "react";
import AuditorFeedback from "../ComplianceFeedback/ComplianceFeedback";
import { Dayjs } from "dayjs";
import { apiServices } from "../../../../infrastructure/api/networkServices";
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add proper error handling and loading state management

The new API integration requires better error handling and user feedback mechanisms.

Consider implementing:

  1. Loading state during API calls
  2. Error message display to users
  3. Success notifications
 import { useState } from "react";
+import { useState } from "react";
+const [isLoading, setIsLoading] = useState(false);
+const [error, setError] = useState<string | null>(null);

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +155 to +170
const handleSave = async () => {
const controlToSave = {
controlCategoryTitle: controlCategory,
control: state,
};
console.log(controlToSave);

try {
const response = await apiServices.post(
"/projects/saveControls",
controlToSave
);
console.log("Controls saved successfully:", response);
} catch (error) {
console.error("Error saving controls:", error);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Enhance error handling and add loading state in handleSave

The current implementation needs improvements in error handling and user feedback.

Apply these improvements:

 const handleSave = async () => {
+  setIsLoading(true);
+  setError(null);
   const controlToSave = {
     controlCategoryTitle: controlCategory,
     control: state,
   };
-  console.log(controlToSave);
   try {
     const response = await apiServices.post(
       "/projects/saveControls",
       controlToSave
     );
-    console.log("Controls saved successfully:", response);
+    // Add type safety for response
+    if (!response.ok) {
+      throw new Error('Failed to save controls');
+    }
+    // Show success notification
+    enqueueSnackbar('Controls saved successfully', { variant: 'success' });
   } catch (error) {
-    console.error("Error saving controls:", error);
+    setError(error instanceof Error ? error.message : 'An error occurred');
+    enqueueSnackbar('Failed to save controls', { variant: 'error' });
   } finally {
+    setIsLoading(false);
   }
   if (OnSave) {
     OnSave(state);
   }
 };

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +163 to +166
const response = await apiServices.post(
"/projects/saveControls",
controlToSave
);
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Authentication middleware is disabled for sensitive endpoint

The API endpoint /projects/saveControls has its authentication middleware commented out, potentially exposing sensitive compliance data. Additionally, there's no visible input validation for the control data being saved.

Key issues found:

  • Authentication is disabled: router.post("/saveControls", /*authenticateJWT,*/ saveControls);
  • No input validation before saving control data
  • Raw user input is directly passed to the API endpoint
🔗 Analysis chain

Verify API endpoint security and data sanitization

The component handles sensitive compliance data and makes API calls with user input.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for API endpoint security configuration
rg -A 5 "/projects/saveControls" src/
# Check for data sanitization
rg -l "sanitize|validate" src/infrastructure/api/

Length of output: 198


Script:

#!/bin/bash
# Search for API endpoint security configuration and data validation
# First, find the correct path structure
fd -t f saveControls
fd -t f apiServices
# Then search for API endpoint and validation patterns
rg -A 5 "saveControls"
rg -A 5 "apiServices.post"
# Look for validation or sanitization patterns
rg -A 5 "controlToSave"

Length of output: 7052

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

🧹 Outside diff range and nitpick comments (10)
Servers/controllers/control.ctrl.ts (2)

Line range hint 124-138: Add transaction management for atomic operations

The nested loops perform multiple database operations that should be atomic. If any operation fails, all changes should be rolled back.

    } else {
+     const client = await pool.connect();
+     try {
+       await client.query('BEGIN');
        let flag = true;
        mainLoop: for (const controlGroup of controlGroups) {
          // ... existing code ...
        }
        if (flag) {
+         await client.query('COMMIT');
          return res.status(201).json(STATUS_CODE[201]({}));
        }
+       await client.query('ROLLBACK');
        return res.status(400).json(STATUS_CODE[400]({}));
+     } catch (error) {
+       await client.query('ROLLBACK');
+       throw error;
+     } finally {
+       client.release();
+     }
    }

Line range hint 124-138: Improve error handling with specific messages

The current implementation uses a boolean flag that doesn't provide specific error information. Consider capturing and returning specific error messages.

-      let flag = true;
+      const errors = [];
       mainLoop: for (const controlGroup of controlGroups) {
         for (const ctrl of controlGroup.control) {
           for (const control of ctrl.controls) {
             const controlId = control.id;
             for (const subControl of control.subControls) {
               const newSubControl = await createNewSubcontrolQuery(
                 controlId,
                 subControl
               );
               if (!newSubControl) {
-                flag = false;
-                break mainLoop;
+                errors.push(`Failed to create subcontrol for control ${controlId}`);
+                continue;
               }
             }
             const newControl = await createNewControlQuery(control);
             if (!newControl) {
-              flag = false;
-              break mainLoop;
+              errors.push(`Failed to create control ${control.id}`);
+              continue;
             }
           }
         }
       }
-      if (flag) {
+      if (errors.length === 0) {
         return res.status(201).json(STATUS_CODE[201]({}));
       }
-      return res.status(400).json(STATUS_CODE[400]({}));
+      return res.status(400).json(STATUS_CODE[400]({ errors }));
Servers/controllers/controlCategory.ctrl.ts (1)

28-28: Simplify boolean comparison

Comparing a boolean to true is redundant. You can simplify the condition if (MOCKDATA_ON === true) to if (MOCKDATA_ON).

Apply this diff to fix the issue:

- if (MOCKDATA_ON === true) {
+ if (MOCKDATA_ON) {
Servers/controllers/project.ctrl.ts (2)

241-241: Remove console.log statements in production code

console.log statements can expose sensitive data and clutter the console output. Consider removing them or using a proper logging mechanism with appropriate log levels.

Apply this diff to fix the issue:

- console.log("subcontrolToSave : ", subcontrolToSave);

262-262: Remove commented-out code

Commented-out code can clutter the codebase and reduce readability. Consider removing it if it's no longer needed.

Apply this diff to fix the issue:

- // controlCategoryId: controlCategory.id,
Servers/mocks/controlCategory.mock.data.ts (1)

3-110: Consider using an enum or constants for category names

The category names are repeated across projects and could benefit from centralization to ensure consistency and ease of maintenance.

Example implementation:

export enum ControlCategoryNames {
  AI_LITERACY = "AI literacy",
  TRANSPARENCY = "Transparency and provision of information to deployers",
  // ... other categories
}

export const ControlCategories: ControlCategory[] = [
  { id: 1, projectId: 1, name: ControlCategoryNames.AI_LITERACY },
  { id: 2, projectId: 1, name: ControlCategoryNames.TRANSPARENCY },
  // ... rest of the categories
];
Clients/src/presentation/pages/ComplianceTracker/NewComplianceTracker.tsx (1)

Line range hint 31-42: Add loading and error states for better UX

The fetchComplianceTracker function should handle loading states and display appropriate UI feedback during API calls.

Consider adding loading and error states:

const NewComplianceTracker = () => {
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState<string | null>(null);
  const [expanded, setExpanded] = useState<number | false>(false);
  const { setDashboardValues } = useContext(VerifyWiseContext);

  const fetchComplianceTracker = async () => {
+   setIsLoading(true);
+   setError(null);
    try {
      const response = await getAllEntities({ routeUrl: "/controls" });
      console.log("Response:", response);
      setDashboardValues((prevValues: any) => ({
        ...prevValues,
        compliance: response.data,
      }));
    } catch (error) {
      console.error("Error fetching compliance tracker:", error);
+     setError("Failed to fetch compliance data");
    } finally {
+     setIsLoading(false);
    }
  };
Clients/src/presentation/pages/ComplianceTracker/controls.req.structure.ts (1)

49-55: Define proper enums for status fields

The status fields use string literals which could lead to inconsistencies.

export enum ControlStatus {
  InProgress = 'IN_PROGRESS',
  Done = 'DONE',
  Waiting = 'WAITING'
}

export enum RiskReviewStatus {
  Acceptable = 'ACCEPTABLE_RISK',
  Residual = 'RESIDUAL_RISK',
  Unacceptable = 'UNACCEPTABLE_RISK'
}
Servers/controllers/assessment.ctrl.ts (1)

Line range hint 222-226: Fix duplicate response sending

There's a potential issue where multiple responses could be sent:

  1. Line 222 sends a 200 response with a message
  2. Line 226 sends another 200 response without a body

This could lead to the error: "Cannot set headers after they are sent to the client"

Apply this fix:

      res.status(200).json(STATUS_CODE[200]({ message: "Answers saved" }));
    } catch (error) {
      return res.status(500).json(STATUS_CODE[500]((error as Error).message));
    }
-   res.status(200);
Clients/src/presentation/components/Modals/Controlpane/NewControlPane.tsx (1)

51-67: Consider adding default values for new required props.

The new props numbering and controlCategory are required but lack default values. This could cause runtime issues if these props are accidentally omitted.

Consider adding default values:

const NewControlPane = ({
  id,
  numbering = '',
  isOpen,
  handleClose,
  title,
  content,
  subControls,
  controlCategory = 'default',
  OnSave,
}: {
  id: string;
  numbering: string;
  isOpen: boolean;
  handleClose: () => void;
  title: string;
  content: string;
  subControls: any[];
  controlCategory: string;
  OnSave?: (state: State) => void;
})
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 65af1ec and baeef19.

📒 Files selected for processing (20)
  • Clients/src/presentation/components/Inputs/Dropdowns/index.tsx (3 hunks)
  • Clients/src/presentation/components/Inputs/Field/index.tsx (4 hunks)
  • Clients/src/presentation/components/Modals/ComplianceFeedback/ComplianceFeedback.tsx (1 hunks)
  • Clients/src/presentation/components/Modals/Controlpane/NewControlPane.tsx (5 hunks)
  • Clients/src/presentation/components/Table/AccordionTable/index.tsx (3 hunks)
  • Clients/src/presentation/pages/ComplianceTracker/NewComplianceTracker.tsx (1 hunks)
  • Clients/src/presentation/pages/ComplianceTracker/controls.req.structure.ts (1 hunks)
  • Servers/controllers/assessment.ctrl.ts (1 hunks)
  • Servers/controllers/control.ctrl.ts (1 hunks)
  • Servers/controllers/controlCategory.ctrl.ts (1 hunks)
  • Servers/controllers/project.ctrl.ts (2 hunks)
  • Servers/controllers/subcontrol.ctrl.ts (1 hunks)
  • Servers/mocks/controlCategory.mock.data.ts (1 hunks)
  • Servers/mocks/tools/control.mock.db.ts (1 hunks)
  • Servers/mocks/tools/controlCategory.mock.db.ts (1 hunks)
  • Servers/models/controlCategory.model.ts (1 hunks)
  • Servers/routes/controlCategory.route.ts (1 hunks)
  • Servers/routes/project.route.ts (2 hunks)
  • Servers/utils/controlCategory.util.ts (1 hunks)
  • Servers/utils/subControl.utils.ts (1 hunks)
🔇 Additional comments (17)
Servers/utils/subControl.utils.ts (2)

20-34: LGTM! Good separation of controlId parameter

The refactoring to separate controlId from the subcontrol object improves the function's interface by making the relationship between controls and subcontrols more explicit. The TypeScript types are well-defined and maintain type safety.


Line range hint 42-52: Verify database schema constraints

The SQL parameters are correctly ordered to match the columns. However, we should ensure that the database has appropriate foreign key constraints for the controlId relationship.

Servers/controllers/control.ctrl.ts (1)

125-126: LGTM! Correct usage of separated controlId parameter

The changes correctly adapt to the new createNewSubcontrolQuery signature by passing controlId as a separate parameter.

Servers/controllers/controlCategory.ctrl.ts (6)

74-74: Avoid exposing internal error messages to the client


83-83: Specify radix when using parseInt


84-84: Validate input data to prevent unexpected errors


98-98: Avoid exposing internal error messages to the client


107-107: Specify radix when using parseInt


118-118: Avoid exposing internal error messages to the client

Servers/controllers/project.ctrl.ts (1)

283-283: Remove console.log statements in production code

Servers/models/controlCategory.model.ts (1)

1-5: Type definition for ControlCategory is well-defined

The type definition correctly specifies the required and optional properties for ControlCategory.

Servers/routes/project.route.ts (1)

21-21: New route /saveControls added successfully

The route /saveControls has been correctly added to handle saving controls.

Clients/src/presentation/components/Modals/ComplianceFeedback/ComplianceFeedback.tsx (1)

Line range hint 8-8: Verify file size constant usage

Ensure that MAX_FILE_SIZE from constants matches any server-side upload limits.

Clients/src/presentation/pages/ComplianceTracker/NewComplianceTracker.tsx (1)

86-86: LGTM: controlCategory prop addition

The addition of controlCategory prop to AccordionTable component aligns with the PR objective of iterating compliance store in the database.

Clients/src/presentation/components/Table/AccordionTable/index.tsx (2)

26-26: LGTM: Type-safe prop addition

The controlCategory prop is properly typed as a string and added to both the destructured props and the interface.

Also applies to: 31-31


97-98: Verify the impact of id prop splitting

The separation of id and numbering props might affect how controls are identified in the system. While the change looks logical, we should ensure this doesn't break any existing functionality.

Also applies to: 108-108

✅ Verification successful

The separation of id and numbering props is correctly implemented

Looking at the NewControlPane component implementation, both id and numbering props are properly defined in the interface and used consistently throughout the component:

  • The id prop is used for unique identification in state management and DOM elements
  • The numbering prop is used for display purposes in the UI
  • This separation of concerns is maintained consistently in the modal, tabs, and dropdown components
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other uses of NewControlPane to verify consistent prop usage
ast-grep --pattern 'NewControlPane $$$'

# Search for any direct references to the id prop
rg "id={.*?}" --type tsx

Length of output: 163


Script:

#!/bin/bash
# Search for other uses of NewControlPane to verify consistent prop usage
ast-grep --pattern 'NewControlPane'

# Search for any direct references to the id prop with proper regex escaping
rg "id=\{[^}]+\}" --type tsx -A 2

# Search for numbering prop usage
rg "numbering=\{[^}]+\}" --type tsx -A 2

Length of output: 622


Script:

#!/bin/bash
# Let's check the NewControlPane component definition to understand the props
cat Clients/src/presentation/components/Modals/Controlpane/NewControlPane.tsx

# Search for id and numbering props with correct file type
rg "id=\{[^}]+\}" -t typescript -t typescriptreact -A 2
rg "numbering=\{[^}]+\}" -t typescript -t typescriptreact -A 2

Length of output: 10153

Clients/src/presentation/components/Inputs/Field/index.tsx (1)

101-103: LGTM: Improved error border handling

The error border styling is now more explicit and consistent with the theme system.

Comment on lines +104 to +108
const controlIdFK = req.body.controlId;
const newSubcontrol = await createNewSubcontrolQuery(
controlIdFK,
subcontrol
);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove redundant controlId from subcontrol object

Since controlId is now passed separately as controlIdFK, it should be removed from the subcontrol object to avoid potential inconsistencies.

-    const subcontrol: {
-      controlId: number;  // Remove this
+    const subcontrol: {
       status: string;
       approver: string;
       // ... other fields
     } = req.body;

Committable suggestion skipped: line range outside the PR's diff.


⚠️ Potential issue

Add validation for controlIdFK

The controlIdFK is extracted from req.body but lacks validation. Consider adding these checks:

  1. Ensure controlIdFK is a valid number
  2. Verify that controlIdFK exists in the controls table before creating the subcontrol
-      const controlIdFK = req.body.controlId;
+      const controlIdFK = parseInt(req.body.controlId);
+      if (isNaN(controlIdFK)) {
+        return res.status(400).json(STATUS_CODE[400]('Invalid controlId'));
+      }
+      // Verify control exists
+      const control = await getControlByIdQuery(controlIdFK);
+      if (!control) {
+        return res.status(404).json(STATUS_CODE[404]('Control not found'));
+      }
       const newSubcontrol = await createNewSubcontrolQuery(
         controlIdFK,
         subcontrol
       );

Committable suggestion skipped: line range outside the PR's diff.

res: Response
): Promise<any> {
try {
const newControlCategory: ControlCategory = req.body;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Validate input data to prevent unexpected errors

Directly assigning req.body to newControlCategory without validation may lead to issues if required fields are missing or invalid. Implement input validation to ensure all necessary fields are present and correctly formatted.

res: Response
): Promise<any> {
try {
const controlCategoryId = parseInt(req.params.id);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Specify radix when using parseInt

Using parseInt without specifying the radix can lead to unexpected results. Always specify the radix parameter to ensure consistent behavior.

Apply this diff to fix the issue:

- const controlCategoryId = parseInt(req.params.id);
+ const controlCategoryId = parseInt(req.params.id, 10);
📝 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 controlCategoryId = parseInt(req.params.id);
const controlCategoryId = parseInt(req.params.id, 10);

);
return res.status(200).json(controlCategory);
} catch (error) {
return res.status(500).json(STATUS_CODE[500]((error as Error).message));
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid exposing internal error messages to the client

Returning detailed error messages to the client can expose sensitive information. Consider logging the error internally and returning a generic message.

Apply this diff to fix the issue:

- return res.status(500).json(STATUS_CODE[500]((error as Error).message));
+ console.error(error);
+ return res.status(500).json(STATUS_CODE[500]("Internal Server 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
return res.status(500).json(STATUS_CODE[500]((error as Error).message));
console.error(error);
return res.status(500).json(STATUS_CODE[500]("Internal Server Error"));

const control: any = createMockControl({
controlCategoryId: controlCategory.id,
control: {
contrlTitle: req.body.control.controlTitle,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in property name contrlTitle

There's a typo in the property name contrlTitle. It should be controlTitle.

Apply this diff to fix the issue:

- contrlTitle: req.body.control.controlTitle,
+ controlTitle: req.body.control.controlTitle,
📝 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
contrlTitle: req.body.control.controlTitle,
controlTitle: req.body.control.controlTitle,

Comment on lines +40 to +77
export const controlsReqStructure = {
projectId: 1234, // id of the project that the control category is related to
controlCategoryTitle: "AI literacy",
controlCategoryId: 1, // After control Category is created id will be saved in a const
control: {
controlCategoryId: 1, // The control category id that the control is related to
controlId: 1, // After control is created id will be saved in a const
controlTitle: "AI Literacy and Responsible AI Training",
controlDescription: "Develop the AI literacy ...",
status: "selected option",
approver: "selected option",
riskReview: "selected option",
owner: "selected option",
reviewer: "selected option",
date: "selected date",
description: "provided description",
subcontrols: [
{
controlId: 1, // The control id that the subcontrol is related to
subControlTitle:
"We ensure executive leadership takes responsibility for decisions related to AI risks",
subControlDescription:
"Leadership is accountable for oversight and strategic decisions regarding AI risks, ensuring alignment with compliance.",
status: "selected option",
approver: "selected option",
riskReview: "selected option",
owner: "selected option",
reviewer: "selected option",
date: "selected date",
description: "provided description",
evidence: "provided evidence",
evidenceFiles: [],
feedback: "provided feedback",
feedbackFiles: [],
},
],
},
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance type safety with TypeScript interfaces

The request structure uses primitive types and contains example values. Let's improve type safety and separate concerns.

  1. Create proper TypeScript interfaces:
interface SubControl {
  controlId: number;
  subControlTitle: string;
  subControlDescription: string;
  status: ControlStatus;
  approver: string;
  riskReview: RiskReviewStatus;
  owner: string;
  reviewer: string;
  date: string;
  description: string;
  evidence: string;
  evidenceFiles: Array<unknown>; // Define proper type
  feedback: string;
  feedbackFiles: Array<unknown>; // Define proper type
}

interface Control {
  controlCategoryId: number;
  controlId: number;
  controlTitle: string;
  controlDescription: string;
  status: ControlStatus;
  approver: string;
  riskReview: RiskReviewStatus;
  owner: string;
  reviewer: string;
  date: string;
  description: string;
  subcontrols: SubControl[];
}

interface ControlsRequest {
  projectId: number;
  controlCategoryTitle: string;
  controlCategoryId: number;
  control: Control;
}

export const controlsReqStructure: ControlsRequest;
  1. Move example values to a separate file:
// controls.examples.ts
export const exampleControlsRequest: ControlsRequest = {
  projectId: 1234,
  controlCategoryTitle: "AI literacy",
  // ... rest of the example
};

@@ -143,6 +143,7 @@ const Field = forwardRef(
</Typography>
)}
<TextField
className="field-input"
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Add accessibility enhancements for scrollable content

The review comment is valid. The component uses overflowY: "auto" in the input props but lacks proper accessibility considerations:

  • No max-height constraint is defined to prevent excessive scrolling
  • Missing ARIA attributes for scrollable content
  • No visible scrolling indicators for keyboard users

Specific locations that need attention:

  • Line 146: Add aria-multiline="true" when type === "description"
  • Line 165: Add maxHeight constraint in the inputProps.sx object
  • Consider adding role="textbox" with aria-multiline="true" for better screen reader support
🔗 Analysis chain

Consider accessibility implications of overflow behavior

While adding overflowY: "auto" improves the visual experience, ensure that the content remains accessible when scrolling.

Consider adding:

  1. A max-height constraint to prevent excessive scrolling
  2. Aria attributes for better screen reader support

Also applies to: 165-165


The previous search for TextField didn't yield results, so let's look for the specific class name and related accessibility attributes to better understand the current implementation and verify the overflow concerns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other TextField components to verify consistent overflow handling
ast-grep --pattern 'TextField $$$'

Length of output: 36


Script:

#!/bin/bash
# Search for the Field component implementation and its usage of overflow properties
rg -U "className=\"field-input\"" -A 5 -B 5

# Search for any aria attributes related to overflow or scrolling
rg "aria-" --type tsx

# Look for style definitions related to field-input
rg "field-input" --type css --type scss

Length of output: 1142


Script:

#!/bin/bash
# Search for aria attributes without file type restriction
rg "aria-"

# Search for field-input class styles without file type restriction
rg "\.field-input"

# Look for the complete Field component implementation to understand the context
rg -U "export.*Field.*" -A 20 Clients/src/presentation/components/Inputs/Field/index.tsx

Length of output: 2304


Script:

#!/bin/bash
# Get the full content of the Field component file to understand the complete implementation
cat Clients/src/presentation/components/Inputs/Field/index.tsx

# Look for any CSS/SCSS files in the component directory
fd -e css -e scss . Clients/src/presentation/components/Inputs/Field/

Length of output: 7544


Script:

#!/bin/bash
# Let's check the CSS file to see any existing overflow or accessibility-related styles
cat Clients/src/presentation/components/Inputs/Field/index.css

Length of output: 941

@@ -191,7 +210,7 @@ const NewControlPane = ({
}}
>
<Typography fontSize={16} fontWeight={600} sx={{ textAlign: "left" }}>
{id} {title}
{numbering} {title}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add input validation and improve accessibility for numbering display.

The numbering display needs validation and security improvements:

  1. No validation of numbering format
  2. Potential XSS vulnerability
  3. Missing accessibility attributes

Consider these improvements:

- <Typography fontSize={16} fontWeight={600} sx={{ textAlign: "left" }}>
-   {numbering} {title}
- </Typography>
+ <Typography 
+   fontSize={16} 
+   fontWeight={600} 
+   sx={{ textAlign: "left" }}
+   aria-label={`Control ${numbering}: ${title}`}
+ >
+   {sanitizeInput(numbering)} {sanitizeInput(title)}
+ </Typography>

// Add utility function at the top of the file
+ const sanitizeInput = (input: string) => {
+   // Basic XSS prevention
+   return input.replace(/[<>]/g, '');
+ };

// Add prop validation
+ if (!/^\d+(\.\d+)*$/.test(numbering)) {
+   console.warn(`Invalid numbering format: ${numbering}. Expected format: "1.2.3"`);
+ }

Apply similar changes to the subcontrol title display at line 279.

Also applies to: 279-279

OnSave,
}: {
id: string;
numbering: string;
isOpen: boolean;
handleClose: () => void;
title: string;
content: string;
subControls: any[];
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Define proper TypeScript interface for subControls.

Using any[] for subControls loses TypeScript's type safety benefits and could lead to runtime errors.

Add a proper interface:

interface SubControl {
  id: string;
  title: string;
  description: string;
  subControlId?: string;
}

// Update props interface
interface NewControlPaneProps {
  id: string;
  numbering: string;
  isOpen: boolean;
  handleClose: () => void;
  title: string;
  content: string;
  subControls: SubControl[];
  controlCategory: string;
  OnSave?: (state: State) => void;
}

Comment on lines +155 to +170
const handleSave = async () => {
const controlToSave = {
controlCategoryTitle: controlCategory,
control: state,
};
console.log(controlToSave);

try {
const response = await apiServices.post(
"/projects/saveControls",
controlToSave
);
console.log("Controls saved successfully:", response);
} catch (error) {
console.error("Error saving controls:", error);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Enhance error handling and user feedback in save operation.

The current implementation has several areas for improvement:

  1. No loading state during API call
  2. Missing user feedback for success/error cases
  3. Modal stays open after successful save
  4. Potential race condition between API call and OnSave callback

Consider this improved implementation:

+ const [isSaving, setIsSaving] = useState(false);

  const handleSave = async () => {
+   setIsSaving(true);
    const controlToSave = {
      controlCategoryTitle: controlCategory,
      control: state,
    };

    try {
      const response = await apiServices.post(
        "/projects/saveControls",
        controlToSave
      );
-     console.log("Controls saved successfully:", response);
+     if (OnSave) {
+       OnSave(state);
+     }
+     handleClose();
+     // Consider using a toast notification system
+     alert('Changes saved successfully');
    } catch (error) {
-     console.error("Error saving controls:", error);
+     // Consider using a toast notification system
+     alert('Failed to save changes: ' + error.message);
    } finally {
+     setIsSaving(false);
    }
-   if (OnSave) {
-     OnSave(state);
-   }
  };

Also update the Save button to show loading state:

  <Button
    variant="contained"
    onClick={handleSave}
+   disabled={isSaving}
    sx={{
      ...buttonStyle,
      width: 68,
      "&:hover": {
        backgroundColor: "#175CD3 ",
      },
    }}
    disableRipple
  >
-   Save
+   {isSaving ? 'Saving...' : 'Save'}
  </Button>

Committable suggestion skipped: line range outside the PR's diff.

@MuhammadKhalilzadeh MuhammadKhalilzadeh merged commit a21e192 into bluewave-labs:master Dec 13, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend Backend related tasks/issues frontend Frontend related tasks/issues team work and collaboration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant