diff --git a/x-pack/plugins/infra/public/components/toolbar_panel.ts b/x-pack/plugins/infra/public/components/toolbar_panel.ts
new file mode 100644
index 0000000000000..65cde03ec98e7
--- /dev/null
+++ b/x-pack/plugins/infra/public/components/toolbar_panel.ts
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EuiPanel } from '@elastic/eui';
+import { euiStyled } from '../../../observability/public';
+
+export const ToolbarPanel = euiStyled(EuiPanel).attrs(() => ({
+ grow: false,
+ paddingSize: 'none',
+}))`
+ border-top: none;
+ border-right: none;
+ border-left: none;
+ border-radius: 0;
+ padding: ${props => `12px ${props.theme.eui.paddingSizes.m}`};
+`;
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/dropdown_button.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/dropdown_button.tsx
new file mode 100644
index 0000000000000..f0bc404dc3797
--- /dev/null
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/dropdown_button.tsx
@@ -0,0 +1,53 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
+import React, { ReactNode } from 'react';
+import { withTheme, EuiTheme } from '../../../../../../observability/public';
+
+interface Props {
+ label: string;
+ onClick: () => void;
+ theme: EuiTheme;
+ children: ReactNode;
+}
+
+export const DropdownButton = withTheme(({ onClick, label, theme, children }: Props) => {
+ return (
+
+
+ {label}
+
+
+
+ {children}
+
+
+
+ );
+});
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/toolbar.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/filter_bar.tsx
similarity index 57%
rename from x-pack/plugins/infra/public/pages/metrics/inventory_view/toolbar.tsx
rename to x-pack/plugins/infra/public/pages/metrics/inventory_view/components/filter_bar.tsx
index d6a87a0197f5f..708d5f7d75907 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/toolbar.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/filter_bar.tsx
@@ -7,17 +7,13 @@
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React from 'react';
-import { Toolbar } from '../../../components/eui/toolbar';
-import { WaffleTimeControls } from './components/waffle/waffle_time_controls';
-import { WaffleInventorySwitcher } from './components/waffle/waffle_inventory_switcher';
-import { SearchBar } from './components/search_bar';
+import { WaffleTimeControls } from './waffle/waffle_time_controls';
+import { SearchBar } from './search_bar';
+import { ToolbarPanel } from '../../../../components/toolbar_panel';
-export const SnapshotToolbar = () => (
-
+export const FilterBar = () => (
+
-
-
-
@@ -25,5 +21,5 @@ export const SnapshotToolbar = () => (
-
+
);
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/layout.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/layout.tsx
index bc8be9862fe63..a71e43874b480 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/layout.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/layout.tsx
@@ -4,20 +4,26 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
+import React, { useCallback } from 'react';
import { useInterval } from 'react-use';
-import { euiPaletteColorBlind } from '@elastic/eui';
-import { NodesOverview } from './nodes_overview';
-import { Toolbar } from './toolbars/toolbar';
+import { euiPaletteColorBlind, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import { convertIntervalToString } from '../../../../utils/convert_interval_to_string';
+import { NodesOverview, calculateBoundsFromNodes } from './nodes_overview';
import { PageContent } from '../../../../components/page';
import { useSnapshot } from '../hooks/use_snaphot';
-import { useInventoryMeta } from '../hooks/use_inventory_meta';
import { useWaffleTimeContext } from '../hooks/use_waffle_time';
import { useWaffleFiltersContext } from '../hooks/use_waffle_filters';
import { useWaffleOptionsContext } from '../hooks/use_waffle_options';
import { useSourceContext } from '../../../../containers/source';
import { InfraFormatterType, InfraWaffleMapGradientLegend } from '../../../../lib/lib';
+import { euiStyled } from '../../../../../../observability/public';
+import { Toolbar } from './toolbars/toolbar';
+import { ViewSwitcher } from './waffle/view_switcher';
+import { SavedViews } from './saved_views';
+import { IntervalLabel } from './waffle/interval_label';
+import { Legend } from './waffle/legend';
+import { createInventoryMetricFormatter } from '../lib/create_inventory_metric_formatter';
const euiVisColorPalette = euiPaletteColorBlind();
@@ -34,7 +40,6 @@ export const Layout = () => {
autoBounds,
boundsOverride,
} = useWaffleOptionsContext();
- const { accounts, regions } = useInventoryMeta(sourceId, nodeType);
const { currentTime, jumpToTime, isAutoReloading } = useWaffleTimeContext();
const { filterQueryAsJson, applyFilterQuery } = useWaffleFiltersContext();
const { loading, nodes, reload, interval } = useSnapshot(
@@ -72,25 +77,75 @@ export const Layout = () => {
isAutoReloading ? 5000 : null
);
+ const intervalAsString = convertIntervalToString(interval);
+ const dataBounds = calculateBoundsFromNodes(nodes);
+ const bounds = autoBounds ? dataBounds : boundsOverride;
+ const formatter = useCallback(createInventoryMetricFormatter(options.metric), [options.metric]);
+
return (
<>
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
};
+
+const MainContainer = euiStyled.div`
+ position: relative;
+ flex: 1 1 auto;
+`;
+
+const TopActionContainer = euiStyled.div`
+ padding: ${props => `12px ${props.theme.eui.paddingSizes.m}`};
+`;
+
+const BottomActionContainer = euiStyled.div`
+ background-color: ${props => props.theme.eui.euiPageBackgroundColor};
+ padding: ${props => props.theme.eui.paddingSizes.m} ${props =>
+ props.theme.eui.paddingSizes.m} ${props => props.theme.eui.paddingSizes.s};
+ position: absolute;
+ left: 0;
+ bottom: 4px;
+ right: 0;
+`;
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/nodes_overview.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/nodes_overview.tsx
index afbfd2a079253..966a327f40bc1 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/nodes_overview.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/nodes_overview.tsx
@@ -4,31 +4,18 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n/react';
-import { get, max, min } from 'lodash';
-import React from 'react';
+import { max, min } from 'lodash';
+import React, { useCallback } from 'react';
+import { InventoryItemType } from '../../../../../common/inventory_models/types';
import { euiStyled } from '../../../../../../observability/public';
-import {
- InfraFormatterType,
- InfraWaffleMapBounds,
- InfraWaffleMapOptions,
-} from '../../../../lib/lib';
-import { createFormatter } from '../../../../utils/formatters';
+import { InfraWaffleMapBounds, InfraWaffleMapOptions, InfraFormatter } from '../../../../lib/lib';
import { NoData } from '../../../../components/empty_states';
import { InfraLoadingPanel } from '../../../../components/loading';
import { Map } from './waffle/map';
-import { ViewSwitcher } from './waffle/view_switcher';
import { TableView } from './table_view';
-import {
- SnapshotNode,
- SnapshotCustomMetricInputRT,
-} from '../../../../../common/http_api/snapshot_api';
-import { convertIntervalToString } from '../../../../utils/convert_interval_to_string';
-import { InventoryItemType } from '../../../../../common/inventory_models/types';
-import { createFormatterForMetric } from '../../metrics_explorer/components/helpers/create_formatter_for_metric';
+import { SnapshotNode } from '../../../../../common/http_api/snapshot_api';
export interface KueryFilterQuery {
kind: 'kuery';
@@ -43,74 +30,13 @@ interface Props {
reload: () => void;
onDrilldown: (filter: KueryFilterQuery) => void;
currentTime: number;
- onViewChange: (view: string) => void;
view: string;
boundsOverride: InfraWaffleMapBounds;
autoBounds: boolean;
- interval: string;
-}
-
-interface MetricFormatter {
- formatter: InfraFormatterType;
- template: string;
- bounds?: { min: number; max: number };
-}
-
-interface MetricFormatters {
- [key: string]: MetricFormatter;
+ formatter: InfraFormatter;
}
-const METRIC_FORMATTERS: MetricFormatters = {
- ['count']: { formatter: InfraFormatterType.number, template: '{{value}}' },
- ['cpu']: {
- formatter: InfraFormatterType.percent,
- template: '{{value}}',
- },
- ['memory']: {
- formatter: InfraFormatterType.percent,
- template: '{{value}}',
- },
- ['rx']: { formatter: InfraFormatterType.bits, template: '{{value}}/s' },
- ['tx']: { formatter: InfraFormatterType.bits, template: '{{value}}/s' },
- ['logRate']: {
- formatter: InfraFormatterType.abbreviatedNumber,
- template: '{{value}}/s',
- },
- ['diskIOReadBytes']: {
- formatter: InfraFormatterType.bytes,
- template: '{{value}}/s',
- },
- ['diskIOWriteBytes']: {
- formatter: InfraFormatterType.bytes,
- template: '{{value}}/s',
- },
- ['s3BucketSize']: {
- formatter: InfraFormatterType.bytes,
- template: '{{value}}',
- },
- ['s3TotalRequests']: {
- formatter: InfraFormatterType.abbreviatedNumber,
- template: '{{value}}',
- },
- ['s3NumberOfObjects']: {
- formatter: InfraFormatterType.abbreviatedNumber,
- template: '{{value}}',
- },
- ['s3UploadBytes']: {
- formatter: InfraFormatterType.bytes,
- template: '{{value}}',
- },
- ['s3DownloadBytes']: {
- formatter: InfraFormatterType.bytes,
- template: '{{value}}',
- },
- ['sqsOldestMessage']: {
- formatter: InfraFormatterType.number,
- template: '{{value}} seconds',
- },
-};
-
-const calculateBoundsFromNodes = (nodes: SnapshotNode[]): InfraWaffleMapBounds => {
+export const calculateBoundsFromNodes = (nodes: SnapshotNode[]): InfraWaffleMapBounds => {
const maxValues = nodes.map(node => node.metric.max);
const minValues = nodes.map(node => node.metric.value);
// if there is only one value then we need to set the bottom range to zero for min
@@ -122,141 +48,97 @@ const calculateBoundsFromNodes = (nodes: SnapshotNode[]): InfraWaffleMapBounds =
return { min: min(minValues) || 0, max: max(maxValues) || 0 };
};
-export const NodesOverview = class extends React.Component {
- public static displayName = 'Waffle';
- public render() {
- const {
- autoBounds,
- boundsOverride,
- loading,
- nodes,
- nodeType,
- reload,
- view,
- currentTime,
- options,
- interval,
- } = this.props;
- if (loading) {
- return (
-
- );
- } else if (!loading && nodes && nodes.length === 0) {
- return (
- {
- reload();
- }}
- testString="noMetricsDataPrompt"
- />
- );
- }
- const dataBounds = calculateBoundsFromNodes(nodes);
- const bounds = autoBounds ? dataBounds : boundsOverride;
- const intervalAsString = convertIntervalToString(interval);
+export const NodesOverview = ({
+ autoBounds,
+ boundsOverride,
+ loading,
+ nodes,
+ nodeType,
+ reload,
+ view,
+ currentTime,
+ options,
+ formatter,
+ onDrilldown,
+}: Props) => {
+ const handleDrilldown = useCallback(
+ (filter: string) => {
+ onDrilldown({
+ kind: 'kuery',
+ expression: filter,
+ });
+ return;
+ },
+ [onDrilldown]
+ );
+
+ const noData = !loading && nodes && nodes.length === 0;
+ if (loading) {
+ return (
+
+ );
+ } else if (noData) {
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {view === 'table' ? (
-
-
-
- ) : (
-
-
-
- )}
-
+ {
+ reload();
+ }}
+ testString="noMetricsDataPrompt"
+ />
);
}
+ const dataBounds = calculateBoundsFromNodes(nodes);
+ const bounds = autoBounds ? dataBounds : boundsOverride;
- private handleViewChange = (view: string) => this.props.onViewChange(view);
-
- // TODO: Change this to a real implimentation using the tickFormatter from the prototype as an example.
- private formatter = (val: string | number) => {
- const { metric } = this.props.options;
- if (SnapshotCustomMetricInputRT.is(metric)) {
- const formatter = createFormatterForMetric(metric);
- return formatter(val);
- }
- const metricFormatter = get(METRIC_FORMATTERS, metric.type, METRIC_FORMATTERS.count);
- if (val == null) {
- return '';
- }
- const formatter = createFormatter(metricFormatter.formatter, metricFormatter.template);
- return formatter(val);
- };
-
- private handleDrilldown = (filter: string) => {
- this.props.onDrilldown({
- kind: 'kuery',
- expression: filter,
- });
- return;
- };
+ if (view === 'table') {
+ return (
+
+
+
+ );
+ }
+ return (
+
+
+
+ );
};
-const MainContainer = euiStyled.div`
- position: relative;
- flex: 1 1 auto;
-`;
-
const TableContainer = euiStyled.div`
padding: ${props => props.theme.eui.paddingSizes.l};
`;
-const ViewSwitcherContainer = euiStyled.div`
- padding: ${props => props.theme.eui.paddingSizes.l};
-`;
-
const MapContainer = euiStyled.div`
position: absolute;
display: flex;
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/save_views.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/saved_views.tsx
similarity index 68%
rename from x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/save_views.tsx
rename to x-pack/plugins/infra/public/pages/metrics/inventory_view/components/saved_views.tsx
index eb40ea595662a..356f0598e00d2 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/save_views.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/saved_views.tsx
@@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
-import { SavedViewsToolbarControls } from '../../../../../components/saved_views/toolbar_control';
-import { inventoryViewSavedObjectType } from '../../../../../../common/saved_objects/inventory_view';
-import { useWaffleViewState } from '../../hooks/use_waffle_view_state';
+import { SavedViewsToolbarControls } from '../../../../components/saved_views/toolbar_control';
+import { inventoryViewSavedObjectType } from '../../../../../common/saved_objects/inventory_view';
+import { useWaffleViewState } from '../hooks/use_waffle_view_state';
export const SavedViews = () => {
const { viewState, defaultViewState, onViewChange } = useWaffleViewState();
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar.tsx
index 3ac9c2c189628..e8485fb812586 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar.tsx
@@ -6,6 +6,7 @@
import React, { FunctionComponent } from 'react';
import { EuiFlexItem } from '@elastic/eui';
+import { useSourceContext } from '../../../../../containers/source';
import {
SnapshotMetricInput,
SnapshotGroupBy,
@@ -19,7 +20,7 @@ import { InfraGroupByOptions } from '../../../../../lib/lib';
import { IIndexPattern } from '../../../../../../../../../src/plugins/data/public';
import { InventoryItemType } from '../../../../../../common/inventory_models/types';
import { WaffleOptionsState } from '../../hooks/use_waffle_options';
-import { SavedViews } from './save_views';
+import { useInventoryMeta } from '../../hooks/use_inventory_meta';
export interface ToolbarProps
extends Omit {
@@ -45,9 +46,6 @@ const wrapToolbarItems = (
<>
-
-
-
>
)}
@@ -56,10 +54,11 @@ const wrapToolbarItems = (
interface Props {
nodeType: InventoryItemType;
- regions: string[];
- accounts: InventoryCloudAccount[];
}
-export const Toolbar = ({ nodeType, accounts, regions }: Props) => {
+
+export const Toolbar = ({ nodeType }: Props) => {
+ const { sourceId } = useSourceContext();
+ const { accounts, regions } = useInventoryMeta(sourceId, nodeType);
const ToolbarItems = findToolbar(nodeType);
return wrapToolbarItems(ToolbarItems, accounts, regions);
};
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar_wrapper.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar_wrapper.tsx
index 86cc0d8ee62e0..ea53122984161 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar_wrapper.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar_wrapper.tsx
@@ -5,14 +5,14 @@
*/
import React from 'react';
-import { EuiFlexGroup } from '@elastic/eui';
+import { EuiFlexItem } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { SnapshotMetricType } from '../../../../../../common/inventory_models/types';
-import { Toolbar } from '../../../../../components/eui/toolbar';
-import { ToolbarProps } from './toolbar';
import { fieldToName } from '../../lib/field_to_display_name';
import { useSourceContext } from '../../../../../containers/source';
import { useWaffleOptionsContext } from '../../hooks/use_waffle_options';
+import { WaffleInventorySwitcher } from '../waffle/waffle_inventory_switcher';
+import { ToolbarProps } from './toolbar';
interface Props {
children: (props: Omit) => React.ReactElement;
@@ -36,26 +36,27 @@ export const ToolbarWrapper = (props: Props) => {
} = useWaffleOptionsContext();
const { createDerivedIndexPattern } = useSourceContext();
return (
-
-
- {props.children({
- createDerivedIndexPattern,
- changeMetric,
- changeGroupBy,
- changeAccount,
- changeRegion,
- changeCustomOptions,
- customOptions,
- groupBy,
- metric,
- nodeType,
- region,
- accountId,
- customMetrics,
- changeCustomMetrics,
- })}
-
-
+ <>
+
+
+
+ {props.children({
+ createDerivedIndexPattern,
+ changeMetric,
+ changeGroupBy,
+ changeAccount,
+ changeRegion,
+ changeCustomOptions,
+ customOptions,
+ groupBy,
+ metric,
+ nodeType,
+ region,
+ accountId,
+ customMetrics,
+ changeCustomMetrics,
+ })}
+ >
);
};
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/interval_label.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/interval_label.tsx
new file mode 100644
index 0000000000000..dbbfb0f49c0e9
--- /dev/null
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/interval_label.tsx
@@ -0,0 +1,31 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { EuiText } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+interface Props {
+ intervalAsString?: string;
+}
+
+export const IntervalLabel = ({ intervalAsString }: Props) => {
+ if (!intervalAsString) {
+ return null;
+ }
+
+ return (
+
+
+
+
+
+ );
+};
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/legend.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/legend.tsx
index ccb4cc71924f4..ac699f96a75a6 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/legend.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/legend.tsx
@@ -53,7 +53,7 @@ export const Legend: React.FC = ({ dataBounds, legend, bounds, formatter
const LegendContainer = euiStyled.div`
position: absolute;
- bottom: 10px;
+ bottom: 0px;
left: 10px;
right: 10px;
`;
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/legend_controls.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/legend_controls.tsx
index 6ec21ad2e1b49..30447e5244241 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/legend_controls.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/legend_controls.tsx
@@ -40,7 +40,7 @@ export const LegendControls = ({ autoBounds, boundsOverride, onChange, dataBound
const [draftBounds, setDraftBounds] = useState(autoBounds ? dataBounds : boundsOverride); // should come from bounds prop
const buttonComponent = (
= ({
}
})}
-
);
}}
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/index.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/index.tsx
index 08d5b3e9e0670..f91e9a4034bc2 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/index.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/index.tsx
@@ -4,9 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiFilterButton, EuiFilterGroup, EuiPopover } from '@elastic/eui';
+import { EuiPopover } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n/react';
import React, { useState, useCallback } from 'react';
import { IFieldType } from 'src/plugins/data/public';
import {
@@ -21,6 +20,7 @@ import { ModeSwitcher } from './mode_switcher';
import { MetricsEditMode } from './metrics_edit_mode';
import { CustomMetricMode } from './types';
import { SnapshotMetricType } from '../../../../../../../common/inventory_models/types';
+import { DropdownButton } from '../../dropdown_button';
interface Props {
options: Array<{ text: string; value: string }>;
@@ -132,17 +132,13 @@ export const WaffleMetricControls = ({
}
const button = (
-
-
-
+
+ {currentLabel}
+
);
return (
-
+ <>
-
+ >
);
};
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/view_switcher.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/view_switcher.tsx
index 78a2cad9ca7ee..76756637eb69e 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/view_switcher.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/view_switcher.tsx
@@ -28,7 +28,7 @@ export const ViewSwitcher = ({ view, onChange }: Props) => {
label: i18n.translate('xpack.infra.viewSwitcher.tableViewLabel', {
defaultMessage: 'Table view',
}),
- iconType: 'editorUnorderedList',
+ iconType: 'visTable',
},
];
return (
@@ -37,9 +37,11 @@ export const ViewSwitcher = ({ view, onChange }: Props) => {
defaultMessage: 'Switch between table and map view',
})}
options={buttons}
- color="primary"
+ color="text"
+ buttonSize="m"
idSelected={view}
onChange={onChange}
+ isIconOnly
/>
);
};
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_accounts_controls.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_accounts_controls.tsx
index a8b0cf21bce85..3e4ff1de8291d 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_accounts_controls.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_accounts_controls.tsx
@@ -4,17 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- EuiContextMenuPanelDescriptor,
- EuiFilterButton,
- EuiFilterGroup,
- EuiPopover,
- EuiContextMenu,
-} from '@elastic/eui';
+import { EuiContextMenuPanelDescriptor, EuiPopover, EuiContextMenu } from '@elastic/eui';
import React, { useCallback, useState, useMemo } from 'react';
-import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { InventoryCloudAccount } from '../../../../../../common/http_api/inventory_meta_api';
+import { DropdownButton } from '../dropdown_button';
interface Props {
accountId: string;
@@ -63,32 +57,26 @@ export const WaffleAccountsControls = (props: Props) => {
[options, accountId, changeAccount]
);
+ const button = (
+
+ {currentLabel
+ ? currentLabel.name
+ : i18n.translate('xpack.infra.waffle.accountAllTitle', {
+ defaultMessage: 'All',
+ })}
+
+ );
+
return (
-
-
-
-
- }
- anchorPosition="downLeft"
- panelPaddingSize="none"
- closePopover={closePopover}
- >
-
-
-
+
+
+
);
};
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_group_by_controls.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_group_by_controls.tsx
index bc763d2cf9378..c1f406f31e85e 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_group_by_controls.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_group_by_controls.tsx
@@ -9,8 +9,6 @@ import {
EuiContextMenu,
EuiContextMenuPanelDescriptor,
EuiContextMenuPanelItemDescriptor,
- EuiFilterButton,
- EuiFilterGroup,
EuiPopover,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
@@ -22,6 +20,7 @@ import { CustomFieldPanel } from './custom_field_panel';
import { euiStyled } from '../../../../../../../observability/public';
import { InventoryItemType } from '../../../../../../common/inventory_models/types';
import { SnapshotGroupBy } from '../../../../../../common/http_api/snapshot_api';
+import { DropdownButton } from '../dropdown_button';
interface Props {
options: Array<{ text: string; field: string; toolTipContent?: string }>;
@@ -121,29 +120,31 @@ export const WaffleGroupByControls = class extends React.PureComponent o != null)
// In this map the `o && o.field` is totally unnecessary but Typescript is
// too stupid to realize that the filter above prevents the next map from being null
- .map(o => {o && o.text})
+ .map(o => (
+
+ {o && o.text}
+
+ ))
) : (
);
+
const button = (
-
-
+
{buttonBody}
-
+
);
return (
-
-
-
-
-
+
+
+
);
}
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx
index 23e06823f407f..e534c97eda090 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx
@@ -4,19 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- EuiPopover,
- EuiContextMenu,
- EuiFilterButton,
- EuiFilterGroup,
- EuiContextMenuPanelDescriptor,
-} from '@elastic/eui';
+import { EuiPopover, EuiContextMenu, EuiContextMenuPanelDescriptor } from '@elastic/eui';
import React, { useCallback, useState, useMemo } from 'react';
-import { FormattedMessage } from '@kbn/i18n/react';
import { findInventoryModel } from '../../../../../../common/inventory_models';
import { InventoryItemType } from '../../../../../../common/inventory_models/types';
import { useWaffleOptionsContext } from '../../hooks/use_waffle_options';
+import { DropdownButton } from '../dropdown_button';
const getDisplayNameForType = (type: InventoryItemType) => {
const inventoryModel = findInventoryModel(type);
@@ -120,27 +114,23 @@ export const WaffleInventorySwitcher: React.FC = () => {
return getDisplayNameForType(nodeType);
}, [nodeType]);
+ const button = (
+
+ {selectedText}
+
+ );
+
return (
-
-
-
+
);
};
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_region_controls.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_region_controls.tsx
index 671e44f42ef6a..9d759424cdc93 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_region_controls.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_region_controls.tsx
@@ -4,16 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- EuiContextMenuPanelDescriptor,
- EuiFilterButton,
- EuiFilterGroup,
- EuiPopover,
- EuiContextMenu,
-} from '@elastic/eui';
+import { EuiContextMenuPanelDescriptor, EuiPopover, EuiContextMenu } from '@elastic/eui';
import React, { useCallback, useState, useMemo } from 'react';
-import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
+import { DropdownButton } from '../dropdown_button';
interface Props {
region?: string;
@@ -62,32 +56,25 @@ export const WaffleRegionControls = (props: Props) => {
[changeRegion, options, region]
);
+ const button = (
+
+ {currentLabel ||
+ i18n.translate('xpack.infra.waffle.region', {
+ defaultMessage: 'All',
+ })}
+
+ );
+
return (
-
-
-
-
- }
- anchorPosition="downLeft"
- panelPaddingSize="none"
- closePopover={closePopover}
- >
-
-
-
+
+
+
);
};
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/index.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/index.tsx
index e473aea7a1f0b..3a2c33d1c824c 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/index.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/index.tsx
@@ -8,7 +8,7 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useContext } from 'react';
-import { SnapshotToolbar } from './toolbar';
+import { FilterBar } from './components/filter_bar';
import { DocumentTitle } from '../../../components/document_title';
import { NoIndices } from '../../../components/empty_states/no_indices';
@@ -56,7 +56,7 @@ export const SnapshotPage = () => {
) : metricIndicesExist ? (
<>
-
+
>
) : hasFailedLoadingSource ? (
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/create_inventory_metric_formatter.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/create_inventory_metric_formatter.ts
new file mode 100644
index 0000000000000..acd71e5137694
--- /dev/null
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/create_inventory_metric_formatter.ts
@@ -0,0 +1,89 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { get } from 'lodash';
+import { createFormatter } from '../../../../utils/formatters';
+import { InfraFormatterType } from '../../../../lib/lib';
+import {
+ SnapshotMetricInput,
+ SnapshotCustomMetricInputRT,
+} from '../../../../../common/http_api/snapshot_api';
+import { createFormatterForMetric } from '../../metrics_explorer/components/helpers/create_formatter_for_metric';
+
+interface MetricFormatter {
+ formatter: InfraFormatterType;
+ template: string;
+ bounds?: { min: number; max: number };
+}
+
+interface MetricFormatters {
+ [key: string]: MetricFormatter;
+}
+
+const METRIC_FORMATTERS: MetricFormatters = {
+ ['count']: { formatter: InfraFormatterType.number, template: '{{value}}' },
+ ['cpu']: {
+ formatter: InfraFormatterType.percent,
+ template: '{{value}}',
+ },
+ ['memory']: {
+ formatter: InfraFormatterType.percent,
+ template: '{{value}}',
+ },
+ ['rx']: { formatter: InfraFormatterType.bits, template: '{{value}}/s' },
+ ['tx']: { formatter: InfraFormatterType.bits, template: '{{value}}/s' },
+ ['logRate']: {
+ formatter: InfraFormatterType.abbreviatedNumber,
+ template: '{{value}}/s',
+ },
+ ['diskIOReadBytes']: {
+ formatter: InfraFormatterType.bytes,
+ template: '{{value}}/s',
+ },
+ ['diskIOWriteBytes']: {
+ formatter: InfraFormatterType.bytes,
+ template: '{{value}}/s',
+ },
+ ['s3BucketSize']: {
+ formatter: InfraFormatterType.bytes,
+ template: '{{value}}',
+ },
+ ['s3TotalRequests']: {
+ formatter: InfraFormatterType.abbreviatedNumber,
+ template: '{{value}}',
+ },
+ ['s3NumberOfObjects']: {
+ formatter: InfraFormatterType.abbreviatedNumber,
+ template: '{{value}}',
+ },
+ ['s3UploadBytes']: {
+ formatter: InfraFormatterType.bytes,
+ template: '{{value}}',
+ },
+ ['s3DownloadBytes']: {
+ formatter: InfraFormatterType.bytes,
+ template: '{{value}}',
+ },
+ ['sqsOldestMessage']: {
+ formatter: InfraFormatterType.number,
+ template: '{{value}} seconds',
+ },
+};
+
+export const createInventoryMetricFormatter = (metric: SnapshotMetricInput) => (
+ val: string | number
+) => {
+ if (SnapshotCustomMetricInputRT.is(metric)) {
+ const formatter = createFormatterForMetric(metric);
+ return formatter(val);
+ }
+ const metricFormatter = get(METRIC_FORMATTERS, metric.type, METRIC_FORMATTERS.count);
+ if (val == null) {
+ return '';
+ }
+ const formatter = createFormatter(metricFormatter.formatter, metricFormatter.template);
+ return formatter(val);
+};
diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/toolbar.tsx b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/toolbar.tsx
index 81971bd31a973..6913f67bad08a 100644
--- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/toolbar.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/toolbar.tsx
@@ -17,7 +17,6 @@ import {
MetricsExplorerTimeOptions,
MetricsExplorerChartOptions,
} from '../hooks/use_metrics_explorer_options';
-import { Toolbar } from '../../../../components/eui/toolbar';
import { MetricsExplorerKueryBar } from './kuery_bar';
import { MetricsExplorerMetrics } from './metrics';
import { MetricsExplorerGroupBy } from './group_by';
@@ -28,6 +27,7 @@ import { MetricExplorerViewState } from '../hooks/use_metric_explorer_state';
import { metricsExplorerViewSavedObjectType } from '../../../../../common/saved_objects/metrics_explorer_view';
import { useKibanaUiSetting } from '../../../../utils/use_kibana_ui_setting';
import { mapKibanaQuickRangesToDatePickerRanges } from '../../../../utils/map_timepicker_quickranges_to_datepicker_ranges';
+import { ToolbarPanel } from '../../../../components/toolbar_panel';
interface Props {
derivedIndexPattern: IIndexPattern;
@@ -65,7 +65,7 @@ export const MetricsExplorerToolbar = ({
const commonlyUsedRanges = mapKibanaQuickRangesToDatePickerRanges(timepickerQuickRanges);
return (
-
+
-
+
);
};
diff --git a/x-pack/plugins/infra/public/utils/is_displayable.test.ts b/x-pack/plugins/infra/public/utils/is_displayable.test.ts
deleted file mode 100644
index ebd5c07327e9b..0000000000000
--- a/x-pack/plugins/infra/public/utils/is_displayable.test.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-import { isDisplayable } from './is_displayable';
-
-describe('isDisplayable()', () => {
- test('field that is not displayable', () => {
- const field = {
- name: 'some.field',
- type: 'number',
- displayable: false,
- };
- expect(isDisplayable(field)).toBe(false);
- });
- test('field that is displayable', () => {
- const field = {
- name: 'some.field',
- type: 'number',
- displayable: true,
- };
- expect(isDisplayable(field)).toBe(true);
- });
- test('field that an ecs field', () => {
- const field = {
- name: '@timestamp',
- type: 'date',
- displayable: true,
- };
- expect(isDisplayable(field)).toBe(true);
- });
- test('field that matches same prefix', () => {
- const field = {
- name: 'system.network.name',
- type: 'string',
- displayable: true,
- };
- expect(isDisplayable(field, ['system.network'])).toBe(true);
- });
- test('field that does not matches same prefix', () => {
- const field = {
- name: 'system.load.1',
- type: 'number',
- displayable: true,
- };
- expect(isDisplayable(field, ['system.network'])).toBe(false);
- });
- test('field that is an K8s allowed field but does not match prefix', () => {
- const field = {
- name: 'kubernetes.namespace',
- type: 'string',
- displayable: true,
- };
- expect(isDisplayable(field, ['kubernetes.pod'])).toBe(true);
- });
- test('field that is a Prometheus allowed field but does not match prefix', () => {
- const field = {
- name: 'prometheus.labels.foo.bar',
- type: 'string',
- displayable: true,
- };
- expect(isDisplayable(field, ['prometheus.metrics'])).toBe(true);
- });
-});
diff --git a/x-pack/plugins/infra/public/utils/is_displayable.ts b/x-pack/plugins/infra/public/utils/is_displayable.ts
deleted file mode 100644
index 534282e807036..0000000000000
--- a/x-pack/plugins/infra/public/utils/is_displayable.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { IFieldType } from 'src/plugins/data/public';
-import { startsWith, uniq } from 'lodash';
-import { getAllowedListForPrefix } from '../../common/ecs_allowed_list';
-
-interface DisplayableFieldType extends IFieldType {
- displayable?: boolean;
-}
-
-const fieldStartsWith = (field: DisplayableFieldType) => (name: string) =>
- startsWith(field.name, name);
-
-export const isDisplayable = (field: DisplayableFieldType, additionalPrefixes: string[] = []) => {
- // We need to start with at least one prefix, even if it's empty
- const prefixes = additionalPrefixes && additionalPrefixes.length ? additionalPrefixes : [''];
- // Create a set of allowed list based on the prefixes
- const allowedList = prefixes.reduce((acc, prefix) => {
- return uniq([...acc, ...getAllowedListForPrefix(prefix)]);
- }, [] as string[]);
- // If the field is displayable and part of the allowed list or covered by the prefix
- return (
- (field.displayable && prefixes.some(fieldStartsWith(field))) ||
- allowedList.some(fieldStartsWith(field))
- );
-};
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 1b77dfb168e88..3e681b8662e98 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -8165,7 +8165,6 @@
"xpack.infra.viewSwitcher.mapViewLabel": "マップビュー",
"xpack.infra.viewSwitcher.tableViewLabel": "表ビュー",
"xpack.infra.waffle.accountAllTitle": "すべて",
- "xpack.infra.waffle.accountLabel": "アカウント: {selectedAccount}",
"xpack.infra.waffle.aggregationNames.avg": "{field} の平均",
"xpack.infra.waffle.aggregationNames.max": "{field} の最大値",
"xpack.infra.waffle.aggregationNames.min": "{field} の最小値",
@@ -8201,11 +8200,8 @@
"xpack.infra.waffle.customMetrics.modeSwitcher.saveButtonAriaLabel": "カスタムメトリックの変更を保存",
"xpack.infra.waffle.customMetrics.submitLabel": "保存",
"xpack.infra.waffle.groupByAllTitle": "すべて",
- "xpack.infra.waffle.groupByButtonLabel": "グループ分けの条件: ",
- "xpack.infra.waffle.inventoryButtonLabel": "ビュー: {selectedText}",
"xpack.infra.waffle.loadingDataText": "データを読み込み中",
"xpack.infra.waffle.maxGroupByTooltip": "一度に選択できるグループは 2 つのみです",
- "xpack.infra.waffle.metricButtonLabel": "メトリック: {selectedMetric}",
"xpack.infra.waffle.metricOptions.countText": "カウント",
"xpack.infra.waffle.metricOptions.cpuUsageText": "CPU 使用状況",
"xpack.infra.waffle.metricOptions.diskIOReadBytes": "ディスク読み取り",
@@ -8232,7 +8228,6 @@
"xpack.infra.waffle.noDataDescription": "期間またはフィルターを調整してみてください。",
"xpack.infra.waffle.noDataTitle": "表示するデータがありません。",
"xpack.infra.waffle.region": "すべて",
- "xpack.infra.waffle.regionLabel": "地域: {selectedRegion}",
"xpack.infra.waffle.savedView.createHeader": "ビューを保存",
"xpack.infra.waffle.savedViews.cancel": "キャンセル",
"xpack.infra.waffle.savedViews.cancelButton": "キャンセル",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index ce2469f29b883..8d50821bd8a58 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -8168,7 +8168,6 @@
"xpack.infra.viewSwitcher.mapViewLabel": "地图视图",
"xpack.infra.viewSwitcher.tableViewLabel": "表视图",
"xpack.infra.waffle.accountAllTitle": "全部",
- "xpack.infra.waffle.accountLabel": "帐户:{selectedAccount}",
"xpack.infra.waffle.aggregationNames.avg": "“{field}”的平均值",
"xpack.infra.waffle.aggregationNames.max": "“{field}”的最大值",
"xpack.infra.waffle.aggregationNames.min": "“{field}”的最小值",
@@ -8204,11 +8203,8 @@
"xpack.infra.waffle.customMetrics.modeSwitcher.saveButtonAriaLabel": "保存定制指标的更改",
"xpack.infra.waffle.customMetrics.submitLabel": "保存",
"xpack.infra.waffle.groupByAllTitle": "全部",
- "xpack.infra.waffle.groupByButtonLabel": "分组依据: ",
- "xpack.infra.waffle.inventoryButtonLabel": "视图:{selectedText}",
"xpack.infra.waffle.loadingDataText": "正在加载数据",
"xpack.infra.waffle.maxGroupByTooltip": "一次只能选择两个分组",
- "xpack.infra.waffle.metricButtonLabel": "指标:{selectedMetric}",
"xpack.infra.waffle.metricOptions.countText": "计数",
"xpack.infra.waffle.metricOptions.cpuUsageText": "CPU 使用",
"xpack.infra.waffle.metricOptions.diskIOReadBytes": "磁盘读取",
@@ -8235,7 +8231,6 @@
"xpack.infra.waffle.noDataDescription": "尝试调整您的时间或筛选。",
"xpack.infra.waffle.noDataTitle": "没有可显示的数据。",
"xpack.infra.waffle.region": "全部",
- "xpack.infra.waffle.regionLabel": "地区:{selectedRegion}",
"xpack.infra.waffle.savedView.createHeader": "保存视图",
"xpack.infra.waffle.savedViews.cancel": "取消",
"xpack.infra.waffle.savedViews.cancelButton": "取消",