Skip to content

Commit 107ff41

Browse files
authored
RI-7437 Rework the visuals of the Slow Log page (#5154)
- update the layout of the slow log page - update the welcome screen - update the placement of the action buttons - replace the virtual table with Redis UI - replace "clear slo log" popover with a modal
1 parent a37de1b commit 107ff41

File tree

17 files changed

+458
-568
lines changed

17 files changed

+458
-568
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import styled from 'styled-components'
2+
import { RiSelect } from 'uiSrc/components/base/forms/select/RiSelect'
3+
4+
export const StyledSelect = styled(RiSelect)`
5+
border: none;
6+
`

redisinsight/ui/src/pages/slow-log/SlowLogPage.tsx

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,15 @@ import {
3232
import { AnalyticsViewTab } from 'uiSrc/slices/interfaces/analytics'
3333

3434
import { FormatedDate } from 'uiSrc/components'
35-
import { FlexItem, Row } from 'uiSrc/components/base/layout/flex'
36-
import { Text } from 'uiSrc/components/base/text'
37-
import {
38-
defaultValueRender,
39-
RiSelect,
40-
} from 'uiSrc/components/base/forms/select/RiSelect'
35+
import { Col, FlexItem, Row } from 'uiSrc/components/base/layout/flex'
36+
import { Text, Title } from 'uiSrc/components/base/text'
37+
import { defaultValueRender } from 'uiSrc/components/base/forms/select/RiSelect'
4138
import { SlowLog } from 'apiSrc/modules/slow-log/models'
4239

4340
import { Actions, EmptySlowLog, SlowLogTable } from './components'
4441

4542
import styles from './styles.module.scss'
43+
import { StyledSelect } from './SlowLogPage.styles'
4644

4745
const HIDE_TIMESTAMP_FROM_WIDTH = 850
4846
const DEFAULT_COUNT_VALUE = '50'
@@ -144,61 +142,78 @@ const SlowLogPage = () => {
144142
const isEmptySlowLog = !data.length
145143

146144
return (
147-
<div className={styles.main} data-testid="slow-log-page">
148-
<Row className={styles.header} align="center" justify="between">
149-
<FlexItem>
150-
<AnalyticsTabs />
151-
</FlexItem>
152-
153-
<FlexItem>
154-
{connectionType !== ConnectionType.Cluster && config && (
155-
<Text size="xs" color="subdued" data-testid="config-info">
156-
Execution time:{' '}
157-
{numberWithSpaces(
158-
convertNumberByUnits(slowlogLogSlowerThan, durationUnit),
159-
)}
160-
&nbsp;
161-
{durationUnit === DurationUnits.milliSeconds
162-
? DurationUnits.mSeconds
163-
: DurationUnits.microSeconds}
164-
, Max length: {numberWithSpaces(slowlogMaxLen)}
165-
</Text>
166-
)}
167-
</FlexItem>
168-
</Row>
169-
145+
<Col className={styles.main} data-testid="slow-log-page">
170146
<AutoSizer disableHeight>
171147
{({ width }) => (
172148
<div style={{ width }}>
149+
<Row className={styles.header} align="center" justify="between">
150+
<FlexItem>
151+
<AnalyticsTabs />
152+
</FlexItem>
153+
154+
<FlexItem>
155+
<Row align="center" gap="xl">
156+
{connectionType !== ConnectionType.Cluster && config && (
157+
<Text size="s" color="secondary" data-testid="config-info">
158+
Execution time:{' '}
159+
{numberWithSpaces(
160+
convertNumberByUnits(
161+
slowlogLogSlowerThan,
162+
durationUnit,
163+
),
164+
)}
165+
&nbsp;
166+
{durationUnit === DurationUnits.milliSeconds
167+
? DurationUnits.mSeconds
168+
: DurationUnits.microSeconds}
169+
, Max length: {numberWithSpaces(slowlogMaxLen)}
170+
</Text>
171+
)}
172+
173+
<Actions
174+
width={width}
175+
isEmptySlowLog={isEmptySlowLog}
176+
durationUnit={durationUnit}
177+
onClear={onClearSlowLogs}
178+
onRefresh={getSlowLogs}
179+
/>
180+
</Row>
181+
</FlexItem>
182+
</Row>
183+
173184
<Row
174185
className={styles.actionsLine}
175186
align="center"
176187
justify="between"
177188
>
178189
<FlexItem>
179-
<Row align="center" gap="s">
190+
<Title size="L" color="primary">
191+
Slow Log
192+
</Title>
193+
</FlexItem>
194+
<FlexItem>
195+
<Row align="center" gap="xs">
180196
<FlexItem>
181-
<Text color="subdued">
197+
<Text size="s" color="primary">
182198
{connectionType === ConnectionType.Cluster
183199
? 'Display per node:'
184200
: 'Display up to:'}
185201
</Text>
186202
</FlexItem>
187203
<FlexItem>
188-
<RiSelect
204+
<StyledSelect
189205
options={countOptions}
190206
valueRender={defaultValueRender}
191207
value={count}
192208
onChange={(value) => setCount(value)}
193-
className={styles.countSelect}
194209
data-testid="count-select"
195210
/>
196211
</FlexItem>
197212
{width > HIDE_TIMESTAMP_FROM_WIDTH && (
198213
<FlexItem style={{ marginLeft: 12 }}>
199214
<Text
200-
size="xs"
201-
color="subdued"
215+
size="s"
216+
color="secondary"
202217
data-testid="entries-from-timestamp"
203218
>
204219
({data.length} entries
@@ -214,15 +229,6 @@ const SlowLogPage = () => {
214229
)}
215230
</Row>
216231
</FlexItem>
217-
<FlexItem>
218-
<Actions
219-
width={width}
220-
isEmptySlowLog={isEmptySlowLog}
221-
durationUnit={durationUnit}
222-
onClear={onClearSlowLogs}
223-
onRefresh={getSlowLogs}
224-
/>
225-
</FlexItem>
226232
</Row>
227233
</div>
228234
)}
@@ -239,7 +245,7 @@ const SlowLogPage = () => {
239245
durationUnit={durationUnit}
240246
/>
241247
)}
242-
</div>
248+
</Col>
243249
)
244250
}
245251

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import styled from 'styled-components'
2+
3+
export const StyledInfoIconWrapper = styled.span`
4+
display: flex;
5+
align-self: center;
6+
cursor: pointer;
7+
`

redisinsight/ui/src/pages/slow-log/components/Actions/Actions.tsx

Lines changed: 33 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React, { useState } from 'react'
22
import { useSelector } from 'react-redux'
3-
import cx from 'classnames'
43
import { useParams } from 'react-router-dom'
54
import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances'
65
import { DurationUnits } from 'uiSrc/constants'
@@ -13,15 +12,14 @@ import { FlexItem, Row } from 'uiSrc/components/base/layout/flex'
1312
import { Spacer } from 'uiSrc/components/base/layout/spacer'
1413
import { EraserIcon, SettingsIcon } from 'uiSrc/components/base/icons'
1514
import {
16-
DestructiveButton,
1715
IconButton,
1816
SecondaryButton,
1917
} from 'uiSrc/components/base/forms/buttons'
20-
import { Text } from 'uiSrc/components/base/text'
2118
import { RiIcon } from 'uiSrc/components/base/icons/RiIcon'
2219

2320
import SlowLogConfig from '../SlowLogConfig'
24-
import styles from './styles.module.scss'
21+
import { StyledInfoIconWrapper } from './Actions.styles'
22+
import { ClearSlowLogModal } from '../ClearSlowLogModal/ClearSlowLogModal'
2523

2624
export interface Props {
2725
width: number
@@ -45,15 +43,15 @@ const Actions = (props: Props) => {
4543
const { name = '' } = useSelector(connectedInstanceSelector)
4644
const { loading, lastRefreshTime } = useSelector(slowLogSelector)
4745

48-
const [isPopoverClearOpen, setIsPopoverClearOpen] = useState(false)
46+
const [isClearModalOpen, setIsClearModalOpen] = useState(false)
4947
const [isPopoverConfigOpen, setIsPopoverConfigOpen] = useState(false)
5048

51-
const showClearPopover = () => {
52-
setIsPopoverClearOpen((isPopoverClearOpen) => !isPopoverClearOpen)
49+
const showClearModal = () => {
50+
setIsClearModalOpen((isClearModalOpen) => !isClearModalOpen)
5351
}
5452

55-
const closePopoverClear = () => {
56-
setIsPopoverClearOpen(false)
53+
const closeClearModal = () => {
54+
setIsClearModalOpen(false)
5755
}
5856
const showConfigPopover = () => {
5957
setIsPopoverConfigOpen((isPopoverConfigOpen) => !isPopoverConfigOpen)
@@ -63,11 +61,6 @@ const Actions = (props: Props) => {
6361
setIsPopoverConfigOpen(false)
6462
}
6563

66-
const handleClearClick = () => {
67-
onClear()
68-
closePopoverClear()
69-
}
70-
7164
const handleEnableAutoRefresh = (
7265
enableAutoRefresh: boolean,
7366
refreshRate: string,
@@ -98,66 +91,32 @@ const Actions = (props: Props) => {
9891
}
9992
}
10093

101-
const ToolTipContent = (
102-
<div className={styles.popoverContainer}>
103-
<RiIcon
104-
type="ToastDangerIcon"
105-
color="attention600"
106-
className={styles.warningIcon}
107-
/>
108-
<div>
109-
<Text size="m" component="div">
110-
<h4 className={styles.popoverTitle}>
111-
<b>Clear Slow Log?</b>
112-
</h4>
113-
<Text size="xs" color="subdued">
114-
Slow Log will be cleared for&nbsp;
115-
<span className={styles.popoverDBName}>{name}</span>
116-
<br />
117-
NOTE: This is server configuration
118-
</Text>
119-
</Text>
120-
<div className={styles.popoverFooter}>
121-
<DestructiveButton
122-
size="small"
123-
icon={EraserIcon}
124-
onClick={() => handleClearClick()}
125-
className={styles.popoverDeleteBtn}
126-
data-testid="reset-confirm-btn"
127-
>
128-
Clear
129-
</DestructiveButton>
130-
</div>
131-
</div>
132-
</div>
133-
)
134-
13594
return (
136-
<Row className={styles.actions} gap="s" align="center">
137-
<FlexItem grow={5} style={{ alignItems: 'flex-end' }}>
95+
<Row gap="s" align="center">
96+
<FlexItem>
13897
<AutoRefresh
13998
postfix="slowlog"
14099
loading={loading}
141100
displayText={width > HIDE_REFRESH_LABEL_WIDTH}
142101
lastRefreshTime={lastRefreshTime}
143-
containerClassName={styles.refreshContainer}
144102
onRefresh={() => onRefresh()}
145103
onEnableAutoRefresh={handleEnableAutoRefresh}
146104
onChangeAutoRefreshRate={handleChangeAutoRefreshRate}
147105
testid="slowlog"
148106
/>
149107
</FlexItem>
150-
<FlexItem grow>
108+
109+
<FlexItem>
151110
<RiPopover
152111
ownFocus
153112
anchorPosition="downRight"
154113
isOpen={isPopoverConfigOpen}
155114
panelPaddingSize="m"
156115
closePopover={() => {}}
157-
panelClassName={cx('popover-without-top-tail', styles.configWrapper)}
158116
button={
159117
<SecondaryButton
160118
size="small"
119+
inverted
161120
icon={SettingsIcon}
162121
aria-label="Configure"
163122
onClick={() => showConfigPopover()}
@@ -173,38 +132,29 @@ const Actions = (props: Props) => {
173132
/>
174133
</RiPopover>
175134
</FlexItem>
135+
176136
{!isEmptySlowLog && (
177-
<FlexItem grow>
178-
<RiPopover
179-
anchorPosition="leftCenter"
180-
ownFocus
181-
isOpen={isPopoverClearOpen}
182-
closePopover={closePopoverClear}
183-
panelPaddingSize="m"
184-
button={
185-
<RiTooltip
186-
position="left"
187-
content="Clear Slow Log"
188-
anchorClassName={styles.icon}
189-
>
190-
<IconButton
191-
icon={EraserIcon}
192-
aria-label="Clear Slow Log"
193-
onClick={() => showClearPopover()}
194-
data-testid="clear-btn"
195-
/>
196-
</RiTooltip>
197-
}
198-
>
199-
{ToolTipContent}
200-
</RiPopover>
201-
</FlexItem>
137+
<>
138+
<IconButton
139+
icon={EraserIcon}
140+
aria-label="Clear Slow Log"
141+
onClick={() => showClearModal()}
142+
data-testid="clear-btn"
143+
/>
144+
145+
<ClearSlowLogModal
146+
name={name}
147+
isOpen={isClearModalOpen}
148+
onClose={closeClearModal}
149+
onClear={onClear}
150+
/>
151+
</>
202152
)}
203-
<FlexItem grow>
153+
154+
<FlexItem>
204155
<RiTooltip
205156
title="Slow Log"
206157
position="bottom"
207-
anchorClassName={styles.icon}
208158
content={
209159
<span data-testid="slowlog-tooltip-text">
210160
Slow Log is a list of slow operations for your Redis instance.
@@ -218,12 +168,9 @@ const Actions = (props: Props) => {
218168
</span>
219169
}
220170
>
221-
<RiIcon
222-
className={styles.infoIcon}
223-
type="InfoIcon"
224-
style={{ cursor: 'pointer' }}
225-
data-testid="slow-log-tooltip-icon"
226-
/>
171+
<StyledInfoIconWrapper>
172+
<RiIcon type="InfoIcon" data-testid="slow-log-tooltip-icon" />
173+
</StyledInfoIconWrapper>
227174
</RiTooltip>
228175
</FlexItem>
229176
</Row>

0 commit comments

Comments
 (0)