diff --git a/frontend/public/locales/en-GB/trace.json b/frontend/public/locales/en-GB/trace.json new file mode 100644 index 0000000000..587f565a21 --- /dev/null +++ b/frontend/public/locales/en-GB/trace.json @@ -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" + } +} diff --git a/frontend/public/locales/en/trace.json b/frontend/public/locales/en/trace.json new file mode 100644 index 0000000000..587f565a21 --- /dev/null +++ b/frontend/public/locales/en/trace.json @@ -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" + } +} diff --git a/frontend/src/container/OptionsMenu/AddColumnField/index.tsx b/frontend/src/container/OptionsMenu/AddColumnField/index.tsx new file mode 100644 index 0000000000..2e789a1024 --- /dev/null +++ b/frontend/src/container/OptionsMenu/AddColumnField/index.tsx @@ -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 ( + + {t('options_menu.addColumn')} + + + + + + + + + ); +} + +interface AddColumnFieldProps { + config: OptionsMenuConfig['addColumn']; +} + +export default AddColumnField; diff --git a/frontend/src/container/OptionsMenu/AddColumnField/styles.ts b/frontend/src/container/OptionsMenu/AddColumnField/styles.ts new file mode 100644 index 0000000000..72df5467af --- /dev/null +++ b/frontend/src/container/OptionsMenu/AddColumnField/styles.ts @@ -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 = styled( + Select, +)` + width: 85%; +`; + +export const AddColumnWrapper = styled(Space)` + width: 100%; +`; diff --git a/frontend/src/container/OptionsMenu/FormatField/index.tsx b/frontend/src/container/OptionsMenu/FormatField/index.tsx new file mode 100644 index 0000000000..09e6743ade --- /dev/null +++ b/frontend/src/container/OptionsMenu/FormatField/index.tsx @@ -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 ( + + {t('options_menu.format')} + + {t('options_menu.row')} + {t('options_menu.default')} + {t('options_menu.column')} + + + ); +} + +interface FormatFieldProps { + config: OptionsMenuConfig['format']; +} + +export default FormatField; diff --git a/frontend/src/container/OptionsMenu/FormatField/styles.ts b/frontend/src/container/OptionsMenu/FormatField/styles.ts new file mode 100644 index 0000000000..d98270a80f --- /dev/null +++ b/frontend/src/container/OptionsMenu/FormatField/styles.ts @@ -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; +`; diff --git a/frontend/src/container/OptionsMenu/MaxLinesField/index.tsx b/frontend/src/container/OptionsMenu/MaxLinesField/index.tsx new file mode 100644 index 0000000000..7c10423f53 --- /dev/null +++ b/frontend/src/container/OptionsMenu/MaxLinesField/index.tsx @@ -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 ( + + {t('options_menu.maxLines')} + + + ); +} + +interface MaxLinesFieldProps { + config: OptionsMenuConfig['maxLines']; +} + +export default MaxLinesField; diff --git a/frontend/src/container/OptionsMenu/MaxLinesField/styles.ts b/frontend/src/container/OptionsMenu/MaxLinesField/styles.ts new file mode 100644 index 0000000000..6c177ff5a4 --- /dev/null +++ b/frontend/src/container/OptionsMenu/MaxLinesField/styles.ts @@ -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; +`; diff --git a/frontend/src/container/OptionsMenu/index.tsx b/frontend/src/container/OptionsMenu/index.tsx new file mode 100644 index 0000000000..96059ef06c --- /dev/null +++ b/frontend/src/container/OptionsMenu/index.tsx @@ -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( + () => ( + + {config?.format && } + {config?.maxLines && } + {config?.addColumn && } + + ), + [config], + ); + + const SettingIcon = isDarkMode ? SettingOutlined : SettingFilled; + + return ( + + + + {t('options_menu.options')} + + + + + ); +} + +export type OptionsMenuConfig = { + format?: Pick; + maxLines?: Pick; + addColumn?: Pick; +}; + +interface OptionsMenuProps { + config: OptionsMenuConfig; +} + +export default OptionsMenu; diff --git a/frontend/src/container/OptionsMenu/styles.ts b/frontend/src/container/OptionsMenu/styles.ts new file mode 100644 index 0000000000..08530660b7 --- /dev/null +++ b/frontend/src/container/OptionsMenu/styles.ts @@ -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; +`;