@devtron-labs/devtron-fe-common-lib 0.0.47-beta-5 → 0.0.48
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/AddCDButton/AddCDButton.d.ts +3 -0
- package/dist/Common/AddCDButton/index.d.ts +2 -0
- package/dist/Common/AddCDButton/types.d.ts +26 -0
- package/dist/Common/AddCDButton/utils.d.ts +2 -0
- package/dist/Common/Common.service.d.ts +0 -1
- package/dist/Common/Constants.d.ts +0 -1
- package/dist/Common/Dialogs/Types.d.ts +1 -0
- package/dist/Common/Helper.d.ts +0 -9
- package/dist/Common/Types.d.ts +43 -60
- package/dist/Common/index.d.ts +1 -1
- package/dist/index.js +86 -1646
- package/package.json +1 -3
- package/src/Common/AddCDButton/AddCDButton.tsx +68 -0
- package/src/Common/AddCDButton/index.ts +2 -0
- package/src/Common/AddCDButton/types.ts +38 -0
- package/src/Common/AddCDButton/utils.tsx +35 -0
- package/src/Common/Common.service.ts +0 -4
- package/src/Common/Constants.ts +1 -2
- package/src/Common/Dialogs/DeleteDialog.tsx +1 -1
- package/src/Common/Dialogs/Types.ts +1 -0
- package/src/Common/Helper.tsx +0 -98
- package/src/Common/Types.ts +49 -63
- package/src/Common/index.ts +1 -1
- package/dist/Common/ChartVersionAndTypeSelector.d.ts +0 -4
- package/src/Common/ChartVersionAndTypeSelector.tsx +0 -78
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.48",
|
|
4
4
|
"description": "Supporting common component library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -50,8 +50,6 @@
|
|
|
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",
|
|
55
53
|
"sass": "^1.56.2",
|
|
56
54
|
"tslib": "^2.4.1"
|
|
57
55
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import Tippy from '@tippyjs/react'
|
|
3
|
+
import { AddCDButtonProps, TooltipContentProps } from './types'
|
|
4
|
+
import { AddCDPositions } from '../Types'
|
|
5
|
+
|
|
6
|
+
function TooltipContent({ tooltipContent }: TooltipContentProps) {
|
|
7
|
+
if (tooltipContent) {
|
|
8
|
+
return (
|
|
9
|
+
<div className="dc__white-space-pre-wrap">
|
|
10
|
+
<p className="m-0 cn-0 fs-12 fw-6 lh-18">Click to add</p>
|
|
11
|
+
|
|
12
|
+
{tooltipContent}
|
|
13
|
+
</div>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return <div className="dc__white-space-pre-wrap">Click to add here</div>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default function AddCDButton({
|
|
21
|
+
position,
|
|
22
|
+
addCDButtons,
|
|
23
|
+
endNode,
|
|
24
|
+
startNode,
|
|
25
|
+
handleAddCD,
|
|
26
|
+
tooltipContent,
|
|
27
|
+
}: Readonly<AddCDButtonProps>) {
|
|
28
|
+
const referenceNode = position === AddCDPositions.RIGHT ? endNode : startNode
|
|
29
|
+
const handleAddCDClick = () => {
|
|
30
|
+
handleAddCD(position)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (addCDButtons?.includes(position)) {
|
|
34
|
+
return (
|
|
35
|
+
<Tippy
|
|
36
|
+
placement="top"
|
|
37
|
+
content={<TooltipContent tooltipContent={tooltipContent} />}
|
|
38
|
+
className="default-tt"
|
|
39
|
+
arrow={false}
|
|
40
|
+
>
|
|
41
|
+
<svg
|
|
42
|
+
x={referenceNode.x + (position === AddCDPositions.RIGHT ? -20 - 5 : referenceNode.width + 5)}
|
|
43
|
+
// Here 10 is the height of the button / 2
|
|
44
|
+
y={referenceNode.y + referenceNode.height / 2 - 10}
|
|
45
|
+
width="20"
|
|
46
|
+
height="20"
|
|
47
|
+
viewBox="0 0 20 20"
|
|
48
|
+
fill="none"
|
|
49
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
50
|
+
data-testid={`add-cd-to-${position}`}
|
|
51
|
+
onClick={handleAddCDClick}
|
|
52
|
+
className="dc__outline-none-imp"
|
|
53
|
+
>
|
|
54
|
+
<rect width="20" height="20" rx="10" fill="#664BEE" className="add-cd-edge-btn" />
|
|
55
|
+
<path
|
|
56
|
+
d="M6.5 10H13.5M10 6.5V13.5"
|
|
57
|
+
stroke="white"
|
|
58
|
+
strokeWidth="1.5"
|
|
59
|
+
strokeLinecap="round"
|
|
60
|
+
strokeLinejoin="round"
|
|
61
|
+
/>
|
|
62
|
+
</svg>
|
|
63
|
+
</Tippy>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AddCDPositions, AddPipelineType, EdgeEndNodeType, EdgeNodeType, Point } from '../Types'
|
|
2
|
+
|
|
3
|
+
export interface AddCDButtonProps {
|
|
4
|
+
position: AddCDPositions
|
|
5
|
+
addCDButtons: AddCDPositions[]
|
|
6
|
+
endNode: Point & EdgeEndNodeType
|
|
7
|
+
startNode: Point & EdgeNodeType
|
|
8
|
+
handleAddCD: (position: AddCDPositions) => void
|
|
9
|
+
tooltipContent?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface HandleAddCD {
|
|
13
|
+
position: AddCDPositions
|
|
14
|
+
handleCDSelect: (
|
|
15
|
+
workflowId: number | string,
|
|
16
|
+
ciPipelineId: number | string,
|
|
17
|
+
parentPipelineType: string,
|
|
18
|
+
parentPipelineId: number | string,
|
|
19
|
+
isWebhookCD?: boolean,
|
|
20
|
+
childPipelineId?: number | string,
|
|
21
|
+
addType?: AddPipelineType,
|
|
22
|
+
) => void
|
|
23
|
+
startNode: EdgeNodeType
|
|
24
|
+
endNode: EdgeEndNodeType
|
|
25
|
+
workflowId: number | string
|
|
26
|
+
ciPipelineId: number | string
|
|
27
|
+
isWebhookCD: boolean
|
|
28
|
+
isParallelEdge: boolean
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface GetPipelineType {
|
|
32
|
+
isWebhookCD: boolean
|
|
33
|
+
startNode: EdgeNodeType
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface TooltipContentProps {
|
|
37
|
+
tooltipContent?: string
|
|
38
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AddCDPositions, AddPipelineType, PipelineType, WorkflowNodeType } from '../Types'
|
|
2
|
+
import { HandleAddCD, GetPipelineType } from './types'
|
|
3
|
+
|
|
4
|
+
const getPipelineType = ({ isWebhookCD, startNode }: GetPipelineType) => {
|
|
5
|
+
if (isWebhookCD) {
|
|
6
|
+
return PipelineType.WEBHOOK
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (startNode.type === WorkflowNodeType.CI) {
|
|
10
|
+
return PipelineType.CI_PIPELINE
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return PipelineType.CD_PIPELINE
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const handleAddCD = ({
|
|
17
|
+
position,
|
|
18
|
+
handleCDSelect,
|
|
19
|
+
startNode,
|
|
20
|
+
endNode,
|
|
21
|
+
workflowId,
|
|
22
|
+
ciPipelineId,
|
|
23
|
+
isWebhookCD,
|
|
24
|
+
isParallelEdge,
|
|
25
|
+
}: HandleAddCD) => {
|
|
26
|
+
if (!handleCDSelect) {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
const pipelineType = getPipelineType({ isWebhookCD, startNode })
|
|
30
|
+
const addPipelineType =
|
|
31
|
+
isParallelEdge && position === AddCDPositions.RIGHT ? AddPipelineType.PARALLEL : AddPipelineType.SEQUENTIAL
|
|
32
|
+
const endNodeId = !isParallelEdge && position === AddCDPositions.RIGHT ? endNode.id : null
|
|
33
|
+
|
|
34
|
+
handleCDSelect(workflowId, ciPipelineId, pipelineType, startNode.id, isWebhookCD, endNodeId, addPipelineType)
|
|
35
|
+
}
|
package/src/Common/Constants.ts
CHANGED
|
@@ -24,8 +24,7 @@ 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'
|
|
28
|
-
DEPLOYMENT_TEMPLATE_LIST: 'app/template/list'
|
|
27
|
+
CD_MATERIAL_GET: 'app/cd-pipeline'
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
export enum KEY_VALUE {
|
|
@@ -45,7 +45,7 @@ export const DeleteDialog: React.FC<DeleteDialogProps> & { Description?: React.F
|
|
|
45
45
|
type="button"
|
|
46
46
|
className="cta delete cta-cd-delete-modal ml-16"
|
|
47
47
|
onClick={handleDelete}
|
|
48
|
-
disabled={props.apiCallInProgress}
|
|
48
|
+
disabled={props.apiCallInProgress || props.disabled}
|
|
49
49
|
data-testid="dialog-delete"
|
|
50
50
|
>
|
|
51
51
|
{props.apiCallInProgress ? (
|
package/src/Common/Helper.tsx
CHANGED
|
@@ -7,8 +7,6 @@ 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'
|
|
12
10
|
|
|
13
11
|
toast.configure({
|
|
14
12
|
autoClose: 3000,
|
|
@@ -460,99 +458,3 @@ export const getUrlWithSearchParams = (url: string, params: Record<string | numb
|
|
|
460
458
|
* Custom exception logger function for logging errors to sentry
|
|
461
459
|
*/
|
|
462
460
|
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
|
@@ -293,6 +293,11 @@ export interface CDMaterialServiceQueryParams {
|
|
|
293
293
|
filter?: CDMaterialFilterQuery
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
+
export interface DownstreamNodesEnvironmentsType {
|
|
297
|
+
environmentId: number
|
|
298
|
+
environmentName: string
|
|
299
|
+
}
|
|
300
|
+
|
|
296
301
|
export interface CommonNodeAttr {
|
|
297
302
|
connectingCiPipelineId?: number
|
|
298
303
|
parents: string | number[] | string[]
|
|
@@ -354,6 +359,9 @@ export interface CommonNodeAttr {
|
|
|
354
359
|
}
|
|
355
360
|
appReleaseTagNames?: string[]
|
|
356
361
|
tagsEditable?: boolean
|
|
362
|
+
deploymentAppCreated?: boolean
|
|
363
|
+
isLast?: boolean
|
|
364
|
+
downstreamEnvironments?: DownstreamNodesEnvironmentsType[]
|
|
357
365
|
}
|
|
358
366
|
|
|
359
367
|
export enum DeploymentAppTypes {
|
|
@@ -624,72 +632,50 @@ export interface CiPipeline {
|
|
|
624
632
|
pipelineType?: string
|
|
625
633
|
}
|
|
626
634
|
|
|
627
|
-
export
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
635
|
+
export enum PipelineType {
|
|
636
|
+
CI_PIPELINE = 'CI_PIPELINE',
|
|
637
|
+
CD_PIPELINE = 'CD_PIPELINE',
|
|
638
|
+
WEBHOOK = 'WEBHOOK',
|
|
639
|
+
LINKED_CD = 'LINKED_CD',
|
|
632
640
|
}
|
|
633
641
|
|
|
634
|
-
export
|
|
635
|
-
|
|
642
|
+
export enum WorkflowNodeType {
|
|
643
|
+
GIT = 'GIT',
|
|
644
|
+
CI = 'CI',
|
|
645
|
+
WEBHOOK = 'WEBHOOK',
|
|
646
|
+
PRE_CD = 'PRECD',
|
|
647
|
+
CD = 'CD',
|
|
648
|
+
POST_CD = 'POSTCD',
|
|
636
649
|
}
|
|
637
650
|
|
|
638
|
-
export
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
children?: React.ReactNode
|
|
651
|
+
export enum AddCDPositions {
|
|
652
|
+
LEFT = 'left',
|
|
653
|
+
RIGHT = 'right',
|
|
642
654
|
}
|
|
643
655
|
|
|
644
|
-
export interface
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
height
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
-
}
|
|
656
|
+
export interface SelectedNode {
|
|
657
|
+
nodeType: WorkflowNodeType
|
|
658
|
+
id: string
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
export enum AddPipelineType {
|
|
662
|
+
SEQUENTIAL = 'SEQUENTIAL',
|
|
663
|
+
PARALLEL = 'PARALLEL',
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export interface Point {
|
|
667
|
+
x: number
|
|
668
|
+
y: number
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
export interface EdgeNodeType {
|
|
672
|
+
height: number
|
|
673
|
+
width: number
|
|
674
|
+
userApprovalConfig?: UserApprovalConfigType
|
|
675
|
+
type?: any
|
|
676
|
+
id?: number | string
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
export interface EdgeEndNodeType extends EdgeNodeType {
|
|
680
|
+
userApprovalConfig?: UserApprovalConfigType
|
|
681
|
+
}
|
package/src/Common/index.ts
CHANGED
|
@@ -42,5 +42,5 @@ export * from './Hooks'
|
|
|
42
42
|
export { AppStatus } from './AppStatus'
|
|
43
43
|
export * from './RJSF'
|
|
44
44
|
export * from './DevtronProgressing'
|
|
45
|
-
export
|
|
45
|
+
export * from './AddCDButton'
|
|
46
46
|
export * from './CustomInput'
|
|
@@ -1,78 +0,0 @@
|
|
|
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
|