@devtron-labs/devtron-fe-common-lib 0.0.6-beta-12 → 0.0.6-beta-14

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 (45) hide show
  1. package/dist/Common/Constants.d.ts +6 -0
  2. package/dist/Common/CustomTagSelector/PropagateTagInfo.d.ts +2 -0
  3. package/dist/Common/CustomTagSelector/TagDetails.d.ts +8 -0
  4. package/dist/Common/CustomTagSelector/TagLabelSelect.d.ts +6 -0
  5. package/dist/Common/CustomTagSelector/TagLabelValueSelector.d.ts +10 -0
  6. package/dist/Common/CustomTagSelector/TagSelector.utils.d.ts +12 -0
  7. package/dist/Common/CustomTagSelector/ValidationRules.d.ts +10 -0
  8. package/dist/Common/CustomTagSelector/index.d.ts +2 -0
  9. package/dist/Common/Dialogs/ConfirmationDialog.d.ts +20 -0
  10. package/dist/Common/Dialogs/DeleteDialog.d.ts +5 -0
  11. package/dist/Common/Dialogs/DialogForm.d.ts +22 -0
  12. package/dist/Common/Dialogs/ForceDeleteDialog.d.ts +3 -0
  13. package/dist/Common/Dialogs/Types.d.ts +15 -0
  14. package/dist/Common/Dialogs/index.d.ts +4 -0
  15. package/dist/Common/PopupMenu.d.ts +23 -0
  16. package/dist/Common/RadioGroup.d.ts +17 -0
  17. package/dist/Common/TippyCustomized.d.ts +35 -0
  18. package/dist/Common/Types.d.ts +12 -0
  19. package/dist/Common/index.d.ts +4 -0
  20. package/dist/index.js +8530 -1
  21. package/package.json +6 -5
  22. package/rollup.config.js +1 -3
  23. package/src/Assets/Icon/ic-help-outline.svg +3 -0
  24. package/src/Assets/Icon/ic-info-outlined.svg +13 -0
  25. package/src/Assets/Icon/inject-tag.svg +5 -0
  26. package/src/Assets/Img/warning-medium.svg +15 -0
  27. package/src/Common/Constants.ts +7 -0
  28. package/src/Common/CustomTagSelector/PropagateTagInfo.tsx +36 -0
  29. package/src/Common/CustomTagSelector/TagDetails.tsx +41 -0
  30. package/src/Common/CustomTagSelector/TagLabelSelect.tsx +56 -0
  31. package/src/Common/CustomTagSelector/TagLabelValueSelector.tsx +144 -0
  32. package/src/Common/CustomTagSelector/TagSelector.utils.ts +71 -0
  33. package/src/Common/CustomTagSelector/ValidationRules.ts +55 -0
  34. package/src/Common/CustomTagSelector/index.ts +2 -0
  35. package/src/Common/Dialogs/ConfirmationDialog.tsx +32 -0
  36. package/src/Common/Dialogs/DeleteDialog.tsx +35 -0
  37. package/src/Common/Dialogs/DialogForm.tsx +95 -0
  38. package/src/Common/Dialogs/ForceDeleteDialog.tsx +19 -0
  39. package/src/Common/Dialogs/Types.ts +16 -0
  40. package/src/Common/Dialogs/index.ts +4 -0
  41. package/src/Common/PopupMenu.tsx +131 -0
  42. package/src/Common/RadioGroup.tsx +63 -0
  43. package/src/Common/TippyCustomized.tsx +173 -0
  44. package/src/Common/Types.ts +14 -0
  45. package/src/Common/index.ts +5 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devtron-labs/devtron-fe-common-lib",
3
- "version": "0.0.6-beta-12",
3
+ "version": "0.0.6-beta-14",
4
4
  "description": "Supporting common component library",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -21,7 +21,6 @@
21
21
  "devDependencies": {
22
22
  "@rollup/plugin-babel": "^6.0.3",
23
23
  "@rollup/plugin-node-resolve": "^15.0.1",
24
- "@rollup/plugin-terser": "^0.2.0",
25
24
  "@rollup/plugin-image": "3.0.1",
26
25
  "rollup-plugin-peer-deps-external": "^2.2.4",
27
26
  "rollup-plugin-postcss": "^4.0.2",
@@ -29,13 +28,14 @@
29
28
  "@types/react": "17.0.39",
30
29
  "@types/react-dom": "17.0.13",
31
30
  "@types/react-router-dom": "^5.3.3",
32
- "rollup": "^3.7.3",
31
+ "rollup": "^3.10.0",
33
32
  "rollup-plugin-delete": "^2.0.0",
34
33
  "@svgr/rollup": "6.5.1",
35
34
  "@rollup/plugin-url": "8.0.1",
36
35
  "typescript": "^4.9.4",
37
36
  "react-toastify": "^8.2.0",
38
- "@sentry/browser": "^7.3.1"
37
+ "@tippyjs/react": "^4.2.0",
38
+ "@sentry/browser": "^7.31.1"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "react": "^17.0.2",
@@ -43,6 +43,7 @@
43
43
  "react-router-dom": "^5.3.0"
44
44
  },
45
45
  "dependencies": {
46
- "sass": "^1.56.2"
46
+ "sass": "^1.56.2",
47
+ "tslib": "^2.4.1"
47
48
  }
48
49
  }
package/rollup.config.js CHANGED
@@ -3,10 +3,9 @@ import resolve from '@rollup/plugin-node-resolve'
3
3
  import typescript from 'rollup-plugin-typescript2'
4
4
  import postcss from 'rollup-plugin-postcss'
5
5
  import { babel } from '@rollup/plugin-babel'
6
- import terser from '@rollup/plugin-terser'
7
6
  import del from 'rollup-plugin-delete'
8
7
  import pkg from './package.json'
9
- import svgr from '@svgr/rollup';
8
+ import svgr from '@svgr/rollup'
10
9
  import url from '@rollup/plugin-url'
11
10
 
12
11
  export default {
@@ -19,7 +18,6 @@ export default {
19
18
  postcss({
20
19
  extensions: ['.css'],
21
20
  }),
22
- terser(),
23
21
  babel({
24
22
  exclude: 'node_modules/**',
25
23
  }),
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17 16">
2
+ <path fill="#767D84" fill-rule="evenodd" d="M9 1.333c3.682 0 6.667 2.985 6.667 6.667S12.682 14.667 9 14.667 2.333 11.682 2.333 8 5.318 1.333 9 1.333zm0 1.334C6.054 2.667 3.667 5.054 3.667 8S6.054 13.333 9 13.333 14.333 10.946 14.333 8 11.946 2.667 9 2.667zm-.137 7.245c.41 0 .747.337.747.747s-.337.747-.747.747-.747-.336-.747-.747c0-.41.338-.747.747-.747zm.046-5.245c1.166 0 2.313.537 2.313 1.82 0 1.185-1.357 1.64-1.648 2.068-.22.319-.146.766-.747.766-.392 0-.583-.319-.583-.61 0-1.085 1.593-1.33 1.593-2.223 0-.492-.327-.783-.873-.783-1.166 0-.711 1.202-1.594 1.202-.319 0-.592-.191-.592-.556 0-.893 1.02-1.684 2.13-1.684z"/>
3
+ </svg>
@@ -0,0 +1,13 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <g fill="#06C">
4
+ <g>
5
+ <g>
6
+ <g>
7
+ <path d="M10 1.667c4.6 0 8.333 3.733 8.333 8.333S14.6 18.333 10 18.333 1.667 14.6 1.667 10 5.4 1.667 10 1.667zm0 1.666C6.32 3.333 3.333 6.32 3.333 10c0 3.68 2.987 6.667 6.667 6.667 3.68 0 6.667-2.987 6.667-6.667 0-3.68-2.987-6.667-6.667-6.667zm0 5.834c.46 0 .833.373.833.833v3.333c0 .46-.373.834-.833.834-.46 0-.833-.373-.833-.834V10c0-.46.373-.833.833-.833zm0-3.334c.46 0 .833.373.833.834 0 .46-.373.833-.833.833-.46 0-.833-.373-.833-.833 0-.46.373-.834.833-.834z" transform="translate(-315.000000, -313.000000) translate(303.000000, 256.000000) translate(4.000000, 49.000000) translate(8.000000, 8.000000)"/>
8
+ </g>
9
+ </g>
10
+ </g>
11
+ </g>
12
+ </g>
13
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M10 10H3.33333" stroke="#596168" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <circle cx="9.99992" cy="9.99967" r="1.66667" fill="#596168"/>
4
+ <path d="M4.41455 6.40325L9.76177 3.39544C9.83454 3.35451 9.91661 3.33301 10.0001 3.33301C10.0836 3.33301 10.1657 3.35451 10.2384 3.39544L15.5856 6.40325C15.6608 6.44554 15.7234 6.50706 15.7669 6.58152C15.8105 6.65598 15.8334 6.74068 15.8334 6.82693V12.8208C15.8334 12.9071 15.8105 12.9918 15.7669 13.0662C15.7234 13.1407 15.6608 13.2022 15.5856 13.2445L10.2384 16.2523C10.1657 16.2933 10.0836 16.3148 10.0001 16.3148C9.91661 16.3148 9.83454 16.2933 9.76177 16.2523L4.41455 13.2445" stroke="#596168" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48">
3
+ <g fill="none" fill-rule="evenodd">
4
+ <path d="M0 0h48v48H0z"/>
5
+ <g fill="#FFEBEB" stroke="#F33E3E" stroke-linejoin="round" stroke-width="2">
6
+ <path d="M7 24h24v17a4 4 0 0 1-4 4H11a4 4 0 0 1-4-4V24z"/>
7
+ <path stroke-linecap="round" d="M19 29.5v10M24 29.5v10M14 29.5v10"/>
8
+ </g>
9
+ <path stroke="#F33E3E" stroke-dasharray="17,3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M42 10a3 3 0 0 1 0 6H31M38 23a3 3 0 0 0-3-3h-8"/>
10
+ <g stroke="#F33E3E" stroke-linejoin="round" stroke-width="2" transform="rotate(-10 36.29 -8.86)">
11
+ <rect width="30" height="5" y="6" fill="#FFEBEB" rx="1"/>
12
+ <path d="M11 0h8a2 2 0 0 1 2 2v4H9V2a2 2 0 0 1 2-2z"/>
13
+ </g>
14
+ </g>
15
+ </svg>
@@ -1,2 +1,9 @@
1
1
  export const RequestTimeout = 60000
2
2
  export const Host = process.env.REACT_APP_ORCHESTRATOR_ROOT
3
+
4
+ export const PATTERNS = {
5
+ KUBERNETES_KEY_PREFIX: /^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$/,
6
+ KUBERNETES_KEY_NAME: /^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$/,
7
+ START_END_ALPHANUMERIC: /^([A-Za-z0-9].*[A-Za-z0-9])$|[A-Za-z0-9]$/,
8
+ ALPHANUMERIC_WITH_SPECIAL_CHAR: /^[A-Za-z0-9._-]+$/, // allow alphanumeric,(.) ,(-),(_)
9
+ }
@@ -0,0 +1,36 @@
1
+ import React from 'react'
2
+ import { ReactComponent as InjectTag } from '../../Assets/Icon/inject-tag.svg'
3
+ import { ReactComponent as Help } from '../../Assets/Icon/ic-help-outline.svg'
4
+ import TippyCustomized, { TippyTheme } from '../TippyCustomized'
5
+
6
+ export default function PropagateTagInfo() {
7
+ const additionalInfo = () => {
8
+ return (
9
+ <div className="p-12 fs-13">
10
+ Use these tags to filter/identify resources via CLI or in other Kubernetes tools.
11
+ </div>
12
+ )
13
+ }
14
+ return (
15
+ <div className="flexbox">
16
+ <InjectTag className="icon-dim-16 mt-2 mr-4" />
17
+ <span>Propagate tags</span>
18
+ <TippyCustomized
19
+ theme={TippyTheme.white}
20
+ className="w-300"
21
+ placement="top"
22
+ Icon={InjectTag}
23
+ heading={'Propagate tags to K8s resources'}
24
+ infoText={`Add a tag and click on the ⬡ icon to propagate tags as labels to Kubernetes resources.`}
25
+ additionalContent={additionalInfo()}
26
+ showCloseButton={true}
27
+ trigger="click"
28
+ interactive={true}
29
+ documentationLink={''}
30
+ documentationLinkText={'View Documentation'}
31
+ >
32
+ <Help className="icon-dim-16 mt-2 ml-4 cursor" />
33
+ </TippyCustomized>
34
+ </div>
35
+ )
36
+ }
@@ -0,0 +1,41 @@
1
+ import React from 'react'
2
+ import { ReactComponent as DeleteCross } from '../../Assets/Icon/ic-close.svg'
3
+ import { ReactComponent as InjectTag } from '../../Assets/Icon/inject-tag.svg'
4
+ import { TagType } from '../Types'
5
+ import TagLabelValueSelector from './TagLabelValueSelector'
6
+
7
+ export default function TagDetails({
8
+ index,
9
+ tagData,
10
+ setTagData,
11
+ removeTag,
12
+ }: {
13
+ index: number
14
+ tagData: TagType
15
+ setTagData: (index: number, tagData: TagType) => void
16
+ removeTag: (index: number) => void
17
+ }) {
18
+ const deleteTag = (): void => {
19
+ removeTag(index)
20
+ }
21
+ const propagateTagToResource = (): void => {
22
+ const _tagData = { ...tagData }
23
+ _tagData.propagate = !_tagData.propagate
24
+ setTagData(index, _tagData)
25
+ }
26
+ return (
27
+ <div className="flexbox mb-8">
28
+ <div
29
+ className={`dc__border pl-4 pr-4 br-4 mr-8 pointer ${tagData.propagate ? 'bcn-7' : ''}`}
30
+ onClick={propagateTagToResource}
31
+ >
32
+ <InjectTag className={`icon-dim-20 mt-4 ${tagData.propagate ? 'scn-0' : ''}`} />
33
+ </div>
34
+ <TagLabelValueSelector selectedTagIndex={index} tagData={tagData} setTagData={setTagData} type="key" />
35
+ <TagLabelValueSelector selectedTagIndex={index} tagData={tagData} setTagData={setTagData} type="value" />
36
+ <div className="dc__border pl-4 pr-4 dc__right-radius-4 pointer" onClick={deleteTag}>
37
+ <DeleteCross className="icon-dim-20 mt-4" />
38
+ </div>
39
+ </div>
40
+ )
41
+ }
@@ -0,0 +1,56 @@
1
+ import React from 'react'
2
+ import PropagateTagInfo from './PropagateTagInfo'
3
+ import { ReactComponent as Add } from '../../Assets/Icon/ic-add.svg'
4
+ import TagDetails from './TagDetails'
5
+ import { TagType } from '../Types'
6
+
7
+ export const TagLabelSelect = ({
8
+ labelTags,
9
+ setLabelTags,
10
+ }: {
11
+ labelTags: TagType[]
12
+ setLabelTags: (tagList: TagType[]) => void
13
+ }) => {
14
+ const setTagData = (index, tagValue): void => {
15
+ const _tags = [...labelTags]
16
+ _tags[index] = tagValue
17
+ setLabelTags(_tags)
18
+ }
19
+
20
+ const addNewTag = (): void => {
21
+ const _tags = [...labelTags]
22
+ _tags.splice(0, 0, { key: '', value: '', propagate: false, isInvalidKey: false, isInvalidValue: false })
23
+ setLabelTags(_tags)
24
+ }
25
+
26
+ const removeTag = (index: number): void => {
27
+ const _tags = [...labelTags]
28
+ _tags.splice(index, 1)
29
+ setLabelTags(_tags)
30
+ }
31
+
32
+ return (
33
+ <div>
34
+ <div className="flexbox dc__content-space mb-8">
35
+ <span>Tags</span>
36
+ <PropagateTagInfo />
37
+ </div>
38
+ <div>
39
+ <div className="dc_width-max-content cb-5 fw-6 fs-13 flexbox mr-20 mb-8 cursor" onClick={addNewTag}>
40
+ <Add className="icon-dim-20 fcb-5" /> Add tag
41
+ </div>
42
+ <div className="mb-8">
43
+ {labelTags?.map((tagData, index) => (
44
+ <TagDetails
45
+ key={`tag-${index}`}
46
+ index={index}
47
+ tagData={tagData}
48
+ setTagData={setTagData}
49
+ removeTag={removeTag}
50
+ />
51
+ ))}
52
+ </div>
53
+ </div>
54
+ </div>
55
+ )
56
+ }
@@ -0,0 +1,144 @@
1
+ import React, { useState, useEffect } from 'react'
2
+ import { OptionType, TagType } from '../Types'
3
+ import PopupMenu from '../PopupMenu'
4
+ import { ValidationRules } from './ValidationRules'
5
+ import { ReactComponent as ErrorCross } from '../../Assets/Icon/ic-close.svg'
6
+ import { ReactComponent as Info } from '../../Assets/Icon/ic-info-outlined.svg'
7
+
8
+ export default function TagLabelValueSelector({
9
+ selectedTagIndex,
10
+ tagData,
11
+ setTagData,
12
+ tagOptions,
13
+ isRequired,
14
+ type,
15
+ }: {
16
+ selectedTagIndex: number
17
+ tagData: TagType
18
+ setTagData: (index: number, tagData: TagType) => void
19
+ tagOptions?: OptionType[]
20
+ isRequired?: boolean
21
+ type?: string
22
+ }) {
23
+ const [selectedValue, setSelectedValue] = useState<string>('')
24
+ const [isPopupOpen, togglePopup] = useState<boolean>(false)
25
+
26
+ const validationRules = new ValidationRules()
27
+
28
+ useEffect(() => {
29
+ const _tagData = { ...tagData }
30
+ setSelectedValue(_tagData[type])
31
+ }, [selectedTagIndex, tagData, type])
32
+
33
+ const handleOnBlur = (e) => {
34
+ if (
35
+ !e.relatedTarget ||
36
+ !e.relatedTarget.classList.value ||
37
+ e.relatedTarget.classList.value.indexOf(`tag-${selectedTagIndex}-class`) === -1
38
+ ) {
39
+ const _tagData = { ...tagData }
40
+ _tagData[type] = selectedValue
41
+ if (type === 'key') {
42
+ _tagData.isInvalidKey = selectedValue
43
+ ? !validationRules.propagateTagKey(selectedValue).isValid
44
+ : _tagData.value !== ''
45
+ } else {
46
+ if (selectedValue) {
47
+ _tagData.isInvalidValue = !validationRules.propagateTagValue(selectedValue).isValid
48
+ _tagData.isInvalidKey = !_tagData.key || _tagData.isInvalidKey
49
+ } else {
50
+ _tagData.isInvalidValue = false
51
+ _tagData.isInvalidKey = !_tagData.key ? false : _tagData.isInvalidKey
52
+ }
53
+ }
54
+ setTagData(selectedTagIndex, _tagData)
55
+ }
56
+ }
57
+
58
+ const handleInputChange = (e): void => {
59
+ setSelectedValue(e.target.value)
60
+ }
61
+
62
+ const onSelectValue = (e): void => {
63
+ const _tagData = { ...tagData }
64
+ _tagData[type] = e.currentTarget.dataset.key
65
+ setTagData(selectedTagIndex, _tagData)
66
+ }
67
+
68
+ const renderValidationsSuggestions = (): JSX.Element => {
69
+ let field = { isValid: true, messages: [] }
70
+ if (type === 'value') {
71
+ if (isRequired || selectedValue) {
72
+ field = validationRules.propagateTagValue(selectedValue)
73
+ }
74
+ } else {
75
+ field = validationRules.propagateTagKey(selectedValue)
76
+ }
77
+ if (!field.isValid) {
78
+ return (
79
+ <div className="p-4">
80
+ {field.messages.map((error) => (
81
+ <div key={error} className="flexbox p-4">
82
+ <span>
83
+ <ErrorCross className="icon-dim-14 scr-5 mt-3 mr-4" />
84
+ </span>
85
+ <span>{error}</span>
86
+ </div>
87
+ ))}
88
+ {type === 'key' && (
89
+ <div className="flexbox p-4">
90
+ <span>
91
+ <Info className="icon-dim-14 mt-3 mr-4" />
92
+ </span>
93
+ <span className="dc__italic-font-style">Key format: prefix/name or name</span>
94
+ </div>
95
+ )}
96
+ </div>
97
+ )
98
+ }
99
+ return null
100
+ }
101
+
102
+ const renderSuggestions = (): JSX.Element => {
103
+ if (tagOptions?.length) {
104
+ const filteredTags = tagOptions.filter((tag) => tag.value.indexOf(selectedValue) >= 0)
105
+ if (filteredTags.length) {
106
+ return (
107
+ <div className="p-8">
108
+ {tagOptions
109
+ .filter((tag) => tag.value.indexOf(selectedValue) >= 0)
110
+ .map((tag, index) => (
111
+ <div data-key={`${tag.value}-${index}`} className="cursor" onClick={onSelectValue}>
112
+ {tag.label}
113
+ </div>
114
+ ))}
115
+ </div>
116
+ )
117
+ }
118
+ }
119
+ return renderValidationsSuggestions()
120
+ }
121
+
122
+ return (
123
+ <PopupMenu onToggleCallback={(isOpen) => togglePopup(isOpen)} autoClose>
124
+ <PopupMenu.Button
125
+ rootClassName={`${
126
+ type === 'key'
127
+ ? `dc__no-right-radius`
128
+ : `dc__no-border-radius dc__no-right-border dc__no-left-border`
129
+ } ${tagData[type === 'key' ? 'isInvalidKey' : 'isInvalidValue'] ? 'er-5 bw-1' : ''}`}
130
+ >
131
+ <input
132
+ type="text"
133
+ className="form__input pt-4-imp pb-4-imp dc__no-border"
134
+ value={selectedValue}
135
+ onChange={handleInputChange}
136
+ onBlur={handleOnBlur}
137
+ />
138
+ </PopupMenu.Button>
139
+ <PopupMenu.Body rootClassName={`tag-${selectedTagIndex}-class`} autoWidth={true}>
140
+ {isPopupOpen && renderSuggestions()}
141
+ </PopupMenu.Body>
142
+ </PopupMenu>
143
+ )
144
+ }
@@ -0,0 +1,71 @@
1
+ export const baseSelectStyles = {
2
+ control: (base, state) => ({
3
+ ...base,
4
+ border: '1px solid var(--N200)',
5
+ boxShadow: 'none',
6
+ minHeight: 'auto',
7
+ borderRadius: 'none',
8
+ height: '32px',
9
+ fontSize: '12px',
10
+ borderRight: '0',
11
+ cursor: state.isDisabled ? 'not-allowed' : 'normal',
12
+ }),
13
+ singleValue: (base, state) => ({
14
+ ...base,
15
+ fontWeight: '500',
16
+ }),
17
+ placeholder: (base, state) => ({
18
+ ...base,
19
+ fontWeight: '500',
20
+ }),
21
+ option: (base, state) => ({
22
+ ...base,
23
+ fontWeight: '500',
24
+ color: 'var(--N900)',
25
+ fontSize: '12px',
26
+ padding: '5px 10px',
27
+ }),
28
+ dropdownIndicator: (styles) => ({ ...styles, padding: 0 }),
29
+ valueContainer: (base, state) => ({
30
+ ...base,
31
+ color: 'var(--N900)',
32
+ background: state.isDisabled ? 'var(--N100) !important' : 'var(--N50) !important',
33
+ padding: '0px 10px',
34
+ display: 'flex',
35
+ height: '30px',
36
+ fontSize: '12px',
37
+ cursor: state.isDisabled ? 'not-allowed' : 'normal',
38
+ pointerEvents: 'all',
39
+ width: '100px',
40
+ whiteSpace: 'nowrap',
41
+ }),
42
+ indicatorsContainer: (base, state) => ({
43
+ ...base,
44
+ background: state.isDisabled ? 'var(--N100) !important' : 'var(--N50) !important',
45
+ }),
46
+ menu: (base, state) => ({
47
+ ...base,
48
+ marginTop: '0',
49
+ }),
50
+ }
51
+
52
+ export const validateKubernetesKey = (key: string) => {
53
+ const invalidMessageList = []
54
+ if (!key || key.split('/')) {
55
+ invalidMessageList.push('Name is required')
56
+ } else {
57
+ const re = new RegExp('/', 'g')
58
+ const noOfSlashInKey = key.match(re).length
59
+ if (noOfSlashInKey > 1) {
60
+ invalidMessageList.push('Key: Max 1 ( / ) allowed')
61
+ } else {
62
+ let name = key
63
+ if (noOfSlashInKey === 1) {
64
+ const [prefix, name]=key.split('/')
65
+
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ export const validateKubernetesValue = (value: string) => {}
@@ -0,0 +1,55 @@
1
+ import { PATTERNS } from '../Constants'
2
+
3
+ const validateTagValue = (value: string): string[] => {
4
+ const errorList = []
5
+ if (value.length > 63) {
6
+ errorList.push('Can be max 63 characters')
7
+ }
8
+ let firstLastAlphanumeric = PATTERNS.START_END_ALPHANUMERIC.test(value)
9
+ if (!firstLastAlphanumeric) {
10
+ errorList.push('Must start and end with an alphanumeric character')
11
+ }
12
+ let validValue = PATTERNS.ALPHANUMERIC_WITH_SPECIAL_CHAR.test(value)
13
+ if (!validValue) {
14
+ errorList.push('Can only contain alphanumeric chars and (-), (_), (.)')
15
+ }
16
+ return errorList
17
+ }
18
+ export class ValidationRules {
19
+
20
+ propagateTagKey = (key: string): { isValid: boolean; messages: string[] } => {
21
+ const errorList = []
22
+ if (!key) {
23
+ errorList.push('Key is required')
24
+ } else {
25
+ const re = new RegExp('/', 'g')
26
+ const noOfSlashInKey = key.match(re)?.length
27
+ if (noOfSlashInKey > 1) {
28
+ errorList.push('Key: Max 1 ( / ) allowed')
29
+ } else if (noOfSlashInKey === 1) {
30
+ const [prefix, name] = key.split('/')
31
+ errorList.push(...validateTagValue(name).map((error) => `Name: ${error}`))
32
+ if (prefix.length > 253) {
33
+ errorList.push('Prefix: Can be max 253 characters')
34
+ }
35
+ let validPrefix = PATTERNS.KUBERNETES_KEY_PREFIX.test(prefix)
36
+ if (!validPrefix) {
37
+ errorList.push('Prefix: Must be a DNS subdomain (a series of DNS labels separated by dots (.)')
38
+ }
39
+ } else {
40
+ errorList.push(...validateTagValue(key).map((error) => `Name: ${error}`))
41
+ }
42
+ }
43
+ return { isValid: errorList.length === 0, messages: errorList }
44
+ }
45
+
46
+ propagateTagValue = (value: string): { isValid: boolean; messages: string[] } => {
47
+ const errorList = []
48
+ if (!value) {
49
+ errorList.push('Value is required')
50
+ } else {
51
+ errorList.push(...validateTagValue(value))
52
+ }
53
+ return { isValid: errorList.length === 0, messages: errorList }
54
+ }
55
+ }
@@ -0,0 +1,2 @@
1
+ export * from './TagLabelSelect'
2
+ export * from './TagLabelValueSelector'
@@ -0,0 +1,32 @@
1
+ import React from 'react'
2
+ import { VisibleModal2 } from '../Modals/VisibleModal2'
3
+ function ConfirmationDialog({ className = '', children }) {
4
+ return (
5
+ <VisibleModal2 className="confirmation-dialog">
6
+ <div className={`confirmation-dialog__body ${className}`}>{children}</div>
7
+ </VisibleModal2>
8
+ )
9
+ }
10
+
11
+ function Icon({ src, className = '' }) {
12
+ return <img src={src} className={`confirmation-dialog__icon ${className}`} alt="" />
13
+ }
14
+
15
+ function Body({ title, subtitle = null, children = null }) {
16
+ return (
17
+ <div className="flex left column ">
18
+ <h3 className="confirmation-dialog__title lh-1-25 dc__break-word w-100">{title}</h3>
19
+ {subtitle && <div className="confirmation-dialog__subtitle">{subtitle}</div>}
20
+ {children}
21
+ </div>
22
+ )
23
+ }
24
+
25
+ function ButtonGroup({ children }) {
26
+ return <div className="flex right confirmation-dialog__button-group">{children}</div>
27
+ }
28
+
29
+ ConfirmationDialog.Icon = Icon
30
+ ConfirmationDialog.Body = Body
31
+ ConfirmationDialog.ButtonGroup = ButtonGroup
32
+ export default ConfirmationDialog
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import warn from '../../../Assets/Img/warning-medium.svg';
3
+ import { Progressing } from '../Progressing'
4
+ import ConfirmationDialog from './ConfirmationDialog';
5
+ import { DeleteDialogProps } from './Types';
6
+
7
+ export const DeleteDialog: React.FC<DeleteDialogProps> & { Description?: React.FC<any> } = function (props) {
8
+
9
+ return <ConfirmationDialog className="confirmation-dialog__body--w-400">
10
+ <ConfirmationDialog.Icon src={warn} />
11
+ <ConfirmationDialog.Body title={props.title}>
12
+ <div className="fs-13 cn-7 lh-1-54 w-100">
13
+ {props.description ? props.description : null}
14
+ {props.children}
15
+ </div>
16
+ </ConfirmationDialog.Body>
17
+ <ConfirmationDialog.ButtonGroup>
18
+ <div className="flex right">
19
+ <button type="button" className="cta cancel cta-cd-delete-modal ml-16" onClick={props.closeDelete} disabled={props.apiCallInProgress}>Cancel</button>
20
+ <button type="button" className="cta delete cta-cd-delete-modal ml-16" onClick={() => props.delete()} disabled={props.apiCallInProgress}>
21
+ {props.apiCallInProgress ? <Progressing /> : `${props.deletePrefix || ''}Delete${props.deletePostfix || ''}`}
22
+ </button>
23
+ </div>
24
+ </ConfirmationDialog.ButtonGroup>
25
+ </ConfirmationDialog >
26
+ }
27
+
28
+ function DeleteDialogDescription(props) {
29
+
30
+ return <>
31
+ {props.children}
32
+ </>
33
+ }
34
+
35
+ DeleteDialog.Description = DeleteDialogDescription;