diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/agg.js b/src/legacy/core_plugins/metrics/public/components/aggs/agg.js
index 734ec440433e..aa0cbc535ed1 100644
--- a/src/legacy/core_plugins/metrics/public/components/aggs/agg.js
+++ b/src/legacy/core_plugins/metrics/public/components/aggs/agg.js
@@ -22,17 +22,26 @@ import React from 'react';
import aggToComponent from '../lib/agg_to_component';
import { sortable } from 'react-anything-sortable';
import { UnsupportedAgg } from './unsupported_agg';
+import { TemporaryUnsupportedAgg } from './temporary_unsupported_agg';
+
+import { isMetricEnabled } from '../../lib/check_ui_restrictions';
function Agg(props) {
- const { model } = props;
+ const { model, uiRestrictions } = props;
+
let Component = aggToComponent[model.type];
+
if (!Component) {
Component = UnsupportedAgg;
+ } else if (!isMetricEnabled(model.type, uiRestrictions)) {
+ Component = TemporaryUnsupportedAgg;
}
+
const style = {
cursor: 'default',
...props.style,
};
+
return (
);
@@ -70,6 +80,7 @@ Agg.propTypes = {
series: PropTypes.object,
siblings: PropTypes.array,
sortData: PropTypes.string,
+ uiRestrictions: PropTypes.object,
};
export default sortable(Agg);
diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/agg_select.js b/src/legacy/core_plugins/metrics/public/components/aggs/agg_select.js
index 5def89a0e0a6..66e61e8f7f99 100644
--- a/src/legacy/core_plugins/metrics/public/components/aggs/agg_select.js
+++ b/src/legacy/core_plugins/metrics/public/components/aggs/agg_select.js
@@ -22,6 +22,7 @@ import React from 'react';
import { EuiComboBox } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { injectI18n } from '@kbn/i18n/react';
+import { isMetricEnabled } from '../../lib/check_ui_restrictions';
const metricAggs = [
{
@@ -169,41 +170,45 @@ function filterByPanelType(panelType) {
}
function AggSelectUi(props) {
- const { siblings, panelType, value, onChange, intl, ...rest } = props;
- const selectedOption = allAggOptions.find(option => {
- return value === option.value;
+ const { siblings, panelType, value, onChange, intl, uiRestrictions, ...rest } = props;
+
+ const selectedOptions = allAggOptions.filter(option => {
+ return value === option.value && isMetricEnabled(option.value, uiRestrictions);
});
- const selectedOptions = selectedOption ? [selectedOption] : [];
let enablePipelines = siblings.some(
s => !!metricAggs.find(m => m.value === s.type)
);
+
if (siblings.length <= 1) enablePipelines = false;
let options;
if (panelType === 'metrics') {
options = metricAggs;
} else {
+ const disableSiblingAggs = agg => ({ ...agg, disabled: !enablePipelines || !isMetricEnabled(agg.value, uiRestrictions) });
+
options = [
{
label: intl.formatMessage({ id: 'tsvb.aggSelect.aggGroups.metricAggLabel', defaultMessage: 'Metric Aggregations' }),
- options: metricAggs,
+ options: metricAggs
+ .map(agg => ({ ...agg, disabled: !isMetricEnabled(agg.value, uiRestrictions) })),
},
{
label: intl.formatMessage({
id: 'tsvb.aggSelect.aggGroups.parentPipelineAggLabel', defaultMessage: 'Parent Pipeline Aggregations' }),
options: pipelineAggs
.filter(filterByPanelType(panelType))
- .map(agg => ({ ...agg, disabled: !enablePipelines })),
+ .map(disableSiblingAggs),
},
{
label: intl.formatMessage({
id: 'tsvb.aggSelect.aggGroups.siblingPipelineAggLabel', defaultMessage: 'Sibling Pipeline Aggregations' }),
- options: siblingAggs.map(agg => ({ ...agg, disabled: !enablePipelines })),
+ options: siblingAggs.map(disableSiblingAggs),
},
{
label: intl.formatMessage({ id: 'tsvb.aggSelect.aggGroups.specialAggLabel', defaultMessage: 'Special Aggregations' }),
- options: specialAggs.map(agg => ({ ...agg, disabled: !enablePipelines })),
+ options: specialAggs.map(disableSiblingAggs),
},
];
}
@@ -233,6 +238,7 @@ AggSelectUi.propTypes = {
panelType: PropTypes.string,
siblings: PropTypes.array,
value: PropTypes.string,
+ uiRestrictions: PropTypes.object,
};
const AggSelect = injectI18n(AggSelectUi);
diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/field_select.js b/src/legacy/core_plugins/metrics/public/components/aggs/field_select.js
index cd9b9842bc96..f0690ec68223 100644
--- a/src/legacy/core_plugins/metrics/public/components/aggs/field_select.js
+++ b/src/legacy/core_plugins/metrics/public/components/aggs/field_select.js
@@ -24,26 +24,39 @@ import {
} from '@elastic/eui';
import generateByTypeFilter from '../lib/generate_by_type_filter';
import { injectI18n } from '@kbn/i18n/react';
+import { isFieldEnabled } from '../../lib/check_ui_restrictions';
+
+function FieldSelectUi({
+ type,
+ fields,
+ indexPattern,
+ value,
+ onChange,
+ disabled,
+ restrict,
+ intl,
+ uiRestrictions,
+ ...rest
+}) {
-function FieldSelectUi(props) {
- const { type, fields, indexPattern, value, onChange, disabled, restrict, intl, ...rest } = props;
if (type === 'count') {
return null;
}
- const options = (fields[indexPattern] || [])
- .filter(generateByTypeFilter(restrict))
- .map(field => {
- return { label: field.name, value: field.name };
- });
- const selectedOption = options.find(option => {
- return value === option.value;
- });
+ const typeFilter = generateByTypeFilter(restrict);
+ const options = (fields[indexPattern] || [])
+ .filter(field => typeFilter(field) && isFieldEnabled(field.name, type, uiRestrictions))
+ .map(field => ({ label: field.name, value: field.name }));
+
+ const selectedOption = options.find(option => value === option.value);
const selectedOptions = selectedOption ? [selectedOption] : [];
return (
@@ -85,6 +85,7 @@ function StandardAgg(props) {
indexPattern={indexPattern}
value={model.field}
onChange={handleSelectChange('field')}
+ uiRestrictions={uiRestrictions}
fullWidth
/>
@@ -95,7 +96,6 @@ function StandardAgg(props) {
);
-
}
StandardAgg.propTypes = {
@@ -108,6 +108,7 @@ StandardAgg.propTypes = {
panel: PropTypes.object,
series: PropTypes.object,
siblings: PropTypes.array,
+ uiRestrictions: PropTypes.object,
};
export default StandardAgg;
diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/std_sibling.js b/src/legacy/core_plugins/metrics/public/components/aggs/std_sibling.js
index 26fd7d8e4a1f..39ec2d9a1840 100644
--- a/src/legacy/core_plugins/metrics/public/components/aggs/std_sibling.js
+++ b/src/legacy/core_plugins/metrics/public/components/aggs/std_sibling.js
@@ -128,6 +128,7 @@ const StandardSiblingAggUi = props => {
panelType={props.panel.type}
siblings={props.siblings}
value={model.type}
+ uiRestrictions={props.uiRestrictions}
onChange={handleSelectChange('type')}
/>
@@ -165,6 +166,7 @@ StandardSiblingAggUi.propTypes = {
panel: PropTypes.object,
series: PropTypes.object,
siblings: PropTypes.array,
+ uiRestrictions: PropTypes.object,
};
export const StandardSiblingAgg = injectI18n(StandardSiblingAggUi);
diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/temporary_unsupported_agg.js b/src/legacy/core_plugins/metrics/public/components/aggs/temporary_unsupported_agg.js
new file mode 100644
index 000000000000..eedc10bdbb03
--- /dev/null
+++ b/src/legacy/core_plugins/metrics/public/components/aggs/temporary_unsupported_agg.js
@@ -0,0 +1,45 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import AggRow from './agg_row';
+import React from 'react';
+import { EuiCode, EuiTitle } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+export function TemporaryUnsupportedAgg(props) {
+ return (
+
+
+
+ {props.model.type}) }}
+ />
+
+
+
+ );
+}
diff --git a/src/legacy/core_plugins/metrics/public/components/lib/create_agg_row_render.js b/src/legacy/core_plugins/metrics/public/components/lib/create_agg_row_render.js
index 6fa3cea6ad3a..91ee48576859 100644
--- a/src/legacy/core_plugins/metrics/public/components/lib/create_agg_row_render.js
+++ b/src/legacy/core_plugins/metrics/public/components/lib/create_agg_row_render.js
@@ -25,8 +25,9 @@ import Agg from '../aggs/agg';
export default function createAggRowRender(props) {
return (row, index, items) => {
- const { panel, model, fields } = props;
+ const { panel, model, fields, uiRestrictions } = props;
const changeHandler = seriesChangeHandler(props, items);
+
return (
);
diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.js b/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.js
index e1fe00d12345..ebc904e1894d 100644
--- a/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.js
+++ b/src/legacy/core_plugins/metrics/public/components/panel_config/gauge.js
@@ -107,6 +107,7 @@ class GaugePanelConfigUi extends Component {
limit={1}
model={this.props.model}
name={this.props.name}
+ visData$={this.props.visData$}
onChange={this.props.onChange}
/>
);
@@ -340,6 +341,7 @@ GaugePanelConfigUi.propTypes = {
fields: PropTypes.object,
model: PropTypes.object,
onChange: PropTypes.func,
+ visData$: PropTypes.object,
};
const GaugePanelConfig = injectI18n(GaugePanelConfigUi);
diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/markdown.js b/src/legacy/core_plugins/metrics/public/components/panel_config/markdown.js
index f0ff628770b4..bcad32017c6b 100644
--- a/src/legacy/core_plugins/metrics/public/components/panel_config/markdown.js
+++ b/src/legacy/core_plugins/metrics/public/components/panel_config/markdown.js
@@ -110,6 +110,7 @@ class MarkdownPanelConfigUi extends Component {
fields={this.props.fields}
model={this.props.model}
name={this.props.name}
+ visData$={this.props.visData$}
onChange={this.props.onChange}
/>
);
@@ -315,7 +316,8 @@ MarkdownPanelConfigUi.propTypes = {
fields: PropTypes.object,
model: PropTypes.object,
onChange: PropTypes.func,
- dateFormat: PropTypes.string
+ dateFormat: PropTypes.string,
+ visData$: PropTypes.object,
};
const MarkdownPanelConfig = injectI18n(MarkdownPanelConfigUi);
diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/metric.js b/src/legacy/core_plugins/metrics/public/components/panel_config/metric.js
index 06cf98a0ad19..edc7e8cd84f1 100644
--- a/src/legacy/core_plugins/metrics/public/components/panel_config/metric.js
+++ b/src/legacy/core_plugins/metrics/public/components/panel_config/metric.js
@@ -76,6 +76,7 @@ class MetricPanelConfig extends Component {
limit={2}
model={this.props.model}
name={this.props.name}
+ visData$={this.props.visData$}
onChange={this.props.onChange}
/>
);
@@ -191,6 +192,7 @@ MetricPanelConfig.propTypes = {
fields: PropTypes.object,
model: PropTypes.object,
onChange: PropTypes.func,
+ visData$: PropTypes.object,
};
export default MetricPanelConfig;
diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/table.js b/src/legacy/core_plugins/metrics/public/components/panel_config/table.js
index d2663beb23db..cc993d520ced 100644
--- a/src/legacy/core_plugins/metrics/public/components/panel_config/table.js
+++ b/src/legacy/core_plugins/metrics/public/components/panel_config/table.js
@@ -161,6 +161,7 @@ class TablePanelConfig extends Component {
fields={this.props.fields}
model={this.props.model}
name={this.props.name}
+ visData$={this.props.visData$}
onChange={this.props.onChange}
/>
@@ -280,6 +281,7 @@ TablePanelConfig.propTypes = {
fields: PropTypes.object,
model: PropTypes.object,
onChange: PropTypes.func,
+ visData$: PropTypes.object,
};
export default TablePanelConfig;
diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/timeseries.js b/src/legacy/core_plugins/metrics/public/components/panel_config/timeseries.js
index 6cc0db1fe761..2f1d23c5211e 100644
--- a/src/legacy/core_plugins/metrics/public/components/panel_config/timeseries.js
+++ b/src/legacy/core_plugins/metrics/public/components/panel_config/timeseries.js
@@ -119,6 +119,7 @@ class TimeseriesPanelConfigUi extends Component {
fields={this.props.fields}
model={this.props.model}
name={this.props.name}
+ visData$={this.props.visData$}
onChange={this.props.onChange}
/>
);
@@ -379,6 +380,7 @@ TimeseriesPanelConfigUi.propTypes = {
fields: PropTypes.object,
model: PropTypes.object,
onChange: PropTypes.func,
+ visData$: PropTypes.object,
};
const TimeseriesPanelConfig = injectI18n(TimeseriesPanelConfigUi);
diff --git a/src/legacy/core_plugins/metrics/public/components/panel_config/top_n.js b/src/legacy/core_plugins/metrics/public/components/panel_config/top_n.js
index 2f7bbb007053..de9bc7284c47 100644
--- a/src/legacy/core_plugins/metrics/public/components/panel_config/top_n.js
+++ b/src/legacy/core_plugins/metrics/public/components/panel_config/top_n.js
@@ -77,6 +77,7 @@ class TopNPanelConfig extends Component {
fields={this.props.fields}
model={this.props.model}
name={this.props.name}
+ visData$={this.props.visData$}
onChange={this.props.onChange}
/>
);
@@ -246,6 +247,7 @@ TopNPanelConfig.propTypes = {
fields: PropTypes.object,
model: PropTypes.object,
onChange: PropTypes.func,
+ visData$: PropTypes.object,
};
export default TopNPanelConfig;
diff --git a/src/legacy/core_plugins/metrics/public/components/series.js b/src/legacy/core_plugins/metrics/public/components/series.js
index ada6f9b3b743..eeb1bbee308f 100644
--- a/src/legacy/core_plugins/metrics/public/components/series.js
+++ b/src/legacy/core_plugins/metrics/public/components/series.js
@@ -19,7 +19,7 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
-import _ from 'lodash';
+import { assign, get } from 'lodash';
import timeseries from './vis_types/timeseries/series';
import metric from './vis_types/metric/series';
@@ -46,7 +46,10 @@ class Series extends Component {
this.state = {
visible: true,
selectedTab: 'metrics',
+ uiRestrictions: undefined,
};
+
+ this.visDataSubscription = null;
}
switchTab = (selectedTab) => {
@@ -56,7 +59,7 @@ class Series extends Component {
handleChange = (part) => {
if (this.props.onChange) {
const { model } = this.props;
- const doc = _.assign({}, model, part);
+ const doc = assign({}, model, part);
this.props.onChange(doc);
}
};
@@ -71,12 +74,25 @@ class Series extends Component {
toggleVisible = (e) => {
e.preventDefault();
- this.setState({ visible: !this.state.visible });
+
+ this.setState({
+ visible: !this.state.visible
+ });
};
+ componentDidMount() {
+ if (this.props.visData$) {
+ this.visDataSubscription = this.props.visData$
+ .subscribe(visData => this.setState({
+ uiRestrictions: get(visData, 'uiRestrictions')
+ }));
+ }
+ }
+
render() {
const { panel } = this.props;
const Component = lookup[panel.type];
+
if (Component) {
const params = {
className: this.props.className,
@@ -98,6 +114,7 @@ class Series extends Component {
selectedTab: this.state.selectedTab,
sortData: this.props.sortData,
style: this.props.style,
+ uiRestrictions: this.state.uiRestrictions,
switchTab: this.switchTab,
toggleVisible: this.toggleVisible,
togglePanelActivation: this.togglePanelActivation,
@@ -116,6 +133,11 @@ class Series extends Component {
);
}
+ componentWillUnmount() {
+ if (this.visDataSubscription) {
+ this.visDataSubscription.unsubscribe();
+ }
+ }
}
Series.defaultProps = {
@@ -139,6 +161,7 @@ Series.propTypes = {
onTouchStart: PropTypes.func,
model: PropTypes.object,
panel: PropTypes.object,
+ visData$: PropTypes.object,
sortData: PropTypes.string,
};
diff --git a/src/legacy/core_plugins/metrics/public/components/series_editor.js b/src/legacy/core_plugins/metrics/public/components/series_editor.js
index c48efffb4f7e..a339108a058b 100644
--- a/src/legacy/core_plugins/metrics/public/components/series_editor.js
+++ b/src/legacy/core_plugins/metrics/public/components/series_editor.js
@@ -72,6 +72,7 @@ class SeriesEditor extends Component {
onClone={() => this.handleClone(row)}
onDelete={handleDelete.bind(null, props, row)}
onShouldSortItem={(direction) => this.sortSeries(index, direction, allSeries)}
+ visData$={this.props.visData$}
model={row}
panel={model}
sortData={row.id}
@@ -115,7 +116,8 @@ SeriesEditor.propTypes = {
limit: PropTypes.number,
model: PropTypes.object,
name: PropTypes.string,
- onChange: PropTypes.func
+ onChange: PropTypes.func,
+ visData$: PropTypes.object,
};
export default SeriesEditor;
diff --git a/src/legacy/core_plugins/metrics/public/components/split.js b/src/legacy/core_plugins/metrics/public/components/split.js
index 5b5fc1f28d3e..c6e4de601510 100644
--- a/src/legacy/core_plugins/metrics/public/components/split.js
+++ b/src/legacy/core_plugins/metrics/public/components/split.js
@@ -20,71 +20,77 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import uuid from 'uuid';
+import { get } from 'lodash';
import { SplitByTerms } from './splits/terms';
import { SplitByFilter } from './splits/filter';
-import SplitByFilters from './splits/filters';
-import SplitByEverything from './splits/everything';
+import { SplitByFilters } from './splits/filters';
+import { SplitByEverything } from './splits/everything';
+import { SplitUnsupported } from './splits/unsupported_split';
+import { isGroupByFieldsEnabled } from '../lib/check_ui_restrictions';
+
+const SPLIT_MODES = {
+ FILTERS: 'filters',
+ FILTER: 'filter',
+ TERMS: 'terms',
+ EVERYTHING: 'everything',
+};
class Split extends Component {
-
componentWillReceiveProps(nextProps) {
const { model } = nextProps;
if (model.split_mode === 'filters' && !model.split_filters) {
this.props.onChange({
split_filters: [
- { color: model.color, id: uuid.v1() }
- ]
+ { color: model.color, id: uuid.v1() },
+ ],
});
}
}
+ getComponent(splitMode, uiRestrictions) {
+ if (!isGroupByFieldsEnabled(splitMode, uiRestrictions)) {
+ return SplitUnsupported;
+ }
+
+ switch (splitMode) {
+ case SPLIT_MODES.TERMS:
+ return SplitByTerms;
+ case SPLIT_MODES.FILTER:
+ return SplitByFilter;
+ case SPLIT_MODES.FILTERS:
+ return SplitByFilters;
+ default:
+ return SplitByEverything;
+ }
+ }
+
render() {
- const { model, panel } = this.props;
+ const { model, panel, uiRestrictions } = this.props;
const indexPattern = model.override_index_pattern &&
model.series_index_pattern ||
panel.index_pattern;
- if (model.split_mode === 'filter') {
- return (
-
- );
- }
- if (model.split_mode === 'filters') {
- return (
-
- );
- }
- if (model.split_mode === 'terms') {
- return (
-
- );
- }
- return (
-
- );
- }
+ const splitMode = get(this.props, 'model.split_mode', SPLIT_MODES.EVERYTHING);
+
+ const Component = this.getComponent(splitMode, uiRestrictions);
+
+ return (
+ );
+ }
}
Split.propTypes = {
fields: PropTypes.object,
model: PropTypes.object,
onChange: PropTypes.func,
- panel: PropTypes.object
+ panel: PropTypes.object,
};
export default Split;
diff --git a/src/legacy/core_plugins/metrics/public/components/splits/__snapshots__/terms.test.js.snap b/src/legacy/core_plugins/metrics/public/components/splits/__snapshots__/terms.test.js.snap
index 611dbbdbe008..2fd00f2d0f28 100644
--- a/src/legacy/core_plugins/metrics/public/components/splits/__snapshots__/terms.test.js.snap
+++ b/src/legacy/core_plugins/metrics/public/components/splits/__snapshots__/terms.test.js.snap
@@ -55,6 +55,7 @@ exports[`src/legacy/core_plugins/metrics/public/components/splits/terms.test.js
}
indexPattern="kibana_sample_data_flights"
onChange={[Function]}
+ type="terms"
value="OriginCityName"
/>
diff --git a/src/legacy/core_plugins/metrics/public/components/splits/everything.js b/src/legacy/core_plugins/metrics/public/components/splits/everything.js
index e6aead092faa..e4ab89579e52 100644
--- a/src/legacy/core_plugins/metrics/public/components/splits/everything.js
+++ b/src/legacy/core_plugins/metrics/public/components/splits/everything.js
@@ -18,14 +18,14 @@
*/
import createSelectHandler from '../lib/create_select_handler';
-import GroupBySelect from './group_by_select';
+import { GroupBySelect } from './group_by_select';
import PropTypes from 'prop-types';
import React from 'react';
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-function SplitByEverything(props) {
- const { onChange, model } = props;
+export const SplitByEverything = (props) => {
+ const { onChange, model, uiRestrictions } = props;
const htmlId = htmlIdGenerator();
const handleSelectChange = createSelectHandler(onChange);
return (
@@ -41,18 +41,18 @@ function SplitByEverything(props) {
);
-
-}
+};
SplitByEverything.propTypes = {
model: PropTypes.object,
- onChange: PropTypes.func
+ onChange: PropTypes.func,
+ uiRestrictions: PropTypes.object,
};
-export default SplitByEverything;
diff --git a/src/legacy/core_plugins/metrics/public/components/splits/filter.js b/src/legacy/core_plugins/metrics/public/components/splits/filter.js
index d7c6cfb60e1a..0a73c6e9c397 100644
--- a/src/legacy/core_plugins/metrics/public/components/splits/filter.js
+++ b/src/legacy/core_plugins/metrics/public/components/splits/filter.js
@@ -19,14 +19,14 @@
import createTextHandler from '../lib/create_text_handler';
import createSelectHandler from '../lib/create_select_handler';
-import GroupBySelect from './group_by_select';
+import { GroupBySelect } from './group_by_select';
import PropTypes from 'prop-types';
import React from 'react';
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiFieldText } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
export const SplitByFilter = props => {
- const { onChange } = props;
+ const { onChange, uiRestrictions } = props;
const defaults = { filter: '' };
const model = { ...defaults, ...props.model };
const htmlId = htmlIdGenerator();
@@ -45,6 +45,7 @@ export const SplitByFilter = props => {
@@ -68,5 +69,6 @@ export const SplitByFilter = props => {
SplitByFilter.propTypes = {
model: PropTypes.object,
- onChange: PropTypes.func
+ onChange: PropTypes.func,
+ uiRestrictions: PropTypes.object,
};
diff --git a/src/legacy/core_plugins/metrics/public/components/splits/filters.js b/src/legacy/core_plugins/metrics/public/components/splits/filters.js
index bc7c412690d3..16532a41d49b 100644
--- a/src/legacy/core_plugins/metrics/public/components/splits/filters.js
+++ b/src/legacy/core_plugins/metrics/public/components/splits/filters.js
@@ -18,18 +18,18 @@
*/
import createSelectHandler from '../lib/create_select_handler';
-import GroupBySelect from './group_by_select';
+import { GroupBySelect } from './group_by_select';
import FilterItems from './filter_items';
import PropTypes from 'prop-types';
import React from 'react';
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-function SplitByFilters(props) {
- const { onChange, model } = props;
+export const SplitByFilters = (props) => {
+ const { onChange, model, uiRestrictions } = props;
const htmlId = htmlIdGenerator();
const handleSelectChange = createSelectHandler(onChange);
- return(
+ return (
@@ -43,6 +43,7 @@ function SplitByFilters(props) {
@@ -55,11 +56,10 @@ function SplitByFilters(props) {
/>
);
-}
+};
SplitByFilters.propTypes = {
model: PropTypes.object,
- onChange: PropTypes.func
+ onChange: PropTypes.func,
+ uiRestrictions: PropTypes.object,
};
-
-export default SplitByFilters;
diff --git a/src/legacy/core_plugins/metrics/public/components/splits/group_by_select.js b/src/legacy/core_plugins/metrics/public/components/splits/group_by_select.js
index 9d11e3fae2ea..512da270d47f 100644
--- a/src/legacy/core_plugins/metrics/public/components/splits/group_by_select.js
+++ b/src/legacy/core_plugins/metrics/public/components/splits/group_by_select.js
@@ -23,31 +23,43 @@ import {
EuiComboBox,
} from '@elastic/eui';
import { injectI18n } from '@kbn/i18n/react';
+import { isGroupByFieldsEnabled } from '../../lib/check_ui_restrictions';
function GroupBySelectUi(props) {
- const { intl } = props;
- const modeOptions = [
+ const { intl, uiRestrictions } = props;
+ const modeOptions = ([
{
- label: intl.formatMessage({ id: 'tsvb.splits.groupBySelect.modeOptions.everythingLabel', defaultMessage: 'Everything' }),
- value: 'everything'
+ label: intl.formatMessage({
+ id: 'tsvb.splits.groupBySelect.modeOptions.everythingLabel',
+ defaultMessage: 'Everything',
+ }),
+ value: 'everything',
},
{
label: intl.formatMessage({ id: 'tsvb.splits.groupBySelect.modeOptions.filterLabel', defaultMessage: 'Filter' }),
- value: 'filter'
+ value: 'filter',
},
{
- label: intl.formatMessage({ id: 'tsvb.splits.groupBySelect.modeOptions.filtersLabel', defaultMessage: 'Filters' }),
- value: 'filters'
+ label: intl.formatMessage({
+ id: 'tsvb.splits.groupBySelect.modeOptions.filtersLabel',
+ defaultMessage: 'Filters',
+ }),
+ value: 'filters',
},
{
label: intl.formatMessage({ id: 'tsvb.splits.groupBySelect.modeOptions.termsLabel', defaultMessage: 'Terms' }),
- value: 'terms'
- }
- ];
+ value: 'terms',
+ },
+ ]).map(field => ({
+ ...field,
+ disabled: !isGroupByFieldsEnabled(field.value, uiRestrictions),
+ }));
+
const selectedValue = props.value || 'everything';
const selectedOption = modeOptions.find(option => {
return selectedValue === option.value;
});
+
return (
);
-
}
GroupBySelectUi.propTypes = {
onChange: PropTypes.func,
- value: PropTypes.string
+ value: PropTypes.string,
+ uiRestrictions: PropTypes.object,
};
-const GroupBySelect = injectI18n(GroupBySelectUi);
-export default GroupBySelect;
+export const GroupBySelect = injectI18n(GroupBySelectUi);
diff --git a/src/legacy/core_plugins/metrics/public/components/splits/terms.js b/src/legacy/core_plugins/metrics/public/components/splits/terms.js
index 295ff3a8a8a9..bb2c994b0945 100644
--- a/src/legacy/core_plugins/metrics/public/components/splits/terms.js
+++ b/src/legacy/core_plugins/metrics/public/components/splits/terms.js
@@ -20,18 +20,26 @@
import PropTypes from 'prop-types';
import React from 'react';
import { get, find } from 'lodash';
-import GroupBySelect from './group_by_select';
+import { GroupBySelect } from './group_by_select';
import createTextHandler from '../lib/create_text_handler';
import createSelectHandler from '../lib/create_select_handler';
import FieldSelect from '../aggs/field_select';
import MetricSelect from '../aggs/metric_select';
-import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiFieldNumber, EuiComboBox, EuiFieldText } from '@elastic/eui';
+import {
+ htmlIdGenerator,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiFormRow,
+ EuiFieldNumber,
+ EuiComboBox,
+ EuiFieldText
+} from '@elastic/eui';
import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
import { FIELD_TYPES } from '../../../common/field_types';
const DEFAULTS = { terms_direction: 'desc', terms_size: 10, terms_order_by: '_count' };
-export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesModel, fields }) => {
+export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesModel, fields, uiRestrictions }) => {
const htmlId = htmlIdGenerator();
const handleTextChange = createTextHandler(onChange);
const handleSelectChange = createSelectHandler(onChange);
@@ -76,6 +84,7 @@ export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesMode
@@ -93,6 +102,8 @@ export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesMode
onChange={handleSelectChange('terms_field')}
value={model.terms_field}
fields={fields}
+ uiRestrictions={uiRestrictions}
+ type={'terms'}
/>
@@ -186,7 +197,8 @@ SplitByTermsUI.propTypes = {
model: PropTypes.object,
onChange: PropTypes.func,
indexPattern: PropTypes.string,
- fields: PropTypes.object
+ fields: PropTypes.object,
+ uiRestrictions: PropTypes.object,
};
export const SplitByTerms = injectI18n(SplitByTermsUI);
diff --git a/src/legacy/core_plugins/metrics/public/components/splits/unsupported_split.js b/src/legacy/core_plugins/metrics/public/components/splits/unsupported_split.js
new file mode 100644
index 000000000000..2749441f86c8
--- /dev/null
+++ b/src/legacy/core_plugins/metrics/public/components/splits/unsupported_split.js
@@ -0,0 +1,70 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import createSelectHandler from '../lib/create_select_handler';
+import { GroupBySelect } from './group_by_select';
+import PropTypes from 'prop-types';
+import React from 'react';
+import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiCode, EuiTitle } from '@elastic/eui';
+
+import { FormattedMessage } from '@kbn/i18n/react';
+
+export const SplitUnsupported = (props) => {
+ const { onChange, model, uiRestrictions } = props;
+ const htmlId = htmlIdGenerator();
+ const handleSelectChange = createSelectHandler(onChange);
+ return (
+
+
+ )}
+ >
+
+
+
+
+
+
+ {model.split_mode}) }}
+ />
+
+
+
+
+ );
+};
+
+SplitUnsupported.propTypes = {
+ model: PropTypes.object,
+ onChange: PropTypes.func,
+ uiRestrictions: PropTypes.object,
+};
+
+
diff --git a/src/legacy/core_plugins/metrics/public/components/vis_editor.js b/src/legacy/core_plugins/metrics/public/components/vis_editor.js
index 0632ef43a811..e8f4857cac87 100644
--- a/src/legacy/core_plugins/metrics/public/components/vis_editor.js
+++ b/src/legacy/core_plugins/metrics/public/components/vis_editor.js
@@ -43,7 +43,7 @@ class VisEditor extends Component {
extractedIndexPatterns: [''],
};
this.onBrush = brushHandler(props.vis.API.timeFilter);
- this.visDataSubject = new Rx.Subject();
+ this.visDataSubject = new Rx.BehaviorSubject(this.props.visData);
this.visData$ = this.visDataSubject.asObservable().pipe(share());
}
@@ -79,8 +79,8 @@ class VisEditor extends Component {
}
if (this.props.isEditorMode) {
- const { params, fields } = this.props.vis;
- const extractedIndexPatterns = extractIndexPatterns(params, fields);
+ const { params } = this.props.vis;
+ const extractedIndexPatterns = extractIndexPatterns(params);
if (!isEqual(this.state.extractedIndexPatterns, extractedIndexPatterns)) {
fetchFields(extractedIndexPatterns)
diff --git a/src/legacy/core_plugins/metrics/public/components/vis_types/gauge/series.js b/src/legacy/core_plugins/metrics/public/components/vis_types/gauge/series.js
index 4dfb4292a314..047543082ce6 100644
--- a/src/legacy/core_plugins/metrics/public/components/vis_types/gauge/series.js
+++ b/src/legacy/core_plugins/metrics/public/components/vis_types/gauge/series.js
@@ -41,7 +41,8 @@ function GaugeSeriesUi(props) {
disableAdd,
selectedTab,
visible,
- intl
+ intl,
+ uiRestrictions
} = props;
const defaults = { label: '' };
@@ -78,6 +79,7 @@ function GaugeSeriesUi(props) {
fields={fields}
panel={panel}
model={model}
+ uiRestrictions={uiRestrictions}
/>
@@ -227,6 +229,7 @@ GaugeSeriesUi.propTypes = {
switchTab: PropTypes.func,
toggleVisible: PropTypes.func,
visible: PropTypes.bool,
+ uiRestrictions: PropTypes.object,
};
const GaugeSeries = injectI18n(GaugeSeriesUi);
diff --git a/src/legacy/core_plugins/metrics/public/components/vis_types/markdown/series.js b/src/legacy/core_plugins/metrics/public/components/vis_types/markdown/series.js
index 015779857208..1f103ac6f0ae 100644
--- a/src/legacy/core_plugins/metrics/public/components/vis_types/markdown/series.js
+++ b/src/legacy/core_plugins/metrics/public/components/vis_types/markdown/series.js
@@ -39,7 +39,8 @@ function MarkdownSeriesUi(props) {
disableAdd,
selectedTab,
visible,
- intl
+ intl,
+ uiRestrictions
} = props;
const defaults = { label: '', var_name: '' };
@@ -76,6 +77,7 @@ function MarkdownSeriesUi(props) {
fields={fields}
panel={panel}
model={model}
+ uiRestrictions={uiRestrictions}
/>
@@ -197,6 +199,7 @@ MarkdownSeriesUi.propTypes = {
switchTab: PropTypes.func,
toggleVisible: PropTypes.func,
visible: PropTypes.bool,
+ uiRestrictions: PropTypes.object,
};
const MarkdownSeries = injectI18n(MarkdownSeriesUi);
diff --git a/src/legacy/core_plugins/metrics/public/components/vis_types/metric/series.js b/src/legacy/core_plugins/metrics/public/components/vis_types/metric/series.js
index 1618d1f74a3c..0df8136a81c3 100644
--- a/src/legacy/core_plugins/metrics/public/components/vis_types/metric/series.js
+++ b/src/legacy/core_plugins/metrics/public/components/vis_types/metric/series.js
@@ -41,7 +41,8 @@ function MetricSeriesUi(props) {
disableAdd,
selectedTab,
visible,
- intl
+ intl,
+ uiRestrictions
} = props;
const defaults = { label: '' };
@@ -78,6 +79,7 @@ function MetricSeriesUi(props) {
fields={fields}
panel={panel}
model={model}
+ uiRestrictions={uiRestrictions}
/>
@@ -232,6 +234,7 @@ MetricSeriesUi.propTypes = {
toggleVisible: PropTypes.func,
visible: PropTypes.bool,
togglePanelActivation: PropTypes.func,
+ uiRestrictions: PropTypes.object,
};
const MetricSeries = injectI18n(MetricSeriesUi);
diff --git a/src/legacy/core_plugins/metrics/public/components/vis_types/table/series.js b/src/legacy/core_plugins/metrics/public/components/vis_types/table/series.js
index 2837177ee977..d253be8608eb 100644
--- a/src/legacy/core_plugins/metrics/public/components/vis_types/table/series.js
+++ b/src/legacy/core_plugins/metrics/public/components/vis_types/table/series.js
@@ -202,6 +202,7 @@ TableSeries.propTypes = {
toggleVisible: PropTypes.func,
visible: PropTypes.bool,
togglePanelActivation: PropTypes.func,
+ uiRestrictions: PropTypes.object,
};
export default injectI18n(TableSeries);
diff --git a/src/legacy/core_plugins/metrics/public/components/vis_types/timeseries/series.js b/src/legacy/core_plugins/metrics/public/components/vis_types/timeseries/series.js
index 1ef073464756..35ec9e57f4d0 100644
--- a/src/legacy/core_plugins/metrics/public/components/vis_types/timeseries/series.js
+++ b/src/legacy/core_plugins/metrics/public/components/vis_types/timeseries/series.js
@@ -41,7 +41,8 @@ const TimeseriesSeries = injectI18n(function (props) {
selectedTab,
onChange,
visible,
- intl
+ intl,
+ uiRestrictions
} = props;
const defaults = { label: '' };
@@ -78,6 +79,7 @@ const TimeseriesSeries = injectI18n(function (props) {
fields={fields}
panel={panel}
model={model}
+ uiRestrictions={uiRestrictions}
/>
@@ -236,6 +238,7 @@ TimeseriesSeries.propTypes = {
toggleVisible: PropTypes.func,
visible: PropTypes.bool,
togglePanelActivation: PropTypes.func,
+ uiRestrictions: PropTypes.object,
};
export default injectI18n(TimeseriesSeries);
diff --git a/src/legacy/core_plugins/metrics/public/components/vis_types/top_n/series.js b/src/legacy/core_plugins/metrics/public/components/vis_types/top_n/series.js
index ba25d4261f5f..8d095a024b0d 100644
--- a/src/legacy/core_plugins/metrics/public/components/vis_types/top_n/series.js
+++ b/src/legacy/core_plugins/metrics/public/components/vis_types/top_n/series.js
@@ -42,7 +42,8 @@ const TopNSeries = injectI18n(function (props) {
disableAdd,
selectedTab,
visible,
- intl
+ intl,
+ uiRestrictions,
} = props;
const handleChange = createTextHandler(onChange);
@@ -55,7 +56,7 @@ const TopNSeries = injectI18n(function (props) {
if (visible) {
let seriesBody;
if (selectedTab === 'metrics') {
- const handleSort = (data) => {
+ const handleSort = data => {
const metrics = data.map(id => model.metrics.find(m => m.id === id));
props.onChange({ metrics });
};
@@ -76,6 +77,7 @@ const TopNSeries = injectI18n(function (props) {
fields={fields}
panel={panel}
model={model}
+ uiRestrictions={uiRestrictions}
/>
@@ -226,6 +228,7 @@ TopNSeries.propTypes = {
toggleVisible: PropTypes.func,
visible: PropTypes.bool,
togglePanelActivation: PropTypes.func,
+ uiRestrictions: PropTypes.object,
};
export default TopNSeries;
diff --git a/src/legacy/core_plugins/metrics/public/lib/check_ui_restrictions.js b/src/legacy/core_plugins/metrics/public/lib/check_ui_restrictions.js
new file mode 100644
index 000000000000..825d7c5022fe
--- /dev/null
+++ b/src/legacy/core_plugins/metrics/public/lib/check_ui_restrictions.js
@@ -0,0 +1,50 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { get } from 'lodash';
+
+export const DEFAULT_UI_RESTRICTION = {
+ '*': true,
+};
+
+const RESTRICTION_TYPES = {
+ WHITE_LISTED_GROUP_BY_FIELDS: 'whiteListedGroupByFields',
+ WHITE_LISTER_METRICS: 'whiteListedMetrics',
+};
+
+const checkUIRestrictions = (key, restrictions = DEFAULT_UI_RESTRICTION, type) => {
+ const isAllEnabled = get(restrictions, `${type}.*`, true);
+
+ return isAllEnabled || get(restrictions, type, {})[key];
+};
+
+export const isMetricEnabled = (key, restrictions) => {
+ return checkUIRestrictions(key, restrictions, RESTRICTION_TYPES.WHITE_LISTER_METRICS);
+};
+
+export const isFieldEnabled = (field, metricType, restrictions = DEFAULT_UI_RESTRICTION) => {
+ if (isMetricEnabled(metricType, restrictions)) {
+ return checkUIRestrictions(field, restrictions[RESTRICTION_TYPES.WHITE_LISTER_METRICS], metricType);
+ }
+ return false;
+};
+
+export const isGroupByFieldsEnabled = (key, restrictions) => {
+ return checkUIRestrictions(key, restrictions, RESTRICTION_TYPES.WHITE_LISTED_GROUP_BY_FIELDS);
+};
diff --git a/src/legacy/core_plugins/metrics/public/lib/extract_index_patterns.js b/src/legacy/core_plugins/metrics/public/lib/extract_index_patterns.js
index 6aedc9ebe2c0..4b9b8cfa5d21 100644
--- a/src/legacy/core_plugins/metrics/public/lib/extract_index_patterns.js
+++ b/src/legacy/core_plugins/metrics/public/lib/extract_index_patterns.js
@@ -18,7 +18,7 @@
*/
import { uniq } from 'lodash';
-export function extractIndexPatterns(params, fetchedFields) {
+export function extractIndexPatterns(params, fetchedFields = {}) {
const patternsToFetch = [];
if (!fetchedFields[params.index_pattern]) {
diff --git a/src/legacy/core_plugins/metrics/server/lib/search_strategies/default_search_capabilities.js b/src/legacy/core_plugins/metrics/server/lib/search_strategies/default_search_capabilities.js
index 33e268577bf0..0d82cf7cb253 100644
--- a/src/legacy/core_plugins/metrics/server/lib/search_strategies/default_search_capabilities.js
+++ b/src/legacy/core_plugins/metrics/server/lib/search_strategies/default_search_capabilities.js
@@ -33,10 +33,32 @@ export class DefaultSearchCapabilities {
return null;
}
+ get whiteListedMetrics() {
+ return this.createUiRestriction();
+ }
+
+ get whiteListedGroupByFields() {
+ return this.createUiRestriction();
+ }
+
+ get uiRestrictions() {
+ return {
+ whiteListedMetrics: this.whiteListedMetrics,
+ whiteListedGroupByFields: this.whiteListedGroupByFields,
+ };
+ }
+
get searchTimezone() {
return getTimezoneFromRequest(this.request);
}
+ createUiRestriction(restrictionsObject) {
+ return {
+ '*': !restrictionsObject,
+ ...(restrictionsObject || {}),
+ };
+ }
+
parseInterval(interval) {
return parseInterval(interval);
}
diff --git a/src/legacy/core_plugins/metrics/server/lib/vis_data/get_series_data.js b/src/legacy/core_plugins/metrics/server/lib/vis_data/get_series_data.js
index 7a4a580481ac..16363684acc3 100644
--- a/src/legacy/core_plugins/metrics/server/lib/vis_data/get_series_data.js
+++ b/src/legacy/core_plugins/metrics/server/lib/vis_data/get_series_data.js
@@ -36,27 +36,37 @@ export async function getSeriesData(req, panel) {
const body = (await Promise.all(bodiesPromises))
.reduce((acc, items) => acc.concat(items), []);
- return searchRequest.search({ body })
- .then(data => {
- const series = data.map(handleResponseBody(panel));
- return {
- [panel.id]: {
- id: panel.id,
- series: series.reduce((acc, series) => acc.concat(series), []),
- },
- };
- })
- .then(resp => {
- if (!panel.annotations || panel.annotations.length === 0) return resp;
- return getAnnotations(req, panel, esQueryConfig, searchStrategy, capabilities).then(annotations => {
- resp[panel.id].annotations = annotations;
- return resp;
- });
- })
- .then(resp => {
- resp.type = panel.type;
- return resp;
- })
- .catch(handleErrorResponse(panel));
-}
+ const meta = {
+ type: panel.type,
+ uiRestrictions: capabilities.uiRestrictions,
+ };
+ try {
+ const data = await searchRequest.search({ body });
+ const series = data.map(handleResponseBody(panel));
+ let annotations = null;
+
+ if (panel.annotations && panel.annotations.length) {
+ annotations = await getAnnotations(req, panel, esQueryConfig, searchStrategy, capabilities);
+ }
+
+ return {
+ ...meta,
+ [panel.id]: {
+ annotations,
+ id: panel.id,
+ series: series.reduce((acc, series) => acc.concat(series), []),
+ },
+ };
+
+ } catch (err) {
+ if (err.body) {
+ err.response = err.body;
+
+ return {
+ ...meta,
+ ...handleErrorResponse(panel)(err),
+ };
+ }
+ }
+}
diff --git a/src/legacy/core_plugins/metrics/server/lib/vis_data/get_table_data.js b/src/legacy/core_plugins/metrics/server/lib/vis_data/get_table_data.js
index c552022473e0..1de391343516 100644
--- a/src/legacy/core_plugins/metrics/server/lib/vis_data/get_table_data.js
+++ b/src/legacy/core_plugins/metrics/server/lib/vis_data/get_table_data.js
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
import buildRequestBody from './table/build_request_body';
import handleErrorResponse from './handle_error_response';
import { get } from 'lodash';
@@ -33,14 +32,27 @@ export async function getTableData(req, panel) {
const { indexPatternObject } = await getIndexPatternObject(req, panelIndexPattern);
const body = buildRequestBody(req, panel, esQueryConfig, indexPatternObject, capabilities);
+ const meta = {
+ type: panel.type,
+ uiRestrictions: capabilities.uiRestrictions,
+ };
+
try {
const [resp] = await searchRequest.search({ body });
const buckets = get(resp, 'aggregations.pivot.buckets', []);
- return { type: 'table', series: buckets.map(processBucket(panel)) };
+
+ return {
+ ...meta,
+ series: buckets.map(processBucket(panel)),
+ };
} catch (err) {
if (err.body) {
err.response = err.body;
- return { type: 'table', ...handleErrorResponse(panel)(err) };
+
+ return {
+ ...meta,
+ ...handleErrorResponse(panel)(err)
+ };
}
}
}
diff --git a/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts
index 2eb0cdc0c4f5..569cf55b532d 100644
--- a/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts
@@ -64,7 +64,10 @@ export class KibanaMetricsAdapter implements InfraMetricsAdapter {
return Promise.all(requests)
.then(results => {
return results.map(result => {
- const metricIds = Object.keys(result).filter(k => k !== 'type');
+ const metricIds = Object.keys(result).filter(
+ k => !['type', 'uiRestrictions'].includes(k)
+ );
+
return metricIds.map((id: string) => {
const infraMetricId: InfraMetric = (InfraMetric as any)[id];
if (!infraMetricId) {
diff --git a/x-pack/plugins/rollup/server/lib/search_strategies/rollup_search_capabilities.js b/x-pack/plugins/rollup/server/lib/search_strategies/rollup_search_capabilities.js
index 3e26b5c9b853..d8d54ef5a423 100644
--- a/x-pack/plugins/rollup/server/lib/search_strategies/rollup_search_capabilities.js
+++ b/x-pack/plugins/rollup/server/lib/search_strategies/rollup_search_capabilities.js
@@ -3,18 +3,10 @@
* 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 { get, has } from 'lodash';
import { unitsMap } from '@elastic/datemath';
const leastCommonInterval = (num = 0, base = 0) => Math.max(Math.ceil(num / base) * base, base);
-
-const getDateHistogramAggregation = (fieldsCapabilities, rollupIndex) => {
- const dateHistogramField = fieldsCapabilities[rollupIndex].aggs.date_histogram;
-
- // there is also only one valid date_histogram field
- return Object.values(dateHistogramField)[0];
-};
-
const isCalendarInterval = ({ unit, value }) => value === 1 && ['calendar', 'mixed'].includes(unitsMap[unit].type);
export const getRollupSearchCapabilities = (DefaultSearchCapabilities) =>
@@ -23,7 +15,13 @@ export const getRollupSearchCapabilities = (DefaultSearchCapabilities) =>
super(req, batchRequestsSupport, fieldsCapabilities);
this.rollupIndex = rollupIndex;
- this.dateHistogram = getDateHistogramAggregation(fieldsCapabilities, rollupIndex);
+ this.availableMetrics = get(fieldsCapabilities, `${rollupIndex}.aggs`, {});
+ }
+
+ get dateHistogram() {
+ const [dateHistogram] = Object.values(this.availableMetrics.date_histogram);
+
+ return dateHistogram;
}
get defaultTimeInterval() {
@@ -34,6 +32,30 @@ export const getRollupSearchCapabilities = (DefaultSearchCapabilities) =>
return get(this.dateHistogram, 'time_zone', null);
}
+ get whiteListedMetrics() {
+ const baseRestrictions = this.createUiRestriction({
+ count: this.createUiRestriction(),
+ });
+
+ const getFields = fields => Object.keys(fields)
+ .reduce((acc, item) => ({
+ ...acc,
+ [item]: true,
+ }), this.createUiRestriction({}));
+
+ return Object.keys(this.availableMetrics).reduce((acc, item) => ({
+ ...acc,
+ [item]: getFields(this.availableMetrics[item]),
+ }), baseRestrictions);
+ }
+
+ get whiteListedGroupByFields() {
+ return this.createUiRestriction({
+ everything: true,
+ terms: has(this.availableMetrics, 'terms'),
+ });
+ }
+
getValidTimeInterval(userIntervalString) {
const parsedRollupJobInterval = this.parseInterval(this.defaultTimeInterval);
const parsedUserInterval = this.parseInterval(userIntervalString);