mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 02:19:02 +08:00
feat: popover is added in the trace tag search (#2118)
* feat: popover is updated * chore: arrow is removed and padding is removed * chore: width is updated
This commit is contained in:
parent
d7a65ba689
commit
f766435acc
@ -16,7 +16,6 @@ import {
|
||||
Container,
|
||||
CurrentTagsContainer,
|
||||
ErrorContainer,
|
||||
Wrapper,
|
||||
} from './styles';
|
||||
import Tags from './Tag';
|
||||
|
||||
@ -90,33 +89,30 @@ function AllTags({
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Wrapper>
|
||||
<Typography>Tags</Typography>
|
||||
<Typography>Tags</Typography>
|
||||
|
||||
<CurrentTagsContainer>
|
||||
{localSelectedTags.map((tags, index) => (
|
||||
<Tags
|
||||
key={tags.Key.join(',')}
|
||||
tag={tags}
|
||||
index={index}
|
||||
onCloseHandler={(): void => onCloseHandler(index)}
|
||||
setLocalSelectedTags={setLocalSelectedTags}
|
||||
localSelectedTags={localSelectedTags}
|
||||
/>
|
||||
))}
|
||||
</CurrentTagsContainer>
|
||||
<CurrentTagsContainer>
|
||||
{localSelectedTags.map((tags, index) => (
|
||||
<Tags
|
||||
key={tags.Key.join(',')}
|
||||
tag={tags}
|
||||
index={index}
|
||||
onCloseHandler={(): void => onCloseHandler(index)}
|
||||
setLocalSelectedTags={setLocalSelectedTags}
|
||||
localSelectedTags={localSelectedTags}
|
||||
/>
|
||||
))}
|
||||
</CurrentTagsContainer>
|
||||
|
||||
<Space wrap direction="horizontal">
|
||||
<Button type="primary" onClick={onTagAddHandler} icon={<PlusOutlined />}>
|
||||
Add Tags Filter
|
||||
</Button>
|
||||
<Space wrap direction="horizontal">
|
||||
<Button type="primary" onClick={onTagAddHandler} icon={<PlusOutlined />}>
|
||||
Add Tags Filter
|
||||
</Button>
|
||||
|
||||
<Text ellipsis>
|
||||
Results will include spans with ALL the specified tags ( Rows are `ANDed`
|
||||
)
|
||||
</Text>
|
||||
</Space>
|
||||
</Wrapper>
|
||||
<Text ellipsis>
|
||||
Results will include spans with ALL the specified tags ( Rows are `ANDed` )
|
||||
</Text>
|
||||
</Space>
|
||||
|
||||
<ButtonContainer>
|
||||
<Space align="start">
|
||||
|
@ -2,25 +2,15 @@ import { Card } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const Container = styled(Card)`
|
||||
top: 120%;
|
||||
min-height: 20vh;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
position: absolute !important;
|
||||
|
||||
.ant-card-body {
|
||||
padding-bottom: 0;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
min-width: 81.5vw;
|
||||
`;
|
||||
|
||||
export const ErrorContainer = styled(Card)`
|
||||
top: 120%;
|
||||
min-height: 20vh;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -28,13 +18,6 @@ export const ErrorContainer = styled(Card)`
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
&&& {
|
||||
padding-right: 2rem;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ButtonContainer = styled(Card)`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
@ -45,6 +28,10 @@ export const ButtonContainer = styled(Card)`
|
||||
padding-right: 38.01px !important;
|
||||
|
||||
margin-top: 1rem !important;
|
||||
|
||||
.ant-card-body {
|
||||
padding: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const CurrentTagsContainer = styled.div`
|
||||
|
1
frontend/src/container/Trace/Search/config.ts
Normal file
1
frontend/src/container/Trace/Search/config.ts
Normal file
@ -0,0 +1 @@
|
||||
export const contentStyle = { padding: 0 };
|
@ -1,5 +1,5 @@
|
||||
import { CaretRightFilled } from '@ant-design/icons';
|
||||
import useClickOutside from 'hooks/useClickOutside';
|
||||
import { Popover } from 'antd';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { connect, useDispatch, useSelector } from 'react-redux';
|
||||
import { bindActionCreators, Dispatch } from 'redux';
|
||||
@ -13,6 +13,7 @@ import { UPDATE_ALL_FILTERS } from 'types/actions/trace';
|
||||
import { TraceReducer } from 'types/reducer/trace';
|
||||
|
||||
import Tags from './AllTags';
|
||||
import { contentStyle } from './config';
|
||||
import { Container, SearchComponent } from './styles';
|
||||
import { parseQueryToTags, parseTagsToQuery } from './util';
|
||||
|
||||
@ -42,33 +43,6 @@ function Search({
|
||||
|
||||
const tagRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useClickOutside(tagRef, (e: HTMLElement) => {
|
||||
// using this hack as overlay span is voilating this condition
|
||||
if (
|
||||
e.nodeName === 'svg' ||
|
||||
e.nodeName === 'path' ||
|
||||
e.nodeName === 'span' ||
|
||||
e.nodeName === 'button'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
e.nodeName === 'DIV' &&
|
||||
![
|
||||
'ant-select-item-option-content',
|
||||
'ant-empty-image',
|
||||
'ant-select-item',
|
||||
'ant-col',
|
||||
'ant-select-item-option-active',
|
||||
].find((p) => p.indexOf(e.className) !== -1) &&
|
||||
!(e.ariaSelected === 'true') &&
|
||||
traces.isTagModalOpen
|
||||
) {
|
||||
updateTagVisibility(false);
|
||||
}
|
||||
});
|
||||
|
||||
const onChangeHandler = (search: string): void => {
|
||||
setValue(search);
|
||||
};
|
||||
@ -77,11 +51,6 @@ function Search({
|
||||
updateTagVisibility(value);
|
||||
};
|
||||
|
||||
const onFocusHandler: React.FocusEventHandler<HTMLInputElement> = (e) => {
|
||||
e.preventDefault();
|
||||
setIsTagsModalHandler(true);
|
||||
};
|
||||
|
||||
const updateFilters = async (
|
||||
selectedTags: TraceReducer['selectedTags'],
|
||||
): Promise<void> => {
|
||||
@ -116,37 +85,45 @@ function Search({
|
||||
|
||||
return (
|
||||
<Container ref={tagRef}>
|
||||
<SearchComponent
|
||||
onChange={(event): void => onChangeHandler(event.target.value)}
|
||||
value={value}
|
||||
allowClear
|
||||
disabled={traces.filterLoading}
|
||||
onFocus={onFocusHandler}
|
||||
placeholder="Click to filter by tags"
|
||||
type="search"
|
||||
enterButton={<CaretRightFilled />}
|
||||
onSearch={(string): void => {
|
||||
if (string.length === 0) {
|
||||
updateTagVisibility(false);
|
||||
updateFilters([]);
|
||||
return;
|
||||
}
|
||||
<Popover
|
||||
placement="bottomLeft"
|
||||
destroyTooltipOnHide
|
||||
open={traces.isTagModalOpen}
|
||||
trigger="click"
|
||||
onOpenChange={setIsTagsModalHandler}
|
||||
showArrow={false}
|
||||
overlayInnerStyle={contentStyle}
|
||||
content={
|
||||
<Tags updateFilters={updateFilters} onChangeHandler={onChangeHandler} />
|
||||
}
|
||||
>
|
||||
<SearchComponent
|
||||
onChange={(event): void => onChangeHandler(event.target.value)}
|
||||
value={value}
|
||||
allowClear
|
||||
disabled={traces.filterLoading}
|
||||
placeholder="Click to filter by tags"
|
||||
type="search"
|
||||
enterButton={<CaretRightFilled />}
|
||||
onSearch={(string): void => {
|
||||
if (string.length === 0) {
|
||||
updateTagVisibility(false);
|
||||
updateFilters([]);
|
||||
return;
|
||||
}
|
||||
|
||||
const { isError, payload } = parseQueryToTags(string);
|
||||
const { isError, payload } = parseQueryToTags(string);
|
||||
|
||||
if (isError) {
|
||||
updateTagIsError(true);
|
||||
} else {
|
||||
updateTagIsError(false);
|
||||
updateTagVisibility(false);
|
||||
updateFilters(payload);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{traces.isTagModalOpen && (
|
||||
<Tags updateFilters={updateFilters} onChangeHandler={onChangeHandler} />
|
||||
)}
|
||||
if (isError) {
|
||||
updateTagIsError(true);
|
||||
} else {
|
||||
updateTagIsError(false);
|
||||
updateTagVisibility(false);
|
||||
updateFilters(payload);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Popover>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
|
||||
const useClickOutside = (
|
||||
ref: React.RefObject<HTMLElement>,
|
||||
callback: (e: HTMLElement) => void | null,
|
||||
): void => {
|
||||
const listener = useCallback(
|
||||
(e: Event) => {
|
||||
const node = e?.target as HTMLElement;
|
||||
|
||||
if (ref.current && !ref.current.contains(node) && callback) {
|
||||
callback(node);
|
||||
}
|
||||
},
|
||||
[callback, ref],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('click', listener);
|
||||
|
||||
return (): void => {
|
||||
document.removeEventListener('click', listener);
|
||||
};
|
||||
}, [ref, callback, listener]);
|
||||
};
|
||||
|
||||
export default useClickOutside;
|
Loading…
x
Reference in New Issue
Block a user