mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 17:09:03 +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