Skip to content

Commit a5e33fb

Browse files
committed
modal
1 parent b54eedb commit a5e33fb

File tree

4 files changed

+124
-23
lines changed

4 files changed

+124
-23
lines changed

apps/site/components/Downloads/EOLModal/index.tsx

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { Modal, Title, Content } from '@node-core/ui-components/Common/Modal';
22
import { useTranslations } from 'next-intl';
33
import type { FC } from 'react';
44

5+
import LinkWithArrow from '#site/components/LinkWithArrow';
6+
import { VulnerabilityChip } from '#site/components/MDX/EOL/VulnerabilityChips';
57
import type { Vulnerability } from '#site/next-data/providers/vulnerabilities';
68
import type { ModalProps } from '#site/providers/modalProvider';
79
import type { NodeRelease } from '#site/types';
@@ -12,23 +14,88 @@ type EOLModalData = {
1214
};
1315

1416
const EOLModal: FC<ModalProps> = ({ open, closeModal, data }) => {
15-
const { release } = data as EOLModalData;
16-
const t = useTranslations();
17+
const { release, vulnerabilities } = data as EOLModalData;
18+
const t = useTranslations('components.eolModal');
1719

18-
const modalHeadingKey = release.codename
19-
? 'components.releaseModal.title'
20-
: 'components.releaseModal.titleWithoutCodename';
20+
const modalHeadingKey = release.codename ? 'title' : 'titleWithoutCodename';
2121

2222
const modalHeading = t(modalHeadingKey, {
2323
version: release.major,
2424
codename: release.codename ?? '',
2525
});
2626

27+
const actualVulnerabilities = vulnerabilities.filter(
28+
vuln => vuln.severity !== 'unknown'
29+
);
30+
2731
return (
2832
<Modal open={open} onOpenChange={closeModal}>
2933
<Title>{modalHeading}</Title>
3034

31-
<Content></Content>
35+
<Content>
36+
{actualVulnerabilities.length > 0 ? (
37+
<>
38+
<p className="m-1">
39+
{t('vulnerabilitiesMessage', {
40+
count: actualVulnerabilities.length,
41+
})}
42+
</p>
43+
44+
<table>
45+
<thead>
46+
<tr>
47+
<th>{t('table.cves')}</th>
48+
<th>{t('table.severity')}</th>
49+
<th>{t('table.overview')}</th>
50+
<th>{t('table.details')}</th>
51+
</tr>
52+
</thead>
53+
<tbody>
54+
{actualVulnerabilities.map((vuln, index) => (
55+
<tr key={index}>
56+
<td>
57+
{vuln.cve.length > 0
58+
? vuln.cve.map(cveId => (
59+
<div key={cveId}>
60+
<LinkWithArrow
61+
href={`https://cve.mitre.org/cgi-bin/cvename.cgi?name=${cveId}`}
62+
target="_blank"
63+
rel="noopener noreferrer"
64+
>
65+
{cveId}
66+
</LinkWithArrow>
67+
</div>
68+
))
69+
: '-'}
70+
</td>
71+
<td>
72+
<VulnerabilityChip severity={vuln.severity} />
73+
</td>
74+
<td className="max-w-xs truncate">
75+
{vuln.description || vuln.overview || '-'}
76+
</td>
77+
<td>
78+
{vuln.ref ? (
79+
<LinkWithArrow
80+
href={vuln.ref}
81+
target="_blank"
82+
rel="noopener noreferrer"
83+
>
84+
{t('blogLinkText')}
85+
</LinkWithArrow>
86+
) : (
87+
'—'
88+
)}
89+
</td>
90+
</tr>
91+
))}
92+
</tbody>
93+
</table>
94+
</>
95+
) : (
96+
<p className="m-1">{t('noVulnerabilitiesMessage')}</p>
97+
)}
98+
</Content>
3299
</Modal>
33100
);
34101
};

apps/site/components/MDX/EOL/VulnerabilityChips.tsx

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,39 @@ import type { Vulnerability } from '#site/next-data/providers/vulnerabilities.js
66
// Mapping of vulnerability severities to UI labels and colors
77
// TODO @bmuenzenmeyer we need i18n keys for these labels
88
const SEVERITY_CONFIG = {
9-
critical: { label: 'Critical', kind: 'error' },
10-
high: { label: 'High', kind: 'warning' },
11-
medium: { label: 'Medium', kind: 'info' },
9+
unknown: { label: 'Unknown', kind: 'neutral' },
1210
low: { label: 'Low', kind: 'default' },
11+
medium: { label: 'Medium', kind: 'info' },
12+
high: { label: 'High', kind: 'warning' },
13+
critical: { label: 'Critical', kind: 'error' },
1314
} as const;
1415

15-
const SEVERITY_ORDER = Object.keys(SEVERITY_CONFIG) as Array<
16-
keyof typeof SEVERITY_CONFIG
17-
>;
16+
const SEVERITY_ORDER = (
17+
Object.keys(SEVERITY_CONFIG) as Array<keyof typeof SEVERITY_CONFIG>
18+
)
19+
// Remove 'unknown'
20+
.slice(1)
21+
// Order by importance
22+
.reverse();
23+
24+
type VulnerabilityChipProps = {
25+
severity: Vulnerability['severity'];
26+
count?: number;
27+
};
28+
29+
export const VulnerabilityChip: FC<VulnerabilityChipProps> = ({
30+
severity,
31+
count = 0,
32+
}) => {
33+
const { label, kind } = SEVERITY_CONFIG[severity];
34+
35+
return (
36+
<Badge size="small" kind={kind} className="mr-0.5">
37+
{label}
38+
{count > 0 ? ` (${count})` : null}
39+
</Badge>
40+
);
41+
};
1842

1943
type VulnerabilityChipsProps = {
2044
vulnerabilities: Array<Vulnerability>;
@@ -36,16 +60,13 @@ const VulnerabilityChips: FC<VulnerabilityChipsProps> = ({
3660
return (
3761
<div className="vulnerability-chips">
3862
{SEVERITY_ORDER.filter(severity => groupedBySeverity[severity] > 0).map(
39-
severity => {
40-
const { label, kind } = SEVERITY_CONFIG[severity];
41-
const count = groupedBySeverity[severity];
42-
43-
return (
44-
<Badge size="small" key={severity} kind={kind} className="mr-0.5">
45-
{label} ({count})
46-
</Badge>
47-
);
48-
}
63+
severity => (
64+
<VulnerabilityChip
65+
key={severity}
66+
severity={severity}
67+
count={groupedBySeverity[severity]}
68+
/>
69+
)
4970
)}
5071
</div>
5172
);

apps/site/next-data/providers/vulnerabilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export interface Vulnerability {
88
description: string;
99
overview: string;
1010
affectedEnvironments: Array<string>;
11-
severity: string;
11+
severity: 'critical' | 'high' | 'medium' | 'low' | 'unknown';
1212
}
1313

1414
interface GroupedVulnerabilities {

packages/i18n/src/locales/en.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,19 @@
171171
"unsupportedVersionWarning": "This version is out of maintenance. Please use a supported version. <link>Understand EOL support.</link>",
172172
"ltsVersionFeaturesNotice": "Want new features sooner? Get the <link>latest Node.js version</link> instead and try the latest improvements!"
173173
},
174+
"eolModal": {
175+
"title": "Node.js v{version} ({codename}) is EoL",
176+
"titleWithoutCodename": "Node.js v{version} is EoL",
177+
"vulnerabilitiesMessage": "There are {count}+ known vulnerabilities associated with this Node.js release. Please review their severity and details to understand the potential impact.",
178+
"noVulnerabilitiesMessage": "There are no known vulnerabilities for this release, but that does not guarantee it is secure. Older or unsupported versions may still contain undiscovered vulnerabilities. We recommend upgrading to a supported release for continued security and stability.",
179+
"blogLinkText": "Blog",
180+
"table": {
181+
"cves": "CVE(s)",
182+
"severity": "Severity",
183+
"overview": "Overview",
184+
"details": "Details"
185+
}
186+
},
174187
"minorReleasesTable": {
175188
"version": "Version",
176189
"links": "Links",

0 commit comments

Comments
 (0)