Skip to content

Conversation

@charurajput16
Copy link
Contributor

@charurajput16 charurajput16 commented May 7, 2025

Describe your changes

  1. Remove hardcode values for frameworks.
  2. Use end points /frameworks to fetch the frameworks from backend.

Write your issue number after "Fixes "

Fixes #1308

Please ensure all items are checked off before requesting a review:

  • I deployed the code locally.
  • I have performed a self-review of my code.
  • I have included the issue # in the PR.
  • I have labelled the PR correctly.
  • The issue I am working on is assigned to me.
  • I didn't use any hardcoded values (otherwise it will not scale, and will make it difficult to maintain consistency across the application).
  • I made sure font sizes, color choices etc are all referenced from the theme.
  • My PR is granular and targeted to one specific feature.
  • I took a screenshot or a video and attached to this PR if there is a UI change.

Summary by CodeRabbit

  • New Features
    • Frameworks are now loaded dynamically with real-time loading indicators and error handling.
    • Users can refresh the list of frameworks manually.
  • Improvements
    • Framework selection and display updated to use framework names and numeric IDs.
    • Enhanced error alerts and retry options if framework data fails to load.
    • Streamlined tab content with improved handling for unsupported or missing frameworks.
  • Bug Fixes
    • Improved reliability and accuracy of framework data shown to users.

@charurajput16 charurajput16 added this to the 1.0 milestone May 7, 2025
@charurajput16 charurajput16 self-assigned this May 7, 2025
@charurajput16 charurajput16 added frontend Frontend related tasks/issues backend Backend related tasks/issues labels May 7, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 7, 2025

Walkthrough

A new useFrameworks React hook and repository function were introduced to fetch framework data from the backend. The Framework type was updated, and the ProjectFrameworks component was refactored to dynamically load and display frameworks, replacing hardcoded framework tabs with data-driven rendering and adding error/loading states.

Changes

File(s) Change Summary
Clients/src/application/hooks/useFrameworks.ts Added a new useFrameworks React hook to fetch and manage framework data, including loading, error, and refresh logic.
Clients/src/application/repository/entity.repository.ts Added getAllFrameworks function to perform an authenticated GET request to the /frameworks endpoint and return framework data.
Clients/src/domain/types/Framework.ts Updated Framework type: changed id to number, added required name, description, created_at, and made is_demo and project_id optional.
Clients/src/presentation/pages/ProjectView/ProjectFrameworks/index.tsx Refactored ProjectFrameworks to use the new useFrameworks hook, replacing static framework list with dynamic backend data, updating tab logic to use numeric IDs, adding error/loading handling, and consolidating content rendering.

Sequence Diagram(s)

sequenceDiagram
    participant UI as ProjectFrameworks Component
    participant Hook as useFrameworks Hook
    participant Repo as getAllFrameworks
    participant API as Backend API

    UI->>Hook: useFrameworks()
    activate Hook
    Hook->>Repo: getAllFrameworks()
    activate Repo
    Repo->>API: GET /frameworks (with auth token)
    API-->>Repo: Frameworks data
    deactivate Repo
    Repo-->>Hook: Frameworks data
    Hook-->>UI: { frameworks, loading, error, refreshFrameworks }
    deactivate Hook
    UI->>UI: Render tabs and content based on frameworks data
Loading

Assessment against linked issues

Objective Addressed Explanation
Fetch frameworks from backend instead of hardcoded tabs (#1308)

Poem

In the garden of code, new frameworks bloom bright,
No more hardcoded tabs, just data in flight!
With hooks and new types, we fetch and we show,
Loading and errors, the UI will know.
A backend bouquet, for all to admire—
This rabbit’s delighted, the code’s hopping higher! 🐇✨

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this 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.

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.

@charurajput16
Copy link
Contributor Author

Screenshot 2025-05-07 at 2 28 57 PM

Copy link
Contributor

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

🧹 Nitpick comments (8)
Clients/src/application/repository/entity.repository.ts (1)

290-297: Function implementation looks good, but JSDoc is missing.

The implementation follows the repository pattern established in the codebase, but unlike other functions in this file, it's missing JSDoc documentation.

Add JSDoc documentation for consistency:

+/**
+ * Fetches all frameworks from the API.
+ *
+ * @param {RequestParams} params - The parameters for the request.
+ * @returns {Promise<any>} A promise that resolves to the list of frameworks.
+ * @throws Will throw an error if the request fails.
+ */
export async function getAllFrameworks({
  authToken = getAuthToken(),
}: RequestParams): Promise<any> {
  const response = await apiServices.get("/frameworks", {
    headers: { Authorization: `Bearer ${authToken}` },
  });
  return response.data;
}
Clients/src/application/hooks/useFrameworks.ts (2)

20-26: Consider more robust response validation.

The current validation only checks if response?.data exists, but doesn't verify that it's an array of Framework objects.

try {
  setLoading(true);
  const response = await getAllFrameworks({ routeUrl: "/frameworks" });
-  if (response?.data) {
+  if (response?.data && Array.isArray(response.data)) {
    setFrameworks(response.data);
    setError(null);
  } else {
-    throw new Error("Invalid response format");
+    throw new Error("Invalid response format: expected an array of frameworks");
  }
} catch (err) {

17-34: Consider adding pagination support for scalability.

If the number of frameworks grows significantly, fetching all at once might become inefficient.

For better scalability, consider adding pagination support to the hook:

  1. Add pagination parameters to the hook interface
  2. Pass these parameters to the API call
  3. Return pagination metadata along with the frameworks

This would make the hook more future-proof as the application scales.

Clients/src/presentation/pages/ProjectView/ProjectFrameworks/index.tsx (5)

71-79: Show a proper loading state instead of “Coming Soon” while fetching

When frameworks are still loading, currentFramework is undefined,
which currently yields the “Coming Soon” placeholder – a confusing message
for users who are simply waiting for data.

-  if (!currentFramework) {
-    return <ComingSoonMessage />;
-  }
+  if (loading) {
+    return (
+      <VWSkeleton variant="rectangular" width="100%" height={400} />
+    );
+  }
+
+  if (!currentFramework) {
+    return <ComingSoonMessage />;
+  }

80-80: Replace magic number with a named constant

Hard-coding 1 makes the intent opaque and fragile. Extract a constant
(or better, fetch a flag from the backend) so the value lives in one place.

+// Temporary until the backend delivers a “primary” flag
+const EU_AI_ACT_ID = 1;
 ...
-  const isEUAIAct = currentFramework.id === 1; // EU AI Act framework ID
+  const isEUAIAct = currentFramework.id === EU_AI_ACT_ID;

116-131: Use semantic, focus-able elements for framework tabs

Rendering tabs as bare <Box> elements hurts accessibility (no keyboard
focus, no ARIA semantics). Wrap them in ButtonBase (or reuse Tab)
to gain keyboard navigation and screen-reader support.

-import { Box, Button, Tab, Typography, Stack, Alert } from '@mui/material';
+import { Box, Button, Tab, Typography, Stack, Alert, ButtonBase } from '@mui/material';
 ...
-<Box
-  key={fw.id}
-  onClick={() => handleFrameworkChange(fw.id)}
-  sx={getFrameworkTabStyle(isActive, idx === frameworks.length - 1)}
->
-  {fw.name}
-</Box>
+<ButtonBase
+  key={fw.id}
+  onClick={() => handleFrameworkChange(fw.id)}
+  sx={getFrameworkTabStyle(isActive, idx === frameworks.length - 1)}
+  disableRipple
+>
+  {fw.name}
+</ButtonBase>

133-135: Wire up the “Add new framework” button

The button is currently inert and may confuse users.

-<Button variant="contained" sx={addButtonStyle}>
+<Button
+  variant="contained"
+  sx={addButtonStyle}
+  onClick={handleAddFramework}   // TODO: implement
+>
   Add new framework
 </Button>

Consider disabling the button or adding a tooltip until the handler is
implemented.


158-162: Avoid rendering the same content twice

renderFrameworkContent() is executed for both panels on every render,
doubling work (API calls, heavy components, etc.). Compute once and pass
the result to the active panel:

-<TabPanel value="compliance" sx={tabPanelStyle}>
-  {renderFrameworkContent()}
-</TabPanel>
-<TabPanel value="assessment" sx={tabPanelStyle}>
-  {renderFrameworkContent()}
-</TabPanel>
+{['compliance', 'assessment'].map(value => (
+  <TabPanel key={value} value={value} sx={tabPanelStyle}>
+    {frameworkContent}
+  </TabPanel>
+))}
const frameworkContent = useMemo(renderFrameworkContent, [
  project,
  currentFramework,
  tracker,
  loading,
]);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4a3ab11 and b58df7b.

📒 Files selected for processing (5)
  • Clients/src/application/hooks/useFrameworks.ts (1 hunks)
  • Clients/src/application/repository/entity.repository.ts (1 hunks)
  • Clients/src/domain/types/Framework.ts (1 hunks)
  • Clients/src/presentation/pages/Home/1.0Home/index.tsx (5 hunks)
  • Clients/src/presentation/pages/ProjectView/ProjectFrameworks/index.tsx (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
Clients/src/application/repository/entity.repository.ts (1)
Clients/src/infrastructure/api/networkServices.ts (1)
  • apiServices (63-206)
Clients/src/application/hooks/useFrameworks.ts (2)
Clients/src/domain/types/Framework.ts (1)
  • Framework (1-8)
Clients/src/application/repository/entity.repository.ts (1)
  • getAllFrameworks (290-297)
Clients/src/presentation/pages/Home/1.0Home/index.tsx (1)
Clients/src/application/hooks/useFetchProjects.ts (1)
  • useProjectData (6-22)
🔇 Additional comments (8)
Clients/src/domain/types/Framework.ts (1)

2-7: Good update to accommodate backend data structure.

The type changes properly align with the dynamic framework data being fetched from the backend. Changing id from string to number matches the numeric IDs used in the framework system, and the additional required fields (name, description, created_at) provide better type safety for the fetched data.

Clients/src/presentation/pages/Home/1.0Home/index.tsx (5)

15-15: Removed unused import.

The unnecessary import space was properly removed.


33-36: Clean approach to disable code by commenting.

Commenting out the state declarations is a clean way to remove the feature while preserving the code for potential future reference or rollback.


45-45: Updated destructuring to remove unused loading state.

The loading state is no longer being used since the progress trackers were removed, so it was correctly removed from the destructuring.


68-75: Clean approach to disable API calls by commenting.

Commenting out the API calls is consistent with removing the feature while preserving the code structure.


105-112: Consistently disabled all related API calls.

All related API calls were properly commented out, maintaining consistency in the codebase.

Clients/src/application/hooks/useFrameworks.ts (2)

5-10: Well-defined interface for hook return values.

The interface clearly defines the return structure of the hook, making it easy to understand and use.


12-46: Well-implemented custom hook with proper state management.

This hook follows React best practices:

  • Uses appropriate useState hooks for data, loading, and error states
  • Implements useCallback for the fetch function to prevent unnecessary re-renders
  • Properly handles loading states, errors, and success scenarios
  • Returns a clean interface with the data and a refresh function

Comment on lines +290 to 297
export async function getAllFrameworks({
authToken = getAuthToken(),
}: RequestParams): Promise<any> {
const response = await apiServices.get("/frameworks", {
headers: { Authorization: `Bearer ${authToken}` },
});
return response.data;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Missing error handling in getAllFrameworks function.

The function doesn't have any error handling, unlike other similar functions in this file that use try/catch blocks to log errors and rethrow them.

Add error handling for consistency with other repository functions:

export async function getAllFrameworks({
  authToken = getAuthToken(),
}: RequestParams): Promise<any> {
+  try {
    const response = await apiServices.get("/frameworks", {
      headers: { Authorization: `Bearer ${authToken}` },
    });
    return response.data;
+  } catch (error) {
+    console.error("Error fetching frameworks:", error);
+    throw 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
export async function getAllFrameworks({
authToken = getAuthToken(),
}: RequestParams): Promise<any> {
const response = await apiServices.get("/frameworks", {
headers: { Authorization: `Bearer ${authToken}` },
});
return response.data;
}
export async function getAllFrameworks({
authToken = getAuthToken(),
}: RequestParams): Promise<any> {
try {
const response = await apiServices.get("/frameworks", {
headers: { Authorization: `Bearer ${authToken}` },
});
return response.data;
} catch (error) {
console.error("Error fetching frameworks:", error);
throw error;
}
}

Comment on lines +54 to +60
// Set initial framework when frameworks are loaded
useEffect(() => {
if (frameworks.length > 0 && !selectedFrameworkId) {
setSelectedFrameworkId(frameworks[0].id);
}
}, [frameworks, selectedFrameworkId]);

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Handle framework list changes & invalid selections

useEffect only sets the initial framework when nothing is selected.
If the frameworks list refreshes (e.g. after refreshFrameworks) and the
previously-selected framework is no longer present, selectedFrameworkId
will keep pointing to a non-existing entry, leaving the UI in an
inconsistent state.

-useEffect(() => {
-  if (frameworks.length > 0 && !selectedFrameworkId) {
-    setSelectedFrameworkId(frameworks[0].id);
-  }
-}, [frameworks, selectedFrameworkId]);
+useEffect(() => {
+  if (frameworks.length === 0) return;
+
+  // If nothing is selected **or** the selected framework disappeared,
+  // default to the first framework.
+  const frameworkExists = frameworks.some(fw => fw.id === selectedFrameworkId);
+  if (selectedFrameworkId === null || !frameworkExists) {
+    setSelectedFrameworkId(frameworks[0].id);
+  }
+}, [frameworks, selectedFrameworkId]);
📝 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
// Set initial framework when frameworks are loaded
useEffect(() => {
if (frameworks.length > 0 && !selectedFrameworkId) {
setSelectedFrameworkId(frameworks[0].id);
}
}, [frameworks, selectedFrameworkId]);
// Set initial framework when frameworks are loaded
useEffect(() => {
if (frameworks.length === 0) return;
// If nothing is selected **or** the selected framework disappeared,
// default to the first framework.
const frameworkExists = frameworks.some(fw => fw.id === selectedFrameworkId);
if (selectedFrameworkId === null || !frameworkExists) {
setSelectedFrameworkId(frameworks[0].id);
}
}, [frameworks, selectedFrameworkId]);

Copy link
Collaborator

@MuhammadKhalilzadeh MuhammadKhalilzadeh left a comment

Choose a reason for hiding this comment

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

There are conflicts here @charurajput16

Copy link
Contributor

@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 comments (1)
Clients/src/presentation/pages/ProjectView/ProjectFrameworks/index.tsx (1)

141-157: ⚠️ Potential issue

Inconsistent variable usage

The code references currentValue and currentTabs which aren't defined in the provided code. These may be relics from the previous implementation or they exist elsewhere in the file. Please ensure these variables are properly defined.

-<TabContext value={currentValue}>
+<TabContext value={tracker}>
-onChange={(_, v) => setCurrentValue(v)}
+onChange={(_, v) => setTracker(v)}
-{currentTabs.map((tab) => (
+{trackerTabs.map((tab) => (
♻️ Duplicate comments (1)
Clients/src/presentation/pages/ProjectView/ProjectFrameworks/index.tsx (1)

56-61: Handle framework list changes & invalid selections

useEffect only sets the initial framework when nothing is selected.
If the frameworks list refreshes (e.g. after refreshFrameworks) and the
previously-selected framework is no longer present, selectedFrameworkId
will keep pointing to a non-existing entry, leaving the UI in an
inconsistent state.

-useEffect(() => {
-  if (frameworks.length > 0 && !selectedFrameworkId) {
-    setSelectedFrameworkId(frameworks[0].id);
-  }
-}, [frameworks, selectedFrameworkId]);
+useEffect(() => {
+  if (frameworks.length === 0) return;
+
+  // If nothing is selected **or** the selected framework disappeared,
+  // default to the first framework.
+  const frameworkExists = frameworks.some(fw => fw.id === selectedFrameworkId);
+  if (selectedFrameworkId === null || !frameworkExists) {
+    setSelectedFrameworkId(frameworks[0].id);
+  }
+}, [frameworks, selectedFrameworkId]);
🧹 Nitpick comments (1)
Clients/src/presentation/pages/ProjectView/ProjectFrameworks/index.tsx (1)

82-82: Replace magic number with a constant

Using 1 as a magic number for the EU AI Act framework ID reduces code readability and maintainability.

-    const isEUAIAct = currentFramework.id === 1; // EU AI Act framework ID
+    const EU_AI_ACT_FRAMEWORK_ID = 1;
+    const isEUAIAct = currentFramework.id === EU_AI_ACT_FRAMEWORK_ID;
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b58df7b and 1f9a52a.

📒 Files selected for processing (1)
  • Clients/src/presentation/pages/ProjectView/ProjectFrameworks/index.tsx (3 hunks)
🧰 Additional context used
🪛 GitHub Actions: Frontend Checks
Clients/src/presentation/pages/ProjectView/ProjectFrameworks/index.tsx

[error] 20-20: TypeScript error TS6133: 'ISO42001Annex' is declared but its value is never read.

🔇 Additional comments (7)
Clients/src/presentation/pages/ProjectView/ProjectFrameworks/index.tsx (7)

11-11: Good job implementing the dynamic framework loading!

The addition of useFrameworks hook is a great improvement to fetch frameworks from the backend instead of hardcoding them.


28-49: Nice reusable component for unavailable frameworks

The ComingSoonMessage component is well-structured with proper styling and informative messaging to let users know when a framework is not yet implemented.


64-67: Good use of memoization for performance optimization

Using useMemo to cache the current framework is a good practice for performance optimization, preventing unnecessary lookups during re-renders.


73-97: Well-structured conditional rendering logic

The renderFrameworkContent function effectively centralizes the logic for rendering different framework content based on the selected framework, improving code organization and maintainability.


99-110: Good error handling with user-friendly recovery

Excellent implementation of error handling with a clear error message and a retry button, providing users with a good fallback experience.


118-133: Good implementation of loading state and dynamic framework tabs

The conditional rendering of skeleton loaders during loading and dynamic mapping of frameworks is well-implemented. This improves user experience by providing visual feedback during loading.


159-164: Clean code with DRY implementation

Using the renderFrameworkContent function for both tab panels follows the DRY principle and ensures consistent rendering logic.

Comment on lines 20 to 21
import ISO42001Annex from "../../ISO/Annex";
import ISO42001Clauses from "../../ISO/Clause";
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove unused imports

The ISO42001Annex import is declared but never used, as indicated by the pipeline failure. Remove this unused import and verify if ISO42001Clauses is also unused.

-import ISO42001Annex from "../../ISO/Annex";
-import ISO42001Clauses from "../../ISO/Clause";

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

🧰 Tools
🪛 GitHub Actions: Frontend Checks

[error] 20-20: TypeScript error TS6133: 'ISO42001Annex' is declared but its value is never read.

@charurajput16
Copy link
Contributor Author

@MuhammadKhalilzadeh - We can skip this PR, as I have handled issues in #1319

@MuhammadKhalilzadeh MuhammadKhalilzadeh deleted the cr-may-07-fetch-frameworks-fron-backend branch May 12, 2025 09:43
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fetch Framework from backend

3 participants