Skip to content

Commit a7da1ad

Browse files
authored
Merge pull request #2061 from bluewave-labs/develop
Merging Develop into Master: Sept 7th 2025
2 parents 2fdf44b + fc2e1bf commit a7da1ad

File tree

197 files changed

+18559
-7017
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

197 files changed

+18559
-7017
lines changed

.claude/settings.local.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(npm run build:*)",
5+
"Bash(mkdir:*)",
6+
"Bash(npm run lint)",
7+
"Bash(npm run lint:*)",
8+
"Bash(npx tsc:*)",
9+
"Bash(npx eslint:*)",
10+
"Bash(git checkout:*)",
11+
"Bash(git add:*)",
12+
"Bash(git commit:*)",
13+
"Bash(git push:*)",
14+
"Bash(gh pr create:*)",
15+
"Bash(grep:*)",
16+
"Bash(git pull:*)",
17+
"Bash(node:*)",
18+
"Bash(npm start)",
19+
"Bash(npx swagger-jsdoc:*)",
20+
"Bash(gh pr list:*)",
21+
"Bash(find:*)",
22+
"Bash(cat:*)",
23+
"Bash(git fetch:*)",
24+
"Bash(git merge:*)",
25+
"Bash(git stash:*)",
26+
"Bash(gh pr view:*)",
27+
"Read(/A:\\VerifyWiseRepository\\verifywise\\Clients\\src\\presentation\\components\\AddNewRiskForm\\MitigationSection/**)",
28+
"Read(/A:\\VerifyWiseRepository\\verifywise\\Clients\\src\\presentation\\components\\AddNewRiskForm/**)",
29+
"Read(/A:\\VerifyWiseRepository\\verifywise\\Clients\\src\\presentation\\components\\AddNewRiskForm\\MitigationSection/**)",
30+
"Read(/A:\\VerifyWiseRepository\\verifywise\\Clients\\src\\presentation\\components\\AddNewRiskForm\\MitigationSection/**)",
31+
"Read(/A:\\VerifyWiseRepository\\verifywise\\Clients\\src\\presentation\\components\\AddNewRiskForm\\MitigationSection/**)",
32+
"Read(/A:\\VerifyWiseRepository\\verifywise\\Clients\\src\\presentation\\components\\AddNewRiskForm\\MitigationSection/**)",
33+
"Read(/A:\\VerifyWiseRepository\\verifywise\\Clients\\src\\presentation\\components\\AddNewRiskForm\\MitigationSection/**)",
34+
"mcp__ide__getDiagnostics",
35+
"Read(/A:\\VerifyWiseRepository\\verifywise\\Clients\\src\\presentation\\components\\AddNewRiskForm\\MitigationSection/**)",
36+
"Read(/A:\\VerifyWiseRepository\\verifywise\\Clients\\src\\presentation\\components\\AddNewRiskForm\\MitigationSection/**)",
37+
"WebFetch(domain:github.com)"
38+
],
39+
"deny": [],
40+
"ask": []
41+
}
42+
}

Clients/Dockerfile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ FROM nginx:1.25-alpine
2222
# Step 8: Copy the build output to NGINX's default public directory
2323
COPY --from=build /app/dist /usr/share/nginx/html
2424

25-
# Step 9: Copy the custom NGINX configuration
25+
# Step 9: Copy the custom error page
26+
# COPY upgrade.html /usr/share/nginx/html/upgrade.html
27+
28+
# Step 10: Copy the custom NGINX configuration
2629
COPY nginx.conf /etc/nginx/conf.d/default.conf
2730

28-
# Step 10: Expose port 80
31+
# Step 11: Expose port 80
2932
EXPOSE 80
3033

31-
# Step 11: Start NGINX server
34+
# Step 12: Start NGINX server
3235
CMD ["nginx", "-g", "daemon off;"]

Clients/nginx.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ server {
99
}
1010

1111
error_page 404 /index.html;
12+
# error_page 502 503 504 /upgrade.html;
1213

1314
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|map)$ {
1415
expires max;

Clients/src/application/config/routes.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import Training from "../../presentation/pages/TrainingRegistar";
2929
import PolicyDashboard from "../../presentation/pages/PolicyDashboard/PoliciesDashboard";
3030
import WatchTower from "../../presentation/pages/WatchTower";
3131
import ModelInventory from "../../presentation/pages/ModelInventory";
32+
import Framework from "../../presentation/pages/Framework";
3233

3334
export const createRoutes = (
3435
triggerSidebar: boolean,
@@ -52,6 +53,8 @@ export const createRoutes = (
5253
<Route path="/file-manager" element={<FileManager />} />
5354
<Route path="/reporting" element={<Reporting />} />
5455
<Route path="/" element={<VWHome />} />
56+
<Route path="/overview" element={<VWHome />} />
57+
<Route path="/framework" element={<Framework />} />
5558
<Route path="/project-view" element={<VWProjectView />} />
5659
<Route path="/fairness-dashboard" element={<FairnessDashboard />} />
5760
<Route path="/fairness-results/:id" element={<FairnessResultsPage />} />

Clients/src/application/constants/permissions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const allowedRoles = {
2222
view: ["Admin", "Editor", "Auditor"],
2323
edit: ["Admin", "Editor"],
2424
manage: ["Admin", "Editor"],
25-
audit: ["Auditor"],
25+
audit: ["Admin", "Editor", "Auditor"],
2626
},
2727
organizations: {
2828
view: ["Admin", "Editor", "Auditor"],

Clients/src/application/hooks/useFrameworks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const useFrameworks = ({
2929
} = useQuery({
3030
queryKey: ['frameworks', 'all'],
3131
queryFn: async () => {
32-
const response = await getAllFrameworks({ routeUrl: "/frameworks" });
32+
const response = await getAllFrameworks();
3333
if (response?.data) {
3434
return response.data;
3535
} else {

Clients/src/application/hooks/useIsMultiTenant.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ export const useIsMultiTenant = () => {
77
useEffect(() => {
88
const fetchOrganizationCount = async () => {
99
const response = await CustomAxios.get("/organizations/exists")
10-
if (!response.data.data.exists || window.location.host === "app.verifywise.ai") {
10+
if (
11+
!response.data.data.exists || (
12+
window.location.host === "app.verifywise.ai" ||
13+
window.location.hostname === "test.verifywise.ai"
14+
)
15+
) {
1116
setIsMultiTenant(true);
1217
}
1318
}
Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,25 @@
1-
import { Project } from '../../domain/types/Project';
2-
import { useCallback, useEffect, useState } from 'react';
1+
import { useQuery } from '@tanstack/react-query';
32
import { getAllProjects } from '../repository/project.repository';
3+
import { Project } from '../../domain/types/Project';
44

5-
export const useProjects = () => {
6-
const [projects, setProjects] = useState<Project[]>([]);
7-
const [loading, setLoading] = useState(true);
5+
// Query keys for projects
6+
export const projectQueryKeys = {
7+
all: ['projects'] as const,
8+
lists: () => [...projectQueryKeys.all, 'list'] as const,
9+
list: () => [...projectQueryKeys.lists()] as const,
10+
details: () => [...projectQueryKeys.all, 'detail'] as const,
11+
detail: (id: string) => [...projectQueryKeys.details(), id] as const,
12+
};
813

9-
const fetchProjects = useCallback(async () => {
10-
try {
14+
// Hook to fetch all projects
15+
export const useProjects = () => {
16+
return useQuery({
17+
queryKey: projectQueryKeys.list(),
18+
queryFn: async (): Promise<Project[]> => {
1119
const response = await getAllProjects();
12-
setProjects(response.data);
13-
} catch (error) {
14-
// Handle error
15-
console.error("Error fetching projects:", error);
16-
} finally {
17-
setLoading(false);
18-
}
19-
}, []);
20-
21-
// Fetch projects when the component mounts
22-
useEffect(() => {
23-
fetchProjects();
24-
}, [fetchProjects]);
25-
26-
27-
28-
return { projects, loading, fetchProjects };
20+
return response?.data || [];
21+
},
22+
staleTime: 5 * 60 * 1000, // 5 minutes
23+
gcTime: 10 * 60 * 1000, // 10 minutes
24+
});
2925
};
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { useMutation, useQueryClient, useQuery } from '@tanstack/react-query';
2+
import {
3+
createVendorRisk,
4+
updateVendorRisk,
5+
deleteVendorRisk,
6+
getVendorRiskById
7+
} from '../repository/vendorRisk.repository';
8+
import { vendorRiskQueryKeys } from './useVendorRisks';
9+
10+
// Hook to create a new vendor risk
11+
export const useCreateVendorRisk = () => {
12+
const queryClient = useQueryClient();
13+
14+
return useMutation({
15+
mutationFn: async (riskData: any) => {
16+
const response = await createVendorRisk({ body: riskData });
17+
return response;
18+
},
19+
onSuccess: () => {
20+
// Invalidate and refetch vendor risks
21+
queryClient.invalidateQueries({ queryKey: vendorRiskQueryKeys.lists() });
22+
},
23+
});
24+
};
25+
26+
// Hook to update a vendor risk
27+
export const useUpdateVendorRisk = () => {
28+
const queryClient = useQueryClient();
29+
30+
return useMutation({
31+
mutationFn: async ({ id, data }: { id: number; data: any }) => {
32+
const response = await updateVendorRisk({ id, body: data });
33+
return response;
34+
},
35+
onSuccess: () => {
36+
// Invalidate and refetch vendor risks
37+
queryClient.invalidateQueries({ queryKey: vendorRiskQueryKeys.lists() });
38+
},
39+
});
40+
};
41+
42+
// Hook to delete a vendor risk
43+
export const useDeleteVendorRisk = () => {
44+
const queryClient = useQueryClient();
45+
46+
return useMutation({
47+
mutationFn: async (id: number) => {
48+
const response = await deleteVendorRisk({ id });
49+
return response;
50+
},
51+
onSuccess: () => {
52+
// Invalidate and refetch vendor risks
53+
queryClient.invalidateQueries({ queryKey: vendorRiskQueryKeys.lists() });
54+
},
55+
});
56+
};
57+
58+
// Hook to fetch a single vendor risk by ID
59+
export const useVendorRisk = (id: number) => {
60+
return useQuery({
61+
queryKey: [...vendorRiskQueryKeys.all, 'detail', id],
62+
queryFn: async () => {
63+
const response = await getVendorRiskById({ id });
64+
return response?.data;
65+
},
66+
enabled: !!id,
67+
staleTime: 5 * 60 * 1000,
68+
gcTime: 10 * 60 * 1000,
69+
});
70+
};
71+

Clients/src/application/hooks/useVendorRisks.tsx

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Custom hook to fetch and manage vendor risks data.
2+
* Custom hook to fetch and manage vendor risks data using TanStack Query.
33
*
44
* @param {Object} params - The parameters object.
55
* @param {string} [params.projectId] - The optional project ID to filter vendor risks.
@@ -11,37 +11,35 @@
1111
* - `vendorRisksSummary` {Object} - The summary of vendor risks categorized by risk levels.
1212
* - `refetchVendorRisks` {Function} - Function to manually refetch vendor risks data.
1313
*/
14-
import { useEffect, useState, useCallback, useMemo } from "react";
14+
import { useQuery } from "@tanstack/react-query";
15+
import { useMemo } from "react";
1516
import { convertToCamelCaseRiskKey } from "../tools/stringUtil";
1617
import { VendorRisk } from "../../domain/types/VendorRisk";
1718
import { getAllVendorRisks } from "../repository/vendorRisk.repository";
1819

19-
const useVendorRisks = ({ projectId, vendorId }: { projectId?: string | null; vendorId?: string | null }) => {
20-
const [vendorRisks, setVendorRisks] = useState<VendorRisk[]>([]);
21-
const [loadingVendorRisks, setLoadingVendorRisks] = useState<boolean>(true);
22-
const [error, setError] = useState<string | boolean>(false);
20+
// Query keys for vendor risks
21+
export const vendorRiskQueryKeys = {
22+
all: ['vendorRisks'] as const,
23+
lists: () => [...vendorRiskQueryKeys.all, 'list'] as const,
24+
list: (filters: { projectId?: string | null; vendorId?: string | null }) =>
25+
[...vendorRiskQueryKeys.lists(), filters] as const,
26+
};
2327

24-
const fetchVendorRisks = useCallback(async () => {
25-
setLoadingVendorRisks(true);
26-
try {
28+
const useVendorRisks = ({ projectId, vendorId }: { projectId?: string | null; vendorId?: string | null }) => {
29+
const {
30+
data: vendorRisks = [],
31+
isLoading: loadingVendorRisks,
32+
error,
33+
refetch: refetchVendorRisks,
34+
} = useQuery({
35+
queryKey: vendorRiskQueryKeys.list({ projectId, vendorId }),
36+
queryFn: async (): Promise<VendorRisk[]> => {
2737
const response = await getAllVendorRisks();
28-
if (response?.data) {
29-
setVendorRisks(response?.data);
30-
}
31-
} catch (err) {
32-
if (err instanceof Error) {
33-
setError(`Request failed: ${err.message}`);
34-
} else {
35-
setError(`Request failed`);
36-
}
37-
} finally {
38-
setLoadingVendorRisks(false);
39-
}
40-
}, []);
41-
42-
useEffect(() => {
43-
fetchVendorRisks();
44-
}, [fetchVendorRisks]);
38+
return response?.data || [];
39+
},
40+
staleTime: 5 * 60 * 1000, // 5 minutes
41+
gcTime: 10 * 60 * 1000, // 10 minutes
42+
});
4543

4644
// Filter risks based on projectId and vendorId
4745
const filteredVendorRisks = useMemo(() => {
@@ -72,10 +70,10 @@ const useVendorRisks = ({ projectId, vendorId }: { projectId?: string | null; ve
7270

7371
return {
7472
loadingVendorRisks,
75-
error,
73+
error: error ? `Request failed: ${error.message}` : false,
7674
vendorRisks: filteredVendorRisks,
7775
vendorRisksSummary,
78-
refetchVendorRisks: fetchVendorRisks,
76+
refetchVendorRisks,
7977
};
8078
};
8179

0 commit comments

Comments
 (0)