@devtron-labs/devtron-fe-common-lib 0.0.45-beta-27 → 0.0.46

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devtron-labs/devtron-fe-common-lib",
3
- "version": "0.0.45-beta-27",
3
+ "version": "0.0.46",
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-node-resolve": "^15.0.1",
23
+ "@rollup/plugin-commonjs": "24.0.1",
24
24
  "@rollup/plugin-image": "3.0.1",
25
- "rollup-plugin-peer-deps-external": "^2.2.4",
26
- "rollup-plugin-postcss": "^4.0.2",
27
- "rollup-plugin-typescript2": "^0.34.1",
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
- "@sentry/browser": "^7.31.1"
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",
@@ -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
+ }
@@ -0,0 +1,2 @@
1
+ export * from './CustomInput'
2
+ export * from './Types'
@@ -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 || props.disabled}
48
+ disabled={props.apiCallInProgress}
49
49
  data-testid="dialog-delete"
50
50
  >
51
51
  {props.apiCallInProgress ? (
@@ -11,7 +11,6 @@ export interface DeleteDialogProps {
11
11
  dataTestId?: string
12
12
  buttonPrimaryText?: string
13
13
  shouldStopPropagation?: boolean
14
- disabled?: boolean
15
14
  }
16
15
 
17
16
  export interface ForceDeleteDialogType {
@@ -3,7 +3,6 @@ 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'
@@ -277,64 +276,6 @@ export function useForm(stateSchema, validationSchema = {}, callback) {
277
276
  return { state, disable, handleOnChange, handleOnSubmit }
278
277
  }
279
278
 
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
279
  export function handleUTCTime(ts: string, isRelativeTime = false) {
339
280
  let timestamp = ''
340
281
  try {
@@ -293,11 +293,6 @@ export interface CDMaterialServiceQueryParams {
293
293
  filter?: CDMaterialFilterQuery
294
294
  }
295
295
 
296
- export interface DownstreamNodesEnvironmentsType {
297
- environmentId: number
298
- environmentName: string
299
- }
300
-
301
296
  export interface CommonNodeAttr {
302
297
  connectingCiPipelineId?: number
303
298
  parents: string | number[] | string[]
@@ -359,9 +354,6 @@ export interface CommonNodeAttr {
359
354
  }
360
355
  appReleaseTagNames?: string[]
361
356
  tagsEditable?: boolean
362
- deploymentAppCreated?: boolean
363
- isLast?: boolean
364
- downstreamEnvironments?: DownstreamNodesEnvironmentsType[]
365
357
  }
366
358
 
367
359
  export enum DeploymentAppTypes {
@@ -630,52 +622,4 @@ export interface CiPipeline {
630
622
  }
631
623
  isOffendingMandatoryPlugin?: boolean
632
624
  pipelineType?: string
633
- }
634
-
635
- export enum PipelineType {
636
- CI_PIPELINE = 'CI_PIPELINE',
637
- CD_PIPELINE = 'CD_PIPELINE',
638
- WEBHOOK = 'WEBHOOK',
639
- LINKED_CD = 'LINKED_CD',
640
- }
641
-
642
- export enum WorkflowNodeType {
643
- GIT = 'GIT',
644
- CI = 'CI',
645
- WEBHOOK = 'WEBHOOK',
646
- PRE_CD = 'PRECD',
647
- CD = 'CD',
648
- POST_CD = 'POSTCD',
649
- }
650
-
651
- export enum AddCDPositions {
652
- LEFT = 'left',
653
- RIGHT = 'right',
654
- }
655
-
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
- }
625
+ }
@@ -42,4 +42,4 @@ export * from './Hooks'
42
42
  export { AppStatus } from './AppStatus'
43
43
  export * from './RJSF'
44
44
  export * from './DevtronProgressing'
45
- export * from './AddCDButton'
45
+ export * from './CustomInput'
@@ -1,3 +0,0 @@
1
- /// <reference types="react" />
2
- import { AddCDButtonProps } from './types';
3
- export default function AddCDButton({ position, addCDButtons, endNode, startNode, handleAddCD, tooltipContent, }: Readonly<AddCDButtonProps>): JSX.Element;
@@ -1,2 +0,0 @@
1
- export { default as AddCDButton } from './AddCDButton';
2
- export { handleAddCD } from './utils';
@@ -1,26 +0,0 @@
1
- import { AddCDPositions, AddPipelineType, EdgeEndNodeType, EdgeNodeType, Point } from '../Types';
2
- export interface AddCDButtonProps {
3
- position: AddCDPositions;
4
- addCDButtons: AddCDPositions[];
5
- endNode: Point & EdgeEndNodeType;
6
- startNode: Point & EdgeNodeType;
7
- handleAddCD: (position: AddCDPositions) => void;
8
- tooltipContent?: string;
9
- }
10
- export interface HandleAddCD {
11
- position: AddCDPositions;
12
- handleCDSelect: (workflowId: number | string, ciPipelineId: number | string, parentPipelineType: string, parentPipelineId: number | string, isWebhookCD?: boolean, childPipelineId?: number | string, addType?: AddPipelineType) => void;
13
- startNode: EdgeNodeType;
14
- endNode: EdgeEndNodeType;
15
- workflowId: number | string;
16
- ciPipelineId: number | string;
17
- isWebhookCD: boolean;
18
- isParallelEdge: boolean;
19
- }
20
- export interface GetPipelineType {
21
- isWebhookCD: boolean;
22
- startNode: EdgeNodeType;
23
- }
24
- export interface TooltipContentProps {
25
- tooltipContent?: string;
26
- }
@@ -1,2 +0,0 @@
1
- import { HandleAddCD } from './types';
2
- export declare const handleAddCD: ({ position, handleCDSelect, startNode, endNode, workflowId, ciPipelineId, isWebhookCD, isParallelEdge, }: HandleAddCD) => void;
@@ -1,68 +0,0 @@
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
- }
@@ -1,2 +0,0 @@
1
- export { default as AddCDButton } from './AddCDButton'
2
- export { handleAddCD } from './utils'
@@ -1,38 +0,0 @@
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
- }
@@ -1,35 +0,0 @@
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
- }