diff --git a/frontend/public/locales/en-GB/traceDetails.json b/frontend/public/locales/en-GB/traceDetails.json new file mode 100644 index 0000000000..bb61ff20ec --- /dev/null +++ b/frontend/public/locales/en-GB/traceDetails.json @@ -0,0 +1,3 @@ +{ + "search_tags": "Search Tag Names" +} diff --git a/frontend/public/locales/en/traceDetails.json b/frontend/public/locales/en/traceDetails.json new file mode 100644 index 0000000000..bb61ff20ec --- /dev/null +++ b/frontend/public/locales/en/traceDetails.json @@ -0,0 +1,3 @@ +{ + "search_tags": "Search Tag Names" +} diff --git a/frontend/src/container/TraceDetail/SelectedSpanDetails/Tags/Tag.tsx b/frontend/src/container/TraceDetail/SelectedSpanDetails/Tags/Tag.tsx new file mode 100644 index 0000000000..42f772475e --- /dev/null +++ b/frontend/src/container/TraceDetail/SelectedSpanDetails/Tags/Tag.tsx @@ -0,0 +1,64 @@ +import { Tooltip } from 'antd'; +import React, { useMemo } from 'react'; +import { useSelector } from 'react-redux'; +import { AppState } from 'store/reducers'; +import { ITraceTag } from 'types/api/trace/getTraceItem'; +import AppReducer from 'types/reducer/app'; + +import EllipsedButton from '../EllipsedButton'; +import { CustomSubText, CustomSubTitle, SubTextContainer } from '../styles'; +import { CommonTagsProps } from '.'; +import { Container } from './styles'; + +function Tag({ tags, onToggleHandler, setText }: TagProps): JSX.Element { + const { isDarkMode } = useSelector((state) => state.app); + + const { value, isEllipsed } = useMemo(() => { + const value = tags.key === 'error' ? 'true' : tags.value; + + return { + value, + isEllipsed: value.length > 24, + }; + }, [tags]); + + return ( + + {tags.value && ( + + {tags.key} + + value}> + + {value} + + + {isEllipsed && ( + + )} + + + + )} + + ); +} + +interface TagProps extends CommonTagsProps { + tags: ITraceTag; +} + +export default Tag; diff --git a/frontend/src/container/TraceDetail/SelectedSpanDetails/Tags/index.tsx b/frontend/src/container/TraceDetail/SelectedSpanDetails/Tags/index.tsx new file mode 100644 index 0000000000..7bd2449cc1 --- /dev/null +++ b/frontend/src/container/TraceDetail/SelectedSpanDetails/Tags/index.tsx @@ -0,0 +1,65 @@ +import { Input, Typography } from 'antd'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { ITraceTag } from 'types/api/trace/getTraceItem'; + +import { ModalText } from '..'; +import { Container } from './styles'; +import Tag from './Tag'; + +function Tags({ tags, onToggleHandler, setText }: TagsProps): JSX.Element { + const { t } = useTranslation(['traceDetails']); + const [allRenderedTags, setAllRenderedTags] = useState(tags); + const isSearchVisible = useMemo(() => tags.length > 5, [tags]); + + useEffect(() => { + setAllRenderedTags(tags); + }, [tags]); + + const onChangeHandler = useCallback( + (e: React.ChangeEvent): void => { + const { value } = e.target; + const filteredTags = tags.filter((tag) => tag.key.includes(value)); + setAllRenderedTags(filteredTags); + }, + [tags], + ); + + if (tags.length === 0) { + return No tags in selected span; + } + + return ( + + {isSearchVisible && ( + + )} + + {allRenderedTags.map((tag) => ( + + ))} + + ); +} + +interface TagsProps extends CommonTagsProps { + tags: ITraceTag[]; +} + +export interface CommonTagsProps { + onToggleHandler: (state: boolean) => void; + setText: React.Dispatch>; +} + +export default Tags; diff --git a/frontend/src/container/TraceDetail/SelectedSpanDetails/Tags/styles.ts b/frontend/src/container/TraceDetail/SelectedSpanDetails/Tags/styles.ts new file mode 100644 index 0000000000..40970fbe1d --- /dev/null +++ b/frontend/src/container/TraceDetail/SelectedSpanDetails/Tags/styles.ts @@ -0,0 +1,8 @@ +import styled from 'styled-components'; + +export const Container = styled.div` + display: flex; + gap: 0.5rem; + flex-direction: column; + width: 100%; +`; diff --git a/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx b/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx index 49596d14d0..ec6f9b037b 100644 --- a/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx +++ b/frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx @@ -5,17 +5,15 @@ import useThemeMode from 'hooks/useThemeMode'; import React, { useMemo, useState } from 'react'; import { ITraceTree } from 'types/api/trace/getTraceItem'; -import EllipsedButton from './EllipsedButton'; import ErrorTag from './ErrorTag'; import { CardContainer, CustomSubText, - CustomSubTitle, CustomText, CustomTitle, styles, - SubTextContainer, } from './styles'; +import Tags from './Tags'; const { TabPane } = Tabs; @@ -31,7 +29,7 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element { const [isOpen, setIsOpen] = useState(false); - const [text, setText] = useState({ + const [text, setText] = useState({ text: '', subText: '', }); @@ -86,48 +84,7 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element { - {tags.length !== 0 ? ( - tags.map((tags) => { - const value = tags.key === 'error' ? 'true' : tags.value; - const isEllipsed = value.length > 24; - - return ( - - {tags.value && ( - <> - {tags.key} - - value}> - - {value} - - - {isEllipsed && ( - - )} - - - - )} - - ); - }) - ) : ( - No tags in selected span - )} + {tree.event && Object.keys(tree.event).length !== 0 ? ( @@ -153,4 +110,9 @@ SelectedSpanDetails.defaultProps = { tree: undefined, }; +export interface ModalText { + text: string; + subText: string; +} + export default SelectedSpanDetails;