Skip to content

Commit 3afb1a1

Browse files
committed
RI-6336 - Allow to hide/show columns in Browser - basic functional implementation
1 parent 5502c95 commit 3afb1a1

File tree

10 files changed

+135
-20
lines changed

10 files changed

+135
-20
lines changed

redisinsight/api/src/modules/browser/keys/dto/get.keys-info.dto.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { IsRedisString, RedisStringType } from 'src/common/decorators';
44
import { RedisString } from 'src/common/constants';
55
import { KeyDto, RedisDataType } from './key.dto';
66

7-
export class GetKeyInfoDto extends KeyDto {}
7+
export class GetKeyInfoDto extends KeyDto { }
88

99
export class GetKeysInfoDto {
1010
@ApiProperty({
@@ -31,4 +31,20 @@ export class GetKeysInfoDto {
3131
})
3232
@IsOptional()
3333
type?: RedisDataType;
34+
35+
@ApiPropertyOptional({
36+
description: 'Flag to determine if keys should be requested and shown in the response',
37+
type: Boolean,
38+
default: true,
39+
})
40+
@IsOptional()
41+
getSize?: boolean;
42+
43+
@ApiPropertyOptional({
44+
description: 'Flag to determine if TTL should be requested and shown in the response',
45+
type: Boolean,
46+
default: true,
47+
})
48+
@IsOptional()
49+
getTtl?: boolean;
3450
}

redisinsight/api/src/modules/browser/keys/keys.service.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class KeysService {
4141
private readonly keyInfoProvider: KeyInfoProvider,
4242
private readonly browserHistory: BrowserHistoryService,
4343
private readonly recommendationService: DatabaseRecommendationService,
44-
) {}
44+
) { }
4545

4646
public async getKeys(
4747
clientMetadata: ClientMetadata,
@@ -103,7 +103,8 @@ export class KeysService {
103103
try {
104104
const client = await this.databaseClientFactory.getOrCreateClient(clientMetadata);
105105
const scanner = this.scanner.getStrategy(client.getConnectionType());
106-
const result = await scanner.getKeysInfo(client, dto.keys, dto.type);
106+
console.log('getKeysInfo', dto, client.getConnectionType(), clientMetadata);
107+
const result = await scanner.getKeysInfo(client, dto.keys, dto.type, dto.getSize, dto.getTtl);
107108

108109
this.recommendationService.check(
109110
clientMetadata,

redisinsight/api/src/modules/browser/keys/scanner/scanner.interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@ export interface IScannerStrategy {
3131
*/
3232
getKeys(client: RedisClient, args: IScannerGetKeysArgs): Promise<IScannerNodeKeys[]>;
3333

34-
getKeysInfo(client: RedisClient, keys: RedisString[], type?: RedisDataType): Promise<GetKeyInfoResponse[]>;
34+
getKeysInfo(client: RedisClient, keys: RedisString[], type?: RedisDataType, getSize?: boolean, getTtl?: boolean): Promise<GetKeyInfoResponse[]>;
3535
}

redisinsight/api/src/modules/browser/keys/scanner/strategies/scanner.strategy.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,7 @@ export abstract class ScannerStrategy implements IScannerStrategy {
1616
client: RedisClient,
1717
keys: RedisString[],
1818
filterType?: RedisDataType,
19+
getSize?: boolean,
20+
getTtl?: boolean,
1921
): Promise<GetKeyInfoResponse[]>;
2022
}

redisinsight/api/src/modules/browser/keys/scanner/strategies/standalone.scanner.strategy.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,19 +162,33 @@ export class StandaloneScannerStrategy extends ScannerStrategy {
162162
client: RedisClient,
163163
keys: RedisString[],
164164
filterType?: RedisDataType,
165+
getSize?: boolean,
166+
getTtl?: boolean,
165167
): Promise<GetKeyInfoResponse[]> {
166-
const sizeResults = await this.getKeysSize(client, keys);
168+
console.log('getKeysInfo', keys, filterType, getSize, getTtl);
169+
const sizeResults = getSize ? await this.getKeysSize(client, keys) : [];
167170
const typeResults = filterType
168171
? Array(keys.length).fill(filterType)
169172
: await this.getKeysType(client, keys);
170-
const ttlResults = await this.getKeysTtl(client, keys);
173+
const ttlResults = getTtl ? await this.getKeysTtl(client, keys) : [];
174+
console.log('sizeResults', sizeResults);
175+
console.log('typeResults', typeResults);
176+
console.log('ttlResults', ttlResults);
171177
return keys.map(
172-
(key: string, index: number): GetKeyInfoResponse => ({
173-
name: key,
174-
type: typeResults[index],
175-
ttl: ttlResults[index],
176-
size: sizeResults[index],
177-
}),
178+
(key: string, index: number): GetKeyInfoResponse => {
179+
const data: GetKeyInfoResponse = {
180+
name: key,
181+
type: typeResults[index],
182+
}
183+
console.log('data bgetTtl', getTtl);
184+
if (getTtl) {
185+
data.ttl = ttlResults[index];
186+
}
187+
if (getSize) {
188+
data.size = sizeResults[index];
189+
}
190+
return data;
191+
},
178192
);
179193
}
180194
}
Lines changed: 3 additions & 0 deletions
Loading

redisinsight/ui/src/pages/browser/components/keys-header/KeysHeader.tsx

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
/* eslint-disable react/destructuring-assignment */
22
/* eslint-disable react/no-this-in-sfc */
3-
import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'
3+
import { EuiButton, EuiButtonIcon, EuiCheckbox, EuiPopover, EuiToolTip } from '@elastic/eui'
44
import cx from 'classnames'
5-
import React, { FC, Ref, SVGProps, useRef } from 'react'
5+
import React, { FC, Ref, SVGProps, useRef, useState } from 'react'
66
import { useDispatch, useSelector } from 'react-redux'
77
import AutoSizer from 'react-virtualized-auto-sizer'
8+
import ColumnsIcon from 'uiSrc/assets/img/icons/columns.svg?react'
89
import TreeViewIcon from 'uiSrc/assets/img/icons/treeview.svg?react'
910
import KeysSummary from 'uiSrc/components/keys-summary'
1011
import { SCAN_COUNT_DEFAULT, SCAN_TREE_COUNT_DEFAULT } from 'uiSrc/constants/api'
1112
import { resetBrowserTree, setBrowserKeyListDataLoaded, } from 'uiSrc/slices/app/context'
1213

13-
import { changeKeyViewType, fetchKeys, keysSelector, resetKeysData, } from 'uiSrc/slices/browser/keys'
14+
import { changeKeyViewType, fetchKeys, keysSelector, resetKeysData, setGetSize, setGetTtl, } from 'uiSrc/slices/browser/keys'
1415
import { redisearchSelector } from 'uiSrc/slices/browser/redisearch'
1516
import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances'
1617
import { KeysStoreData, KeyViewType, SearchMode } from 'uiSrc/slices/interfaces/keys'
@@ -57,9 +58,11 @@ const KeysHeader = (props: Props) => {
5758
} = props
5859

5960
const { id: instanceId } = useSelector(connectedInstanceSelector)
60-
const { viewType, searchMode, isFiltered } = useSelector(keysSelector)
61+
const { viewType, searchMode, isFiltered, getSize, getTtl } = useSelector(keysSelector)
6162
const { selectedIndex } = useSelector(redisearchSelector)
6263

64+
const [columnsConfigShown, setColumnsConfigShown] = useState(false)
65+
6366
const rootDivRef: Ref<HTMLDivElement> = useRef(null)
6467

6568
const dispatch = useDispatch()
@@ -113,6 +116,8 @@ const KeysHeader = (props: Props) => {
113116
height: '36px !important',
114117
}
115118

119+
const toggleColumnsConfigVisibility = () => setColumnsConfigShown(!columnsConfigShown)
120+
116121
const handleRefreshKeys = () => {
117122
dispatch(fetchKeys(
118123
{
@@ -237,6 +242,46 @@ const KeysHeader = (props: Props) => {
237242
onChangeAutoRefreshRate={handleChangeAutoRefreshRate}
238243
testid="keys"
239244
/>
245+
<div className={styles.columnsButtonPopup}>
246+
<EuiPopover
247+
ownFocus={false}
248+
anchorPosition="downLeft"
249+
isOpen={columnsConfigShown}
250+
anchorClassName={styles.anchorWrapper}
251+
panelClassName={styles.popoverWrapper}
252+
closePopover={() => setColumnsConfigShown(false)}
253+
button={(
254+
<EuiButton
255+
size="s"
256+
color="secondary"
257+
iconType={ColumnsIcon}
258+
onClick={toggleColumnsConfigVisibility}
259+
className={styles.columnsButton}
260+
data-testid="btn-columns-actions"
261+
aria-label="columns"
262+
>
263+
<span className={styles.columnsButtonText}>Columns</span>
264+
</EuiButton>
265+
)}
266+
>
267+
<EuiCheckbox
268+
id="show-key-size"
269+
name="show-key-size"
270+
label="Key size"
271+
checked={getSize}
272+
onChange={(e) => dispatch(setGetSize(e.target.checked))}
273+
data-testid="show-key-size"
274+
/>
275+
<EuiCheckbox
276+
id="show-ttl"
277+
name="show-ttl"
278+
label="TTL"
279+
checked={getTtl}
280+
onChange={(e) => dispatch(setGetTtl(e.target.checked))}
281+
data-testid="show-ttl"
282+
/>
283+
</EuiPopover>
284+
</div>
240285
{ViewSwitch()}
241286
</div>
242287
</div>

redisinsight/ui/src/pages/browser/components/keys-header/styles.module.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,13 @@
6666
align-items: center;
6767
margin: 4px 4px 4px auto;
6868
}
69+
70+
.columnsButton {
71+
padding: 4px 6px 4px 4px;
72+
border-color: transparent !important;
73+
box-shadow: none !important;
74+
}
75+
76+
.columnsButtonPopup {
77+
margin-left: 20px;
78+
}

redisinsight/ui/src/slices/browser/keys.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ export const initialState: KeysStore = {
7979
isBrowserFullScreen: false,
8080
searchMode: localStorageService?.get(BrowserStorageItem.browserSearchMode) ?? SearchMode.Pattern,
8181
viewType: localStorageService?.get(BrowserStorageItem.browserViewType) ?? KeyViewType.Browser,
82+
getSize: true,
83+
getTtl: true,
8284
data: {
8385
total: 0,
8486
scanned: 0,
@@ -421,7 +423,13 @@ const keysSlice = createSlice({
421423
},
422424
setSelectedKeyRefreshDisabled: (state, { payload }: PayloadAction<boolean>) => {
423425
state.selectedKey.isRefreshDisabled = payload
424-
}
426+
},
427+
setGetSize: (state, { payload }: PayloadAction<boolean>) => {
428+
state.getSize = payload
429+
},
430+
setGetTtl: (state, { payload }: PayloadAction<boolean>) => {
431+
state.getTtl = payload
432+
},
425433
},
426434
})
427435

@@ -472,6 +480,8 @@ export const {
472480
deleteSearchHistorySuccess,
473481
deleteSearchHistoryFailure,
474482
setSelectedKeyRefreshDisabled,
483+
setGetSize,
484+
setGetTtl,
475485
} = keysSlice.actions
476486

477487
// A selector
@@ -537,7 +547,7 @@ export function fetchPatternKeysAction(
537547
type,
538548
match: match || DEFAULT_SEARCH_MATCH,
539549
keysInfo: false,
540-
scanThreshold
550+
scanThreshold,
541551
},
542552
{
543553
params: { encoding },
@@ -1036,12 +1046,18 @@ export function fetchKeysMetadata(
10361046
return async (_dispatch: AppDispatch, stateInit: () => RootState) => {
10371047
try {
10381048
const state = stateInit()
1049+
const { getSize, getTtl } = state.browser.keys
10391050
const { data } = await apiService.post<GetKeyInfoResponse[]>(
10401051
getUrl(
10411052
state.connections.instances?.connectedInstance?.id,
10421053
ApiEndpoints.KEYS_METADATA
10431054
),
1044-
{ keys, type: filter || undefined },
1055+
{
1056+
keys,
1057+
type: filter || undefined,
1058+
getSize,
1059+
getTtl
1060+
},
10451061
{ params: { encoding: state.app.info.encoding }, signal }
10461062
)
10471063

@@ -1067,12 +1083,18 @@ export function fetchKeysMetadataTree(
10671083
return async (_dispatch: AppDispatch, stateInit: () => RootState) => {
10681084
try {
10691085
const state = stateInit()
1086+
const { getSize, getTtl } = state.browser.keys
10701087
const { data } = await apiService.post<GetKeyInfoResponse[]>(
10711088
getUrl(
10721089
state.connections.instances?.connectedInstance?.id,
10731090
ApiEndpoints.KEYS_METADATA
10741091
),
1075-
{ keys: keys.map(([, nameBuffer]) => nameBuffer), type: filter || undefined },
1092+
{
1093+
keys: keys.map(([, nameBuffer]) => nameBuffer),
1094+
type: filter || undefined,
1095+
getSize,
1096+
getTtl
1097+
},
10761098
{ params: { encoding: state.app.info.encoding }, signal }
10771099
)
10781100

redisinsight/ui/src/slices/interfaces/keys.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ export interface KeysStore {
5252
data: null | Array<SearchHistoryItem>
5353
loading: boolean
5454
}
55+
getSize: boolean
56+
getTtl: boolean
5557
}
5658

5759
export interface SearchHistoryItem {

0 commit comments

Comments
 (0)