diff --git a/web/locales/en/plugin__netobserv-plugin.json b/web/locales/en/plugin__netobserv-plugin.json index 1f60c2e64..c2bad9282 100644 --- a/web/locales/en/plugin__netobserv-plugin.json +++ b/web/locales/en/plugin__netobserv-plugin.json @@ -45,12 +45,13 @@ "Dropped packets": "Dropped packets", "DNS latencies": "DNS latencies", "RTT": "RTT", + "Display options": "Display options", "The level of details represented.": "The level of details represented.", "Scope": "Scope", "Long labels can reduce visibility.": "Long labels can reduce visibility.", "Truncate labels": "Truncate labels", "Single graph focus": "Single graph focus", - "Display options": "Display options", + "Query options": "Query options", "Conversation": "Conversation", "Flow": "Flow", "Loki": "Loki", @@ -87,7 +88,6 @@ "Depending on the matching and filter settings, several queries can be performed under the cover, each with this parameter set, resulting in more results after aggregation.": "Depending on the matching and filter settings, several queries can be performed under the cover, each with this parameter set, resulting in more results after aggregation.", "Top / Bottom": "Top / Bottom", "Limit": "Limit", - "Query options": "Query options", "Refresh off": "Refresh off", "15 seconds": "15 seconds", "30 seconds": "30 seconds", @@ -298,6 +298,7 @@ "Name": "Name", "IP": "IP", "No information available for this content. Change scope to get more details.": "No information available for this content. Change scope to get more details.", + "Cluster name": "Cluster name", "Stats": "Stats", "Top 5 DNS latency": "Top 5 DNS latency", "Top 5 flow RTT": "Top 5 flow RTT", @@ -311,7 +312,6 @@ "Average rate": "Average rate", "Latest time": "Latest time", "Latest rate": "Latest rate", - "Cluster name": "Cluster name", "Edge": "Edge", "Drops": "Drops", "Query is slow": "Query is slow", diff --git a/web/src/components/dropdowns/__tests__/group-dropdown.spec.tsx b/web/src/components/dropdowns/__tests__/group-dropdown.spec.tsx index aeb230bad..40a630b63 100644 --- a/web/src/components/dropdowns/__tests__/group-dropdown.spec.tsx +++ b/web/src/components/dropdowns/__tests__/group-dropdown.spec.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import { FlowScope } from '../../../model/flow-query'; import { MetricScopeOptions } from '../../../model/metrics'; import { TopologyGroupTypes } from '../../../model/topology'; -import GroupDropdown from '../group-dropdown'; +import { GroupDropdown } from '../group-dropdown'; describe('', () => { const props = { diff --git a/web/src/components/dropdowns/__tests__/layout-dropdown.spec.tsx b/web/src/components/dropdowns/__tests__/layout-dropdown.spec.tsx index d100417cd..ee995d8ce 100644 --- a/web/src/components/dropdowns/__tests__/layout-dropdown.spec.tsx +++ b/web/src/components/dropdowns/__tests__/layout-dropdown.spec.tsx @@ -2,7 +2,7 @@ import { mount, shallow } from 'enzyme'; import * as React from 'react'; import { LayoutName } from '../../../model/topology'; -import LayoutDropdown from '../layout-dropdown'; +import { LayoutDropdown } from '../layout-dropdown'; describe('', () => { const props = { diff --git a/web/src/components/dropdowns/__tests__/metric-function-dropdown.spec.tsx b/web/src/components/dropdowns/__tests__/metric-function-dropdown.spec.tsx index 9705bd49c..1ad2cbb69 100644 --- a/web/src/components/dropdowns/__tests__/metric-function-dropdown.spec.tsx +++ b/web/src/components/dropdowns/__tests__/metric-function-dropdown.spec.tsx @@ -1,7 +1,7 @@ import { mount, shallow } from 'enzyme'; import * as React from 'react'; -import MetricFunctionDropdown from '../metric-function-dropdown'; +import { MetricFunctionDropdown } from '../metric-function-dropdown'; describe('', () => { const props = { diff --git a/web/src/components/dropdowns/__tests__/metric-type-dropdown.spec.tsx b/web/src/components/dropdowns/__tests__/metric-type-dropdown.spec.tsx index 6d8febab7..528e6b546 100644 --- a/web/src/components/dropdowns/__tests__/metric-type-dropdown.spec.tsx +++ b/web/src/components/dropdowns/__tests__/metric-type-dropdown.spec.tsx @@ -1,7 +1,7 @@ import { mount, shallow } from 'enzyme'; import * as React from 'react'; -import MetricTypeDropdown from '../metric-type-dropdown'; +import { MetricTypeDropdown } from '../metric-type-dropdown'; describe('', () => { const props = { diff --git a/web/src/components/dropdowns/__tests__/query-options-dropdown.spec.tsx b/web/src/components/dropdowns/__tests__/query-options-dropdown.spec.tsx index 4e5b48317..0634b5937 100644 --- a/web/src/components/dropdowns/__tests__/query-options-dropdown.spec.tsx +++ b/web/src/components/dropdowns/__tests__/query-options-dropdown.spec.tsx @@ -2,10 +2,11 @@ import { Checkbox, Radio, Select } from '@patternfly/react-core'; import { shallow } from 'enzyme'; import * as React from 'react'; import { act } from 'react-dom/test-utils'; -import QueryOptionsDropdown, { QueryOptionsDropdownProps, QueryOptionsPanel } from '../query-options-dropdown'; +import { QueryOptionsDropdown, QueryOptionsProps } from '../query-options-dropdown'; +import { QueryOptionsPanel } from '../query-options-panel'; describe('', () => { - const props: QueryOptionsDropdownProps = { + const props: QueryOptionsProps = { recordType: 'allConnections', dataSource: 'auto', showDuplicates: true, @@ -35,7 +36,7 @@ describe('', () => { }); describe('', () => { - const props: QueryOptionsDropdownProps = { + const props: QueryOptionsProps = { recordType: 'allConnections', dataSource: 'auto', showDuplicates: true, diff --git a/web/src/components/dropdowns/__tests__/refresh-dropdown.spec.tsx b/web/src/components/dropdowns/__tests__/refresh-dropdown.spec.tsx index 41b8c0c67..381f52b36 100644 --- a/web/src/components/dropdowns/__tests__/refresh-dropdown.spec.tsx +++ b/web/src/components/dropdowns/__tests__/refresh-dropdown.spec.tsx @@ -1,7 +1,7 @@ import { mount, shallow } from 'enzyme'; import * as React from 'react'; -import RefreshDropdown, { RefreshDropdownProps } from '../refresh-dropdown'; +import { RefreshDropdown, RefreshDropdownProps } from '../refresh-dropdown'; describe('', () => { const props: RefreshDropdownProps = { diff --git a/web/src/components/dropdowns/__tests__/table-display-dropdown.spec.tsx b/web/src/components/dropdowns/__tests__/table-display-dropdown.spec.tsx index 1d5ee76f2..e2cdb3cb3 100644 --- a/web/src/components/dropdowns/__tests__/table-display-dropdown.spec.tsx +++ b/web/src/components/dropdowns/__tests__/table-display-dropdown.spec.tsx @@ -3,7 +3,8 @@ import { mount, shallow } from 'enzyme'; import * as React from 'react'; import { act } from 'react-dom/test-utils'; -import { Size, TableDisplayDropdown, TableDisplayOptions } from '../table-display-dropdown'; +import { Size, TableDisplayDropdown } from '../table-display-dropdown'; +import { TableDisplayOptions } from '../table-display-options'; describe('', () => { const props = { diff --git a/web/src/components/dropdowns/__tests__/time-range-dropdown.spec.tsx b/web/src/components/dropdowns/__tests__/time-range-dropdown.spec.tsx index b20a47dd1..d04b0f5a3 100644 --- a/web/src/components/dropdowns/__tests__/time-range-dropdown.spec.tsx +++ b/web/src/components/dropdowns/__tests__/time-range-dropdown.spec.tsx @@ -1,7 +1,7 @@ import { mount, shallow } from 'enzyme'; import * as React from 'react'; -import TimeRangeDropdown, { TimeRangeDropdownProps } from '../time-range-dropdown'; +import { TimeRangeDropdown, TimeRangeDropdownProps } from '../time-range-dropdown'; describe('', () => { const props: TimeRangeDropdownProps = { diff --git a/web/src/components/dropdowns/overview-display-dropdown.tsx b/web/src/components/dropdowns/overview-display-dropdown.tsx index 0d3ce926a..a530267d9 100644 --- a/web/src/components/dropdowns/overview-display-dropdown.tsx +++ b/web/src/components/dropdowns/overview-display-dropdown.tsx @@ -1,16 +1,14 @@ -import { Select, Switch, Text, TextVariants, Tooltip } from '@patternfly/react-core'; -import { InfoAltIcon } from '@patternfly/react-icons'; +import { Select, Text, TextVariants } from '@patternfly/react-core'; import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { FlowScope } from '../../model/flow-query'; - import './overview-display-dropdown.css'; -import ScopeDropdown from './scope-dropdown'; -import TruncateDropdown, { TruncateLength } from './truncate-dropdown'; +import { OverviewDisplayOptions } from './overview-display-options'; +import { TruncateLength } from './truncate-dropdown'; export type Size = 's' | 'm' | 'l'; -export interface OverviewDisplayOptionsProps { +export interface OverviewDisplayDropdownProps { metricScope: FlowScope; setMetricScope: (s: FlowScope) => void; truncateLength: TruncateLength; @@ -20,7 +18,7 @@ export interface OverviewDisplayOptionsProps { allowedScopes: FlowScope[]; } -export const OverviewDisplayOptions: React.FC = ({ +export const OverviewDisplayDropdown: React.FC = ({ metricScope, setMetricScope, truncateLength, @@ -30,62 +28,6 @@ export const OverviewDisplayOptions: React.FC = ({ allowedScopes }) => { const { t } = useTranslation('plugin__netobserv-plugin'); - - return ( - <> -
- -
- - {t('Scope')} - -
-
-
- -
-
-
- -
- - {t('Truncate labels')} - -
-
-
- -
-
-
- -
- - ); -}; - -export const OverviewDisplayDropdown: React.FC<{ - metricScope: FlowScope; - setMetricScope: (s: FlowScope) => void; - truncateLength: TruncateLength; - setTruncateLength: (v: TruncateLength) => void; - focus: boolean; - setFocus: (v: boolean) => void; - allowedScopes: FlowScope[]; -}> = ({ metricScope, setMetricScope, truncateLength, setTruncateLength, focus, setFocus, allowedScopes }) => { - const { t } = useTranslation('plugin__netobserv-plugin'); const [isOpen, setOpen] = React.useState(false); return ( diff --git a/web/src/components/dropdowns/overview-display-options.tsx b/web/src/components/dropdowns/overview-display-options.tsx new file mode 100644 index 000000000..d0d5babbf --- /dev/null +++ b/web/src/components/dropdowns/overview-display-options.tsx @@ -0,0 +1,78 @@ +import { Switch, Text, TextVariants, Tooltip } from '@patternfly/react-core'; +import { InfoAltIcon } from '@patternfly/react-icons'; +import * as React from 'react'; +import { useTranslation } from 'react-i18next'; +import { FlowScope } from '../../model/flow-query'; + +import ScopeDropdown from './scope-dropdown'; +import TruncateDropdown, { TruncateLength } from './truncate-dropdown'; + +export type Size = 's' | 'm' | 'l'; + +export interface OverviewDisplayOptionsProps { + metricScope: FlowScope; + setMetricScope: (s: FlowScope) => void; + truncateLength: TruncateLength; + setTruncateLength: (v: TruncateLength) => void; + focus: boolean; + setFocus: (v: boolean) => void; + allowedScopes: FlowScope[]; +} + +export const OverviewDisplayOptions: React.FC = ({ + metricScope, + setMetricScope, + truncateLength, + setTruncateLength, + focus, + setFocus, + allowedScopes +}) => { + const { t } = useTranslation('plugin__netobserv-plugin'); + + return ( + <> +
+ +
+ + {t('Scope')} + +
+
+
+ +
+
+
+ +
+ + {t('Truncate labels')} + +
+
+
+ +
+
+
+ +
+ + ); +}; + +export default OverviewDisplayOptions; diff --git a/web/src/components/dropdowns/query-options-dropdown.tsx b/web/src/components/dropdowns/query-options-dropdown.tsx index a809d7da0..f83ddb281 100644 --- a/web/src/components/dropdowns/query-options-dropdown.tsx +++ b/web/src/components/dropdowns/query-options-dropdown.tsx @@ -1,13 +1,10 @@ -import { Checkbox, Radio, Select, Text, TextContent, TextVariants, Tooltip } from '@patternfly/react-core'; -import { InfoAltIcon } from '@patternfly/react-icons'; +import { Select, Text, TextVariants } from '@patternfly/react-core'; import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { DataSource, Match, PacketLoss, RecordType } from '../../model/flow-query'; +import { QueryOptionsPanel } from './query-options-panel'; -export const topValues = [5, 10, 15]; -export const limitValues = [50, 100, 500, 1000]; - -export interface QueryOptionsDropdownProps { +export interface QueryOptionsProps { recordType: RecordType; setRecordType: (recordType: RecordType) => void; dataSource: DataSource; @@ -30,354 +27,7 @@ export interface QueryOptionsDropdownProps { setPacketLoss: (pl: PacketLoss) => void; } -type RecordTypeOption = { label: string; value: RecordType }; -type DataSourceOption = { label: string; value: DataSource }; -type MatchOption = { label: string; value: Match }; - -type PacketLossOption = { label: string; value: PacketLoss }; - -// Exported for tests -export const QueryOptionsPanel: React.FC = ({ - recordType, - setRecordType, - dataSource, - setDataSource, - showDuplicates, - setShowDuplicates, - allowLoki, - allowProm, - allowFlow, - allowConnection, - allowShowDuplicates, - deduperMark, - allowPktDrops, - useTopK, - limit, - setLimit, - match, - setMatch, - packetLoss, - setPacketLoss -}) => { - const { t } = useTranslation('plugin__netobserv-plugin'); - - const recordTypeOptions: RecordTypeOption[] = [ - { - label: t('Conversation'), - value: 'allConnections' - }, - { - label: t('Flow'), - value: 'flowLog' - } - ]; - - const dataSourceOptions: DataSourceOption[] = [ - { - label: t('Loki'), - value: 'loki' - }, - { - label: t('Prometheus'), - value: 'prom' - }, - { - label: t('Auto'), - value: 'auto' - } - ]; - - const matchOptions: MatchOption[] = [ - { - label: t('Match all'), - value: 'all' - }, - { - label: t('Match any'), - value: 'any' - } - ]; - - const packetLossOptions: PacketLossOption[] = [ - { - label: t('Fully dropped'), - value: 'dropped' - }, - { - label: t('Containing drops'), - value: 'hasDrops' - }, - { - label: t('Without drops'), - value: 'sent' - }, - { - label: t('All'), - value: 'all' - } - ]; - - const values = useTopK ? topValues : limitValues; - - return ( - <> -
- -
- - {t('Log type')} - -
-
- {recordTypeOptions.map(opt => { - const disabled = - (!allowFlow && opt.value === 'flowLog') || (!allowConnection && opt.value === 'allConnections'); - return ( -
- -
- ); - })} -
-
- -
- - {t('Datasource')} - -
-
- {dataSourceOptions.map(opt => { - const disabled = (!allowProm && opt.value === 'prom') || (!allowLoki && opt.value === 'loki'); - return ( -
- -
- ); - })} -
- {deduperMark && ( -
- -
- - {t('Duplicated flows')} - -
-
- -
- )} -
- -
- - {t('Match filters')} - -
-
- {matchOptions.map(opt => ( -
- -
- ))} -
-
- - - {t('Filter flows by their drop status. Only packets dropped by the kernel are monitored here.')} - - - - {t('Fully dropped shows the flows that are 100% dropped')} - - - - {t('Containing drops shows the flows having at least one packet dropped')} - - - - {t('Without drops show the flows having 0% dropped')} - - - - {t('All shows everything')} - - - } - > -
- - {t('Drops filter')} - -
-
- {packetLossOptions.map(opt => { - const disabled = !allowPktDrops && opt.value !== 'all'; - return ( -
- -
- ); - })} -
-
- -
- - {useTopK ? t('Top / Bottom') : t('Limit')} - -
-
- {values.map(l => ( -
- -
- ))} -
- - ); -}; - -export const QueryOptionsDropdown: React.FC = props => { +export const QueryOptionsDropdown: React.FC = props => { const { t } = useTranslation('plugin__netobserv-plugin'); const [isOpen, setOpen] = React.useState(false); return ( diff --git a/web/src/components/dropdowns/query-options-panel.tsx b/web/src/components/dropdowns/query-options-panel.tsx new file mode 100644 index 000000000..cd009a485 --- /dev/null +++ b/web/src/components/dropdowns/query-options-panel.tsx @@ -0,0 +1,358 @@ +import { Checkbox, Radio, Text, TextContent, TextVariants, Tooltip } from '@patternfly/react-core'; +import { InfoAltIcon } from '@patternfly/react-icons'; +import * as React from 'react'; +import { useTranslation } from 'react-i18next'; +import { DataSource, Match, PacketLoss, RecordType } from '../../model/flow-query'; +import { QueryOptionsProps } from './query-options-dropdown'; + +export const topValues = [5, 10, 15]; +export const limitValues = [50, 100, 500, 1000]; + +type RecordTypeOption = { label: string; value: RecordType }; +type DataSourceOption = { label: string; value: DataSource }; +type MatchOption = { label: string; value: Match }; + +type PacketLossOption = { label: string; value: PacketLoss }; + +// Exported for tests +export const QueryOptionsPanel: React.FC = ({ + recordType, + setRecordType, + dataSource, + setDataSource, + showDuplicates, + setShowDuplicates, + allowLoki, + allowProm, + allowFlow, + allowConnection, + allowShowDuplicates, + deduperMark, + allowPktDrops, + useTopK, + limit, + setLimit, + match, + setMatch, + packetLoss, + setPacketLoss +}) => { + const { t } = useTranslation('plugin__netobserv-plugin'); + + const recordTypeOptions: RecordTypeOption[] = [ + { + label: t('Conversation'), + value: 'allConnections' + }, + { + label: t('Flow'), + value: 'flowLog' + } + ]; + + const dataSourceOptions: DataSourceOption[] = [ + { + label: t('Loki'), + value: 'loki' + }, + { + label: t('Prometheus'), + value: 'prom' + }, + { + label: t('Auto'), + value: 'auto' + } + ]; + + const matchOptions: MatchOption[] = [ + { + label: t('Match all'), + value: 'all' + }, + { + label: t('Match any'), + value: 'any' + } + ]; + + const packetLossOptions: PacketLossOption[] = [ + { + label: t('Fully dropped'), + value: 'dropped' + }, + { + label: t('Containing drops'), + value: 'hasDrops' + }, + { + label: t('Without drops'), + value: 'sent' + }, + { + label: t('All'), + value: 'all' + } + ]; + + const values = useTopK ? topValues : limitValues; + + return ( + <> +
+ +
+ + {t('Log type')} + +
+
+ {recordTypeOptions.map(opt => { + const disabled = + (!allowFlow && opt.value === 'flowLog') || (!allowConnection && opt.value === 'allConnections'); + return ( +
+ +
+ ); + })} +
+
+ +
+ + {t('Datasource')} + +
+
+ {dataSourceOptions.map(opt => { + const disabled = (!allowProm && opt.value === 'prom') || (!allowLoki && opt.value === 'loki'); + return ( +
+ +
+ ); + })} +
+ {deduperMark && ( +
+ +
+ + {t('Duplicated flows')} + +
+
+ +
+ )} +
+ +
+ + {t('Match filters')} + +
+
+ {matchOptions.map(opt => ( +
+ +
+ ))} +
+
+ + + {t('Filter flows by their drop status. Only packets dropped by the kernel are monitored here.')} + + + - {t('Fully dropped shows the flows that are 100% dropped')} + + + - {t('Containing drops shows the flows having at least one packet dropped')} + + + - {t('Without drops show the flows having 0% dropped')} + + + - {t('All shows everything')} + + + } + > +
+ + {t('Drops filter')} + +
+
+ {packetLossOptions.map(opt => { + const disabled = !allowPktDrops && opt.value !== 'all'; + return ( +
+ +
+ ); + })} +
+
+ +
+ + {useTopK ? t('Top / Bottom') : t('Limit')} + +
+
+ {values.map(l => ( +
+ +
+ ))} +
+ + ); +}; + +export default QueryOptionsPanel; diff --git a/web/src/components/dropdowns/table-display-dropdown.tsx b/web/src/components/dropdowns/table-display-dropdown.tsx index 7d56cf70f..3cc449d18 100644 --- a/web/src/components/dropdowns/table-display-dropdown.tsx +++ b/web/src/components/dropdowns/table-display-dropdown.tsx @@ -1,62 +1,17 @@ -import { Radio, Select, Text, TextVariants, Tooltip } from '@patternfly/react-core'; -import { InfoAltIcon } from '@patternfly/react-icons'; -import * as _ from 'lodash'; +import { Select, Text, TextVariants } from '@patternfly/react-core'; import * as React from 'react'; import { useTranslation } from 'react-i18next'; import './table-display-dropdown.css'; +import { TableDisplayOptions } from './table-display-options'; export type Size = 's' | 'm' | 'l'; -export interface TableDisplayOptionsProps { +export interface TableDisplayDropdownProps { size: Size; setSize: (v: Size) => void; } -export const TableDisplayOptions: React.FC = ({ size, setSize }) => { - const { t } = useTranslation('plugin__netobserv-plugin'); - - const sizeOptions = { - s: t('Compact'), - m: t('Normal'), - l: t('Large') - }; - - return ( - <> -
- -
- - {t('Row size')} - -
-
- {_.map(sizeOptions, (name, key) => { - return ( -
- -
- ); - })} -
- - ); -}; - -export const TableDisplayDropdown: React.FC<{ - size: Size; - setSize: (v: Size) => void; -}> = ({ size, setSize }) => { +export const TableDisplayDropdown: React.FC = ({ size, setSize }) => { const { t } = useTranslation('plugin__netobserv-plugin'); const [isOpen, setOpen] = React.useState(false); diff --git a/web/src/components/dropdowns/table-display-options.tsx b/web/src/components/dropdowns/table-display-options.tsx new file mode 100644 index 000000000..3e2b7a997 --- /dev/null +++ b/web/src/components/dropdowns/table-display-options.tsx @@ -0,0 +1,55 @@ +import { Radio, Text, TextVariants, Tooltip } from '@patternfly/react-core'; +import { InfoAltIcon } from '@patternfly/react-icons'; +import * as _ from 'lodash'; +import * as React from 'react'; +import { useTranslation } from 'react-i18next'; + +export type Size = 's' | 'm' | 'l'; + +export interface TableDisplayOptionsProps { + size: Size; + setSize: (v: Size) => void; +} + +export const TableDisplayOptions: React.FC = ({ size, setSize }) => { + const { t } = useTranslation('plugin__netobserv-plugin'); + + const sizeOptions = { + s: t('Compact'), + m: t('Normal'), + l: t('Large') + }; + + return ( + <> +
+ +
+ + {t('Row size')} + +
+
+ {_.map(sizeOptions, (name, key) => { + return ( +
+ +
+ ); + })} +
+ + ); +}; + +export default TableDisplayOptions; diff --git a/web/src/components/dropdowns/topology-display-dropdown.tsx b/web/src/components/dropdowns/topology-display-dropdown.tsx index 22ecd4be9..5d97cb073 100644 --- a/web/src/components/dropdowns/topology-display-dropdown.tsx +++ b/web/src/components/dropdowns/topology-display-dropdown.tsx @@ -1,240 +1,10 @@ -import { Checkbox, Flex, FlexItem, Select, Switch, Text, TextVariants, Tooltip } from '@patternfly/react-core'; -import { InfoAltIcon } from '@patternfly/react-icons'; +import { Select, Text, TextVariants } from '@patternfly/react-core'; import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { FlowScope, MetricType, StatFunction } from '../../model/flow-query'; -import { MetricScopeOptions } from '../../model/metrics'; -import { LayoutName, TopologyGroupTypes, TopologyOptions } from '../../model/topology'; -import GroupDropdown from './group-dropdown'; -import LayoutDropdown from './layout-dropdown'; -import TruncateDropdown, { TruncateLength } from './truncate-dropdown'; - -import MetricFunctionDropdown from './metric-function-dropdown'; -import MetricTypeDropdown from './metric-type-dropdown'; -import ScopeDropdown from './scope-dropdown'; +import { TopologyOptions } from '../../model/topology'; import './topology-display-dropdown.css'; - -export type Size = 's' | 'm' | 'l'; - -export interface TopologyDisplayOptionsProps { - metricFunction: StatFunction; - setMetricFunction: (f: StatFunction) => void; - metricType: MetricType; - setMetricType: (t: MetricType) => void; - metricScope: FlowScope; - setMetricScope: (s: FlowScope) => void; - topologyOptions: TopologyOptions; - setTopologyOptions: (o: TopologyOptions) => void; - allowPktDrop: boolean; - allowDNSMetric: boolean; - allowRTTMetric: boolean; - allowedScopes: FlowScope[]; -} - -export const TopologyDisplayOptions: React.FC = ({ - metricFunction, - setMetricFunction, - metricType, - setMetricType, - metricScope, - setMetricScope, - topologyOptions, - setTopologyOptions, - allowPktDrop, - allowDNSMetric, - allowRTTMetric, - allowedScopes -}) => { - const { t } = useTranslation('plugin__netobserv-plugin'); - - const setLayout = (layout: LayoutName) => { - setTopologyOptions({ - ...topologyOptions, - layout - }); - }; - - const setGroupType = (groupTypes: TopologyGroupTypes) => { - setTopologyOptions({ - ...topologyOptions, - groupTypes - }); - }; - - const setTruncateLength = (truncateLength: TruncateLength) => { - setTopologyOptions({ - ...topologyOptions, - truncateLength - }); - }; - - return ( - <> -
- -
- - {t('Edge labels')} - -
-
-
- - - - - - - - -
-
-
- -
- - {t('Scope')} - -
-
-
- -
-
-
- -
- - {t('Groups')} - -
-
-
- -
-
-
- -
- - {t('Layout')} - -
-
-
- -
-
-
- -
- - {t('Show')} - -
-
- - setTopologyOptions({ - ...topologyOptions, - edges: !topologyOptions.edges - }) - } - /> - - setTopologyOptions({ - ...topologyOptions, - edgeTags: !topologyOptions.edgeTags - }) - } - /> - - setTopologyOptions({ - ...topologyOptions, - nodeBadges: !topologyOptions.nodeBadges - }) - } - /> -
-
- -
- - {t('Truncate labels')} - -
-
-
- -
-
-
-
- - setTopologyOptions({ - ...topologyOptions, - startCollapsed: !topologyOptions.startCollapsed - }) - } - isReversed - /> -
-
- - ); -}; +import { TopologyDisplayOptions } from './topology-display-options'; export const TopologyDisplayDropdown: React.FC<{ metricFunction: StatFunction; diff --git a/web/src/components/dropdowns/topology-display-options.tsx b/web/src/components/dropdowns/topology-display-options.tsx new file mode 100644 index 000000000..dfb47294a --- /dev/null +++ b/web/src/components/dropdowns/topology-display-options.tsx @@ -0,0 +1,238 @@ +import { Checkbox, Flex, FlexItem, Switch, Text, TextVariants, Tooltip } from '@patternfly/react-core'; +import { InfoAltIcon } from '@patternfly/react-icons'; +import * as React from 'react'; +import { useTranslation } from 'react-i18next'; +import { FlowScope, MetricType, StatFunction } from '../../model/flow-query'; +import { MetricScopeOptions } from '../../model/metrics'; +import { LayoutName, TopologyGroupTypes, TopologyOptions } from '../../model/topology'; +import GroupDropdown from './group-dropdown'; +import LayoutDropdown from './layout-dropdown'; +import TruncateDropdown, { TruncateLength } from './truncate-dropdown'; + +import MetricFunctionDropdown from './metric-function-dropdown'; +import MetricTypeDropdown from './metric-type-dropdown'; +import ScopeDropdown from './scope-dropdown'; + +export type Size = 's' | 'm' | 'l'; + +export interface TopologyDisplayOptionsProps { + metricFunction: StatFunction; + setMetricFunction: (f: StatFunction) => void; + metricType: MetricType; + setMetricType: (t: MetricType) => void; + metricScope: FlowScope; + setMetricScope: (s: FlowScope) => void; + topologyOptions: TopologyOptions; + setTopologyOptions: (o: TopologyOptions) => void; + allowPktDrop: boolean; + allowDNSMetric: boolean; + allowRTTMetric: boolean; + allowedScopes: FlowScope[]; +} + +export const TopologyDisplayOptions: React.FC = ({ + metricFunction, + setMetricFunction, + metricType, + setMetricType, + metricScope, + setMetricScope, + topologyOptions, + setTopologyOptions, + allowPktDrop, + allowDNSMetric, + allowRTTMetric, + allowedScopes +}) => { + const { t } = useTranslation('plugin__netobserv-plugin'); + + const setLayout = (layout: LayoutName) => { + setTopologyOptions({ + ...topologyOptions, + layout + }); + }; + + const setGroupType = (groupTypes: TopologyGroupTypes) => { + setTopologyOptions({ + ...topologyOptions, + groupTypes + }); + }; + + const setTruncateLength = (truncateLength: TruncateLength) => { + setTopologyOptions({ + ...topologyOptions, + truncateLength + }); + }; + + return ( + <> +
+ +
+ + {t('Edge labels')} + +
+
+
+ + + + + + + + +
+
+
+ +
+ + {t('Scope')} + +
+
+
+ +
+
+
+ +
+ + {t('Groups')} + +
+
+
+ +
+
+
+ +
+ + {t('Layout')} + +
+
+
+ +
+
+
+ +
+ + {t('Show')} + +
+
+ + setTopologyOptions({ + ...topologyOptions, + edges: !topologyOptions.edges + }) + } + /> + + setTopologyOptions({ + ...topologyOptions, + edgeTags: !topologyOptions.edgeTags + }) + } + /> + + setTopologyOptions({ + ...topologyOptions, + nodeBadges: !topologyOptions.nodeBadges + }) + } + /> +
+
+ +
+ + {t('Truncate labels')} + +
+
+
+ +
+
+
+
+ + setTopologyOptions({ + ...topologyOptions, + startCollapsed: !topologyOptions.startCollapsed + }) + } + isReversed + /> +
+
+ + ); +}; + +export default TopologyDisplayOptions; diff --git a/web/src/components/netflow-topology/element-panel-content.tsx b/web/src/components/netflow-topology/element-panel-content.tsx new file mode 100644 index 000000000..8af8dc627 --- /dev/null +++ b/web/src/components/netflow-topology/element-panel-content.tsx @@ -0,0 +1,155 @@ +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionToggle, + Button, + Divider, + Flex, + FlexItem, + Text, + TextContent, + TextVariants +} from '@patternfly/react-core'; +import { FilterIcon, TimesIcon } from '@patternfly/react-icons'; +import { BaseEdge, BaseNode } from '@patternfly/react-topology'; +import * as React from 'react'; +import { useTranslation } from 'react-i18next'; +import { Filter, FilterDefinition } from '../../model/filters'; +import { GraphElementPeer, isElementFiltered, NodeData, toggleElementFilter } from '../../model/topology'; +import { createPeer } from '../../utils/metrics'; +import { ElementFields } from './element-fields'; + +export interface ElementPanelContentProps { + element: GraphElementPeer; + filters: Filter[]; + setFilters: (filters: Filter[]) => void; + filterDefinitions: FilterDefinition[]; +} + +export const ElementPanelContent: React.FC = ({ + element, + filters, + setFilters, + filterDefinitions +}) => { + const { t } = useTranslation('plugin__netobserv-plugin'); + const [hidden, setHidden] = React.useState([]); + const data = element.getData(); + + const toggle = React.useCallback( + (id: string) => { + const index = hidden.indexOf(id); + const newExpanded: string[] = + index >= 0 ? [...hidden.slice(0, index), ...hidden.slice(index + 1, hidden.length)] : [...hidden, id]; + setHidden(newExpanded); + }, + [hidden] + ); + + const clusterName = React.useCallback( + (d: NodeData) => { + if (!d.peer.clusterName) { + return <>; + } + const fields = createPeer({ clusterName: d.peer.clusterName }); + const isFiltered = isElementFiltered(fields, filters, filterDefinitions); + return ( + + {t('Cluster name')} + + {d.peer.clusterName} + +