mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
* Visual builder: percentile ranks should allow multiple values (#33642) * Visual builder: percentile ranks should allow multiple values Fix: #33144 * Visual builder: percentile ranks should allow multiple values - fix translation Fix: #33144 * Visual builder: percentile ranks should allow multiple values - fix translation Fix: #33144 * Visual builder: percentile ranks should allow multiple values - add migration script * Visual builder: percentile ranks should allow multiple values - fix tests * Visual builder: percentile ranks should allow multiple values - add executeMigrations function * Visual builder: percentile ranks should allow multiple values - fix table view label * Visual builder: percentile ranks should allow multiple values - fix comments * Visual builder: percentile ranks should allow multiple values -add multi value row * Visual builder: percentile ranks should allow multiple values -add multi value row * Visual builder: percentile ranks should allow multiple values fix review comments * Visual builder: percentile ranks should allow multiple values fix review comments * [TSVB] Code cleanup - remove unused file (core_plugins/metrics/public/lib/create_new_panel.js) * x-pack/test/saved_object_api_integration/common/suites/find.ts Fix broken build (#34224)
This commit is contained in:
parent
f1a42b7ac6
commit
48c1781af0
32 changed files with 512 additions and 124 deletions
|
@ -17,7 +17,7 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { cloneDeep, get, omit } from 'lodash';
|
import { cloneDeep, get, omit, has } from 'lodash';
|
||||||
|
|
||||||
function migrateIndexPattern(doc) {
|
function migrateIndexPattern(doc) {
|
||||||
const searchSourceJSON = get(doc, 'attributes.kibanaSavedObjectMeta.searchSourceJSON');
|
const searchSourceJSON = get(doc, 'attributes.kibanaSavedObjectMeta.searchSourceJSON');
|
||||||
|
@ -145,6 +145,44 @@ export const migrations = {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(`Failure attempting to migrate saved object '${doc.attributes.title}' - ${e}`);
|
throw new Error(`Failure attempting to migrate saved object '${doc.attributes.title}' - ${e}`);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'7.1.0': doc => {
|
||||||
|
// [TSVB] Migrate percentile-rank aggregation (value -> values)
|
||||||
|
const migratePercentileRankAggregation = doc => {
|
||||||
|
const visStateJSON = get(doc, 'attributes.visState');
|
||||||
|
let visState;
|
||||||
|
|
||||||
|
if (visStateJSON) {
|
||||||
|
try {
|
||||||
|
visState = JSON.parse(visStateJSON);
|
||||||
|
} catch (e) {
|
||||||
|
// Let it go, the data is invalid and we'll leave it as is
|
||||||
|
}
|
||||||
|
if (visState && visState.type === 'metrics') {
|
||||||
|
const series = get(visState, 'params.series') || [];
|
||||||
|
|
||||||
|
series.forEach(part => {
|
||||||
|
(part.metrics || []).forEach(metric => {
|
||||||
|
if (metric.type === 'percentile_rank' && has(metric, 'value')) {
|
||||||
|
metric.values = [metric.value];
|
||||||
|
|
||||||
|
delete metric.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...doc,
|
||||||
|
attributes: {
|
||||||
|
...doc.attributes,
|
||||||
|
visState: JSON.stringify(visState),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return doc;
|
||||||
|
};
|
||||||
|
|
||||||
|
return migratePercentileRankAggregation(doc);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dashboard: {
|
dashboard: {
|
||||||
|
|
|
@ -56,16 +56,10 @@ export default function calculateLabel(metric, metrics) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metric.type === 'percentile_rank') {
|
|
||||||
return i18n.translate('tsvb.calculateLabel.percentileRankLabel', {
|
|
||||||
defaultMessage: '{lookupMetricType} ({metricValue}) of {metricField}',
|
|
||||||
values: { lookupMetricType: lookup[metric.type], metricValue: metric.value, metricField: metric.field }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includes(paths, metric.type)) {
|
if (includes(paths, metric.type)) {
|
||||||
const targetMetric = metrics.find(m => startsWith(metric.field, m.id));
|
const targetMetric = metrics.find(m => startsWith(metric.field, m.id));
|
||||||
const targetLabel = calculateLabel(targetMetric, metrics);
|
const targetLabel = calculateLabel(targetMetric, metrics);
|
||||||
|
|
||||||
// For percentiles we need to parse the field id to extract the percentile
|
// For percentiles we need to parse the field id to extract the percentile
|
||||||
// the user configured in the percentile aggregation and specified in the
|
// the user configured in the percentile aggregation and specified in the
|
||||||
// submetric they selected. This applies only to pipeline aggs.
|
// submetric they selected. This applies only to pipeline aggs.
|
||||||
|
|
|
@ -19,21 +19,23 @@
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import _ from 'lodash';
|
import { includes } from 'lodash';
|
||||||
|
import { injectI18n } from '@kbn/i18n/react';
|
||||||
import {
|
import {
|
||||||
EuiComboBox,
|
EuiComboBox,
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
import calculateSiblings from '../lib/calculate_siblings';
|
import calculateSiblings from '../lib/calculate_siblings';
|
||||||
import calculateLabel from '../../../common/calculate_label';
|
import calculateLabel from '../../../common/calculate_label';
|
||||||
import basicAggs from '../../../common/basic_aggs';
|
import basicAggs from '../../../common/basic_aggs';
|
||||||
import { injectI18n } from '@kbn/i18n/react';
|
import { toPercentileNumber } from '../../../common/to_percentile_number';
|
||||||
|
import { METRIC_TYPES } from '../../../common/metric_types';
|
||||||
|
|
||||||
function createTypeFilter(restrict, exclude) {
|
function createTypeFilter(restrict, exclude) {
|
||||||
return metric => {
|
return metric => {
|
||||||
if (_.includes(exclude, metric.type)) return false;
|
if (includes(exclude, metric.type)) return false;
|
||||||
switch (restrict) {
|
switch (restrict) {
|
||||||
case 'basic':
|
case 'basic':
|
||||||
return _.includes(basicAggs, metric.type);
|
return includes(basicAggs, metric.type);
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -73,15 +75,31 @@ function MetricSelectUi(props) {
|
||||||
.filter(row => /^percentile/.test(row.type))
|
.filter(row => /^percentile/.test(row.type))
|
||||||
.reduce((acc, row) => {
|
.reduce((acc, row) => {
|
||||||
const label = calculateLabel(row, calculatedMetrics);
|
const label = calculateLabel(row, calculatedMetrics);
|
||||||
row.percentiles.forEach(p => {
|
|
||||||
|
switch (row.type) {
|
||||||
|
case METRIC_TYPES.PERCENTILE_RANK:
|
||||||
|
(row.values || []).forEach(p => {
|
||||||
|
const value = toPercentileNumber(p);
|
||||||
|
|
||||||
|
acc.push({
|
||||||
|
value: `${row.id}[${value}]`,
|
||||||
|
label: `${label} (${value})`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
case METRIC_TYPES.PERCENTILE:
|
||||||
|
(row.percentiles || []).forEach(p => {
|
||||||
if (p.value) {
|
if (p.value) {
|
||||||
const value = /\./.test(p.value) ? p.value : `${p.value}.0`;
|
const value = toPercentileNumber(p.value);
|
||||||
|
|
||||||
acc.push({
|
acc.push({
|
||||||
value: `${row.id}[${value}]`,
|
value: `${row.id}[${value}]`,
|
||||||
label: `${label} (${value})`,
|
label: `${label} (${value})`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
export { PercentileRankAgg } from './percentile_rank';
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* 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 PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import { get } from 'lodash';
|
||||||
|
import { FormattedMessage } from '@kbn/i18n/react';
|
||||||
|
import {
|
||||||
|
htmlIdGenerator,
|
||||||
|
EuiFieldNumber,
|
||||||
|
EuiFlexGroup,
|
||||||
|
EuiFlexItem,
|
||||||
|
EuiFormLabel,
|
||||||
|
EuiSpacer,
|
||||||
|
} from '@elastic/eui';
|
||||||
|
|
||||||
|
import AddDeleteButtons from '../../add_delete_buttons';
|
||||||
|
|
||||||
|
export const MultiValueRow = ({
|
||||||
|
model,
|
||||||
|
onChange,
|
||||||
|
onDelete,
|
||||||
|
onAdd,
|
||||||
|
disableAdd,
|
||||||
|
disableDelete,
|
||||||
|
}) => {
|
||||||
|
const htmlId = htmlIdGenerator();
|
||||||
|
|
||||||
|
const onFieldNumberChange = event => onChange({
|
||||||
|
...model,
|
||||||
|
value: get(event, 'target.value')
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="tvbAggRow__multiValueRow">
|
||||||
|
<EuiFlexGroup responsive={false} alignItems="center">
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiFormLabel htmlFor={htmlId('value')}>
|
||||||
|
<FormattedMessage
|
||||||
|
id="tsvb.multivalueRow.valueLabel"
|
||||||
|
defaultMessage="Value:"
|
||||||
|
/>
|
||||||
|
</EuiFormLabel>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiFieldNumber
|
||||||
|
value={model.value === '' ? '' : Number(model.value)}
|
||||||
|
placeholder={0}
|
||||||
|
onChange={onFieldNumberChange}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<AddDeleteButtons
|
||||||
|
onAdd={onAdd}
|
||||||
|
onDelete={() => onDelete(model)}
|
||||||
|
disableDelete={disableDelete}
|
||||||
|
disableAdd={disableAdd}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
<EuiSpacer/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiValueRow.defaultProps = {
|
||||||
|
model: {
|
||||||
|
id: null,
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiValueRow.propTypes = {
|
||||||
|
model: PropTypes.object,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
onDelete: PropTypes.func,
|
||||||
|
onAdd: PropTypes.func,
|
||||||
|
defaultAddValue: PropTypes.string,
|
||||||
|
disableDelete: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
|
@ -19,33 +19,40 @@
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import AggSelect from './agg_select';
|
import { assign } from 'lodash';
|
||||||
import FieldSelect from './field_select';
|
import AggSelect from '../agg_select';
|
||||||
import AggRow from './agg_row';
|
import FieldSelect from '../field_select';
|
||||||
import createChangeHandler from '../lib/create_change_handler';
|
import AggRow from '../agg_row';
|
||||||
import createSelectHandler from '../lib/create_select_handler';
|
import createChangeHandler from '../../lib/create_change_handler';
|
||||||
import createTextHandler from '../lib/create_text_handler';
|
import createSelectHandler from '../../lib/create_select_handler';
|
||||||
|
import { PercentileRankValues } from './percentile_rank_values';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
htmlIdGenerator,
|
htmlIdGenerator,
|
||||||
EuiFlexGroup,
|
EuiFlexGroup,
|
||||||
EuiFlexItem,
|
EuiFlexItem,
|
||||||
EuiFormLabel,
|
EuiFormLabel,
|
||||||
EuiFieldText,
|
|
||||||
EuiFormRow,
|
EuiFormRow,
|
||||||
|
EuiSpacer,
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
import { FormattedMessage } from '@kbn/i18n/react';
|
import { FormattedMessage } from '@kbn/i18n/react';
|
||||||
|
|
||||||
export const PercentileRankAgg = props => {
|
export const PercentileRankAgg = props => {
|
||||||
const { series, panel, fields } = props;
|
const { series, panel, fields } = props;
|
||||||
const defaults = { value: '' };
|
const defaults = { values: [''] };
|
||||||
const model = { ...defaults, ...props.model };
|
const model = { ...defaults, ...props.model };
|
||||||
|
|
||||||
const handleChange = createChangeHandler(props.onChange, model);
|
|
||||||
const handleSelectChange = createSelectHandler(handleChange);
|
|
||||||
const handleTextChange = createTextHandler(handleChange);
|
|
||||||
|
|
||||||
const indexPattern = series.override_index_pattern && series.series_index_pattern || panel.index_pattern;
|
const indexPattern = series.override_index_pattern && series.series_index_pattern || panel.index_pattern;
|
||||||
const htmlId = htmlIdGenerator();
|
const htmlId = htmlIdGenerator();
|
||||||
|
const isTablePanel = panel.type === 'table';
|
||||||
|
const handleChange = createChangeHandler(props.onChange, model);
|
||||||
|
const handleSelectChange = createSelectHandler(handleChange);
|
||||||
|
|
||||||
|
const handlePercentileRankValuesChange = (values) => {
|
||||||
|
handleChange(assign({}, model, {
|
||||||
|
values,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AggRow
|
<AggRow
|
||||||
|
@ -89,21 +96,15 @@ export const PercentileRankAgg = props => {
|
||||||
/>
|
/>
|
||||||
</EuiFormRow>
|
</EuiFormRow>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem>
|
|
||||||
<EuiFormRow
|
|
||||||
id={htmlId('value')}
|
|
||||||
label={(<FormattedMessage
|
|
||||||
id="tsvb.percentileRank.valueLabel"
|
|
||||||
defaultMessage="Value"
|
|
||||||
/>)}
|
|
||||||
>
|
|
||||||
<EuiFieldText
|
|
||||||
value={model.value}
|
|
||||||
onChange={handleTextChange('value')}
|
|
||||||
/>
|
|
||||||
</EuiFormRow>
|
|
||||||
</EuiFlexItem>
|
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
|
<EuiSpacer/>
|
||||||
|
<PercentileRankValues
|
||||||
|
disableAdd={isTablePanel}
|
||||||
|
disableDelete={isTablePanel}
|
||||||
|
showOnlyLastRow={isTablePanel}
|
||||||
|
model={model.values}
|
||||||
|
onChange={handlePercentileRankValuesChange}
|
||||||
|
/>
|
||||||
</AggRow>
|
</AggRow>
|
||||||
);
|
);
|
||||||
};
|
};
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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 PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import { last } from 'lodash';
|
||||||
|
|
||||||
|
import {
|
||||||
|
EuiFlexGroup,
|
||||||
|
} from '@elastic/eui';
|
||||||
|
import { MultiValueRow } from './multi_value_row';
|
||||||
|
|
||||||
|
export const PercentileRankValues = props => {
|
||||||
|
const model = props.model || [];
|
||||||
|
const { onChange, disableAdd, disableDelete, showOnlyLastRow } = props;
|
||||||
|
|
||||||
|
const onChangeValue = ({ value, id }) => {
|
||||||
|
model[id] = value;
|
||||||
|
|
||||||
|
onChange(model);
|
||||||
|
};
|
||||||
|
const onDeleteValue = ({ id }) => onChange(
|
||||||
|
model.filter((item, currentIndex) => id !== currentIndex),
|
||||||
|
);
|
||||||
|
const onAddValue = () => onChange([...model, '']);
|
||||||
|
|
||||||
|
const renderRow = ({ rowModel, disableDelete, disableAdd }) => (
|
||||||
|
<MultiValueRow
|
||||||
|
key={`percentileRankValue__item${rowModel.id}`}
|
||||||
|
onAdd={onAddValue}
|
||||||
|
onChange={onChangeValue}
|
||||||
|
onDelete={onDeleteValue}
|
||||||
|
disableDelete={disableDelete}
|
||||||
|
disableAdd={disableAdd}
|
||||||
|
model={rowModel}
|
||||||
|
/>);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EuiFlexGroup direction="column" responsive={false} gutterSize="xs">
|
||||||
|
{showOnlyLastRow && renderRow({
|
||||||
|
rowModel: {
|
||||||
|
id: model.length - 1,
|
||||||
|
value: last(model),
|
||||||
|
},
|
||||||
|
disableAdd: true,
|
||||||
|
disableDelete: true
|
||||||
|
})}
|
||||||
|
|
||||||
|
{!showOnlyLastRow && model.map((value, id, array) => (
|
||||||
|
renderRow({
|
||||||
|
rowModel: {
|
||||||
|
id,
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
disableAdd,
|
||||||
|
disableDelete: disableDelete || array.length < 2,
|
||||||
|
})))}
|
||||||
|
</EuiFlexGroup>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
PercentileRankValues.propTypes = {
|
||||||
|
model: PropTypes.array,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
disableDelete: PropTypes.bool,
|
||||||
|
disableAdd: PropTypes.bool,
|
||||||
|
showOnlyLastRow: PropTypes.bool,
|
||||||
|
};
|
|
@ -17,7 +17,7 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _, { isArray, last, get } from 'lodash';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { fieldFormats } from 'ui/registry/field_formats';
|
import { fieldFormats } from 'ui/registry/field_formats';
|
||||||
|
@ -28,6 +28,8 @@ import { EuiToolTip, EuiIcon } from '@elastic/eui';
|
||||||
import replaceVars from '../../lib/replace_vars';
|
import replaceVars from '../../lib/replace_vars';
|
||||||
import { FormattedMessage } from '@kbn/i18n/react';
|
import { FormattedMessage } from '@kbn/i18n/react';
|
||||||
|
|
||||||
|
import { METRIC_TYPES } from '../../../../common/metric_types';
|
||||||
|
|
||||||
const DateFormat = fieldFormats.getType('date');
|
const DateFormat = fieldFormats.getType('date');
|
||||||
|
|
||||||
function getColor(rules, colorKey, value) {
|
function getColor(rules, colorKey, value) {
|
||||||
|
@ -44,12 +46,6 @@ function getColor(rules, colorKey, value) {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPercentileLabel = (metric, item) => {
|
|
||||||
const { value } = _.last(metric.percentiles);
|
|
||||||
const label = calculateLabel(metric, item.metrics);
|
|
||||||
return `${label}, ${value || 0}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TableVis extends Component {
|
class TableVis extends Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -58,9 +54,7 @@ class TableVis extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
get visibleSeries() {
|
get visibleSeries() {
|
||||||
return _
|
return get(this.props, 'model.series', []).filter(series => !series.hidden);
|
||||||
.get(this.props, 'model.series', [])
|
|
||||||
.filter(series => !series.hidden);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderRow = row => {
|
renderRow = row => {
|
||||||
|
@ -108,11 +102,23 @@ class TableVis extends Component {
|
||||||
order: 'asc',
|
order: 'asc',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const calculateHeaderLabel = (metric, item) => {
|
||||||
|
const defaultLabel = item.label || calculateLabel(metric, item.metrics);
|
||||||
|
|
||||||
|
switch (metric.type) {
|
||||||
|
case METRIC_TYPES.PERCENTILE:
|
||||||
|
return `${defaultLabel} (${last(metric.percentiles).value || 0})`;
|
||||||
|
case METRIC_TYPES.PERCENTILE_RANK:
|
||||||
|
return `${defaultLabel} (${last(metric.values) || 0})`;
|
||||||
|
default:
|
||||||
|
return defaultLabel;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const columns = this.visibleSeries.map(item => {
|
const columns = this.visibleSeries.map(item => {
|
||||||
const metric = _.last(item.metrics);
|
const metric = last(item.metrics);
|
||||||
const label = metric.type === 'percentile' ?
|
const label = calculateHeaderLabel(metric, item);
|
||||||
getPercentileLabel(metric, item) :
|
|
||||||
item.label || calculateLabel(metric, item.metrics);
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (!isSortable(metric)) return;
|
if (!isSortable(metric)) return;
|
||||||
let order;
|
let order;
|
||||||
|
@ -193,7 +199,7 @@ class TableVis extends Component {
|
||||||
const header = this.renderHeader();
|
const header = this.renderHeader();
|
||||||
let rows;
|
let rows;
|
||||||
|
|
||||||
if (_.isArray(visData.series) && visData.series.length) {
|
if (isArray(visData.series) && visData.series.length) {
|
||||||
rows = visData.series.map(this.renderRow);
|
rows = visData.series.map(this.renderRow);
|
||||||
} else {
|
} else {
|
||||||
const message = model.pivot_id ?
|
const message = model.pivot_id ?
|
||||||
|
|
|
@ -21,17 +21,17 @@ import React from 'react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { EuiIcon } from '@elastic/eui';
|
import { EuiIcon } from '@elastic/eui';
|
||||||
|
|
||||||
export default props => (row) => {
|
export default props => (row, index = 0) => {
|
||||||
|
|
||||||
function tickFormatter(value) {
|
function tickFormatter(value) {
|
||||||
if (_.isFunction(props.tickFormatter)) return props.tickFormatter(value);
|
if (_.isFunction(props.tickFormatter)) return props.tickFormatter(value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
const key = `tvbLegend__item${row.id}${index}`;
|
||||||
const formatter = row.tickFormatter || tickFormatter;
|
const formatter = row.tickFormatter || tickFormatter;
|
||||||
const value = formatter(props.seriesValues[row.id]);
|
const value = formatter(props.seriesValues[row.id]);
|
||||||
const classes = ['tvbLegend__item'];
|
const classes = ['tvbLegend__item'];
|
||||||
const key = row.id;
|
|
||||||
if (!_.includes(props.seriesFilter, row.id)) classes.push('disabled');
|
if (!_.includes(props.seriesFilter, row.id)) classes.push('disabled');
|
||||||
if (row.label == null || row.legend === false) return (<div key={key} style={{ display: 'none' }}/>);
|
if (row.label == null || row.legend === false) return (<div key={key} style={{ display: 'none' }}/>);
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
import parseSettings from './parse_settings';
|
import parseSettings from './parse_settings';
|
||||||
import getBucketsPath from './get_buckets_path';
|
import getBucketsPath from './get_buckets_path';
|
||||||
import { parseInterval } from './parse_interval';
|
import { parseInterval } from './parse_interval';
|
||||||
import { set } from 'lodash';
|
import { set, isEmpty } from 'lodash';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
|
|
||||||
function checkMetric(metric, fields) {
|
function checkMetric(metric, fields) {
|
||||||
|
@ -122,17 +122,6 @@ export default {
|
||||||
return body;
|
return body;
|
||||||
},
|
},
|
||||||
|
|
||||||
percentile_rank: bucket => {
|
|
||||||
checkMetric(bucket, ['type', 'field', 'value']);
|
|
||||||
const body = {
|
|
||||||
percentile_ranks: {
|
|
||||||
field: bucket.field,
|
|
||||||
values: [bucket.value],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return body;
|
|
||||||
},
|
|
||||||
|
|
||||||
avg_bucket: extendStatsBucket,
|
avg_bucket: extendStatsBucket,
|
||||||
max_bucket: extendStatsBucket,
|
max_bucket: extendStatsBucket,
|
||||||
min_bucket: extendStatsBucket,
|
min_bucket: extendStatsBucket,
|
||||||
|
@ -158,6 +147,19 @@ export default {
|
||||||
return agg;
|
return agg;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
percentile_rank: bucket => {
|
||||||
|
checkMetric(bucket, ['type', 'field', 'values']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
percentile_ranks: {
|
||||||
|
field: bucket.field,
|
||||||
|
values: (bucket.values || [])
|
||||||
|
.map(value => isEmpty(value) ? 0 : value),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
derivative: (bucket, metrics, bucketSize) => {
|
derivative: (bucket, metrics, bucketSize) => {
|
||||||
checkMetric(bucket, ['type', 'field']);
|
checkMetric(bucket, ['type', 'field']);
|
||||||
const body = {
|
const body = {
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { get, includes, max, min, sum } from 'lodash';
|
import { get, includes, max, min, sum } from 'lodash';
|
||||||
import { EXTENDED_STATS_TYPES, METRIC_TYPES } from './metric_types';
|
import { toPercentileNumber } from '../../../../common/to_percentile_number';
|
||||||
import { toPercentileNumber } from './to_percentile_number';
|
import { EXTENDED_STATS_TYPES, METRIC_TYPES } from '../../../../common/metric_types';
|
||||||
|
|
||||||
const aggFns = {
|
const aggFns = {
|
||||||
max,
|
max,
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { startsWith } from 'lodash';
|
import { startsWith } from 'lodash';
|
||||||
import { METRIC_TYPES } from './metric_types';
|
import { toPercentileNumber } from '../../../../common/to_percentile_number';
|
||||||
import { toPercentileNumber } from './to_percentile_number';
|
import { METRIC_TYPES } from '../../../../common/metric_types';
|
||||||
|
|
||||||
const percentileTest = /\[[0-9\.]+\]$/;
|
const percentileTest = /\[[0-9\.]+\]$/;
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ export default (id, metrics) => {
|
||||||
bucketsPath += `[${toPercentileNumber(percent.value)}]`;
|
bucketsPath += `[${toPercentileNumber(percent.value)}]`;
|
||||||
break;
|
break;
|
||||||
case METRIC_TYPES.PERCENTILE_RANK:
|
case METRIC_TYPES.PERCENTILE_RANK:
|
||||||
|
if (percentileTest.test(bucketsPath)) break;
|
||||||
bucketsPath += `[${toPercentileNumber(metric.value)}]`;
|
bucketsPath += `[${toPercentileNumber(metric.value)}]`;
|
||||||
break;
|
break;
|
||||||
case METRIC_TYPES.STD_DEVIATION:
|
case METRIC_TYPES.STD_DEVIATION:
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import percentile from './percentile';
|
import percentile from './percentile';
|
||||||
|
import percentileRank from './percentile_rank';
|
||||||
|
|
||||||
import seriesAgg from './series_agg';
|
import seriesAgg from './series_agg';
|
||||||
import stdDeviationBands from './std_deviation_bands';
|
import stdDeviationBands from './std_deviation_bands';
|
||||||
import stdDeviationSibling from './std_deviation_sibling';
|
import stdDeviationSibling from './std_deviation_sibling';
|
||||||
|
@ -29,6 +31,7 @@ import { mathAgg } from './math';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
percentile,
|
percentile,
|
||||||
|
percentileRank,
|
||||||
stdDeviationBands,
|
stdDeviationBands,
|
||||||
stdDeviationSibling,
|
stdDeviationSibling,
|
||||||
stdMetric,
|
stdMetric,
|
||||||
|
|
|
@ -22,15 +22,20 @@ import getAggValue from '../../helpers/get_agg_value';
|
||||||
import getDefaultDecoration from '../../helpers/get_default_decoration';
|
import getDefaultDecoration from '../../helpers/get_default_decoration';
|
||||||
import getSplits from '../../helpers/get_splits';
|
import getSplits from '../../helpers/get_splits';
|
||||||
import getLastMetric from '../../helpers/get_last_metric';
|
import getLastMetric from '../../helpers/get_last_metric';
|
||||||
|
import { METRIC_TYPES } from '../../../../../common/metric_types';
|
||||||
|
|
||||||
export default function percentile(resp, panel, series, meta) {
|
export default function percentile(resp, panel, series, meta) {
|
||||||
return next => results => {
|
return next => results => {
|
||||||
const metric = getLastMetric(series);
|
const metric = getLastMetric(series);
|
||||||
if (metric.type !== 'percentile') return next(results);
|
|
||||||
|
if (metric.type !== METRIC_TYPES.PERCENTILE) {
|
||||||
|
return next(results);
|
||||||
|
}
|
||||||
|
|
||||||
getSplits(resp, panel, series, meta).forEach((split) => {
|
getSplits(resp, panel, series, meta).forEach((split) => {
|
||||||
metric.percentiles.forEach(percentile => {
|
metric.percentiles.forEach(percentile => {
|
||||||
const percentileValue = percentile.value ? percentile.value : 0;
|
const percentileValue = percentile.value ? percentile.value : 0;
|
||||||
const label = (split.label) + ` (${percentileValue})`;
|
const label = `${split.label} (${percentileValue})`;
|
||||||
const data = split.timeseries.buckets.map(bucket => {
|
const data = split.timeseries.buckets.map(bucket => {
|
||||||
const m = _.assign({}, metric, { percent: percentileValue });
|
const m = _.assign({}, metric, { percent: percentileValue });
|
||||||
return [bucket.key, getAggValue(bucket, m)];
|
return [bucket.key, getAggValue(bucket, m)];
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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 getAggValue from '../../helpers/get_agg_value';
|
||||||
|
import getDefaultDecoration from '../../helpers/get_default_decoration';
|
||||||
|
import getSplits from '../../helpers/get_splits';
|
||||||
|
import getLastMetric from '../../helpers/get_last_metric';
|
||||||
|
import { toPercentileNumber } from '../../../../../common/to_percentile_number';
|
||||||
|
import { METRIC_TYPES } from '../../../../../common/metric_types';
|
||||||
|
|
||||||
|
export default function percentileRank(resp, panel, series, meta) {
|
||||||
|
return next => results => {
|
||||||
|
const metric = getLastMetric(series);
|
||||||
|
|
||||||
|
if (metric.type !== METRIC_TYPES.PERCENTILE_RANK) {
|
||||||
|
return next(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSplits(resp, panel, series, meta).forEach(split => {
|
||||||
|
(metric.values || []).forEach(percentileRank => {
|
||||||
|
const data = split.timeseries.buckets.map(bucket => (
|
||||||
|
[bucket.key, getAggValue(bucket, {
|
||||||
|
...metric,
|
||||||
|
value: toPercentileNumber(percentileRank)
|
||||||
|
})]
|
||||||
|
));
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
data,
|
||||||
|
id: `${split.id}:${percentileRank}`,
|
||||||
|
label: `${split.label} (${percentileRank || 0})`,
|
||||||
|
color: split.color,
|
||||||
|
...getDefaultDecoration(series),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return next(results);
|
||||||
|
};
|
||||||
|
}
|
|
@ -21,13 +21,16 @@ import getDefaultDecoration from '../../helpers/get_default_decoration';
|
||||||
import getSplits from '../../helpers/get_splits';
|
import getSplits from '../../helpers/get_splits';
|
||||||
import getLastMetric from '../../helpers/get_last_metric';
|
import getLastMetric from '../../helpers/get_last_metric';
|
||||||
import mapBucket from '../../helpers/map_bucket';
|
import mapBucket from '../../helpers/map_bucket';
|
||||||
|
import { METRIC_TYPES } from '../../../../../common/metric_types';
|
||||||
|
|
||||||
export default function stdMetric(resp, panel, series, meta) {
|
export default function stdMetric(resp, panel, series, meta) {
|
||||||
return next => results => {
|
return next => results => {
|
||||||
const metric = getLastMetric(series);
|
const metric = getLastMetric(series);
|
||||||
if (metric.type === 'std_deviation' && metric.mode === 'band') {
|
if (metric.type === METRIC_TYPES.STD_DEVIATION && metric.mode === 'band') {
|
||||||
return next(results);
|
return next(results);
|
||||||
}
|
}
|
||||||
if (metric.type === 'percentile') {
|
|
||||||
|
if ([METRIC_TYPES.PERCENTILE_RANK, METRIC_TYPES.PERCENTILE].includes(metric.type)) {
|
||||||
return next(results);
|
return next(results);
|
||||||
}
|
}
|
||||||
if (/_bucket$/.test(metric.type)) return next(results);
|
if (/_bucket$/.test(metric.type)) return next(results);
|
||||||
|
|
|
@ -22,11 +22,14 @@ import stdMetric from './std_metric';
|
||||||
import stdSibling from './std_sibling';
|
import stdSibling from './std_sibling';
|
||||||
import seriesAgg from './series_agg';
|
import seriesAgg from './series_agg';
|
||||||
import percentile from './percentile';
|
import percentile from './percentile';
|
||||||
|
import percentileRank from './percentile_rank';
|
||||||
|
|
||||||
import { math } from './math';
|
import { math } from './math';
|
||||||
import { dropLastBucketFn } from './drop_last_bucket';
|
import { dropLastBucketFn } from './drop_last_bucket';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
percentile,
|
percentile,
|
||||||
|
percentileRank,
|
||||||
stdMetric,
|
stdMetric,
|
||||||
stdSibling,
|
stdSibling,
|
||||||
math,
|
math,
|
||||||
|
|
|
@ -19,29 +19,35 @@
|
||||||
import { last } from 'lodash';
|
import { last } from 'lodash';
|
||||||
import getSplits from '../../helpers/get_splits';
|
import getSplits from '../../helpers/get_splits';
|
||||||
import getLastMetric from '../../helpers/get_last_metric';
|
import getLastMetric from '../../helpers/get_last_metric';
|
||||||
|
import { toPercentileNumber } from '../../../../../common/to_percentile_number';
|
||||||
|
import { METRIC_TYPES } from '../../../../../common/metric_types';
|
||||||
|
|
||||||
export default function percentile(bucket, panel, series) {
|
export default function percentile(bucket, panel, series) {
|
||||||
return next => results => {
|
return next => results => {
|
||||||
const metric = getLastMetric(series);
|
const metric = getLastMetric(series);
|
||||||
if (metric.type !== 'percentile') return next(results);
|
|
||||||
|
|
||||||
const fakeResp = { aggregations: bucket };
|
if (metric.type !== METRIC_TYPES.PERCENTILE) {
|
||||||
|
return next(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fakeResp = {
|
||||||
|
aggregations: bucket,
|
||||||
|
};
|
||||||
|
|
||||||
getSplits(fakeResp, panel, series).forEach(split => {
|
getSplits(fakeResp, panel, series).forEach(split => {
|
||||||
|
|
||||||
// table allows only one percentile in a series (the last one will be chosen in case of several)
|
// table allows only one percentile in a series (the last one will be chosen in case of several)
|
||||||
const percentile = last(metric.percentiles);
|
const percentile = last(metric.percentiles);
|
||||||
let percentileKey = percentile.value ? percentile.value : 0;
|
const percentileKey = toPercentileNumber(percentile.value);
|
||||||
if (!/\./.test(percentileKey)) {
|
const data = split.timeseries.buckets
|
||||||
percentileKey = `${percentileKey}.0`;
|
.map(bucket => [bucket.key, bucket[metric.id].values[percentileKey]]);
|
||||||
}
|
|
||||||
|
|
||||||
const data = split.timeseries.buckets.map(bucket => [bucket.key, bucket[metric.id].values[percentileKey]]);
|
|
||||||
|
|
||||||
results.push({
|
results.push({
|
||||||
id: split.id,
|
id: split.id,
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return next(results);
|
return next(results);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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 { last } from 'lodash';
|
||||||
|
import getSplits from '../../helpers/get_splits';
|
||||||
|
import getLastMetric from '../../helpers/get_last_metric';
|
||||||
|
import { toPercentileNumber } from '../../../../../common/to_percentile_number';
|
||||||
|
import getAggValue from '../../helpers/get_agg_value';
|
||||||
|
import { METRIC_TYPES } from '../../../../../common/metric_types';
|
||||||
|
|
||||||
|
export default function percentileRank(bucket, panel, series) {
|
||||||
|
return next => results => {
|
||||||
|
const metric = getLastMetric(series);
|
||||||
|
|
||||||
|
if (metric.type !== METRIC_TYPES.PERCENTILE_RANK) {
|
||||||
|
return next(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fakeResp = {
|
||||||
|
aggregations: bucket,
|
||||||
|
};
|
||||||
|
|
||||||
|
getSplits(fakeResp, panel, series).forEach(split => {
|
||||||
|
// table allows only one percentile rank in a series (the last one will be chosen in case of several)
|
||||||
|
const lastRankValue = last(metric.values);
|
||||||
|
const percentileRank = toPercentileNumber(lastRankValue);
|
||||||
|
|
||||||
|
const data = split.timeseries.buckets.map(bucket => (
|
||||||
|
[bucket.key, getAggValue(bucket, {
|
||||||
|
...metric,
|
||||||
|
value: percentileRank
|
||||||
|
})]
|
||||||
|
));
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
data,
|
||||||
|
id: split.id,
|
||||||
|
label: `${split.label} (${percentileRank || 0})`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return next(results);
|
||||||
|
};
|
||||||
|
}
|
|
@ -20,18 +20,28 @@
|
||||||
import getSplits from '../../helpers/get_splits';
|
import getSplits from '../../helpers/get_splits';
|
||||||
import getLastMetric from '../../helpers/get_last_metric';
|
import getLastMetric from '../../helpers/get_last_metric';
|
||||||
import mapBucket from '../../helpers/map_bucket';
|
import mapBucket from '../../helpers/map_bucket';
|
||||||
|
import { METRIC_TYPES } from '../../../../../common/metric_types';
|
||||||
|
|
||||||
export default function stdMetric(bucket, panel, series) {
|
export default function stdMetric(bucket, panel, series) {
|
||||||
return next => results => {
|
return next => results => {
|
||||||
const metric = getLastMetric(series);
|
const metric = getLastMetric(series);
|
||||||
if (metric.type === 'std_deviation' && metric.mode === 'band') {
|
|
||||||
return next(results);
|
|
||||||
}
|
|
||||||
if (metric.type === 'percentile') {
|
|
||||||
return next(results);
|
|
||||||
}
|
|
||||||
if (/_bucket$/.test(metric.type)) return next(results);
|
|
||||||
|
|
||||||
const fakeResp = { aggregations: bucket };
|
if (metric.type === METRIC_TYPES.STD_DEVIATION && metric.mode === 'band') {
|
||||||
|
return next(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([METRIC_TYPES.PERCENTILE_RANK, METRIC_TYPES.PERCENTILE].includes(metric.type)) {
|
||||||
|
return next(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/_bucket$/.test(metric.type)) {
|
||||||
|
return next(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fakeResp = {
|
||||||
|
aggregations: bucket,
|
||||||
|
};
|
||||||
|
|
||||||
getSplits(fakeResp, panel, series).forEach(split => {
|
getSplits(fakeResp, panel, series).forEach(split => {
|
||||||
const data = split.timeseries.buckets.map(mapBucket(metric));
|
const data = split.timeseries.buckets.map(mapBucket(metric));
|
||||||
results.push({
|
results.push({
|
||||||
|
|
|
@ -54,9 +54,6 @@ export default function ({ getService }) {
|
||||||
saved_objects: [
|
saved_objects: [
|
||||||
{
|
{
|
||||||
id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab',
|
id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab',
|
||||||
migrationVersion: {
|
|
||||||
visualization: '7.0.0'
|
|
||||||
},
|
|
||||||
type: 'visualization',
|
type: 'visualization',
|
||||||
updated_at: '2017-09-21T18:51:23.794Z',
|
updated_at: '2017-09-21T18:51:23.794Z',
|
||||||
version: resp.body.saved_objects[0].version,
|
version: resp.body.saved_objects[0].version,
|
||||||
|
@ -70,7 +67,7 @@ export default function ({ getService }) {
|
||||||
kibanaSavedObjectMeta: resp.body.saved_objects[0].attributes.kibanaSavedObjectMeta
|
kibanaSavedObjectMeta: resp.body.saved_objects[0].attributes.kibanaSavedObjectMeta
|
||||||
},
|
},
|
||||||
migrationVersion: {
|
migrationVersion: {
|
||||||
visualization: '7.0.0',
|
visualization: '7.1.0',
|
||||||
},
|
},
|
||||||
references: [{
|
references: [{
|
||||||
name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
|
name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
|
||||||
|
|
|
@ -48,16 +48,13 @@ export default function ({ getService }) {
|
||||||
id: resp.body.id,
|
id: resp.body.id,
|
||||||
type: 'visualization',
|
type: 'visualization',
|
||||||
migrationVersion: {
|
migrationVersion: {
|
||||||
visualization: '7.0.0'
|
visualization: '7.1.0'
|
||||||
},
|
},
|
||||||
updated_at: resp.body.updated_at,
|
updated_at: resp.body.updated_at,
|
||||||
version: 'WzgsMV0=',
|
version: 'WzgsMV0=',
|
||||||
attributes: {
|
attributes: {
|
||||||
title: 'My favorite vis'
|
title: 'My favorite vis'
|
||||||
},
|
},
|
||||||
migrationVersion: {
|
|
||||||
visualization: '7.0.0',
|
|
||||||
},
|
|
||||||
references: [],
|
references: [],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -93,16 +90,13 @@ export default function ({ getService }) {
|
||||||
id: resp.body.id,
|
id: resp.body.id,
|
||||||
type: 'visualization',
|
type: 'visualization',
|
||||||
migrationVersion: {
|
migrationVersion: {
|
||||||
visualization: '7.0.0'
|
visualization: '7.1.0'
|
||||||
},
|
},
|
||||||
updated_at: resp.body.updated_at,
|
updated_at: resp.body.updated_at,
|
||||||
version: 'WzAsMV0=',
|
version: 'WzAsMV0=',
|
||||||
attributes: {
|
attributes: {
|
||||||
title: 'My favorite vis'
|
title: 'My favorite vis'
|
||||||
},
|
},
|
||||||
migrationVersion: {
|
|
||||||
visualization: '7.0.0',
|
|
||||||
},
|
|
||||||
references: [],
|
references: [],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -47,7 +47,7 @@ export default function ({ getService }) {
|
||||||
'title': 'Count of requests'
|
'title': 'Count of requests'
|
||||||
},
|
},
|
||||||
migrationVersion: {
|
migrationVersion: {
|
||||||
visualization: '7.0.0',
|
visualization: '7.1.0',
|
||||||
},
|
},
|
||||||
references: [
|
references: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,14 +36,11 @@ export default function ({ getService }) {
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
expect(resp.body).to.eql({
|
expect(resp.body).to.eql({
|
||||||
id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab',
|
id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab',
|
||||||
migrationVersion: {
|
|
||||||
visualization: '7.0.0'
|
|
||||||
},
|
|
||||||
type: 'visualization',
|
type: 'visualization',
|
||||||
updated_at: '2017-09-21T18:51:23.794Z',
|
updated_at: '2017-09-21T18:51:23.794Z',
|
||||||
version: resp.body.version,
|
version: resp.body.version,
|
||||||
migrationVersion: {
|
migrationVersion: {
|
||||||
visualization: '7.0.0',
|
visualization: '7.1.0',
|
||||||
},
|
},
|
||||||
attributes: {
|
attributes: {
|
||||||
title: 'Count of requests',
|
title: 'Count of requests',
|
||||||
|
|
|
@ -2797,7 +2797,6 @@
|
||||||
"tsvb.calculateLabel.lookupMetricTypeOfTargetLabel": "{targetLabel} 的 {lookupMetricType}",
|
"tsvb.calculateLabel.lookupMetricTypeOfTargetLabel": "{targetLabel} 的 {lookupMetricType}",
|
||||||
"tsvb.calculateLabel.lookupMetricTypeOfTargetWithAdditionalLabel": "{targetLabel} ({additionalLabel}) 的 {lookupMetricType}",
|
"tsvb.calculateLabel.lookupMetricTypeOfTargetWithAdditionalLabel": "{targetLabel} ({additionalLabel}) 的 {lookupMetricType}",
|
||||||
"tsvb.calculateLabel.mathLabel": "数学",
|
"tsvb.calculateLabel.mathLabel": "数学",
|
||||||
"tsvb.calculateLabel.percentileRankLabel": "{metricField} 的 {lookupMetricType} ({metricValue})",
|
|
||||||
"tsvb.calculateLabel.seriesAggLabel": "序列聚合 ({metricFunction})",
|
"tsvb.calculateLabel.seriesAggLabel": "序列聚合 ({metricFunction})",
|
||||||
"tsvb.calculateLabel.staticValueLabel": "{metricValue} 的静态值",
|
"tsvb.calculateLabel.staticValueLabel": "{metricValue} 的静态值",
|
||||||
"tsvb.calculateLabel.unknownLabel": "未知",
|
"tsvb.calculateLabel.unknownLabel": "未知",
|
||||||
|
@ -2978,7 +2977,7 @@
|
||||||
"tsvb.percentile.shadeLabel": "阴影(0 到 1):",
|
"tsvb.percentile.shadeLabel": "阴影(0 到 1):",
|
||||||
"tsvb.percentileRank.aggregationLabel": "聚合",
|
"tsvb.percentileRank.aggregationLabel": "聚合",
|
||||||
"tsvb.percentileRank.fieldLabel": "字段",
|
"tsvb.percentileRank.fieldLabel": "字段",
|
||||||
"tsvb.percentileRank.valueLabel": "值",
|
"tsvb.multivalueRow.valueLabel": "值",
|
||||||
"tsvb.positiveOnly.aggregationLabel": "聚合",
|
"tsvb.positiveOnly.aggregationLabel": "聚合",
|
||||||
"tsvb.positiveOnly.metricLabel": "指标",
|
"tsvb.positiveOnly.metricLabel": "指标",
|
||||||
"tsvb.replaceVars.errors.markdownErrorDescription": "请确认您仅在使用 Markdown、已知变量和内置 Handlebar 表达式",
|
"tsvb.replaceVars.errors.markdownErrorDescription": "请确认您仅在使用 Markdown、已知变量和内置 Handlebar 表达式",
|
||||||
|
|
|
@ -90,7 +90,7 @@ export function bulkGetTestSuiteFactory(esArchiver: any, supertest: SuperTest<an
|
||||||
id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`,
|
id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`,
|
||||||
type: 'visualization',
|
type: 'visualization',
|
||||||
migrationVersion: {
|
migrationVersion: {
|
||||||
visualization: '7.0.0',
|
visualization: '7.1.0',
|
||||||
},
|
},
|
||||||
updated_at: '2017-09-21T18:51:23.794Z',
|
updated_at: '2017-09-21T18:51:23.794Z',
|
||||||
version: resp.body.saved_objects[0].version,
|
version: resp.body.saved_objects[0].version,
|
||||||
|
|
|
@ -59,7 +59,7 @@ export function createTestSuiteFactory(es: any, esArchiver: any, supertest: Supe
|
||||||
expect(resp.body).to.eql({
|
expect(resp.body).to.eql({
|
||||||
id: resp.body.id,
|
id: resp.body.id,
|
||||||
migrationVersion: {
|
migrationVersion: {
|
||||||
visualization: '7.0.0',
|
visualization: '7.1.0',
|
||||||
},
|
},
|
||||||
type: spaceAwareType,
|
type: spaceAwareType,
|
||||||
updated_at: resp.body.updated_at,
|
updated_at: resp.body.updated_at,
|
||||||
|
|
|
@ -71,7 +71,7 @@ export function exportTestSuiteFactory(esArchiver: any, supertest: SuperTest<any
|
||||||
id: `${getIdPrefix(spaceId)}91200a00-9efd-11e7-acb3-3dab96693fab`,
|
id: `${getIdPrefix(spaceId)}91200a00-9efd-11e7-acb3-3dab96693fab`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
migrationVersion: { visualization: '7.0.0' },
|
migrationVersion: { visualization: '7.1.0' },
|
||||||
updated_at: '2017-09-21T18:51:23.794Z',
|
updated_at: '2017-09-21T18:51:23.794Z',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -102,7 +102,7 @@ export function findTestSuiteFactory(esArchiver: any, supertest: SuperTest<any>)
|
||||||
title: 'Count of requests',
|
title: 'Count of requests',
|
||||||
},
|
},
|
||||||
migrationVersion: {
|
migrationVersion: {
|
||||||
visualization: '7.0.0',
|
visualization: '7.1.0',
|
||||||
},
|
},
|
||||||
references: [
|
references: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,7 +96,7 @@ export function getTestSuiteFactory(esArchiver: any, supertest: SuperTest<any>)
|
||||||
id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`,
|
id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`,
|
||||||
type: 'visualization',
|
type: 'visualization',
|
||||||
migrationVersion: {
|
migrationVersion: {
|
||||||
visualization: '7.0.0',
|
visualization: '7.1.0',
|
||||||
},
|
},
|
||||||
updated_at: '2017-09-21T18:51:23.794Z',
|
updated_at: '2017-09-21T18:51:23.794Z',
|
||||||
version: resp.body.version,
|
version: resp.body.version,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue