@devtron-labs/devtron-fe-common-lib 0.0.45 → 0.0.47-beta-3
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 +1 -0
- package/dist/Common/CustomInput/CustomInput.d.ts +3 -0
- package/dist/Common/CustomInput/Types.d.ts +29 -0
- package/dist/Common/CustomInput/index.d.ts +2 -0
- package/dist/Common/Helper.d.ts +10 -17
- package/dist/Common/Types.d.ts +64 -1
- package/dist/Common/index.d.ts +2 -0
- package/dist/index.js +1808 -137
- package/package.json +16 -14
- package/src/Common/ChartVersionAndTypeSelector.tsx +78 -0
- package/src/Common/Common.service.ts +4 -0
- package/src/Common/Constants.ts +2 -1
- package/src/Common/CustomInput/CustomInput.tsx +131 -0
- package/src/Common/CustomInput/Types.ts +30 -0
- package/src/Common/CustomInput/index.ts +2 -0
- package/src/Common/Helper.tsx +100 -61
- package/src/Common/Types.ts +70 -1
- 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.47-beta-3",
|
|
4
4
|
"description": "Supporting common component library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -20,25 +20,25 @@
|
|
|
20
20
|
"homepage": "https://github.com/devtron-labs/devtron-fe-common-lib#readme",
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@rollup/plugin-babel": "^6.0.3",
|
|
23
|
-
"@rollup/plugin-
|
|
23
|
+
"@rollup/plugin-commonjs": "24.0.1",
|
|
24
24
|
"@rollup/plugin-image": "3.0.1",
|
|
25
|
-
"rollup
|
|
26
|
-
"rollup
|
|
27
|
-
"
|
|
25
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
26
|
+
"@rollup/plugin-url": "8.0.1",
|
|
27
|
+
"@sentry/browser": "^7.31.1",
|
|
28
|
+
"@svgr/rollup": "6.5.1",
|
|
29
|
+
"@tippyjs/react": "^4.2.0",
|
|
28
30
|
"@types/react": "17.0.39",
|
|
29
31
|
"@types/react-dom": "17.0.13",
|
|
30
32
|
"@types/react-router-dom": "^5.3.3",
|
|
31
|
-
"rollup": "^3.10.0",
|
|
32
|
-
"rollup-plugin-delete": "^2.0.0",
|
|
33
|
-
"@svgr/rollup": "6.5.1",
|
|
34
|
-
"@rollup/plugin-url": "8.0.1",
|
|
35
|
-
"@rollup/plugin-commonjs": "24.0.1",
|
|
36
33
|
"moment": "^2.29.4",
|
|
37
|
-
"typescript": "^4.9.4",
|
|
38
|
-
"react-toastify": "^8.2.0",
|
|
39
|
-
"@tippyjs/react": "^4.2.0",
|
|
40
34
|
"react-select": "5.2.2",
|
|
41
|
-
"
|
|
35
|
+
"react-toastify": "^8.2.0",
|
|
36
|
+
"rollup": "^3.10.0",
|
|
37
|
+
"rollup-plugin-delete": "^2.0.0",
|
|
38
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
39
|
+
"rollup-plugin-postcss": "^4.0.2",
|
|
40
|
+
"rollup-plugin-typescript2": "^0.34.1",
|
|
41
|
+
"typescript": "^4.9.4"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@rjsf/core": "^5.13.3",
|
|
@@ -50,6 +50,8 @@
|
|
|
50
50
|
"react-router-dom": "^5.3.0"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
+
"fast-json-patch": "^3.1.1",
|
|
54
|
+
"jsonpath-plus": "^7.2.0",
|
|
53
55
|
"sass": "^1.56.2",
|
|
54
56
|
"tslib": "^2.4.1"
|
|
55
57
|
}
|
|
@@ -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 {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { CustomInputProps } from './Types'
|
|
2
|
+
import { ReactComponent as Info } from '../../Assets/Icon/ic-info-filled.svg'
|
|
3
|
+
import { ReactComponent as ErrorIcon } from '../../Assets/Icon/ic-warning.svg'
|
|
4
|
+
|
|
5
|
+
export function CustomInput({
|
|
6
|
+
name,
|
|
7
|
+
value,
|
|
8
|
+
error,
|
|
9
|
+
onChange,
|
|
10
|
+
onFocus = (e) => {},
|
|
11
|
+
label,
|
|
12
|
+
type = 'text',
|
|
13
|
+
disabled = false,
|
|
14
|
+
labelClassName = '',
|
|
15
|
+
placeholder = '',
|
|
16
|
+
tabIndex = 1,
|
|
17
|
+
dataTestid = '',
|
|
18
|
+
isRequiredField = false,
|
|
19
|
+
autoFocus = false,
|
|
20
|
+
rootClassName = '',
|
|
21
|
+
autoComplete = 'off',
|
|
22
|
+
helperText = '',
|
|
23
|
+
handleOnBlur,
|
|
24
|
+
readOnly = false,
|
|
25
|
+
noTrim = false,
|
|
26
|
+
ref,
|
|
27
|
+
onKeyPress,
|
|
28
|
+
defaultValue,
|
|
29
|
+
onKeyDown,
|
|
30
|
+
required,
|
|
31
|
+
additionalErrorInfo
|
|
32
|
+
}: CustomInputProps) {
|
|
33
|
+
|
|
34
|
+
function handleError(error: any): any[] {
|
|
35
|
+
if (!Array.isArray(error)) {
|
|
36
|
+
return [error]
|
|
37
|
+
}
|
|
38
|
+
return error
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const onBlur = (event) => {
|
|
42
|
+
//NOTE: This is to prevent the input from being trimmed when the user do not want to trim the input
|
|
43
|
+
if (!noTrim) {
|
|
44
|
+
event.stopPropagation()
|
|
45
|
+
event.target.value = event.target.value?.trim()
|
|
46
|
+
onChange(event)
|
|
47
|
+
}
|
|
48
|
+
if (typeof handleOnBlur === 'function') {
|
|
49
|
+
handleOnBlur(event)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const renderFormErrorWithIcon = (error: string) => {
|
|
54
|
+
return (
|
|
55
|
+
<div className="form__error" key={error}>
|
|
56
|
+
<ErrorIcon className="form__icon form__icon--error" />
|
|
57
|
+
{error}
|
|
58
|
+
{typeof additionalErrorInfo === 'function' && additionalErrorInfo()}
|
|
59
|
+
</div>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const getInputError = () => {
|
|
64
|
+
if (!error?.length) {
|
|
65
|
+
return null
|
|
66
|
+
} else {
|
|
67
|
+
if (typeof error === 'object') {
|
|
68
|
+
return handleError(error).map((err: string) => renderFormErrorWithIcon(err))
|
|
69
|
+
}
|
|
70
|
+
return renderFormErrorWithIcon(error)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const renderInputLabelConditionally = () => {
|
|
75
|
+
if (typeof label === 'string') {
|
|
76
|
+
return <span className={`${isRequiredField ? 'dc__required-field' : ''}`}>{label}</span>
|
|
77
|
+
} else {
|
|
78
|
+
return label()
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const renderInputLabel = () => {
|
|
83
|
+
if (!label) {
|
|
84
|
+
return null
|
|
85
|
+
} else {
|
|
86
|
+
return (
|
|
87
|
+
<label className={`form__label ${labelClassName}`} data-testid={`label-${dataTestid}`}>
|
|
88
|
+
{renderInputLabelConditionally()}
|
|
89
|
+
</label>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<div className="flex column left top">
|
|
96
|
+
{renderInputLabel()}
|
|
97
|
+
<input
|
|
98
|
+
data-testid={dataTestid}
|
|
99
|
+
type={type}
|
|
100
|
+
name={name}
|
|
101
|
+
autoComplete={autoComplete}
|
|
102
|
+
className={`form__input ${rootClassName}`}
|
|
103
|
+
onChange={(e) => {
|
|
104
|
+
e.persist()
|
|
105
|
+
onChange(e)
|
|
106
|
+
}}
|
|
107
|
+
onBlur={onBlur}
|
|
108
|
+
onFocus={onFocus}
|
|
109
|
+
placeholder={placeholder}
|
|
110
|
+
value={value}
|
|
111
|
+
disabled={disabled}
|
|
112
|
+
tabIndex={tabIndex}
|
|
113
|
+
autoFocus={autoFocus}
|
|
114
|
+
readOnly={readOnly}
|
|
115
|
+
ref={ref}
|
|
116
|
+
onKeyPress={onKeyPress}
|
|
117
|
+
defaultValue={defaultValue}
|
|
118
|
+
onKeyDown={onKeyDown}
|
|
119
|
+
required={required}
|
|
120
|
+
/>
|
|
121
|
+
|
|
122
|
+
{getInputError()}
|
|
123
|
+
{helperText && (
|
|
124
|
+
<div className="form__text-field-info">
|
|
125
|
+
<Info className="form__icon form__icon--info" />
|
|
126
|
+
<p className="sentence-case">{helperText}</p>
|
|
127
|
+
</div>
|
|
128
|
+
)}
|
|
129
|
+
</div>
|
|
130
|
+
)
|
|
131
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { HTMLInputTypeAttribute } from 'react'
|
|
2
|
+
|
|
3
|
+
export interface CustomInputProps {
|
|
4
|
+
name: string
|
|
5
|
+
value: string | number
|
|
6
|
+
onChange: (e: any) => void
|
|
7
|
+
onFocus?: (e: any) => void
|
|
8
|
+
autoComplete?: string
|
|
9
|
+
label?: string | (() => React.ReactNode)
|
|
10
|
+
labelClassName?: string
|
|
11
|
+
type?: HTMLInputTypeAttribute
|
|
12
|
+
disabled?: boolean
|
|
13
|
+
placeholder?: string
|
|
14
|
+
tabIndex?: number
|
|
15
|
+
dataTestid?: string
|
|
16
|
+
isRequiredField?: boolean
|
|
17
|
+
autoFocus?: boolean
|
|
18
|
+
rootClassName?: string
|
|
19
|
+
error?: string[] | string
|
|
20
|
+
helperText?: string
|
|
21
|
+
handleOnBlur?: (e) => void
|
|
22
|
+
readOnly?: boolean
|
|
23
|
+
noTrim?: boolean
|
|
24
|
+
ref?: React.LegacyRef<HTMLInputElement>
|
|
25
|
+
onKeyPress?: (e) => void
|
|
26
|
+
defaultValue?: string | number | ReadonlyArray<string> | undefined
|
|
27
|
+
onKeyDown?: (e) => void
|
|
28
|
+
required?: boolean
|
|
29
|
+
additionalErrorInfo?: React.ReactNode
|
|
30
|
+
}
|
package/src/Common/Helper.tsx
CHANGED
|
@@ -3,11 +3,12 @@ import moment from 'moment'
|
|
|
3
3
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
4
4
|
import { useLocation } from 'react-router-dom'
|
|
5
5
|
import { toast } from 'react-toastify'
|
|
6
|
-
import { ReactComponent as FormError } from '../Assets/Icon/ic-warning.svg'
|
|
7
6
|
import { ERROR_EMPTY_SCREEN, TOKEN_COOKIE_NAME } from './Constants'
|
|
8
7
|
import { ServerErrors } from './ServerError'
|
|
9
8
|
import { toastAccessDenied } from './ToastBody'
|
|
10
9
|
import { AsyncOptions, AsyncState, UseSearchString } from './Types'
|
|
10
|
+
import { JSONPath } from 'jsonpath-plus'
|
|
11
|
+
import * as jsonpatch from 'fast-json-patch'
|
|
11
12
|
|
|
12
13
|
toast.configure({
|
|
13
14
|
autoClose: 3000,
|
|
@@ -116,11 +117,11 @@ export function getRandomColor(email: string): string {
|
|
|
116
117
|
return colors[sum % colors.length]
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
export const getAlphabetIcon = (str: string,
|
|
120
|
+
export const getAlphabetIcon = (str: string, rootClassName: string = "") => {
|
|
120
121
|
if (!str) return null
|
|
121
122
|
return (
|
|
122
123
|
<span
|
|
123
|
-
className={`${
|
|
124
|
+
className={`${rootClassName} alphabet-icon__initial fs-13 icon-dim-20 flex cn-0 mr-8`}
|
|
124
125
|
style={{ backgroundColor: getRandomColor(str) }}
|
|
125
126
|
>
|
|
126
127
|
{str[0]}
|
|
@@ -277,64 +278,6 @@ export function useForm(stateSchema, validationSchema = {}, callback) {
|
|
|
277
278
|
return { state, disable, handleOnChange, handleOnSubmit }
|
|
278
279
|
}
|
|
279
280
|
|
|
280
|
-
function handleError(error: any): any[] {
|
|
281
|
-
if (!error) {
|
|
282
|
-
return []
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (!Array.isArray(error)) {
|
|
286
|
-
return [error]
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
return error
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
export function CustomInput({
|
|
293
|
-
name,
|
|
294
|
-
value,
|
|
295
|
-
error,
|
|
296
|
-
onChange,
|
|
297
|
-
onBlur = (e) => {},
|
|
298
|
-
onFocus = (e) => {},
|
|
299
|
-
label,
|
|
300
|
-
type = 'text',
|
|
301
|
-
disabled = false,
|
|
302
|
-
autoComplete = 'off',
|
|
303
|
-
labelClassName = '',
|
|
304
|
-
placeholder = '',
|
|
305
|
-
tabIndex = 1,
|
|
306
|
-
dataTestid = '',
|
|
307
|
-
}) {
|
|
308
|
-
return (
|
|
309
|
-
<div className="flex column left top">
|
|
310
|
-
<label className={`form__label ${labelClassName}`}>{label}</label>
|
|
311
|
-
<input
|
|
312
|
-
data-testid={dataTestid}
|
|
313
|
-
type={type}
|
|
314
|
-
name={name}
|
|
315
|
-
autoComplete="off"
|
|
316
|
-
className="form__input"
|
|
317
|
-
onChange={(e) => {
|
|
318
|
-
e.persist()
|
|
319
|
-
onChange(e)
|
|
320
|
-
}}
|
|
321
|
-
onBlur={onBlur}
|
|
322
|
-
onFocus={onFocus}
|
|
323
|
-
placeholder={placeholder}
|
|
324
|
-
value={value}
|
|
325
|
-
disabled={disabled}
|
|
326
|
-
tabIndex={tabIndex}
|
|
327
|
-
/>
|
|
328
|
-
{handleError(error).map((err) => (
|
|
329
|
-
<div className="form__error" key={err}>
|
|
330
|
-
<FormError className="form__icon form__icon--error" />
|
|
331
|
-
{err}
|
|
332
|
-
</div>
|
|
333
|
-
))}
|
|
334
|
-
</div>
|
|
335
|
-
)
|
|
336
|
-
}
|
|
337
|
-
|
|
338
281
|
export function handleUTCTime(ts: string, isRelativeTime = false) {
|
|
339
282
|
let timestamp = ''
|
|
340
283
|
try {
|
|
@@ -517,3 +460,99 @@ export const getUrlWithSearchParams = (url: string, params: Record<string | numb
|
|
|
517
460
|
* Custom exception logger function for logging errors to sentry
|
|
518
461
|
*/
|
|
519
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])) obj[key] = obj[key].filter((item) => item !== null)
|
|
506
|
+
if (obj[key].length === 0) {
|
|
507
|
+
// Check if the array is empty
|
|
508
|
+
delete obj[key] // Delete the key if the array is empty
|
|
509
|
+
} else if (obj[key] && typeof obj[key] === 'object') {
|
|
510
|
+
if (removeEmptyObjectKeysAndNullValues(obj[key])) {
|
|
511
|
+
delete obj[key]
|
|
512
|
+
}
|
|
513
|
+
} else if (obj[key] === null || obj[key] === undefined) {
|
|
514
|
+
delete obj[key]
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return Object.keys(obj).length === 0
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
export function getUnlockedJSON(json, jsonPathArray) {
|
|
521
|
+
const jsonCopy = JSON.parse(JSON.stringify(json))
|
|
522
|
+
let patches = jsonPathArray.flatMap((jsonPath) => {
|
|
523
|
+
const pathsToRemove = JSONPath({ path: jsonPath, json: jsonCopy, resultType: 'all' })
|
|
524
|
+
return pathsToRemove.map((result) =>
|
|
525
|
+
Array.isArray(result.parent)
|
|
526
|
+
? { op: 'replace', path: result.pointer, value: null }
|
|
527
|
+
: { op: 'remove', path: result.pointer },
|
|
528
|
+
)
|
|
529
|
+
})
|
|
530
|
+
let newDocument = jsonpatch.applyPatch(jsonCopy, patches).newDocument
|
|
531
|
+
|
|
532
|
+
removeEmptyObjectKeysAndNullValues(newDocument)
|
|
533
|
+
return newDocument
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
export function getLockedJSON(json, jsonPathArray: string[]) {
|
|
537
|
+
const jsonCopy = JSON.parse(JSON.stringify(json))
|
|
538
|
+
let resultJson = {}
|
|
539
|
+
jsonPathArray.forEach((jsonPath) => {
|
|
540
|
+
const elements = JSONPath({ path: jsonPath, json: jsonCopy, resultType: 'all' })
|
|
541
|
+
elements.forEach((element) => {
|
|
542
|
+
const pathArray: string[] = JSONPath.toPathArray(element.path)
|
|
543
|
+
const lastPath = pathArray.pop()
|
|
544
|
+
let current = resultJson
|
|
545
|
+
for (let i = 0; i < pathArray.length; i++) {
|
|
546
|
+
let key = isNaN(Number(pathArray[i])) ? pathArray[i] : parseInt(pathArray[i])
|
|
547
|
+
if (!current[key]) {
|
|
548
|
+
current[key] = isNaN(Number(pathArray[i + 1])) ? {} : []
|
|
549
|
+
}
|
|
550
|
+
current = current[key]
|
|
551
|
+
}
|
|
552
|
+
let key = isNaN(Number(lastPath)) ? lastPath : parseInt(lastPath)
|
|
553
|
+
current[key] = element.value
|
|
554
|
+
})
|
|
555
|
+
})
|
|
556
|
+
return resultJson['$']
|
|
557
|
+
}
|
|
558
|
+
|
package/src/Common/Types.ts
CHANGED
|
@@ -79,7 +79,6 @@ export interface TippyCustomizedProps {
|
|
|
79
79
|
documentationLink?: string
|
|
80
80
|
documentationLinkText?: string
|
|
81
81
|
children: React.ReactElement<any>
|
|
82
|
-
followCursor?: boolean
|
|
83
82
|
}
|
|
84
83
|
export interface GenericEmptyStateType {
|
|
85
84
|
title: ReactNode
|
|
@@ -624,3 +623,73 @@ export interface CiPipeline {
|
|
|
624
623
|
isOffendingMandatoryPlugin?: boolean
|
|
625
624
|
pipelineType?: string
|
|
626
625
|
}
|
|
626
|
+
|
|
627
|
+
export interface DeploymentChartVersionType {
|
|
628
|
+
chartRefId: number
|
|
629
|
+
chartVersion: string
|
|
630
|
+
chartType: string
|
|
631
|
+
type: number
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
export interface ChartVersionAndTypeSelectorProps {
|
|
635
|
+
setSelectedChartRefId: React.Dispatch<React.SetStateAction<number>>
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export interface InformationBarProps {
|
|
639
|
+
text: string
|
|
640
|
+
className?: string
|
|
641
|
+
children?: React.ReactNode
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
export interface CodeEditorInterface {
|
|
645
|
+
value?: string
|
|
646
|
+
lineDecorationsWidth?: number
|
|
647
|
+
responseType?: string
|
|
648
|
+
onChange?: (string) => void
|
|
649
|
+
onBlur?: () => void
|
|
650
|
+
onFocus?: () => void
|
|
651
|
+
children?: any
|
|
652
|
+
defaultValue?: string
|
|
653
|
+
mode?: 'json' | 'yaml' | 'shell' | 'dockerfile' | 'plaintext'
|
|
654
|
+
tabSize?: number
|
|
655
|
+
readOnly?: boolean
|
|
656
|
+
noParsing?: boolean
|
|
657
|
+
minHeight?: number
|
|
658
|
+
maxHeight?: number
|
|
659
|
+
inline?: boolean
|
|
660
|
+
height?: number | string
|
|
661
|
+
shebang?: string | JSX.Element
|
|
662
|
+
diffView?: boolean
|
|
663
|
+
loading?: boolean
|
|
664
|
+
customLoader?: JSX.Element
|
|
665
|
+
theme?: string
|
|
666
|
+
original?: string
|
|
667
|
+
focus?: boolean
|
|
668
|
+
validatorSchema?: any
|
|
669
|
+
isKubernetes?: boolean
|
|
670
|
+
cleanData?: boolean
|
|
671
|
+
chartVersion?: any
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
export interface CodeEditorComposition {
|
|
675
|
+
Header?: React.FC<any>
|
|
676
|
+
LanguageChanger?: React.FC<any>
|
|
677
|
+
ThemeChanger?: React.FC<any>
|
|
678
|
+
ValidationError?: React.FC<any>
|
|
679
|
+
Clipboard?: React.FC<any>
|
|
680
|
+
Warning?: React.FC<InformationBarProps>
|
|
681
|
+
ErrorBar?: React.FC<InformationBarProps>
|
|
682
|
+
Information?: React.FC<InformationBarProps>
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
export interface CodeEditorHeaderComposition {
|
|
686
|
+
LanguageChanger?: React.FC<any>;
|
|
687
|
+
ThemeChanger?: React.FC<any>;
|
|
688
|
+
ValidationError?: React.FC<any>;
|
|
689
|
+
Clipboard?: React.FC<any>;
|
|
690
|
+
}
|
|
691
|
+
export interface CodeEditorHeaderInterface {
|
|
692
|
+
children?: any;
|
|
693
|
+
className?: string
|
|
694
|
+
hideDefaultSplitHeader?: boolean;
|
|
695
|
+
}
|
package/src/Common/index.ts
CHANGED