@automattic/jetpack-components 0.58.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/components/badge/index.tsx +39 -0
- package/components/badge/style.module.scss +25 -0
- package/components/boost-score-graph/style-tooltip.scss +16 -0
- package/components/boost-score-graph/tooltips-plugin.ts +16 -21
- package/components/icon-tooltip/index.tsx +28 -1
- package/components/icon-tooltip/types.ts +5 -0
- package/components/layout/container/index.tsx +16 -11
- package/components/text/index.tsx +2 -3
- package/components/text/types.ts +0 -1
- package/components/threat-fixer-button/index.tsx +142 -0
- package/components/threat-fixer-button/styles.module.scss +9 -0
- package/components/threat-severity-badge/index.tsx +14 -24
- package/components/threats-data-views/constants.ts +49 -0
- package/components/threats-data-views/index.tsx +539 -0
- package/components/threats-data-views/styles.module.scss +41 -0
- package/components/threats-data-views/threats-status-toggle-group-control.tsx +160 -0
- package/index.ts +2 -0
- package/package.json +21 -18
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
### This is a list detailing changes for the Jetpack RNA Components package releases.
|
|
4
4
|
|
|
5
|
+
## [0.59.0] - 2024-11-11
|
|
6
|
+
### Added
|
|
7
|
+
- Add ThreatsDataViews component [#39754]
|
|
8
|
+
- Components: add ref for container component [#39850]
|
|
9
|
+
- IconTooltip: add support for showing tooltip on hover. [#39916]
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- Add ToggleGroupControl to ThreatsDataViews for easily toggling between Active and Historical threats [#39901]
|
|
13
|
+
- Updated package dependencies. [#39999]
|
|
14
|
+
- Updated package dependencies. [#40000]
|
|
15
|
+
- Updated package dependencies. [#40060]
|
|
16
|
+
|
|
17
|
+
## [0.58.1] - 2024-11-04
|
|
18
|
+
### Added
|
|
19
|
+
- Enable test coverage. [#39961]
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- Fix tooltip behavior. [#39879]
|
|
23
|
+
|
|
5
24
|
## [0.58.0] - 2024-10-15
|
|
6
25
|
### Added
|
|
7
26
|
- Add DiffViewer component [#39672]
|
|
@@ -1195,6 +1214,8 @@
|
|
|
1195
1214
|
### Changed
|
|
1196
1215
|
- Update node version requirement to 14.16.1
|
|
1197
1216
|
|
|
1217
|
+
[0.59.0]: https://github.com/Automattic/jetpack-components/compare/0.58.1...0.59.0
|
|
1218
|
+
[0.58.1]: https://github.com/Automattic/jetpack-components/compare/0.58.0...0.58.1
|
|
1198
1219
|
[0.58.0]: https://github.com/Automattic/jetpack-components/compare/0.57.0...0.58.0
|
|
1199
1220
|
[0.57.0]: https://github.com/Automattic/jetpack-components/compare/0.56.3...0.57.0
|
|
1200
1221
|
[0.56.3]: https://github.com/Automattic/jetpack-components/compare/0.56.2...0.56.3
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import styles from './style.module.scss';
|
|
4
|
+
|
|
5
|
+
type BadgeProps = {
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
variant?: 'success' | 'warning' | 'danger';
|
|
9
|
+
[ key: string ]: unknown;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Badge component
|
|
14
|
+
*
|
|
15
|
+
* @param {object} props - The component properties.
|
|
16
|
+
* @param {string} props.variant - The badge variant (i.e. 'success', 'warning', 'danger').
|
|
17
|
+
* @param {JSX.Element} props.children - Badge text or content.
|
|
18
|
+
* @param {string} props.className - Additional class name to pass to the Badge component.
|
|
19
|
+
*
|
|
20
|
+
* @return {React.ReactElement} The `Badge` component.
|
|
21
|
+
*/
|
|
22
|
+
const Badge: React.FC< BadgeProps > = ( { children, className, variant = 'info', ...props } ) => {
|
|
23
|
+
const classes = clsx(
|
|
24
|
+
styles.badge,
|
|
25
|
+
{
|
|
26
|
+
[ styles[ 'is-success' ] ]: variant === 'success',
|
|
27
|
+
[ styles[ 'is-warning' ] ]: variant === 'warning',
|
|
28
|
+
[ styles[ 'is-danger' ] ]: variant === 'danger',
|
|
29
|
+
},
|
|
30
|
+
className
|
|
31
|
+
);
|
|
32
|
+
return (
|
|
33
|
+
<span className={ classes } { ...props }>
|
|
34
|
+
{ children }
|
|
35
|
+
</span>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default Badge;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.badge {
|
|
2
|
+
display: inline-block;
|
|
3
|
+
border-radius: 4px;
|
|
4
|
+
background-color: var(--jp-gray-0);
|
|
5
|
+
color: var(--jp-gray-80);
|
|
6
|
+
padding: 4px 8px;
|
|
7
|
+
font-size: 13px;
|
|
8
|
+
font-weight: 400;
|
|
9
|
+
line-height: 16px;
|
|
10
|
+
|
|
11
|
+
&.is-success {
|
|
12
|
+
background-color: var(--jp-green-5);
|
|
13
|
+
color: var(--jp-green-50);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&.is-warning {
|
|
17
|
+
background-color: var(--jp-yellow-5);
|
|
18
|
+
color: var(--jp-yellow-60);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&.is-danger {
|
|
22
|
+
background-color: var(--jp-red-5);
|
|
23
|
+
color: var(--jp-red-70);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -5,6 +5,17 @@ $white: #ffffff;
|
|
|
5
5
|
.jb-score-tooltips-container {
|
|
6
6
|
width: 100%;
|
|
7
7
|
position: relative;
|
|
8
|
+
pointer-events: none;
|
|
9
|
+
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.jb-score-tooltip-react-root {
|
|
13
|
+
position: absolute;
|
|
14
|
+
bottom: -20px;
|
|
15
|
+
translate: -50% calc( 100% - 20px );
|
|
16
|
+
z-index: 1000;
|
|
17
|
+
pointer-events: auto;
|
|
18
|
+
user-select: text;
|
|
8
19
|
}
|
|
9
20
|
|
|
10
21
|
.jb-score-tooltip {
|
|
@@ -17,6 +28,11 @@ $white: #ffffff;
|
|
|
17
28
|
width: 20em;
|
|
18
29
|
position: relative;
|
|
19
30
|
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.05);
|
|
31
|
+
display: none;
|
|
32
|
+
|
|
33
|
+
.visible &, &:hover {
|
|
34
|
+
display: block;
|
|
35
|
+
}
|
|
20
36
|
|
|
21
37
|
hr {
|
|
22
38
|
border-top: 1px solid $grey;
|
|
@@ -25,35 +25,26 @@ export function tooltipsPlugin( periods ) {
|
|
|
25
25
|
if ( ! reactDom ) {
|
|
26
26
|
reactDom = ReactDOM.createRoot( reactRoot );
|
|
27
27
|
}
|
|
28
|
-
reactRoot.
|
|
29
|
-
reactRoot.style.bottom = -20 + 'px';
|
|
30
|
-
reactRoot.style.translate = '-50% calc( 100% - 20px )';
|
|
31
|
-
reactRoot.style.zIndex = '1000';
|
|
28
|
+
reactRoot.classList.add( 'jb-score-tooltip-react-root' );
|
|
32
29
|
|
|
33
30
|
container.appendChild( reactRoot );
|
|
34
31
|
|
|
35
32
|
u.over.appendChild( container );
|
|
36
33
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
function hideTips() {
|
|
41
|
-
reactRoot.style.display = 'none';
|
|
42
|
-
}
|
|
34
|
+
u.over.addEventListener( 'mouseenter', () => {
|
|
35
|
+
container.classList.add( 'visible' );
|
|
36
|
+
} );
|
|
43
37
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
function showTips() {
|
|
48
|
-
reactRoot.style.display = null;
|
|
49
|
-
}
|
|
38
|
+
u.over.addEventListener( 'mouseleave', () => {
|
|
39
|
+
container.classList.remove( 'visible' );
|
|
40
|
+
} );
|
|
50
41
|
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
reactRoot.addEventListener( 'mouseenter', () => {
|
|
43
|
+
reactRoot.classList.add( 'visible' );
|
|
53
44
|
} );
|
|
54
45
|
|
|
55
|
-
|
|
56
|
-
|
|
46
|
+
reactRoot.addEventListener( 'mouseleave', () => {
|
|
47
|
+
reactRoot.classList.remove( 'visible' );
|
|
57
48
|
} );
|
|
58
49
|
}
|
|
59
50
|
|
|
@@ -62,7 +53,7 @@ export function tooltipsPlugin( periods ) {
|
|
|
62
53
|
* @param {uPlot} u - The uPlot instance.
|
|
63
54
|
*/
|
|
64
55
|
function setSize( u: uPlot ) {
|
|
65
|
-
container.style.
|
|
56
|
+
container.style.paddingTop = u.over.clientHeight + 'px';
|
|
66
57
|
}
|
|
67
58
|
|
|
68
59
|
/**
|
|
@@ -75,6 +66,10 @@ export function tooltipsPlugin( periods ) {
|
|
|
75
66
|
|
|
76
67
|
const period = periods[ idx ];
|
|
77
68
|
|
|
69
|
+
if ( ! period ) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
78
73
|
// Timestamp of the cursor position
|
|
79
74
|
const timestamp = u.data[ 0 ][ idx ];
|
|
80
75
|
|
|
@@ -38,12 +38,14 @@ const IconTooltip: React.FC< IconTooltipProps > = ( {
|
|
|
38
38
|
children,
|
|
39
39
|
popoverAnchorStyle = 'icon',
|
|
40
40
|
forceShow = false,
|
|
41
|
+
hoverShow = false,
|
|
41
42
|
wide = false,
|
|
42
43
|
inline = true,
|
|
43
44
|
shift = false,
|
|
44
45
|
} ) => {
|
|
45
46
|
const POPOVER_HELPER_WIDTH = 124;
|
|
46
47
|
const [ isVisible, setIsVisible ] = useState( false );
|
|
48
|
+
const [ hoverTimeout, setHoverTimeout ] = useState( null );
|
|
47
49
|
const hideTooltip = useCallback( () => setIsVisible( false ), [ setIsVisible ] );
|
|
48
50
|
const toggleTooltip = useCallback(
|
|
49
51
|
e => {
|
|
@@ -78,8 +80,33 @@ const IconTooltip: React.FC< IconTooltipProps > = ( {
|
|
|
78
80
|
|
|
79
81
|
const isForcedToShow = isAnchorWrapper && forceShow;
|
|
80
82
|
|
|
83
|
+
const handleMouseEnter = useCallback( () => {
|
|
84
|
+
if ( hoverShow ) {
|
|
85
|
+
if ( hoverTimeout ) {
|
|
86
|
+
clearTimeout( hoverTimeout );
|
|
87
|
+
setHoverTimeout( null );
|
|
88
|
+
}
|
|
89
|
+
setIsVisible( true );
|
|
90
|
+
}
|
|
91
|
+
}, [ hoverShow, hoverTimeout ] );
|
|
92
|
+
|
|
93
|
+
const handleMouseLeave = useCallback( () => {
|
|
94
|
+
if ( hoverShow ) {
|
|
95
|
+
const id = setTimeout( () => {
|
|
96
|
+
setIsVisible( false );
|
|
97
|
+
setHoverTimeout( null );
|
|
98
|
+
}, 100 );
|
|
99
|
+
setHoverTimeout( id );
|
|
100
|
+
}
|
|
101
|
+
}, [ hoverShow ] );
|
|
102
|
+
|
|
81
103
|
return (
|
|
82
|
-
<div
|
|
104
|
+
<div
|
|
105
|
+
className={ wrapperClassNames }
|
|
106
|
+
data-testid="icon-tooltip_wrapper"
|
|
107
|
+
onMouseEnter={ handleMouseEnter }
|
|
108
|
+
onMouseLeave={ handleMouseLeave }
|
|
109
|
+
>
|
|
83
110
|
{ ! isAnchorWrapper && (
|
|
84
111
|
<Button variant="link" onMouseDown={ toggleTooltip }>
|
|
85
112
|
<Gridicon className={ iconClassName } icon={ iconCode } size={ iconSize } />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
|
-
import { createElement, useMemo } from 'react';
|
|
2
|
+
import { createElement, forwardRef, useMemo } from 'react';
|
|
3
3
|
import { ContainerProps } from '../types';
|
|
4
4
|
import styles from './style.module.scss';
|
|
5
5
|
import type React from 'react';
|
|
@@ -7,17 +7,21 @@ import type React from 'react';
|
|
|
7
7
|
/**
|
|
8
8
|
* JP Container
|
|
9
9
|
*
|
|
10
|
-
* @param {ContainerProps}
|
|
10
|
+
* @param {ContainerProps} props - Component properties.
|
|
11
|
+
* @param {React.MutableRefObject} ref - Ref to the component
|
|
11
12
|
* @return {React.ReactElement} Container component.
|
|
12
13
|
*/
|
|
13
|
-
const Container
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
const Container = (
|
|
15
|
+
{
|
|
16
|
+
children,
|
|
17
|
+
fluid = false,
|
|
18
|
+
tagName = 'div',
|
|
19
|
+
className,
|
|
20
|
+
horizontalGap = 1,
|
|
21
|
+
horizontalSpacing = 1,
|
|
22
|
+
}: ContainerProps,
|
|
23
|
+
ref: React.MutableRefObject< HTMLElement | null >
|
|
24
|
+
): React.ReactElement => {
|
|
21
25
|
const containerStyle = useMemo( () => {
|
|
22
26
|
const padding = `calc( var(--horizontal-spacing) * ${ horizontalSpacing } )`;
|
|
23
27
|
const rowGap = `calc( var(--horizontal-spacing) * ${ horizontalGap } )`;
|
|
@@ -38,9 +42,10 @@ const Container: React.FC< ContainerProps > = ( {
|
|
|
38
42
|
{
|
|
39
43
|
className: containerClassName,
|
|
40
44
|
style: containerStyle,
|
|
45
|
+
ref,
|
|
41
46
|
},
|
|
42
47
|
children
|
|
43
48
|
);
|
|
44
49
|
};
|
|
45
50
|
|
|
46
|
-
export default Container;
|
|
51
|
+
export default forwardRef< HTMLElement, ContainerProps >( Container );
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
|
-
import React, {
|
|
2
|
+
import React, { forwardRef, useMemo } from 'react';
|
|
3
3
|
import { BOX_MODEL_VALUES, VARIANTS_MAPPING } from './constants';
|
|
4
4
|
import styles from './style.module.scss';
|
|
5
5
|
import type { H3Props, TextProps, TitleProps } from './types';
|
|
@@ -26,12 +26,11 @@ const Text = forwardRef< HTMLElement, TextProps >(
|
|
|
26
26
|
}, '' );
|
|
27
27
|
}, [ componentProps ] );
|
|
28
28
|
|
|
29
|
-
componentProps.ref = ref;
|
|
30
|
-
|
|
31
29
|
return (
|
|
32
30
|
<Component
|
|
33
31
|
className={ clsx( styles.reset, styles[ variant ], className, boxModelClasses ) }
|
|
34
32
|
{ ...componentProps }
|
|
33
|
+
ref={ ref }
|
|
35
34
|
>
|
|
36
35
|
{ children }
|
|
37
36
|
</Component>
|
package/components/text/types.ts
CHANGED
|
@@ -39,7 +39,6 @@ export type TextProps = {
|
|
|
39
39
|
children: React.ReactNode;
|
|
40
40
|
/** Force an specific tag (span, div) or use a custom component that will receive className and children */
|
|
41
41
|
component?: React.FC< { [ prop: string ]: unknown } > | React.ElementType;
|
|
42
|
-
[ prop: string ]: unknown;
|
|
43
42
|
};
|
|
44
43
|
|
|
45
44
|
export type H3Props = TextProps & {
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { Button, Text, ActionPopover } from '@automattic/jetpack-components';
|
|
2
|
+
import { CONTACT_SUPPORT_URL, type Threat, fixerStatusIsStale } from '@automattic/jetpack-scan';
|
|
3
|
+
import { ExternalLink } from '@wordpress/components';
|
|
4
|
+
import { createInterpolateElement, useCallback, useMemo, useState } from '@wordpress/element';
|
|
5
|
+
import { __, sprintf } from '@wordpress/i18n';
|
|
6
|
+
import styles from './styles.module.scss';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Threat Fixer Button component.
|
|
10
|
+
*
|
|
11
|
+
* @param {object} props - Component props.
|
|
12
|
+
* @param {object} props.threat - The threat.
|
|
13
|
+
* @param {Function} props.onClick - The onClick function.
|
|
14
|
+
* @param {string} props.className - The className.
|
|
15
|
+
*
|
|
16
|
+
* @return {JSX.Element} The component.
|
|
17
|
+
*/
|
|
18
|
+
export default function ThreatFixerButton( {
|
|
19
|
+
threat,
|
|
20
|
+
className,
|
|
21
|
+
onClick,
|
|
22
|
+
}: {
|
|
23
|
+
threat: Threat;
|
|
24
|
+
onClick: ( items: Threat[] ) => void;
|
|
25
|
+
className?: string;
|
|
26
|
+
} ): JSX.Element {
|
|
27
|
+
const [ isPopoverVisible, setIsPopoverVisible ] = useState( false );
|
|
28
|
+
|
|
29
|
+
const [ anchor, setAnchor ] = useState( null );
|
|
30
|
+
|
|
31
|
+
const children = useMemo( () => {
|
|
32
|
+
if ( ! threat.fixable ) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
if ( threat.fixer && 'error' in threat.fixer && threat.fixer.error ) {
|
|
36
|
+
return __( 'Error', 'jetpack' );
|
|
37
|
+
}
|
|
38
|
+
if ( threat.fixer && 'status' in threat.fixer && threat.fixer.status === 'in_progress' ) {
|
|
39
|
+
return __( 'Fixing…', 'jetpack' );
|
|
40
|
+
}
|
|
41
|
+
if ( threat.fixable.fixer === 'delete' ) {
|
|
42
|
+
return __( 'Delete', 'jetpack' );
|
|
43
|
+
}
|
|
44
|
+
if ( threat.fixable.fixer === 'update' ) {
|
|
45
|
+
return __( 'Update', 'jetpack' );
|
|
46
|
+
}
|
|
47
|
+
return __( 'Fix', 'jetpack' );
|
|
48
|
+
}, [ threat.fixable, threat.fixer ] );
|
|
49
|
+
|
|
50
|
+
const errorMessage = useMemo( () => {
|
|
51
|
+
if ( threat.fixer && fixerStatusIsStale( threat.fixer ) ) {
|
|
52
|
+
return __( 'The fixer is taking longer than expected.', 'jetpack' );
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if ( threat.fixer && 'error' in threat.fixer && threat.fixer.error ) {
|
|
56
|
+
return __( 'An error occurred auto-fixing this threat.', 'jetpack' );
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return null;
|
|
60
|
+
}, [ threat.fixer ] );
|
|
61
|
+
|
|
62
|
+
const handleClick = useCallback(
|
|
63
|
+
( event: React.MouseEvent ) => {
|
|
64
|
+
event.stopPropagation();
|
|
65
|
+
if ( errorMessage && ! isPopoverVisible ) {
|
|
66
|
+
setIsPopoverVisible( true );
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
onClick( [ threat ] );
|
|
70
|
+
},
|
|
71
|
+
[ onClick, errorMessage, isPopoverVisible, threat ]
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const closePopover = useCallback( () => {
|
|
75
|
+
setIsPopoverVisible( false );
|
|
76
|
+
}, [] );
|
|
77
|
+
|
|
78
|
+
if ( ! threat.fixable ) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<div>
|
|
84
|
+
<Button
|
|
85
|
+
size="small"
|
|
86
|
+
weight="regular"
|
|
87
|
+
variant="secondary"
|
|
88
|
+
onClick={ handleClick }
|
|
89
|
+
children={ children }
|
|
90
|
+
className={ className }
|
|
91
|
+
disabled={
|
|
92
|
+
threat.fixer &&
|
|
93
|
+
'status' in threat.fixer &&
|
|
94
|
+
threat.fixer.status === 'in_progress' &&
|
|
95
|
+
! errorMessage
|
|
96
|
+
}
|
|
97
|
+
isLoading={
|
|
98
|
+
threat.fixer && 'status' in threat.fixer && threat.fixer.status === 'in_progress'
|
|
99
|
+
}
|
|
100
|
+
isDestructive={
|
|
101
|
+
( threat.fixable && threat.fixable.fixer === 'delete' ) ||
|
|
102
|
+
( threat.fixer && 'error' in threat.fixer && threat.fixer.error ) ||
|
|
103
|
+
( threat.fixer && fixerStatusIsStale( threat.fixer ) )
|
|
104
|
+
}
|
|
105
|
+
style={ { minWidth: '72px' } }
|
|
106
|
+
ref={ setAnchor }
|
|
107
|
+
/>
|
|
108
|
+
{ isPopoverVisible && (
|
|
109
|
+
<ActionPopover
|
|
110
|
+
anchor={ anchor }
|
|
111
|
+
buttonContent={ __( 'Retry Fix', 'jetpack' ) }
|
|
112
|
+
hideCloseButton={ true }
|
|
113
|
+
noArrow={ false }
|
|
114
|
+
onClick={ handleClick }
|
|
115
|
+
onClose={ closePopover }
|
|
116
|
+
title={ __( 'Auto-fix error', 'jetpack' ) }
|
|
117
|
+
>
|
|
118
|
+
<Text>
|
|
119
|
+
{ createInterpolateElement(
|
|
120
|
+
sprintf(
|
|
121
|
+
/* translators: placeholder is an error message. */
|
|
122
|
+
__(
|
|
123
|
+
'%s Please try again or <supportLink>contact support</supportLink>.',
|
|
124
|
+
'jetpack'
|
|
125
|
+
),
|
|
126
|
+
errorMessage
|
|
127
|
+
),
|
|
128
|
+
{
|
|
129
|
+
supportLink: (
|
|
130
|
+
<ExternalLink
|
|
131
|
+
href={ CONTACT_SUPPORT_URL }
|
|
132
|
+
className={ styles[ 'support-link' ] }
|
|
133
|
+
/>
|
|
134
|
+
),
|
|
135
|
+
}
|
|
136
|
+
) }
|
|
137
|
+
</Text>
|
|
138
|
+
</ActionPopover>
|
|
139
|
+
) }
|
|
140
|
+
</div>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
@@ -1,34 +1,24 @@
|
|
|
1
1
|
import { _x } from '@wordpress/i18n';
|
|
2
|
-
import
|
|
2
|
+
import Badge from '../badge';
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const ThreatSeverityBadge = ( { severity } ) => {
|
|
5
5
|
if ( severity >= 5 ) {
|
|
6
|
-
return
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
return (
|
|
7
|
+
<Badge variant="danger">
|
|
8
|
+
{ _x( 'Critical', 'Severity label for issues rated 5 or higher.', 'jetpack' ) }
|
|
9
|
+
</Badge>
|
|
10
|
+
);
|
|
9
11
|
}
|
|
10
|
-
return 'is-low';
|
|
11
|
-
};
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
if ( severity >= 3 && severity < 5 ) {
|
|
14
|
+
return (
|
|
15
|
+
<Badge variant="warning">
|
|
16
|
+
{ _x( 'High', 'Severity label for issues rated between 3 and 5.', 'jetpack' ) }
|
|
17
|
+
</Badge>
|
|
18
|
+
);
|
|
18
19
|
}
|
|
19
|
-
return _x( 'Low', 'Severity label for issues rated below 3.', 'jetpack' );
|
|
20
|
-
};
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<div
|
|
25
|
-
className={ `${ styles[ 'threat-severity-badge' ] } ${
|
|
26
|
-
styles[ severityClassNames( severity ) ]
|
|
27
|
-
}` }
|
|
28
|
-
>
|
|
29
|
-
{ severityText( severity ) }
|
|
30
|
-
</div>
|
|
31
|
-
);
|
|
21
|
+
return <Badge>{ _x( 'Low', 'Severity label for issues rated below 3.', 'jetpack' ) }</Badge>;
|
|
32
22
|
};
|
|
33
23
|
|
|
34
24
|
export default ThreatSeverityBadge;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { __ } from '@wordpress/i18n';
|
|
2
|
+
import {
|
|
3
|
+
code as fileIcon,
|
|
4
|
+
color as themeIcon,
|
|
5
|
+
plugins as pluginIcon,
|
|
6
|
+
shield as shieldIcon,
|
|
7
|
+
wordpress as coreIcon,
|
|
8
|
+
} from '@wordpress/icons';
|
|
9
|
+
|
|
10
|
+
export const THREAT_STATUSES: { value: string; label: string; variant?: 'success' | 'warning' }[] =
|
|
11
|
+
[
|
|
12
|
+
{ value: 'current', label: __( 'Active', 'jetpack' ), variant: 'warning' },
|
|
13
|
+
{ value: 'fixed', label: __( 'Fixed', 'jetpack' ), variant: 'success' },
|
|
14
|
+
{ value: 'ignored', label: __( 'Ignored', 'jetpack' ) },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
export const THREAT_TYPES = [
|
|
18
|
+
{ value: 'plugin', label: __( 'Plugin', 'jetpack' ) },
|
|
19
|
+
{ value: 'theme', label: __( 'Theme', 'jetpack' ) },
|
|
20
|
+
{ value: 'core', label: __( 'WordPress', 'jetpack' ) },
|
|
21
|
+
{ value: 'file', label: __( 'File', 'jetpack' ) },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export const THREAT_ICONS = {
|
|
25
|
+
plugin: pluginIcon,
|
|
26
|
+
theme: themeIcon,
|
|
27
|
+
core: coreIcon,
|
|
28
|
+
file: fileIcon,
|
|
29
|
+
default: shieldIcon,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const THREAT_FIELD_THREAT = 'threat';
|
|
33
|
+
export const THREAT_FIELD_TITLE = 'title';
|
|
34
|
+
export const THREAT_FIELD_DESCRIPTION = 'description';
|
|
35
|
+
export const THREAT_FIELD_ICON = 'icon';
|
|
36
|
+
export const THREAT_FIELD_STATUS = 'status';
|
|
37
|
+
export const THREAT_FIELD_TYPE = 'type';
|
|
38
|
+
export const THREAT_FIELD_EXTENSION = 'extension';
|
|
39
|
+
export const THREAT_FIELD_PLUGIN = 'plugin';
|
|
40
|
+
export const THREAT_FIELD_THEME = 'theme';
|
|
41
|
+
export const THREAT_FIELD_SEVERITY = 'severity';
|
|
42
|
+
export const THREAT_FIELD_SIGNATURE = 'signature';
|
|
43
|
+
export const THREAT_FIELD_FIRST_DETECTED = 'first-detected';
|
|
44
|
+
export const THREAT_FIELD_FIXED_ON = 'fixed-on';
|
|
45
|
+
export const THREAT_FIELD_AUTO_FIX = 'auto-fix';
|
|
46
|
+
|
|
47
|
+
export const THREAT_ACTION_FIX = 'fix';
|
|
48
|
+
export const THREAT_ACTION_IGNORE = 'ignore';
|
|
49
|
+
export const THREAT_ACTION_UNIGNORE = 'unignore';
|