@devtron-labs/devtron-fe-common-lib 0.0.58-beta-25 → 0.0.59-beta-1
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/Api.d.ts +9 -0
- package/dist/Common/Constants.d.ts +1 -0
- package/dist/Common/CustomInput/CustomInput.d.ts +1 -1
- package/dist/Common/CustomInput/Types.d.ts +2 -1
- package/dist/Common/Helper.d.ts +1 -4
- package/dist/Common/SearchBar/types.d.ts +2 -2
- package/dist/Common/Types.d.ts +3 -2
- package/dist/Pages/GlobalConfigurations/BuildInfra/BuildInfraConfigForm.d.ts +4 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/BuildInfraDescriptionField.d.ts +4 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/BuildInfraFormAction.d.ts +7 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/BuildInfraFormItem.d.ts +4 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/BuildInfraProfileNameField.d.ts +4 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/Descriptor.d.ts +4 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/Footer.d.ts +4 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/constants.d.ts +52 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/index.d.ts +7 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/services.d.ts +6 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/types.d.ts +286 -0
- package/dist/Pages/GlobalConfigurations/BuildInfra/utils.d.ts +12 -0
- package/dist/Pages/GlobalConfigurations/index.d.ts +1 -0
- package/dist/Pages/index.d.ts +1 -0
- package/dist/Shared/Components/APIResponseHandler/APIResponseHandler.d.ts +4 -0
- package/dist/Shared/Components/APIResponseHandler/constants.d.ts +4 -0
- package/dist/Shared/Components/APIResponseHandler/index.d.ts +2 -0
- package/dist/Shared/Components/APIResponseHandler/types.d.ts +37 -0
- package/dist/Shared/Components/BulkSelection/BulkSelection.d.ts +4 -0
- package/dist/Shared/Components/BulkSelection/BulkSelectionDropdownItems.d.ts +4 -0
- package/dist/Shared/Components/BulkSelection/UseBulkSelection.d.ts +3 -0
- package/dist/Shared/Components/BulkSelection/constants.d.ts +8 -0
- package/dist/Shared/Components/BulkSelection/index.d.ts +3 -0
- package/dist/Shared/Components/BulkSelection/types.d.ts +50 -0
- package/dist/Shared/Components/ReactSelect/index.d.ts +1 -0
- package/dist/Shared/Components/ReactSelect/utils.d.ts +12 -0
- package/dist/Shared/Components/index.d.ts +3 -0
- package/dist/Shared/Helpers.d.ts +16 -0
- package/dist/Shared/index.d.ts +3 -0
- package/dist/Shared/validations.d.ts +7 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1175 -190
- package/package.json +1 -1
- package/src/Assets/Icon/ic-check-all.svg +5 -0
- package/src/Assets/Icon/ic-check-square.svg +4 -0
- package/src/Assets/Icon/ic-cpu.svg +4 -0
- package/src/Assets/Icon/ic-memory.svg +3 -0
- package/src/Assets/Icon/ic-timer.svg +3 -0
- package/src/Common/Api.ts +21 -0
- package/src/Common/BreadCrumb/Types.ts +0 -1
- package/src/Common/Checkbox.tsx +1 -0
- package/src/Common/Constants.ts +2 -1
- package/src/Common/CustomInput/CustomInput.tsx +6 -2
- package/src/Common/CustomInput/Types.ts +4 -3
- package/src/Common/DraggableWrapper/DraggableWrapper.tsx +3 -1
- package/src/Common/Helper.tsx +16 -30
- package/src/Common/RJSF/utils.ts +2 -0
- package/src/Common/SearchBar/SearchBar.component.tsx +26 -15
- package/src/Common/SearchBar/searchBar.scss +1 -1
- package/src/Common/SearchBar/types.ts +1 -3
- package/src/Common/Types.ts +2 -1
- package/src/Pages/GlobalConfigurations/BuildInfra/BuildInfraConfigForm.tsx +128 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/BuildInfraDescriptionField.tsx +44 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/BuildInfraFormAction.tsx +106 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/BuildInfraFormItem.tsx +55 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/BuildInfraProfileNameField.tsx +32 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/Descriptor.tsx +45 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/Footer.tsx +55 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/Readme.md +4 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/constants.tsx +141 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/index.ts +7 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/services.tsx +167 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/types.tsx +339 -0
- package/src/Pages/GlobalConfigurations/BuildInfra/utils.tsx +508 -0
- package/src/Pages/GlobalConfigurations/index.ts +1 -0
- package/src/Pages/index.ts +1 -0
- package/src/Shared/Components/APIResponseHandler/APIResponseHandler.tsx +41 -0
- package/src/Shared/Components/APIResponseHandler/constants.tsx +5 -0
- package/src/Shared/Components/APIResponseHandler/index.ts +2 -0
- package/src/Shared/Components/APIResponseHandler/types.tsx +39 -0
- package/src/Shared/Components/BulkSelection/BulkSelection.tsx +81 -0
- package/src/Shared/Components/BulkSelection/BulkSelectionDropdownItems.tsx +31 -0
- package/src/Shared/Components/BulkSelection/UseBulkSelection.tsx +99 -0
- package/src/Shared/Components/BulkSelection/constants.tsx +12 -0
- package/src/Shared/Components/BulkSelection/index.ts +3 -0
- package/src/Shared/Components/BulkSelection/types.tsx +58 -0
- package/src/Shared/Components/ReactSelect/index.ts +1 -0
- package/src/Shared/Components/ReactSelect/utils.tsx +97 -0
- package/src/Shared/Components/index.ts +3 -0
- package/src/Shared/Helpers.tsx +29 -0
- package/src/Shared/index.ts +3 -0
- package/src/Shared/validations.tsx +72 -0
- package/src/index.ts +3 -1
|
@@ -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
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { DescriptorProps } from './types'
|
|
2
|
+
import { BreadCrumb, TippyCustomized, TippyTheme } from '../../../Common'
|
|
3
|
+
import { ReactComponent as QuestionFilled } from '../../../Assets/Icon/ic-help.svg'
|
|
4
|
+
import { ReactComponent as ICHelpOutline } from '../../../Assets/Icon/ic-help-outline.svg'
|
|
5
|
+
import { BUILD_INFRA_TEXT } from './constants'
|
|
6
|
+
|
|
7
|
+
const Descriptor = ({
|
|
8
|
+
additionalContainerClasses,
|
|
9
|
+
breadCrumbs,
|
|
10
|
+
children,
|
|
11
|
+
tippyInfoText,
|
|
12
|
+
tippyAdditionalContent,
|
|
13
|
+
}: DescriptorProps) => (
|
|
14
|
+
<div className={`flexbox dc__content-space dc__align-items-center w-100 ${additionalContainerClasses ?? ''}`}>
|
|
15
|
+
<div className="flexbox dc__align-items-center dc__gap-4">
|
|
16
|
+
<BreadCrumb breadcrumbs={breadCrumbs} />
|
|
17
|
+
|
|
18
|
+
<TippyCustomized
|
|
19
|
+
theme={TippyTheme.white}
|
|
20
|
+
className="w-300 h-100 dc__align-left"
|
|
21
|
+
placement="right"
|
|
22
|
+
Icon={QuestionFilled}
|
|
23
|
+
iconClass="fcv-5"
|
|
24
|
+
infoText={tippyInfoText ?? BUILD_INFRA_TEXT.EDIT_DEFAULT_TOOLTIP}
|
|
25
|
+
additionalContent={tippyAdditionalContent}
|
|
26
|
+
heading={BUILD_INFRA_TEXT.HEADING}
|
|
27
|
+
showCloseButton
|
|
28
|
+
trigger="click"
|
|
29
|
+
interactive
|
|
30
|
+
>
|
|
31
|
+
<button
|
|
32
|
+
className="p-0 h-20 dc__no-background dc__no-border dc__tab-focus"
|
|
33
|
+
type="button"
|
|
34
|
+
aria-label="build-infra-info"
|
|
35
|
+
>
|
|
36
|
+
<ICHelpOutline className="icon-dim-20" />
|
|
37
|
+
</button>
|
|
38
|
+
</TippyCustomized>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
{children}
|
|
42
|
+
</div>
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
export default Descriptor
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { FunctionComponent, ReactElement } from 'react'
|
|
2
|
+
import Tippy from '@tippyjs/react'
|
|
3
|
+
import { BUILD_INFRA_TEST_IDS, BUILD_INFRA_TEXT } from './constants'
|
|
4
|
+
import { FooterProps } from './types'
|
|
5
|
+
import { ConditionalWrap, Progressing } from '../../../Common'
|
|
6
|
+
|
|
7
|
+
const Footer: FunctionComponent<FooterProps> = ({ disabled, handleCancel, editProfile, loading }) => {
|
|
8
|
+
const disableMessage = disabled
|
|
9
|
+
? BUILD_INFRA_TEXT.SUBMIT_BUTTON_TIPPY.INVALID_INPUT
|
|
10
|
+
: BUILD_INFRA_TEXT.SUBMIT_BUTTON_TIPPY.REQUEST_IN_PROGRESS
|
|
11
|
+
|
|
12
|
+
const getButtonText = () => {
|
|
13
|
+
if (editProfile) {
|
|
14
|
+
return BUILD_INFRA_TEXT.EDIT_SUBMIT
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return BUILD_INFRA_TEXT.SAVE_SUBMIT
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const renderTippy = (children: ReactElement) => (
|
|
21
|
+
<Tippy content={disableMessage} placement="top" className="default-tt" arrow={false}>
|
|
22
|
+
{children}
|
|
23
|
+
</Tippy>
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div className="flex pl pr pb pt h-64 dc__gap-12 dc__border-top dc__content-start">
|
|
28
|
+
<ConditionalWrap condition={disabled || loading} wrap={renderTippy}>
|
|
29
|
+
<div className="flexbox dc__align-items-center">
|
|
30
|
+
<button
|
|
31
|
+
type="submit"
|
|
32
|
+
className="cta submit h-32 flex"
|
|
33
|
+
disabled={disabled || loading}
|
|
34
|
+
data-testid={BUILD_INFRA_TEST_IDS.SUBMIT_BUTTON}
|
|
35
|
+
>
|
|
36
|
+
{loading ? <Progressing size={16} /> : getButtonText()}
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
</ConditionalWrap>
|
|
40
|
+
|
|
41
|
+
{handleCancel && (
|
|
42
|
+
<button
|
|
43
|
+
type="button"
|
|
44
|
+
className="cta cancel h-32 flex"
|
|
45
|
+
data-testid={BUILD_INFRA_TEST_IDS.CANCEL_BUTTON}
|
|
46
|
+
onClick={handleCancel}
|
|
47
|
+
>
|
|
48
|
+
{BUILD_INFRA_TEXT.EDIT_CANCEL}
|
|
49
|
+
</button>
|
|
50
|
+
)}
|
|
51
|
+
</div>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default Footer
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
In case someone wants to add a new build infrastructure field, the following steps should be followed:
|
|
2
|
+
- Update the BUILD_INFRA_FORM_FIELDS, in constants.tsx
|
|
3
|
+
- Add BuildInfraConfigTypes, BuildInfraLocators, BuildInfraInheritActions(If any) in types.tsx
|
|
4
|
+
- In utils.tsx, update the handleProfileInputChange and validation functions accordingly
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { ReactComponent as ICCpu } from '../../../Assets/Icon/ic-cpu.svg'
|
|
2
|
+
import { ReactComponent as ICMemory } from '../../../Assets/Icon/ic-memory.svg'
|
|
3
|
+
import { ReactComponent as ICTimer } from '../../../Assets/Icon/ic-timer.svg'
|
|
4
|
+
import { UseBreadcrumbProps } from '../../../Common/BreadCrumb/Types'
|
|
5
|
+
import {
|
|
6
|
+
BuildInfraConfigTypes,
|
|
7
|
+
BuildInfraFormFieldType,
|
|
8
|
+
BuildInfraLocators,
|
|
9
|
+
BuildInfraMetaConfigTypes,
|
|
10
|
+
ProfileInputErrorType,
|
|
11
|
+
BuildInfraProfileBase,
|
|
12
|
+
BuildInfraProfileVariants,
|
|
13
|
+
HandleProfileInputChangeType,
|
|
14
|
+
} from './types'
|
|
15
|
+
|
|
16
|
+
export const BUILD_INFRA_INPUT_CONSTRAINTS = {
|
|
17
|
+
STEP: 0.01,
|
|
18
|
+
MIN: 0,
|
|
19
|
+
DECIMAL_PLACES: 2,
|
|
20
|
+
} as const
|
|
21
|
+
|
|
22
|
+
export const BUILD_INFRA_TEXT = {
|
|
23
|
+
HEADING: 'Build Infra Configuration',
|
|
24
|
+
EDIT_SUBMIT: 'Save changes',
|
|
25
|
+
SAVE_SUBMIT: 'Save',
|
|
26
|
+
EDIT_CANCEL: 'Cancel',
|
|
27
|
+
EDIT_DEFAULT_TOOLTIP:
|
|
28
|
+
'Efficiently control infrastructure settings such as CPU, Memory, and Build timeout for your build pipelines. Streamline resource management to optimise build time and cost effortlessly.',
|
|
29
|
+
DESCRIPTION_LABEL: 'Description',
|
|
30
|
+
DESCRIPTION_PLACEHOLDER: 'Enter a description here',
|
|
31
|
+
PROFILE_LABEL: 'Profile name',
|
|
32
|
+
PROFILE_PLACEHOLDER: 'Eg. java or node',
|
|
33
|
+
INHERITING_HEADING_DESCRIPTION: 'Inheriting from default',
|
|
34
|
+
SUBMIT_BUTTON_TIPPY: {
|
|
35
|
+
INVALID_INPUT: 'Valid input is required for all mandatory fields.',
|
|
36
|
+
REQUEST_IN_PROGRESS: 'Request in progress.',
|
|
37
|
+
},
|
|
38
|
+
VALIDATE_REQUEST_LIMIT: {
|
|
39
|
+
// Might use the constants from BUILD_INFRA_INPUT_CONSTRAINTS even for NEGATIVE_REQUEST and NEGATIVE_LIMIT
|
|
40
|
+
NEGATIVE_REQUEST: 'Request should be a positive number.',
|
|
41
|
+
NEGATIVE_LIMIT: 'Limit should be a positive number.',
|
|
42
|
+
REQUEST_LESS_THAN_LIMIT: 'Request should be less than or equal to limit.',
|
|
43
|
+
CAN_NOT_COMPUTE: 'Request and limit value diff are too high to validate.',
|
|
44
|
+
REQUEST_DECIMAL_PLACES: `Request should be upto ${BUILD_INFRA_INPUT_CONSTRAINTS.DECIMAL_PLACES} decimal places.`,
|
|
45
|
+
LIMIT_DECIMAL_PLACES: `Limit should be upto ${BUILD_INFRA_INPUT_CONSTRAINTS.DECIMAL_PLACES} decimal places.`,
|
|
46
|
+
},
|
|
47
|
+
getInvalidActionMessage: (action: HandleProfileInputChangeType['action']) => `Invalid action type: ${action}`,
|
|
48
|
+
getSubmitSuccessMessage: (profileName: string, isEdited: boolean) =>
|
|
49
|
+
`${profileName} profile is ${isEdited ? 'updated' : 'created'}`,
|
|
50
|
+
PROFILE_NOT_FOUND: {
|
|
51
|
+
title: 'Profile not found',
|
|
52
|
+
subTitle: 'The profile you are looking for does not exist.',
|
|
53
|
+
},
|
|
54
|
+
INVALID_FORM_MESSAGE: 'Valid input is required for all mandatory fields.',
|
|
55
|
+
} as const
|
|
56
|
+
|
|
57
|
+
export const BUILD_INFRA_BREADCRUMB: UseBreadcrumbProps = {
|
|
58
|
+
alias: {
|
|
59
|
+
'global-config': null,
|
|
60
|
+
'build-infra': {
|
|
61
|
+
component: <h2 className="m-0 cn-9 fs-16 fw-6 lh-32">{BUILD_INFRA_TEXT.HEADING}</h2>,
|
|
62
|
+
linked: false,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// TODO: move heading to component itself
|
|
68
|
+
export const BUILD_INFRA_FORM_FIELDS: BuildInfraFormFieldType[] = [
|
|
69
|
+
{
|
|
70
|
+
heading: <h3 className="m-0 cn-9 fs-13 fw-6 lh-20 w-240 dc__no-shrink">CPU (Request - Limit)</h3>,
|
|
71
|
+
marker: ICCpu,
|
|
72
|
+
actions: [
|
|
73
|
+
{
|
|
74
|
+
actionType: BuildInfraConfigTypes.CPU_REQUEST,
|
|
75
|
+
label: 'Request',
|
|
76
|
+
placeholder: 'Type CPU request',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
actionType: BuildInfraConfigTypes.CPU_LIMIT,
|
|
80
|
+
label: 'Limit',
|
|
81
|
+
placeholder: 'Type CPU limit',
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
locator: BuildInfraLocators.CPU,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
heading: <h3 className="m-0 cn-9 fs-13 fw-6 lh-20 w-240 dc__no-shrink">Memory (Request - Limit)</h3>,
|
|
88
|
+
marker: ICMemory,
|
|
89
|
+
actions: [
|
|
90
|
+
{
|
|
91
|
+
actionType: BuildInfraConfigTypes.MEMORY_REQUEST,
|
|
92
|
+
label: 'Request',
|
|
93
|
+
placeholder: 'Type memory request',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
actionType: BuildInfraConfigTypes.MEMORY_LIMIT,
|
|
97
|
+
label: 'Limit',
|
|
98
|
+
placeholder: 'Type memory limit',
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
locator: BuildInfraLocators.MEMORY,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
heading: <h3 className="m-0 cn-9 fs-13 fw-6 lh-20 w-240 dc__no-shrink">Build timeout</h3>,
|
|
105
|
+
marker: ICTimer,
|
|
106
|
+
actions: [
|
|
107
|
+
{
|
|
108
|
+
actionType: BuildInfraConfigTypes.BUILD_TIMEOUT,
|
|
109
|
+
label: 'Timeout',
|
|
110
|
+
placeholder: 'Type build timeout',
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
locator: BuildInfraLocators.BUILD_TIMEOUT,
|
|
114
|
+
},
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
export const PROFILE_INPUT_ERROR_FIELDS = Object.fromEntries(
|
|
118
|
+
Object.values({ ...BuildInfraConfigTypes, ...BuildInfraMetaConfigTypes }).map((value) => [value, null]),
|
|
119
|
+
) as ProfileInputErrorType
|
|
120
|
+
|
|
121
|
+
// fields required to be filled before submitting the form in create view, since we pre-populate the form with default values so no need in configs
|
|
122
|
+
export const CREATE_MODE_REQUIRED_INPUT_FIELDS = [BuildInfraMetaConfigTypes.NAME]
|
|
123
|
+
|
|
124
|
+
export const DEFAULT_PROFILE_NAME = 'default' as const
|
|
125
|
+
|
|
126
|
+
export const CREATE_PROFILE_BASE_VALUE: BuildInfraProfileBase = {
|
|
127
|
+
name: '',
|
|
128
|
+
description: '',
|
|
129
|
+
type: BuildInfraProfileVariants.NORMAL,
|
|
130
|
+
appCount: 0,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const CREATE_VIEW_CHECKED_CONFIGS = {
|
|
134
|
+
[BuildInfraConfigTypes.CPU_REQUEST]: true,
|
|
135
|
+
[BuildInfraConfigTypes.CPU_LIMIT]: true,
|
|
136
|
+
} as const
|
|
137
|
+
|
|
138
|
+
export const BUILD_INFRA_TEST_IDS = {
|
|
139
|
+
SUBMIT_BUTTON: 'build-infra-submit-button',
|
|
140
|
+
CANCEL_BUTTON: 'build-infra-cancel-button',
|
|
141
|
+
} as const
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as BuildInfraDescriptor } from './Descriptor'
|
|
2
|
+
export { default as BuildInfraFooter } from './Footer'
|
|
3
|
+
export { default as BuildInfraConfigForm } from './BuildInfraConfigForm'
|
|
4
|
+
export * from './services'
|
|
5
|
+
export * from './utils'
|
|
6
|
+
export * from './types'
|
|
7
|
+
export * from './constants'
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { ROUTES, ResponseType, get, post, put, showError } from '../../../Common'
|
|
2
|
+
import { CREATE_PROFILE_BASE_VALUE, CREATE_VIEW_CHECKED_CONFIGS } from './constants'
|
|
3
|
+
import {
|
|
4
|
+
BuildInfraConfigTypes,
|
|
5
|
+
BuildInfraConfigurationMapType,
|
|
6
|
+
BuildInfraConfigurationType,
|
|
7
|
+
BuildInfraProfileAPIResponseType,
|
|
8
|
+
BuildInfraProfileBase,
|
|
9
|
+
BuildInfraProfileResponseDataType,
|
|
10
|
+
BuildInfraProfileResponseType,
|
|
11
|
+
BuildInfraProfileTransformerType,
|
|
12
|
+
CreateBuildInfraProfileType,
|
|
13
|
+
CreateBuildInfraServicePayloadType,
|
|
14
|
+
CreateBuildInfraServiceConfigurationType,
|
|
15
|
+
GetBuildInfraProfileType,
|
|
16
|
+
UpdateBuildInfraProfileType,
|
|
17
|
+
BuildInfraConfigurationMapWithoutDefaultType,
|
|
18
|
+
} from './types'
|
|
19
|
+
|
|
20
|
+
const getBaseProfileObject = (
|
|
21
|
+
fromCreateView: boolean,
|
|
22
|
+
profile: BuildInfraProfileResponseDataType,
|
|
23
|
+
): BuildInfraProfileBase => {
|
|
24
|
+
if (fromCreateView) {
|
|
25
|
+
return CREATE_PROFILE_BASE_VALUE
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
id: profile.id,
|
|
30
|
+
name: profile.name,
|
|
31
|
+
description: profile.description,
|
|
32
|
+
type: profile.type,
|
|
33
|
+
appCount: profile.appCount,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Would receive a single profile and return transformed response
|
|
38
|
+
export const getTransformedBuildInfraProfileResponse = ({
|
|
39
|
+
configurationUnits,
|
|
40
|
+
defaultConfigurations,
|
|
41
|
+
profile,
|
|
42
|
+
fromCreateView,
|
|
43
|
+
}: BuildInfraProfileTransformerType): BuildInfraProfileResponseType => {
|
|
44
|
+
// Assuming would contain all the keys
|
|
45
|
+
const defaultConfigurationsMap =
|
|
46
|
+
defaultConfigurations?.reduce((acc, configuration) => {
|
|
47
|
+
acc[configuration.key] = configuration
|
|
48
|
+
return acc
|
|
49
|
+
}, {} as BuildInfraConfigurationMapWithoutDefaultType) ?? ({} as BuildInfraConfigurationMapWithoutDefaultType)
|
|
50
|
+
|
|
51
|
+
const profileConfigurations =
|
|
52
|
+
profile?.configurations?.reduce((acc, configuration) => {
|
|
53
|
+
acc[configuration.key] = configuration
|
|
54
|
+
return acc
|
|
55
|
+
}, {} as BuildInfraConfigurationMapWithoutDefaultType) ?? ({} as BuildInfraConfigurationMapWithoutDefaultType)
|
|
56
|
+
|
|
57
|
+
const configurations = Object.keys(defaultConfigurationsMap).reduce((acc, key) => {
|
|
58
|
+
const defaultConfiguration: BuildInfraConfigurationType = defaultConfigurationsMap[key]
|
|
59
|
+
const profileConfiguration =
|
|
60
|
+
profileConfigurations[key]?.profileName === profile?.name ? profileConfigurations[key] : null
|
|
61
|
+
// Pushing default value in configurations in case we de-activate the configuration
|
|
62
|
+
const defaultValue = {
|
|
63
|
+
value: defaultConfiguration.value,
|
|
64
|
+
unit: defaultConfiguration.unit,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (fromCreateView) {
|
|
68
|
+
acc[key] = {
|
|
69
|
+
key,
|
|
70
|
+
value: defaultConfiguration.value,
|
|
71
|
+
unit: defaultConfiguration.unit,
|
|
72
|
+
active: CREATE_VIEW_CHECKED_CONFIGS[key] ?? false,
|
|
73
|
+
defaultValue,
|
|
74
|
+
}
|
|
75
|
+
return acc
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (profileConfiguration) {
|
|
79
|
+
acc[key] = {
|
|
80
|
+
...profileConfiguration,
|
|
81
|
+
defaultValue,
|
|
82
|
+
}
|
|
83
|
+
return acc
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Removing id from it since we do not have a configuration
|
|
87
|
+
// While generating payload, we will check on the basis of id and active flag.
|
|
88
|
+
acc[key] = {
|
|
89
|
+
key,
|
|
90
|
+
value: defaultConfiguration.value,
|
|
91
|
+
// saving profile name as undefined and this would be a check, if we are deriving from default or not
|
|
92
|
+
unit: defaultConfiguration.unit,
|
|
93
|
+
active: false,
|
|
94
|
+
defaultValue,
|
|
95
|
+
}
|
|
96
|
+
return acc
|
|
97
|
+
}, {} as BuildInfraConfigurationMapType)
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
configurationUnits,
|
|
101
|
+
profile: {
|
|
102
|
+
...(profile && getBaseProfileObject(fromCreateView, profile)),
|
|
103
|
+
configurations,
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export const getBuildInfraProfileByName = async ({
|
|
109
|
+
name,
|
|
110
|
+
fromCreateView,
|
|
111
|
+
}: GetBuildInfraProfileType): Promise<BuildInfraProfileResponseType> => {
|
|
112
|
+
try {
|
|
113
|
+
const response = await get(`${ROUTES.INFRA_CONFIG_PROFILE}/${name}`)
|
|
114
|
+
const {
|
|
115
|
+
result: { configurationUnits, defaultConfigurations, profile },
|
|
116
|
+
} = response as ResponseType<BuildInfraProfileAPIResponseType>
|
|
117
|
+
|
|
118
|
+
return getTransformedBuildInfraProfileResponse({
|
|
119
|
+
configurationUnits,
|
|
120
|
+
defaultConfigurations,
|
|
121
|
+
profile,
|
|
122
|
+
fromCreateView,
|
|
123
|
+
})
|
|
124
|
+
} catch (error) {
|
|
125
|
+
showError(error)
|
|
126
|
+
throw error
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const getBuildInfraProfilePayload = (
|
|
131
|
+
profileInput: CreateBuildInfraProfileType['profileInput'],
|
|
132
|
+
): CreateBuildInfraServicePayloadType => {
|
|
133
|
+
const currentConfigurations = profileInput.configurations
|
|
134
|
+
const configurationKeys = Object.keys(currentConfigurations) as BuildInfraConfigTypes[]
|
|
135
|
+
// would only keep the configurations with id or active flag as true
|
|
136
|
+
const configurations: CreateBuildInfraServiceConfigurationType[] = configurationKeys.reduce((acc, key) => {
|
|
137
|
+
const configuration = currentConfigurations[key]
|
|
138
|
+
if (configuration.id || configuration.active) {
|
|
139
|
+
acc.push({
|
|
140
|
+
id: configuration.id,
|
|
141
|
+
key,
|
|
142
|
+
value: Number(configuration.value),
|
|
143
|
+
unit: configuration.unit,
|
|
144
|
+
active: configuration.active,
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
return acc
|
|
148
|
+
}, [] as CreateBuildInfraServiceConfigurationType[])
|
|
149
|
+
|
|
150
|
+
const payload: CreateBuildInfraServicePayloadType = {
|
|
151
|
+
name: profileInput.name,
|
|
152
|
+
description: profileInput.description,
|
|
153
|
+
type: profileInput.type,
|
|
154
|
+
configurations,
|
|
155
|
+
}
|
|
156
|
+
return payload
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export const updateBuildInfraProfile = ({ name, profileInput }: UpdateBuildInfraProfileType) => {
|
|
160
|
+
const payload = getBuildInfraProfilePayload(profileInput)
|
|
161
|
+
return put(`${ROUTES.INFRA_CONFIG_PROFILE}/${name}`, payload)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const createBuildInfraProfile = async ({ profileInput }: CreateBuildInfraProfileType) => {
|
|
165
|
+
const payload = getBuildInfraProfilePayload(profileInput)
|
|
166
|
+
return post(ROUTES.INFRA_CONFIG_PROFILE, payload)
|
|
167
|
+
}
|