|
1 |
| -import { EuiText, EuiToolTip } from '@elastic/eui' |
2 |
| -import React, { useCallback, useEffect, useState } from 'react' |
| 1 | +import { EuiProgress, EuiTab, EuiTabs } from '@elastic/eui' |
| 2 | +import React from 'react' |
3 | 3 | import { useDispatch, useSelector } from 'react-redux'
|
4 |
| -import { keyBy } from 'lodash' |
5 | 4 |
|
6 |
| -import { formatLongName } from 'uiSrc/utils' |
7 |
| -import { streamDataSelector, deleteStreamEntry } from 'uiSrc/slices/browser/stream' |
8 |
| -import { ITableColumn } from 'uiSrc/components/virtual-table/interfaces' |
9 |
| -import PopoverDelete from 'uiSrc/pages/browser/components/popover-delete/PopoverDelete' |
10 |
| -import { getFormatTime } from 'uiSrc/utils/streamUtils' |
11 |
| -import { KeyTypes, TableCellTextAlignment } from 'uiSrc/constants' |
12 |
| -import { getBasedOnViewTypeEvent, sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry' |
| 5 | +import { streamSelector, setStreamViewType, streamGroupsSelector } from 'uiSrc/slices/browser/stream' |
13 | 6 | import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances'
|
14 |
| -import { keysSelector } from 'uiSrc/slices/browser/keys' |
15 |
| -import { StreamEntryDto } from 'apiSrc/modules/browser/dto/stream.dto' |
| 7 | +import { StreamViewType } from 'uiSrc/slices/interfaces/stream' |
16 | 8 |
|
17 |
| -import StreamDetails from './StreamDetails' |
| 9 | +import { streamViewTypeTabs } from './constants' |
| 10 | +import ConsumersViewWrapper from './consumers-view' |
| 11 | +import GroupsViewWrapper from './groups-view' |
| 12 | +import StreamDataViewWrapper from './stream-data-view' |
| 13 | +import StreamTabs from './stream-tabs' |
18 | 14 |
|
19 |
| -import styles from './StreamDetails/styles.module.scss' |
20 |
| - |
21 |
| -export interface IStreamEntry extends StreamEntryDto { |
22 |
| - editing: boolean |
23 |
| -} |
24 |
| - |
25 |
| -const suffix = '_stream' |
26 |
| -const actionsWidth = 50 |
27 |
| -const minColumnWidth = 190 |
28 |
| - |
29 |
| -interface Props { |
| 15 | +export interface Props { |
30 | 16 | isFooterOpen: boolean
|
31 | 17 | }
|
32 | 18 |
|
33 | 19 | const StreamDetailsWrapper = (props: Props) => {
|
34 |
| - const { |
35 |
| - entries: loadedEntries = [], |
36 |
| - keyName: key |
37 |
| - } = useSelector(streamDataSelector) |
38 | 20 | const { id: instanceId } = useSelector(connectedInstanceSelector)
|
39 |
| - const { viewType } = useSelector(keysSelector) |
| 21 | + const { viewType, loading } = useSelector(streamSelector) |
| 22 | + const { loading: loadingGroups } = useSelector(streamGroupsSelector) |
40 | 23 |
|
41 | 24 | const dispatch = useDispatch()
|
42 | 25 |
|
43 |
| - const [uniqFields, setUniqFields] = useState({}) |
44 |
| - const [entries, setEntries] = useState<IStreamEntry[]>([]) |
45 |
| - const [columns, setColumns] = useState<ITableColumn[]>([]) |
46 |
| - const [deleting, setDeleting] = useState<string>('') |
47 |
| - |
48 |
| - useEffect(() => { |
49 |
| - let fields = {} |
50 |
| - const streamEntries: IStreamEntry[] = loadedEntries?.map((item) => { |
51 |
| - fields = { |
52 |
| - ...fields, |
53 |
| - ...keyBy(Object.keys(item.fields)) |
54 |
| - } |
55 |
| - |
56 |
| - return { |
57 |
| - ...item, |
58 |
| - editing: false, |
59 |
| - } |
60 |
| - }) |
61 |
| - |
62 |
| - setUniqFields(fields) |
63 |
| - setEntries(streamEntries) |
64 |
| - setColumns([idColumn, ...Object.keys(fields).map((field) => getTemplateColumn(field)), actionsColumn]) |
65 |
| - }, [loadedEntries, deleting]) |
66 |
| - |
67 |
| - const closePopover = useCallback(() => { |
68 |
| - setDeleting('') |
69 |
| - }, []) |
70 |
| - |
71 |
| - const showPopover = useCallback((entry = '') => { |
72 |
| - setDeleting(`${entry + suffix}`) |
73 |
| - }, []) |
74 |
| - |
75 |
| - const onSuccessRemoved = () => { |
76 |
| - sendEventTelemetry({ |
77 |
| - event: getBasedOnViewTypeEvent( |
78 |
| - viewType, |
79 |
| - TelemetryEvent.BROWSER_KEY_VALUE_REMOVED, |
80 |
| - TelemetryEvent.TREE_VIEW_KEY_VALUE_REMOVED |
81 |
| - ), |
82 |
| - eventData: { |
83 |
| - databaseId: instanceId, |
84 |
| - keyType: KeyTypes.Stream, |
85 |
| - numberOfRemoved: 1, |
86 |
| - } |
87 |
| - }) |
88 |
| - } |
89 |
| - |
90 |
| - const handleDeleteEntry = (entryId = '') => { |
91 |
| - dispatch(deleteStreamEntry(key, [entryId], onSuccessRemoved)) |
92 |
| - closePopover() |
93 |
| - } |
94 |
| - |
95 |
| - const handleRemoveIconClick = () => { |
96 |
| - sendEventTelemetry({ |
97 |
| - event: getBasedOnViewTypeEvent( |
98 |
| - viewType, |
99 |
| - TelemetryEvent.BROWSER_KEY_VALUE_REMOVE_CLICKED, |
100 |
| - TelemetryEvent.TREE_VIEW_KEY_VALUE_REMOVE_CLICKED |
101 |
| - ), |
102 |
| - eventData: { |
103 |
| - databaseId: instanceId, |
104 |
| - keyType: KeyTypes.Stream |
105 |
| - } |
106 |
| - }) |
107 |
| - } |
108 |
| - |
109 |
| - const handleEditEntry = (entryId = '', editing: boolean) => { |
110 |
| - const newFieldsState = entries.map((item) => { |
111 |
| - if (item.id === entryId) { |
112 |
| - return { ...item, editing } |
113 |
| - } |
114 |
| - return item |
115 |
| - }) |
116 |
| - setEntries(newFieldsState) |
117 |
| - } |
118 |
| - |
119 |
| - const getTemplateColumn = (label: string) : ITableColumn => ({ |
120 |
| - id: label, |
121 |
| - label, |
122 |
| - minWidth: minColumnWidth, |
123 |
| - isSortable: false, |
124 |
| - className: styles.cell, |
125 |
| - headerClassName: styles.cellHeader, |
126 |
| - headerCellClassName: 'truncateText', |
127 |
| - render: function Id(_name: string, { id, fields }: StreamEntryDto) { |
128 |
| - const value = fields[label] ?? '' |
129 |
| - const cellContent = value.substring(0, 200) |
130 |
| - const tooltipContent = formatLongName(value) |
131 |
| - |
132 |
| - return ( |
133 |
| - <EuiText size="s" style={{ maxWidth: '100%', minHeight: '36px' }}> |
134 |
| - <div |
135 |
| - style={{ display: 'flex' }} |
136 |
| - className="streamEntry" |
137 |
| - data-testid={`stream-entry-field-${id}`} |
138 |
| - > |
139 |
| - <EuiToolTip |
140 |
| - title="Value" |
141 |
| - className={styles.tooltip} |
142 |
| - anchorClassName="streamEntry line-clamp-2" |
143 |
| - position="bottom" |
144 |
| - content={tooltipContent} |
145 |
| - > |
146 |
| - <>{cellContent}</> |
147 |
| - </EuiToolTip> |
148 |
| - </div> |
149 |
| - </EuiText> |
150 |
| - ) |
151 |
| - } |
152 |
| - }) |
153 |
| - |
154 |
| - const [idColumn, actionsColumn]: ITableColumn[] = [ |
155 |
| - { |
156 |
| - id: 'id', |
157 |
| - label: 'Entry ID', |
158 |
| - absoluteWidth: minColumnWidth, |
159 |
| - minWidth: minColumnWidth, |
160 |
| - isSortable: true, |
161 |
| - className: styles.cell, |
162 |
| - headerClassName: styles.cellHeader, |
163 |
| - render: function Id(_name: string, { id }: StreamEntryDto) { |
164 |
| - const timestamp = id.split('-')?.[0] |
165 |
| - return ( |
166 |
| - <div> |
167 |
| - <EuiText color="subdued" size="s" style={{ maxWidth: '100%' }}> |
168 |
| - <div className="truncateText streamEntry" style={{ display: 'flex' }} data-testid={`stream-entry-${id}-date`}> |
169 |
| - {getFormatTime(timestamp)} |
170 |
| - </div> |
171 |
| - </EuiText> |
172 |
| - <EuiText size="s" style={{ maxWidth: '100%' }}> |
173 |
| - <div className="streamEntryId" data-testid={`stream-entry-${id}`}> |
174 |
| - {id} |
175 |
| - </div> |
176 |
| - </EuiText> |
177 |
| - </div> |
178 |
| - ) |
179 |
| - }, |
180 |
| - }, |
181 |
| - { |
182 |
| - id: 'actions', |
183 |
| - label: '', |
184 |
| - headerClassName: styles.actionsHeader, |
185 |
| - textAlignment: TableCellTextAlignment.Left, |
186 |
| - absoluteWidth: actionsWidth, |
187 |
| - maxWidth: actionsWidth, |
188 |
| - minWidth: actionsWidth, |
189 |
| - render: function Actions(_act: any, { id }: StreamEntryDto) { |
190 |
| - return ( |
191 |
| - <div> |
192 |
| - <PopoverDelete |
193 |
| - text={( |
194 |
| - <> |
195 |
| - Entry {id} will be removed from |
196 |
| - <br /> |
197 |
| - {key} |
198 |
| - </> |
199 |
| - )} |
200 |
| - item={id} |
201 |
| - suffix={suffix} |
202 |
| - deleting={deleting} |
203 |
| - closePopover={closePopover} |
204 |
| - updateLoading={false} |
205 |
| - showPopover={showPopover} |
206 |
| - testid={`remove-entry-button-${id}`} |
207 |
| - handleDeleteItem={handleDeleteEntry} |
208 |
| - handleButtonClick={handleRemoveIconClick} |
209 |
| - /> |
210 |
| - </div> |
211 |
| - ) |
212 |
| - }, |
213 |
| - }, |
214 |
| - ] |
215 |
| - |
216 | 26 | return (
|
217 | 27 | <>
|
218 |
| - <StreamDetails |
219 |
| - data={entries} |
220 |
| - columns={columns} |
221 |
| - onEditEntry={handleEditEntry} |
222 |
| - onClosePopover={closePopover} |
223 |
| - {...props} |
224 |
| - /> |
| 28 | + {(loading || loadingGroups) && ( |
| 29 | + <EuiProgress |
| 30 | + color="primary" |
| 31 | + size="xs" |
| 32 | + position="absolute" |
| 33 | + data-testid="progress-key-stream" |
| 34 | + /> |
| 35 | + )} |
| 36 | + <StreamTabs /> |
| 37 | + {viewType === StreamViewType.Data && ( |
| 38 | + <StreamDataViewWrapper {...props} /> |
| 39 | + )} |
| 40 | + {viewType === StreamViewType.Groups && ( |
| 41 | + <GroupsViewWrapper {...props} /> |
| 42 | + )} |
| 43 | + {viewType === StreamViewType.Consumers && ( |
| 44 | + <ConsumersViewWrapper {...props} /> |
| 45 | + )} |
225 | 46 | </>
|
226 | 47 | )
|
227 | 48 | }
|
|
0 commit comments