Skip to content

Commit 4682cea

Browse files
Merge pull request #2444 from bluewave-labs/yb-oct-18-soft-delete-ui
Yb oct 18 soft delete UI
2 parents c530b8d + d29b803 commit 4682cea

File tree

15 files changed

+191
-44
lines changed

15 files changed

+191
-44
lines changed

Clients/src/application/hooks/useVendorRisks.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,28 @@ import { getAllVendorRisks } from "../repository/vendorRisk.repository";
2121
export const vendorRiskQueryKeys = {
2222
all: ['vendorRisks'] as const,
2323
lists: () => [...vendorRiskQueryKeys.all, 'list'] as const,
24-
list: (filters: { projectId?: string | null; vendorId?: string | null }) =>
24+
list: (filters: { projectId?: string | null; vendorId?: string | null; filter?: 'active' | 'deleted' | 'all' }) =>
2525
[...vendorRiskQueryKeys.lists(), filters] as const,
2626
};
2727

28-
const useVendorRisks = ({ projectId, vendorId }: { projectId?: string | null; vendorId?: string | null }) => {
28+
const useVendorRisks = ({
29+
projectId,
30+
vendorId,
31+
filter = 'active'
32+
}: {
33+
projectId?: string | null;
34+
vendorId?: string | null;
35+
filter?: 'active' | 'deleted' | 'all';
36+
}) => {
2937
const {
3038
data: vendorRisks = [],
3139
isLoading: loadingVendorRisks,
3240
error,
3341
refetch: refetchVendorRisks,
3442
} = useQuery({
35-
queryKey: vendorRiskQueryKeys.list({ projectId, vendorId }),
43+
queryKey: vendorRiskQueryKeys.list({ projectId, vendorId, filter }),
3644
queryFn: async (): Promise<VendorRisk[]> => {
37-
const response = await getAllVendorRisks();
45+
const response = await getAllVendorRisks({ filter });
3846
return response?.data || [];
3947
},
4048
staleTime: 5 * 60 * 1000, // 5 minutes

Clients/src/application/repository/entity.repository.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,10 @@ export async function deleteEntityById({
114114
*/
115115
export async function getAllEntities({
116116
routeUrl,
117-
}: RequestParams): Promise<any> {
117+
params,
118+
}: RequestParams & { params?: Record<string, any> }): Promise<any> {
118119
try {
119-
const response = await apiServices.get(routeUrl);
120+
const response = await apiServices.get(routeUrl, { params });
120121
return response.data;
121122
} catch (error) {
122123
console.error("Error getting all users:", error);

Clients/src/application/repository/projectRisk.repository.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ export async function getProjectRiskById({
1515

1616
export async function getAllProjectRisks({
1717
signal,
18+
filter = 'active',
1819
}: {
1920
signal?: AbortSignal;
21+
filter?: 'active' | 'deleted' | 'all';
2022
} = {}): Promise<any> {
21-
const response = await apiServices.get("/projectRisks", {
23+
const response = await apiServices.get(`/projectRisks?filter=${filter}`, {
2224
signal,
2325
});
2426
return response.data;
@@ -27,11 +29,13 @@ export async function getAllProjectRisks({
2729
export async function getAllProjectRisksByProjectId({
2830
projectId,
2931
signal,
32+
filter = 'active',
3033
}: {
3134
projectId: string;
3235
signal?: AbortSignal;
36+
filter?: 'active' | 'deleted' | 'all';
3337
}): Promise<any> {
34-
const response = await apiServices.get(`/projectRisks/by-projid/${projectId}`, {
38+
const response = await apiServices.get(`/projectRisks/by-projid/${projectId}?filter=${filter}`, {
3539
signal,
3640
});
3741
return response.data;
@@ -40,11 +44,13 @@ export async function getAllProjectRisksByProjectId({
4044
export async function getAllRisksByFrameworkId({
4145
frameworkId,
4246
signal,
47+
filter = 'active',
4348
}: {
4449
frameworkId: number;
4550
signal?: AbortSignal;
51+
filter?: 'active' | 'deleted' | 'all';
4652
}): Promise<any> {
47-
const response = await apiServices.get(`/projectRisks/by-frameworkid/${frameworkId}`, {
53+
const response = await apiServices.get(`/projectRisks/by-frameworkid/${frameworkId}?filter=${filter}`, {
4854
signal,
4955
});
5056
return response.data;

Clients/src/application/repository/vendorRisk.repository.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import { apiServices } from "../../infrastructure/api/networkServices";
22

33
export async function getAllVendorRisks({
44
signal,
5+
filter = 'active',
56
}: {
67
signal?: AbortSignal;
8+
filter?: 'active' | 'deleted' | 'all';
79
} = {}): Promise<any> {
8-
const response = await apiServices.get("/vendorRisks/all", {
10+
const response = await apiServices.get(`/vendorRisks/all?filter=${filter}`, {
911
signal,
1012
});
1113
return response.data;
@@ -14,11 +16,13 @@ export async function getAllVendorRisks({
1416
export async function getVendorRisksByProjectId({
1517
projectId,
1618
signal,
19+
filter = 'active',
1720
}: {
1821
projectId: number;
1922
signal?: AbortSignal;
23+
filter?: 'active' | 'deleted' | 'all';
2024
}): Promise<any> {
21-
const response = await apiServices.get(`/vendorRisks/by-projid/${projectId}`, {
25+
const response = await apiServices.get(`/vendorRisks/by-projid/${projectId}?filter=${filter}`, {
2226
signal,
2327
});
2428
return response.data
@@ -27,11 +31,13 @@ export async function getVendorRisksByProjectId({
2731
export async function getVendorRisksByVendorId({
2832
vendorId,
2933
signal,
34+
filter = 'active',
3035
}: {
3136
vendorId: number;
3237
signal?: AbortSignal;
38+
filter?: 'active' | 'deleted' | 'all';
3339
}): Promise<any> {
34-
const response = await apiServices.get(`/vendorRisks/by-vendorid/${vendorId}`, {
40+
const response = await apiServices.get(`/vendorRisks/by-vendorid/${vendorId}?filter=${filter}`, {
3541
signal,
3642
});
3743
return response.data;

Clients/src/domain/interfaces/i.modelRisk.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ export interface IModelRisk {
3838
model_id?: number | null;
3939
created_at?: Date;
4040
updated_at?: Date;
41+
is_deleted?: boolean;
42+
deleted_at?: Date;
4143
}
4244

4345
export interface IModelRiskFormData {

Clients/src/domain/types/ProjectRisk.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,6 @@ export type ProjectRisk = {
9292
recommendations?: string;
9393
projects?: number[];
9494
frameworks?: number[];
95+
is_deleted?: boolean;
96+
deleted_at?: Date;
9597
};

Clients/src/domain/types/VendorRisk.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ export type VendorRisk = {
1212
action_owner: number;
1313
risk_level: string;
1414
vendor_name: string;
15+
is_deleted?: boolean;
16+
deleted_at?: Date;
1517
};

Clients/src/presentation/components/RiskVisualization/RiskFilters.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ interface FilterState {
1616
riskLevel: string;
1717
owner: string;
1818
mitigationStatus: string;
19+
deletionStatus: string;
1920
}
2021

2122
const initialFilterState: FilterState = {
2223
riskLevel: "all",
2324
owner: "all",
2425
mitigationStatus: "all",
26+
deletionStatus: "active",
2527
};
2628

2729
const RiskFilters: React.FC<RiskFiltersProps> = ({
@@ -197,6 +199,19 @@ const RiskFilters: React.FC<RiskFiltersProps> = ({
197199
sx={{ minWidth: 160 }}
198200
/>
199201

202+
<Select
203+
id="deletion-status-filter"
204+
label="Risk status"
205+
value={filters.deletionStatus}
206+
items={[
207+
{ _id: "active", name: "Active only" },
208+
{ _id: "all", name: "Active + deleted" },
209+
{ _id: "deleted", name: "Deleted only" },
210+
]}
211+
onChange={(e) => handleFilterChange("deletionStatus", e.target.value)}
212+
sx={{ minWidth: 140 }}
213+
/>
214+
200215
</Stack>
201216
</Box>
202217
);

Clients/src/presentation/components/Table/RisksTable/index.tsx

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ const RiskTable: React.FC<IRiskTableProps> = ({
5454
null
5555
);
5656
const cellStyle = singleTheme.tableStyles.primary.body.cell;
57+
58+
const getCellStyle = (row: VendorRisk) => ({
59+
...cellStyle,
60+
...(row.is_deleted && {
61+
textDecoration: 'line-through',
62+
})
63+
});
5764
const formattedUsers = users?.map((user: any) => ({
5865
_id: user.id,
5966
name: `${user.name} ${user.surname}`,
@@ -156,11 +163,17 @@ const RiskTable: React.FC<IRiskTableProps> = ({
156163
.map((row: VendorRisk & { project_titles: string }) => (
157164
<TableRow
158165
key={row.risk_id}
159-
sx={singleTheme.tableStyles.primary.body.row}
166+
sx={{
167+
...singleTheme.tableStyles.primary.body.row,
168+
...(row.is_deleted && {
169+
opacity: 0.7,
170+
backgroundColor: theme.palette.action?.hover || '#fafafa',
171+
})
172+
}}
160173
onClick={() => onEdit(row.risk_id!)}
161174
>
162-
<TableCell sx={cellStyle}>{row.risk_description}</TableCell>
163-
<TableCell sx={cellStyle}>
175+
<TableCell sx={getCellStyle(row)}>{row.risk_description}</TableCell>
176+
<TableCell sx={getCellStyle(row)}>
164177
{
165178
formattedVendors?.find(
166179
(vendor: any) => vendor._id === row.vendor_id
@@ -169,7 +182,7 @@ const RiskTable: React.FC<IRiskTableProps> = ({
169182
</TableCell>
170183
<TableCell
171184
sx={{
172-
...cellStyle,
185+
...getCellStyle(row),
173186
maxWidth: 200,
174187
whiteSpace: "nowrap",
175188
overflow: "hidden",
@@ -261,18 +274,18 @@ const RiskTable: React.FC<IRiskTableProps> = ({
261274
);
262275
})()}
263276
</TableCell>
264-
<TableCell sx={cellStyle}>
277+
<TableCell sx={getCellStyle(row)}>
265278
{
266279
formattedUsers?.find(
267280
(user: any) => user._id === row.action_owner
268281
)?.name
269282
}
270283
</TableCell>
271-
<TableCell sx={cellStyle}>
284+
<TableCell sx={getCellStyle(row)}>
272285
<RiskChip label={row.risk_severity} />
273286
</TableCell>
274-
<TableCell sx={cellStyle}>{row.likelihood}</TableCell>
275-
<TableCell sx={cellStyle}>
287+
<TableCell sx={getCellStyle(row)}>{row.likelihood}</TableCell>
288+
<TableCell sx={getCellStyle(row)}>
276289
<RiskChip label={row.risk_level} />
277290
</TableCell>
278291
<TableCell

Clients/src/presentation/components/Table/VWProjectRisksTable/VWProjectRisksTableBody.tsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { TableBody, TableCell, TableRow, Chip, Dialog } from "@mui/material";
1+
import { TableBody, TableCell, TableRow, Chip, Dialog, useTheme } from "@mui/material";
22
import singleTheme from "../../../themes/v1SingleTheme";
33
import { Suspense, useContext, useEffect, useState } from "react";
44
import { ProjectRisk } from "../../../../domain/types/ProjectRisk";
@@ -60,12 +60,20 @@ const VWProjectRisksTableBody = ({
6060
onDeleteRisk: (id: number) => void;
6161
flashRow: number | null;
6262
}) => {
63+
const theme = useTheme();
6364
const { setInputValues } = useContext(VerifyWiseContext);
6465
const { userRoleName } = useAuth();
6566
const { users } = useUsers();
6667
const isDeletingAllowed =
6768
allowedRoles.projectRisks.delete.includes(userRoleName);
6869
const cellStyle = singleTheme.tableStyles.primary.body.cell;
70+
71+
const getCellStyle = (row: ProjectRisk) => ({
72+
...cellStyle,
73+
...(row.is_deleted && {
74+
textDecoration: 'line-through',
75+
})
76+
});
6977
const handleEditRisk = (row: any, event?: React.SyntheticEvent) => {
7078
setSelectedRow(row);
7179
setInputValues(row);
@@ -117,11 +125,17 @@ const VWProjectRisksTableBody = ({
117125
.map((row: ProjectRisk, index: number) => (
118126
<TableRow
119127
key={index}
120-
sx={singleTheme.tableStyles.primary.body.row}
128+
sx={{
129+
...singleTheme.tableStyles.primary.body.row,
130+
...(row.is_deleted && {
131+
opacity: 0.7,
132+
backgroundColor: theme.palette.action?.hover || '#fafafa',
133+
})
134+
}}
121135
onClick={(e) => handleEditRisk(row, e)}
122136
>
123137
<TableCell
124-
sx={cellStyle}
138+
sx={getCellStyle(row)}
125139
style={{
126140
backgroundColor: flashRow === row.id ? "#e3f5e6" : "",
127141
}}
@@ -133,7 +147,7 @@ const VWProjectRisksTableBody = ({
133147
: "-"}
134148
</TableCell>
135149
<TableCell
136-
sx={cellStyle}
150+
sx={getCellStyle(row)}
137151
style={{
138152
backgroundColor: flashRow === row.id ? "#e3f5e6" : "",
139153
}}
@@ -143,23 +157,23 @@ const VWProjectRisksTableBody = ({
143157
: "-"}
144158
</TableCell>
145159
<TableCell
146-
sx={cellStyle}
160+
sx={getCellStyle(row)}
147161
style={{
148162
backgroundColor: flashRow === row.id ? "#e3f5e6" : "",
149163
}}
150164
>
151165
<RiskChip label={row.severity} />
152166
</TableCell>
153167
<TableCell
154-
sx={cellStyle}
168+
sx={getCellStyle(row)}
155169
style={{
156170
backgroundColor: flashRow === row.id ? "#e3f5e6" : "",
157171
}}
158172
>
159173
{row.likelihood ? row.likelihood : "-"}
160174
</TableCell>
161175
<TableCell
162-
sx={cellStyle}
176+
sx={getCellStyle(row)}
163177
style={{
164178
backgroundColor: flashRow === row.id ? "#e3f5e6" : "",
165179
}}
@@ -183,23 +197,23 @@ const VWProjectRisksTableBody = ({
183197
)}
184198
</TableCell>
185199
<TableCell
186-
sx={cellStyle}
200+
sx={getCellStyle(row)}
187201
style={{
188202
backgroundColor: flashRow === row.id ? "#e3f5e6" : "",
189203
}}
190204
>
191205
<RiskChip label={row.risk_level_autocalculated} />
192206
</TableCell>
193207
<TableCell
194-
sx={cellStyle}
208+
sx={getCellStyle(row)}
195209
style={{
196210
backgroundColor: flashRow === row.id ? "#e3f5e6" : "",
197211
}}
198212
>
199213
{row.deadline ? formatDate(row.deadline.toString()) : "NA"}
200214
</TableCell>
201215
<TableCell
202-
sx={cellStyle}
216+
sx={getCellStyle(row)}
203217
style={{
204218
backgroundColor: flashRow === row.id ? "#e3f5e6" : "",
205219
}}

0 commit comments

Comments
 (0)