|
10 | 10 | */ |
11 | 11 |
|
12 | 12 | import { DownloadIcon, KebabHorizontalIcon, SkipIcon, SyncIcon, XCircleIcon } from '@primer/octicons-react'; |
13 | | -import { |
14 | | - type IReactionDisposer, |
15 | | - action, |
16 | | - autorun, |
17 | | - computed, |
18 | | - makeObservable, |
19 | | - observable, |
20 | | - transaction, |
21 | | - untracked, |
22 | | -} from 'mobx'; |
| 13 | +import { type IReactionDisposer, autorun, computed, makeObservable, observable, transaction, untracked } from 'mobx'; |
23 | 14 | import { observer } from 'mobx-react'; |
24 | | -import React, { Component, type FC, type ReactNode, useState } from 'react'; |
| 15 | +import React, { Component, type FC, type ReactNode, useCallback, useState } from 'react'; |
25 | 16 | import { type MessageSearch, type MessageSearchRequest, api, createMessageSearch } from '../../../../state/backendApi'; |
26 | 17 | import type { Payload, Topic, TopicAction } from '../../../../state/restInterfaces'; |
27 | 18 | import type { TopicMessage } from '../../../../state/restInterfaces'; |
@@ -250,8 +241,6 @@ export class TopicMessageView extends Component<TopicMessageViewProps> { |
250 | 241 | currentSearchRun: string | null = null; |
251 | 242 |
|
252 | 243 | @observable downloadMessages: TopicMessage[] | null = null; |
253 | | - @observable expandedKeys: React.Key[] = []; |
254 | | - |
255 | 244 | constructor(props: TopicMessageViewProps) { |
256 | 245 | super(props); |
257 | 246 | this.executeMessageSearch = this.executeMessageSearch.bind(this); // needed because we must pass the function directly as 'submit' prop |
@@ -750,29 +739,35 @@ export class TopicMessageView extends Component<TopicMessageViewProps> { |
750 | 739 | const tsFormat = uiState.topicSettings.previewTimestamps; |
751 | 740 | const hasKeyTags = uiState.topicSettings.previewTags.count((x) => x.isActive && x.searchInMessageKey) > 0; |
752 | 741 |
|
753 | | - function onCopyValue(original: TopicMessage) { |
754 | | - navigator.clipboard |
755 | | - .writeText(getPayloadAsString(original.value.payload ?? original.value.rawBytes)) |
756 | | - .then(() => { |
757 | | - toast({ |
758 | | - status: 'success', |
759 | | - description: 'Value copied to clipboard', |
760 | | - }); |
761 | | - }) |
762 | | - .catch(navigatorClipboardErrorHandler); |
763 | | - } |
| 742 | + const onCopyValue = useCallback( |
| 743 | + (original: TopicMessage) => { |
| 744 | + navigator.clipboard |
| 745 | + .writeText(getPayloadAsString(original.value.payload ?? original.value.rawBytes)) |
| 746 | + .then(() => { |
| 747 | + toast({ |
| 748 | + status: 'success', |
| 749 | + description: 'Value copied to clipboard', |
| 750 | + }); |
| 751 | + }) |
| 752 | + .catch(navigatorClipboardErrorHandler); |
| 753 | + }, |
| 754 | + [toast], |
| 755 | + ); |
764 | 756 |
|
765 | | - function onCopyKey(original: TopicMessage) { |
766 | | - navigator.clipboard |
767 | | - .writeText(getPayloadAsString(original.key.payload ?? original.key.rawBytes)) |
768 | | - .then(() => { |
769 | | - toast({ |
770 | | - status: 'success', |
771 | | - description: 'Key copied to clipboard', |
772 | | - }); |
773 | | - }) |
774 | | - .catch(navigatorClipboardErrorHandler); |
775 | | - } |
| 757 | + const onCopyKey = useCallback( |
| 758 | + (original: TopicMessage) => { |
| 759 | + navigator.clipboard |
| 760 | + .writeText(getPayloadAsString(original.key.payload ?? original.key.rawBytes)) |
| 761 | + .then(() => { |
| 762 | + toast({ |
| 763 | + status: 'success', |
| 764 | + description: 'Key copied to clipboard', |
| 765 | + }); |
| 766 | + }) |
| 767 | + .catch(navigatorClipboardErrorHandler); |
| 768 | + }, |
| 769 | + [toast], |
| 770 | + ); |
776 | 771 |
|
777 | 772 | const isValueDeserializerActive = |
778 | 773 | uiState.topicSettings.searchParams.valueDeserializer !== null && |
@@ -991,18 +986,21 @@ export class TopicMessageView extends Component<TopicMessageViewProps> { |
991 | 986 | query.pageSize = String(pageSize); |
992 | 987 | }); |
993 | 988 | })} |
994 | | - subComponent={({ row: { original } }) => ( |
995 | | - <ExpandedMessage |
996 | | - msg={original} |
997 | | - loadLargeMessage={() => |
998 | | - this.loadLargeMessage(this.props.topic.topicName, original.partitionID, original.offset) |
999 | | - } |
1000 | | - onDownloadRecord={() => { |
1001 | | - this.downloadMessages = [original]; |
1002 | | - }} |
1003 | | - onCopyKey={onCopyKey} |
1004 | | - onCopyValue={onCopyValue} |
1005 | | - /> |
| 989 | + subComponent={useCallback( |
| 990 | + ({ row: { original } }: { row: { original: TopicMessage } }) => ( |
| 991 | + <ExpandedMessage |
| 992 | + msg={original} |
| 993 | + loadLargeMessage={() => |
| 994 | + this.loadLargeMessage(this.props.topic.topicName, original.partitionID, original.offset) |
| 995 | + } |
| 996 | + onDownloadRecord={() => { |
| 997 | + this.downloadMessages = [original]; |
| 998 | + }} |
| 999 | + onCopyKey={onCopyKey} |
| 1000 | + onCopyValue={onCopyValue} |
| 1001 | + /> |
| 1002 | + ), |
| 1003 | + [onCopyKey, onCopyValue], |
1006 | 1004 | )} |
1007 | 1005 | /> |
1008 | 1006 | <Button |
@@ -1044,15 +1042,6 @@ export class TopicMessageView extends Component<TopicMessageViewProps> { |
1044 | 1042 | ); |
1045 | 1043 | }); |
1046 | 1044 |
|
1047 | | - @action toggleRecordExpand(r: TopicMessage) { |
1048 | | - const key = `${r.offset} ${r.partitionID}${r.timestamp}`; |
1049 | | - // try collapsing it, removeAll returns the number of matches |
1050 | | - const removed = this.expandedKeys.removeAll((x) => x === key); |
1051 | | - if (removed === 0) |
1052 | | - // wasn't expanded, so expand it now |
1053 | | - this.expandedKeys.push(key); |
1054 | | - } |
1055 | | - |
1056 | 1045 | async executeMessageSearch(): Promise<TopicMessage[]> { |
1057 | 1046 | const searchParams = uiState.topicSettings.searchParams; |
1058 | 1047 | const canUseFilters = |
|
0 commit comments