Skip to content

Commit 8e47a1c

Browse files
Merge pull request #392 from devtron-labs/release-candidate-v0.22.0
release: Release candidate v0.22.0
2 parents 627f85d + 58f92af commit 8e47a1c

26 files changed

+500
-187
lines changed

package-lock.json

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "0.6.0-patch-1",
3+
"version": "0.6.5",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",
@@ -84,7 +84,6 @@
8484
"react-draggable": "^4.4.5",
8585
"react-ga4": "^1.4.1",
8686
"react-mde": "^11.5.0",
87-
"react-router": "^5.3.0",
8887
"react-router-dom": "^5.3.0",
8988
"react-select": "5.8.0",
9089
"rxjs": "^7.8.1",

src/Common/Constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export const URLS = {
6666
GLOBAL_CONFIG_SCOPED_VARIABLES: '/global-config/scoped-variables',
6767
GLOBAL_CONFIG_DEPLOYMENT_CHARTS_LIST: '/global-config/deployment-charts',
6868
NETWORK_STATUS_INTERFACE: '/network-status-interface',
69+
CONFIG_DRIFT: 'config-drift',
6970
}
7071

7172
export const ROUTES = {

src/Common/Hooks/useUrlFilters/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export interface UseUrlFiltersProps<T, K> {
2525
* Callback function for parsing the search params
2626
*/
2727
parseSearchParams?: (searchParams: URLSearchParams) => K
28+
localStorageKey?: `${string}__${string}`
2829
}
2930

3031
export type UseUrlFiltersReturnType<T, K = unknown> = K & {

src/Common/Hooks/useUrlFilters/useUrlFilters.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { useMemo } from 'react'
17+
import { useEffect, useMemo } from 'react'
1818
import { useHistory, useLocation } from 'react-router-dom'
1919
import { DEFAULT_BASE_PAGE_SIZE, EXCLUDED_FALSY_VALUES, SortingOrder } from '../../Constants'
2020
import { DEFAULT_PAGE_NUMBER, URL_FILTER_KEYS } from './constants'
2121
import { UseUrlFiltersProps, UseUrlFiltersReturnType } from './types'
22+
import { setItemInLocalStorageIfKeyExists } from './utils'
2223

2324
const { PAGE_SIZE, PAGE_NUMBER, SEARCH_KEY, SORT_BY, SORT_ORDER } = URL_FILTER_KEYS
2425

@@ -42,11 +43,20 @@ const { PAGE_SIZE, PAGE_NUMBER, SEARCH_KEY, SORT_BY, SORT_ORDER } = URL_FILTER_K
4243
const useUrlFilters = <T = string, K = unknown>({
4344
initialSortKey,
4445
parseSearchParams,
46+
localStorageKey,
4547
}: UseUrlFiltersProps<T, K> = {}): UseUrlFiltersReturnType<T, K> => {
4648
const location = useLocation()
4749
const history = useHistory()
4850
const searchParams = new URLSearchParams(location.search)
4951

52+
const getParsedSearchParams: UseUrlFiltersProps<T, K>['parseSearchParams'] = (searchParamsToParse) => {
53+
if (parseSearchParams) {
54+
return parseSearchParams(searchParamsToParse)
55+
}
56+
57+
return {} as K
58+
}
59+
5060
const { pageSize, pageNumber, searchKey, sortBy, sortOrder, parsedParams } = useMemo(() => {
5161
const _pageSize = searchParams.get(PAGE_SIZE)
5262
const _pageNumber = searchParams.get(PAGE_NUMBER)
@@ -58,7 +68,7 @@ const useUrlFilters = <T = string, K = unknown>({
5868
// Fallback to ascending order
5969
const sortByOrder = Object.values(SortingOrder).includes(_sortOrder) ? _sortOrder : SortingOrder.ASC
6070

61-
const _parsedParams = parseSearchParams ? parseSearchParams(searchParams) : ({} as K)
71+
const _parsedParams = getParsedSearchParams(searchParams)
6272

6373
return {
6474
pageSize: Number(_pageSize) || DEFAULT_BASE_PAGE_SIZE,
@@ -126,6 +136,7 @@ const useUrlFilters = <T = string, K = unknown>({
126136

127137
const clearFilters = () => {
128138
history.replace({ search: '' })
139+
setItemInLocalStorageIfKeyExists(localStorageKey, '')
129140
}
130141

131142
const updateSearchParams = (paramsToSerialize: Partial<K>) => {
@@ -143,10 +154,24 @@ const useUrlFilters = <T = string, K = unknown>({
143154
searchParams.delete(key)
144155
}
145156
})
157+
// Skipping primary params => pageSize, pageNumber, searchKey, sortBy, sortOrder
158+
setItemInLocalStorageIfKeyExists(localStorageKey, JSON.stringify(getParsedSearchParams(searchParams)))
146159
// Not replacing the params as it is being done by _resetPageNumber
147160
_resetPageNumber()
148161
}
149162

163+
useEffect(() => {
164+
// if we have search string, set secondary params in local storage accordingly
165+
if (location.search) {
166+
localStorage.setItem(localStorageKey, JSON.stringify(parsedParams))
167+
return
168+
}
169+
const localStorageValue = localStorage.getItem(localStorageKey)
170+
if (localStorageValue) {
171+
updateSearchParams(JSON.parse(localStorageValue))
172+
}
173+
}, [])
174+
150175
return {
151176
pageSize,
152177
changePage,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const setItemInLocalStorageIfKeyExists = (localStorageKey: string, value: string) => {
2+
if (localStorageKey) {
3+
localStorage.setItem(localStorageKey, value)
4+
}
5+
}

src/Common/SortableTableHeaderCell/SortableTableHeaderCell.tsx

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
*/
1616

1717
import { Tooltip } from '@Common/Tooltip'
18-
import { ReactComponent as SortIcon } from '../../Assets/Icon/ic-arrow-up-down.svg'
19-
import { ReactComponent as SortArrowDown } from '../../Assets/Icon/ic-sort-arrow-down.svg'
18+
import Draggable, { DraggableProps } from 'react-draggable'
19+
import { ReactComponent as SortIcon } from '@Icons/ic-arrow-up-down.svg'
20+
import { ReactComponent as SortArrowDown } from '@Icons/ic-sort-arrow-down.svg'
2021
import { SortingOrder } from '../Constants'
2122
import { noop } from '../Helper'
2223
import { SortableTableHeaderCellProps } from './types'
24+
import './sortableTableHeaderCell.scss'
2325

2426
/**
2527
* Reusable component for the table header cell with support for sorting icons
@@ -34,6 +36,23 @@ import { SortableTableHeaderCellProps } from './types'
3436
* disabled={isDisabled}
3537
* />
3638
* ```
39+
*
40+
* @example Non-sortable cell
41+
* ```tsx
42+
* <SortableTableHeaderCell
43+
* isSortable={false}
44+
* title="Header Cell"
45+
* />
46+
* ```
47+
*
48+
* * @example Resizable cell (Layout to be controlled externally using useResizableTableConfig)
49+
* ```tsx
50+
* <SortableTableHeaderCell
51+
* isSortable={false}
52+
* isResizable
53+
* title="Header Cell"
54+
* />
55+
* ```
3756
*/
3857
const SortableTableHeaderCell = ({
3958
isSorted,
@@ -43,7 +62,12 @@ const SortableTableHeaderCell = ({
4362
disabled,
4463
isSortable = true,
4564
showTippyOnTruncate = false,
65+
id,
66+
handleResize,
67+
isResizable,
4668
}: SortableTableHeaderCellProps) => {
69+
const isCellResizable = !!(isResizable && id && handleResize)
70+
4771
const renderSortIcon = () => {
4872
if (!isSortable) {
4973
return null
@@ -60,18 +84,46 @@ const SortableTableHeaderCell = ({
6084
return <SortIcon className="icon-dim-12 mw-12 scn-7 dc__no-shrink" />
6185
}
6286

87+
const handleDrag: DraggableProps['onDrag'] = (_, data) => {
88+
if (isCellResizable) {
89+
handleResize(id, data.deltaX)
90+
}
91+
}
92+
6393
return (
64-
<button
65-
type="button"
66-
className={`dc__transparent p-0 cn-7 flex dc__content-start dc__gap-4 dc__select-text ${!isSortable ? 'cursor-default' : ''}`}
67-
onClick={isSortable ? triggerSorting : noop}
68-
disabled={disabled}
69-
>
70-
<Tooltip showOnTruncate={showTippyOnTruncate} content={title}>
71-
<span className="dc__uppercase dc__ellipsis-right">{title}</span>
72-
</Tooltip>
73-
{renderSortIcon()}
74-
</button>
94+
<div className="flex dc__content-space dc__gap-6 dc__position-rel">
95+
<button
96+
type="button"
97+
className={`dc__transparent p-0 cn-7 flex dc__content-start dc__gap-4 dc__select-text ${!isSortable ? 'cursor-default' : ''} dc__position-rel`}
98+
onClick={isSortable ? triggerSorting : noop}
99+
disabled={disabled}
100+
>
101+
<Tooltip showOnTruncate={showTippyOnTruncate} content={title}>
102+
<span className="dc__uppercase dc__truncate">{title}</span>
103+
</Tooltip>
104+
{renderSortIcon()}
105+
</button>
106+
{isCellResizable && (
107+
<Draggable
108+
handle=".sortable-table-header__resize-btn"
109+
defaultClassNameDragging="sortable-table-header__resize-btn--dragging"
110+
position={{
111+
x: 0,
112+
y: 0,
113+
}}
114+
axis="none"
115+
onDrag={handleDrag}
116+
bounds={{
117+
top: 0,
118+
bottom: 0,
119+
}}
120+
>
121+
<div className="sortable-table-header__resize-btn flex h-100 dc__no-shrink px-2 dc__position-abs dc__cursor-col-resize dc__right-3--neg">
122+
<div className="dc__divider h-16" />
123+
</div>
124+
</Draggable>
125+
)}
126+
</div>
75127
)
76128
}
77129

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const DEFAULT_MINIMUM_HEADER_WIDTH = 70
2+
3+
export const DEFAULT_MAXIMUM_HEADER_WIDTH = 600

src/Common/SortableTableHeaderCell/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@
1515
*/
1616

1717
export { default as SortableTableHeaderCell } from './SortableTableHeaderCell'
18+
export { default as useResizableTableConfig } from './useResizableTableConfig'
1819
export type { SortableTableHeaderCellProps } from './types'
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.sortable-table-header {
2+
&__resize-btn {
3+
> div {
4+
transition: all 0.1s ease-out;
5+
}
6+
7+
&:hover, &--dragging {
8+
> div {
9+
height: 100% !important;
10+
background-color: var(--B500);
11+
}
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)