Skip to content

Commit a7f068e

Browse files
authored
Merge branch 'main' into debug-mode
2 parents 0fb5416 + 21b7afd commit a7f068e

File tree

13 files changed

+143
-35
lines changed

13 files changed

+143
-35
lines changed

client/public/locales/en/translation.json

+1
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@
383383
"rootPath": "Root path",
384384
"scheduled": "Scheduled",
385385
"select": "Select",
386+
"section": "Section",
386387
"settingsAllowApps": "Allow reviewing applications without running an assessment first",
387388
"showLess": "Show less",
388389
"showMore": "Show more",
+16-11
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
import * as React from "react";
2-
import { Flex, FlexItem, Icon, Text } from "@patternfly/react-core";
2+
import { Button, Icon } from "@patternfly/react-core";
33
import ExternalLinkAltIcon from "@patternfly/react-icons/dist/esm/icons/external-link-alt-icon";
44

55
/**
66
* Render a link open an external href in another tab with appropriate styling.
77
*/
88
export const ExternalLink: React.FC<{
99
href: string;
10+
isInline?: boolean;
1011
children: React.ReactNode;
11-
}> = ({ href, children }) => (
12-
<Flex spaceItems={{ default: "spaceItemsSm" }}>
13-
<FlexItem>
14-
<Text component="a" href={href} target="_blank">
15-
{children}
16-
</Text>
17-
</FlexItem>
18-
<FlexItem>
12+
}> = ({ href, isInline = false, children }) => (
13+
<Button
14+
variant="link"
15+
isInline={isInline}
16+
component="a"
17+
href={href}
18+
target="_blank"
19+
rel="noreferrer"
20+
icon={
1921
<Icon size="sm" status="info">
2022
<ExternalLinkAltIcon />
2123
</Icon>
22-
</FlexItem>
23-
</Flex>
24+
}
25+
iconPosition="right"
26+
>
27+
{children}
28+
</Button>
2429
);
2530

2631
export default ExternalLink;

client/src/app/pages/assessment/components/assessment-actions/components/dynamic-assessment-actions-row.css

+4
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@
77
background-color: var(--pf-v5-global--warning-color--100) !important ;
88
margin-right: 10px;
99
}
10+
11+
.actions-col {
12+
vertical-align: middle !important;
13+
}

client/src/app/pages/assessment/components/assessment-actions/components/dynamic-assessment-actions-row.tsx

+11-5
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,21 @@ const DynamicAssessmentActionsRow: FunctionComponent<
102102
onDeleteError
103103
);
104104

105-
const determineAction = () => {
105+
const determineAction = React.useCallback(() => {
106106
if (!assessment) {
107107
return AssessmentAction.Take;
108108
} else if (assessment.status === "started") {
109109
return AssessmentAction.Continue;
110110
} else {
111111
return AssessmentAction.Retake;
112112
}
113-
};
113+
}, [assessment]);
114+
115+
const [action, setAction] = React.useState(determineAction());
116+
117+
React.useEffect(() => {
118+
setAction(determineAction());
119+
}, [determineAction, assessment]);
114120

115121
const determineButtonClassName = () => {
116122
const action = determineAction();
@@ -202,7 +208,7 @@ const DynamicAssessmentActionsRow: FunctionComponent<
202208

203209
return (
204210
<>
205-
<Td>
211+
<Td className="actions-col">
206212
<div>
207213
{isReadonly ? null : !isDeleting && !isFetching && !isMutating ? (
208214
<Button
@@ -213,7 +219,7 @@ const DynamicAssessmentActionsRow: FunctionComponent<
213219
onHandleAssessmentAction();
214220
}}
215221
>
216-
{determineAction()}
222+
{action}
217223
</Button>
218224
) : (
219225
<Spinner role="status" size="md">
@@ -247,7 +253,7 @@ const DynamicAssessmentActionsRow: FunctionComponent<
247253
</div>
248254
</Td>
249255
{assessment ? (
250-
<Td isActionCell>
256+
<Td isActionCell className="actions-col">
251257
<Button
252258
type="button"
253259
variant="plain"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.actions-row {
2+
min-height: 5vh;
3+
}
4+
.actions-col {
5+
vertical-align: middle !important;
6+
}

client/src/app/pages/assessment/components/assessment-actions/components/questionnaires-table.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import "./questionnaires-table.css";
12
import React, { useState } from "react";
23
import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table";
34

@@ -98,7 +99,7 @@ const QuestionnairesTable: React.FC<QuestionnairesTableProps> = ({
9899
);
99100

100101
return (
101-
<Tr key={questionnaire.name}>
102+
<Tr key={questionnaire.name} className="actions-row">
102103
<TableRowContentWithControls
103104
{...tableControls}
104105
item={questionnaire}
@@ -107,6 +108,7 @@ const QuestionnairesTable: React.FC<QuestionnairesTableProps> = ({
107108
<Td
108109
width={20}
109110
{...getTdProps({ columnKey: "questionnaires" })}
111+
className="actions-col"
110112
>
111113
{questionnaire.name}
112114
</Td>

client/src/app/pages/dependencies/dependency-apps-table.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,9 @@ const DependencyVersionColumn = ({
269269
return (
270270
<TextContent>
271271
{mavenCentralLink ? (
272-
<ExternalLink href={mavenCentralLink}>{version}</ExternalLink>
272+
<ExternalLink isInline href={mavenCentralLink}>
273+
{version}
274+
</ExternalLink>
273275
) : (
274276
<Text>{version}</Text>
275277
)}

client/src/app/pages/issues/components/issue-description-and-links.tsx

+3-13
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import * as React from "react";
22
import ReactMarkdown from "react-markdown";
3-
import { TextContent, List, ListItem, Button } from "@patternfly/react-core";
3+
import { TextContent, List, ListItem } from "@patternfly/react-core";
44
import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
5-
import ExternalLinkSquareAltIcon from "@patternfly/react-icons/dist/esm/icons/external-link-square-alt-icon";
65

76
import { AnalysisIssueLink } from "@app/api/models";
87
import { markdownPFComponents } from "@app/components/markdownPFComponents";
8+
import ExternalLink from "@app/components/ExternalLink";
99

1010
export interface IIssueDescriptionAndLinksProps {
1111
description: string;
@@ -26,17 +26,7 @@ export const IssueDescriptionAndLinks: React.FC<
2626
<List isPlain>
2727
{links.map((link) => (
2828
<ListItem key={link.url}>
29-
<Button
30-
variant="link"
31-
component="a"
32-
icon={<ExternalLinkSquareAltIcon />}
33-
iconPosition="right"
34-
href={link.url}
35-
target="_blank"
36-
rel="noreferrer"
37-
>
38-
{link.title}
39-
</Button>
29+
<ExternalLink href={link.url}>{link.title}</ExternalLink>
4030
</ListItem>
4131
))}
4232
</List>

client/src/app/pages/migration-waves/components/ticket-issue.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ export const TicketIssue: React.FC<ITicketIssueProps> = ({ ticket }) => {
1717
return (
1818
<Text component={TextVariants.p}>
1919
{ticket?.link ? (
20-
<ExternalLink href={ticket.link}>{ticketIssue}</ExternalLink>
20+
<ExternalLink isInline href={ticket.link}>
21+
{ticketIssue}
22+
</ExternalLink>
2123
) : (
2224
t("terms.unassigned")
2325
)}

client/src/app/pages/reports/components/application-landscape/application-landscape.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ export const ApplicationLandscape: React.FC<IApplicationLandscapeProps> = ({
148148
riskLabel={
149149
<Link to={getRisksUrl(["red"])}>{t("terms.highRisk")}</Link>
150150
}
151+
riskTitle={t("terms.highRisk")}
151152
riskDescription={questionnaire?.riskMessages?.red ?? ""}
152153
/>
153154
</FlexItem>
@@ -163,6 +164,7 @@ export const ApplicationLandscape: React.FC<IApplicationLandscapeProps> = ({
163164
{t("terms.mediumRisk")}
164165
</Link>
165166
}
167+
riskTitle={t("terms.mediumRisk")}
166168
riskDescription={questionnaire?.riskMessages?.yellow ?? ""}
167169
/>
168170
</FlexItem>
@@ -176,6 +178,7 @@ export const ApplicationLandscape: React.FC<IApplicationLandscapeProps> = ({
176178
riskLabel={
177179
<Link to={getRisksUrl(["green"])}>{t("terms.lowRisk")}</Link>
178180
}
181+
riskTitle={t("terms.lowRisk")}
179182
riskDescription={questionnaire?.riskMessages?.green ?? ""}
180183
/>
181184
</FlexItem>
@@ -191,6 +194,7 @@ export const ApplicationLandscape: React.FC<IApplicationLandscapeProps> = ({
191194
{`${t("terms.unassessed")}/${t("terms.unknown")}`}
192195
</Link>
193196
}
197+
riskTitle={t("terms.unassessed")}
194198
/>
195199
</FlexItem>
196200
</Flex>

client/src/app/pages/reports/components/donut/donut.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export interface IDonutProps {
1818
total: number;
1919
color: string;
2020
riskLabel: string | React.ReactElement;
21-
riskDescription?: string | React.ReactElement;
21+
riskDescription?: string;
22+
riskTitle: string;
2223
isAssessment: boolean;
2324
}
2425

@@ -29,6 +30,7 @@ export const Donut: React.FC<IDonutProps> = ({
2930
color,
3031
riskLabel,
3132
isAssessment,
33+
riskTitle,
3234
}) => {
3335
const { t } = useTranslation();
3436

@@ -50,7 +52,7 @@ export const Donut: React.FC<IDonutProps> = ({
5052
}
5153
constrainToVisibleArea={true}
5254
data={[
53-
{ x: riskLabel, y: value },
55+
{ x: riskTitle, y: value },
5456
{ x: t("terms.other"), y: total - value },
5557
]}
5658
labels={({ datum }) => `${datum.x}: ${datum.y}`}

client/src/app/pages/reports/components/identified-risks-table/identified-risks-table.tsx

+85
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { Link } from "react-router-dom";
3232
import { Paths } from "@app/Paths";
3333
import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
3434
import RiskIcon from "@app/components/risk-icon/risk-icon";
35+
import { FilterToolbar, FilterType } from "@app/components/FilterToolbar";
3536

3637
export interface IIdentifiedRisksTableProps {
3738
assessmentRefs?: IdRef[];
@@ -152,6 +153,7 @@ export const IdentifiedRisksTable: React.FC<IIdentifiedRisksTableProps> = ({
152153
},
153154
variant: "compact",
154155
isPaginationEnabled: true,
156+
isFilterEnabled: true,
155157
isSortEnabled: true,
156158
hasActionsColumn: false,
157159
getSortValues: (item) => ({
@@ -173,6 +175,86 @@ export const IdentifiedRisksTable: React.FC<IIdentifiedRisksTableProps> = ({
173175
],
174176
isExpansionEnabled: true,
175177
expandableVariant: "single",
178+
filterCategories: [
179+
{
180+
key: "questionnaireName",
181+
title: t("terms.questionnaire"),
182+
type: FilterType.multiselect,
183+
placeholderText:
184+
t("actions.filterBy", {
185+
what: t("terms.questionnaire").toLowerCase(),
186+
}) + "...",
187+
getItemValue: (item) => item.questionnaireName || "",
188+
selectOptions: [
189+
...new Set(
190+
tableData.map((item) => item.questionnaireName).filter(Boolean)
191+
),
192+
].map((name) => ({ key: name, value: name })),
193+
},
194+
{
195+
key: "section",
196+
title: t("terms.section"),
197+
type: FilterType.multiselect,
198+
placeholderText:
199+
t("actions.filterBy", {
200+
what: t("terms.section").toLowerCase(),
201+
}) + "...",
202+
getItemValue: (item) => item.section || "",
203+
selectOptions: [
204+
...new Set(tableData.map((item) => item.section).filter(Boolean)),
205+
].map((name) => ({ key: name, value: name })),
206+
},
207+
{
208+
key: "question",
209+
title: t("terms.question"),
210+
type: FilterType.multiselect,
211+
placeholderText:
212+
t("actions.filterBy", {
213+
what: t("terms.question").toLowerCase(),
214+
}) + "...",
215+
getItemValue: (item) => item.question.text || "",
216+
selectOptions: [
217+
...new Set(
218+
tableData.map((item) => item.question.text).filter(Boolean)
219+
),
220+
].map((name) => ({ key: name, value: name })),
221+
},
222+
{
223+
key: "answer",
224+
title: t("terms.answer"),
225+
type: FilterType.multiselect,
226+
placeholderText:
227+
t("actions.filterBy", {
228+
what: t("terms.answer").toLowerCase(),
229+
}) + "...",
230+
getItemValue: (item) => item.answer.text || "",
231+
selectOptions: [
232+
...new Set(tableData.map((item) => item.answer.text).filter(Boolean)),
233+
].map((name) => ({ key: name, value: name })),
234+
},
235+
{
236+
key: "risk",
237+
title: t("terms.risk"),
238+
type: FilterType.multiselect,
239+
placeholderText:
240+
t("actions.filterBy", { what: t("terms.risk").toLowerCase() }) +
241+
"...",
242+
getItemValue: (item: ITableRowData) => {
243+
const riskKey = item.answer.risk;
244+
const riskValue =
245+
riskLevelMapping[riskKey as keyof typeof riskLevelMapping];
246+
return riskValue.toString();
247+
},
248+
selectOptions: [
249+
{ key: "3", value: "High" },
250+
{ key: "2", value: "Medium" },
251+
{ key: "1", value: "Low" },
252+
{ key: "0", value: "Unknown" },
253+
],
254+
},
255+
],
256+
initialItemsPerPage: 10,
257+
isSelectionEnabled: false,
176258
});
177259

178260
const {
@@ -181,6 +263,7 @@ export const IdentifiedRisksTable: React.FC<IIdentifiedRisksTableProps> = ({
181263
propHelpers: {
182264
toolbarProps,
183265
paginationToolbarItemProps,
266+
filterToolbarProps,
184267
paginationProps,
185268
tableProps,
186269
getThProps,
@@ -196,6 +279,8 @@ export const IdentifiedRisksTable: React.FC<IIdentifiedRisksTableProps> = ({
196279
<>
197280
<Toolbar {...toolbarProps}>
198281
<ToolbarContent>
282+
<FilterToolbar<ITableRowData, string> {...filterToolbarProps} />
283+
199284
<ToolbarItem {...paginationToolbarItemProps}>
200285
<SimplePagination
201286
idPrefix={`${"identified-risks-table"}}`}

client/src/app/queries/assessments.ts

-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ export const useFetchAssessmentsByItemId = (
182182
};
183183
const assessmentsWithOrder: AssessmentWithSectionOrder[] =
184184
data?.map(addSectionOrderToQuestions) || [];
185-
186185
return {
187186
assessments: assessmentsWithOrder,
188187
isFetching: isLoading,

0 commit comments

Comments
 (0)