@devtron-labs/devtron-fe-common-lib 0.0.6-beta-17 → 0.0.6-beta-18

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.6-beta-17",
3
+ "version": "0.0.6-beta-18",
4
4
  "description": "Supporting common component library",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -32,9 +32,11 @@
32
32
  "rollup-plugin-delete": "^2.0.0",
33
33
  "@svgr/rollup": "6.5.1",
34
34
  "@rollup/plugin-url": "8.0.1",
35
+ "@rollup/plugin-commonjs": "24.0.1",
35
36
  "typescript": "^4.9.4",
36
37
  "react-toastify": "^8.2.0",
37
38
  "@tippyjs/react": "^4.2.0",
39
+ "react-select": "^5.2.2",
38
40
  "@sentry/browser": "^7.31.1"
39
41
  },
40
42
  "peerDependencies": {
package/rollup.config.js CHANGED
@@ -7,13 +7,15 @@ import del from 'rollup-plugin-delete'
7
7
  import pkg from './package.json'
8
8
  import svgr from '@svgr/rollup'
9
9
  import url from '@rollup/plugin-url'
10
+ import commonjs from '@rollup/plugin-commonjs';
10
11
 
11
12
  export default {
12
13
  input: './src/index.ts',
13
- output: [{ file: pkg.main, format: 'es' }],
14
+ output: [{ file: pkg.main, format: 'cjs' }],
14
15
  plugins: [
15
16
  peerDepsExternal(),
16
17
  resolve(),
18
+ commonjs(),
17
19
  typescript(),
18
20
  postcss({
19
21
  extensions: ['.css'],
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28" width="24" height="24">
2
+ <g fill="none" fill-rule="evenodd" transform="translate(2 2)">
3
+ <rect width="20" height="20" fill="#B1B7BC" rx="10"/>
4
+ <path fill="#FFF" fill-rule="nonzero" d="M6.464 6.464a1 1 0 0 1 1.415 0l2.12 2.12 2.122-2.12a1 1 0 0 1 1.32-.083l.095.083a1 1 0 0 1 0 1.415l-2.122 2.12 2.122 2.122a1 1 0 0 1 .083 1.32l-.083.095a1 1 0 0 1-1.415 0L10 11.414l-2.121 2.122a1 1 0 0 1-1.32.083l-.095-.083a1 1 0 0 1 0-1.415L8.584 10l-2.12-2.121a1 1 0 0 1-.083-1.32z"/>
5
+ </g>
6
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <path stroke="#06C" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.898 12.564l4.95 4.95L19.455 6.906"/>
4
+ </g>
5
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="21" viewBox="0 0 20 21">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <path fill="#FDE7E7" stroke="#F33E3E" stroke-linejoin="round" stroke-width="2" d="M10 1.667C5.4 1.667 1.667 5.4 1.667 10S5.4 18.333 10 18.333 18.333 14.6 18.333 10 14.6 1.667 10 1.667z"/>
4
+ <path fill="#F33E3E" d="M10 10.833c.46 0 .833-.373.833-.833V6.667c0-.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"/>
5
+ </g>
6
+ </svg>
@@ -4,6 +4,6 @@ export const Host = process.env.REACT_APP_ORCHESTRATOR_ROOT
4
4
  export const PATTERNS = {
5
5
  KUBERNETES_KEY_PREFIX: /^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$/,
6
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]$/,
7
+ START_END_ALPHANUMERIC: /^([Az09].*[A-Za-z0-9])$|[A-Za-z0-9]$/,
8
8
  ALPHANUMERIC_WITH_SPECIAL_CHAR: /^[A-Za-z0-9._-]+$/, // allow alphanumeric,(.) ,(-),(_)
9
9
  }
@@ -13,25 +13,25 @@ export default function PropagateTagInfo() {
13
13
  )
14
14
  }
15
15
  return (
16
- <div className="flexbox">
17
- <InjectTag className="icon-dim-16 mt-2 mr-4" />
18
- <span>Propagate tags</span>
19
- <TippyCustomized
20
- theme={TippyTheme.white}
21
- className="w-300"
22
- placement="top"
23
- Icon={InjectTag}
24
- heading={'Propagate tags to K8s resources'}
25
- infoText={`Add a tag and click on the ⬡ icon to propagate tags as labels to Kubernetes resources.`}
26
- additionalContent={additionalInfo()}
27
- showCloseButton={true}
28
- trigger="click"
29
- interactive={true}
30
- documentationLink={''}
31
- documentationLinkText={'View Documentation'}
32
- >
16
+ <TippyCustomized
17
+ theme={TippyTheme.white}
18
+ className="w-300"
19
+ placement="top"
20
+ Icon={InjectTag}
21
+ heading={'Propagate tags to K8s resources'}
22
+ infoText={`Add a tag and click on the ⬡ icon to propagate tags as labels to Kubernetes resources.`}
23
+ additionalContent={additionalInfo()}
24
+ showCloseButton={true}
25
+ trigger="click"
26
+ interactive={true}
27
+ documentationLink={''}
28
+ documentationLinkText={'View Documentation'}
29
+ >
30
+ <div className="flexbox">
31
+ <InjectTag className="icon-dim-16 mt-2 mr-4" />
32
+ <span>Propagate tags</span>
33
33
  <Help className="icon-dim-16 mt-2 ml-4 cursor" />
34
- </TippyCustomized>
35
- </div>
34
+ </div>
35
+ </TippyCustomized>
36
36
  )
37
37
  }
@@ -4,12 +4,7 @@ import { ReactComponent as InjectTag } from '../../Assets/Icon/inject-tag.svg'
4
4
  import { TagDetailType } from '../Types'
5
5
  import { TagLabelValueSelector } from './TagLabelValueSelector'
6
6
 
7
- export default function TagDetails({
8
- index,
9
- tagData,
10
- setTagData,
11
- removeTag,
12
- }: TagDetailType) {
7
+ export default function TagDetails({ index, tagData, setTagData, removeTag }: TagDetailType) {
13
8
  const deleteTag = (): void => {
14
9
  removeTag(index)
15
10
  }
@@ -26,8 +21,20 @@ export default function TagDetails({
26
21
  >
27
22
  <InjectTag className={`icon-dim-20 mt-4 ${tagData.propagate ? 'scn-0' : ''}`} />
28
23
  </div>
29
- <TagLabelValueSelector selectedTagIndex={index} tagData={tagData} setTagData={setTagData} type="key" />
30
- <TagLabelValueSelector selectedTagIndex={index} tagData={tagData} setTagData={setTagData} type="value" />
24
+ <TagLabelValueSelector
25
+ selectedTagIndex={index}
26
+ tagData={tagData}
27
+ setTagData={setTagData}
28
+ type="key"
29
+ placeholder="Enter key"
30
+ />
31
+ <TagLabelValueSelector
32
+ selectedTagIndex={index}
33
+ tagData={tagData}
34
+ setTagData={setTagData}
35
+ type="value"
36
+ placeholder="Enter value"
37
+ />
31
38
  <div className="dc__border pl-4 pr-4 dc__right-radius-4 pointer" onClick={deleteTag}>
32
39
  <DeleteCross className="icon-dim-20 mt-4" />
33
40
  </div>
@@ -12,6 +12,7 @@ export const TagLabelValueSelector = ({
12
12
  tagOptions,
13
13
  isRequired,
14
14
  type,
15
+ placeholder,
15
16
  }: TagLabelValueSelectorType) => {
16
17
  const [selectedValue, setSelectedValue] = useState<string>('')
17
18
  const [isPopupOpen, togglePopup] = useState<boolean>(false)
@@ -58,7 +59,9 @@ export const TagLabelValueSelector = ({
58
59
  const renderValidationsSuggestions = (): JSX.Element => {
59
60
  let field = { isValid: true, messages: [] }
60
61
  if (type === 'key') {
61
- field = validationRules.propagateTagKey(selectedValue)
62
+ if (selectedValue || tagData.value || tagData.description) {
63
+ field = validationRules.propagateTagKey(selectedValue)
64
+ }
62
65
  } else if (isRequired || selectedValue) {
63
66
  field = validationRules.propagateTagValue(selectedValue)
64
67
  }
@@ -68,7 +71,7 @@ export const TagLabelValueSelector = ({
68
71
  {field.messages.map((error) => (
69
72
  <div key={error} className="flexbox p-4">
70
73
  <span>
71
- <ErrorCross className="icon-dim-14 scr-5 mt-3 mr-4" />
74
+ <ErrorCross className="fcr-5 mr-4" />
72
75
  </span>
73
76
  <span>{error}</span>
74
77
  </div>
@@ -76,7 +79,7 @@ export const TagLabelValueSelector = ({
76
79
  {type === 'key' && (
77
80
  <div className="flexbox p-4">
78
81
  <span>
79
- <Info className="icon-dim-14 mt-3 mr-4" />
82
+ <Info className="mr-4" />
80
83
  </span>
81
84
  <span className="dc__italic-font-style">Key format: prefix/name or name</span>
82
85
  </div>
@@ -110,7 +113,7 @@ export const TagLabelValueSelector = ({
110
113
  return (
111
114
  <PopupMenu onToggleCallback={(isOpen) => togglePopup(isOpen)} autoClose>
112
115
  <PopupMenu.Button
113
- rootClassName={`${
116
+ rootClassName={`h-32 ${
114
117
  type === 'key'
115
118
  ? `dc__no-right-radius`
116
119
  : `dc__no-border-radius dc__no-right-border dc__no-left-border`
@@ -122,6 +125,7 @@ export const TagLabelValueSelector = ({
122
125
  value={selectedValue}
123
126
  onChange={handleInputChange}
124
127
  onBlur={handleOnBlur}
128
+ placeholder={placeholder}
125
129
  />
126
130
  </PopupMenu.Button>
127
131
  <PopupMenu.Body rootClassName={`tag-${selectedTagIndex}-class`} autoWidth={true}>
@@ -0,0 +1,92 @@
1
+ import React, { CSSProperties } from 'react'
2
+ import { Link } from 'react-router-dom'
3
+ import './infoColourBar.scss'
4
+
5
+ interface InfoColourBarType {
6
+ message: React.ReactNode
7
+ classname: string
8
+ Icon
9
+ iconClass?: string
10
+ iconSize?: number // E.g. 16, 20, etc.. Currently, there are around 12 sizes supported. Check `icons.css` or `base.scss` for supported sizes or add new size (class names starts with `icon-dim-`).
11
+ renderActionButton?: () => JSX.Element
12
+ linkText?: React.ReactNode
13
+ redirectLink?: string
14
+ linkOnClick?: () => void
15
+ linkClass?: string
16
+ internalLink?: boolean
17
+ styles?: CSSProperties
18
+ }
19
+
20
+ function InfoColourBar({
21
+ message,
22
+ classname,
23
+ Icon,
24
+ iconClass,
25
+ iconSize,
26
+ renderActionButton,
27
+ linkText,
28
+ redirectLink,
29
+ linkOnClick,
30
+ linkClass,
31
+ internalLink,
32
+ styles,
33
+ }: InfoColourBarType) {
34
+ const renderLink = () => {
35
+ if (!linkText) {
36
+ return null
37
+ } else if (redirectLink) {
38
+ if (internalLink) {
39
+ return (
40
+ <Link
41
+ to={redirectLink}
42
+ onClick={linkOnClick}
43
+ className="cursor dc__link dc__underline-onhover mr-5"
44
+ >
45
+ {linkText}
46
+ </Link>
47
+ )
48
+ }
49
+
50
+ return (
51
+ <a
52
+ href={redirectLink}
53
+ target="_blank"
54
+ onClick={linkOnClick}
55
+ className="cursor dc__link dc__underline-onhover mr-5"
56
+ >
57
+ {linkText}
58
+ </a>
59
+ )
60
+ }
61
+
62
+ return (
63
+ linkOnClick && (
64
+ <div onClick={linkOnClick} className="cursor dc__link dc__underline-onhover">
65
+ {linkText}
66
+ </div>
67
+ )
68
+ )
69
+ }
70
+
71
+ return (
72
+ <div className="info-bar-container">
73
+ <div
74
+ className={`${classname} info_text flex dc__content-space pt-8 pb-8 pl-16 pr-16 br-4 top fs-13 fw-4`}
75
+ style={styles}
76
+ >
77
+ <div className={`flex top ${typeof renderActionButton === 'function' ? 'mr-5' : ''}`}>
78
+ <div className={`icon-dim-${iconSize ?? '20'} mr-10`}>
79
+ <Icon className={`icon-dim-${iconSize ?? '20'} ${iconClass || ''} mr-8`} />
80
+ </div>
81
+ <div className={`info-bar-message-wrapper ${linkClass || ''}`}>
82
+ <span className={linkText && redirectLink ? 'mr-5' : ''}>{message}</span>
83
+ {renderLink()}
84
+ </div>
85
+ </div>
86
+ {typeof renderActionButton === 'function' && renderActionButton()}
87
+ </div>
88
+ </div>
89
+ )
90
+ }
91
+
92
+ export default InfoColourBar
@@ -0,0 +1,28 @@
1
+ .info-bar-container {
2
+ .info_text .success {
3
+ background-color: var(--G100);
4
+ }
5
+ .warn {
6
+ background: var(--Y100);
7
+ border: solid var(--Y200);
8
+
9
+ .warning-icon path:nth-child(2) {
10
+ fill: var(--Y700);
11
+ }
12
+ }
13
+
14
+ .info_bar {
15
+ background-color: var(--B100);
16
+ border: 1px solid var(--B200);
17
+ }
18
+
19
+ .error_bar {
20
+ background-color: var(--R100);
21
+ border: 1px solid var(--R200);
22
+ }
23
+
24
+ .question-bar {
25
+ background-color: var(--V100);
26
+ border: 1px solid var(--V200);
27
+ }
28
+ }
@@ -0,0 +1,150 @@
1
+ import React from 'react'
2
+ import Select, { components } from 'react-select'
3
+ import { ReactComponent as ClearIcon } from '../Assets/Icon/ic-appstatus-cancelled.svg'
4
+ import { ReactComponent as Check } from '../Assets/Icon/ic-check.svg'
5
+ import { ReactComponent as RedWarning } from '../Assets/Icon/ic-error-medium.svg'
6
+
7
+ export const Option = (props) => {
8
+ const { selectOption, data } = props
9
+ return (
10
+ <div className="flex left pl-12" style={{ background: props.isFocused ? 'var(--N100)' : 'transparent' }}>
11
+ <input
12
+ checked={props.isSelected}
13
+ disabled={props.isDisabled}
14
+ onChange={(e) => selectOption(data)}
15
+ type="checkbox"
16
+ style={{ height: '16px', width: '16px', flex: '0 0 16px' }}
17
+ className="mr-8"
18
+ />
19
+ <components.Option {...props} />
20
+ </div>
21
+ )
22
+ }
23
+
24
+ export const SingleSelectOption = (props) => {
25
+ const { selectOption, data } = props
26
+ const style = { height: '16px', width: '16px', flex: '0 0 16px' }
27
+ const onClick = (e) => selectOption(data)
28
+ return (
29
+ <div className="flex left pl-12" style={{ background: props.isFocused ? 'var(--N100)' : 'transparent' }}>
30
+ {props.isSelected ? (
31
+ <Check onClick={onClick} className="mr-8 icon-dim-16" style={style} />
32
+ ) : (
33
+ <span onClick={onClick} className="mr-8" style={style} />
34
+ )}
35
+ <components.Option {...props} />
36
+ </div>
37
+ )
38
+ }
39
+
40
+ export const MultiValueContainer = (props) => {
41
+ const { children, data, innerProps, selectProps } = props
42
+ const { label, value } = data
43
+ return (
44
+ <components.MultiValueContainer {...{ data, innerProps, selectProps }}>
45
+ <div className={`flex fs-12 ml-4 cn-9`}>{label}</div>
46
+ {children[1]}
47
+ </components.MultiValueContainer>
48
+ )
49
+ }
50
+
51
+ export const ClearIndicator = (props) => {
52
+ const {
53
+ children = <ClearIcon className="icon-dim-24" />,
54
+ getStyles,
55
+ innerProps: { ref, ...restInnerProps },
56
+ } = props
57
+ return (
58
+ <div {...restInnerProps} ref={ref} style={getStyles('clearIndicator', props)}>
59
+ <div className="flex pointer">{children}</div>
60
+ </div>
61
+ )
62
+ }
63
+
64
+ export const MultiValueRemove = (props) => {
65
+ const {
66
+ data,
67
+ innerProps: { onClick, onMouseDown },
68
+ selectProps,
69
+ } = props
70
+ return (
71
+ <components.MultiValueRemove {...props}>
72
+ <ClearIcon
73
+ {...{ onClick, onMouseDown }}
74
+ onClick={(e) => onClick(data)}
75
+ style={{ height: '18px', width: '18px' }}
76
+ />
77
+ </components.MultiValueRemove>
78
+ )
79
+ }
80
+
81
+ export const MultiValueChipContainer = ({ validator, isAllSelected = false, ...props }) => {
82
+ const { children, data, innerProps, selectProps } = props
83
+ const { label, value } = data
84
+ const isValidEmail = validator ? validator(value) : true
85
+
86
+ if(isAllSelected && value !== '*') return null
87
+
88
+ return (
89
+ <components.MultiValueContainer {...{ data, innerProps, selectProps }}>
90
+ <div className={`flex fs-12 pl-4 pr-4`}>
91
+ {!isValidEmail && <RedWarning className="mr-4 icon-dim-16" />}
92
+ <div className={`${isValidEmail ? 'cn-9' : 'cr-5'}`}>{label}</div>
93
+ </div>
94
+ {children[1]}
95
+ </components.MultiValueContainer>
96
+ )
97
+ }
98
+
99
+ export const multiSelectStyles = {
100
+ control: (base, state) => ({
101
+ ...base,
102
+ cursor: state.isDisabled ? 'not-allowed' : 'normal',
103
+ border: state.isFocused ? '1px solid #06c' : '1px solid #d6dbdf',
104
+ boxShadow: 'none',
105
+ minheight: '24px !important'
106
+ }),
107
+ menu: (base, state) => ({
108
+ ...base,
109
+ top: `40px`,
110
+ }),
111
+ option: (base, state) => {
112
+ return ({
113
+ ...base,
114
+ backgroundColor: state.isFocused ? 'var(--N100)' : 'white',
115
+ color: 'var(--N900)',
116
+ padding: '8px 12px',
117
+ })
118
+ },
119
+ container: (base, state) => ({
120
+ ...base,
121
+ cursor: state.isDisabled ? 'not-allowed' : 'normal'
122
+ }),
123
+ valueContainer: (base, state) => ({
124
+ ...base,
125
+ color: state.selectProps.menuIsOpen ? 'var(--N500)' : base.color,
126
+ }),
127
+ }
128
+
129
+ interface CustomSelect {
130
+ sortSelected?: boolean
131
+ options: any[]
132
+ onChange: (...args) => void
133
+ value?: any
134
+ name?: string
135
+ placeholder?: string
136
+ className?: string
137
+ classNamePrefix?: string
138
+ menuPortalTarget?: any
139
+ components?: object
140
+ styles?: object
141
+ isMulti?: boolean
142
+ isDisabled?: boolean
143
+ closeMenuOnSelect?: boolean
144
+ hideSelectedOptions?: boolean
145
+ formatOptionLabel?: (...args) => any
146
+ }
147
+
148
+ export const CustomSelect: React.FC<CustomSelect> = (props) => {
149
+ return <Select {...props} />
150
+ }
@@ -18,6 +18,7 @@ export interface TagType {
18
18
  value?: string
19
19
  description?: string
20
20
  propagate: boolean
21
+ mandatoryProjectIdsCsv?: string[]
21
22
  isInvalidKey?: boolean
22
23
  isInvalidValue?: boolean
23
24
  }
@@ -51,4 +52,5 @@ export interface TagLabelValueSelectorType {
51
52
  tagOptions?: OptionType[]
52
53
  isRequired?: boolean
53
54
  type?: string
55
+ placeholder?: string
54
56
  }
@@ -19,4 +19,6 @@ export * from './RadioGroup'
19
19
  export { default as PopupMenu } from './PopupMenu'
20
20
  export * from './TippyCustomized'
21
21
  export * from './CustomTagSelector'
22
- export * from './Dialogs'
22
+ export * from './Dialogs'
23
+ export * from './MultiSelectCustomization'
24
+ export * from './InfoColorBar/InfoColourbar'