@devtron-labs/devtron-fe-common-lib 0.0.26-beta-3 → 0.0.26-beta1

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.26-beta-3",
3
+ "version": "0.0.26-beta1",
4
4
  "description": "Supporting common component library",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -326,7 +326,7 @@ export function CustomInput({
326
326
  tabIndex={tabIndex}
327
327
  />
328
328
  {handleError(error).map((err) => (
329
- <div className="form__error">
329
+ <div className="form__error" key={err}>
330
330
  <FormError className="form__icon form__icon--error" />
331
331
  {err}
332
332
  </div>
@@ -27,6 +27,7 @@ export interface ImageTaggingContainerType {
27
27
  setTagsEditable?: (tagsEditable: boolean) => void
28
28
  toggleCardMode?: (id: number) => void
29
29
  hideHardDelete?: boolean
30
+ isSuperAdmin?: boolean
30
31
  }
31
32
 
32
33
  export interface ImageButtonType {
@@ -32,6 +32,7 @@ export const ImageTagsContainer = ({
32
32
  toggleCardMode,
33
33
  hideHardDelete,
34
34
  forceReInit,
35
+ isSuperAdmin
35
36
  }: ImageTaggingContainerType) => {
36
37
  const [initialTags, setInitialTags] = useState<ReleaseTag[]>(imageReleaseTags ? imageReleaseTags : [])
37
38
  const [initialDescription, setInitialDescription] = useState(imageComment ? imageComment.comment : '')
@@ -44,13 +45,9 @@ export const ImageTagsContainer = ({
44
45
  const [createTags, setCreateTags] = useState<ReleaseTag[]>([])
45
46
  const [softDeleteTags, setSoftDeleteTags] = useState<ReleaseTag[]>([])
46
47
  const [hardDeleteTags, setHardDeleteTags] = useState<ReleaseTag[]>([])
47
- const [isSuperAdmin, setSuperAdmin] = useState<boolean>(false)
48
48
  const [descriptionValidationMessage, setDescriptionValidationMessage] = useState<string>('')
49
49
  const [textInput, setTextInput] = useState<string>('')
50
50
 
51
- useEffect(() => {
52
- initialise()
53
- }, [])
54
51
 
55
52
  useEffect(() => {
56
53
  reInitState()
@@ -60,16 +57,6 @@ export const ImageTagsContainer = ({
60
57
  setExistingTags(appReleaseTagNames ? appReleaseTagNames : [])
61
58
  }, [appReleaseTagNames])
62
59
 
63
- async function initialise() {
64
- try {
65
- const userRole = await getUserRole()
66
-
67
- const superAdmin = userRole?.result?.roles?.includes('role:super-admin___')
68
- setSuperAdmin(superAdmin)
69
- } catch (err) {
70
- showError(err)
71
- }
72
- }
73
60
 
74
61
  const reInitState = () => {
75
62
  if (forceReInit || !isEditing) {
@@ -34,6 +34,4 @@ export * from './Policy.Types'
34
34
  export { default as DeleteComponent } from './DeleteComponentModal/DeleteComponent'
35
35
  export * from './ImageTags'
36
36
  export * from './ImageTags.Types'
37
- export * from './ResizableTextarea'
38
- export { default as DebouncedSearch } from './DebouncedSearch/DebouncedSearch'
39
- export { default as Grid } from './Grid/Grid'
37
+ export * from './ResizableTextarea'
@@ -1,15 +0,0 @@
1
- /// <reference types="react" />
2
- import { DebouncedSearchProps } from './Types';
3
- /**
4
- * @param onSearch - Callback function to be called on search
5
- * @param Icon - (Optional) Icon to be shown before the input
6
- * @param iconClass - (Optional) Class for the icon
7
- * @param children - (Optional) In case we want to add another button or any other element
8
- * @param placeholder - (Optional) Placeholder for the input
9
- * @param containerClass - (Optional) Class for the container
10
- * @param inputClass - (Optional) Class for the input field
11
- * @param debounceTimeout - (Optional) Timeout for the debounce with default value of 500ms
12
- * @param clearSearch - (Optional) To clear the search text
13
- * @param showClearIcon - (Optional) To show the clear icon default value is true
14
- */
15
- export default function DebouncedSearch({ onSearch, Icon, children, placeholder, containerClass, iconClass, inputClass, debounceTimeout, clearSearch, showClearIcon, }: DebouncedSearchProps): JSX.Element;
@@ -1,13 +0,0 @@
1
- /// <reference types="react" />
2
- export interface DebouncedSearchProps {
3
- onSearch: (query: string) => void;
4
- Icon?: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
5
- placeholder?: string;
6
- inputClass?: string;
7
- containerClass?: string;
8
- iconClass?: string;
9
- children?: React.ReactNode;
10
- debounceTimeout?: number;
11
- clearSearch?: boolean;
12
- showClearIcon?: boolean;
13
- }
@@ -1 +0,0 @@
1
- export declare function useDebouncedEffect(callback: any, delay: any, deps?: unknown[]): void;
@@ -1,3 +0,0 @@
1
- /// <reference types="react" />
2
- import { GridProps } from './types';
3
- export default function Grid({ container, spacing, item, xs, containerClass, itemClass, children, }: GridProps): JSX.Element;
@@ -1,10 +0,0 @@
1
- /// <reference types="react" />
2
- export interface GridProps {
3
- container?: boolean;
4
- spacing?: number;
5
- item?: boolean;
6
- xs?: number;
7
- containerClass?: string;
8
- itemClass?: string;
9
- children?: React.ReactNode;
10
- }
@@ -1,8 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
2
- <g fill="none" fill-rule="evenodd">
3
- <g transform="translate(2.667 2.667)">
4
- <rect width="26.667" height="26.667" class="fill-color" fill="#596168" rx="13.333"/>
5
- <path fill="#FFF" fill-rule="nonzero" d="M8.62 8.62c.52-.521 1.364-.521 1.885 0l2.828 2.827 2.829-2.828a1.334 1.334 0 0 1 1.777-.097l.108.097c.521.521.521 1.365 0 1.886l-2.828 2.828 2.828 2.829c.486.486.519 1.254.098 1.777l-.098.108c-.52.521-1.365.521-1.885 0l-2.83-2.828-2.827 2.828a1.334 1.334 0 0 1-1.777.098l-.109-.098a1.333 1.333 0 0 1 0-1.885l2.828-2.83-2.828-2.827a1.334 1.334 0 0 1-.097-1.777z"/>
6
- </g>
7
- </g>
8
- </svg>
@@ -1,75 +0,0 @@
1
- import React, { useEffect, useState } from 'react'
2
- import { useDebouncedEffect } from './Utils'
3
- import { ReactComponent as ICClear } from '../../Assets/Icon/ic-error-cross.svg'
4
- import { DebouncedSearchProps } from './Types'
5
-
6
- /**
7
- * @param onSearch - Callback function to be called on search
8
- * @param Icon - (Optional) Icon to be shown before the input
9
- * @param iconClass - (Optional) Class for the icon
10
- * @param children - (Optional) In case we want to add another button or any other element
11
- * @param placeholder - (Optional) Placeholder for the input
12
- * @param containerClass - (Optional) Class for the container
13
- * @param inputClass - (Optional) Class for the input field
14
- * @param debounceTimeout - (Optional) Timeout for the debounce with default value of 500ms
15
- * @param clearSearch - (Optional) To clear the search text
16
- * @param showClearIcon - (Optional) To show the clear icon default value is true
17
- */
18
- export default function DebouncedSearch({
19
- onSearch,
20
- Icon,
21
- children,
22
- placeholder,
23
- containerClass = '',
24
- iconClass = '',
25
- inputClass = '',
26
- debounceTimeout = 500,
27
- clearSearch,
28
- showClearIcon = true,
29
- }: DebouncedSearchProps) {
30
- const [searchText, setSearchText] = useState<string>('')
31
-
32
- useEffect(() => {
33
- setSearchText('')
34
- }, [clearSearch])
35
-
36
- const handleSearchTextChange = (e: React.ChangeEvent<HTMLInputElement>) => {
37
- setSearchText(e.target.value)
38
- }
39
-
40
- const handleClearSearch = () => {
41
- setSearchText('')
42
- }
43
-
44
- useDebouncedEffect(() => onSearch(searchText), debounceTimeout, [searchText, onSearch])
45
-
46
- return (
47
- <div className={containerClass}>
48
- {Icon && <Icon className={iconClass} />}
49
-
50
- <input
51
- type="text"
52
- className={inputClass}
53
- placeholder={placeholder ?? 'Search'}
54
- value={searchText}
55
- onChange={handleSearchTextChange}
56
- autoFocus
57
- data-testid="debounced-search"
58
- />
59
-
60
- {showClearIcon && !!searchText && (
61
- <button
62
- type="button"
63
- className="dc__outline-none-imp dc__no-border p-0 bc-n50 flex"
64
- onClick={handleClearSearch}
65
- data-testid="clear-search"
66
- >
67
- <ICClear className="icon-dim-20 icon-n6" />
68
- </button>
69
- )}
70
-
71
- {/* In case we want to add another button or something */}
72
- {children}
73
- </div>
74
- )
75
- }
@@ -1,12 +0,0 @@
1
- export interface DebouncedSearchProps {
2
- onSearch: (query: string) => void
3
- Icon?: React.FunctionComponent<React.SVGProps<SVGSVGElement>>
4
- placeholder?: string
5
- inputClass?: string
6
- containerClass?: string
7
- iconClass?: string
8
- children?: React.ReactNode
9
- debounceTimeout?: number
10
- clearSearch?: boolean
11
- showClearIcon?: boolean
12
- }
@@ -1,19 +0,0 @@
1
- import { useEffect, useRef } from 'react'
2
-
3
- export function useDebouncedEffect(callback, delay, deps: unknown[] = []) {
4
- // function will be executed only after the specified time once the user stops firing the event.
5
- const firstUpdate = useRef(true)
6
- useEffect(() => {
7
- if (firstUpdate.current) {
8
- firstUpdate.current = false
9
- return
10
- }
11
- const handler = setTimeout(() => {
12
- callback()
13
- }, delay)
14
-
15
- return () => {
16
- clearTimeout(handler)
17
- }
18
- }, [delay, ...deps])
19
- }
@@ -1,61 +0,0 @@
1
- import React from 'react'
2
- import { render, screen, fireEvent } from '@testing-library/react'
3
- import { ReactComponent as ICClear } from '../../../../assets/icons/ic-error.svg'
4
- import DebouncedSearch from '../DebouncedSearch'
5
-
6
- jest.mock('../../helpers/Helpers', () => ({
7
- useDebouncedEffect: jest.fn().mockImplementation((fn) => fn()),
8
- }))
9
-
10
- describe('When DebouncedSearch mounts', () => {
11
- it('should have a input field', () => {
12
- render(<DebouncedSearch onSearch={jest.fn()} />)
13
- expect(screen.getByRole('textbox')).toBeTruthy()
14
- })
15
-
16
- it('should have a clear icon when clearSearch is true and user has typed something', () => {
17
- const { getByTestId } = render(<DebouncedSearch onSearch={jest.fn()} clearSearch debounceTimeout={0} />)
18
- fireEvent.change(screen.getByRole('textbox'), { target: { value: 'test' } })
19
- expect(getByTestId('clear-search')).toBeTruthy()
20
- })
21
-
22
- it('should call onSearch when input value changes', () => {
23
- const onSearch = jest.fn()
24
- render(<DebouncedSearch onSearch={onSearch} debounceTimeout={0} />)
25
- fireEvent.change(screen.getByRole('textbox'), { target: { value: 'test' } })
26
- expect(onSearch).toHaveBeenCalled()
27
- })
28
-
29
- it('should clear input value when clear icon is clicked', () => {
30
- const { container } = render(<DebouncedSearch onSearch={jest.fn()} clearSearch debounceTimeout={0} />)
31
- fireEvent.change(screen.getByRole('textbox'), { target: { value: 'test' } })
32
- const inputBar = container.querySelector('input')
33
- expect(inputBar.value).toBe('test')
34
- fireEvent.click(screen.getByRole('button'))
35
- expect(inputBar.value).toBe('')
36
- })
37
-
38
- it('should have a placeholder', () => {
39
- render(<DebouncedSearch onSearch={jest.fn()} placeholder="test" />)
40
- expect(screen.getByPlaceholderText('test')).toBeTruthy()
41
- })
42
-
43
- it('should not show clear icon when showClearIcon is false', () => {
44
- render(<DebouncedSearch onSearch={jest.fn()} showClearIcon={false} />)
45
- expect(screen.queryByRole('button')).toBeNull()
46
- })
47
-
48
- it('should have a custom Icon', () => {
49
- const { container } = render(<DebouncedSearch onSearch={jest.fn()} Icon={ICClear} iconClass="icon-class" />)
50
- expect(container.querySelector('.icon-class')).toBeTruthy()
51
- })
52
-
53
- it('should support children', () => {
54
- render(
55
- <DebouncedSearch onSearch={jest.fn()}>
56
- <div>test</div>
57
- </DebouncedSearch>,
58
- )
59
- expect(screen.getByText('test')).toBeTruthy()
60
- })
61
- })
@@ -1,39 +0,0 @@
1
- import React from 'react'
2
- import { GridProps } from './types'
3
-
4
- // This is meant to be a reusable component that will provide a grid like dynamic layout where xs is the number of columns out of 12 that the item will take up
5
- export default function Grid({
6
- container,
7
- spacing = 0,
8
- item,
9
- xs,
10
- containerClass = '',
11
- itemClass = '',
12
- children,
13
- }: GridProps) {
14
- const containerStyles = container ? { gap: spacing + 'px' } : {}
15
-
16
- if (item) {
17
- const getColumnWidth = () => {
18
- const percentageWidth = (xs / 12) * 100
19
- // DONT CHANGE IT FROM CALC SINCE CALC CONVERTS TO PX which is needed to handle text overflow
20
- return `calc(${percentageWidth}%)`
21
- }
22
-
23
- const itemStyles = {
24
- flex: `1 1 ${getColumnWidth()}`,
25
- }
26
-
27
- return (
28
- <div className={`p-0 ${itemClass}`} style={itemStyles}>
29
- {children}
30
- </div>
31
- )
32
- }
33
-
34
- return (
35
- <div className={`flex-wrap flexbox ${container ? containerClass : ''}`} style={containerStyles}>
36
- {children}
37
- </div>
38
- )
39
- }
@@ -1,9 +0,0 @@
1
- export interface GridProps {
2
- container?: boolean
3
- spacing?: number
4
- item?: boolean
5
- xs?: number
6
- containerClass?: string
7
- itemClass?: string
8
- children?: React.ReactNode
9
- }