mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 04:35:58 +08:00
feat: add the options menu (#2832)
Co-authored-by: Nazarenko19 <danil.nazarenko2000@gmail.com> Co-authored-by: Palash Gupta <palashgdev@gmail.com>
This commit is contained in:
parent
e5bb125a55
commit
7415de4751
11
frontend/public/locales/en-GB/trace.json
Normal file
11
frontend/public/locales/en-GB/trace.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"options_menu": {
|
||||||
|
"options": "Options",
|
||||||
|
"format": "Format",
|
||||||
|
"row": "Row",
|
||||||
|
"default": "Default",
|
||||||
|
"column": "Column",
|
||||||
|
"maxLines": "Max lines per Row",
|
||||||
|
"addColumn": "Add a column"
|
||||||
|
}
|
||||||
|
}
|
11
frontend/public/locales/en/trace.json
Normal file
11
frontend/public/locales/en/trace.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"options_menu": {
|
||||||
|
"options": "Options",
|
||||||
|
"format": "Format",
|
||||||
|
"row": "Row",
|
||||||
|
"default": "Default",
|
||||||
|
"column": "Column",
|
||||||
|
"maxLines": "Max lines per Row",
|
||||||
|
"addColumn": "Add a column"
|
||||||
|
}
|
||||||
|
}
|
43
frontend/src/container/OptionsMenu/AddColumnField/index.tsx
Normal file
43
frontend/src/container/OptionsMenu/AddColumnField/index.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { SearchOutlined } from '@ant-design/icons';
|
||||||
|
import { Input } from 'antd';
|
||||||
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { OptionsMenuConfig } from '..';
|
||||||
|
import { FieldTitle } from '../styles';
|
||||||
|
import { AddColumnSelect, AddColumnWrapper, SearchIconWrapper } from './styles';
|
||||||
|
|
||||||
|
function AddColumnField({ config }: AddColumnFieldProps): JSX.Element | null {
|
||||||
|
const { t } = useTranslation(['trace']);
|
||||||
|
const isDarkMode = useIsDarkMode();
|
||||||
|
|
||||||
|
if (!config) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AddColumnWrapper direction="vertical">
|
||||||
|
<FieldTitle>{t('options_menu.addColumn')}</FieldTitle>
|
||||||
|
|
||||||
|
<Input.Group compact>
|
||||||
|
<AddColumnSelect
|
||||||
|
allowClear
|
||||||
|
maxTagCount={0}
|
||||||
|
size="small"
|
||||||
|
mode="multiple"
|
||||||
|
placeholder="Search"
|
||||||
|
options={config.options}
|
||||||
|
value={config.value}
|
||||||
|
onChange={config.onChange}
|
||||||
|
/>
|
||||||
|
<SearchIconWrapper $isDarkMode={isDarkMode}>
|
||||||
|
<SearchOutlined />
|
||||||
|
</SearchIconWrapper>
|
||||||
|
</Input.Group>
|
||||||
|
</AddColumnWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddColumnFieldProps {
|
||||||
|
config: OptionsMenuConfig['addColumn'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddColumnField;
|
28
frontend/src/container/OptionsMenu/AddColumnField/styles.ts
Normal file
28
frontend/src/container/OptionsMenu/AddColumnField/styles.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { Card, Select, SelectProps, Space } from 'antd';
|
||||||
|
import { themeColors } from 'constants/theme';
|
||||||
|
import { FunctionComponent } from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
export const SearchIconWrapper = styled(Card)<{ $isDarkMode: boolean }>`
|
||||||
|
width: 15%;
|
||||||
|
border-color: ${({ $isDarkMode }): string =>
|
||||||
|
$isDarkMode ? themeColors.borderDarkGrey : themeColors.borderLightGrey};
|
||||||
|
|
||||||
|
.ant-card-body {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.25rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AddColumnSelect: FunctionComponent<SelectProps> = styled(
|
||||||
|
Select,
|
||||||
|
)<SelectProps>`
|
||||||
|
width: 85%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AddColumnWrapper = styled(Space)`
|
||||||
|
width: 100%;
|
||||||
|
`;
|
33
frontend/src/container/OptionsMenu/FormatField/index.tsx
Normal file
33
frontend/src/container/OptionsMenu/FormatField/index.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { OptionsMenuConfig } from '..';
|
||||||
|
import { FieldTitle } from '../styles';
|
||||||
|
import { FormatFieldWrapper, RadioButton, RadioGroup } from './styles';
|
||||||
|
|
||||||
|
function FormatField({ config }: FormatFieldProps): JSX.Element | null {
|
||||||
|
const { t } = useTranslation(['trace']);
|
||||||
|
|
||||||
|
if (!config) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormatFieldWrapper direction="vertical">
|
||||||
|
<FieldTitle>{t('options_menu.format')}</FieldTitle>
|
||||||
|
<RadioGroup
|
||||||
|
size="small"
|
||||||
|
buttonStyle="solid"
|
||||||
|
value={config.value}
|
||||||
|
onChange={config.onChange}
|
||||||
|
>
|
||||||
|
<RadioButton value="row">{t('options_menu.row')}</RadioButton>
|
||||||
|
<RadioButton value="default">{t('options_menu.default')}</RadioButton>
|
||||||
|
<RadioButton value="column">{t('options_menu.column')}</RadioButton>
|
||||||
|
</RadioGroup>
|
||||||
|
</FormatFieldWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FormatFieldProps {
|
||||||
|
config: OptionsMenuConfig['format'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FormatField;
|
17
frontend/src/container/OptionsMenu/FormatField/styles.ts
Normal file
17
frontend/src/container/OptionsMenu/FormatField/styles.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Radio, Space } from 'antd';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
export const FormatFieldWrapper = styled(Space)`
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 1.125rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const RadioGroup = styled(Radio.Group)`
|
||||||
|
display: flex;
|
||||||
|
text-align: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const RadioButton = styled(Radio.Button)`
|
||||||
|
font-size: 0.75rem;
|
||||||
|
flex: 1;
|
||||||
|
`;
|
29
frontend/src/container/OptionsMenu/MaxLinesField/index.tsx
Normal file
29
frontend/src/container/OptionsMenu/MaxLinesField/index.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { OptionsMenuConfig } from '..';
|
||||||
|
import { FieldTitle } from '../styles';
|
||||||
|
import { MaxLinesFieldWrapper, MaxLinesInput } from './styles';
|
||||||
|
|
||||||
|
function MaxLinesField({ config }: MaxLinesFieldProps): JSX.Element | null {
|
||||||
|
const { t } = useTranslation(['trace']);
|
||||||
|
|
||||||
|
if (!config) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MaxLinesFieldWrapper>
|
||||||
|
<FieldTitle>{t('options_menu.maxLines')}</FieldTitle>
|
||||||
|
<MaxLinesInput
|
||||||
|
controls
|
||||||
|
size="small"
|
||||||
|
value={config.value}
|
||||||
|
onChange={config.onChange}
|
||||||
|
/>
|
||||||
|
</MaxLinesFieldWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MaxLinesFieldProps {
|
||||||
|
config: OptionsMenuConfig['maxLines'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MaxLinesField;
|
12
frontend/src/container/OptionsMenu/MaxLinesField/styles.ts
Normal file
12
frontend/src/container/OptionsMenu/MaxLinesField/styles.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { InputNumber } from 'antd';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
export const MaxLinesFieldWrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const MaxLinesInput = styled(InputNumber)`
|
||||||
|
max-width: 46px;
|
||||||
|
`;
|
57
frontend/src/container/OptionsMenu/index.tsx
Normal file
57
frontend/src/container/OptionsMenu/index.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { SettingFilled, SettingOutlined } from '@ant-design/icons';
|
||||||
|
import {
|
||||||
|
InputNumberProps,
|
||||||
|
Popover,
|
||||||
|
RadioProps,
|
||||||
|
SelectProps,
|
||||||
|
Space,
|
||||||
|
} from 'antd';
|
||||||
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import AddColumnField from './AddColumnField';
|
||||||
|
import FormatField from './FormatField';
|
||||||
|
import MaxLinesField from './MaxLinesField';
|
||||||
|
import { OptionsContainer, OptionsContentWrapper } from './styles';
|
||||||
|
|
||||||
|
function OptionsMenu({ config }: OptionsMenuProps): JSX.Element {
|
||||||
|
const { t } = useTranslation(['trace']);
|
||||||
|
const isDarkMode = useIsDarkMode();
|
||||||
|
|
||||||
|
const OptionsContent = useMemo(
|
||||||
|
() => (
|
||||||
|
<OptionsContentWrapper direction="vertical">
|
||||||
|
{config?.format && <FormatField config={config.format} />}
|
||||||
|
{config?.maxLines && <MaxLinesField config={config.maxLines} />}
|
||||||
|
{config?.addColumn && <AddColumnField config={config.addColumn} />}
|
||||||
|
</OptionsContentWrapper>
|
||||||
|
),
|
||||||
|
[config],
|
||||||
|
);
|
||||||
|
|
||||||
|
const SettingIcon = isDarkMode ? SettingOutlined : SettingFilled;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<OptionsContainer>
|
||||||
|
<Popover placement="bottom" trigger="click" content={OptionsContent}>
|
||||||
|
<Space align="center">
|
||||||
|
{t('options_menu.options')}
|
||||||
|
<SettingIcon />
|
||||||
|
</Space>
|
||||||
|
</Popover>
|
||||||
|
</OptionsContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OptionsMenuConfig = {
|
||||||
|
format?: Pick<RadioProps, 'value' | 'onChange'>;
|
||||||
|
maxLines?: Pick<InputNumberProps, 'value' | 'onChange'>;
|
||||||
|
addColumn?: Pick<SelectProps, 'options' | 'value' | 'onChange'>;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface OptionsMenuProps {
|
||||||
|
config: OptionsMenuConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OptionsMenu;
|
19
frontend/src/container/OptionsMenu/styles.ts
Normal file
19
frontend/src/container/OptionsMenu/styles.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Card, Space, Typography } from 'antd';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
export const OptionsContainer = styled(Card)`
|
||||||
|
.ant-card-body {
|
||||||
|
display: flex;
|
||||||
|
padding: 0.25rem 0.938rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const OptionsContentWrapper = styled(Space)`
|
||||||
|
min-width: 11rem;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const FieldTitle = styled(Typography.Text)`
|
||||||
|
font-size: 0.75rem;
|
||||||
|
`;
|
Loading…
x
Reference in New Issue
Block a user