Skip to content

Commit

Permalink
[TH2-4981] UI: highlight fields that I provide in filters for all mes…
Browse files Browse the repository at this point in the history
…sages (#567)
  • Loading branch information
tesohi authored Feb 27, 2024
1 parent 57e9c43 commit 404170a
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 2 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "th2-rpt-viewer",
"version": "5.1.28",
"version": "5.1.29",
"description": "",
"main": "index.tsx",
"private": true,
Expand Down
29 changes: 28 additions & 1 deletion src/components/message/message-card/MessageBodyCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,20 @@ import MessageBody, {
isMessageValue,
isNullValue,
} from '../../../models/MessageBody';
import { HighlightColorManager } from '../../../helpers/highlightUtils';

const BEAUTIFIED_PAD_VALUE = 15;
const DEFAULT_HIGHLIGHT_COLOR = '#e2dfdf';
const SELECTED_HIGHLIGHT_COLOR = '#fff';

const highlightColorManager = new HighlightColorManager();

interface Props {
isBeautified: boolean;
body: MessageBody | null;
isSelected: boolean;
sortOrderItems: string[];
filterBodyValues: string[] | undefined;
}

const getSortedFields = (fields: MessageBodyFields, sortOrder: string[]) => {
Expand Down Expand Up @@ -64,7 +68,13 @@ const getSortedFields = (fields: MessageBodyFields, sortOrder: string[]) => {
return [...primarySortedFields, ...secondarySortedFields, ...tertiarySortedFields];
};

function MessageBodyCard({ isBeautified, body, isSelected, sortOrderItems }: Props) {
function MessageBodyCard({
isBeautified,
body,
isSelected,
sortOrderItems,
filterBodyValues,
}: Props) {
const [areSameContext, highlightSameContext] = React.useState(false);

const fields = React.useMemo(
Expand Down Expand Up @@ -93,6 +103,7 @@ function MessageBodyCard({ isBeautified, body, isSelected, sortOrderItems }: Pro
field={value}
isBeautified={isBeautified}
setIsHighlighted={highlightSameContext}
filterBodyValues={filterBodyValues}
/>
{isBeautified || idx === arr.length - 1 ? null : ', '}
</React.Fragment>
Expand All @@ -116,6 +127,7 @@ interface FieldProps {
highlightColor: string;
primarySort: string[];
renderInfo?: () => React.ReactNode;
filterBodyValues: string[] | undefined;
}

function MessageBodyCardField(props: FieldProps) {
Expand All @@ -127,12 +139,23 @@ function MessageBodyCardField(props: FieldProps) {
isRoot = true,
setIsHighlighted,
highlightColor,
filterBodyValues,
} = props;

const [areSameContext, highlightSameContext] = React.useState(false);

const highlight = React.useMemo(() => debounce(() => setIsHighlighted(true), 60), []);

const fieldColor = React.useMemo(() => {
if (!isSimpleValue(field)) {
return '';
}
if (filterBodyValues?.some(filter => field?.simpleValue?.includes(filter) || false)) {
return highlightColorManager.getHighlightColor(field.simpleValue);
}
return '';
}, [filterBodyValues]);

const removeHighlight = React.useCallback(() => {
highlight.cancel();
setIsHighlighted(false);
Expand All @@ -148,6 +171,7 @@ function MessageBodyCardField(props: FieldProps) {
label={label}
isRoot={false}
setIsHighlighted={setIsHighlighted}
filterBodyValues={filterBodyValues}
/>
);
}
Expand All @@ -165,6 +189,7 @@ function MessageBodyCardField(props: FieldProps) {
className='mc-body__field'
style={{
display: isBeautified ? 'block' : undefined,
backgroundColor: fieldColor,
}}>
<span
onMouseEnter={highlight}
Expand Down Expand Up @@ -212,6 +237,7 @@ function MessageBodyCardField(props: FieldProps) {
isRoot={true}
setIsHighlighted={highlightSameContext}
highlightColor={highlightColor}
filterBodyValues={filterBodyValues}
/>
{isBeautified || idx === arr.length - 1 ? null : ', '}
</React.Fragment>
Expand Down Expand Up @@ -251,6 +277,7 @@ function MessageBodyCardField(props: FieldProps) {
isRoot={false}
setIsHighlighted={highlightSameContext}
highlightColor={highlightColor}
filterBodyValues={filterBodyValues}
/>
{isBeautified || idx === arr.length - 1 ? null : ', '}
</React.Fragment>
Expand Down
10 changes: 10 additions & 0 deletions src/components/message/message-card/MessageCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,16 @@ const MessageCard = observer(({ message, viewType, setViewType }: Props) => {
const { messageId } = message;

const messagesStore = useMessagesWorkspaceStore();
const { filterStore } = messagesStore;
const messagesDataStore = useMessagesDataStore();
const bookmarksStore = useBookmarksStore();
const { sortOrderItems } = useMessageBodySortStore();
const booksStore = useBooksStore();

const [isHighlighted, setHighlighted] = React.useState(false);

const [filterBodyValues, setFilterBodyValues] = React.useState<string[] | undefined>();

const hoverTimeout = React.useRef<NodeJS.Timeout>();

const isContentBeautified = viewType === MessageViewType.FORMATTED;
Expand All @@ -60,6 +63,12 @@ const MessageCard = observer(({ message, viewType, setViewType }: Props) => {

const isSoftFiltered = messagesDataStore.isSoftFiltered.get(messageId);

React.useEffect(() => {
if (filterStore.isMessagesFilterApplied) {
setFilterBodyValues(filterStore.filterParams['body-values']);
}
}, [filterStore.isMessagesFilterApplied]);

React.useEffect(() => {
const abortController = new AbortController();

Expand Down Expand Up @@ -113,6 +122,7 @@ const MessageCard = observer(({ message, viewType, setViewType }: Props) => {
viewType={viewType}
setViewType={setViewType}
isHighlighted={isHighlighted}
filterBodyValues={filterBodyValues}
hoverMessage={hoverMessage}
unhoverMessage={unhoverMessage}
isBookmarked={isBookmarked}
Expand Down
3 changes: 3 additions & 0 deletions src/components/message/message-card/MessageCardBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface MessageCardBaseProps {
isExported?: boolean;
isExport?: boolean;
sortOrderItems?: string[];
filterBodyValues?: string[] | undefined;
viewType: MessageViewType;
setViewType: (viewType: MessageViewType) => void;
addMessageToExport?: () => void;
Expand All @@ -61,6 +62,7 @@ const MessageCardBase = React.memo(
isExport,
sortOrderItems,
addMessageToExport,
filterBodyValues,
}: MessageCardBaseProps) => {
const { messageId, bodyBase64, body } = message;

Expand Down Expand Up @@ -90,6 +92,7 @@ const MessageCardBase = React.memo(
rawContent: bodyBase64,
isSelected: isAttached || false,
sortOrderItems: sortOrderItems || [],
filterBodyValues,
};

const messageCardToolsConfig: MessageCardToolsConfig = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export type MessageCardViewTypeRendererProps = {
isEmbedded?: boolean;
isDetailed?: boolean;
sortOrderItems: string[];
filterBodyValues: string[] | undefined;
};

const MessageCardViewTypeRenderer = ({
Expand All @@ -41,6 +42,7 @@ const MessageCardViewTypeRenderer = ({
isSelected,
messageBody,
sortOrderItems,
filterBodyValues,
}: MessageCardViewTypeRendererProps) => {
switch (viewType) {
case MessageViewType.FORMATTED:
Expand All @@ -53,13 +55,15 @@ const MessageCardViewTypeRenderer = ({
isSelected={isSelected}
body={messageBody}
sortOrderItems={sortOrderItems}
filterBodyValues={filterBodyValues}
/>
}>
<MessageBodyCard
isBeautified={isBeautified}
body={messageBody}
isSelected={isSelected}
sortOrderItems={sortOrderItems}
filterBodyValues={filterBodyValues}
/>
</ErrorBoundary>
);
Expand Down
46 changes: 46 additions & 0 deletions src/helpers/highlightUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/** ****************************************************************************
* Copyright 2020-2020 Exactpro (Exactpro Systems Limited)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************** */

export function randomHighlightColor(alpha = 0.5): string {
const r = Math.floor(Math.random() * 150 + 50);
const g = Math.floor(Math.random() * 150 + 50);
const b = Math.floor(Math.random() * 150 + 50);
return `rgba(${r},${g},${b},${alpha})`;
}

export class HighlightColorManager {
private predefinedColors: string[] = [
'rgba(255, 0, 0, 0.5)',
'rgba(0, 255, 0, 0.5)',
'rgba(0, 255, 255, 0.5)',
'rgba(255, 255, 0, 0.5)',
'rgba(255, 0, 255, 0.5)',
];

private colorMap: Map<string, string> = new Map();

public getHighlightColor(value: string): string {
const color = this.colorMap.get(value);
if (color) {
return color;
}

const newColor = this.predefinedColors.pop() || randomHighlightColor();

this.colorMap.set(value, newColor);
return newColor;
}
}

0 comments on commit 404170a

Please sign in to comment.