@devtron-labs/devtron-fe-common-lib 0.0.7 → 0.0.9-beta-2
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/dist/Common/BreadCrumb/BreadCrumb.d.ts +1 -29
- package/dist/Common/BreadCrumb/Types.d.ts +28 -0
- package/dist/Common/CIPipeline.Types.d.ts +264 -0
- package/dist/Common/Checkbox.d.ts +1 -14
- package/dist/Common/Constants.d.ts +18 -0
- package/dist/Common/CustomTagSelector/ResizableTagTextArea.d.ts +1 -1
- package/dist/Common/CustomTagSelector/TagLabelValueSelector.d.ts +1 -1
- package/dist/Common/CustomTagSelector/Types.d.ts +11 -3
- package/dist/Common/CustomTagSelector/ValidationRules.d.ts +1 -1
- package/dist/Common/DeleteComponentModal/DeleteComponent.d.ts +4 -0
- package/dist/Common/DeleteComponentModal/types.d.ts +15 -0
- package/dist/Common/Dialogs/ConfirmationDialog.d.ts +5 -16
- package/dist/Common/Dialogs/DialogForm.d.ts +1 -9
- package/dist/Common/Dialogs/Types.d.ts +28 -0
- package/dist/Common/EmptyState/EmptyState.d.ts +2 -1
- package/dist/Common/EmptyState/GenericEmptyState.d.ts +5 -0
- package/dist/Common/Error.d.ts +2 -2
- package/dist/Common/Helper.d.ts +31 -1
- package/dist/Common/InfoColorBar/InfoColourbar.d.ts +2 -15
- package/dist/Common/Modals/Modal.d.ts +2 -9
- package/dist/Common/MultiSelectCustomization.d.ts +1 -2
- package/dist/Common/PopupMenu.d.ts +4 -21
- package/dist/Common/Progressing.d.ts +4 -13
- package/dist/Common/RadioGroup/RadioGroup.d.ts +17 -0
- package/dist/Common/RadioGroup.d.ts +1 -10
- package/dist/Common/Reload.d.ts +2 -4
- package/dist/Common/Security/ScanVulnerabilitiesTable.d.ts +4 -0
- package/dist/Common/TippyCustomized.d.ts +2 -30
- package/dist/Common/Toggle/Toggle.d.ts +12 -0
- package/dist/Common/Types.d.ts +293 -0
- package/dist/Common/index.d.ts +7 -1
- package/dist/index.js +2472 -1948
- package/package.json +2 -2
- package/rollup.config.js +3 -3
- package/src/Assets/Icon/ic-help.svg +3 -0
- package/src/Assets/Icon/ic-info-filled.svg +7 -0
- package/src/Assets/Icon/ic-warning.svg +7 -0
- package/src/Assets/Img/app-not-deployed.png +0 -0
- package/src/Common/Api.ts +7 -1
- package/src/Common/BreadCrumb/BreadCrumb.tsx +1 -30
- package/src/Common/BreadCrumb/Types.ts +30 -0
- package/src/Common/CIPipeline.Types.ts +276 -0
- package/src/Common/Checkbox.tsx +3 -16
- package/src/Common/Constants.ts +21 -0
- package/src/Common/CustomTagSelector/ResizableTagTextArea.tsx +6 -4
- package/src/Common/CustomTagSelector/TagDetails.tsx +15 -2
- package/src/Common/CustomTagSelector/TagLabelSelect.tsx +7 -3
- package/src/Common/CustomTagSelector/TagLabelValueSelector.tsx +66 -26
- package/src/Common/CustomTagSelector/Types.ts +11 -3
- package/src/Common/CustomTagSelector/ValidationRules.ts +21 -18
- package/src/Common/DeleteComponentModal/DeleteComponent.tsx +95 -0
- package/src/Common/DeleteComponentModal/types.ts +15 -0
- package/src/Common/Dialogs/ConfirmationDialog.tsx +6 -4
- package/src/Common/Dialogs/DeleteDialog.tsx +45 -27
- package/src/Common/Dialogs/DialogForm.tsx +2 -11
- package/src/Common/Dialogs/Types.ts +29 -0
- package/src/Common/Drawer/Drawer.scss +12 -11
- package/src/Common/EmptyState/EmptyState.tsx +5 -5
- package/src/Common/EmptyState/GenericEmptyState.tsx +41 -0
- package/src/Common/EmptyState/emptyState.scss +4 -15
- package/src/Common/Error.tsx +13 -16
- package/src/Common/ErrorScreenNotFound.tsx +23 -30
- package/src/Common/Helper.tsx +258 -2
- package/src/Common/InfoColorBar/InfoColourbar.tsx +6 -18
- package/src/Common/Modals/Modal.tsx +7 -1
- package/src/Common/Modals/OpaqueModal.tsx +2 -2
- package/src/Common/Modals/VisibleModal.tsx +1 -1
- package/src/Common/Modals/VisibleModal2.tsx +1 -1
- package/src/Common/MultiSelectCustomization.tsx +3 -3
- package/src/Common/PopupMenu.tsx +23 -6
- package/src/Common/Progressing.tsx +8 -15
- package/src/Common/RadioGroup/RadioGroup.tsx +88 -0
- package/src/Common/RadioGroup/radioGroup.scss +46 -0
- package/src/Common/RadioGroup.tsx +3 -13
- package/src/Common/Reload.tsx +15 -10
- package/src/Common/Security/ScanVulnerabilitiesTable.tsx +55 -0
- package/src/Common/Security/scanVulnerabilities.css +67 -0
- package/src/Common/TippyCustomized.tsx +29 -31
- package/src/Common/Toggle/Toggle.scss +70 -0
- package/src/Common/Toggle/Toggle.tsx +38 -0
- package/src/Common/Types.ts +319 -0
- package/src/Common/index.ts +7 -1
- package/dist/27bfa7a87d0b7039.png +0 -0
- package/dist/b5d52f036bdcd3ed.png +0 -0
- package/src/Assets/Icon/ic-close.svg +0 -9
- /package/src/Assets/Img/{warning-medium.svg → delete-medium.svg} +0 -0
package/src/Common/PopupMenu.tsx
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import React, { useEffect } from 'react'
|
|
2
|
-
import {Modal} from './Modals/Modal'
|
|
3
|
-
|
|
1
|
+
import React, { useEffect } from 'react'
|
|
2
|
+
import { Modal } from './Modals/Modal'
|
|
3
|
+
import { PopupMenuBodyType, PopupMenuButtonType, PopupMenuType } from './Types'
|
|
4
|
+
|
|
5
|
+
const PopupContext = React.createContext(null)
|
|
4
6
|
|
|
5
7
|
function usePopupContext() {
|
|
6
8
|
const context = React.useContext(PopupContext)
|
|
@@ -10,7 +12,12 @@ function usePopupContext() {
|
|
|
10
12
|
return context
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
function PopupMenu({
|
|
15
|
+
function PopupMenu({
|
|
16
|
+
children = null,
|
|
17
|
+
onToggleCallback = null,
|
|
18
|
+
autoClose = false,
|
|
19
|
+
autoPosition = false,
|
|
20
|
+
}: PopupMenuType) {
|
|
14
21
|
const [popupPosition, setPopupPosition] = React.useState(null)
|
|
15
22
|
const [opacity, setOpacity] = React.useState(0)
|
|
16
23
|
const observer = React.useRef<IntersectionObserver | null>(null)
|
|
@@ -135,7 +142,8 @@ function Button({
|
|
|
135
142
|
tabIndex = 0,
|
|
136
143
|
onHover = false,
|
|
137
144
|
isKebab = false,
|
|
138
|
-
|
|
145
|
+
dataTestId = "",
|
|
146
|
+
}: PopupMenuButtonType) {
|
|
139
147
|
const { handleOpen, popupPosition, buttonRef, initialiseButtonWidth } = usePopupContext()
|
|
140
148
|
return (
|
|
141
149
|
<button
|
|
@@ -148,13 +156,21 @@ function Button({
|
|
|
148
156
|
}`}
|
|
149
157
|
onMouseEnter={onHover ? (disabled ? null : handleOpen) : () => {}}
|
|
150
158
|
onClick={disabled ? null : handleOpen}
|
|
159
|
+
data-testid={dataTestId}
|
|
151
160
|
>
|
|
152
161
|
{children}
|
|
153
162
|
</button>
|
|
154
163
|
)
|
|
155
164
|
}
|
|
156
165
|
|
|
157
|
-
function Body({
|
|
166
|
+
function Body({
|
|
167
|
+
children = null,
|
|
168
|
+
rootClassName = '',
|
|
169
|
+
style = {},
|
|
170
|
+
autoWidth = false,
|
|
171
|
+
preventWheelDisable = false,
|
|
172
|
+
noBackDrop,
|
|
173
|
+
}: PopupMenuBodyType) {
|
|
158
174
|
const { handleClose, popupPosition, opacity, callbackRef, buttonWidth } = usePopupContext()
|
|
159
175
|
return popupPosition ? (
|
|
160
176
|
<Modal
|
|
@@ -170,6 +186,7 @@ function Body({ children = null, rootClassName = '', style = {}, autoWidth = fal
|
|
|
170
186
|
opacity: opacity,
|
|
171
187
|
}}
|
|
172
188
|
preventWheelDisable={preventWheelDisable}
|
|
189
|
+
noBackDrop={noBackDrop}
|
|
173
190
|
>
|
|
174
191
|
{children}
|
|
175
192
|
</Modal>
|
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
+
import { ProgressingProps } from './Types'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
pageLoader?: boolean
|
|
5
|
-
loadingText?: string
|
|
6
|
-
size?: number
|
|
7
|
-
fullHeight?: boolean
|
|
8
|
-
theme?: 'white' | 'default'
|
|
9
|
-
styles?: React.CSSProperties
|
|
10
|
-
children?: React.ReactNode
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function Progressing({ pageLoader, size, theme, styles }: ProgressingProps): JSX.Element {
|
|
4
|
+
export function Progressing({ pageLoader, size, theme, styles, fillColor }: ProgressingProps): JSX.Element {
|
|
14
5
|
const loaderSize = size ? `${size}px` : pageLoader ? '48px' : '20px'
|
|
15
6
|
return (
|
|
16
|
-
<div className={`loader ${theme || 'default'}-background`} style={styles}>
|
|
7
|
+
<div className={`loader ${theme || 'default'}-background`} style={styles} data-testid="progressing">
|
|
17
8
|
<div style={{ width: loaderSize, height: loaderSize }}>
|
|
18
9
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" className="loader__svg">
|
|
19
10
|
<g fill="none" fillRule="evenodd" strokeLinecap="round">
|
|
@@ -27,7 +18,7 @@ export function Progressing({ pageLoader, size, theme, styles }: ProgressingProp
|
|
|
27
18
|
type="rotate"
|
|
28
19
|
/>
|
|
29
20
|
<path
|
|
30
|
-
fill=
|
|
21
|
+
fill={fillColor || '#06C'}
|
|
31
22
|
fillRule="nonzero"
|
|
32
23
|
d="M12 2.5A9.5 9.5 0 1 1 2.5 12a1.5 1.5 0 0 1 3 0A6.5 6.5 0 1 0 12 5.5a1.5 1.5 0 0 1 0-3z"
|
|
33
24
|
/>
|
|
@@ -42,16 +33,18 @@ export function DetailsProgressing({
|
|
|
42
33
|
loadingText,
|
|
43
34
|
size = 24,
|
|
44
35
|
fullHeight = false,
|
|
45
|
-
children,
|
|
46
36
|
styles,
|
|
37
|
+
fillColor,
|
|
38
|
+
children,
|
|
47
39
|
}: ProgressingProps): JSX.Element {
|
|
48
40
|
return (
|
|
49
41
|
<div
|
|
50
42
|
className={`details-loader bcn-0 flex column fs-14 fw-6 ${fullHeight ? 'h-100' : 'details-loader-height'}`}
|
|
51
43
|
style={styles}
|
|
44
|
+
data-testid="details-progressing"
|
|
52
45
|
>
|
|
53
46
|
<span style={{ width: `${size}px`, height: `${size}px` }}>
|
|
54
|
-
<Progressing size={size} />
|
|
47
|
+
<Progressing size={size} fillColor={fillColor} />
|
|
55
48
|
</span>
|
|
56
49
|
{loadingText && <span className="mt-10">{loadingText}</span>}
|
|
57
50
|
{children}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import Tippy from '@tippyjs/react'
|
|
2
|
+
import React, { useState, useEffect } from 'react'
|
|
3
|
+
import { ConditionalWrap } from '../Helper'
|
|
4
|
+
import './radioGroup.scss'
|
|
5
|
+
|
|
6
|
+
const RadioContext = React.createContext(null)
|
|
7
|
+
|
|
8
|
+
function useRadioContext() {
|
|
9
|
+
const context = React.useContext(RadioContext)
|
|
10
|
+
if (!context) {
|
|
11
|
+
throw new Error(`Radio compound components cannot be rendered outside the Toggle component`)
|
|
12
|
+
}
|
|
13
|
+
return context
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface RadioGroupInterface {
|
|
17
|
+
name: string
|
|
18
|
+
onChange: any
|
|
19
|
+
className?: string
|
|
20
|
+
initialTab: string
|
|
21
|
+
disabled: boolean
|
|
22
|
+
showTippy?: boolean
|
|
23
|
+
tippyContent?: any
|
|
24
|
+
dataTestId?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface RadioGroupComposition {
|
|
28
|
+
Radio?: React.FC<any>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const RadioGroup: React.FC<RadioGroupInterface> & RadioGroupComposition = React.memo(function RadioGroup({
|
|
32
|
+
name,
|
|
33
|
+
onChange,
|
|
34
|
+
children,
|
|
35
|
+
className = '',
|
|
36
|
+
initialTab,
|
|
37
|
+
disabled = false,
|
|
38
|
+
dataTestId
|
|
39
|
+
}) {
|
|
40
|
+
const [selected, select] = useState(null)
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (initialTab === selected) return
|
|
44
|
+
select(initialTab)
|
|
45
|
+
}, [initialTab])
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<RadioContext.Provider value={{ name, selected, select, disabled, onChange }}>
|
|
49
|
+
<div className={`${className} radio-group`}>{children}</div>
|
|
50
|
+
</RadioContext.Provider>
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
function Radio({ value, children, className = '', showTippy = false, tippyContent = '', canSelect = true, isDisabled = false, tippyClass = '', dataTestId }) {
|
|
55
|
+
const { name, selected, select, disabled, onChange } = useRadioContext()
|
|
56
|
+
return (
|
|
57
|
+
<ConditionalWrap
|
|
58
|
+
condition={showTippy}
|
|
59
|
+
wrap={(children) => (
|
|
60
|
+
<Tippy className={`default-tt w-250 ${tippyClass}`} arrow={false} placement="bottom" content={tippyContent}>
|
|
61
|
+
{children}
|
|
62
|
+
</Tippy>
|
|
63
|
+
)}
|
|
64
|
+
>
|
|
65
|
+
<label className={`${className} radio ${(isDisabled || disabled)? 'disabled': ''}`}>
|
|
66
|
+
<input
|
|
67
|
+
type="checkbox"
|
|
68
|
+
value={value}
|
|
69
|
+
name={name}
|
|
70
|
+
|
|
71
|
+
checked={value === selected}
|
|
72
|
+
onChange={(e) => {
|
|
73
|
+
e.persist()
|
|
74
|
+
if (canSelect) {
|
|
75
|
+
select(e.target.value)
|
|
76
|
+
}
|
|
77
|
+
onChange(e)
|
|
78
|
+
}}
|
|
79
|
+
disabled={isDisabled || disabled}
|
|
80
|
+
/>
|
|
81
|
+
<span className="radio__item-label" data-testid={dataTestId}>{children}</span>
|
|
82
|
+
</label>
|
|
83
|
+
</ConditionalWrap>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
RadioGroup.Radio = Radio
|
|
88
|
+
export default RadioGroup
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
.radio-group {
|
|
2
|
+
.label,
|
|
3
|
+
.radio,
|
|
4
|
+
.checkbox {
|
|
5
|
+
margin: 0;
|
|
6
|
+
}
|
|
7
|
+
height: 30px;
|
|
8
|
+
background: white;
|
|
9
|
+
display: flex;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
align-items: center;
|
|
12
|
+
padding: 4px;
|
|
13
|
+
border-radius: 4px;
|
|
14
|
+
.radio {
|
|
15
|
+
height: 100%;
|
|
16
|
+
width: auto;
|
|
17
|
+
color: var(--N400);
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
}
|
|
21
|
+
.radio+.radio {
|
|
22
|
+
margin-top: 0;
|
|
23
|
+
}
|
|
24
|
+
input[type=checkbox] {
|
|
25
|
+
display: contents;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
max-width: 0px;
|
|
28
|
+
height: 0;
|
|
29
|
+
opacity: 0;
|
|
30
|
+
margin: unset;
|
|
31
|
+
}
|
|
32
|
+
input+.radio__item-label {
|
|
33
|
+
padding: 4px 6px;
|
|
34
|
+
height: 100%;
|
|
35
|
+
width: 100%;
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
transition: all 0.5s;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
}
|
|
41
|
+
input[type=checkbox]:checked+.radio__item-label {
|
|
42
|
+
background: #2c3354;
|
|
43
|
+
color: white;
|
|
44
|
+
border-radius: 4px;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import React, { Component, createContext } from 'react'
|
|
2
|
+
import { RadioGroupItemProps, RadioGroupProps } from './Types'
|
|
2
3
|
const RadioGroupContext = createContext({ name: '', value: '', disabled: false, onChange: (event) => {} })
|
|
3
4
|
|
|
4
|
-
export interface RadioGroupItemProps {
|
|
5
|
-
value: string
|
|
6
|
-
}
|
|
7
|
-
|
|
8
5
|
export class RadioGroupItem extends Component<RadioGroupItemProps> {
|
|
9
6
|
render() {
|
|
10
7
|
return (
|
|
@@ -21,8 +18,9 @@ export class RadioGroupItem extends Component<RadioGroupItemProps> {
|
|
|
21
18
|
onChange={context.onChange}
|
|
22
19
|
value={this.props.value}
|
|
23
20
|
checked={context.value === this.props.value}
|
|
21
|
+
data-testid={this.props.dataTestId}
|
|
24
22
|
/>
|
|
25
|
-
<span className="form__radio-item-content">
|
|
23
|
+
<span className="form__radio-item-content" data-testid={`${this.props.dataTestId}-span`}>
|
|
26
24
|
<span className="radio__button"></span>
|
|
27
25
|
<span className="radio__title">{this.props.children}</span>
|
|
28
26
|
</span>
|
|
@@ -35,14 +33,6 @@ export class RadioGroupItem extends Component<RadioGroupItemProps> {
|
|
|
35
33
|
}
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
export interface RadioGroupProps {
|
|
39
|
-
value: string
|
|
40
|
-
name: string
|
|
41
|
-
disabled?: boolean
|
|
42
|
-
onChange: (event) => void
|
|
43
|
-
className?: string
|
|
44
|
-
}
|
|
45
|
-
|
|
46
36
|
export class RadioGroup extends Component<RadioGroupProps> {
|
|
47
37
|
render() {
|
|
48
38
|
return (
|
package/src/Common/Reload.tsx
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import loadingFailure from '../Assets/Img/ic-loading-failure.png'
|
|
2
|
+
import loadingFailure from '../Assets/Img/ic-loading-failure.png'
|
|
3
|
+
import { ReloadType } from './Types'
|
|
3
4
|
|
|
4
|
-
export default function Reload({ reload
|
|
5
|
-
function refresh(e){
|
|
6
|
-
window.location.reload()
|
|
5
|
+
export default function Reload({ reload, className = '' }: ReloadType) {
|
|
6
|
+
function refresh(e) {
|
|
7
|
+
window.location.reload()
|
|
7
8
|
}
|
|
8
9
|
return (
|
|
9
|
-
<article className={`flex ${className}`}
|
|
10
|
-
<div className="flex column
|
|
11
|
-
<img src={loadingFailure} style={{
|
|
10
|
+
<article className={`flex w-100 h-100 ${className}`}>
|
|
11
|
+
<div className="flex column w-250 dc__align-center" data-testid="reload">
|
|
12
|
+
<img src={loadingFailure} style={{ height: 'auto' }} className="w-100 mb-12" alt="load-error" />
|
|
12
13
|
<h3 className="title dc__bold">Failed to load</h3>
|
|
13
|
-
<div className="dc__empty__subtitle"
|
|
14
|
-
|
|
14
|
+
<div className="dc__empty__subtitle mb-20">
|
|
15
|
+
We could not load this page. Please give us another try.
|
|
16
|
+
</div>
|
|
17
|
+
<button type="button" className="cta ghosted" onClick={typeof reload === 'function' ? reload : refresh}>
|
|
18
|
+
Retry
|
|
19
|
+
</button>
|
|
15
20
|
</div>
|
|
16
21
|
</article>
|
|
17
22
|
)
|
|
18
|
-
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { ScanVulnerabilitiesTableProps, VulnerabilityType } from '../Types'
|
|
3
|
+
import './scanVulnerabilities.css'
|
|
4
|
+
|
|
5
|
+
export default function ScanVulnerabilitiesTable({ vulnerabilities }: ScanVulnerabilitiesTableProps) {
|
|
6
|
+
const renderRow = (vulnerability: VulnerabilityType) => {
|
|
7
|
+
return (
|
|
8
|
+
<tr
|
|
9
|
+
className="dc__security-tab__table-row cursor"
|
|
10
|
+
onClick={(e) => {
|
|
11
|
+
window.open(`https://cve.mitre.org/cgi-bin/cvename.cgi?name=${vulnerability.name}`, '_blank')
|
|
12
|
+
}}
|
|
13
|
+
>
|
|
14
|
+
<td className="security-tab__cell-cve dc__cve-cell">
|
|
15
|
+
<a
|
|
16
|
+
href={`https://cve.mitre.org/cgi-bin/cvename.cgi?name=${vulnerability.name}`}
|
|
17
|
+
rel="noopener noreferrer"
|
|
18
|
+
target="_blank"
|
|
19
|
+
>
|
|
20
|
+
{vulnerability.name}
|
|
21
|
+
</a>
|
|
22
|
+
</td>
|
|
23
|
+
<td className="security-tab__cell-severity">
|
|
24
|
+
<span className={`fill-${vulnerability.severity?.toLowerCase()}`}>{vulnerability.severity}</span>
|
|
25
|
+
</td>
|
|
26
|
+
<td className="security-tab__cell-package">{vulnerability.package}</td>
|
|
27
|
+
<td className="security-tab__cell-current-ver">{vulnerability.version}</td>
|
|
28
|
+
<td className="security-tab__cell-fixed-ver">{vulnerability.fixedVersion}</td>
|
|
29
|
+
<td
|
|
30
|
+
className={`security-tab__cell-policy security-tab__cell-policy--${vulnerability.policy?.toLowerCase()}`}
|
|
31
|
+
>
|
|
32
|
+
{vulnerability.policy?.toLowerCase()}
|
|
33
|
+
</td>
|
|
34
|
+
</tr>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<table className="security-tab__table">
|
|
40
|
+
<tbody>
|
|
41
|
+
<tr className="security-tab__table-header">
|
|
42
|
+
<th className="security-cell-header security-tab__cell-cve">CVE</th>
|
|
43
|
+
<th className="security-cell-header security-tab__cell-severity">Severity</th>
|
|
44
|
+
<th className="security-cell-header security-tab__cell-package">Package</th>
|
|
45
|
+
<th className="security-cell-header security-tab__cell-current-ver">Current Version</th>
|
|
46
|
+
<th className="security-cell-header security-tab__cell-fixed-ver">Fixed In Version</th>
|
|
47
|
+
<th className="security-cell-header security-tab__cell-policy">Policy</th>
|
|
48
|
+
</tr>
|
|
49
|
+
{vulnerabilities.map((vulnerability) => {
|
|
50
|
+
return renderRow(vulnerability)
|
|
51
|
+
})}
|
|
52
|
+
</tbody>
|
|
53
|
+
</table>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
.modal-body--scan-details {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
right: 0;
|
|
5
|
+
background: var(--N000);
|
|
6
|
+
width: 800px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.security-tab__table {
|
|
10
|
+
width: 100%;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.security-tab__table-header {
|
|
14
|
+
border-bottom: solid 1px var(--N200);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.security-cell-header {
|
|
18
|
+
font-size: 12px;
|
|
19
|
+
font-weight: 600;
|
|
20
|
+
line-height: 1.5;
|
|
21
|
+
letter-spacing: normal;
|
|
22
|
+
text-transform: uppercase;
|
|
23
|
+
color: var(--N500);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.dc__security-tab__table-row {
|
|
27
|
+
font-size: 13px;
|
|
28
|
+
font-weight: normal;
|
|
29
|
+
line-height: 1.54;
|
|
30
|
+
letter-spacing: normal;
|
|
31
|
+
color: var(--N900);
|
|
32
|
+
box-shadow: inset 0 -1px 0 0 #f5f5f5;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.security-tab__cell-cve,
|
|
36
|
+
.security-tab__cell-severity,
|
|
37
|
+
.security-tab__cell-package,
|
|
38
|
+
.security-tab__cell-current-ver,
|
|
39
|
+
.security-tab__cell-fixed-ver,
|
|
40
|
+
.security-tab__cell-policy {
|
|
41
|
+
padding: 10px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.security-tab__cell-cve {
|
|
45
|
+
padding-left: 0px;
|
|
46
|
+
text-align: left;
|
|
47
|
+
width: 20%;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.security-tab__cell-policy {
|
|
51
|
+
padding-right: 0px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.security-tab__cell-policy--whitelist,
|
|
55
|
+
.security-tab__cell-policy--whitelisted {
|
|
56
|
+
color: var(--G500);
|
|
57
|
+
text-transform: capitalize;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.security-tab__cell-policy--block {
|
|
61
|
+
color: var(--R500);
|
|
62
|
+
text-transform: capitalize;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.scanned-object__results {
|
|
66
|
+
margin: 0 20px;
|
|
67
|
+
}
|
|
@@ -1,41 +1,16 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useRef, useState } from 'react'
|
|
2
2
|
import Tippy from '@tippyjs/react'
|
|
3
|
-
import { Placement } from 'tippy.js'
|
|
4
3
|
import { ReactComponent as CloseIcon } from '../Assets/Icon/ic-cross.svg'
|
|
4
|
+
import { ReactComponent as QuestionFilled } from '../Assets/Icon/ic-help.svg'
|
|
5
5
|
import 'tippy.js/animations/shift-toward-subtle.css'
|
|
6
|
-
import { TippyTheme } from './Types'
|
|
7
|
-
|
|
8
|
-
interface TippyCustomizedProps {
|
|
9
|
-
theme: TippyTheme
|
|
10
|
-
visible?: boolean
|
|
11
|
-
heading?: string
|
|
12
|
-
infoTextHeading?: string
|
|
13
|
-
placement: Placement
|
|
14
|
-
className?: string
|
|
15
|
-
Icon?: React.FunctionComponent<React.SVGProps<SVGSVGElement>>
|
|
16
|
-
iconPath?: string
|
|
17
|
-
iconClass?: string
|
|
18
|
-
iconSize?: number // E.g. 16, 20, etc.. Currently, there are around 12 sizes supported. Check `icons.css` or `base.scss` for supported sizes or add new size (class names starts with `icon-dim-`).
|
|
19
|
-
onImageLoadError?: (e) => void
|
|
20
|
-
onClose?: () => void
|
|
21
|
-
infoText?: string
|
|
22
|
-
showCloseButton?: boolean
|
|
23
|
-
arrow?: boolean
|
|
24
|
-
interactive?: boolean
|
|
25
|
-
showOnCreate?: boolean
|
|
26
|
-
trigger?: string
|
|
27
|
-
animation?: string
|
|
28
|
-
duration?: number
|
|
29
|
-
additionalContent?: ReactNode
|
|
30
|
-
documentationLink?: string
|
|
31
|
-
documentationLinkText?: string
|
|
32
|
-
children: React.ReactElement<any>
|
|
33
|
-
}
|
|
6
|
+
import { TippyCustomizedProps, TippyTheme } from './Types'
|
|
7
|
+
import { not } from './Helper'
|
|
34
8
|
|
|
35
9
|
// This component will handle some of the new tippy designs and interactions
|
|
36
10
|
// So this can be updated to support further for new features or interactions
|
|
37
11
|
export function TippyCustomized(props: TippyCustomizedProps) {
|
|
38
12
|
const tippyRef = useRef(null)
|
|
13
|
+
const [showHeadingInfo, setShowHeadingInfo] = useState(false)
|
|
39
14
|
const isWhiteTheme = props.theme === TippyTheme.white
|
|
40
15
|
|
|
41
16
|
const onTippyMount = (tippyInstance) => {
|
|
@@ -52,6 +27,7 @@ export function TippyCustomized(props: TippyCustomizedProps) {
|
|
|
52
27
|
props.onClose()
|
|
53
28
|
}
|
|
54
29
|
}
|
|
30
|
+
setShowHeadingInfo(false)
|
|
55
31
|
}
|
|
56
32
|
|
|
57
33
|
const closeOnEsc = (e) => {
|
|
@@ -60,6 +36,10 @@ export function TippyCustomized(props: TippyCustomizedProps) {
|
|
|
60
36
|
}
|
|
61
37
|
}
|
|
62
38
|
|
|
39
|
+
const toggleHeadingInfo = (e) => {
|
|
40
|
+
setShowHeadingInfo(not)
|
|
41
|
+
}
|
|
42
|
+
|
|
63
43
|
const getTippyContent = () => {
|
|
64
44
|
const {
|
|
65
45
|
Icon,
|
|
@@ -68,6 +48,7 @@ export function TippyCustomized(props: TippyCustomizedProps) {
|
|
|
68
48
|
iconSize,
|
|
69
49
|
onImageLoadError,
|
|
70
50
|
heading,
|
|
51
|
+
headingInfo,
|
|
71
52
|
infoTextHeading,
|
|
72
53
|
infoText,
|
|
73
54
|
showCloseButton,
|
|
@@ -86,7 +67,7 @@ export function TippyCustomized(props: TippyCustomizedProps) {
|
|
|
86
67
|
<img
|
|
87
68
|
className={`icon-dim-${iconSize || 20} mr-6 ${iconClass || ''}`}
|
|
88
69
|
src={iconPath}
|
|
89
|
-
alt=
|
|
70
|
+
alt="Heading"
|
|
90
71
|
onError={onImageLoadError}
|
|
91
72
|
/>
|
|
92
73
|
) : (
|
|
@@ -97,6 +78,11 @@ export function TippyCustomized(props: TippyCustomizedProps) {
|
|
|
97
78
|
)
|
|
98
79
|
)}
|
|
99
80
|
{heading && <span className={`fs-14 fw-6 lh-20 ${showCloseButton ? 'mr-6' : ''}`}>{heading}</span>}
|
|
81
|
+
{headingInfo && (
|
|
82
|
+
<div className="icon-dim-20 cursor" onClick={toggleHeadingInfo}>
|
|
83
|
+
<QuestionFilled className="icon-dim-20" />
|
|
84
|
+
</div>
|
|
85
|
+
)}
|
|
100
86
|
{showCloseButton && (
|
|
101
87
|
<div className="icon-dim-16 ml-auto">
|
|
102
88
|
<CloseIcon
|
|
@@ -106,6 +92,18 @@ export function TippyCustomized(props: TippyCustomizedProps) {
|
|
|
106
92
|
</div>
|
|
107
93
|
)}
|
|
108
94
|
</div>
|
|
95
|
+
{showHeadingInfo && (
|
|
96
|
+
<div
|
|
97
|
+
className={`flex left bcv-1 fs-13 fw-4 lh-20 pt-8 pb-8 ${
|
|
98
|
+
isWhiteTheme ? 'pl-12 pr-12' : 'pl-20 pr-20'
|
|
99
|
+
}`}
|
|
100
|
+
>
|
|
101
|
+
<div className="icon-dim-20 mr-8">
|
|
102
|
+
<QuestionFilled className="icon-dim-20 fcv-5" />
|
|
103
|
+
</div>
|
|
104
|
+
<div className="dc__word-break dc__hyphens-auto">{headingInfo}</div>
|
|
105
|
+
</div>
|
|
106
|
+
)}
|
|
109
107
|
{infoTextHeading && (
|
|
110
108
|
<div
|
|
111
109
|
className={`dc__word-break dc__hyphens-auto fs-14 fw-6 lh-20 ${
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
.toggle__switch {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: inline-block;
|
|
4
|
+
width: 100%;
|
|
5
|
+
height: 100%;
|
|
6
|
+
|
|
7
|
+
&.disabled{
|
|
8
|
+
cursor: not-allowed;
|
|
9
|
+
.toggle__slider{
|
|
10
|
+
cursor: not-allowed;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
/* Hide default HTML checkbox */
|
|
17
|
+
|
|
18
|
+
.toggle__switch input {
|
|
19
|
+
opacity: 0;
|
|
20
|
+
width: 0;
|
|
21
|
+
height: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
/* The slider */
|
|
26
|
+
|
|
27
|
+
.toggle__slider {
|
|
28
|
+
position: absolute;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
top: 0;
|
|
31
|
+
left: 0;
|
|
32
|
+
right: 0;
|
|
33
|
+
bottom: 0;
|
|
34
|
+
background-color: #ccc;
|
|
35
|
+
transition: all .4s ease;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.toggle__slider:before {
|
|
39
|
+
position: absolute;
|
|
40
|
+
content: "";
|
|
41
|
+
height: calc( 100% - 8px);
|
|
42
|
+
width: calc( 50% - 4px);
|
|
43
|
+
left: 4px;
|
|
44
|
+
bottom: 4px;
|
|
45
|
+
background-color: white;
|
|
46
|
+
transition: all 0.4s ease;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
input:checked+.toggle__slider {
|
|
50
|
+
background-color: var(--color);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
input:focus+.toggle__slider {
|
|
54
|
+
box-shadow: 0 0 1px var(--color);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
input:checked+.toggle__slider:before {
|
|
58
|
+
transform: translateX(calc( 100%));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/* Rounded sliders */
|
|
63
|
+
|
|
64
|
+
.toggle__slider.round {
|
|
65
|
+
border-radius: 34px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.toggle__slider.round:before {
|
|
69
|
+
border-radius: 50%;
|
|
70
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useEffectAfterMount } from '../Helper';
|
|
3
|
+
import './Toggle.scss'
|
|
4
|
+
|
|
5
|
+
const Toggle = ({selected=false, onSelect=null, color="#36b37e", rootClassName="", disabled=false, dataTestId="handle-toggle-button", ...props})=>{
|
|
6
|
+
const [active, setActive] = React.useState(selected);
|
|
7
|
+
|
|
8
|
+
useEffectAfterMount(()=>{
|
|
9
|
+
if(typeof onSelect === 'function'){
|
|
10
|
+
if(active !== selected){
|
|
11
|
+
onSelect(active)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},[active])
|
|
15
|
+
|
|
16
|
+
useEffectAfterMount(() => {
|
|
17
|
+
setActive(selected)
|
|
18
|
+
}, [selected])
|
|
19
|
+
|
|
20
|
+
function handleClick(e){
|
|
21
|
+
if(!disabled){
|
|
22
|
+
setActive(active=>!active)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<label
|
|
28
|
+
{...props}
|
|
29
|
+
className={`${rootClassName} toggle__switch ${disabled ? 'disabled' : ''}`}
|
|
30
|
+
style={{ ['--color' as any]: color }}
|
|
31
|
+
>
|
|
32
|
+
<input type="checkbox" checked={!!active} onChange={handleClick} className="toggle__input" />
|
|
33
|
+
<span className="toggle__slider round" data-testid={dataTestId}></span>
|
|
34
|
+
</label>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default Toggle
|