@devtron-labs/devtron-fe-common-lib 0.0.61-beta-8 → 0.0.61-beta-10

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.
Files changed (97) hide show
  1. package/dist/Common/Constants.d.ts +1 -14
  2. package/dist/Common/DraggableWrapper/types.d.ts +1 -4
  3. package/dist/Common/Helper.d.ts +4 -1
  4. package/dist/Common/Hooks/index.d.ts +0 -1
  5. package/dist/Common/Types.d.ts +1 -13
  6. package/dist/Common/index.d.ts +0 -1
  7. package/dist/Pages/GlobalConfigurations/BuildInfra/BuildInfraConfigForm.d.ts +4 -0
  8. package/dist/Pages/GlobalConfigurations/BuildInfra/BuildInfraDescriptionField.d.ts +4 -0
  9. package/dist/Pages/GlobalConfigurations/BuildInfra/BuildInfraFormAction.d.ts +7 -0
  10. package/dist/Pages/GlobalConfigurations/BuildInfra/BuildInfraFormItem.d.ts +4 -0
  11. package/dist/Pages/GlobalConfigurations/BuildInfra/BuildInfraProfileNameField.d.ts +4 -0
  12. package/dist/Pages/GlobalConfigurations/BuildInfra/Descriptor.d.ts +4 -0
  13. package/dist/Pages/GlobalConfigurations/BuildInfra/Footer.d.ts +4 -0
  14. package/dist/Pages/GlobalConfigurations/BuildInfra/constants.d.ts +50 -0
  15. package/dist/Pages/GlobalConfigurations/BuildInfra/index.d.ts +7 -0
  16. package/dist/Pages/GlobalConfigurations/BuildInfra/services.d.ts +6 -0
  17. package/dist/Pages/GlobalConfigurations/BuildInfra/types.d.ts +286 -0
  18. package/dist/Pages/GlobalConfigurations/BuildInfra/utils.d.ts +12 -0
  19. package/dist/Pages/GlobalConfigurations/index.d.ts +1 -1
  20. package/dist/Shared/Components/APIResponseHandler/APIResponseHandler.d.ts +4 -0
  21. package/dist/Shared/Components/APIResponseHandler/constants.d.ts +4 -0
  22. package/dist/Shared/Components/APIResponseHandler/index.d.ts +2 -0
  23. package/dist/Shared/Components/APIResponseHandler/types.d.ts +37 -0
  24. package/dist/Shared/Components/BulkSelection/constants.d.ts +1 -0
  25. package/dist/Shared/Components/BulkSelection/types.d.ts +0 -2
  26. package/dist/Shared/Components/ReactSelect/index.d.ts +1 -0
  27. package/dist/Shared/Components/ReactSelect/utils.d.ts +12 -0
  28. package/dist/Shared/Components/index.d.ts +2 -0
  29. package/dist/Shared/Helpers.d.ts +16 -0
  30. package/dist/Shared/index.d.ts +2 -0
  31. package/dist/Shared/validations.d.ts +8 -0
  32. package/dist/index.js +1193 -386
  33. package/package.json +1 -1
  34. package/src/Assets/Icon/ic-cpu.svg +4 -0
  35. package/src/Assets/Icon/ic-memory.svg +3 -0
  36. package/src/Assets/Icon/ic-timer.svg +3 -0
  37. package/src/Common/BreadCrumb/Types.ts +0 -1
  38. package/src/Common/Checkbox.tsx +1 -0
  39. package/src/Common/Constants.ts +3 -18
  40. package/src/Common/CustomInput/CustomInput.tsx +2 -1
  41. package/src/Common/DraggableWrapper/DraggableWrapper.tsx +3 -1
  42. package/src/Common/DraggableWrapper/types.ts +1 -4
  43. package/src/Common/Helper.tsx +31 -24
  44. package/src/Common/Hooks/index.ts +0 -1
  45. package/src/Common/RJSF/utils.ts +2 -0
  46. package/src/Common/SearchBar/searchBar.scss +1 -1
  47. package/src/Common/Types.ts +1 -13
  48. package/src/Common/index.ts +0 -1
  49. package/src/Pages/GlobalConfigurations/BuildInfra/BuildInfraConfigForm.tsx +128 -0
  50. package/src/Pages/GlobalConfigurations/BuildInfra/BuildInfraDescriptionField.tsx +44 -0
  51. package/src/Pages/GlobalConfigurations/BuildInfra/BuildInfraFormAction.tsx +106 -0
  52. package/src/Pages/GlobalConfigurations/BuildInfra/BuildInfraFormItem.tsx +55 -0
  53. package/src/Pages/GlobalConfigurations/BuildInfra/BuildInfraProfileNameField.tsx +32 -0
  54. package/src/Pages/GlobalConfigurations/BuildInfra/Descriptor.tsx +45 -0
  55. package/src/Pages/GlobalConfigurations/BuildInfra/Footer.tsx +56 -0
  56. package/src/Pages/GlobalConfigurations/BuildInfra/Readme.md +4 -0
  57. package/src/Pages/GlobalConfigurations/BuildInfra/constants.tsx +139 -0
  58. package/src/Pages/GlobalConfigurations/BuildInfra/index.ts +7 -0
  59. package/src/Pages/GlobalConfigurations/BuildInfra/services.tsx +167 -0
  60. package/src/Pages/GlobalConfigurations/BuildInfra/types.tsx +339 -0
  61. package/src/Pages/GlobalConfigurations/BuildInfra/utils.tsx +507 -0
  62. package/src/Pages/GlobalConfigurations/index.ts +1 -1
  63. package/src/Shared/Components/APIResponseHandler/APIResponseHandler.tsx +41 -0
  64. package/src/Shared/Components/APIResponseHandler/constants.tsx +5 -0
  65. package/src/Shared/Components/APIResponseHandler/index.ts +2 -0
  66. package/src/Shared/Components/APIResponseHandler/types.tsx +39 -0
  67. package/src/Shared/Components/BulkSelection/BulkSelection.tsx +2 -2
  68. package/src/Shared/Components/BulkSelection/BulkSelectionDropdownItems.tsx +3 -1
  69. package/src/Shared/Components/BulkSelection/BulkSelectionProvider.tsx +17 -17
  70. package/src/Shared/Components/BulkSelection/constants.tsx +1 -0
  71. package/src/Shared/Components/BulkSelection/types.tsx +0 -2
  72. package/src/Shared/Components/ReactSelect/index.ts +1 -0
  73. package/src/Shared/Components/ReactSelect/utils.tsx +97 -0
  74. package/src/Shared/Components/index.ts +2 -0
  75. package/src/Shared/Helpers.tsx +29 -0
  76. package/src/Shared/index.ts +2 -0
  77. package/src/Shared/validations.tsx +130 -0
  78. package/dist/Common/Hooks/useUrlFilters/constants.d.ts +0 -8
  79. package/dist/Common/Hooks/useUrlFilters/index.d.ts +0 -2
  80. package/dist/Common/Hooks/useUrlFilters/types.d.ts +0 -19
  81. package/dist/Common/Hooks/useUrlFilters/useUrlFilters.d.ts +0 -20
  82. package/dist/Common/SortableTableHeaderCell/SortableTableHeaderCell.d.ts +0 -18
  83. package/dist/Common/SortableTableHeaderCell/index.d.ts +0 -2
  84. package/dist/Common/SortableTableHeaderCell/types.d.ts +0 -25
  85. package/dist/Pages/GlobalConfigurations/Authorization/constants.d.ts +0 -15
  86. package/dist/Pages/GlobalConfigurations/Authorization/index.d.ts +0 -1
  87. package/src/Assets/Icon/ic-arrow-up-down.svg +0 -3
  88. package/src/Assets/Icon/ic-sort-arrow-down.svg +0 -3
  89. package/src/Common/Hooks/useUrlFilters/constants.ts +0 -9
  90. package/src/Common/Hooks/useUrlFilters/index.ts +0 -2
  91. package/src/Common/Hooks/useUrlFilters/types.ts +0 -21
  92. package/src/Common/Hooks/useUrlFilters/useUrlFilters.ts +0 -121
  93. package/src/Common/SortableTableHeaderCell/SortableTableHeaderCell.tsx +0 -44
  94. package/src/Common/SortableTableHeaderCell/index.ts +0 -2
  95. package/src/Common/SortableTableHeaderCell/types.ts +0 -26
  96. package/src/Pages/GlobalConfigurations/Authorization/constants.ts +0 -16
  97. package/src/Pages/GlobalConfigurations/Authorization/index.ts +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devtron-labs/devtron-fe-common-lib",
3
- "version": "0.0.61-beta-8",
3
+ "version": "0.0.61-beta-10",
4
4
  "description": "Supporting common component library",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
2
+ <path d="M12.5 5.625H7.5M12.5 8.125H7.5M15.625 3.125V16.875C15.625 17.2202 15.3452 17.5 15 17.5H5C4.65482 17.5 4.375 17.2202 4.375 16.875V3.125C4.375 2.77982 4.65482 2.5 5 2.5H15C15.3452 2.5 15.625 2.77982 15.625 3.125Z" stroke="#596168" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M10 15C10.5178 15 10.9375 14.5803 10.9375 14.0625C10.9375 13.5447 10.5178 13.125 10 13.125C9.48223 13.125 9.0625 13.5447 9.0625 14.0625C9.0625 14.5803 9.48223 15 10 15Z" fill="#596168"/>
4
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
2
+ <path d="M16.25 8.125H18.125M16.25 11.875H18.125M1.875 8.125H3.75M1.875 11.875H3.75M11.875 16.25V18.125M8.125 16.25V18.125M11.875 1.875V3.75M8.125 1.875V3.75M7.8125 7.8125H12.1875V12.1875H7.8125V7.8125ZM4.375 3.75H15.625C15.9702 3.75 16.25 4.02982 16.25 4.375V15.625C16.25 15.9702 15.9702 16.25 15.625 16.25H4.375C4.02982 16.25 3.75 15.9702 3.75 15.625V4.375C3.75 4.02982 4.02982 3.75 4.375 3.75Z" stroke="#596168" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
2
+ <path d="M10 11.0415L13.0936 7.94791M8.125 1.6665H11.875M16.875 11.0415C16.875 14.8385 13.797 17.9165 10 17.9165C6.20304 17.9165 3.125 14.8385 3.125 11.0415C3.125 7.24455 6.20304 4.1665 10 4.1665C13.797 4.1665 16.875 7.24455 16.875 11.0415Z" stroke="#596168" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
@@ -1,4 +1,3 @@
1
-
2
1
  export interface Breadcrumb {
3
2
  to: string
4
3
  name: string
@@ -10,6 +10,7 @@ Valid States of Checkbox:
10
10
  5. disabled: false, checked: true, value: INTERMIDIATE
11
11
  6. disabled: false, checked: true, value: CHECKED
12
12
  */
13
+ // TODO: Associate label with input element
13
14
  export class Checkbox extends Component<CheckboxProps> {
14
15
  render() {
15
16
  let rootClassName = `${this.props.rootClassName ? this.props.rootClassName : ''}`
@@ -25,7 +25,8 @@ export const ROUTES = {
25
25
  USER_CHECK_ROLE: 'user/check/roles',
26
26
  IMAGE_TAGGING:'app/image-tagging',
27
27
  CD_MATERIAL_GET: 'app/cd-pipeline',
28
- DEPLOYMENT_TEMPLATE_LIST: 'app/template/list'
28
+ DEPLOYMENT_TEMPLATE_LIST: 'app/template/list',
29
+ INFRA_CONFIG_PROFILE: 'infra-config/profile',
29
30
  }
30
31
 
31
32
  export enum KEY_VALUE {
@@ -251,20 +252,4 @@ export const MAX_Z_INDEX = 2147483647
251
252
  export const SELECTED_APPROVAL_TAB_STATE = {
252
253
  APPROVAL: 'approval',
253
254
  PENDING: 'pending',
254
- }
255
-
256
- export enum SortingOrder {
257
- /**
258
- * Ascending order
259
- */
260
- ASC = 'ASC',
261
- /**
262
- * Descending order
263
- */
264
- DESC = 'DESC',
265
- }
266
-
267
- /**
268
- * Base page size for pagination
269
- */
270
- export const DEFAULT_BASE_PAGE_SIZE = 20
255
+ }
@@ -2,6 +2,7 @@ import { CustomInputProps } from './Types'
2
2
  import { ReactComponent as Info } from '../../Assets/Icon/ic-info-filled.svg'
3
3
  import { ReactComponent as ErrorIcon } from '../../Assets/Icon/ic-warning.svg'
4
4
 
5
+ // TODO: label association with input
5
6
  export function CustomInput({
6
7
  name,
7
8
  value,
@@ -13,7 +14,7 @@ export function CustomInput({
13
14
  disabled = false,
14
15
  labelClassName = '',
15
16
  placeholder = '',
16
- tabIndex = 1,
17
+ tabIndex = 0,
17
18
  dataTestid = '',
18
19
  isRequiredField = false,
19
20
  autoFocus = false,
@@ -94,8 +94,9 @@ export default function DraggableWrapper({
94
94
  }
95
95
 
96
96
  return (
97
+ // Since we are using position fixed so we need to disable click on the div so that it does not interfere with the click of other elements
97
98
  <div
98
- className="dc__position-fixed"
99
+ className="dc__position-fixed dc__disable-click"
99
100
  style={{
100
101
  zIndex,
101
102
  }}
@@ -106,6 +107,7 @@ export default function DraggableWrapper({
106
107
  {...childDivProps}
107
108
  style={{
108
109
  zIndex,
110
+ pointerEvents: 'auto',
109
111
  }}
110
112
  >
111
113
  {children}
@@ -8,10 +8,7 @@ export enum DraggablePositionVariant {
8
8
 
9
9
  export interface DraggableWrapperProps {
10
10
  children: ReactNode
11
- /**
12
- * Support for passing the direct value or calc functions as well
13
- */
14
- zIndex?: number | string
11
+ zIndex?: number
15
12
  positionVariant?: DraggablePositionVariant
16
13
  /**
17
14
  * dragSelector (class - (append with .), id, etc) will be used to identify the grabbable button that will grab the div to drag
@@ -447,16 +447,9 @@ export const processDeployedTime = (lastDeployed, isArgoInstalled) => {
447
447
  */
448
448
  export const getUrlWithSearchParams = (url: string, params: Record<string | number, any>) => {
449
449
  const searchParams = new URLSearchParams()
450
- // TODO: Common out
451
450
  Object.keys(params).forEach((key) => {
452
451
  if (params[key]) {
453
- if (Array.isArray(params[key])) {
454
- params[key].forEach((val) => {
455
- searchParams.append(key, val)
456
- })
457
- } else {
458
- searchParams.set(key, params[key])
459
- }
452
+ searchParams.append(key, params[key])
460
453
  }
461
454
  })
462
455
  const queryString = searchParams.toString()
@@ -506,18 +499,27 @@ export const getFilteredChartVersions = (charts, selectedChartType) => {
506
499
  chartRefId: item.chartRefId,
507
500
  }))
508
501
  }
509
- function removeEmptyObjectKeysAndNullValues(obj) {
510
- // It recursively removes empty object keys and array values that are null
502
+
503
+ function removeEmptyObjectKeysAndNullValues(obj, originaljsonCopy) {
504
+ // It recursively removes empty object keys and empty array keys
511
505
  for (let key in obj) {
512
506
  if (Array.isArray(obj[key])) {
513
- if (obj[key].length === 0) continue
514
- obj[key] = obj[key].filter((item) => item !== null)
515
507
  // Check if the array is empty
516
- if (obj[key].length === 0) {
517
- delete obj[key] // Delete the key if the array is empty
508
+ if (obj[key].length !== 0) {
509
+ obj[key].forEach((element, index) => {
510
+ if (element === null || (typeof element === 'object' && Object.keys(element).length === 0))
511
+ obj[key].splice(index, 1)
512
+ else removeEmptyObjectKeysAndNullValues(element, originaljsonCopy[key][index])
513
+ })
514
+ }
515
+ if (obj[key].length === 0 && originaljsonCopy[key].length !== 0) {
516
+ delete obj[key]
518
517
  }
519
518
  } else if (obj[key] && typeof obj[key] === 'object') {
520
- if (removeEmptyObjectKeysAndNullValues(obj[key])) {
519
+ if (
520
+ removeEmptyObjectKeysAndNullValues(obj[key], originaljsonCopy[key]) &&
521
+ Object.keys(originaljsonCopy[key]).length !== 0
522
+ ) {
521
523
  delete obj[key]
522
524
  }
523
525
  } else if (obj[key] === undefined) {
@@ -527,20 +529,25 @@ function removeEmptyObjectKeysAndNullValues(obj) {
527
529
  return Object.keys(obj).length === 0
528
530
  }
529
531
 
530
- export function getUnlockedJSON(json, jsonPathArray) {
532
+ export function getUnlockedJSON(json, jsonPathArray, removeParentKeysAndEmptyArrays = false) {
533
+ if (!jsonPathArray.length) return { newDocument: json, removedPatches: [] }
534
+
531
535
  const jsonCopy = JSON.parse(JSON.stringify(json))
536
+ const originaljsonCopy = JSON.parse(JSON.stringify(json))
537
+ let removedPatches = []
532
538
  let patches = jsonPathArray.flatMap((jsonPath) => {
533
539
  const pathsToRemove = JSONPath({ path: jsonPath, json: jsonCopy, resultType: 'all' })
534
- return pathsToRemove.map((result) =>
535
- Array.isArray(result.parent)
536
- ? { op: 'replace', path: result.pointer, value: null }
537
- : { op: 'remove', path: result.pointer },
538
- )
540
+ //reversing patches to handle correct array index deletion
541
+ pathsToRemove.reverse()
542
+ return pathsToRemove.map((result) => {
543
+ //storing removed patches to have functionality of undo
544
+ removedPatches.push({ op: 'add', path: result.pointer, value: result.value })
545
+ return { op: 'remove', path: result.pointer }
546
+ })
539
547
  })
540
548
  let newDocument = jsonpatch.applyPatch(jsonCopy, patches).newDocument
541
-
542
- removeEmptyObjectKeysAndNullValues(newDocument)
543
- return newDocument
549
+ if (removeParentKeysAndEmptyArrays) removeEmptyObjectKeysAndNullValues(newDocument, originaljsonCopy)
550
+ return { newDocument, removedPatches: removedPatches.reverse() }
544
551
  }
545
552
 
546
553
  export function getLockedJSON(json, jsonPathArray: string[]) {
@@ -1,4 +1,3 @@
1
1
  export { useSuperAdmin } from './UseSuperAdmin/UseSuperAdmin'
2
2
  export { useClickOutside } from './UseClickOutside/UseClickOutside'
3
3
  export { useWindowSize } from './UseWindowSize/UseWindowSize'
4
- export * from './useUrlFilters'
@@ -19,6 +19,7 @@ export const getCommonSelectStyle = (styleOverrides = {}) => {
19
19
  ...base,
20
20
  paddingTop: 0,
21
21
  paddingBottom: 0,
22
+ cursor: 'pointer',
22
23
  }),
23
24
  control: (base, state) => ({
24
25
  ...base,
@@ -33,6 +34,7 @@ export const getCommonSelectStyle = (styleOverrides = {}) => {
33
34
  color: 'var(--N900)',
34
35
  backgroundColor: state.isFocused ? 'var(--N100)' : 'white',
35
36
  padding: '10px 12px',
37
+ cursor: 'pointer',
36
38
  }),
37
39
  dropdownIndicator: (base, state) => ({
38
40
  ...base,
@@ -3,7 +3,7 @@
3
3
  &:focus,
4
4
  &:focus-within {
5
5
  outline: none;
6
- border: solid 1px var(--B500);
6
+ border: solid 1px var(--B500) !important;
7
7
  }
8
8
 
9
9
  &__input {
@@ -1,7 +1,7 @@
1
1
  import React, { ReactNode, CSSProperties } from 'react'
2
2
  import { Placement } from 'tippy.js'
3
3
  import { ImageComment, ReleaseTag } from './ImageTags.Types'
4
- import { DockerConfigOverrideType, SortingOrder, TaskErrorObj } from '.'
4
+ import { DockerConfigOverrideType, TaskErrorObj } from '.'
5
5
 
6
6
  /**
7
7
  * Generic response type object with support for overriding the result type
@@ -764,15 +764,3 @@ export interface EdgeNodeType {
764
764
  export interface EdgeEndNodeType extends EdgeNodeType {
765
765
  userApprovalConfig?: UserApprovalConfigType
766
766
  }
767
-
768
- /**
769
- * Search params for sorting configuration
770
- *
771
- * Note: Either both sortOrder and sortBy are required or none
772
- */
773
- export type SortingParams<T = string> =
774
- | {
775
- sortOrder: SortingOrder
776
- sortBy: T
777
- }
778
- | { sortOrder?: never; sortBy?: never }
@@ -27,7 +27,6 @@ export * from './Checkbox'
27
27
  export { default as EmptyState } from './EmptyState/EmptyState'
28
28
  export { default as GenericEmptyState } from './EmptyState/GenericEmptyState'
29
29
  export * from './SearchBar'
30
- export * from './SortableTableHeaderCell'
31
30
  export { default as Toggle } from './Toggle/Toggle'
32
31
  export { default as ScanVulnerabilitiesTable } from './Security/ScanVulnerabilitiesTable'
33
32
  export { default as StyledRadioGroup } from './RadioGroup/RadioGroup'
@@ -0,0 +1,128 @@
1
+ import { FunctionComponent } from 'react'
2
+ import { Progressing } from '../../../Common'
3
+ import BuildInfraFormAction from './BuildInfraFormAction'
4
+ import BuildInfraFormItem from './BuildInfraFormItem'
5
+ import BuildInfraProfileDescriptionField from './BuildInfraDescriptionField'
6
+ import BuildInfraProfileNameField from './BuildInfraProfileNameField'
7
+ import { BUILD_INFRA_FORM_FIELDS, BUILD_INFRA_TEXT } from './constants'
8
+ import { BuildInfraActionType, BuildInfraConfigFormProps, InheritingHeaderProps } from './types'
9
+
10
+ const InheritingHeader = ({
11
+ defaultHeading,
12
+ inheritingData,
13
+ isInheriting,
14
+ isDefaultProfile,
15
+ }: InheritingHeaderProps) => {
16
+ const inheritingDataString = inheritingData.map((data) => `${data.value} ${data.unit ?? ''}`).join(' - ')
17
+
18
+ if (isDefaultProfile || !isInheriting) {
19
+ // For typing issues
20
+ // eslint-disable-next-line react/jsx-no-useless-fragment
21
+ return <>{defaultHeading}</>
22
+ }
23
+
24
+ return (
25
+ <div className="flexbox dc__align-items-center dc__content-space w-100">
26
+ {defaultHeading}
27
+
28
+ <div className="flexbox dc__content-space w-100">
29
+ <span className="m-0 pt-0 pb-0 pl-4 pr-4 fs-13 lh-20 fw-4 cn-9 dc__ellipsis-right dc__word-break-all flex-grow-1">
30
+ {inheritingDataString}
31
+ </span>
32
+
33
+ {/* TODO: Add ellipsis */}
34
+ <p className="m-0 cn-7 fs-13 fw-4 lh-20 dc__no-shrink">
35
+ {BUILD_INFRA_TEXT.INHERITING_HEADING_DESCRIPTION}
36
+ </p>
37
+ </div>
38
+ </div>
39
+ )
40
+ }
41
+
42
+ const BuildInfraConfigForm: FunctionComponent<BuildInfraConfigFormProps> = ({
43
+ profileInput,
44
+ profileInputErrors,
45
+ handleProfileInputChange,
46
+ isDefaultProfile,
47
+ unitsMap,
48
+ configurationContainerLabel,
49
+ }) => {
50
+ const currentConfigurations = profileInput?.configurations
51
+
52
+ // will get the desired configuration from the currentConfigurations and then check if it is active or not
53
+ const isInheritingProfileValues = (actions: BuildInfraActionType[]) =>
54
+ actions.some((action) => !currentConfigurations[action.actionType].active)
55
+
56
+ // Had to show loader for an instance due to batching of state updates not working as expected :/
57
+ if (!currentConfigurations) {
58
+ return <Progressing pageLoader />
59
+ }
60
+
61
+ return (
62
+ <div className="flexbox-col dc__mxw-920 dc__gap-16">
63
+ {!isDefaultProfile && (
64
+ <div className="flexbox-col dc__gap-12">
65
+ <BuildInfraProfileNameField
66
+ handleProfileInputChange={handleProfileInputChange}
67
+ currentValue={profileInput.name}
68
+ error={profileInputErrors.name}
69
+ />
70
+
71
+ <BuildInfraProfileDescriptionField
72
+ handleProfileInputChange={handleProfileInputChange}
73
+ currentValue={profileInput.description}
74
+ error={profileInputErrors.description}
75
+ />
76
+ </div>
77
+ )}
78
+
79
+ <div className="flexbox-col dc__gap-12">
80
+ {configurationContainerLabel}
81
+
82
+ <div className="w-100 flexbox-col dc__gap-16 br-4 dc__border-n1 p-16">
83
+ {BUILD_INFRA_FORM_FIELDS.map((field, index) => (
84
+ <BuildInfraFormItem
85
+ key={field.locator}
86
+ marker={field.marker}
87
+ heading={
88
+ <InheritingHeader
89
+ defaultHeading={field.heading}
90
+ inheritingData={field.actions.map(
91
+ (action) => currentConfigurations[action.actionType],
92
+ )}
93
+ isInheriting={isInheritingProfileValues(field.actions)}
94
+ isDefaultProfile={isDefaultProfile}
95
+ />
96
+ }
97
+ showDivider={index !== BUILD_INFRA_FORM_FIELDS.length - 1}
98
+ isInheriting={isInheritingProfileValues(field.actions)}
99
+ handleProfileInputChange={handleProfileInputChange}
100
+ locator={field.locator}
101
+ isDefaultProfile={isDefaultProfile}
102
+ >
103
+ <div className="w-50 flexbox dc__gap-12 w-100 dc__align-start">
104
+ {field.actions.map((action) => (
105
+ <BuildInfraFormAction
106
+ key={action.actionType}
107
+ actionType={action.actionType}
108
+ label={action.label}
109
+ placeholder={action.placeholder}
110
+ error={profileInputErrors[action.actionType]}
111
+ // Assumption is for default profiles all input fields are required
112
+ isRequired
113
+ profileUnitsMap={unitsMap[action.actionType]}
114
+ handleProfileInputChange={handleProfileInputChange}
115
+ currentUnitName={currentConfigurations[action.actionType].unit}
116
+ currentValue={currentConfigurations[action.actionType].value}
117
+ />
118
+ ))}
119
+ </div>
120
+ </BuildInfraFormItem>
121
+ ))}
122
+ </div>
123
+ </div>
124
+ </div>
125
+ )
126
+ }
127
+
128
+ export default BuildInfraConfigForm
@@ -0,0 +1,44 @@
1
+ import { FormEvent, FunctionComponent } from 'react'
2
+ import { ReactComponent as ErrorIcon } from '../../../Assets/Icon/ic-warning.svg'
3
+ import { BuildInfraInputFieldComponentProps, BuildInfraMetaConfigTypes } from './types'
4
+ import { BUILD_INFRA_TEXT } from './constants'
5
+
6
+ const BuildInfraProfileDescriptionField: FunctionComponent<BuildInfraInputFieldComponentProps> = ({
7
+ handleProfileInputChange,
8
+ currentValue,
9
+ error,
10
+ }) => {
11
+ const handleChange = (e: FormEvent<HTMLTextAreaElement>) => {
12
+ handleProfileInputChange({
13
+ action: BuildInfraMetaConfigTypes.DESCRIPTION,
14
+ data: { value: e.currentTarget.value },
15
+ })
16
+ }
17
+
18
+ return (
19
+ <div className="flexbox-col dc__gap-4 w-100 dc__align-start">
20
+ <label htmlFor="build-infra-profile-description" className="m-0 fs-13 fw-4 lh-20 cn-7">
21
+ {BUILD_INFRA_TEXT.DESCRIPTION_LABEL}
22
+ </label>
23
+
24
+ <textarea
25
+ data-testid="build-infra-profile-description"
26
+ name="profile-description"
27
+ className="form__textarea mxh-140 dc__hover-border-n300"
28
+ id="build-infra-profile-description"
29
+ placeholder={BUILD_INFRA_TEXT.DESCRIPTION_PLACEHOLDER}
30
+ value={currentValue}
31
+ onChange={handleChange}
32
+ />
33
+
34
+ {error && (
35
+ <div className="form__error">
36
+ <ErrorIcon className="form__icon form__icon--error" />
37
+ {error}
38
+ </div>
39
+ )}
40
+ </div>
41
+ )
42
+ }
43
+
44
+ export default BuildInfraProfileDescriptionField
@@ -0,0 +1,106 @@
1
+ import { FormEvent, FunctionComponent, useMemo } from 'react'
2
+ import ReactSelect from 'react-select'
3
+ import { BuildInfraFormActionProps } from './types'
4
+ import { OptionType } from '../../../Common'
5
+ import { unitSelectorStyles } from './utils'
6
+ import { BUILD_INFRA_INPUT_CONSTRAINTS } from './constants'
7
+ import { ReactComponent as ErrorIcon } from '../../../Assets/Icon/ic-warning.svg'
8
+
9
+ /**
10
+ * In case need arise for variants break this CustomInput and Select as a separate component
11
+ */
12
+ const BuildInfraFormAction: FunctionComponent<BuildInfraFormActionProps> = ({
13
+ actionType,
14
+ label,
15
+ placeholder,
16
+ error,
17
+ isRequired,
18
+ profileUnitsMap,
19
+ handleProfileInputChange,
20
+ currentUnitName,
21
+ currentValue,
22
+ }) => {
23
+ const handleUnitChange = (selectedUnit: OptionType) => {
24
+ const data = {
25
+ unit: selectedUnit.label,
26
+ value: currentValue,
27
+ }
28
+ handleProfileInputChange({ action: actionType, data })
29
+ }
30
+
31
+ const handleInputChange = (e: FormEvent<HTMLInputElement>) => {
32
+ const data = {
33
+ unit: currentUnitName,
34
+ value: e.currentTarget.value,
35
+ }
36
+ handleProfileInputChange({ action: actionType, data })
37
+ }
38
+
39
+ const unitOptions = useMemo(() => {
40
+ const units =
41
+ Object.values(profileUnitsMap)?.map((unit) => ({
42
+ label: unit.name,
43
+ value: String(unit.conversionFactor),
44
+ })) ?? []
45
+ return units.sort((a, b) => Number(a.value) - Number(b.value))
46
+ }, [profileUnitsMap])
47
+
48
+ const currentUnit = useMemo(
49
+ () => unitOptions.find((unit) => unit.label === currentUnitName),
50
+ [unitOptions, currentUnitName],
51
+ )
52
+
53
+ return (
54
+ <div className="flexbox-col dc__gap-4 dc__mxw-420 w-100 dc__align-start">
55
+ <label
56
+ htmlFor={`${actionType}-input`}
57
+ className={`fs-13 fw-4 lh-20 cn-7 ${isRequired ? 'dc__required-field' : ''}`}
58
+ >
59
+ {label}
60
+ </label>
61
+ <div className="w-100 flexbox dc__align-items-center">
62
+ <div className="flex-grow-1">
63
+ <input
64
+ data-testid={`${actionType}-input-field`}
65
+ name={actionType}
66
+ type="number"
67
+ step={BUILD_INFRA_INPUT_CONSTRAINTS.STEP}
68
+ min={BUILD_INFRA_INPUT_CONSTRAINTS.MIN}
69
+ className="form__input dc__no-right-border dc__no-right-radius"
70
+ placeholder={placeholder}
71
+ value={currentValue}
72
+ onChange={handleInputChange}
73
+ required={isRequired}
74
+ autoComplete="off"
75
+ id={`${actionType}-input`}
76
+ />
77
+ </div>
78
+
79
+ {profileUnitsMap && (
80
+ <ReactSelect
81
+ name={`${actionType}-unit`}
82
+ className="bcn-0 dc__mxw-120"
83
+ options={unitOptions}
84
+ value={currentUnit}
85
+ onChange={handleUnitChange}
86
+ isSearchable={false}
87
+ components={{
88
+ IndicatorSeparator: null,
89
+ ClearIndicator: null,
90
+ }}
91
+ styles={unitSelectorStyles()}
92
+ />
93
+ )}
94
+ </div>
95
+
96
+ {error && (
97
+ <div className="form__error">
98
+ <ErrorIcon className="form__icon form__icon--error" />
99
+ {error}
100
+ </div>
101
+ )}
102
+ </div>
103
+ )
104
+ }
105
+
106
+ export default BuildInfraFormAction
@@ -0,0 +1,55 @@
1
+ import { FormEvent, FunctionComponent } from 'react'
2
+ import { BuildInfraFormItemProps, BuildInfraInheritActions } from './types'
3
+ import { CHECKBOX_VALUE, Checkbox } from '../../../Common'
4
+
5
+ const BuildInfraFormItem: FunctionComponent<BuildInfraFormItemProps> = ({
6
+ heading,
7
+ marker: Marker,
8
+ children,
9
+ isInheriting,
10
+ showDivider,
11
+ handleProfileInputChange,
12
+ locator,
13
+ isDefaultProfile,
14
+ }) => {
15
+ const handleActivationChange = (e: FormEvent<HTMLInputElement>) => {
16
+ const { checked } = e.currentTarget
17
+ const action = (checked ? `activate_${locator}` : `de_activate_${locator}`) as BuildInfraInheritActions
18
+ handleProfileInputChange({ action })
19
+ }
20
+
21
+ const renderMarker = () => {
22
+ if (isDefaultProfile) {
23
+ return <Marker className="icon-dim-20 dc__no-shrink" />
24
+ }
25
+
26
+ return (
27
+ <Checkbox
28
+ onChange={handleActivationChange}
29
+ isChecked={!isInheriting}
30
+ value={CHECKBOX_VALUE.CHECKED}
31
+ dataTestId={`${locator}_marker`}
32
+ />
33
+ )
34
+ }
35
+
36
+ // If in configuration active is false, means it is inheriting values from other profile
37
+ return (
38
+ <>
39
+ <div className="flexbox-col dc__gap-8 w-100">
40
+ <div className="flexbox dc__gap-12 dc__align-start w-100">
41
+ {renderMarker()}
42
+
43
+ <div className="flexbox-col dc__gap-8 w-100">
44
+ {heading}
45
+ {!isInheriting && children}
46
+ </div>
47
+ </div>
48
+ </div>
49
+
50
+ {showDivider && <div className="w-100 dc__border-bottom-n1" />}
51
+ </>
52
+ )
53
+ }
54
+
55
+ export default BuildInfraFormItem
@@ -0,0 +1,32 @@
1
+ import { FormEvent, FunctionComponent } from 'react'
2
+ import { BuildInfraMetaConfigTypes, BuildInfraInputFieldComponentProps } from './types'
3
+ import { CustomInput } from '../../../Common'
4
+ import { BUILD_INFRA_TEXT } from './constants'
5
+
6
+ const BuildInfraProfileNameField: FunctionComponent<BuildInfraInputFieldComponentProps> = ({
7
+ handleProfileInputChange,
8
+ currentValue,
9
+ error,
10
+ }) => {
11
+ const handleChange = (e: FormEvent<HTMLInputElement>) => {
12
+ handleProfileInputChange({ action: BuildInfraMetaConfigTypes.NAME, data: { value: e.currentTarget.value } })
13
+ }
14
+
15
+ return (
16
+ <div className="flexbox-col dc__gap-4 w-100 dc__align-start">
17
+ <CustomInput
18
+ name="profile-name"
19
+ label={BUILD_INFRA_TEXT.PROFILE_LABEL}
20
+ labelClassName="m-0 dc__required-field fs-13 fw-4 lh-20 cn-7"
21
+ placeholder={BUILD_INFRA_TEXT.PROFILE_PLACEHOLDER}
22
+ value={currentValue}
23
+ onChange={handleChange}
24
+ error={error}
25
+ required
26
+ inputWrapClassName="w-100"
27
+ />
28
+ </div>
29
+ )
30
+ }
31
+
32
+ export default BuildInfraProfileNameField