mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-01 04:22:02 +08:00
feat: search in tags is updated (#1788)
* feat: search in tags is updated * chore: placeholder is updated
This commit is contained in:
parent
18d80d47e5
commit
8aae9f53a9
3
frontend/public/locales/en-GB/traceDetails.json
Normal file
3
frontend/public/locales/en-GB/traceDetails.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"search_tags": "Search Tag Names"
|
||||||
|
}
|
3
frontend/public/locales/en/traceDetails.json
Normal file
3
frontend/public/locales/en/traceDetails.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"search_tags": "Search Tag Names"
|
||||||
|
}
|
@ -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;
|
@ -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;
|
@ -0,0 +1,8 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
export const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user