feat: search in tags is updated (#1788)

* feat: search in tags is updated

* chore: placeholder is updated
This commit is contained in:
Palash Gupta 2022-12-01 14:19:12 +05:30 committed by GitHub
parent 18d80d47e5
commit 8aae9f53a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 151 additions and 46 deletions

View File

@ -0,0 +1,3 @@
{
"search_tags": "Search Tag Names"
}

View File

@ -0,0 +1,3 @@
{
"search_tags": "Search Tag Names"
}

View File

@ -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<AppState, AppReducer>((state) => state.app);
const { value, isEllipsed } = useMemo(() => {
const value = tags.key === 'error' ? 'true' : tags.value;
return {
value,
isEllipsed: value.length > 24,
};
}, [tags]);
return (
<React.Fragment key={JSON.stringify(tags)}>
{tags.value && (
<Container>
<CustomSubTitle>{tags.key}</CustomSubTitle>
<SubTextContainer isDarkMode={isDarkMode}>
<Tooltip overlay={(): string => value}>
<CustomSubText
ellipsis={{
rows: isEllipsed ? 1 : 0,
}}
isDarkMode={isDarkMode}
>
{value}
</CustomSubText>
{isEllipsed && (
<EllipsedButton
{...{
event: tags.key,
onToggleHandler,
setText,
value,
buttonText: 'View full value',
}}
/>
)}
</Tooltip>
</SubTextContainer>
</Container>
)}
</React.Fragment>
);
}
interface TagProps extends CommonTagsProps {
tags: ITraceTag;
}
export default Tag;

View File

@ -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<HTMLInputElement>): void => {
const { value } = e.target;
const filteredTags = tags.filter((tag) => tag.key.includes(value));
setAllRenderedTags(filteredTags);
},
[tags],
);
if (tags.length === 0) {
return <Typography>No tags in selected span</Typography>;
}
return (
<Container>
{isSearchVisible && (
<Input.Search
placeholder={t('traceDetails:search_tags')}
allowClear
onChange={onChangeHandler}
/>
)}
{allRenderedTags.map((tag) => (
<Tag
key={JSON.stringify(tag)}
{...{
onToggleHandler,
setText,
tags: tag,
}}
/>
))}
</Container>
);
}
interface TagsProps extends CommonTagsProps {
tags: ITraceTag[];
}
export interface CommonTagsProps {
onToggleHandler: (state: boolean) => void;
setText: React.Dispatch<React.SetStateAction<ModalText>>;
}
export default Tags;

View File

@ -0,0 +1,8 @@
import styled from 'styled-components';
export const Container = styled.div`
display: flex;
gap: 0.5rem;
flex-direction: column;
width: 100%;
`;

View File

@ -5,17 +5,15 @@ import useThemeMode from 'hooks/useThemeMode';
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { ITraceTree } from 'types/api/trace/getTraceItem'; import { ITraceTree } from 'types/api/trace/getTraceItem';
import EllipsedButton from './EllipsedButton';
import ErrorTag from './ErrorTag'; import ErrorTag from './ErrorTag';
import { import {
CardContainer, CardContainer,
CustomSubText, CustomSubText,
CustomSubTitle,
CustomText, CustomText,
CustomTitle, CustomTitle,
styles, styles,
SubTextContainer,
} from './styles'; } from './styles';
import Tags from './Tags';
const { TabPane } = Tabs; const { TabPane } = Tabs;
@ -31,7 +29,7 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [text, setText] = useState({ const [text, setText] = useState<ModalText>({
text: '', text: '',
subText: '', subText: '',
}); });
@ -86,48 +84,7 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element {
<Tabs defaultActiveKey="1"> <Tabs defaultActiveKey="1">
<TabPane tab="Tags" key="1"> <TabPane tab="Tags" key="1">
{tags.length !== 0 ? ( <Tags onToggleHandler={onToggleHandler} setText={setText} tags={tags} />
tags.map((tags) => {
const value = tags.key === 'error' ? 'true' : tags.value;
const isEllipsed = value.length > 24;
return (
<React.Fragment key={JSON.stringify(tags)}>
{tags.value && (
<>
<CustomSubTitle>{tags.key}</CustomSubTitle>
<SubTextContainer isDarkMode={isDarkMode}>
<Tooltip overlay={(): string => value}>
<CustomSubText
ellipsis={{
rows: isEllipsed ? 1 : 0,
}}
isDarkMode={isDarkMode}
>
{value}
</CustomSubText>
{isEllipsed && (
<EllipsedButton
{...{
event: tags.key,
onToggleHandler,
setText,
value,
buttonText: 'View full value',
}}
/>
)}
</Tooltip>
</SubTextContainer>
</>
)}
</React.Fragment>
);
})
) : (
<Typography>No tags in selected span</Typography>
)}
</TabPane> </TabPane>
<TabPane tab="Events" key="2"> <TabPane tab="Events" key="2">
{tree.event && Object.keys(tree.event).length !== 0 ? ( {tree.event && Object.keys(tree.event).length !== 0 ? (
@ -153,4 +110,9 @@ SelectedSpanDetails.defaultProps = {
tree: undefined, tree: undefined,
}; };
export interface ModalText {
text: string;
subText: string;
}
export default SelectedSpanDetails; export default SelectedSpanDetails;