@devtron-labs/devtron-fe-common-lib 0.0.50 → 0.0.51-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/ChartVersionAndTypeSelector.d.ts +4 -0
- package/dist/Common/Common.service.d.ts +1 -0
- package/dist/Common/Constants.d.ts +2 -0
- package/dist/Common/DraggableWrapper/DraggableButton.d.ts +3 -0
- package/dist/Common/DraggableWrapper/DraggableWrapper.d.ts +9 -0
- package/dist/Common/DraggableWrapper/index.d.ts +3 -0
- package/dist/Common/DraggableWrapper/types.d.ts +19 -0
- package/dist/Common/Grid/Grid.d.ts +1 -1
- package/dist/Common/Grid/types.d.ts +2 -2
- package/dist/Common/Helper.d.ts +9 -0
- package/dist/Common/Hooks/UseWindowSize/UseWindowSize.d.ts +4 -0
- package/dist/Common/Hooks/index.d.ts +1 -0
- package/dist/Common/Types.d.ts +64 -0
- package/dist/Common/index.d.ts +2 -0
- package/dist/index.js +1920 -157
- package/package.json +5 -2
- package/src/Assets/Icon/ic-drag.svg +8 -0
- package/src/Common/ChartVersionAndTypeSelector.tsx +78 -0
- package/src/Common/Common.service.ts +4 -0
- package/src/Common/Constants.ts +5 -2
- package/src/Common/DraggableWrapper/DraggableButton.tsx +11 -0
- package/src/Common/DraggableWrapper/DraggableWrapper.tsx +109 -0
- package/src/Common/DraggableWrapper/index.ts +3 -0
- package/src/Common/DraggableWrapper/types.ts +22 -0
- package/src/Common/Grid/Grid.tsx +7 -2
- package/src/Common/Grid/types.ts +3 -1
- package/src/Common/Helper.tsx +101 -0
- package/src/Common/Hooks/UseWindowSize/UseWindowSize.tsx +30 -0
- package/src/Common/Hooks/index.ts +1 -0
- package/src/Common/Types.ts +69 -0
- package/src/Common/index.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devtron-labs/devtron-fe-common-lib",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.51-beta-2",
|
|
4
4
|
"description": "Supporting common component library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -47,9 +47,12 @@
|
|
|
47
47
|
"react": "^17.0.2",
|
|
48
48
|
"react-dom": "^17.0.2",
|
|
49
49
|
"react-router": "^5.3.0",
|
|
50
|
-
"react-router-dom": "^5.3.0"
|
|
50
|
+
"react-router-dom": "^5.3.0",
|
|
51
|
+
"react-draggable": "^4.4.5"
|
|
51
52
|
},
|
|
52
53
|
"dependencies": {
|
|
54
|
+
"fast-json-patch": "^3.1.1",
|
|
55
|
+
"jsonpath-plus": "^7.2.0",
|
|
53
56
|
"sass": "^1.56.2",
|
|
54
57
|
"tslib": "^2.4.1"
|
|
55
58
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M10.3335 9.33325C10.8858 9.33325 11.3335 8.88554 11.3335 8.33325C11.3335 7.78097 10.8858 7.33325 10.3335 7.33325C9.78121 7.33325 9.3335 7.78097 9.3335 8.33325C9.3335 8.88554 9.78121 9.33325 10.3335 9.33325Z" fill="#596168"/>
|
|
3
|
+
<path d="M5.66675 9.33325C6.21903 9.33325 6.66675 8.88554 6.66675 8.33325C6.66675 7.78097 6.21903 7.33325 5.66675 7.33325C5.11446 7.33325 4.66675 7.78097 4.66675 8.33325C4.66675 8.88554 5.11446 9.33325 5.66675 9.33325Z" fill="#596168"/>
|
|
4
|
+
<path d="M10.3335 5.33325C10.8858 5.33325 11.3335 4.88554 11.3335 4.33325C11.3335 3.78097 10.8858 3.33325 10.3335 3.33325C9.78121 3.33325 9.3335 3.78097 9.3335 4.33325C9.3335 4.88554 9.78121 5.33325 10.3335 5.33325Z" fill="#596168"/>
|
|
5
|
+
<path d="M5.66675 5.33325C6.21903 5.33325 6.66675 4.88554 6.66675 4.33325C6.66675 3.78097 6.21903 3.33325 5.66675 3.33325C5.11446 3.33325 4.66675 3.78097 4.66675 4.33325C4.66675 4.88554 5.11446 5.33325 5.66675 5.33325Z" fill="#596168"/>
|
|
6
|
+
<path d="M10.3335 13.3333C10.8858 13.3333 11.3335 12.8855 11.3335 12.3333C11.3335 11.781 10.8858 11.3333 10.3335 11.3333C9.78121 11.3333 9.3335 11.781 9.3335 12.3333C9.3335 12.8855 9.78121 13.3333 10.3335 13.3333Z" fill="#596168"/>
|
|
7
|
+
<path d="M5.66675 13.3333C6.21903 13.3333 6.66675 12.8855 6.66675 12.3333C6.66675 11.781 6.21903 11.3333 5.66675 11.3333C5.11446 11.3333 4.66675 11.781 4.66675 12.3333C4.66675 12.8855 5.11446 13.3333 5.66675 13.3333Z" fill="#596168"/>
|
|
8
|
+
</svg>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react'
|
|
2
|
+
import { fetchChartTemplateVersions } from './Common.service'
|
|
3
|
+
import { ChartVersionAndTypeSelectorProps, DeploymentChartVersionType } from './Types'
|
|
4
|
+
import ReactSelect from 'react-select'
|
|
5
|
+
import { customStyles, getFilteredChartVersions, showError } from './Helper'
|
|
6
|
+
|
|
7
|
+
// @TODO: Generalize this component to be used in CodeEditor as Chart selector toolbar
|
|
8
|
+
// when the Code Editor is moved to the fe-common-lib
|
|
9
|
+
const ChartVersionAndTypeSelector = ({ setSelectedChartRefId }: ChartVersionAndTypeSelectorProps) => {
|
|
10
|
+
const [charts, setCharts] = useState<DeploymentChartVersionType[]>([])
|
|
11
|
+
const [selectedChartType, setSelectedChartType] = useState(null)
|
|
12
|
+
const [chartVersionOptions, setChartVersionOptions] = useState([])
|
|
13
|
+
const [chartTypeOptions, setChartTypeOptions] = useState([])
|
|
14
|
+
const [selectedChartVersion, setSelectedChartVersion] = useState(null)
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
fetchChartTemplateVersions()
|
|
18
|
+
.then((res) => {
|
|
19
|
+
const charts = res?.result || []
|
|
20
|
+
setCharts(charts)
|
|
21
|
+
// Extract unique chart types from the data
|
|
22
|
+
const chartTypeOptions = [...new Set(charts.map((item) => item.chartType))].map((type) => ({
|
|
23
|
+
value: type,
|
|
24
|
+
label: type,
|
|
25
|
+
}))
|
|
26
|
+
setChartTypeOptions(chartTypeOptions)
|
|
27
|
+
const filteredVersions = getFilteredChartVersions(charts, chartTypeOptions[0])
|
|
28
|
+
selectFirstChartVersion(filteredVersions)
|
|
29
|
+
})
|
|
30
|
+
.catch((err) => {
|
|
31
|
+
showError(err)
|
|
32
|
+
})
|
|
33
|
+
}, [])
|
|
34
|
+
|
|
35
|
+
const selectFirstChartVersion = (filteredVersions) => {
|
|
36
|
+
setChartVersionOptions(filteredVersions)
|
|
37
|
+
setSelectedChartVersion(filteredVersions[0]) // Select the first chart version by default
|
|
38
|
+
setSelectedChartRefId(filteredVersions[0]?.chartRefId)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Function to update chart version options based on selected chart type
|
|
42
|
+
const handleChartTypeChange = (selectedOption) => {
|
|
43
|
+
setSelectedChartType(selectedOption)
|
|
44
|
+
const filteredVersions = getFilteredChartVersions(charts, selectedOption)
|
|
45
|
+
selectFirstChartVersion(filteredVersions)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Function to handle the change of the selected chart version
|
|
49
|
+
const handleChartVersionChange = (selectedOption) => {
|
|
50
|
+
setSelectedChartVersion(selectedOption)
|
|
51
|
+
setSelectedChartRefId(selectedOption.chartRefId)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div className="flex">
|
|
56
|
+
<div className="chart-type-options flex" data-testid="chart-type-options">
|
|
57
|
+
<span className="chart-type-options-label mr-4">Chart Type</span>
|
|
58
|
+
<ReactSelect
|
|
59
|
+
value={selectedChartType ?? chartTypeOptions[0]}
|
|
60
|
+
options={chartTypeOptions}
|
|
61
|
+
onChange={handleChartTypeChange}
|
|
62
|
+
styles={customStyles}
|
|
63
|
+
/>
|
|
64
|
+
</div>
|
|
65
|
+
<div className="chart-version-options flex" data-testid="chart-version-options">
|
|
66
|
+
<span className="chart-version-options-label mr-4">Chart Version</span>
|
|
67
|
+
<ReactSelect
|
|
68
|
+
value={selectedChartVersion ?? chartVersionOptions[0]}
|
|
69
|
+
options={chartVersionOptions}
|
|
70
|
+
onChange={handleChartVersionChange}
|
|
71
|
+
styles={customStyles}
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default ChartVersionAndTypeSelector
|
package/src/Common/Constants.ts
CHANGED
|
@@ -24,7 +24,8 @@ export const ROUTES = {
|
|
|
24
24
|
PROJECT_LIST_MIN: 'team/autocomplete',
|
|
25
25
|
USER_CHECK_ROLE: 'user/check/roles',
|
|
26
26
|
IMAGE_TAGGING:'app/image-tagging',
|
|
27
|
-
CD_MATERIAL_GET: 'app/cd-pipeline'
|
|
27
|
+
CD_MATERIAL_GET: 'app/cd-pipeline',
|
|
28
|
+
DEPLOYMENT_TEMPLATE_LIST: 'app/template/list'
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
export enum KEY_VALUE {
|
|
@@ -239,4 +240,6 @@ export const RepositoryAction = {
|
|
|
239
240
|
CONTAINER: "CONTAINER",
|
|
240
241
|
CHART_PULL: "CHART_PULL",
|
|
241
242
|
CHART_PUSH: "CHART_PUSH"
|
|
242
|
-
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export const MAX_Z_INDEX = 2147483647
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { ReactComponent as ICDrag } from '../../Assets/Icon/ic-drag.svg'
|
|
3
|
+
import { DraggableButtonProps } from './types'
|
|
4
|
+
|
|
5
|
+
export default function DraggableButton({ dragClassName }: DraggableButtonProps) {
|
|
6
|
+
return (
|
|
7
|
+
<button type="button" className="dc__outline-none-imp dc__no-border p-0 dc__transparent h-20">
|
|
8
|
+
<ICDrag className={`${dragClassName} dc__grabbable icon-dim-20 fcn-6`} />
|
|
9
|
+
</button>
|
|
10
|
+
)
|
|
11
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react'
|
|
2
|
+
import Draggable, { ControlPosition, DraggableData } from 'react-draggable'
|
|
3
|
+
import { DraggableWrapperProps, DraggablePositionVariant } from './types'
|
|
4
|
+
import { useWindowSize } from '../Hooks'
|
|
5
|
+
import { MAX_Z_INDEX } from '../Constants'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* TODO: import it as lazy, after it is supported in common
|
|
9
|
+
* 1. If using react select please use menuPlacement='auto'
|
|
10
|
+
* 2. dragClassName will be used to identify the grabbable button that will grab the div to drag
|
|
11
|
+
* 3. parentRef is the reference point from which we will derive the base top:0 ,left: 0 position
|
|
12
|
+
*/
|
|
13
|
+
export default function DraggableWrapper({
|
|
14
|
+
children,
|
|
15
|
+
zIndex = MAX_Z_INDEX,
|
|
16
|
+
positionVariant,
|
|
17
|
+
dragClassName,
|
|
18
|
+
parentRef,
|
|
19
|
+
boundaryGap = 16,
|
|
20
|
+
childDivProps = {},
|
|
21
|
+
}: DraggableWrapperProps) {
|
|
22
|
+
const windowSize = useWindowSize()
|
|
23
|
+
const nodeRef = useRef<HTMLDivElement>(null)
|
|
24
|
+
|
|
25
|
+
const getDefaultPosition = (positionVariant: DraggablePositionVariant): ControlPosition => {
|
|
26
|
+
// if i return x: 0, y: 0 then it will be top left corner of parentDiv
|
|
27
|
+
const parentRect = parentRef?.current?.getBoundingClientRect() ?? {
|
|
28
|
+
width: 0,
|
|
29
|
+
height: 0,
|
|
30
|
+
top: 0,
|
|
31
|
+
left: 0,
|
|
32
|
+
bottom: 0,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
switch (positionVariant) {
|
|
36
|
+
case DraggablePositionVariant.PARENT_BOTTOM_CENTER: {
|
|
37
|
+
const x = parentRect.width / 2 - nodeRef.current?.getBoundingClientRect().width / 2
|
|
38
|
+
const y =
|
|
39
|
+
Math.min(parentRect.height, windowSize.height) -
|
|
40
|
+
parentRect.top -
|
|
41
|
+
nodeRef.current?.getBoundingClientRect().height -
|
|
42
|
+
boundaryGap
|
|
43
|
+
return { x, y }
|
|
44
|
+
}
|
|
45
|
+
case DraggablePositionVariant.SCREEN_BOTTOM_CENTER: {
|
|
46
|
+
const x = windowSize.width / 2 - parentRect.left - nodeRef.current?.getBoundingClientRect().width / 2
|
|
47
|
+
const y =
|
|
48
|
+
windowSize.height - parentRect.top - nodeRef.current?.getBoundingClientRect().height - boundaryGap
|
|
49
|
+
|
|
50
|
+
return { x, y }
|
|
51
|
+
}
|
|
52
|
+
// Add more cases for other variants if needed
|
|
53
|
+
default:
|
|
54
|
+
throw new Error('Please use DraggablePositionVariant enum')
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const [position, setPosition] = useState<ControlPosition>({
|
|
59
|
+
x: 0,
|
|
60
|
+
y: 0,
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// On change of windowSize we will reset the position to default
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
const defaultPosition = getDefaultPosition(positionVariant)
|
|
66
|
+
setPosition(defaultPosition)
|
|
67
|
+
}, [nodeRef, positionVariant, windowSize])
|
|
68
|
+
|
|
69
|
+
function handlePositionChange(e, data: DraggableData) {
|
|
70
|
+
const offsetX = parentRef?.current?.getBoundingClientRect().left ?? 0
|
|
71
|
+
const offsetY = parentRef?.current?.getBoundingClientRect().top ?? 0
|
|
72
|
+
|
|
73
|
+
if (
|
|
74
|
+
offsetX + data.x + nodeRef.current?.getBoundingClientRect().width + boundaryGap > windowSize.width ||
|
|
75
|
+
offsetY + data.y + nodeRef.current?.getBoundingClientRect().height + boundaryGap > windowSize.height ||
|
|
76
|
+
offsetX + data.x < 0 ||
|
|
77
|
+
offsetY + data.y < 0
|
|
78
|
+
) {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
setPosition({
|
|
83
|
+
x: data.x,
|
|
84
|
+
y: data.y,
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
// Check there might be a case if we need it to be absolute?
|
|
90
|
+
<div
|
|
91
|
+
className="dc__position-fixed"
|
|
92
|
+
style={{
|
|
93
|
+
zIndex,
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
<Draggable handle={`.${dragClassName}`} nodeRef={nodeRef} position={position} onDrag={handlePositionChange}>
|
|
97
|
+
<div
|
|
98
|
+
ref={nodeRef}
|
|
99
|
+
{...childDivProps}
|
|
100
|
+
style={{
|
|
101
|
+
zIndex,
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
{children}
|
|
105
|
+
</div>
|
|
106
|
+
</Draggable>
|
|
107
|
+
</div>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react'
|
|
2
|
+
|
|
3
|
+
export enum DraggablePositionVariant {
|
|
4
|
+
PARENT_BOTTOM_CENTER = 'PARENT_BOTTOM_CENTER',
|
|
5
|
+
SCREEN_BOTTOM_CENTER = 'SCREEN_BOTTOM_CENTER',
|
|
6
|
+
// Can add more based on requirement
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface DraggableWrapperProps {
|
|
10
|
+
children: React.ReactNode
|
|
11
|
+
zIndex?: number
|
|
12
|
+
positionVariant?: DraggablePositionVariant
|
|
13
|
+
dragClassName: string
|
|
14
|
+
parentRef?: React.RefObject<HTMLDivElement>
|
|
15
|
+
boundaryGap?: number
|
|
16
|
+
childDivProps?: HTMLAttributes<HTMLDivElement>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* dragClassName is the class that we feed to Draggable to identify dragging buttons
|
|
21
|
+
*/
|
|
22
|
+
export interface DraggableButtonProps extends Pick<DraggableWrapperProps, 'dragClassName'> {}
|
package/src/Common/Grid/Grid.tsx
CHANGED
|
@@ -10,6 +10,7 @@ export default function Grid({
|
|
|
10
10
|
containerClass = '',
|
|
11
11
|
itemClass = '',
|
|
12
12
|
children,
|
|
13
|
+
...containerDivProps
|
|
13
14
|
}: GridProps) {
|
|
14
15
|
const containerStyles = container ? { gap: spacing + 'px' } : {}
|
|
15
16
|
|
|
@@ -25,14 +26,18 @@ export default function Grid({
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
return (
|
|
28
|
-
<div className={`p-0 ${itemClass}`} style={itemStyles}>
|
|
29
|
+
<div className={`p-0 ${itemClass}`} style={itemStyles} {...containerDivProps}>
|
|
29
30
|
{children}
|
|
30
31
|
</div>
|
|
31
32
|
)
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
return (
|
|
35
|
-
<div
|
|
36
|
+
<div
|
|
37
|
+
className={`flex-wrap flexbox ${container ? containerClass : ''}`}
|
|
38
|
+
style={containerStyles}
|
|
39
|
+
{...containerDivProps}
|
|
40
|
+
>
|
|
36
41
|
{children}
|
|
37
42
|
</div>
|
|
38
43
|
)
|
package/src/Common/Grid/types.ts
CHANGED
package/src/Common/Helper.tsx
CHANGED
|
@@ -7,6 +7,8 @@ import { ERROR_EMPTY_SCREEN, TOKEN_COOKIE_NAME } from './Constants'
|
|
|
7
7
|
import { ServerErrors } from './ServerError'
|
|
8
8
|
import { toastAccessDenied } from './ToastBody'
|
|
9
9
|
import { AsyncOptions, AsyncState, UseSearchString } from './Types'
|
|
10
|
+
import { JSONPath } from 'jsonpath-plus'
|
|
11
|
+
import * as jsonpatch from 'fast-json-patch'
|
|
10
12
|
|
|
11
13
|
toast.configure({
|
|
12
14
|
autoClose: 3000,
|
|
@@ -458,3 +460,102 @@ export const getUrlWithSearchParams = (url: string, params: Record<string | numb
|
|
|
458
460
|
* Custom exception logger function for logging errors to sentry
|
|
459
461
|
*/
|
|
460
462
|
export const logExceptionToSentry = Sentry.captureException.bind(window)
|
|
463
|
+
|
|
464
|
+
export const customStyles = {
|
|
465
|
+
control: (base, state) => ({
|
|
466
|
+
...base,
|
|
467
|
+
minHeight: '32px',
|
|
468
|
+
boxShadow: 'none',
|
|
469
|
+
border: 'none',
|
|
470
|
+
cursor: 'pointer',
|
|
471
|
+
background: 'transparent',
|
|
472
|
+
}),
|
|
473
|
+
indicatorSeparator: (base, state) => ({
|
|
474
|
+
...base,
|
|
475
|
+
width: 0,
|
|
476
|
+
}),
|
|
477
|
+
valueContainer: (base, state) => ({
|
|
478
|
+
...base,
|
|
479
|
+
padding: '0',
|
|
480
|
+
fontSize: '13px',
|
|
481
|
+
fontWeight: '600',
|
|
482
|
+
}),
|
|
483
|
+
dropdownIndicator: (base, state) => ({
|
|
484
|
+
...base,
|
|
485
|
+
color: 'var(--N400)',
|
|
486
|
+
padding: '0 8px',
|
|
487
|
+
transition: 'all .2s ease',
|
|
488
|
+
transform: state.selectProps.menuIsOpen ? 'rotate(180deg)' : 'rotate(0deg)',
|
|
489
|
+
}),
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
export const getFilteredChartVersions = (charts, selectedChartType) => {
|
|
493
|
+
// Filter chart versions based on selected chart type
|
|
494
|
+
return charts
|
|
495
|
+
.filter((item) => item?.chartType === selectedChartType.value)
|
|
496
|
+
.map((item) => ({
|
|
497
|
+
value: item?.chartVersion,
|
|
498
|
+
label: item?.chartVersion,
|
|
499
|
+
chartRefId: item.chartRefId,
|
|
500
|
+
}))
|
|
501
|
+
}
|
|
502
|
+
function removeEmptyObjectKeysAndNullValues(obj) {
|
|
503
|
+
// It recursively removes empty object keys and array values that are null
|
|
504
|
+
for (let key in obj) {
|
|
505
|
+
if (Array.isArray(obj[key])) {
|
|
506
|
+
if (obj[key].length === 0) continue
|
|
507
|
+
obj[key] = obj[key].filter((item) => item !== null)
|
|
508
|
+
// Check if the array is empty
|
|
509
|
+
if (obj[key].length === 0) {
|
|
510
|
+
delete obj[key] // Delete the key if the array is empty
|
|
511
|
+
}
|
|
512
|
+
} else if (obj[key] && typeof obj[key] === 'object') {
|
|
513
|
+
if (removeEmptyObjectKeysAndNullValues(obj[key])) {
|
|
514
|
+
delete obj[key]
|
|
515
|
+
}
|
|
516
|
+
} else if (obj[key] === undefined) {
|
|
517
|
+
delete obj[key]
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return Object.keys(obj).length === 0
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
export function getUnlockedJSON(json, jsonPathArray) {
|
|
524
|
+
const jsonCopy = JSON.parse(JSON.stringify(json))
|
|
525
|
+
let patches = jsonPathArray.flatMap((jsonPath) => {
|
|
526
|
+
const pathsToRemove = JSONPath({ path: jsonPath, json: jsonCopy, resultType: 'all' })
|
|
527
|
+
return pathsToRemove.map((result) =>
|
|
528
|
+
Array.isArray(result.parent)
|
|
529
|
+
? { op: 'replace', path: result.pointer, value: null }
|
|
530
|
+
: { op: 'remove', path: result.pointer },
|
|
531
|
+
)
|
|
532
|
+
})
|
|
533
|
+
let newDocument = jsonpatch.applyPatch(jsonCopy, patches).newDocument
|
|
534
|
+
|
|
535
|
+
removeEmptyObjectKeysAndNullValues(newDocument)
|
|
536
|
+
return newDocument
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
export function getLockedJSON(json, jsonPathArray: string[]) {
|
|
540
|
+
const jsonCopy = JSON.parse(JSON.stringify(json))
|
|
541
|
+
let resultJson = {}
|
|
542
|
+
jsonPathArray.forEach((jsonPath) => {
|
|
543
|
+
const elements = JSONPath({ path: jsonPath, json: jsonCopy, resultType: 'all' })
|
|
544
|
+
elements.forEach((element) => {
|
|
545
|
+
const pathArray: string[] = JSONPath.toPathArray(element.path)
|
|
546
|
+
const lastPath = pathArray.pop()
|
|
547
|
+
let current = resultJson
|
|
548
|
+
for (let i = 0; i < pathArray.length; i++) {
|
|
549
|
+
let key = isNaN(Number(pathArray[i])) ? pathArray[i] : parseInt(pathArray[i])
|
|
550
|
+
if (!current[key]) {
|
|
551
|
+
current[key] = isNaN(Number(pathArray[i + 1]??lastPath)) ? {} : []
|
|
552
|
+
}
|
|
553
|
+
current = current[key]
|
|
554
|
+
}
|
|
555
|
+
let key = isNaN(Number(lastPath)) ? lastPath : parseInt(lastPath)
|
|
556
|
+
current[key] = element.value
|
|
557
|
+
})
|
|
558
|
+
})
|
|
559
|
+
return resultJson['$']
|
|
560
|
+
}
|
|
561
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react'
|
|
2
|
+
|
|
3
|
+
function getSize() {
|
|
4
|
+
return {
|
|
5
|
+
width: window.innerWidth,
|
|
6
|
+
height: window.innerHeight,
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function useWindowSize() {
|
|
11
|
+
let timeout
|
|
12
|
+
const [windowSize, setWindowSize] = useState(getSize)
|
|
13
|
+
|
|
14
|
+
function handleResize(e) {
|
|
15
|
+
if (timeout) {
|
|
16
|
+
window.cancelAnimationFrame(timeout)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
timeout = window.requestAnimationFrame(function () {
|
|
20
|
+
setWindowSize(getSize())
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
window.addEventListener('resize', handleResize, false)
|
|
26
|
+
return () => window.removeEventListener('resize', handleResize, false)
|
|
27
|
+
}, [])
|
|
28
|
+
|
|
29
|
+
return windowSize
|
|
30
|
+
}
|
package/src/Common/Types.ts
CHANGED
|
@@ -631,6 +631,75 @@ export interface CiPipeline {
|
|
|
631
631
|
isOffendingMandatoryPlugin?: boolean
|
|
632
632
|
pipelineType?: string
|
|
633
633
|
}
|
|
634
|
+
export interface InformationBarProps {
|
|
635
|
+
text: string
|
|
636
|
+
className?: string
|
|
637
|
+
children?: React.ReactNode
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
export interface CodeEditorInterface {
|
|
641
|
+
value?: string
|
|
642
|
+
lineDecorationsWidth?: number
|
|
643
|
+
responseType?: string
|
|
644
|
+
onChange?: (string) => void
|
|
645
|
+
onBlur?: () => void
|
|
646
|
+
onFocus?: () => void
|
|
647
|
+
children?: any
|
|
648
|
+
defaultValue?: string
|
|
649
|
+
mode?: 'json' | 'yaml' | 'shell' | 'dockerfile' | 'plaintext'
|
|
650
|
+
tabSize?: number
|
|
651
|
+
readOnly?: boolean
|
|
652
|
+
noParsing?: boolean
|
|
653
|
+
minHeight?: number
|
|
654
|
+
maxHeight?: number
|
|
655
|
+
inline?: boolean
|
|
656
|
+
height?: number | string
|
|
657
|
+
shebang?: string | JSX.Element
|
|
658
|
+
diffView?: boolean
|
|
659
|
+
loading?: boolean
|
|
660
|
+
customLoader?: JSX.Element
|
|
661
|
+
theme?: string
|
|
662
|
+
original?: string
|
|
663
|
+
focus?: boolean
|
|
664
|
+
validatorSchema?: any
|
|
665
|
+
isKubernetes?: boolean
|
|
666
|
+
cleanData?: boolean
|
|
667
|
+
chartVersion?: any
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
export interface CodeEditorComposition {
|
|
671
|
+
Header?: React.FC<any>
|
|
672
|
+
LanguageChanger?: React.FC<any>
|
|
673
|
+
ThemeChanger?: React.FC<any>
|
|
674
|
+
ValidationError?: React.FC<any>
|
|
675
|
+
Clipboard?: React.FC<any>
|
|
676
|
+
Warning?: React.FC<InformationBarProps>
|
|
677
|
+
ErrorBar?: React.FC<InformationBarProps>
|
|
678
|
+
Information?: React.FC<InformationBarProps>
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
export interface CodeEditorHeaderComposition {
|
|
682
|
+
LanguageChanger?: React.FC<any>;
|
|
683
|
+
ThemeChanger?: React.FC<any>;
|
|
684
|
+
ValidationError?: React.FC<any>;
|
|
685
|
+
Clipboard?: React.FC<any>;
|
|
686
|
+
}
|
|
687
|
+
export interface CodeEditorHeaderInterface {
|
|
688
|
+
children?: any;
|
|
689
|
+
className?: string
|
|
690
|
+
hideDefaultSplitHeader?: boolean;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
export interface DeploymentChartVersionType {
|
|
694
|
+
chartRefId: number
|
|
695
|
+
chartVersion: string
|
|
696
|
+
chartType: string
|
|
697
|
+
type: number
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
export interface ChartVersionAndTypeSelectorProps {
|
|
701
|
+
setSelectedChartRefId: React.Dispatch<React.SetStateAction<number>>
|
|
702
|
+
}
|
|
634
703
|
|
|
635
704
|
export enum PipelineType {
|
|
636
705
|
CI_PIPELINE = 'CI_PIPELINE',
|
package/src/Common/index.ts
CHANGED
|
@@ -42,5 +42,7 @@ export * from './Hooks'
|
|
|
42
42
|
export { AppStatus } from './AppStatus'
|
|
43
43
|
export * from './RJSF'
|
|
44
44
|
export * from './DevtronProgressing'
|
|
45
|
+
export { default as ChartVersionAndTypeSelector } from './ChartVersionAndTypeSelector'
|
|
45
46
|
export * from './AddCDButton'
|
|
46
47
|
export * from './CustomInput'
|
|
48
|
+
export * from './DraggableWrapper'
|