mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[TSVB] Turn Prettier on (#38106)
* Add the TSVB module to Prettier * Pretty the TSVB by Prettier
This commit is contained in:
parent
a33201cf39
commit
cac41c3eae
269 changed files with 4076 additions and 3865 deletions
|
@ -56,6 +56,7 @@ module.exports = {
|
|||
'x-pack/plugins/apm/**/*',
|
||||
'x-pack/plugins/canvas/**/*',
|
||||
'**/*.{ts,tsx}',
|
||||
'src/legacy/core_plugins/metrics/**/*.js',
|
||||
],
|
||||
plugins: ['prettier'],
|
||||
rules: Object.assign(
|
||||
|
|
|
@ -44,17 +44,13 @@ describe('aggLookup', () => {
|
|||
it('returns options for basic', () => {
|
||||
const options = createOptions('basic');
|
||||
expect(options).to.have.length(15);
|
||||
expect(options.every(opt => isBasicAgg({ type: opt.value }))).to.equal(
|
||||
true
|
||||
);
|
||||
expect(options.every(opt => isBasicAgg({ type: opt.value }))).to.equal(true);
|
||||
});
|
||||
|
||||
it('returns options for pipeline', () => {
|
||||
const options = createOptions('pipeline');
|
||||
expect(options).to.have.length(15);
|
||||
expect(options.every(opt => !isBasicAgg({ type: opt.value }))).to.equal(
|
||||
true
|
||||
);
|
||||
expect(options.every(opt => !isBasicAgg({ type: opt.value }))).to.equal(true);
|
||||
});
|
||||
|
||||
it('returns options for all if given unknown key', () => {
|
||||
|
|
|
@ -49,20 +49,14 @@ describe('calculateLabel(metric, metrics)', () => {
|
|||
|
||||
it('returns formated label for pipeline aggs', () => {
|
||||
const metric = { id: 2, type: 'derivative', field: 1 };
|
||||
const metrics = [
|
||||
{ id: 1, type: 'max', field: 'network.out.bytes' },
|
||||
metric
|
||||
];
|
||||
const metrics = [{ id: 1, type: 'max', field: 'network.out.bytes' }, metric];
|
||||
const label = calculateLabel(metric, metrics);
|
||||
expect(label).to.equal('Derivative of Max of network.out.bytes');
|
||||
});
|
||||
|
||||
it('returns formated label for derivative of percentile', () => {
|
||||
const metric = { id: 2, type: 'derivative', field: '1[50.0]' };
|
||||
const metrics = [
|
||||
{ id: 1, type: 'percentile', field: 'network.out.bytes' },
|
||||
metric
|
||||
];
|
||||
const metrics = [{ id: 1, type: 'percentile', field: 'network.out.bytes' }, metric];
|
||||
const label = calculateLabel(metric, metrics);
|
||||
expect(label).to.equal('Derivative of Percentile of network.out.bytes (50.0)');
|
||||
});
|
||||
|
@ -72,7 +66,7 @@ describe('calculateLabel(metric, metrics)', () => {
|
|||
const metrics = [
|
||||
{ id: 1, type: 'max', field: 'network.out.bytes' },
|
||||
{ id: 2, type: 'moving_average', field: 1 },
|
||||
metric
|
||||
metric,
|
||||
];
|
||||
const label = calculateLabel(metric, metrics);
|
||||
expect(label).to.equal('Derivative of Moving Average of Max of network.out.bytes');
|
||||
|
@ -82,10 +76,9 @@ describe('calculateLabel(metric, metrics)', () => {
|
|||
const metric = { id: 2, type: 'derivative', field: 1 };
|
||||
const metrics = [
|
||||
{ id: 1, type: 'max', field: 'network.out.bytes', alias: 'Outbound Traffic' },
|
||||
metric
|
||||
metric,
|
||||
];
|
||||
const label = calculateLabel(metric, metrics);
|
||||
expect(label).to.equal('Derivative of Outbound Traffic');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -23,7 +23,9 @@ import { i18n } from '@kbn/i18n';
|
|||
export const lookup = {
|
||||
count: i18n.translate('tsvb.aggLookup.countLabel', { defaultMessage: 'Count' }),
|
||||
calculation: i18n.translate('tsvb.aggLookup.calculationLabel', { defaultMessage: 'Calculation' }),
|
||||
std_deviation: i18n.translate('tsvb.aggLookup.deviationLabel', { defaultMessage: 'Std. Deviation' }),
|
||||
std_deviation: i18n.translate('tsvb.aggLookup.deviationLabel', {
|
||||
defaultMessage: 'Std. Deviation',
|
||||
}),
|
||||
variance: i18n.translate('tsvb.aggLookup.varianceLabel', { defaultMessage: 'Variance' }),
|
||||
sum_of_squares: i18n.translate('tsvb.aggLookup.sumOfSqLabel', { defaultMessage: 'Sum of Sq.' }),
|
||||
avg: i18n.translate('tsvb.aggLookup.averageLabel', { defaultMessage: 'Average' }),
|
||||
|
@ -31,24 +33,44 @@ export const lookup = {
|
|||
min: i18n.translate('tsvb.aggLookup.minLabel', { defaultMessage: 'Min' }),
|
||||
sum: i18n.translate('tsvb.aggLookup.sumLabel', { defaultMessage: 'Sum' }),
|
||||
percentile: i18n.translate('tsvb.aggLookup.percentileLabel', { defaultMessage: 'Percentile' }),
|
||||
percentile_rank: i18n.translate('tsvb.aggLookup.percentileRankLabel', { defaultMessage: 'Percentile Rank' }),
|
||||
percentile_rank: i18n.translate('tsvb.aggLookup.percentileRankLabel', {
|
||||
defaultMessage: 'Percentile Rank',
|
||||
}),
|
||||
cardinality: i18n.translate('tsvb.aggLookup.cardinalityLabel', { defaultMessage: 'Cardinality' }),
|
||||
value_count: i18n.translate('tsvb.aggLookup.valueCountLabel', { defaultMessage: 'Value Count' }),
|
||||
derivative: i18n.translate('tsvb.aggLookup.derivativeLabel', { defaultMessage: 'Derivative' }),
|
||||
cumulative_sum: i18n.translate('tsvb.aggLookup.cumulativeSumLabel', { defaultMessage: 'Cumulative Sum' }),
|
||||
moving_average: i18n.translate('tsvb.aggLookup.movingAverageLabel', { defaultMessage: 'Moving Average' }),
|
||||
avg_bucket: i18n.translate('tsvb.aggLookup.overallAverageLabel', { defaultMessage: 'Overall Average' }),
|
||||
cumulative_sum: i18n.translate('tsvb.aggLookup.cumulativeSumLabel', {
|
||||
defaultMessage: 'Cumulative Sum',
|
||||
}),
|
||||
moving_average: i18n.translate('tsvb.aggLookup.movingAverageLabel', {
|
||||
defaultMessage: 'Moving Average',
|
||||
}),
|
||||
avg_bucket: i18n.translate('tsvb.aggLookup.overallAverageLabel', {
|
||||
defaultMessage: 'Overall Average',
|
||||
}),
|
||||
min_bucket: i18n.translate('tsvb.aggLookup.overallMinLabel', { defaultMessage: 'Overall Min' }),
|
||||
max_bucket: i18n.translate('tsvb.aggLookup.overallMaxLabel', { defaultMessage: 'Overall Max' }),
|
||||
sum_bucket: i18n.translate('tsvb.aggLookup.overallSumLabel', { defaultMessage: 'Overall Sum' }),
|
||||
variance_bucket: i18n.translate('tsvb.aggLookup.overallVarianceLabel', { defaultMessage: 'Overall Variance' }),
|
||||
sum_of_squares_bucket: i18n.translate('tsvb.aggLookup.overallSumOfSqLabel', { defaultMessage: 'Overall Sum of Sq.' }),
|
||||
std_deviation_bucket: i18n.translate('tsvb.aggLookup.overallStdDeviationLabel', { defaultMessage: 'Overall Std. Deviation' }),
|
||||
variance_bucket: i18n.translate('tsvb.aggLookup.overallVarianceLabel', {
|
||||
defaultMessage: 'Overall Variance',
|
||||
}),
|
||||
sum_of_squares_bucket: i18n.translate('tsvb.aggLookup.overallSumOfSqLabel', {
|
||||
defaultMessage: 'Overall Sum of Sq.',
|
||||
}),
|
||||
std_deviation_bucket: i18n.translate('tsvb.aggLookup.overallStdDeviationLabel', {
|
||||
defaultMessage: 'Overall Std. Deviation',
|
||||
}),
|
||||
series_agg: i18n.translate('tsvb.aggLookup.seriesAggLabel', { defaultMessage: 'Series Agg' }),
|
||||
math: i18n.translate('tsvb.aggLookup.mathLabel', { defaultMessage: 'Math' }),
|
||||
serial_diff: i18n.translate('tsvb.aggLookup.serialDifferenceLabel', { defaultMessage: 'Serial Difference' }),
|
||||
filter_ratio: i18n.translate('tsvb.aggLookup.filterRatioLabel', { defaultMessage: 'Filter Ratio' }),
|
||||
positive_only: i18n.translate('tsvb.aggLookup.positiveOnlyLabel', { defaultMessage: 'Positive Only' }),
|
||||
serial_diff: i18n.translate('tsvb.aggLookup.serialDifferenceLabel', {
|
||||
defaultMessage: 'Serial Difference',
|
||||
}),
|
||||
filter_ratio: i18n.translate('tsvb.aggLookup.filterRatioLabel', {
|
||||
defaultMessage: 'Filter Ratio',
|
||||
}),
|
||||
positive_only: i18n.translate('tsvb.aggLookup.positiveOnlyLabel', {
|
||||
defaultMessage: 'Positive Only',
|
||||
}),
|
||||
static: i18n.translate('tsvb.aggLookup.staticValueLabel', { defaultMessage: 'Static Value' }),
|
||||
top_hit: i18n.translate('tsvb.aggLookup.topHitLabel', { defaultMessage: 'Top Hit' }),
|
||||
};
|
||||
|
@ -75,15 +97,7 @@ const byType = {
|
|||
_all: lookup,
|
||||
pipeline: pipeline,
|
||||
basic: _.omit(lookup, pipeline),
|
||||
metrics: _.pick(lookup, [
|
||||
'count',
|
||||
'avg',
|
||||
'min',
|
||||
'max',
|
||||
'sum',
|
||||
'cardinality',
|
||||
'value_count',
|
||||
]),
|
||||
metrics: _.pick(lookup, ['count', 'avg', 'min', 'max', 'sum', 'cardinality', 'value_count']),
|
||||
};
|
||||
|
||||
export function isBasicAgg(item) {
|
||||
|
@ -101,9 +115,9 @@ export function createOptions(type = '_all', siblings = []) {
|
|||
return {
|
||||
label: disabled
|
||||
? i18n.translate('tsvb.aggLookup.addPipelineAggDescription', {
|
||||
defaultMessage: '{label} (use the "+" button to add this pipeline agg)',
|
||||
values: { label }
|
||||
})
|
||||
defaultMessage: '{label} (use the "+" button to add this pipeline agg)',
|
||||
values: { label },
|
||||
})
|
||||
: label,
|
||||
value,
|
||||
disabled,
|
||||
|
|
|
@ -27,5 +27,5 @@ export const basicAggs = [
|
|||
'variance',
|
||||
'sum_of_squares',
|
||||
'value_count',
|
||||
'cardinality'
|
||||
'cardinality',
|
||||
];
|
||||
|
|
|
@ -37,24 +37,34 @@ const paths = [
|
|||
];
|
||||
|
||||
export function calculateLabel(metric, metrics) {
|
||||
if (!metric) return i18n.translate('tsvb.calculateLabel.unknownLabel', { defaultMessage: 'Unknown' });
|
||||
if (!metric)
|
||||
return i18n.translate('tsvb.calculateLabel.unknownLabel', { defaultMessage: 'Unknown' });
|
||||
if (metric.alias) return metric.alias;
|
||||
|
||||
if (metric.type === 'count') return i18n.translate('tsvb.calculateLabel.countLabel', { defaultMessage: 'Count' });
|
||||
if (metric.type === 'count')
|
||||
return i18n.translate('tsvb.calculateLabel.countLabel', { defaultMessage: 'Count' });
|
||||
if (metric.type === 'calculation') {
|
||||
return i18n.translate('tsvb.calculateLabel.bucketScriptsLabel', { defaultMessage: 'Bucket Script' });
|
||||
return i18n.translate('tsvb.calculateLabel.bucketScriptsLabel', {
|
||||
defaultMessage: 'Bucket Script',
|
||||
});
|
||||
}
|
||||
if (metric.type === 'math') return i18n.translate('tsvb.calculateLabel.mathLabel', { defaultMessage: 'Math' });
|
||||
if (metric.type === 'math')
|
||||
return i18n.translate('tsvb.calculateLabel.mathLabel', { defaultMessage: 'Math' });
|
||||
if (metric.type === 'series_agg') {
|
||||
return i18n.translate('tsvb.calculateLabel.seriesAggLabel',
|
||||
{ defaultMessage: 'Series Agg ({metricFunction})', values: { metricFunction: metric.function } }
|
||||
);
|
||||
return i18n.translate('tsvb.calculateLabel.seriesAggLabel', {
|
||||
defaultMessage: 'Series Agg ({metricFunction})',
|
||||
values: { metricFunction: metric.function },
|
||||
});
|
||||
}
|
||||
if (metric.type === 'filter_ratio') return i18n.translate('tsvb.calculateLabel.filterRatioLabel', { defaultMessage: 'Filter Ratio' });
|
||||
if (metric.type === 'filter_ratio')
|
||||
return i18n.translate('tsvb.calculateLabel.filterRatioLabel', {
|
||||
defaultMessage: 'Filter Ratio',
|
||||
});
|
||||
if (metric.type === 'static') {
|
||||
return i18n.translate('tsvb.calculateLabel.staticValueLabel',
|
||||
{ defaultMessage: 'Static Value of {metricValue}', values: { metricValue: metric.value } }
|
||||
);
|
||||
return i18n.translate('tsvb.calculateLabel.staticValueLabel', {
|
||||
defaultMessage: 'Static Value of {metricValue}',
|
||||
values: { metricValue: metric.value },
|
||||
});
|
||||
}
|
||||
|
||||
if (includes(paths, metric.type)) {
|
||||
|
@ -70,18 +80,22 @@ export function calculateLabel(metric, metrics) {
|
|||
if (matches) {
|
||||
return i18n.translate('tsvb.calculateLabel.lookupMetricTypeOfTargetWithAdditionalLabel', {
|
||||
defaultMessage: '{lookupMetricType} of {targetLabel} ({additionalLabel})',
|
||||
values: { lookupMetricType: lookup[metric.type], targetLabel, additionalLabel: matches[1] }
|
||||
values: {
|
||||
lookupMetricType: lookup[metric.type],
|
||||
targetLabel,
|
||||
additionalLabel: matches[1],
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
return i18n.translate('tsvb.calculateLabel.lookupMetricTypeOfTargetLabel', {
|
||||
defaultMessage: '{lookupMetricType} of {targetLabel}',
|
||||
values: { lookupMetricType: lookup[metric.type], targetLabel }
|
||||
values: { lookupMetricType: lookup[metric.type], targetLabel },
|
||||
});
|
||||
}
|
||||
|
||||
return i18n.translate('tsvb.calculateLabel.lookupMetricTypeOfMetricFieldRankLabel', {
|
||||
defaultMessage: '{lookupMetricType} of {metricField}',
|
||||
values: { lookupMetricType: lookup[metric.type], metricField: metric.field }
|
||||
values: { lookupMetricType: lookup[metric.type], metricField: metric.field },
|
||||
});
|
||||
}
|
||||
|
|
|
@ -39,10 +39,7 @@ describe('extractIndexPatterns(vis)', () => {
|
|||
series_index_pattern: 'example-2-*',
|
||||
},
|
||||
],
|
||||
annotations: [
|
||||
{ index_pattern: 'notes-*' },
|
||||
{ index_pattern: 'example-1-*' },
|
||||
],
|
||||
annotations: [{ index_pattern: 'notes-*' }, { index_pattern: 'example-1-*' }],
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
import { isArray, last } from 'lodash';
|
||||
|
||||
const DEFAULT_VALUE = 0;
|
||||
const extractValue = data => data && data[1] || null;
|
||||
const extractValue = data => (data && data[1]) || null;
|
||||
|
||||
export const getLastValue = (data, defaultValue = DEFAULT_VALUE) => {
|
||||
if (!isArray(data)) {
|
||||
|
|
|
@ -40,4 +40,3 @@ describe('getLastValue(data)', () => {
|
|||
expect(getLastValue(null, '-')).toBe('-');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -21,4 +21,3 @@ import dateMath from '@elastic/datemath';
|
|||
|
||||
export const GTE_INTERVAL_RE = new RegExp(`^>=([\\d\\.]+\\s*(${dateMath.units.join('|')}))$`);
|
||||
export const INTERVAL_STRING_RE = new RegExp(`^([\\d\\.]+)\\s*(${dateMath.units.join('|')})$`);
|
||||
|
||||
|
|
|
@ -32,5 +32,5 @@ export const METRIC_TYPES = {
|
|||
export const EXTENDED_STATS_TYPES = [
|
||||
METRIC_TYPES.STD_DEVIATION,
|
||||
METRIC_TYPES.VARIANCE,
|
||||
METRIC_TYPES.SUM_OF_SQUARES
|
||||
METRIC_TYPES.SUM_OF_SQUARES,
|
||||
];
|
||||
|
|
|
@ -25,7 +25,7 @@ const IS_DARK_THEME = chrome.getUiSettingsClient().get('theme:darkMode');
|
|||
/**
|
||||
* Returns true if the color that is passed has low luminosity
|
||||
*/
|
||||
const isColorDark = (c) => {
|
||||
const isColorDark = c => {
|
||||
return color(c).luminosity() < 0.45;
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,7 @@ const isColorDark = (c) => {
|
|||
* Checks to see if the `currentTheme` is dark in luminosity.
|
||||
* Defaults to checking `theme:darkMode`.
|
||||
*/
|
||||
export const isThemeDark = (currentTheme) => {
|
||||
export const isThemeDark = currentTheme => {
|
||||
let themeIsDark = currentTheme || IS_DARK_THEME;
|
||||
|
||||
// If passing a string, check the luminosity
|
||||
|
@ -68,5 +68,3 @@ export const isBackgroundInverted = (backgroundColor, currentTheme) => {
|
|||
const themeIsDark = isThemeDark(currentTheme);
|
||||
return backgroundIsDark !== themeIsDark;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -23,14 +23,12 @@ import { fieldsRoutes } from './server/routes/fields';
|
|||
import { visDataRoutes } from './server/routes/vis';
|
||||
import { SearchStrategiesRegister } from './server/lib/search_strategies/search_strategies_register';
|
||||
|
||||
export default function (kibana) {
|
||||
export default function(kibana) {
|
||||
return new kibana.Plugin({
|
||||
require: ['kibana', 'elasticsearch'],
|
||||
|
||||
uiExports: {
|
||||
visTypes: [
|
||||
'plugins/metrics/kbn_vis_types',
|
||||
],
|
||||
visTypes: ['plugins/metrics/kbn_vis_types'],
|
||||
interpreter: ['plugins/metrics/tsvb_fn'],
|
||||
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
|
||||
},
|
||||
|
|
|
@ -86,12 +86,14 @@ export function AddDeleteButtons(props) {
|
|||
let activatePanelBtn = null;
|
||||
|
||||
if (isBoolean(props.isPanelActive)) {
|
||||
const tooltip = props.isPanelActive ? props.deactivatePanelTooltip : props.activatePanelTooltip;
|
||||
const tooltip = props.isPanelActive
|
||||
? props.deactivatePanelTooltip
|
||||
: props.activatePanelTooltip;
|
||||
const iconType = props.isPanelActive ? 'eye' : 'eyeClosed';
|
||||
|
||||
activatePanelBtn = (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content={tooltip} >
|
||||
<EuiToolTip content={tooltip}>
|
||||
<EuiButtonIcon
|
||||
data-test-subj={`${testSubj}ActivatePanelBtn`}
|
||||
aria-label={tooltip}
|
||||
|
@ -123,12 +125,24 @@ export function AddDeleteButtons(props) {
|
|||
|
||||
AddDeleteButtons.defaultProps = {
|
||||
testSubj: 'Add',
|
||||
activeTooltip: i18n.translate('tsvb.addDeleteButtons.addButtonDefaultTooltip', { defaultMessage: 'Add' }),
|
||||
addTooltip: i18n.translate('tsvb.addDeleteButtons.addButtonDefaultTooltip', { defaultMessage: 'Add' }),
|
||||
deleteTooltip: i18n.translate('tsvb.addDeleteButtons.deleteButtonDefaultTooltip', { defaultMessage: 'Delete' }),
|
||||
cloneTooltip: i18n.translate('tsvb.addDeleteButtons.cloneButtonDefaultTooltip', { defaultMessage: 'Clone' }),
|
||||
activatePanelTooltip: i18n.translate('tsvb.addDeleteButtons.reEnableTooltip', { defaultMessage: 'Re-enable' }),
|
||||
deactivatePanelTooltip: i18n.translate('tsvb.addDeleteButtons.temporarilyDisableTooltip', { defaultMessage: 'Temporarily Disable' }),
|
||||
activeTooltip: i18n.translate('tsvb.addDeleteButtons.addButtonDefaultTooltip', {
|
||||
defaultMessage: 'Add',
|
||||
}),
|
||||
addTooltip: i18n.translate('tsvb.addDeleteButtons.addButtonDefaultTooltip', {
|
||||
defaultMessage: 'Add',
|
||||
}),
|
||||
deleteTooltip: i18n.translate('tsvb.addDeleteButtons.deleteButtonDefaultTooltip', {
|
||||
defaultMessage: 'Delete',
|
||||
}),
|
||||
cloneTooltip: i18n.translate('tsvb.addDeleteButtons.cloneButtonDefaultTooltip', {
|
||||
defaultMessage: 'Clone',
|
||||
}),
|
||||
activatePanelTooltip: i18n.translate('tsvb.addDeleteButtons.reEnableTooltip', {
|
||||
defaultMessage: 'Re-enable',
|
||||
}),
|
||||
deactivatePanelTooltip: i18n.translate('tsvb.addDeleteButtons.temporarilyDisableTooltip', {
|
||||
defaultMessage: 'Temporarily Disable',
|
||||
}),
|
||||
};
|
||||
|
||||
AddDeleteButtons.propTypes = {
|
||||
|
|
|
@ -26,57 +26,52 @@ import { AddDeleteButtons } from './add_delete_buttons';
|
|||
describe('AddDeleteButtons', () => {
|
||||
it('calls onAdd={handleAdd}', () => {
|
||||
const handleAdd = sinon.spy();
|
||||
const wrapper = shallowWithIntl(
|
||||
<AddDeleteButtons onAdd={handleAdd} />
|
||||
);
|
||||
wrapper.find('EuiButtonIcon').at(0).simulate('click');
|
||||
const wrapper = shallowWithIntl(<AddDeleteButtons onAdd={handleAdd} />);
|
||||
wrapper
|
||||
.find('EuiButtonIcon')
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
expect(handleAdd.calledOnce).to.equal(true);
|
||||
});
|
||||
|
||||
it('calls onDelete={handleDelete}', () => {
|
||||
const handleDelete = sinon.spy();
|
||||
const wrapper = shallowWithIntl(
|
||||
<AddDeleteButtons onDelete={handleDelete} />
|
||||
);
|
||||
wrapper.find('EuiButtonIcon').at(1).simulate('click');
|
||||
const wrapper = shallowWithIntl(<AddDeleteButtons onDelete={handleDelete} />);
|
||||
wrapper
|
||||
.find('EuiButtonIcon')
|
||||
.at(1)
|
||||
.simulate('click');
|
||||
expect(handleDelete.calledOnce).to.equal(true);
|
||||
});
|
||||
|
||||
it('calls onClone={handleClone}', () => {
|
||||
const handleClone = sinon.spy();
|
||||
const wrapper = shallowWithIntl(
|
||||
<AddDeleteButtons onClone={handleClone} />
|
||||
);
|
||||
wrapper.find('EuiButtonIcon').at(0).simulate('click');
|
||||
const wrapper = shallowWithIntl(<AddDeleteButtons onClone={handleClone} />);
|
||||
wrapper
|
||||
.find('EuiButtonIcon')
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
expect(handleClone.calledOnce).to.equal(true);
|
||||
});
|
||||
|
||||
it('disableDelete={true}', () => {
|
||||
const wrapper = shallowWithIntl(
|
||||
<AddDeleteButtons disableDelete={true} />
|
||||
);
|
||||
const wrapper = shallowWithIntl(<AddDeleteButtons disableDelete={true} />);
|
||||
expect(wrapper.find({ text: 'Delete' })).to.have.length(0);
|
||||
});
|
||||
|
||||
it('disableAdd={true}', () => {
|
||||
const wrapper = shallowWithIntl(
|
||||
<AddDeleteButtons disableAdd={true} />
|
||||
);
|
||||
const wrapper = shallowWithIntl(<AddDeleteButtons disableAdd={true} />);
|
||||
expect(wrapper.find({ text: 'Add' })).to.have.length(0);
|
||||
});
|
||||
|
||||
it('should not display clone by default', () => {
|
||||
const wrapper = shallowWithIntl(
|
||||
<AddDeleteButtons />
|
||||
);
|
||||
const wrapper = shallowWithIntl(<AddDeleteButtons />);
|
||||
expect(wrapper.find({ text: 'Clone' })).to.have.length(0);
|
||||
});
|
||||
|
||||
it('should not display clone when disableAdd={true}', () => {
|
||||
const fn = sinon.spy();
|
||||
const wrapper = shallowWithIntl(
|
||||
<AddDeleteButtons onClone={fn} disableAdd={true} />
|
||||
);
|
||||
const wrapper = shallowWithIntl(<AddDeleteButtons onClone={fn} disableAdd={true} />);
|
||||
expect(wrapper.find({ text: 'Clone' })).to.have.length(0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -42,10 +42,7 @@ export function Agg(props) {
|
|||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={props.className}
|
||||
style={style}
|
||||
>
|
||||
<div className={props.className} style={style}>
|
||||
<Component
|
||||
fields={props.fields}
|
||||
disableDelete={props.disableDelete}
|
||||
|
|
|
@ -38,21 +38,33 @@ function AggRowUi(props) {
|
|||
|
||||
return (
|
||||
<div className="tvbAggRow">
|
||||
<EuiFlexGroup data-test-subj="aggRow" gutterSize="s" alignItems="flexStart" responsive={false}>
|
||||
<EuiFlexGroup
|
||||
data-test-subj="aggRow"
|
||||
gutterSize="s"
|
||||
alignItems="flexStart"
|
||||
responsive={false}
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIcon className="tvbAggRow__visibilityIcon" type={iconType} color={iconColor} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem className="tvbAggRow__children">
|
||||
{props.children}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem className="tvbAggRow__children">{props.children}</EuiFlexItem>
|
||||
|
||||
<SeriesDragHandler dragHandleProps={props.dragHandleProps} hideDragHandler={props.disableDelete} />
|
||||
<SeriesDragHandler
|
||||
dragHandleProps={props.dragHandleProps}
|
||||
hideDragHandler={props.disableDelete}
|
||||
/>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
testSubj="addMetric"
|
||||
addTooltip={intl.formatMessage({ id: 'tsvb.aggRow.addMetricButtonTooltip', defaultMessage: 'Add Metric' })}
|
||||
deleteTooltip={intl.formatMessage({ id: 'tsvb.aggRow.deleteMetricButtonTooltip', defaultMessage: 'Delete Metric' })}
|
||||
addTooltip={intl.formatMessage({
|
||||
id: 'tsvb.aggRow.addMetricButtonTooltip',
|
||||
defaultMessage: 'Add Metric',
|
||||
})}
|
||||
deleteTooltip={intl.formatMessage({
|
||||
id: 'tsvb.aggRow.deleteMetricButtonTooltip',
|
||||
defaultMessage: 'Delete Metric',
|
||||
})}
|
||||
onAdd={props.onAdd}
|
||||
onDelete={props.onDelete}
|
||||
disableDelete={props.disableDelete}
|
||||
|
|
|
@ -30,137 +30,179 @@ const metricAggs = [
|
|||
value: 'avg',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.cardinalityLabel', { defaultMessage: 'Cardinality' }),
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.cardinalityLabel', {
|
||||
defaultMessage: 'Cardinality',
|
||||
}),
|
||||
value: 'cardinality',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.countLabel', { defaultMessage: 'Count' }),
|
||||
value: 'count'
|
||||
value: 'count',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.filterRatioLabel', { defaultMessage: 'Filter Ratio' }),
|
||||
value: 'filter_ratio'
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.filterRatioLabel', {
|
||||
defaultMessage: 'Filter Ratio',
|
||||
}),
|
||||
value: 'filter_ratio',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.maxLabel', { defaultMessage: 'Max' }),
|
||||
value: 'max'
|
||||
value: 'max',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.minLabel', { defaultMessage: 'Min' }),
|
||||
value: 'min'
|
||||
value: 'min',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.percentileLabel', { defaultMessage: 'Percentile' }),
|
||||
value: 'percentile'
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.percentileLabel', {
|
||||
defaultMessage: 'Percentile',
|
||||
}),
|
||||
value: 'percentile',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.percentileRankLabel', { defaultMessage: 'Percentile Rank' }),
|
||||
value: 'percentile_rank'
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.percentileRankLabel', {
|
||||
defaultMessage: 'Percentile Rank',
|
||||
}),
|
||||
value: 'percentile_rank',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.staticValueLabel', { defaultMessage: 'Static Value' }),
|
||||
value: 'static'
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.staticValueLabel', {
|
||||
defaultMessage: 'Static Value',
|
||||
}),
|
||||
value: 'static',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.stdDeviationLabel', { defaultMessage: 'Std. Deviation' }),
|
||||
value: 'std_deviation'
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.stdDeviationLabel', {
|
||||
defaultMessage: 'Std. Deviation',
|
||||
}),
|
||||
value: 'std_deviation',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.sumLabel', { defaultMessage: 'Sum' }),
|
||||
value: 'sum'
|
||||
value: 'sum',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.sumOfSquaresLabel', { defaultMessage: 'Sum of Squares' }),
|
||||
value: 'sum_of_squares'
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.sumOfSquaresLabel', {
|
||||
defaultMessage: 'Sum of Squares',
|
||||
}),
|
||||
value: 'sum_of_squares',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.topHitLabel', { defaultMessage: 'Top Hit' }),
|
||||
value: 'top_hit'
|
||||
value: 'top_hit',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.valueCountLabel', { defaultMessage: 'Value Count' }),
|
||||
value: 'value_count'
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.valueCountLabel', {
|
||||
defaultMessage: 'Value Count',
|
||||
}),
|
||||
value: 'value_count',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.varianceLabel', { defaultMessage: 'Variance' }),
|
||||
value: 'variance'
|
||||
label: i18n.translate('tsvb.aggSelect.metricsAggs.varianceLabel', {
|
||||
defaultMessage: 'Variance',
|
||||
}),
|
||||
value: 'variance',
|
||||
},
|
||||
];
|
||||
|
||||
const pipelineAggs = [
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.bucketScriptLabel', { defaultMessage: 'Bucket Script' }),
|
||||
value: 'calculation'
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.bucketScriptLabel', {
|
||||
defaultMessage: 'Bucket Script',
|
||||
}),
|
||||
value: 'calculation',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.cumulativeSumLabel', { defaultMessage: 'Cumulative Sum' }),
|
||||
value: 'cumulative_sum'
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.cumulativeSumLabel', {
|
||||
defaultMessage: 'Cumulative Sum',
|
||||
}),
|
||||
value: 'cumulative_sum',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.derivativeLabel', { defaultMessage: 'Derivative' }),
|
||||
value: 'derivative'
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.derivativeLabel', {
|
||||
defaultMessage: 'Derivative',
|
||||
}),
|
||||
value: 'derivative',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.movingAverageLabel', { defaultMessage: 'Moving Average' }),
|
||||
value: 'moving_average'
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.movingAverageLabel', {
|
||||
defaultMessage: 'Moving Average',
|
||||
}),
|
||||
value: 'moving_average',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.positiveOnlyLabel', { defaultMessage: 'Positive Only' }),
|
||||
value: 'positive_only'
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.positiveOnlyLabel', {
|
||||
defaultMessage: 'Positive Only',
|
||||
}),
|
||||
value: 'positive_only',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.serialDifferenceLabel', { defaultMessage: 'Serial Difference' }),
|
||||
value: 'serial_diff'
|
||||
label: i18n.translate('tsvb.aggSelect.pipelineAggs.serialDifferenceLabel', {
|
||||
defaultMessage: 'Serial Difference',
|
||||
}),
|
||||
value: 'serial_diff',
|
||||
},
|
||||
];
|
||||
|
||||
const siblingAggs = [
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallAverageLabel', { defaultMessage: 'Overall Average' }),
|
||||
value: 'avg_bucket' },
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallMaxLabel', { defaultMessage: 'Overall Max' }),
|
||||
value: 'max_bucket'
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallAverageLabel', {
|
||||
defaultMessage: 'Overall Average',
|
||||
}),
|
||||
value: 'avg_bucket',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallMinLabel', { defaultMessage: 'Overall Min' }),
|
||||
value: 'min_bucket'
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallMaxLabel', {
|
||||
defaultMessage: 'Overall Max',
|
||||
}),
|
||||
value: 'max_bucket',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallStdDeviationLabel', { defaultMessage: 'Overall Std. Deviation' }),
|
||||
value: 'std_deviation_bucket'
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallMinLabel', {
|
||||
defaultMessage: 'Overall Min',
|
||||
}),
|
||||
value: 'min_bucket',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallSumLabel', { defaultMessage: 'Overall Sum' }),
|
||||
value: 'sum_bucket'
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallStdDeviationLabel', {
|
||||
defaultMessage: 'Overall Std. Deviation',
|
||||
}),
|
||||
value: 'std_deviation_bucket',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallSumOfSquaresLabel', { defaultMessage: 'Overall Sum of Squares' }),
|
||||
value: 'sum_of_squares_bucket'
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallSumLabel', {
|
||||
defaultMessage: 'Overall Sum',
|
||||
}),
|
||||
value: 'sum_bucket',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallVarianceLabel', { defaultMessage: 'Overall Variance' }),
|
||||
value: 'variance_bucket'
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallSumOfSquaresLabel', {
|
||||
defaultMessage: 'Overall Sum of Squares',
|
||||
}),
|
||||
value: 'sum_of_squares_bucket',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.siblingAggs.overallVarianceLabel', {
|
||||
defaultMessage: 'Overall Variance',
|
||||
}),
|
||||
value: 'variance_bucket',
|
||||
},
|
||||
];
|
||||
|
||||
const specialAggs = [
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.specialAggs.seriesAggLabel', { defaultMessage: 'Series Agg' }),
|
||||
value: 'series_agg'
|
||||
label: i18n.translate('tsvb.aggSelect.specialAggs.seriesAggLabel', {
|
||||
defaultMessage: 'Series Agg',
|
||||
}),
|
||||
value: 'series_agg',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.aggSelect.specialAggs.mathLabel', { defaultMessage: 'Math' }),
|
||||
value: 'math'
|
||||
value: 'math',
|
||||
},
|
||||
];
|
||||
|
||||
const allAggOptions = [
|
||||
...metricAggs,
|
||||
...pipelineAggs,
|
||||
...siblingAggs,
|
||||
...specialAggs
|
||||
];
|
||||
const allAggOptions = [...metricAggs, ...pipelineAggs, ...siblingAggs, ...specialAggs];
|
||||
|
||||
function filterByPanelType(panelType) {
|
||||
return agg => {
|
||||
|
@ -176,9 +218,7 @@ function AggSelectUi(props) {
|
|||
return value === option.value && isMetricEnabled(option.value, uiRestrictions);
|
||||
});
|
||||
|
||||
let enablePipelines = siblings.some(
|
||||
s => !!metricAggs.find(m => m.value === s.type)
|
||||
);
|
||||
let enablePipelines = siblings.some(s => !!metricAggs.find(m => m.value === s.type));
|
||||
|
||||
if (siblings.length <= 1) enablePipelines = false;
|
||||
|
||||
|
@ -186,28 +226,41 @@ function AggSelectUi(props) {
|
|||
if (panelType === 'metrics') {
|
||||
options = metricAggs;
|
||||
} else {
|
||||
const disableSiblingAggs = agg => ({ ...agg, disabled: !enablePipelines || !isMetricEnabled(agg.value, uiRestrictions) });
|
||||
const disableSiblingAggs = agg => ({
|
||||
...agg,
|
||||
disabled: !enablePipelines || !isMetricEnabled(agg.value, uiRestrictions),
|
||||
});
|
||||
|
||||
options = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.aggSelect.aggGroups.metricAggLabel', defaultMessage: 'Metric Aggregations' }),
|
||||
options: metricAggs
|
||||
.map(agg => ({ ...agg, disabled: !isMetricEnabled(agg.value, uiRestrictions) })),
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.aggSelect.aggGroups.metricAggLabel',
|
||||
defaultMessage: 'Metric Aggregations',
|
||||
}),
|
||||
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(disableSiblingAggs),
|
||||
id: 'tsvb.aggSelect.aggGroups.parentPipelineAggLabel',
|
||||
defaultMessage: 'Parent Pipeline Aggregations',
|
||||
}),
|
||||
options: pipelineAggs.filter(filterByPanelType(panelType)).map(disableSiblingAggs),
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.aggSelect.aggGroups.siblingPipelineAggLabel', defaultMessage: 'Sibling Pipeline Aggregations' }),
|
||||
id: 'tsvb.aggSelect.aggGroups.siblingPipelineAggLabel',
|
||||
defaultMessage: 'Sibling Pipeline Aggregations',
|
||||
}),
|
||||
options: siblingAggs.map(disableSiblingAggs),
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.aggSelect.aggGroups.specialAggLabel', defaultMessage: 'Special Aggregations' }),
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.aggSelect.aggGroups.specialAggLabel',
|
||||
defaultMessage: 'Special Aggregations',
|
||||
}),
|
||||
options: specialAggs.map(disableSiblingAggs),
|
||||
},
|
||||
];
|
||||
|
@ -222,7 +275,10 @@ function AggSelectUi(props) {
|
|||
<div data-test-subj="aggSelector">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
placeholder={intl.formatMessage({ id: 'tsvb.aggSelect.selectAggPlaceholder', defaultMessage: 'Select aggregation' })}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'tsvb.aggSelect.selectAggPlaceholder',
|
||||
defaultMessage: 'Select aggregation',
|
||||
})}
|
||||
options={options}
|
||||
selectedOptions={selectedOptions}
|
||||
onChange={handleChange}
|
||||
|
|
|
@ -30,7 +30,6 @@ import { handleAdd, handleDelete } from '../lib/collection_actions';
|
|||
const DROPPABLE_ID = 'aggs_dnd';
|
||||
|
||||
export class Aggs extends PureComponent {
|
||||
|
||||
render() {
|
||||
const { panel, model, fields, uiRestrictions } = this.props;
|
||||
const list = model.metrics;
|
||||
|
@ -38,11 +37,7 @@ export class Aggs extends PureComponent {
|
|||
const onChange = seriesChangeHandler(this.props, list);
|
||||
|
||||
return (
|
||||
<EuiDroppable
|
||||
droppableId={`${DROPPABLE_ID}:${model.id}`}
|
||||
type="MICRO"
|
||||
spacing="s"
|
||||
>
|
||||
<EuiDroppable droppableId={`${DROPPABLE_ID}:${model.id}`} type="MICRO" spacing="s">
|
||||
{list.map((row, idx) => (
|
||||
<EuiDraggable
|
||||
spacing="s"
|
||||
|
|
|
@ -41,12 +41,13 @@ import {
|
|||
} from '@elastic/eui';
|
||||
|
||||
export class CalculationAgg extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
if (!this.props.model.variables) {
|
||||
this.props.onChange(_.assign({}, this.props.model, {
|
||||
variables: [{ id: uuid.v1() }]
|
||||
}));
|
||||
this.props.onChange(
|
||||
_.assign({}, this.props.model, {
|
||||
variables: [{ id: uuid.v1() }],
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,10 +91,7 @@ export class CalculationAgg extends Component {
|
|||
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('variables')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.calculation.variablesLabel"
|
||||
defaultMessage="Variables"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.calculation.variablesLabel" defaultMessage="Variables" />
|
||||
</EuiFormLabel>
|
||||
<CalculationVars
|
||||
id={htmlId('variables')}
|
||||
|
@ -107,10 +105,12 @@ export class CalculationAgg extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('painless')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.calculation.painlessScriptLabel"
|
||||
defaultMessage="Painless Script"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.calculation.painlessScriptLabel"
|
||||
defaultMessage="Painless Script"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
helpText={
|
||||
<div>
|
||||
|
@ -119,26 +119,21 @@ export class CalculationAgg extends Component {
|
|||
defaultMessage="Variables are keys on the {params} object, i.e. {paramsName}. To access the bucket
|
||||
interval (in milliseconds) use {paramsInterval}."
|
||||
values={{
|
||||
params: (<EuiCode>params</EuiCode>),
|
||||
paramsName: (<EuiCode>params.<name></EuiCode>),
|
||||
paramsInterval: (<EuiCode>params._interval</EuiCode>)
|
||||
params: <EuiCode>params</EuiCode>,
|
||||
paramsName: <EuiCode>params.<name></EuiCode>,
|
||||
paramsInterval: <EuiCode>params._interval</EuiCode>,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<EuiTextArea
|
||||
onChange={handleTextChange('script')}
|
||||
value={model.script}
|
||||
fullWidth
|
||||
/>
|
||||
<EuiTextArea onChange={handleTextChange('script')} value={model.script} fullWidth />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CalculationAgg.propTypes = {
|
||||
|
|
|
@ -60,10 +60,7 @@ export function CumulativeSumAgg(props) {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.cumulativeSum.metricLabel"
|
||||
defaultMessage="Metric"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.cumulativeSum.metricLabel" defaultMessage="Metric" />}
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
|
@ -76,7 +73,6 @@ export function CumulativeSumAgg(props) {
|
|||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
CumulativeSumAgg.propTypes = {
|
||||
|
|
|
@ -59,10 +59,7 @@ export const DerivativeAgg = props => {
|
|||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.derivative.aggregationLabel"
|
||||
defaultMessage="Aggregation"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.derivative.aggregationLabel" defaultMessage="Aggregation" />
|
||||
</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
|
@ -76,10 +73,7 @@ export const DerivativeAgg = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.derivative.metricLabel"
|
||||
defaultMessage="Metric"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.derivative.metricLabel" defaultMessage="Metric" />}
|
||||
fullWidth
|
||||
>
|
||||
<MetricSelect
|
||||
|
@ -94,18 +88,16 @@ export const DerivativeAgg = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('units')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.derivative.unitsLabel"
|
||||
defaultMessage="Units (1s, 1m, etc)"
|
||||
description="1s and 1m are required values and must not be translated."
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.derivative.unitsLabel"
|
||||
defaultMessage="Units (1s, 1m, etc)"
|
||||
description="1s and 1m are required values and must not be translated."
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('unit')}
|
||||
value={model.unit}
|
||||
fullWidth
|
||||
/>
|
||||
<EuiFieldText onChange={handleTextChange('unit')} value={model.unit} fullWidth />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -19,9 +19,7 @@
|
|||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiComboBox,
|
||||
} from '@elastic/eui';
|
||||
import { EuiComboBox } from '@elastic/eui';
|
||||
import { injectI18n } from '@kbn/i18n/react';
|
||||
import { isFieldEnabled } from '../../lib/check_ui_restrictions';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -41,35 +39,39 @@ function FieldSelectUi({
|
|||
uiRestrictions,
|
||||
...rest
|
||||
}) {
|
||||
|
||||
if (type === 'count') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const selectedOptions = [];
|
||||
const options = Object.values((fields[indexPattern] || []).reduce((acc, field) => {
|
||||
if (isFieldTypeEnabled(restrict, field.type) && isFieldEnabled(field.name, type, uiRestrictions)) {
|
||||
const item = {
|
||||
label: field.name,
|
||||
value: field.name
|
||||
};
|
||||
|
||||
if (acc[field.type]) {
|
||||
acc[field.type].options.push(item);
|
||||
} else {
|
||||
acc[field.type] = {
|
||||
options: [item],
|
||||
label: field.type,
|
||||
const options = Object.values(
|
||||
(fields[indexPattern] || []).reduce((acc, field) => {
|
||||
if (
|
||||
isFieldTypeEnabled(restrict, field.type) &&
|
||||
isFieldEnabled(field.name, type, uiRestrictions)
|
||||
) {
|
||||
const item = {
|
||||
label: field.name,
|
||||
value: field.name,
|
||||
};
|
||||
|
||||
if (acc[field.type]) {
|
||||
acc[field.type].options.push(item);
|
||||
} else {
|
||||
acc[field.type] = {
|
||||
options: [item],
|
||||
label: field.type,
|
||||
};
|
||||
}
|
||||
|
||||
if (value === item.value) {
|
||||
selectedOptions.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (value === item.value) {
|
||||
selectedOptions.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {}));
|
||||
return acc;
|
||||
}, {})
|
||||
);
|
||||
|
||||
if (onChange && value && !selectedOptions.length) {
|
||||
onChange();
|
||||
|
@ -94,7 +96,7 @@ FieldSelectUi.defaultProps = {
|
|||
restrict: [],
|
||||
placeholder: i18n.translate('tsvb.fieldSelect.selectFieldPlaceholder', {
|
||||
defaultMessage: 'Select field...',
|
||||
})
|
||||
}),
|
||||
};
|
||||
|
||||
FieldSelectUi.propTypes = {
|
||||
|
|
|
@ -39,21 +39,18 @@ import { ES_TYPES } from '../../../common/es_types';
|
|||
import { METRIC_TYPES } from '../../../common/metric_types';
|
||||
|
||||
export const FilterRatioAgg = props => {
|
||||
const {
|
||||
series,
|
||||
fields,
|
||||
panel
|
||||
} = props;
|
||||
const { series, fields, panel } = props;
|
||||
|
||||
const handleChange = createChangeHandler(props.onChange, props.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 defaults = {
|
||||
numerator: '*',
|
||||
denominator: '*',
|
||||
metric_agg: 'count'
|
||||
metric_agg: 'count',
|
||||
};
|
||||
|
||||
const model = { ...defaults, ...props.model };
|
||||
|
@ -71,13 +68,9 @@ export const FilterRatioAgg = props => {
|
|||
dragHandleProps={props.dragHandleProps}
|
||||
>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.filterRatio.aggregationLabel"
|
||||
defaultMessage="Aggregation"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.filterRatio.aggregationLabel" defaultMessage="Aggregation" />
|
||||
</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
|
@ -91,39 +84,32 @@ export const FilterRatioAgg = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('numerator')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.filterRatio.numeratorLabel"
|
||||
defaultMessage="Numerator"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.filterRatio.numeratorLabel" defaultMessage="Numerator" />
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('numerator')}
|
||||
value={model.numerator}
|
||||
/>
|
||||
<EuiFieldText onChange={handleTextChange('numerator')} value={model.numerator} />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('denominator')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.filterRatio.denominatorLabel"
|
||||
defaultMessage="Denominator"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.filterRatio.denominatorLabel"
|
||||
defaultMessage="Denominator"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('denominator')}
|
||||
value={model.denominator}
|
||||
/>
|
||||
<EuiFieldText onChange={handleTextChange('denominator')} value={model.denominator} />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('metric')}>
|
||||
<FormattedMessage
|
||||
|
@ -140,14 +126,11 @@ export const FilterRatioAgg = props => {
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{ model.metric_agg !== 'count' ? (
|
||||
{model.metric_agg !== 'count' ? (
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('aggField')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.filterRatio.fieldLabel"
|
||||
defaultMessage="Field"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.filterRatio.fieldLabel" defaultMessage="Field" />}
|
||||
>
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
|
@ -158,8 +141,8 @@ export const FilterRatioAgg = props => {
|
|||
onChange={handleSelectChange('field')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>) : null }
|
||||
|
||||
</EuiFlexItem>
|
||||
) : null}
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
|
|
|
@ -74,10 +74,7 @@ export class MathAgg extends Component {
|
|||
<EuiFlexGroup direction="column" gutterSize="l">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.math.aggregationLabel"
|
||||
defaultMessage="Aggregation"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.math.aggregationLabel" defaultMessage="Aggregation" />
|
||||
</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
|
@ -89,10 +86,7 @@ export class MathAgg extends Component {
|
|||
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('variables')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.math.variablesLabel"
|
||||
defaultMessage="Variables"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.math.variablesLabel" defaultMessage="Variables" />
|
||||
</EuiFormLabel>
|
||||
<CalculationVars
|
||||
id={htmlId('variables')}
|
||||
|
@ -107,38 +101,40 @@ export class MathAgg extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id="mathExpressionInput"
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.math.expressionLabel"
|
||||
defaultMessage="Expression"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.math.expressionLabel" defaultMessage="Expression" />
|
||||
}
|
||||
fullWidth
|
||||
helpText={(<FormattedMessage
|
||||
id="tsvb.math.expressionDescription"
|
||||
defaultMessage="This field uses basic math expressions (see {link}) - Variables are keys on the {params} object,
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id="tsvb.math.expressionDescription"
|
||||
defaultMessage="This field uses basic math expressions (see {link}) - Variables are keys on the {params} object,
|
||||
i.e. {paramsName} To access all the data use {paramsValues} for an array of the values and {paramsTimestamps} for
|
||||
an array of the timestamps. {paramsTimestamp} is available for the current bucket's timestamp,
|
||||
{paramsIndex} is available for the current bucket's index, and {paramsInterval}s available for
|
||||
an array of the timestamps. {paramsTimestamp} is available for the current bucket's timestamp,
|
||||
{paramsIndex} is available for the current bucket's index, and {paramsInterval}s available for
|
||||
the interval in milliseconds."
|
||||
values={{
|
||||
link: (
|
||||
<EuiLink
|
||||
href="https://github.com/elastic/tinymath/blob/master/docs/functions.md"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.math.expressionDescription.tinyMathLinkText"
|
||||
defaultMessage="TinyMath"
|
||||
/>
|
||||
</EuiLink>),
|
||||
params: (<EuiCode>params</EuiCode>),
|
||||
paramsName: (<EuiCode>params.<name></EuiCode>),
|
||||
paramsValues: (<EuiCode>params._all.<name>.values</EuiCode>),
|
||||
paramsTimestamps: (<EuiCode>params._all.<name>.timestamps</EuiCode>),
|
||||
paramsTimestamp: (<EuiCode>params._timestamp</EuiCode>),
|
||||
paramsIndex: (<EuiCode>params._index</EuiCode>),
|
||||
paramsInterval: (<EuiCode>params._interval</EuiCode>)
|
||||
}}
|
||||
/>)}
|
||||
values={{
|
||||
link: (
|
||||
<EuiLink
|
||||
href="https://github.com/elastic/tinymath/blob/master/docs/functions.md"
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.math.expressionDescription.tinyMathLinkText"
|
||||
defaultMessage="TinyMath"
|
||||
/>
|
||||
</EuiLink>
|
||||
),
|
||||
params: <EuiCode>params</EuiCode>,
|
||||
paramsName: <EuiCode>params.<name></EuiCode>,
|
||||
paramsValues: <EuiCode>params._all.<name>.values</EuiCode>,
|
||||
paramsTimestamps: <EuiCode>params._all.<name>.timestamps</EuiCode>,
|
||||
paramsTimestamp: <EuiCode>params._timestamp</EuiCode>,
|
||||
paramsIndex: <EuiCode>params._index</EuiCode>,
|
||||
paramsInterval: <EuiCode>params._interval</EuiCode>,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiTextArea
|
||||
data-test-subj="mathExpression"
|
||||
|
|
|
@ -21,9 +21,7 @@ import PropTypes from 'prop-types';
|
|||
import React from 'react';
|
||||
import { includes } from 'lodash';
|
||||
import { injectI18n } from '@kbn/i18n/react';
|
||||
import {
|
||||
EuiComboBox,
|
||||
} from '@elastic/eui';
|
||||
import { EuiComboBox } from '@elastic/eui';
|
||||
import { calculateSiblings } from '../lib/calculate_siblings';
|
||||
import { calculateLabel } from '../../../common/calculate_label';
|
||||
import { basicAggs } from '../../../common/basic_aggs';
|
||||
|
@ -46,11 +44,7 @@ function createTypeFilter(restrict, exclude) {
|
|||
export function filterRows(includeSiblings) {
|
||||
return row => {
|
||||
if (includeSiblings) {
|
||||
return (
|
||||
!/^series/.test(row.type) &&
|
||||
!/^percentile/.test(row.type) &&
|
||||
row.type !== 'math'
|
||||
);
|
||||
return !/^series/.test(row.type) && !/^percentile/.test(row.type) && row.type !== 'math';
|
||||
}
|
||||
return (
|
||||
!/_bucket$/.test(row.type) &&
|
||||
|
@ -62,7 +56,19 @@ export function filterRows(includeSiblings) {
|
|||
}
|
||||
|
||||
function MetricSelectUi(props) {
|
||||
const { additionalOptions, restrict, metric, metrics, onChange, value, exclude, includeSiblings, clearable, intl, ...rest } = props;
|
||||
const {
|
||||
additionalOptions,
|
||||
restrict,
|
||||
metric,
|
||||
metrics,
|
||||
onChange,
|
||||
value,
|
||||
exclude,
|
||||
includeSiblings,
|
||||
clearable,
|
||||
intl,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const calculatedMetrics = metrics.filter(createTypeFilter(restrict, exclude));
|
||||
|
||||
|
@ -116,7 +122,10 @@ function MetricSelectUi(props) {
|
|||
|
||||
return (
|
||||
<EuiComboBox
|
||||
placeholder={intl.formatMessage({ id: 'tsvb.metricSelect.selectMetricPlaceholder', defaultMessage: 'Select metric…' })}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'tsvb.metricSelect.selectMetricPlaceholder',
|
||||
defaultMessage: 'Select metric…',
|
||||
})}
|
||||
options={allOptions}
|
||||
selectedOptions={selectedOptions}
|
||||
onChange={onChange}
|
||||
|
|
|
@ -45,7 +45,7 @@ const MovingAverageAggUi = props => {
|
|||
settings: '',
|
||||
minimize: 0,
|
||||
window: '',
|
||||
model: 'simple'
|
||||
model: 'simple',
|
||||
};
|
||||
const model = { ...defaults, ...props.model };
|
||||
const handleChange = createChangeHandler(props.onChange, model);
|
||||
|
@ -54,31 +54,42 @@ const MovingAverageAggUi = props => {
|
|||
const handleNumberChange = createNumberHandler(handleChange);
|
||||
const modelOptions = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.movingAverage.modelOptions.simpleLabel', defaultMessage: 'Simple' }),
|
||||
value: 'simple'
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.movingAverage.modelOptions.linearLabel', defaultMessage: 'Linear' }),
|
||||
value: 'linear'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.movingAverage.modelOptions.simpleLabel',
|
||||
defaultMessage: 'Simple',
|
||||
}),
|
||||
value: 'simple',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.movingAverage.modelOptions.exponentiallyWeightedLabel', defaultMessage: 'Exponentially Weighted' }),
|
||||
value: 'ewma'
|
||||
id: 'tsvb.movingAverage.modelOptions.linearLabel',
|
||||
defaultMessage: 'Linear',
|
||||
}),
|
||||
value: 'linear',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.movingAverage.modelOptions.holtLinearLabel', defaultMessage: 'Holt-Linear' }),
|
||||
value: 'holt'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.movingAverage.modelOptions.exponentiallyWeightedLabel',
|
||||
defaultMessage: 'Exponentially Weighted',
|
||||
}),
|
||||
value: 'ewma',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.movingAverage.modelOptions.holtWintersLabel', defaultMessage: 'Holt-Winters' }),
|
||||
value: 'holt_winters'
|
||||
}
|
||||
];
|
||||
const minimizeOptions = [
|
||||
{ label: 'True', value: 1 },
|
||||
{ label: 'False', value: 0 }
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.movingAverage.modelOptions.holtLinearLabel',
|
||||
defaultMessage: 'Holt-Linear',
|
||||
}),
|
||||
value: 'holt',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.movingAverage.modelOptions.holtWintersLabel',
|
||||
defaultMessage: 'Holt-Winters',
|
||||
}),
|
||||
value: 'holt_winters',
|
||||
},
|
||||
];
|
||||
const minimizeOptions = [{ label: 'True', value: 1 }, { label: 'False', value: 0 }];
|
||||
const htmlId = htmlIdGenerator();
|
||||
const selectedModelOption = modelOptions.find(option => {
|
||||
return model.model === option.value;
|
||||
|
@ -115,10 +126,7 @@ const MovingAverageAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.movingAverage.metricLabel"
|
||||
defaultMessage="Metric"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.movingAverage.metricLabel" defaultMessage="Metric" />}
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
|
@ -136,14 +144,14 @@ const MovingAverageAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('model')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.movingAverage.modelLabel"
|
||||
defaultMessage="Model"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.movingAverage.modelLabel" defaultMessage="Model" />}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
placeholder={intl.formatMessage({ id: 'tsvb.movingAverage.model.selectPlaceholder', defaultMessage: 'Select' })}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'tsvb.movingAverage.model.selectPlaceholder',
|
||||
defaultMessage: 'Select',
|
||||
})}
|
||||
options={modelOptions}
|
||||
selectedOptions={selectedModelOption ? [selectedModelOption] : []}
|
||||
onChange={handleSelectChange('model')}
|
||||
|
@ -154,10 +162,12 @@ const MovingAverageAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('windowSize')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.movingAverage.windowSizeLabel"
|
||||
defaultMessage="Window Size"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.movingAverage.windowSizeLabel"
|
||||
defaultMessage="Window Size"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
|
@ -174,13 +184,15 @@ const MovingAverageAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('minimize')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.movingAverage.minimizeLabel"
|
||||
defaultMessage="Minimize"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.movingAverage.minimizeLabel" defaultMessage="Minimize" />
|
||||
}
|
||||
>
|
||||
<EuiComboBox
|
||||
placeholder={intl.formatMessage({ id: 'tsvb.movingAverage.minimize.selectPlaceholder', defaultMessage: 'Select' })}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'tsvb.movingAverage.minimize.selectPlaceholder',
|
||||
defaultMessage: 'Select',
|
||||
})}
|
||||
options={minimizeOptions}
|
||||
selectedOptions={selectedMinimizeOption ? [selectedMinimizeOption] : []}
|
||||
onChange={handleSelectChange('minimize')}
|
||||
|
@ -191,10 +203,9 @@ const MovingAverageAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('predict')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.movingAverage.predictLabel"
|
||||
defaultMessage="Predict"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.movingAverage.predictLabel" defaultMessage="Predict" />
|
||||
}
|
||||
>
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
|
@ -216,25 +227,20 @@ const MovingAverageAggUi = props => {
|
|||
<EuiFormRow
|
||||
fullWidth
|
||||
id={htmlId('settings')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.movingAverage.settingsLabel"
|
||||
defaultMessage="Settings"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.movingAverage.settingsLabel" defaultMessage="Settings" />
|
||||
}
|
||||
helpText={
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.movingAverage.settingsDescription"
|
||||
defaultMessage="{keyValue} space-delimited"
|
||||
values={{ keyValue: (<EuiCode>Key=Value</EuiCode>) }}
|
||||
values={{ keyValue: <EuiCode>Key=Value</EuiCode> }}
|
||||
/>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<EuiTextArea
|
||||
onChange={handleTextChange('settings')}
|
||||
value={model.settings}
|
||||
fullWidth
|
||||
/>
|
||||
<EuiTextArea onChange={handleTextChange('settings')} value={model.settings} fullWidth />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</AggRow>
|
||||
|
|
|
@ -23,9 +23,6 @@ import _ from 'lodash';
|
|||
import { AggSelect } from './agg_select';
|
||||
import { FieldSelect } from './field_select';
|
||||
import { AggRow } from './agg_row';
|
||||
import { collectionActions } from '../lib/collection_actions';
|
||||
import { AddDeleteButtons } from '../add_delete_buttons';
|
||||
import uuid from 'uuid';
|
||||
import { createChangeHandler } from '../lib/create_change_handler';
|
||||
import { createSelectHandler } from '../lib/create_select_handler';
|
||||
import {
|
||||
|
@ -34,186 +31,24 @@ import {
|
|||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiComboBox,
|
||||
EuiFieldNumber,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { ES_TYPES } from '../../../common/es_types';
|
||||
|
||||
const newPercentile = (opts) => {
|
||||
return _.assign({ id: uuid.v1(), mode: 'line', shade: 0.2 }, opts);
|
||||
};
|
||||
import { Percentiles, newPercentile } from './percentile_ui';
|
||||
|
||||
const RESTRICT_FIELDS = [ES_TYPES.NUMBER];
|
||||
|
||||
class PercentilesUi extends Component {
|
||||
|
||||
handleTextChange(item, name) {
|
||||
return (e) => {
|
||||
const handleChange = collectionActions.handleChange.bind(null, this.props);
|
||||
const part = {};
|
||||
part[name] = _.get(e, '[0].value', _.get(e, 'target.value'));
|
||||
handleChange(_.assign({}, item, part));
|
||||
};
|
||||
}
|
||||
|
||||
renderRow = (row, i, items) => {
|
||||
const defaults = { value: '', percentile: '', shade: '' };
|
||||
const model = { ...defaults, ...row };
|
||||
const { intl, panel } = this.props;
|
||||
|
||||
const percentileFieldNumber = (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFieldNumber
|
||||
aria-label={intl.formatMessage({ id: 'tsvb.percentile.percentileAriaLabel', defaultMessage: 'Percentile' })}
|
||||
placeholder={0}
|
||||
max={100}
|
||||
min={0}
|
||||
step={1}
|
||||
onChange={this.handleTextChange(model, 'value')}
|
||||
value={model.value === '' ? '' : Number(model.value)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
|
||||
if (panel.type === 'table') {
|
||||
return percentileFieldNumber;
|
||||
}
|
||||
|
||||
const handleAdd = collectionActions.handleAdd.bind(null, this.props, newPercentile);
|
||||
const handleDelete = collectionActions.handleDelete.bind(null, this.props, model);
|
||||
const modeOptions = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.percentile.modeOptions.lineLabel', defaultMessage: 'Line' }),
|
||||
value: 'line'
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.percentile.modeOptions.bandLabel', defaultMessage: 'Band' }),
|
||||
value: 'band'
|
||||
}
|
||||
];
|
||||
const optionsStyle = {};
|
||||
if (model.mode === 'line') {
|
||||
optionsStyle.display = 'none';
|
||||
}
|
||||
const labelStyle = { marginBottom: 0 };
|
||||
const htmlId = htmlIdGenerator(model.id);
|
||||
const selectedModeOption = modeOptions.find(option => {
|
||||
return model.mode === option.value;
|
||||
});
|
||||
return (
|
||||
<EuiFlexItem key={model.id}>
|
||||
<EuiFlexGroup alignItems="center" responsive={false} gutterSize="s">
|
||||
|
||||
{ percentileFieldNumber }
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('mode')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.percentile.modeLabel"
|
||||
defaultMessage="Mode:"
|
||||
/>
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('mode')}
|
||||
options={modeOptions}
|
||||
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
|
||||
onChange={this.handleTextChange(model, 'mode')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('fillTo')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.percentile.fillToLabel"
|
||||
defaultMessage="Fill to:"
|
||||
/>
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFieldNumber
|
||||
id={htmlId('fillTo')}
|
||||
step={1}
|
||||
onChange={this.handleTextChange(model, 'percentile')}
|
||||
value={Number(model.percentile)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('shade')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.percentile.shadeLabel"
|
||||
defaultMessage="Shade (0 to 1):"
|
||||
/>
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFieldNumber
|
||||
id={htmlId('shade')}
|
||||
style={optionsStyle}
|
||||
step={0.1}
|
||||
onChange={this.handleTextChange(model, 'shade')}
|
||||
value={Number(model.shade)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
disableDelete={items.length < 2}
|
||||
responsive={false}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { model, name, panel } = this.props;
|
||||
if (!model[name]) return (<div/>);
|
||||
let rows;
|
||||
if (panel.type === 'table') {
|
||||
rows = this.renderRow(_.last(model[name]));
|
||||
} else {
|
||||
rows = model[name].map(this.renderRow);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiFlexGroup direction="column" gutterSize="s">
|
||||
{ rows }
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PercentilesUi.defaultProps = {
|
||||
name: 'percentile'
|
||||
};
|
||||
|
||||
PercentilesUi.propTypes = {
|
||||
name: PropTypes.string,
|
||||
model: PropTypes.object,
|
||||
panel: PropTypes.object,
|
||||
onChange: PropTypes.func
|
||||
};
|
||||
|
||||
const Percentiles = injectI18n(PercentilesUi);
|
||||
|
||||
export class PercentileAgg extends Component { // eslint-disable-line react/no-multi-comp
|
||||
export class PercentileAgg extends Component {
|
||||
// eslint-disable-line react/no-multi-comp
|
||||
|
||||
componentWillMount() {
|
||||
if (!this.props.model.percentiles) {
|
||||
this.props.onChange(_.assign({}, this.props.model, {
|
||||
percentiles: [newPercentile({ value: 50 })]
|
||||
}));
|
||||
this.props.onChange(
|
||||
_.assign({}, this.props.model, {
|
||||
percentiles: [newPercentile({ value: 50 })],
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,7 +57,8 @@ export class PercentileAgg extends Component { // eslint-disable-line react/no-m
|
|||
|
||||
const handleChange = createChangeHandler(this.props.onChange, model);
|
||||
const handleSelectChange = createSelectHandler(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();
|
||||
|
||||
return (
|
||||
|
@ -253,10 +89,7 @@ export class PercentileAgg extends Component { // eslint-disable-line react/no-m
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('field')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.percentile.fieldLabel"
|
||||
defaultMessage="Field"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.percentile.fieldLabel" defaultMessage="Field" />}
|
||||
>
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
|
@ -272,17 +105,10 @@ export class PercentileAgg extends Component { // eslint-disable-line react/no-m
|
|||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<Percentiles
|
||||
onChange={handleChange}
|
||||
name="percentiles"
|
||||
model={model}
|
||||
panel={panel}
|
||||
/>
|
||||
|
||||
<Percentiles onChange={handleChange} name="percentiles" model={model} panel={panel} />
|
||||
</AggRow>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PercentileAgg.propTypes = {
|
||||
|
|
|
@ -31,30 +31,21 @@ import {
|
|||
|
||||
import { AddDeleteButtons } from '../../add_delete_buttons';
|
||||
|
||||
export const MultiValueRow = ({
|
||||
model,
|
||||
onChange,
|
||||
onDelete,
|
||||
onAdd,
|
||||
disableAdd,
|
||||
disableDelete,
|
||||
}) => {
|
||||
export const MultiValueRow = ({ model, onChange, onDelete, onAdd, disableAdd, disableDelete }) => {
|
||||
const htmlId = htmlIdGenerator();
|
||||
|
||||
const onFieldNumberChange = event => onChange({
|
||||
...model,
|
||||
value: get(event, 'target.value')
|
||||
});
|
||||
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:"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.multivalueRow.valueLabel" defaultMessage="Value:" />
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -73,7 +64,7 @@ export const MultiValueRow = ({
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer/>
|
||||
<EuiSpacer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -93,4 +84,3 @@ MultiValueRow.propTypes = {
|
|||
defaultAddValue: PropTypes.string,
|
||||
disableDelete: PropTypes.bool,
|
||||
};
|
||||
|
||||
|
|
|
@ -45,16 +45,19 @@ export const PercentileRankAgg = props => {
|
|||
const defaults = { values: [''] };
|
||||
const model = { ...defaults, ...props.model };
|
||||
|
||||
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 isTablePanel = panel.type === 'table';
|
||||
const handleChange = createChangeHandler(props.onChange, model);
|
||||
const handleSelectChange = createSelectHandler(handleChange);
|
||||
|
||||
const handlePercentileRankValuesChange = (values) => {
|
||||
handleChange(assign({}, model, {
|
||||
values,
|
||||
}));
|
||||
const handlePercentileRankValuesChange = values => {
|
||||
handleChange(
|
||||
assign({}, model, {
|
||||
values,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -85,10 +88,7 @@ export const PercentileRankAgg = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('field')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.percentileRank.fieldLabel"
|
||||
defaultMessage="Field"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.percentileRank.fieldLabel" defaultMessage="Field" />}
|
||||
>
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
|
@ -101,7 +101,7 @@ export const PercentileRankAgg = props => {
|
|||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer/>
|
||||
<EuiSpacer />
|
||||
<PercentileRankValues
|
||||
disableAdd={isTablePanel}
|
||||
disableDelete={isTablePanel}
|
||||
|
|
|
@ -20,9 +20,7 @@ import PropTypes from 'prop-types';
|
|||
import React from 'react';
|
||||
import { last } from 'lodash';
|
||||
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
} from '@elastic/eui';
|
||||
import { EuiFlexGroup } from '@elastic/eui';
|
||||
import { MultiValueRow } from './multi_value_row';
|
||||
|
||||
export const PercentileRankValues = props => {
|
||||
|
@ -34,9 +32,8 @@ export const PercentileRankValues = props => {
|
|||
|
||||
onChange(model);
|
||||
};
|
||||
const onDeleteValue = ({ id }) => onChange(
|
||||
model.filter((item, currentIndex) => id !== currentIndex),
|
||||
);
|
||||
const onDeleteValue = ({ id }) =>
|
||||
onChange(model.filter((item, currentIndex) => id !== currentIndex));
|
||||
const onAddValue = () => onChange([...model, '']);
|
||||
|
||||
const renderRow = ({ rowModel, disableDelete, disableAdd }) => (
|
||||
|
@ -48,28 +45,32 @@ export const PercentileRankValues = props => {
|
|||
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) => (
|
||||
{showOnlyLastRow &&
|
||||
renderRow({
|
||||
rowModel: {
|
||||
id,
|
||||
value,
|
||||
id: model.length - 1,
|
||||
value: last(model),
|
||||
},
|
||||
disableAdd,
|
||||
disableDelete: disableDelete || array.length < 2,
|
||||
})))}
|
||||
disableAdd: true,
|
||||
disableDelete: true,
|
||||
})}
|
||||
|
||||
{!showOnlyLastRow &&
|
||||
model.map((value, id, array) =>
|
||||
renderRow({
|
||||
rowModel: {
|
||||
id,
|
||||
value,
|
||||
},
|
||||
disableAdd,
|
||||
disableDelete: disableDelete || array.length < 2,
|
||||
})
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* 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, { Component } from 'react';
|
||||
import _ from 'lodash';
|
||||
import { collectionActions } from '../lib/collection_actions';
|
||||
import { AddDeleteButtons } from '../add_delete_buttons';
|
||||
import uuid from 'uuid';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiComboBox,
|
||||
EuiFieldNumber,
|
||||
} from '@elastic/eui';
|
||||
import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
export const newPercentile = opts => {
|
||||
return _.assign({ id: uuid.v1(), mode: 'line', shade: 0.2 }, opts);
|
||||
};
|
||||
|
||||
class PercentilesUi extends Component {
|
||||
handleTextChange(item, name) {
|
||||
return e => {
|
||||
const handleChange = collectionActions.handleChange.bind(null, this.props);
|
||||
const part = {};
|
||||
part[name] = _.get(e, '[0].value', _.get(e, 'target.value'));
|
||||
handleChange(_.assign({}, item, part));
|
||||
};
|
||||
}
|
||||
|
||||
renderRow = (row, i, items) => {
|
||||
const defaults = { value: '', percentile: '', shade: '' };
|
||||
const model = { ...defaults, ...row };
|
||||
const { intl, panel } = this.props;
|
||||
|
||||
const percentileFieldNumber = (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFieldNumber
|
||||
aria-label={intl.formatMessage({
|
||||
id: 'tsvb.percentile.percentileAriaLabel',
|
||||
defaultMessage: 'Percentile',
|
||||
})}
|
||||
placeholder={0}
|
||||
max={100}
|
||||
min={0}
|
||||
step={1}
|
||||
onChange={this.handleTextChange(model, 'value')}
|
||||
value={model.value === '' ? '' : Number(model.value)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
|
||||
if (panel.type === 'table') {
|
||||
return percentileFieldNumber;
|
||||
}
|
||||
|
||||
const handleAdd = collectionActions.handleAdd.bind(null, this.props, newPercentile);
|
||||
const handleDelete = collectionActions.handleDelete.bind(null, this.props, model);
|
||||
const modeOptions = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.percentile.modeOptions.lineLabel',
|
||||
defaultMessage: 'Line',
|
||||
}),
|
||||
value: 'line',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.percentile.modeOptions.bandLabel',
|
||||
defaultMessage: 'Band',
|
||||
}),
|
||||
value: 'band',
|
||||
},
|
||||
];
|
||||
const optionsStyle = {};
|
||||
if (model.mode === 'line') {
|
||||
optionsStyle.display = 'none';
|
||||
}
|
||||
const labelStyle = { marginBottom: 0 };
|
||||
const htmlId = htmlIdGenerator(model.id);
|
||||
const selectedModeOption = modeOptions.find(option => {
|
||||
return model.mode === option.value;
|
||||
});
|
||||
return (
|
||||
<EuiFlexItem key={model.id}>
|
||||
<EuiFlexGroup alignItems="center" responsive={false} gutterSize="s">
|
||||
{percentileFieldNumber}
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('mode')}>
|
||||
<FormattedMessage id="tsvb.percentile.modeLabel" defaultMessage="Mode:" />
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('mode')}
|
||||
options={modeOptions}
|
||||
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
|
||||
onChange={this.handleTextChange(model, 'mode')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('fillTo')}>
|
||||
<FormattedMessage id="tsvb.percentile.fillToLabel" defaultMessage="Fill to:" />
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFieldNumber
|
||||
id={htmlId('fillTo')}
|
||||
step={1}
|
||||
onChange={this.handleTextChange(model, 'percentile')}
|
||||
value={Number(model.percentile)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('shade')}>
|
||||
<FormattedMessage id="tsvb.percentile.shadeLabel" defaultMessage="Shade (0 to 1):" />
|
||||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFieldNumber
|
||||
id={htmlId('shade')}
|
||||
style={optionsStyle}
|
||||
step={0.1}
|
||||
onChange={this.handleTextChange(model, 'shade')}
|
||||
value={Number(model.shade)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
disableDelete={items.length < 2}
|
||||
responsive={false}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { model, name, panel } = this.props;
|
||||
if (!model[name]) return <div />;
|
||||
let rows;
|
||||
if (panel.type === 'table') {
|
||||
rows = this.renderRow(_.last(model[name]));
|
||||
} else {
|
||||
rows = model[name].map(this.renderRow);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiFlexGroup direction="column" gutterSize="s">
|
||||
{rows}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PercentilesUi.defaultProps = {
|
||||
name: 'percentile',
|
||||
};
|
||||
|
||||
PercentilesUi.propTypes = {
|
||||
name: PropTypes.string,
|
||||
model: PropTypes.object,
|
||||
panel: PropTypes.object,
|
||||
onChange: PropTypes.func,
|
||||
};
|
||||
|
||||
export const Percentiles = injectI18n(PercentilesUi);
|
|
@ -65,10 +65,7 @@ export const PositiveOnlyAgg = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.positiveOnly.metricLabel"
|
||||
defaultMessage="Metric"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.positiveOnly.metricLabel" defaultMessage="Metric" />}
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
|
|
|
@ -51,10 +51,7 @@ export const SerialDiffAgg = props => {
|
|||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.serialDiff.aggregationLabel"
|
||||
defaultMessage="Aggregation"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.serialDiff.aggregationLabel" defaultMessage="Aggregation" />
|
||||
</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
|
@ -67,10 +64,7 @@ export const SerialDiffAgg = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.serialDiff.metricLabel"
|
||||
defaultMessage="Metric"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.serialDiff.metricLabel" defaultMessage="Metric" />}
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
|
@ -83,13 +77,15 @@ export const SerialDiffAgg = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('lag')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.serialDiff.lagLabel"
|
||||
defaultMessage="Lag"
|
||||
description="'Lag' refers to the parameter name of the serial diff translation
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.serialDiff.lagLabel"
|
||||
defaultMessage="Lag"
|
||||
description="'Lag' refers to the parameter name of the serial diff translation
|
||||
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-serialdiff-aggregation.html.
|
||||
This should only be translated if there is a reasaonable word explaining what that parameter does."
|
||||
/>)}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
|
|
|
@ -44,40 +44,67 @@ function SeriesAggUi(props) {
|
|||
|
||||
const functionOptions = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.seriesAgg.functionOptions.sumLabel', defaultMessage: 'Sum' }),
|
||||
value: 'sum'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.seriesAgg.functionOptions.sumLabel',
|
||||
defaultMessage: 'Sum',
|
||||
}),
|
||||
value: 'sum',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.seriesAgg.functionOptions.maxLabel', defaultMessage: 'Max' }),
|
||||
value: 'max'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.seriesAgg.functionOptions.maxLabel',
|
||||
defaultMessage: 'Max',
|
||||
}),
|
||||
value: 'max',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.seriesAgg.functionOptions.minLabel', defaultMessage: 'Min' }),
|
||||
value: 'min'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.seriesAgg.functionOptions.minLabel',
|
||||
defaultMessage: 'Min',
|
||||
}),
|
||||
value: 'min',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.seriesAgg.functionOptions.avgLabel', defaultMessage: 'Avg' }),
|
||||
value: 'mean'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.seriesAgg.functionOptions.avgLabel',
|
||||
defaultMessage: 'Avg',
|
||||
}),
|
||||
value: 'mean',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.seriesAgg.functionOptions.overallSumLabel', defaultMessage: 'Overall Sum' }),
|
||||
value: 'overall_sum'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.seriesAgg.functionOptions.overallSumLabel',
|
||||
defaultMessage: 'Overall Sum',
|
||||
}),
|
||||
value: 'overall_sum',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.seriesAgg.functionOptions.overallMaxLabel', defaultMessage: 'Overall Max' }),
|
||||
value: 'overall_max'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.seriesAgg.functionOptions.overallMaxLabel',
|
||||
defaultMessage: 'Overall Max',
|
||||
}),
|
||||
value: 'overall_max',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.seriesAgg.functionOptions.overallMinLabel', defaultMessage: 'Overall Min' }),
|
||||
value: 'overall_min'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.seriesAgg.functionOptions.overallMinLabel',
|
||||
defaultMessage: 'Overall Min',
|
||||
}),
|
||||
value: 'overall_min',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.seriesAgg.functionOptions.overallAvgLabel', defaultMessage: 'Overall Avg' }),
|
||||
value: 'overall_avg'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.seriesAgg.functionOptions.overallAvgLabel',
|
||||
defaultMessage: 'Overall Avg',
|
||||
}),
|
||||
value: 'overall_avg',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.seriesAgg.functionOptions.cumulativeSumLabel', defaultMessage: 'Cumulative Sum' }),
|
||||
value: 'cumulative_sum'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.seriesAgg.functionOptions.cumulativeSumLabel',
|
||||
defaultMessage: 'Cumulative Sum',
|
||||
}),
|
||||
value: 'cumulative_sum',
|
||||
},
|
||||
];
|
||||
const selectedFunctionOption = functionOptions.find(option => {
|
||||
|
@ -118,10 +145,7 @@ function SeriesAggUi(props) {
|
|||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.seriesAgg.aggregationLabel"
|
||||
defaultMessage="Aggregation"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.seriesAgg.aggregationLabel" defaultMessage="Aggregation" />
|
||||
</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
|
@ -134,10 +158,7 @@ function SeriesAggUi(props) {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('function')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.seriesAgg.functionLabel"
|
||||
defaultMessage="Function"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.seriesAgg.functionLabel" defaultMessage="Function" />}
|
||||
>
|
||||
<EuiComboBox
|
||||
options={functionOptions}
|
||||
|
@ -150,7 +171,6 @@ function SeriesAggUi(props) {
|
|||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
SeriesAggUi.propTypes = {
|
||||
|
|
|
@ -61,10 +61,7 @@ export const Static = props => {
|
|||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.static.aggregationLabel"
|
||||
defaultMessage="Aggregation"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.static.aggregationLabel" defaultMessage="Aggregation" />
|
||||
</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
|
@ -77,10 +74,9 @@ export const Static = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('staticValue')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.static.staticValuesLabel"
|
||||
defaultMessage="Static Value"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.static.staticValuesLabel" defaultMessage="Static Value" />
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
onChange={handleTextChange('value')}
|
||||
|
|
|
@ -35,7 +35,8 @@ export function StandardAgg(props) {
|
|||
const handleSelectChange = createSelectHandler(handleChange);
|
||||
const restrictFields = model.type === METRIC_TYPES.CARDINALITY ? [] : [ES_TYPES.NUMBER];
|
||||
|
||||
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();
|
||||
|
||||
return (
|
||||
|
@ -50,10 +51,7 @@ export function StandardAgg(props) {
|
|||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.stdAgg.aggregationLabel"
|
||||
defaultMessage="Aggregation"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.stdAgg.aggregationLabel" defaultMessage="Aggregation" />
|
||||
</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
|
@ -66,33 +64,26 @@ export function StandardAgg(props) {
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{
|
||||
model.type !== 'count'
|
||||
? (
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('field')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.stdAgg.fieldLabel"
|
||||
defaultMessage="Field"
|
||||
/>)}
|
||||
fullWidth
|
||||
>
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
type={model.type}
|
||||
restrict={restrictFields}
|
||||
indexPattern={indexPattern}
|
||||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
uiRestrictions={uiRestrictions}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
) : null
|
||||
}
|
||||
|
||||
{model.type !== 'count' ? (
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('field')}
|
||||
label={<FormattedMessage id="tsvb.stdAgg.fieldLabel" defaultMessage="Field" />}
|
||||
fullWidth
|
||||
>
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
type={model.type}
|
||||
restrict={restrictFields}
|
||||
indexPattern={indexPattern}
|
||||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
uiRestrictions={uiRestrictions}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
) : null}
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
|
|
|
@ -46,23 +46,35 @@ const StandardDeviationAggUi = props => {
|
|||
|
||||
const modeOptions = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.stdDeviation.modeOptions.rawLabel', defaultMessage: 'Raw' }),
|
||||
value: 'raw'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.stdDeviation.modeOptions.rawLabel',
|
||||
defaultMessage: 'Raw',
|
||||
}),
|
||||
value: 'raw',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.stdDeviation.modeOptions.upperBoundLabel', defaultMessage: 'Upper Bound' }),
|
||||
value: 'upper'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.stdDeviation.modeOptions.upperBoundLabel',
|
||||
defaultMessage: 'Upper Bound',
|
||||
}),
|
||||
value: 'upper',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.stdDeviation.modeOptions.lowerBoundLabel', defaultMessage: 'Lower Bound' }),
|
||||
value: 'lower'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.stdDeviation.modeOptions.lowerBoundLabel',
|
||||
defaultMessage: 'Lower Bound',
|
||||
}),
|
||||
value: 'lower',
|
||||
},
|
||||
];
|
||||
|
||||
if (panel.type !== 'table') {
|
||||
modeOptions.push({
|
||||
label: intl.formatMessage({ id: 'tsvb.stdDeviation.modeOptions.boundsBandLabel', defaultMessage: 'Bounds Band' }),
|
||||
value: 'band'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.stdDeviation.modeOptions.boundsBandLabel',
|
||||
defaultMessage: 'Bounds Band',
|
||||
}),
|
||||
value: 'band',
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -70,7 +82,8 @@ const StandardDeviationAggUi = props => {
|
|||
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 selectedModeOption = modeOptions.find(option => {
|
||||
return model.mode === option.value;
|
||||
|
@ -104,10 +117,7 @@ const StandardDeviationAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('field')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.stdDeviation.fieldLabel"
|
||||
defaultMessage="Field"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.stdDeviation.fieldLabel" defaultMessage="Field" />}
|
||||
>
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
|
@ -122,24 +132,15 @@ const StandardDeviationAggUi = props => {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('sigma')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.stdDeviation.sigmaLabel"
|
||||
defaultMessage="Sigma"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.stdDeviation.sigmaLabel" defaultMessage="Sigma" />}
|
||||
>
|
||||
<EuiFieldText
|
||||
value={model.sigma}
|
||||
onChange={handleTextChange('sigma')}
|
||||
/>
|
||||
<EuiFieldText value={model.sigma} onChange={handleTextChange('sigma')} />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('mode')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.stdDeviation.modeLabel"
|
||||
defaultMessage="Mode"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.stdDeviation.modeLabel" defaultMessage="Mode" />}
|
||||
>
|
||||
<EuiComboBox
|
||||
options={modeOptions}
|
||||
|
|
|
@ -52,36 +52,42 @@ const StandardSiblingAggUi = props => {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('sigma')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.stdSibling.sigmaLabel"
|
||||
defaultMessage="Sigma"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.stdSibling.sigmaLabel" defaultMessage="Sigma" />}
|
||||
>
|
||||
<EuiFieldText
|
||||
value={model.sigma}
|
||||
onChange={handleTextChange('sigma')}
|
||||
/>
|
||||
<EuiFieldText value={model.sigma} onChange={handleTextChange('sigma')} />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
|
||||
const modeOptions = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.stdSibling.modeOptions.rawLabel', defaultMessage: 'Raw' }),
|
||||
value: 'raw'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.stdSibling.modeOptions.rawLabel',
|
||||
defaultMessage: 'Raw',
|
||||
}),
|
||||
value: 'raw',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.stdSibling.modeOptions.upperBoundLabel', defaultMessage: 'Upper Bound' }),
|
||||
value: 'upper'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.stdSibling.modeOptions.upperBoundLabel',
|
||||
defaultMessage: 'Upper Bound',
|
||||
}),
|
||||
value: 'upper',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.stdSibling.modeOptions.lowerBoundLabel', defaultMessage: 'Lower Bound' }),
|
||||
value: 'lower'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.stdSibling.modeOptions.lowerBoundLabel',
|
||||
defaultMessage: 'Lower Bound',
|
||||
}),
|
||||
value: 'lower',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.stdSibling.modeOptions.boundsBandLabel', defaultMessage: 'Bounds Band' }),
|
||||
value: 'band'
|
||||
}
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.stdSibling.modeOptions.boundsBandLabel',
|
||||
defaultMessage: 'Bounds Band',
|
||||
}),
|
||||
value: 'band',
|
||||
},
|
||||
];
|
||||
const selectedModeOption = modeOptions.find(option => {
|
||||
return model.mode === option.value;
|
||||
|
@ -91,10 +97,7 @@ const StandardSiblingAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('mode')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.stdSibling.modeLabel"
|
||||
defaultMessage="Mode"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.stdSibling.modeLabel" defaultMessage="Mode" />}
|
||||
>
|
||||
<EuiComboBox
|
||||
options={modeOptions}
|
||||
|
@ -119,10 +122,7 @@ const StandardSiblingAggUi = props => {
|
|||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.stdSibling.aggregationLabel"
|
||||
defaultMessage="Aggregation"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.stdSibling.aggregationLabel" defaultMessage="Aggregation" />
|
||||
</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
|
@ -136,10 +136,7 @@ const StandardSiblingAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.stdSibling.metricLabel"
|
||||
defaultMessage="Metric"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.stdSibling.metricLabel" defaultMessage="Metric" />}
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
|
@ -150,8 +147,8 @@ const StandardSiblingAggUi = props => {
|
|||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
{ stdDev.sigma }
|
||||
{ stdDev.mode }
|
||||
{stdDev.sigma}
|
||||
{stdDev.mode}
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
|
|
|
@ -37,7 +37,7 @@ export function TemporaryUnsupportedAgg(props) {
|
|||
<FormattedMessage
|
||||
id="tsvb.unsupportedAgg.aggIsTemporaryUnsupportedDescription"
|
||||
defaultMessage="The {modelType} aggregation is currently unsupported."
|
||||
values={{ modelType: (<EuiCode>{props.model.type}</EuiCode>) }}
|
||||
values={{ modelType: <EuiCode>{props.model.type}</EuiCode> }}
|
||||
/>
|
||||
</span>
|
||||
</EuiTitle>
|
||||
|
|
|
@ -113,14 +113,15 @@ const TopHitAggUi = props => {
|
|||
};
|
||||
const model = { ...defaults, ...props.model };
|
||||
const indexPattern =
|
||||
(series.override_index_pattern && series.series_index_pattern) ||
|
||||
panel.index_pattern;
|
||||
(series.override_index_pattern && series.series_index_pattern) || panel.index_pattern;
|
||||
|
||||
const aggWithOptionsRestrictFields = [
|
||||
PANEL_TYPES.TABLE,
|
||||
PANEL_TYPES.METRIC,
|
||||
PANEL_TYPES.MARKDOWN
|
||||
].includes(panel.type) ? [ES_TYPES.NUMBER, ES_TYPES.KEYWORD, ES_TYPES.STRING] : [ES_TYPES.NUMBER];
|
||||
PANEL_TYPES.MARKDOWN,
|
||||
].includes(panel.type)
|
||||
? [ES_TYPES.NUMBER, ES_TYPES.KEYWORD, ES_TYPES.STRING]
|
||||
: [ES_TYPES.NUMBER];
|
||||
|
||||
const handleChange = createChangeHandler(props.onChange, model);
|
||||
const handleSelectChange = createSelectHandler(handleChange);
|
||||
|
@ -152,10 +153,7 @@ const TopHitAggUi = props => {
|
|||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.topHit.aggregationLabel"
|
||||
defaultMessage="Aggregation"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.topHit.aggregationLabel" defaultMessage="Aggregation" />
|
||||
</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
|
@ -168,10 +166,7 @@ const TopHitAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('field')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.topHit.fieldLabel"
|
||||
defaultMessage="Field"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.topHit.fieldLabel" defaultMessage="Field" />}
|
||||
>
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
|
@ -185,16 +180,13 @@ const TopHitAggUi = props => {
|
|||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="m"/>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('size')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.topHit.sizeLabel"
|
||||
defaultMessage="Size"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.topHit.sizeLabel" defaultMessage="Size" />}
|
||||
>
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
|
@ -210,10 +202,12 @@ const TopHitAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('agg_with')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.topHit.aggregateWithLabel"
|
||||
defaultMessage="Aggregate with"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.topHit.aggregateWithLabel"
|
||||
defaultMessage="Aggregate with"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
|
@ -230,10 +224,7 @@ const TopHitAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('order_by')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.topHit.orderByLabel"
|
||||
defaultMessage="Order by"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.topHit.orderByLabel" defaultMessage="Order by" />}
|
||||
>
|
||||
<FieldSelect
|
||||
restrict={ORDER_DATE_RESTRICT_FIELDS}
|
||||
|
@ -247,10 +238,7 @@ const TopHitAggUi = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('order')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.topHit.orderLabel"
|
||||
defaultMessage="Order"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.topHit.orderLabel" defaultMessage="Order" />}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
|
|
|
@ -37,7 +37,7 @@ export function UnsupportedAgg(props) {
|
|||
<FormattedMessage
|
||||
id="tsvb.unsupportedAgg.aggIsNotSupportedDescription"
|
||||
defaultMessage="The {modelType} aggregation is no longer supported."
|
||||
values={{ modelType: (<EuiCode>{props.model.type}</EuiCode>) }}
|
||||
values={{ modelType: <EuiCode>{props.model.type}</EuiCode> }}
|
||||
/>
|
||||
</span>
|
||||
</EuiTitle>
|
||||
|
|
|
@ -27,14 +27,13 @@ import { EuiFlexGroup, EuiFlexItem, EuiFieldText } from '@elastic/eui';
|
|||
import { injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
class CalculationVarsUi extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.renderRow = this.renderRow.bind(this);
|
||||
}
|
||||
|
||||
handleChange(item, name) {
|
||||
return (e) => {
|
||||
return e => {
|
||||
const handleChange = collectionActions.handleChange.bind(null, this.props);
|
||||
const part = {};
|
||||
part[name] = _.get(e, '[0].value', _.get(e, 'target.value'));
|
||||
|
@ -46,14 +45,20 @@ class CalculationVarsUi extends Component {
|
|||
const handleAdd = collectionActions.handleAdd.bind(null, this.props);
|
||||
const handleDelete = collectionActions.handleDelete.bind(null, this.props, row);
|
||||
const { intl } = this.props;
|
||||
return (
|
||||
return (
|
||||
<EuiFlexItem key={row.id} data-test-subj="varRow">
|
||||
<EuiFlexGroup alignItems="center" responsive={false} gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
className="tvbAggs__varName"
|
||||
aria-label={intl.formatMessage({ id: 'tsvb.vars.variableNameAriaLabel', defaultMessage: 'Variable name' })}
|
||||
placeholder={intl.formatMessage({ id: 'tsvb.vars.variableNamePlaceholder', defaultMessage: 'Variable name' })}
|
||||
aria-label={intl.formatMessage({
|
||||
id: 'tsvb.vars.variableNameAriaLabel',
|
||||
defaultMessage: 'Variable name',
|
||||
})}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'tsvb.vars.variableNamePlaceholder',
|
||||
defaultMessage: 'Variable name',
|
||||
})}
|
||||
onChange={this.handleChange(row, 'name')}
|
||||
value={row.name}
|
||||
/>
|
||||
|
@ -82,20 +87,19 @@ class CalculationVarsUi extends Component {
|
|||
|
||||
render() {
|
||||
const { model, name } = this.props;
|
||||
if (!model[name]) return (<div/>);
|
||||
if (!model[name]) return <div />;
|
||||
const rows = model[name].map(this.renderRow);
|
||||
return (
|
||||
<EuiFlexGroup direction="column" gutterSize="s">
|
||||
{ rows }
|
||||
{rows}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CalculationVarsUi.defaultProps = {
|
||||
name: 'variables',
|
||||
includeSiblings: false
|
||||
includeSiblings: false,
|
||||
};
|
||||
|
||||
CalculationVarsUi.propTypes = {
|
||||
|
@ -103,7 +107,7 @@ CalculationVarsUi.propTypes = {
|
|||
model: PropTypes.object,
|
||||
name: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
includeSiblings: PropTypes.bool
|
||||
includeSiblings: PropTypes.bool,
|
||||
};
|
||||
|
||||
export const CalculationVars = injectI18n(CalculationVarsUi);
|
||||
|
|
|
@ -56,7 +56,7 @@ function newAnnotation() {
|
|||
time_field: '@timestamp',
|
||||
icon: 'fa-tag',
|
||||
ignore_global_filters: 1,
|
||||
ignore_panel_filters: 1
|
||||
ignore_panel_filters: 1,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ export class AnnotationsEditor extends Component {
|
|||
}
|
||||
|
||||
handleChange(item, name) {
|
||||
return (e) => {
|
||||
return e => {
|
||||
const handleChange = collectionActions.handleChange.bind(null, this.props);
|
||||
const part = {};
|
||||
part[name] = _.get(e, '[0].value', _.get(e, 'target.value'));
|
||||
|
@ -81,7 +81,7 @@ export class AnnotationsEditor extends Component {
|
|||
const part = { query_string: filter };
|
||||
collectionActions.handleChange(this.props, {
|
||||
...model,
|
||||
...part
|
||||
...part,
|
||||
});
|
||||
};
|
||||
renderRow(row) {
|
||||
|
@ -89,10 +89,10 @@ export class AnnotationsEditor extends Component {
|
|||
fields: '',
|
||||
template: '',
|
||||
index_pattern: '*',
|
||||
query_string: { query: '', language: getDefaultQueryLanguage() }
|
||||
query_string: { query: '', language: getDefaultQueryLanguage() },
|
||||
};
|
||||
const model = { ...defaults, ...row };
|
||||
const handleChange = (part) => {
|
||||
const handleChange = part => {
|
||||
const fn = collectionActions.handleChange.bind(null, this.props);
|
||||
fn(_.assign({}, model, part));
|
||||
};
|
||||
|
@ -102,10 +102,8 @@ export class AnnotationsEditor extends Component {
|
|||
});
|
||||
};
|
||||
const htmlId = htmlIdGenerator(model.id);
|
||||
const handleAdd = collectionActions.handleAdd
|
||||
.bind(null, this.props, newAnnotation);
|
||||
const handleDelete = collectionActions.handleDelete
|
||||
.bind(null, this.props, model);
|
||||
const handleAdd = collectionActions.handleAdd.bind(null, this.props, newAnnotation);
|
||||
const handleDelete = collectionActions.handleDelete.bind(null, this.props, model);
|
||||
return (
|
||||
<div className="tvbAnnotationsEditor" key={model.id}>
|
||||
<EuiFlexGroup responsive={false}>
|
||||
|
@ -123,10 +121,12 @@ export class AnnotationsEditor extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('indexPattern')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.annotationsEditor.indexPatternLabel"
|
||||
defaultMessage="Index pattern (required)"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.annotationsEditor.indexPatternLabel"
|
||||
defaultMessage="Index pattern (required)"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
|
@ -139,10 +139,12 @@ export class AnnotationsEditor extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('timeField')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.annotationsEditor.timeFieldLabel"
|
||||
defaultMessage="Time field (required)"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.annotationsEditor.timeFieldLabel"
|
||||
defaultMessage="Time field (required)"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<FieldSelect
|
||||
|
@ -163,10 +165,12 @@ export class AnnotationsEditor extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('queryString')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.annotationsEditor.queryStringLabel"
|
||||
defaultMessage="Query string"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.annotationsEditor.queryStringLabel"
|
||||
defaultMessage="Query string"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<QueryBarInput
|
||||
|
@ -218,24 +222,25 @@ export class AnnotationsEditor extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('icon')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.annotationsEditor.iconLabel"
|
||||
defaultMessage="Icon (required)"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.annotationsEditor.iconLabel"
|
||||
defaultMessage="Icon (required)"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<IconSelect
|
||||
value={model.icon}
|
||||
onChange={this.handleChange(model, 'icon')}
|
||||
/>
|
||||
<IconSelect value={model.icon} onChange={this.handleChange(model, 'icon')} />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('fields')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.annotationsEditor.fieldsLabel"
|
||||
defaultMessage="Fields (required - comma separated paths)"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.annotationsEditor.fieldsLabel"
|
||||
defaultMessage="Fields (required - comma separated paths)"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
|
@ -248,16 +253,18 @@ export class AnnotationsEditor extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('rowTemplate')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.annotationsEditor.rowTemplateLabel"
|
||||
defaultMessage="Row template (required)"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.annotationsEditor.rowTemplateLabel"
|
||||
defaultMessage="Row template (required)"
|
||||
/>
|
||||
}
|
||||
helpText={
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.annotationsEditor.rowTemplateHelpText"
|
||||
defaultMessage="eg.{rowTemplateExample}"
|
||||
values={{ rowTemplateExample: (<EuiCode>{'{{field}}'}</EuiCode>) }}
|
||||
values={{ rowTemplateExample: <EuiCode>{'{{field}}'}</EuiCode> }}
|
||||
/>
|
||||
</span>
|
||||
}
|
||||
|
@ -290,8 +297,7 @@ export class AnnotationsEditor extends Component {
|
|||
const { model } = this.props;
|
||||
let content;
|
||||
if (!model.annotations || !model.annotations.length) {
|
||||
const handleAdd = collectionActions.handleAdd
|
||||
.bind(null, this.props, newAnnotation);
|
||||
const handleAdd = collectionActions.handleAdd.bind(null, this.props, newAnnotation);
|
||||
content = (
|
||||
<EuiText textAlign="center">
|
||||
<p>
|
||||
|
@ -322,25 +328,21 @@ export class AnnotationsEditor extends Component {
|
|||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
{ annotations }
|
||||
{annotations}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return(
|
||||
<div className="tvbAnnotationsEditor__container">
|
||||
{ content }
|
||||
</div>
|
||||
);
|
||||
return <div className="tvbAnnotationsEditor__container">{content}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
AnnotationsEditor.defaultProps = {
|
||||
name: 'annotations'
|
||||
name: 'annotations',
|
||||
};
|
||||
|
||||
AnnotationsEditor.propTypes = {
|
||||
fields: PropTypes.object,
|
||||
model: PropTypes.object,
|
||||
name: PropTypes.string,
|
||||
onChange: PropTypes.func
|
||||
onChange: PropTypes.func,
|
||||
};
|
||||
|
|
|
@ -22,17 +22,16 @@
|
|||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { EuiIconTip, } from '@elastic/eui';
|
||||
import { EuiIconTip } from '@elastic/eui';
|
||||
import { CustomColorPicker } from './custom_color_picker';
|
||||
import { injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
class ColorPickerUI extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
displayPicker: false,
|
||||
color: {}
|
||||
color: {},
|
||||
};
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
|
@ -68,7 +67,7 @@ class ColorPickerUI extends Component {
|
|||
<button
|
||||
aria-label={this.props.intl.formatMessage({
|
||||
id: 'tsvb.colorPicker.notAccessibleAriaLabel',
|
||||
defaultMessage: 'Color picker, not accessible'
|
||||
defaultMessage: 'Color picker, not accessible',
|
||||
})}
|
||||
className="tvbColorPicker__swatch-empty"
|
||||
onClick={this.handleClick}
|
||||
|
@ -77,11 +76,15 @@ class ColorPickerUI extends Component {
|
|||
}
|
||||
return (
|
||||
<button
|
||||
aria-label={this.props.intl.formatMessage({
|
||||
id: 'tsvb.colorPicker.notAccessibleWithValueAriaLabel',
|
||||
defaultMessage: 'Color picker ({value}), not accessible' }, {
|
||||
value: this.props.value
|
||||
})}
|
||||
aria-label={this.props.intl.formatMessage(
|
||||
{
|
||||
id: 'tsvb.colorPicker.notAccessibleWithValueAriaLabel',
|
||||
defaultMessage: 'Color picker ({value}), not accessible',
|
||||
},
|
||||
{
|
||||
value: this.props.value,
|
||||
}
|
||||
)}
|
||||
style={{ backgroundColor: this.props.value }}
|
||||
className="tvbColorPicker__swatch"
|
||||
onClick={this.handleClick}
|
||||
|
@ -102,7 +105,7 @@ class ColorPickerUI extends Component {
|
|||
color="danger"
|
||||
content={this.props.intl.formatMessage({
|
||||
id: 'tsvb.colorPicker.clearIconLabel',
|
||||
defaultMessage: 'Clear'
|
||||
defaultMessage: 'Clear',
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
|
@ -110,34 +113,24 @@ class ColorPickerUI extends Component {
|
|||
}
|
||||
return (
|
||||
<div className="tvbColorPicker" data-test-subj="tvbColorPicker">
|
||||
{ swatch }
|
||||
{ clear }
|
||||
{
|
||||
this.state.displayPicker
|
||||
? (
|
||||
<div className="tvbColorPicker__popover">
|
||||
<div
|
||||
className="tvbColorPicker__cover"
|
||||
onClick={this.handleClose}
|
||||
/>
|
||||
<CustomColorPicker
|
||||
color={value}
|
||||
onChangeComplete={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
{swatch}
|
||||
{clear}
|
||||
{this.state.displayPicker ? (
|
||||
<div className="tvbColorPicker__popover">
|
||||
<div className="tvbColorPicker__cover" onClick={this.handleClose} />
|
||||
<CustomColorPicker color={value} onChangeComplete={this.handleChange} />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ColorPickerUI.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
disableTrash: PropTypes.bool,
|
||||
onChange: PropTypes.func
|
||||
onChange: PropTypes.func,
|
||||
};
|
||||
|
||||
export const ColorPicker = injectI18n(ColorPickerUI);
|
||||
|
|
|
@ -35,14 +35,13 @@ import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
class ColorRulesUI extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.renderRow = this.renderRow.bind(this);
|
||||
}
|
||||
|
||||
handleChange(item, name, cast = String) {
|
||||
return (e) => {
|
||||
return e => {
|
||||
const handleChange = collectionActions.handleChange.bind(null, this.props);
|
||||
const part = {};
|
||||
part[name] = cast(_.get(e, '[0].value', _.get(e, 'target.value')));
|
||||
|
@ -59,15 +58,36 @@ class ColorRulesUI extends Component {
|
|||
const handleDelete = collectionActions.handleDelete.bind(null, this.props, model);
|
||||
const { intl } = this.props;
|
||||
const operatorOptions = [
|
||||
{ label: intl.formatMessage({ id: 'tsvb.colorRules.greaterThanLabel', defaultMessage: '> greater than' }), value: 'gt' },
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.colorRules.greaterThanOrEqualLabel', defaultMessage: '>= greater than or equal' }),
|
||||
value: 'gte'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.colorRules.greaterThanLabel',
|
||||
defaultMessage: '> greater than',
|
||||
}),
|
||||
value: 'gt',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.colorRules.greaterThanOrEqualLabel',
|
||||
defaultMessage: '>= greater than or equal',
|
||||
}),
|
||||
value: 'gte',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.colorRules.lessThanLabel',
|
||||
defaultMessage: '< less than',
|
||||
}),
|
||||
value: 'lt',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.colorRules.lessThanOrEqualLabel',
|
||||
defaultMessage: '<= less than or equal',
|
||||
}),
|
||||
value: 'lte',
|
||||
},
|
||||
{ label: intl.formatMessage({ id: 'tsvb.colorRules.lessThanLabel', defaultMessage: '< less than' }), value: 'lt' },
|
||||
{ label: intl.formatMessage({ id: 'tsvb.colorRules.lessThanOrEqualLabel', defaultMessage: '<= less than or equal' }), value: 'lte' },
|
||||
];
|
||||
const handleColorChange = (part) => {
|
||||
const handleColorChange = part => {
|
||||
const handleChange = collectionActions.handleChange.bind(null, this.props);
|
||||
handleChange(_.assign({}, model, part));
|
||||
};
|
||||
|
@ -104,7 +124,14 @@ class ColorRulesUI extends Component {
|
|||
);
|
||||
}
|
||||
return (
|
||||
<EuiFlexGroup wrap={true} responsive={false} gutterSize="s" key={model.id} alignItems="center" className="tvbColorRules__rule">
|
||||
<EuiFlexGroup
|
||||
wrap={true}
|
||||
responsive={false}
|
||||
gutterSize="s"
|
||||
key={model.id}
|
||||
alignItems="center"
|
||||
className="tvbColorRules__rule"
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={labelStyle}>
|
||||
<FormattedMessage
|
||||
|
@ -124,7 +151,7 @@ class ColorRulesUI extends Component {
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{ secondary }
|
||||
{secondary}
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('ifMetricIs')}>
|
||||
|
@ -149,7 +176,10 @@ class ColorRulesUI extends Component {
|
|||
|
||||
<EuiFlexItem>
|
||||
<EuiFieldNumber
|
||||
aria-label={intl.formatMessage({ id: 'tsvb.colorRules.valueAriaLabel', defaultMessage: 'Value' })}
|
||||
aria-label={intl.formatMessage({
|
||||
id: 'tsvb.colorRules.valueAriaLabel',
|
||||
defaultMessage: 'Value',
|
||||
})}
|
||||
value={model.value}
|
||||
onChange={this.handleChange(model, 'value', Number)}
|
||||
fullWidth
|
||||
|
@ -170,24 +200,23 @@ class ColorRulesUI extends Component {
|
|||
|
||||
render() {
|
||||
const { model, name } = this.props;
|
||||
if (!model[name]) return (<div/>);
|
||||
if (!model[name]) return <div />;
|
||||
const rows = model[name].map(this.renderRow);
|
||||
return (
|
||||
<div>
|
||||
{ rows }
|
||||
</div>
|
||||
);
|
||||
return <div>{rows}</div>;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ColorRulesUI.defaultProps = {
|
||||
name: 'color_rules',
|
||||
primaryName: i18n.translate('tsvb.colorRules.defaultPrimaryNameLabel', { defaultMessage: 'background' }),
|
||||
primaryName: i18n.translate('tsvb.colorRules.defaultPrimaryNameLabel', {
|
||||
defaultMessage: 'background',
|
||||
}),
|
||||
primaryVarName: 'background_color',
|
||||
secondaryName: i18n.translate('tsvb.colorRules.defaultSecondaryNameLabel', { defaultMessage: 'text' }),
|
||||
secondaryName: i18n.translate('tsvb.colorRules.defaultSecondaryNameLabel', {
|
||||
defaultMessage: 'text',
|
||||
}),
|
||||
secondaryVarName: 'color',
|
||||
hideSecondary: false
|
||||
hideSecondary: false,
|
||||
};
|
||||
|
||||
ColorRulesUI.propTypes = {
|
||||
|
@ -198,7 +227,7 @@ ColorRulesUI.propTypes = {
|
|||
primaryVarName: PropTypes.string,
|
||||
secondaryName: PropTypes.string,
|
||||
secondaryVarName: PropTypes.string,
|
||||
hideSecondary: PropTypes.bool
|
||||
hideSecondary: PropTypes.bool,
|
||||
};
|
||||
|
||||
export const ColorRules = injectI18n(ColorRulesUI);
|
||||
|
|
|
@ -20,7 +20,13 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { ColorWrap as colorWrap, Saturation, Hue, Alpha, Checkboard } from 'react-color/lib/components/common';
|
||||
import {
|
||||
ColorWrap as colorWrap,
|
||||
Saturation,
|
||||
Hue,
|
||||
Alpha,
|
||||
Checkboard,
|
||||
} from 'react-color/lib/components/common';
|
||||
import ChromeFields from 'react-color/lib/components/chrome/ChromeFields';
|
||||
import ChromePointer from 'react-color/lib/components/chrome/ChromePointer';
|
||||
import ChromePointerCircle from 'react-color/lib/components/chrome/ChromePointerCircle';
|
||||
|
@ -47,38 +53,33 @@ class CustomColorPickerUI extends Component {
|
|||
|
||||
const styles = {
|
||||
active: {
|
||||
background: `rgba(${ rgb.r }, ${ rgb.g }, ${ rgb.b }, ${ rgb.a })`,
|
||||
background: `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${rgb.a})`,
|
||||
},
|
||||
Saturation: {
|
||||
radius: '2px 2px 0 0 '
|
||||
radius: '2px 2px 0 0 ',
|
||||
},
|
||||
Hue: {
|
||||
radius: '2px',
|
||||
},
|
||||
Alpha: {
|
||||
radius: '2px',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const handleSwatchChange = (data) => {
|
||||
const handleSwatchChange = data => {
|
||||
if (data.hex) {
|
||||
color.isValidHex(data.hex) && this.props.onChange({
|
||||
hex: data.hex,
|
||||
source: 'hex',
|
||||
});
|
||||
color.isValidHex(data.hex) &&
|
||||
this.props.onChange({
|
||||
hex: data.hex,
|
||||
source: 'hex',
|
||||
});
|
||||
} else {
|
||||
this.props.onChange(data);
|
||||
}
|
||||
};
|
||||
|
||||
const swatches = this.props.colors.map((c) => {
|
||||
return (
|
||||
<CompactColor
|
||||
key={c}
|
||||
color={c}
|
||||
onClick={handleSwatchChange}
|
||||
/>
|
||||
);
|
||||
const swatches = this.props.colors.map(c => {
|
||||
return <CompactColor key={c} color={c} onClick={handleSwatchChange} />;
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -93,14 +94,32 @@ class CustomColorPickerUI extends Component {
|
|||
</div>
|
||||
<div className="tvbColorPickerPopUp__body">
|
||||
<div className="tvbColorPickerPopUp__controls">
|
||||
<div className={this.props.disableAlpha ? 'tvbColorPickerPopUp__color-disableAlpha' : 'tvbColorPickerPopUp__color'}>
|
||||
<div className={this.props.disableAlpha ? 'tvbColorPickerPopUp__swatch-disableAlpha' : 'tvbColorPickerPopUp__swatch'}>
|
||||
<div
|
||||
className={
|
||||
this.props.disableAlpha
|
||||
? 'tvbColorPickerPopUp__color-disableAlpha'
|
||||
: 'tvbColorPickerPopUp__color'
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
this.props.disableAlpha
|
||||
? 'tvbColorPickerPopUp__swatch-disableAlpha'
|
||||
: 'tvbColorPickerPopUp__swatch'
|
||||
}
|
||||
>
|
||||
<div className="tvbColorPickerPopUp__active" />
|
||||
<Checkboard />
|
||||
</div>
|
||||
</div>
|
||||
<div className="tvbColorPickerPopUp__toggles">
|
||||
<div className={this.props.disableAlpha ? 'tvbColorPickerPopUp__hue-disableAlpha' : 'tvbColorPickerPopUp__hue'}>
|
||||
<div
|
||||
className={
|
||||
this.props.disableAlpha
|
||||
? 'tvbColorPickerPopUp__hue-disableAlpha'
|
||||
: 'tvbColorPickerPopUp__hue'
|
||||
}
|
||||
>
|
||||
<Hue
|
||||
style={styles.Hue}
|
||||
{...this.props}
|
||||
|
@ -108,7 +127,13 @@ class CustomColorPickerUI extends Component {
|
|||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
<div className={this.props.disableAlpha ? 'tvbColorPickerPopUp__alpha-disableAlpha' : 'tvbColorPickerPopUp__alpha'}>
|
||||
<div
|
||||
className={
|
||||
this.props.disableAlpha
|
||||
? 'tvbColorPickerPopUp__alpha-disableAlpha'
|
||||
: 'tvbColorPickerPopUp__alpha'
|
||||
}
|
||||
>
|
||||
<Alpha
|
||||
style={styles.Alpha}
|
||||
{...this.props}
|
||||
|
@ -123,9 +148,7 @@ class CustomColorPickerUI extends Component {
|
|||
onChange={this.handleChange}
|
||||
disableAlpha={this.props.disableAlpha}
|
||||
/>
|
||||
<div className="tvbColorPickerPopUp__swatches">
|
||||
{swatches}
|
||||
</div>
|
||||
<div className="tvbColorPickerPopUp__swatches">{swatches}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -134,19 +157,49 @@ class CustomColorPickerUI extends Component {
|
|||
|
||||
CustomColorPickerUI.defaultProps = {
|
||||
colors: [
|
||||
'#4D4D4D', '#999999', '#FFFFFF', '#F44E3B', '#FE9200', '#FCDC00',
|
||||
'#DBDF00', '#A4DD00', '#68CCCA', '#73D8FF', '#AEA1FF', '#FDA1FF',
|
||||
'#333333', '#808080', '#cccccc', '#D33115', '#E27300', '#FCC400',
|
||||
'#B0BC00', '#68BC00', '#16A5A5', '#009CE0', '#7B64FF', '#FA28FF',
|
||||
'#0F1419', '#666666', '#B3B3B3', '#9F0500', '#C45100', '#FB9E00',
|
||||
'#808900', '#194D33', '#0C797D', '#0062B1', '#653294', '#AB149E',
|
||||
'#4D4D4D',
|
||||
'#999999',
|
||||
'#FFFFFF',
|
||||
'#F44E3B',
|
||||
'#FE9200',
|
||||
'#FCDC00',
|
||||
'#DBDF00',
|
||||
'#A4DD00',
|
||||
'#68CCCA',
|
||||
'#73D8FF',
|
||||
'#AEA1FF',
|
||||
'#FDA1FF',
|
||||
'#333333',
|
||||
'#808080',
|
||||
'#cccccc',
|
||||
'#D33115',
|
||||
'#E27300',
|
||||
'#FCC400',
|
||||
'#B0BC00',
|
||||
'#68BC00',
|
||||
'#16A5A5',
|
||||
'#009CE0',
|
||||
'#7B64FF',
|
||||
'#FA28FF',
|
||||
'#0F1419',
|
||||
'#666666',
|
||||
'#B3B3B3',
|
||||
'#9F0500',
|
||||
'#C45100',
|
||||
'#FB9E00',
|
||||
'#808900',
|
||||
'#194D33',
|
||||
'#0C797D',
|
||||
'#0062B1',
|
||||
'#653294',
|
||||
'#AB149E',
|
||||
],
|
||||
};
|
||||
|
||||
CustomColorPickerUI.propTypes = {
|
||||
color: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
onChangeComplete: PropTypes.func,
|
||||
onChange: PropTypes.func
|
||||
onChange: PropTypes.func,
|
||||
};
|
||||
|
||||
export const CustomColorPicker = colorWrap(CustomColorPickerUI);
|
||||
|
|
|
@ -21,7 +21,13 @@ import PropTypes from 'prop-types';
|
|||
import React, { Component } from 'react';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
htmlIdGenerator, EuiComboBox, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiFieldText, EuiLink,
|
||||
htmlIdGenerator,
|
||||
EuiComboBox,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiFieldText,
|
||||
EuiLink,
|
||||
} from '@elastic/eui';
|
||||
import { durationOutputOptions, durationInputOptions, isDuration } from './lib/durations';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -30,7 +36,6 @@ import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
|||
const DEFAULT_OUTPUT_PRECISION = '2';
|
||||
|
||||
class DataFormatPickerUI extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
@ -50,7 +55,7 @@ class DataFormatPickerUI extends Component {
|
|||
}
|
||||
|
||||
handleCustomChange = () => {
|
||||
this.props.onChange([{ value: this.custom && this.custom.value || '' }]);
|
||||
this.props.onChange([{ value: (this.custom && this.custom.value) || '' }]);
|
||||
};
|
||||
|
||||
handleChange = selectedOptions => {
|
||||
|
@ -62,16 +67,18 @@ class DataFormatPickerUI extends Component {
|
|||
this.handleCustomChange();
|
||||
} else if (selectedOptions[0].value === 'duration') {
|
||||
const { from, to, decimals } = this.state;
|
||||
this.props.onChange([{
|
||||
value: `${from},${to},${decimals}`,
|
||||
}]);
|
||||
this.props.onChange([
|
||||
{
|
||||
value: `${from},${to},${decimals}`,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
this.props.onChange(selectedOptions);
|
||||
}
|
||||
};
|
||||
|
||||
handleDurationChange(name) {
|
||||
return (selectedOptions) => {
|
||||
return selectedOptions => {
|
||||
if (selectedOptions.length < 1) {
|
||||
return;
|
||||
}
|
||||
|
@ -83,14 +90,19 @@ class DataFormatPickerUI extends Component {
|
|||
newValue = selectedOptions[0].value;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
[name]: newValue,
|
||||
}, () => {
|
||||
const { from, to, decimals } = this.state;
|
||||
this.props.onChange([{
|
||||
value: `${from},${to},${decimals}`,
|
||||
}]);
|
||||
});
|
||||
this.setState(
|
||||
{
|
||||
[name]: newValue,
|
||||
},
|
||||
() => {
|
||||
const { from, to, decimals } = this.state;
|
||||
this.props.onChange([
|
||||
{
|
||||
value: `${from},${to},${decimals}`,
|
||||
},
|
||||
]);
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -107,23 +119,38 @@ class DataFormatPickerUI extends Component {
|
|||
const { intl } = this.props;
|
||||
const options = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.dataFormatPicker.bytesLabel', defaultMessage: 'Bytes' }),
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.dataFormatPicker.bytesLabel',
|
||||
defaultMessage: 'Bytes',
|
||||
}),
|
||||
value: 'bytes',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.dataFormatPicker.numberLabel', defaultMessage: 'Number' }),
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.dataFormatPicker.numberLabel',
|
||||
defaultMessage: 'Number',
|
||||
}),
|
||||
value: 'number',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.dataFormatPicker.percentLabel', defaultMessage: 'Percent' }),
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.dataFormatPicker.percentLabel',
|
||||
defaultMessage: 'Percent',
|
||||
}),
|
||||
value: 'percent',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.dataFormatPicker.durationLabel', defaultMessage: 'Duration' }),
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.dataFormatPicker.durationLabel',
|
||||
defaultMessage: 'Duration',
|
||||
}),
|
||||
value: 'duration',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.dataFormatPicker.customLabel', defaultMessage: 'Custom' }),
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.dataFormatPicker.customLabel',
|
||||
defaultMessage: 'Custom',
|
||||
}),
|
||||
value: 'custom',
|
||||
},
|
||||
];
|
||||
|
@ -153,10 +180,9 @@ class DataFormatPickerUI extends Component {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('from')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.dataFormatPicker.fromLabel"
|
||||
defaultMessage="From"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.dataFormatPicker.fromLabel" defaultMessage="From" />
|
||||
}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
|
@ -170,10 +196,7 @@ class DataFormatPickerUI extends Component {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('to')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.dataFormatPicker.toLabel"
|
||||
defaultMessage="To"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.dataFormatPicker.toLabel" defaultMessage="To" />}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
|
@ -189,21 +212,22 @@ class DataFormatPickerUI extends Component {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('decimal')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.dataFormatPicker.decimalPlacesLabel"
|
||||
defaultMessage="Decimal places"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.dataFormatPicker.decimalPlacesLabel"
|
||||
defaultMessage="Decimal places"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
defaultValue={decimals}
|
||||
inputRef={(el) => this.decimals = el}
|
||||
inputRef={el => (this.decimals = el)}
|
||||
placeholder={DEFAULT_OUTPUT_PRECISION}
|
||||
onChange={this.handleDurationChange('decimals')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>)
|
||||
}
|
||||
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
@ -211,17 +235,23 @@ class DataFormatPickerUI extends Component {
|
|||
custom = (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.dataFormatPicker.formatStringLabel"
|
||||
defaultMessage="Format string"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.dataFormatPicker.formatStringLabel"
|
||||
defaultMessage="Format string"
|
||||
/>
|
||||
}
|
||||
helpText={
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.dataFormatPicker.formatStringHelpText"
|
||||
defaultMessage="See {numeralJsLink}"
|
||||
values={{
|
||||
numeralJsLink: (<EuiLink href="http://numeraljs.com/#format" target="_BLANK">Numeral.js</EuiLink>),
|
||||
numeralJsLink: (
|
||||
<EuiLink href="http://numeraljs.com/#format" target="_BLANK">
|
||||
Numeral.js
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
|
@ -229,7 +259,7 @@ class DataFormatPickerUI extends Component {
|
|||
>
|
||||
<EuiFieldText
|
||||
defaultValue={value}
|
||||
inputRef={(el) => this.custom = el}
|
||||
inputRef={el => (this.custom = el)}
|
||||
onChange={this.handleCustomChange}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
|
|
@ -50,11 +50,7 @@ export function ErrorComponent(props) {
|
|||
</div>
|
||||
);
|
||||
} else if (reason) {
|
||||
additionalInfo = (
|
||||
<div className="tvbError__additional">
|
||||
{reason}
|
||||
</div>
|
||||
);
|
||||
additionalInfo = <div className="tvbError__additional">{reason}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -64,11 +60,12 @@ export function ErrorComponent(props) {
|
|||
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
{title ||
|
||||
<FormattedMessage
|
||||
id="tsvb.error.requestForPanelFailedErrorMessage"
|
||||
defaultMessage="The request for this panel failed"
|
||||
/>}
|
||||
{title || (
|
||||
<FormattedMessage
|
||||
id="tsvb.error.requestForPanelFailedErrorMessage"
|
||||
defaultMessage="The request for this panel failed"
|
||||
/>
|
||||
)}
|
||||
|
||||
{additionalInfo}
|
||||
</EuiText>
|
||||
|
@ -77,5 +74,5 @@ export function ErrorComponent(props) {
|
|||
}
|
||||
|
||||
ErrorComponent.propTypes = {
|
||||
error: PropTypes.object
|
||||
error: PropTypes.object,
|
||||
};
|
||||
|
|
|
@ -19,9 +19,7 @@
|
|||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiComboBox,
|
||||
} from '@elastic/eui';
|
||||
import { EuiComboBox } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
function renderOption(option) {
|
||||
|
@ -54,33 +52,76 @@ export function IconSelect(props) {
|
|||
|
||||
IconSelect.defaultProps = {
|
||||
icons: [
|
||||
{ value: 'fa-asterisk', label: i18n.translate('tsvb.iconSelect.asteriskLabel', { defaultMessage: 'Asterisk' }) },
|
||||
{ value: 'fa-bell', label: i18n.translate('tsvb.iconSelect.bellLabel', { defaultMessage: 'Bell' }) },
|
||||
{ value: 'fa-bolt', label: i18n.translate('tsvb.iconSelect.boltLabel', { defaultMessage: 'Bolt' }) },
|
||||
{ value: 'fa-bomb', label: i18n.translate('tsvb.iconSelect.bombLabel', { defaultMessage: 'Bomb' }) },
|
||||
{ value: 'fa-bug', label: i18n.translate('tsvb.iconSelect.bugLabel', { defaultMessage: 'Bug' }) },
|
||||
{ value: 'fa-comment', label: i18n.translate('tsvb.iconSelect.commentLabel', { defaultMessage: 'Comment' }) },
|
||||
{
|
||||
value: 'fa-asterisk',
|
||||
label: i18n.translate('tsvb.iconSelect.asteriskLabel', { defaultMessage: 'Asterisk' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-bell',
|
||||
label: i18n.translate('tsvb.iconSelect.bellLabel', { defaultMessage: 'Bell' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-bolt',
|
||||
label: i18n.translate('tsvb.iconSelect.boltLabel', { defaultMessage: 'Bolt' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-bomb',
|
||||
label: i18n.translate('tsvb.iconSelect.bombLabel', { defaultMessage: 'Bomb' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-bug',
|
||||
label: i18n.translate('tsvb.iconSelect.bugLabel', { defaultMessage: 'Bug' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-comment',
|
||||
label: i18n.translate('tsvb.iconSelect.commentLabel', { defaultMessage: 'Comment' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-exclamation-circle',
|
||||
label: i18n.translate('tsvb.iconSelect.exclamationCircleLabel', { defaultMessage: 'Exclamation Circle' })
|
||||
label: i18n.translate('tsvb.iconSelect.exclamationCircleLabel', {
|
||||
defaultMessage: 'Exclamation Circle',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'fa-exclamation-triangle',
|
||||
label: i18n.translate('tsvb.iconSelect.exclamationTriangleLabel', { defaultMessage: 'Exclamation Triangle' })
|
||||
label: i18n.translate('tsvb.iconSelect.exclamationTriangleLabel', {
|
||||
defaultMessage: 'Exclamation Triangle',
|
||||
}),
|
||||
},
|
||||
{ value: 'fa-fire', label: i18n.translate('tsvb.iconSelect.fireLabel', { defaultMessage: 'Fire' }) },
|
||||
{ value: 'fa-flag', label: i18n.translate('tsvb.iconSelect.flagLabel', { defaultMessage: 'Flag' }) },
|
||||
{ value: 'fa-heart', label: i18n.translate('tsvb.iconSelect.heartLabel', { defaultMessage: 'Heart' }) },
|
||||
{ value: 'fa-map-marker', label: i18n.translate('tsvb.iconSelect.mapMarkerLabel', { defaultMessage: 'Map Marker' }) },
|
||||
{ value: 'fa-map-pin', label: i18n.translate('tsvb.iconSelect.mapPinLabel', { defaultMessage: 'Map Pin' }) },
|
||||
{ value: 'fa-star', label: i18n.translate('tsvb.iconSelect.starLabel', { defaultMessage: 'Star' }) },
|
||||
{ value: 'fa-tag', label: i18n.translate('tsvb.iconSelect.tagLabel', { defaultMessage: 'Tag' }) },
|
||||
]
|
||||
{
|
||||
value: 'fa-fire',
|
||||
label: i18n.translate('tsvb.iconSelect.fireLabel', { defaultMessage: 'Fire' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-flag',
|
||||
label: i18n.translate('tsvb.iconSelect.flagLabel', { defaultMessage: 'Flag' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-heart',
|
||||
label: i18n.translate('tsvb.iconSelect.heartLabel', { defaultMessage: 'Heart' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-map-marker',
|
||||
label: i18n.translate('tsvb.iconSelect.mapMarkerLabel', { defaultMessage: 'Map Marker' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-map-pin',
|
||||
label: i18n.translate('tsvb.iconSelect.mapPinLabel', { defaultMessage: 'Map Pin' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-star',
|
||||
label: i18n.translate('tsvb.iconSelect.starLabel', { defaultMessage: 'Star' }),
|
||||
},
|
||||
{
|
||||
value: 'fa-tag',
|
||||
label: i18n.translate('tsvb.iconSelect.tagLabel', { defaultMessage: 'Tag' }),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
IconSelect.propTypes = {
|
||||
icons: PropTypes.array,
|
||||
id: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
value: PropTypes.string.isRequired
|
||||
value: PropTypes.string.isRequired,
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ export const IndexPattern = props => {
|
|||
default_index_pattern: '',
|
||||
[indexPatternName]: '*',
|
||||
[intervalName]: 'auto',
|
||||
[dropBucketName]: 1
|
||||
[dropBucketName]: 1,
|
||||
};
|
||||
|
||||
const htmlId = htmlIdGenerator();
|
||||
|
@ -63,14 +63,15 @@ export const IndexPattern = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('indexPattern')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.indexPatternLabel"
|
||||
defaultMessage="Index pattern"
|
||||
/>)}
|
||||
helpText={isDefaultIndexPatternUsed && <FormattedMessage
|
||||
id="tsvb.indexPattern.searchByDefaultIndex"
|
||||
defaultMessage="Default index pattern is used. To query all indexes use *"
|
||||
/>}
|
||||
label={<FormattedMessage id="tsvb.indexPatternLabel" defaultMessage="Index pattern" />}
|
||||
helpText={
|
||||
isDefaultIndexPatternUsed && (
|
||||
<FormattedMessage
|
||||
id="tsvb.indexPattern.searchByDefaultIndex"
|
||||
defaultMessage="Default index pattern is used. To query all indexes use *"
|
||||
/>
|
||||
)
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
|
@ -86,10 +87,9 @@ export const IndexPattern = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('timeField')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.indexPattern.timeFieldLabel"
|
||||
defaultMessage="Time field"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.indexPattern.timeFieldLabel" defaultMessage="Time field" />
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<FieldSelect
|
||||
|
@ -108,15 +108,16 @@ export const IndexPattern = props => {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('interval')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.indexPattern.intervalLabel"
|
||||
defaultMessage="Interval"
|
||||
/>)}
|
||||
helpText={(<FormattedMessage
|
||||
id="tsvb.indexPattern.intervalHelpText"
|
||||
defaultMessage="Examples: auto, 1m, 1d, 7d, 1y, >=1m"
|
||||
description="auto, 1m, 1d, 7d, 1y, >=1m are required values and must not be translated."
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.indexPattern.intervalLabel" defaultMessage="Interval" />
|
||||
}
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id="tsvb.indexPattern.intervalHelpText"
|
||||
defaultMessage="Examples: auto, 1m, 1d, 7d, 1y, >=1m"
|
||||
description="auto, 1m, 1d, 7d, 1y, >=1m are required values and must not be translated."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
disabled={props.disabled}
|
||||
|
@ -134,11 +135,7 @@ export const IndexPattern = props => {
|
|||
/>
|
||||
</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model[dropBucketName]}
|
||||
name={dropBucketName}
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
<YesNo value={model[dropBucketName]} name={dropBucketName} onChange={props.onChange} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
|
@ -156,5 +153,5 @@ IndexPattern.propTypes = {
|
|||
onChange: PropTypes.func.isRequired,
|
||||
prefix: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
className: PropTypes.string
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
|
|
@ -27,12 +27,12 @@ describe('calculateSiblings(metrics, metric)', () => {
|
|||
{ id: 2, type: 'derivative', field: 1 },
|
||||
{ id: 3, type: 'derivative', field: 2 },
|
||||
{ id: 4, type: 'moving_average', field: 2 },
|
||||
{ id: 5, type: 'count' }
|
||||
{ id: 5, type: 'count' },
|
||||
];
|
||||
const siblings = calculateSiblings(metrics, { id: 2 });
|
||||
expect(siblings).to.eql([
|
||||
{ id: 1, type: 'max', field: 'network.bytes' },
|
||||
{ id: 5, type: 'count' }
|
||||
{ id: 5, type: 'count' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -19,25 +19,20 @@
|
|||
|
||||
import sinon from 'sinon';
|
||||
import { expect } from 'chai';
|
||||
import {
|
||||
handleChange,
|
||||
handleAdd,
|
||||
handleDelete
|
||||
} from '../collection_actions';
|
||||
import { handleChange, handleAdd, handleDelete } from '../collection_actions';
|
||||
|
||||
describe('collection actions', () => {
|
||||
|
||||
it('handleChange() calls props.onChange() with updated collection', () => {
|
||||
const fn = sinon.spy();
|
||||
const props = {
|
||||
model: { test: [{ id: 1, title: 'foo' }] },
|
||||
name: 'test',
|
||||
onChange: fn
|
||||
onChange: fn,
|
||||
};
|
||||
handleChange.call(null, props, { id: 1, title: 'bar' });
|
||||
expect(fn.calledOnce).to.equal(true);
|
||||
expect(fn.firstCall.args[0]).to.eql({
|
||||
test: [{ id: 1, title: 'bar' }]
|
||||
test: [{ id: 1, title: 'bar' }],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -47,13 +42,13 @@ describe('collection actions', () => {
|
|||
const props = {
|
||||
model: { test: [{ id: 1, title: 'foo' }] },
|
||||
name: 'test',
|
||||
onChange: fn
|
||||
onChange: fn,
|
||||
};
|
||||
handleAdd.call(null, props, newItemFn);
|
||||
expect(fn.calledOnce).to.equal(true);
|
||||
expect(newItemFn.calledOnce).to.equal(true);
|
||||
expect(fn.firstCall.args[0]).to.eql({
|
||||
test: [{ id: 1, title: 'foo' }, { id: 2, title: 'example' }]
|
||||
test: [{ id: 1, title: 'foo' }, { id: 2, title: 'example' }],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -62,16 +57,12 @@ describe('collection actions', () => {
|
|||
const props = {
|
||||
model: { test: [{ id: 1, title: 'foo' }] },
|
||||
name: 'test',
|
||||
onChange: fn
|
||||
onChange: fn,
|
||||
};
|
||||
handleDelete.call(null, props, { id: 1 });
|
||||
expect(fn.calledOnce).to.equal(true);
|
||||
expect(fn.firstCall.args[0]).to.eql({
|
||||
test: []
|
||||
test: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
|
|
@ -18,7 +18,5 @@
|
|||
*/
|
||||
|
||||
describe('convertSeriesToVars(series, model)', () => {
|
||||
it('returns and object', () => {
|
||||
|
||||
});
|
||||
it('returns and object', () => {});
|
||||
});
|
||||
|
|
|
@ -22,7 +22,6 @@ import { expect } from 'chai';
|
|||
import { createNumberHandler } from '../create_number_handler';
|
||||
|
||||
describe('createNumberHandler()', () => {
|
||||
|
||||
let handleChange;
|
||||
let changeHandler;
|
||||
let event;
|
||||
|
@ -39,8 +38,7 @@ describe('createNumberHandler()', () => {
|
|||
expect(event.preventDefault.calledOnce).to.equal(true);
|
||||
expect(handleChange.calledOnce).to.equal(true);
|
||||
expect(handleChange.firstCall.args[0]).to.eql({
|
||||
test: 1
|
||||
test: 1,
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -35,8 +35,7 @@ describe('createSelectHandler()', () => {
|
|||
it('calls handleChange() function with partial', () => {
|
||||
expect(handleChange.calledOnce).to.equal(true);
|
||||
expect(handleChange.firstCall.args[0]).to.eql({
|
||||
test: 'foo'
|
||||
test: 'foo',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import { expect } from 'chai';
|
|||
import { createTextHandler } from '../create_text_handler';
|
||||
|
||||
describe('createTextHandler()', () => {
|
||||
|
||||
let handleChange;
|
||||
let changeHandler;
|
||||
let event;
|
||||
|
@ -39,9 +38,7 @@ describe('createTextHandler()', () => {
|
|||
expect(event.preventDefault.calledOnce).to.equal(true);
|
||||
expect(handleChange.calledOnce).to.equal(true);
|
||||
expect(handleChange.firstCall.args[0]).to.eql({
|
||||
test: 'foo'
|
||||
test: 'foo',
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -31,5 +31,3 @@ describe('getAxisLabelString(interval)', () => {
|
|||
expect(getAxisLabelString(7200000)).to.equal('per 2 hours');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -22,14 +22,10 @@ import { expect } from 'chai';
|
|||
import { reIdSeries } from '../re_id_series';
|
||||
|
||||
describe('reIdSeries()', () => {
|
||||
|
||||
it('reassign ids for series with just basic metrics', () => {
|
||||
const series = {
|
||||
id: uuid.v1(),
|
||||
metrics: [
|
||||
{ id: uuid.v1() },
|
||||
{ id: uuid.v1() }
|
||||
]
|
||||
metrics: [{ id: uuid.v1() }, { id: uuid.v1() }],
|
||||
};
|
||||
const newSeries = reIdSeries(series);
|
||||
expect(newSeries).to.not.equal(series);
|
||||
|
@ -43,11 +39,8 @@ describe('reIdSeries()', () => {
|
|||
const firstMetricId = uuid.v1();
|
||||
const series = {
|
||||
id: uuid.v1(),
|
||||
metrics: [
|
||||
{ id: firstMetricId },
|
||||
{ id: uuid.v1() }
|
||||
],
|
||||
terms_order_by: firstMetricId
|
||||
metrics: [{ id: firstMetricId }, { id: uuid.v1() }],
|
||||
terms_order_by: firstMetricId,
|
||||
};
|
||||
const newSeries = reIdSeries(series);
|
||||
expect(newSeries).to.not.equal(series);
|
||||
|
@ -62,10 +55,7 @@ describe('reIdSeries()', () => {
|
|||
const firstMetricId = uuid.v1();
|
||||
const series = {
|
||||
id: uuid.v1(),
|
||||
metrics: [
|
||||
{ id: firstMetricId },
|
||||
{ id: uuid.v1(), field: firstMetricId }
|
||||
]
|
||||
metrics: [{ id: firstMetricId }, { id: uuid.v1(), field: firstMetricId }],
|
||||
};
|
||||
const newSeries = reIdSeries(series);
|
||||
expect(newSeries).to.not.equal(series);
|
||||
|
@ -82,16 +72,13 @@ describe('reIdSeries()', () => {
|
|||
{
|
||||
id: uuid.v1(),
|
||||
type: 'calculation',
|
||||
variables: [{ id: uuid.v1(), field: firstMetricId }]
|
||||
}
|
||||
]
|
||||
variables: [{ id: uuid.v1(), field: firstMetricId }],
|
||||
},
|
||||
],
|
||||
};
|
||||
const newSeries = reIdSeries(series);
|
||||
expect(newSeries).to.not.equal(series);
|
||||
expect(newSeries.id).to.not.equal(series.id);
|
||||
expect(newSeries.metrics[1].variables[0].field).to.equal(newSeries.metrics[0].id);
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
|
|
@ -21,7 +21,6 @@ import { expect } from 'chai';
|
|||
import { tickFormatter } from '../tick_formatter';
|
||||
|
||||
describe('tickFormatter(format, template)', () => {
|
||||
|
||||
it('returns a number with two decimal place by default', () => {
|
||||
const fn = tickFormatter();
|
||||
expect(fn(1.5556)).to.equal('1.56');
|
||||
|
@ -29,17 +28,17 @@ describe('tickFormatter(format, template)', () => {
|
|||
|
||||
it('returns a percent with percent formatter', () => {
|
||||
const config = {
|
||||
'format:percent:defaultPattern': '0.[00]%'
|
||||
'format:percent:defaultPattern': '0.[00]%',
|
||||
};
|
||||
const fn = tickFormatter('percent', null, (key) => config[key]);
|
||||
const fn = tickFormatter('percent', null, key => config[key]);
|
||||
expect(fn(0.5556)).to.equal('55.56%');
|
||||
});
|
||||
|
||||
it('returns a byte formatted string with byte formatter', () => {
|
||||
const config = {
|
||||
'format:bytes:defaultPattern': '0.0b'
|
||||
'format:bytes:defaultPattern': '0.0b',
|
||||
};
|
||||
const fn = tickFormatter('bytes', null, (key) => config[key]);
|
||||
const fn = tickFormatter('bytes', null, key => config[key]);
|
||||
expect(fn(1500 ^ 10)).to.equal('1.5KB');
|
||||
});
|
||||
|
||||
|
@ -50,9 +49,9 @@ describe('tickFormatter(format, template)', () => {
|
|||
|
||||
it('returns a located string with custom locale setting', () => {
|
||||
const config = {
|
||||
'format:number:defaultLocale': 'fr'
|
||||
'format:number:defaultLocale': 'fr',
|
||||
};
|
||||
const fn = tickFormatter('0,0.0', null, (key) => config[key]);
|
||||
const fn = tickFormatter('0,0.0', null, key => config[key]);
|
||||
expect(fn(1500)).to.equal('1 500,0');
|
||||
});
|
||||
|
||||
|
@ -68,9 +67,9 @@ describe('tickFormatter(format, template)', () => {
|
|||
|
||||
it('returns formatted value if passed a bad template', () => {
|
||||
const config = {
|
||||
'format:number:defaultPattern': '0,0.[00]'
|
||||
'format:number:defaultPattern': '0,0.[00]',
|
||||
};
|
||||
const fn = tickFormatter('number', '{{value', (key) => config[key]);
|
||||
const fn = tickFormatter('number', '{{value', key => config[key]);
|
||||
expect(fn(1.5556)).to.equal('1.56');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
import _ from 'lodash';
|
||||
|
||||
function getAncestors(siblings, item) {
|
||||
const ancestors = item.id && [item.id] || [];
|
||||
siblings.forEach((sib) => {
|
||||
const ancestors = (item.id && [item.id]) || [];
|
||||
siblings.forEach(sib => {
|
||||
if (_.includes(ancestors, sib.field)) {
|
||||
ancestors.push(sib.id);
|
||||
}
|
||||
|
@ -33,4 +33,3 @@ export const calculateSiblings = (siblings, model) => {
|
|||
const ancestors = getAncestors(siblings, model);
|
||||
return siblings.filter(row => !_.includes(ancestors, row.id));
|
||||
};
|
||||
|
||||
|
|
|
@ -28,30 +28,32 @@ export const convertSeriesToVars = (series, model, dateFormat = 'lll', getConfig
|
|||
series
|
||||
.filter(row => _.startsWith(row.id, seriesModel.id))
|
||||
.forEach(row => {
|
||||
const varName = [
|
||||
_.snakeCase(row.label),
|
||||
_.snakeCase(seriesModel.var_name)
|
||||
].filter(v => v).join('.');
|
||||
const varName = [_.snakeCase(row.label), _.snakeCase(seriesModel.var_name)]
|
||||
.filter(v => v)
|
||||
.join('.');
|
||||
|
||||
const formatter = tickFormatter(seriesModel.formatter, seriesModel.value_template, getConfig);
|
||||
const formatter = tickFormatter(
|
||||
seriesModel.formatter,
|
||||
seriesModel.value_template,
|
||||
getConfig
|
||||
);
|
||||
const lastValue = getLastValue(row.data);
|
||||
|
||||
const data = {
|
||||
last: {
|
||||
raw: lastValue,
|
||||
formatted: formatter(lastValue)
|
||||
formatted: formatter(lastValue),
|
||||
},
|
||||
data: {
|
||||
raw: row.data,
|
||||
formatted: row.data.map(point => {
|
||||
return [moment(point[0]).format(dateFormat), formatter(point[1])];
|
||||
})
|
||||
}
|
||||
}),
|
||||
},
|
||||
};
|
||||
_.set(variables, varName, data);
|
||||
_.set(variables, `${_.snakeCase(row.label)}.label`, row.label);
|
||||
});
|
||||
});
|
||||
return variables;
|
||||
|
||||
};
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
import _ from 'lodash';
|
||||
import { detectIE } from './detect_ie';
|
||||
|
||||
export const createNumberHandler = (handleChange) => {
|
||||
return (name, defaultValue) => (e) => {
|
||||
export const createNumberHandler = handleChange => {
|
||||
return (name, defaultValue) => e => {
|
||||
if (!detectIE() || e.keyCode === 13) e.preventDefault();
|
||||
|
||||
const value = Number(_.get(e, 'target.value', defaultValue));
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
|
||||
export const createSelectHandler = (handleChange) => {
|
||||
return (name) => (selectedOptions) => {
|
||||
export const createSelectHandler = handleChange => {
|
||||
return name => selectedOptions => {
|
||||
if (_.isFunction(handleChange)) {
|
||||
return handleChange({
|
||||
[name]: _.get(selectedOptions, '[0].value', null)
|
||||
[name]: _.get(selectedOptions, '[0].value', null),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
import _ from 'lodash';
|
||||
import { detectIE } from './detect_ie';
|
||||
|
||||
export const createTextHandler = (handleChange) => {
|
||||
return (name, defaultValue) => (e) => {
|
||||
export const createTextHandler = handleChange => {
|
||||
return (name, defaultValue) => e => {
|
||||
// IE preventDefault breaks input, but we still need top prevent enter from being pressed
|
||||
if (!detectIE() || e.keyCode === 13) e.preventDefault();
|
||||
|
||||
|
|
|
@ -33,4 +33,3 @@ export function createXaxisFormatter(interval, rules, dateFormat) {
|
|||
return moment(val).format(getFormat(interval, rules, dateFormat));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@ import { i18n } from '@kbn/i18n';
|
|||
|
||||
const durationBaseOptions = [
|
||||
{
|
||||
label: i18n.translate('tsvb.durationOptions.millisecondsLabel', { defaultMessage: 'Milliseconds' }),
|
||||
label: i18n.translate('tsvb.durationOptions.millisecondsLabel', {
|
||||
defaultMessage: 'Milliseconds',
|
||||
}),
|
||||
value: 'ms',
|
||||
},
|
||||
{
|
||||
|
@ -64,44 +66,50 @@ export const durationOutputOptions = [
|
|||
|
||||
export const durationInputOptions = [
|
||||
{
|
||||
label: i18n.translate('tsvb.durationOptions.picosecondsLabel', { defaultMessage: 'Picoseconds' }),
|
||||
label: i18n.translate('tsvb.durationOptions.picosecondsLabel', {
|
||||
defaultMessage: 'Picoseconds',
|
||||
}),
|
||||
value: 'ps',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.durationOptions.nanosecondsLabel', { defaultMessage: 'Nanoseconds' }),
|
||||
label: i18n.translate('tsvb.durationOptions.nanosecondsLabel', {
|
||||
defaultMessage: 'Nanoseconds',
|
||||
}),
|
||||
value: 'ns',
|
||||
},
|
||||
{
|
||||
label: i18n.translate('tsvb.durationOptions.microsecondsLabel', { defaultMessage: 'Microseconds' }),
|
||||
label: i18n.translate('tsvb.durationOptions.microsecondsLabel', {
|
||||
defaultMessage: 'Microseconds',
|
||||
}),
|
||||
value: 'us',
|
||||
},
|
||||
...durationBaseOptions,
|
||||
];
|
||||
|
||||
export const inputFormats = {
|
||||
'ps': 'picoseconds',
|
||||
'ns': 'nanoseconds',
|
||||
'us': 'microseconds',
|
||||
'ms': 'milliseconds',
|
||||
's': 'seconds',
|
||||
'm': 'minutes',
|
||||
'h': 'hours',
|
||||
'd': 'days',
|
||||
'w': 'weeks',
|
||||
'M': 'months',
|
||||
'Y': 'years',
|
||||
ps: 'picoseconds',
|
||||
ns: 'nanoseconds',
|
||||
us: 'microseconds',
|
||||
ms: 'milliseconds',
|
||||
s: 'seconds',
|
||||
m: 'minutes',
|
||||
h: 'hours',
|
||||
d: 'days',
|
||||
w: 'weeks',
|
||||
M: 'months',
|
||||
Y: 'years',
|
||||
};
|
||||
|
||||
export const outputFormats = {
|
||||
'humanize': 'humanize',
|
||||
'ms': 'asMilliseconds',
|
||||
's': 'asSeconds',
|
||||
'm': 'asMinutes',
|
||||
'h': 'asHours',
|
||||
'd': 'asDays',
|
||||
'w': 'asWeeks',
|
||||
'M': 'asMonths',
|
||||
'Y': 'asYears',
|
||||
humanize: 'humanize',
|
||||
ms: 'asMilliseconds',
|
||||
s: 'asSeconds',
|
||||
m: 'asMinutes',
|
||||
h: 'asHours',
|
||||
d: 'asDays',
|
||||
w: 'asWeeks',
|
||||
M: 'asMonths',
|
||||
Y: 'asYears',
|
||||
};
|
||||
|
||||
export const isDuration = format => {
|
||||
|
|
|
@ -23,13 +23,12 @@ export function getAxisLabelString(interval) {
|
|||
const convertedValue = convertIntervalIntoUnit(interval);
|
||||
|
||||
if (convertedValue) {
|
||||
return i18n.translate('tsvb.axisLabelOptions.axisLabel',
|
||||
{
|
||||
defaultMessage: 'per {unitValue} {unitString}',
|
||||
values: {
|
||||
unitValue: convertedValue.unitValue,
|
||||
unitString: convertedValue.unitString,
|
||||
},
|
||||
});
|
||||
return i18n.translate('tsvb.axisLabelOptions.axisLabel', {
|
||||
defaultMessage: 'per {unitValue} {unitString}',
|
||||
values: {
|
||||
unitValue: convertedValue.unitValue,
|
||||
unitString: convertedValue.unitString,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
import chrome from 'ui/chrome';
|
||||
|
||||
export function getDefaultQueryLanguage() {
|
||||
|
|
|
@ -32,12 +32,11 @@ export const unitLookup = {
|
|||
d: i18n.translate('tsvb.getInterval.daysLabel', { defaultMessage: 'days' }),
|
||||
w: i18n.translate('tsvb.getInterval.weeksLabel', { defaultMessage: 'weeks' }),
|
||||
M: i18n.translate('tsvb.getInterval.monthsLabel', { defaultMessage: 'months' }),
|
||||
y: i18n.translate('tsvb.getInterval.yearsLabel', { defaultMessage: 'years' })
|
||||
y: i18n.translate('tsvb.getInterval.yearsLabel', { defaultMessage: 'years' }),
|
||||
};
|
||||
|
||||
export const convertIntervalIntoUnit = (interval, hasTranslateUnitString = true) => {
|
||||
const units = pluck(clone(relativeOptions).reverse(), 'value')
|
||||
.filter(s => /^[smhdwMy]$/.test(s));
|
||||
const units = pluck(clone(relativeOptions).reverse(), 'value').filter(s => /^[smhdwMy]$/.test(s));
|
||||
const duration = moment.duration(interval, 'ms');
|
||||
|
||||
for (let i = 0; i < units.length; i++) {
|
||||
|
@ -46,16 +45,18 @@ export const convertIntervalIntoUnit = (interval, hasTranslateUnitString = true)
|
|||
if (Math.abs(as) > 1) {
|
||||
return {
|
||||
unitValue: Math.round(Math.abs(as)),
|
||||
unitString: hasTranslateUnitString ? unitLookup[units[i]] : units[i]
|
||||
unitString: hasTranslateUnitString ? unitLookup[units[i]] : units[i],
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
export const isGteInterval = (interval) => GTE_INTERVAL_RE.test(interval);
|
||||
export const isGteInterval = interval => GTE_INTERVAL_RE.test(interval);
|
||||
|
||||
export const isIntervalValid = (interval) => {
|
||||
return isString(interval) &&
|
||||
(interval === AUTO_INTERVAL || INTERVAL_STRING_RE.test(interval) || isGteInterval(interval));
|
||||
export const isIntervalValid = interval => {
|
||||
return (
|
||||
isString(interval) &&
|
||||
(interval === AUTO_INTERVAL || INTERVAL_STRING_RE.test(interval) || isGteInterval(interval))
|
||||
);
|
||||
};
|
||||
|
||||
export const getInterval = (visData, model) => {
|
||||
|
|
|
@ -22,6 +22,6 @@ import uuid from 'uuid';
|
|||
export const newMetricAggFn = () => {
|
||||
return {
|
||||
id: uuid.v1(),
|
||||
type: 'count'
|
||||
type: 'count',
|
||||
};
|
||||
};
|
||||
|
|
|
@ -22,18 +22,21 @@ import _ from 'lodash';
|
|||
import { newMetricAggFn } from './new_metric_agg_fn';
|
||||
|
||||
export const newSeriesFn = (obj = {}) => {
|
||||
return _.assign({
|
||||
id: uuid.v1(),
|
||||
color: '#68BC00',
|
||||
split_mode: 'everything',
|
||||
metrics: [ newMetricAggFn() ],
|
||||
separate_axis: 0,
|
||||
axis_position: 'right',
|
||||
formatter: 'number',
|
||||
chart_type: 'line',
|
||||
line_width: 1,
|
||||
point_size: 1,
|
||||
fill: 0.5,
|
||||
stacked: 'none'
|
||||
}, obj);
|
||||
return _.assign(
|
||||
{
|
||||
id: uuid.v1(),
|
||||
color: '#68BC00',
|
||||
split_mode: 'everything',
|
||||
metrics: [newMetricAggFn()],
|
||||
separate_axis: 0,
|
||||
axis_position: 'right',
|
||||
formatter: 'number',
|
||||
chart_type: 'line',
|
||||
line_width: 1,
|
||||
point_size: 1,
|
||||
fill: 0.5,
|
||||
stacked: 'none',
|
||||
},
|
||||
obj
|
||||
);
|
||||
};
|
||||
|
|
|
@ -23,19 +23,21 @@ import _ from 'lodash';
|
|||
export const reIdSeries = source => {
|
||||
const series = _.cloneDeep(source);
|
||||
series.id = uuid.v1();
|
||||
series.metrics.forEach((metric) => {
|
||||
series.metrics.forEach(metric => {
|
||||
const id = uuid.v1();
|
||||
const metricId = metric.id;
|
||||
metric.id = id;
|
||||
if (series.terms_order_by === metricId) series.terms_order_by = id;
|
||||
series.metrics.filter(r => r.field === metricId).forEach(r => r.field = id);
|
||||
series.metrics.filter(r => r.type === 'calculation' &&
|
||||
r.variables.some(v => v.field === metricId))
|
||||
series.metrics.filter(r => r.field === metricId).forEach(r => (r.field = id));
|
||||
series.metrics
|
||||
.filter(r => r.type === 'calculation' && r.variables.some(v => v.field === metricId))
|
||||
.forEach(r => {
|
||||
r.variables.filter(v => v.field === metricId).forEach(v => {
|
||||
v.id = uuid.v1();
|
||||
v.field = id;
|
||||
});
|
||||
r.variables
|
||||
.filter(v => v.field === metricId)
|
||||
.forEach(v => {
|
||||
v.id = uuid.v1();
|
||||
v.field = id;
|
||||
});
|
||||
});
|
||||
});
|
||||
return series;
|
||||
|
|
|
@ -16,11 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
export const reorder = (
|
||||
list,
|
||||
startIndex,
|
||||
endIndex,
|
||||
) => {
|
||||
export const reorder = (list, startIndex, endIndex) => {
|
||||
const result = Array.from(list);
|
||||
const [removed] = result.splice(startIndex, 1);
|
||||
result.splice(endIndex, 0, removed);
|
||||
|
|
|
@ -38,18 +38,26 @@ export function replaceVars(str, args = {}, vars = {}) {
|
|||
const badVar = e.message.split(/"/)[1];
|
||||
e.error = {
|
||||
caused_by: {
|
||||
reason: i18n.translate('tsvb.replaceVars.errors.unknownVarDescription',
|
||||
{ defaultMessage: '{badVar} is an unknown variable', values: { badVar: '{{' + badVar + '}}' } }),
|
||||
title: i18n.translate('tsvb.replaceVars.errors.unknownVarTitle', { defaultMessage: 'Error processing your markdown' })
|
||||
}
|
||||
reason: i18n.translate('tsvb.replaceVars.errors.unknownVarDescription', {
|
||||
defaultMessage: '{badVar} is an unknown variable',
|
||||
values: { badVar: '{{' + badVar + '}}' },
|
||||
}),
|
||||
title: i18n.translate('tsvb.replaceVars.errors.unknownVarTitle', {
|
||||
defaultMessage: 'Error processing your markdown',
|
||||
}),
|
||||
},
|
||||
};
|
||||
} else {
|
||||
e.error = {
|
||||
caused_by: {
|
||||
reason: i18n.translate('tsvb.replaceVars.errors.markdownErrorDescription', {
|
||||
defaultMessage: 'Please verify you are only using markdown, known variables, and built-in Handlebars expressions' }),
|
||||
title: i18n.translate('tsvb.replaceVars.errors.markdownErrorTitle', { defaultMessage: 'Error processing your markdown' })
|
||||
}
|
||||
defaultMessage:
|
||||
'Please verify you are only using markdown, known variables, and built-in Handlebars expressions',
|
||||
}),
|
||||
title: i18n.translate('tsvb.replaceVars.errors.markdownErrorTitle', {
|
||||
defaultMessage: 'Error processing your markdown',
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
return e;
|
||||
|
|
|
@ -20,10 +20,7 @@
|
|||
import _ from 'lodash';
|
||||
import { newMetricAggFn } from './new_metric_agg_fn';
|
||||
import { isBasicAgg } from '../../../common/agg_lookup';
|
||||
import {
|
||||
handleAdd,
|
||||
handleChange
|
||||
} from './collection_actions';
|
||||
import { handleAdd, handleChange } from './collection_actions';
|
||||
|
||||
export const seriesChangeHandler = (props, items) => doc => {
|
||||
// If we only have one sibling and the user changes to a pipeline
|
||||
|
|
|
@ -45,7 +45,7 @@ export const tickFormatter = (format = '0,0.[00]', template, getConfig = null) =
|
|||
formatter = new FieldFormat({ pattern: format }, getConfig);
|
||||
}
|
||||
}
|
||||
return (val) => {
|
||||
return val => {
|
||||
let value;
|
||||
if (!isNumber(val)) {
|
||||
value = val;
|
||||
|
|
|
@ -30,13 +30,7 @@ import _ from 'lodash';
|
|||
import 'brace/mode/markdown';
|
||||
import 'brace/theme/github';
|
||||
|
||||
import {
|
||||
EuiText,
|
||||
EuiCodeBlock,
|
||||
EuiSpacer,
|
||||
EuiTitle,
|
||||
EuiCodeEditor,
|
||||
} from '@elastic/eui';
|
||||
import { EuiText, EuiCodeBlock, EuiSpacer, EuiTitle, EuiCodeEditor } from '@elastic/eui';
|
||||
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
|
@ -47,7 +41,7 @@ export class MarkdownEditor extends Component {
|
|||
subscription = null;
|
||||
|
||||
componentDidMount() {
|
||||
if(this.props.visData$) {
|
||||
if (this.props.visData$) {
|
||||
this.subscription = this.props.visData$.subscribe(visData => {
|
||||
this.setState({ visData });
|
||||
});
|
||||
|
@ -55,18 +49,18 @@ export class MarkdownEditor extends Component {
|
|||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if(this.subscription) {
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
handleChange = (value) => {
|
||||
handleChange = value => {
|
||||
this.props.onChange({ markdown: value });
|
||||
}
|
||||
};
|
||||
|
||||
handleOnLoad = (ace) => {
|
||||
handleOnLoad = ace => {
|
||||
this.ace = ace;
|
||||
}
|
||||
};
|
||||
|
||||
handleVarClick(snippet) {
|
||||
return () => {
|
||||
|
@ -158,13 +152,17 @@ export class MarkdownEditor extends Component {
|
|||
{handlebarLink} on the available expressions."
|
||||
values={{
|
||||
handlebarLink: (
|
||||
<a href="http://handlebarsjs.com/expressions.html" target="_BLANK" rel="noreferrer noopener">
|
||||
<a
|
||||
href="http://handlebarsjs.com/expressions.html"
|
||||
target="_BLANK"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.markdownEditor.howUseVariablesInMarkdownDescription.documentationLinkText"
|
||||
defaultMessage="Click here for documentation"
|
||||
/>
|
||||
</a>
|
||||
)
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
|
@ -173,16 +171,10 @@ export class MarkdownEditor extends Component {
|
|||
<thead>
|
||||
<tr>
|
||||
<th scope="col">
|
||||
<FormattedMessage
|
||||
id="tsvb.markdownEditor.nameLabel"
|
||||
defaultMessage="Name"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.markdownEditor.nameLabel" defaultMessage="Name" />
|
||||
</th>
|
||||
<th scope="col">
|
||||
<FormattedMessage
|
||||
id="tsvb.markdownEditor.valueLabel"
|
||||
defaultMessage="Value"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.markdownEditor.valueLabel" defaultMessage="Value" />
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -190,7 +182,11 @@ export class MarkdownEditor extends Component {
|
|||
</table>
|
||||
|
||||
{rows.length === 0 && (
|
||||
<EuiTitle size="xxs" className="tsvbMarkdownVariablesTable__noVariables" data-test-subj="tvbMarkdownEditor__noVariables">
|
||||
<EuiTitle
|
||||
size="xxs"
|
||||
className="tsvbMarkdownVariablesTable__noVariables"
|
||||
data-test-subj="tvbMarkdownEditor__noVariables"
|
||||
>
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.markdownEditor.noVariablesAvailableDescription"
|
||||
|
@ -208,7 +204,7 @@ export class MarkdownEditor extends Component {
|
|||
id="tsvb.markdownEditor.howToAccessEntireTreeDescription"
|
||||
defaultMessage="There is also a special variable named {all} which you can use to access the entire tree. This is useful for
|
||||
creating lists with data from a group by:"
|
||||
values={{ all: (<code>_all</code>) }}
|
||||
values={{ all: <code>_all</code> }}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
|
|
|
@ -33,7 +33,7 @@ const types = {
|
|||
metric,
|
||||
top_n: topN,
|
||||
gauge,
|
||||
markdown
|
||||
markdown,
|
||||
};
|
||||
|
||||
export function PanelConfig(props) {
|
||||
|
@ -49,7 +49,8 @@ export function PanelConfig(props) {
|
|||
defaultMessage="Missing panel config for “{modelType}”"
|
||||
values={{ modelType: model.type }}
|
||||
/>
|
||||
</div>);
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
PanelConfig.propTypes = {
|
||||
|
|
|
@ -58,8 +58,10 @@ class GaugePanelConfigUi extends Component {
|
|||
componentWillMount() {
|
||||
const { model } = this.props;
|
||||
const parts = {};
|
||||
if (!model.gauge_color_rules ||
|
||||
(model.gauge_color_rules && model.gauge_color_rules.length === 0)) {
|
||||
if (
|
||||
!model.gauge_color_rules ||
|
||||
(model.gauge_color_rules && model.gauge_color_rules.length === 0)
|
||||
) {
|
||||
parts.gauge_color_rules = [{ id: uuid.v1() }];
|
||||
}
|
||||
if (model.gauge_width == null) parts.gauge_width = 10;
|
||||
|
@ -80,7 +82,7 @@ class GaugePanelConfigUi extends Component {
|
|||
filter: { query: '', language: getDefaultQueryLanguage() },
|
||||
gauge_style: 'circle',
|
||||
gauge_inner_width: '',
|
||||
gauge_width: ''
|
||||
gauge_width: '',
|
||||
};
|
||||
const model = { ...defaults, ...this.props.model };
|
||||
const handleSelectChange = createSelectHandler(this.props.onChange);
|
||||
|
@ -88,14 +90,18 @@ class GaugePanelConfigUi extends Component {
|
|||
const styleOptions = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.gauge.styleOptions.circleLabel', defaultMessage: 'Circle' }),
|
||||
value: 'circle'
|
||||
id: 'tsvb.gauge.styleOptions.circleLabel',
|
||||
defaultMessage: 'Circle',
|
||||
}),
|
||||
value: 'circle',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.gauge.styleOptions.halfCircleLabel', defaultMessage: 'Half Circle' }),
|
||||
value: 'half'
|
||||
}
|
||||
id: 'tsvb.gauge.styleOptions.halfCircleLabel',
|
||||
defaultMessage: 'Half Circle',
|
||||
}),
|
||||
value: 'half',
|
||||
},
|
||||
];
|
||||
const htmlId = htmlIdGenerator();
|
||||
const selectedGaugeStyleOption = styleOptions.find(option => {
|
||||
|
@ -120,10 +126,7 @@ class GaugePanelConfigUi extends Component {
|
|||
<EuiPanel>
|
||||
<EuiTitle size="s">
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.dataLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.gauge.optionsTab.dataLabel" defaultMessage="Data" />
|
||||
</span>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
@ -140,10 +143,12 @@ class GaugePanelConfigUi extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilter')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<QueryBarInput
|
||||
|
@ -180,10 +185,7 @@ class GaugePanelConfigUi extends Component {
|
|||
<EuiPanel>
|
||||
<EuiTitle size="s">
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.styleLabel"
|
||||
defaultMessage="Style"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.gauge.optionsTab.styleLabel" defaultMessage="Style" />
|
||||
</span>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
@ -192,10 +194,12 @@ class GaugePanelConfigUi extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('gaugeMax')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.gaugeMaxLabel"
|
||||
defaultMessage="Gauge max (empty for auto)"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.gaugeMaxLabel"
|
||||
defaultMessage="Gauge max (empty for auto)"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
|
@ -213,10 +217,12 @@ class GaugePanelConfigUi extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('gaugeStyle')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.gaugeStyleLabel"
|
||||
defaultMessage="Gauge style"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.gaugeStyleLabel"
|
||||
defaultMessage="Gauge style"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
|
@ -230,10 +236,12 @@ class GaugePanelConfigUi extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('innerLine')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.innerLineWidthLabel"
|
||||
defaultMessage="Inner line width"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.innerLineWidthLabel"
|
||||
defaultMessage="Inner line width"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
onChange={handleTextChange('gauge_inner_width')}
|
||||
|
@ -244,10 +252,12 @@ class GaugePanelConfigUi extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('gaugeLine')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.gaugeLineWidthLabel"
|
||||
defaultMessage="Gauge line width"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.gaugeLineWidthLabel"
|
||||
defaultMessage="Gauge line width"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
onChange={handleTextChange('gauge_width')}
|
||||
|
@ -319,19 +329,10 @@ class GaugePanelConfigUi extends Component {
|
|||
return (
|
||||
<div>
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.gauge.dataTab.dataButtonLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<EuiTab isSelected={selectedTab === 'data'} onClick={() => this.switchTab('data')}>
|
||||
<FormattedMessage id="tsvb.gauge.dataTab.dataButtonLabel" defaultMessage="Data" />
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
>
|
||||
<EuiTab isSelected={selectedTab === 'options'} onClick={() => this.switchTab('options')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.gauge.optionsTab.panelOptionsButtonLabel"
|
||||
defaultMessage="Panel options"
|
||||
|
@ -342,7 +343,6 @@ class GaugePanelConfigUi extends Component {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GaugePanelConfigUi.propTypes = {
|
||||
|
|
|
@ -86,24 +86,33 @@ class MarkdownPanelConfigUi extends Component {
|
|||
|
||||
const alignOptions = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.markdown.alignOptions.topLabel', defaultMessage: 'Top' }),
|
||||
value: 'top'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.markdown.alignOptions.topLabel',
|
||||
defaultMessage: 'Top',
|
||||
}),
|
||||
value: 'top',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.markdown.alignOptions.middleLabel', defaultMessage: 'Middle' }),
|
||||
value: 'middle'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.markdown.alignOptions.middleLabel',
|
||||
defaultMessage: 'Middle',
|
||||
}),
|
||||
value: 'middle',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.markdown.alignOptions.bottomLabel', defaultMessage: 'Bottom' }),
|
||||
value: 'bottom'
|
||||
}
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.markdown.alignOptions.bottomLabel',
|
||||
defaultMessage: 'Bottom',
|
||||
}),
|
||||
value: 'bottom',
|
||||
},
|
||||
];
|
||||
const selectedAlignOption = alignOptions.find(option => {
|
||||
return model.markdown_vertical_align === option.value;
|
||||
});
|
||||
let view;
|
||||
if (selectedTab === 'markdown') {
|
||||
view = (<MarkdownEditor {...this.props}/>);
|
||||
view = <MarkdownEditor {...this.props} />;
|
||||
} else if (selectedTab === 'data') {
|
||||
view = (
|
||||
<SeriesEditor
|
||||
|
@ -121,10 +130,7 @@ class MarkdownPanelConfigUi extends Component {
|
|||
<EuiPanel>
|
||||
<EuiTitle size="s">
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.markdown.optionsTab.dataLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.markdown.optionsTab.dataLabel" defaultMessage="Data" />
|
||||
</span>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
@ -141,15 +147,19 @@ class MarkdownPanelConfigUi extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilter')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.markdown.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.markdown.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<QueryBarInput
|
||||
query={{
|
||||
language: model.filter.language ? model.filter.language : getDefaultQueryLanguage(),
|
||||
language: model.filter.language
|
||||
? model.filter.language
|
||||
: getDefaultQueryLanguage(),
|
||||
query: model.filter.query || '',
|
||||
}}
|
||||
onChange={filter => this.props.onChange({ filter })}
|
||||
|
@ -181,10 +191,7 @@ class MarkdownPanelConfigUi extends Component {
|
|||
<EuiPanel>
|
||||
<EuiTitle size="s">
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.markdown.optionsTab.styleLabel"
|
||||
defaultMessage="Style"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.markdown.optionsTab.styleLabel" defaultMessage="Style" />
|
||||
</span>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
@ -296,10 +303,7 @@ class MarkdownPanelConfigUi extends Component {
|
|||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.markdown.dataTab.dataButtonLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.markdown.dataTab.dataButtonLabel" defaultMessage="Data" />
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
|
|
|
@ -53,9 +53,12 @@ export class MetricPanelConfig extends Component {
|
|||
|
||||
componentWillMount() {
|
||||
const { model } = this.props;
|
||||
if (!model.background_color_rules || (model.background_color_rules && model.background_color_rules.length === 0)) {
|
||||
if (
|
||||
!model.background_color_rules ||
|
||||
(model.background_color_rules && model.background_color_rules.length === 0)
|
||||
) {
|
||||
this.props.onChange({
|
||||
background_color_rules: [{ id: uuid.v1() }]
|
||||
background_color_rules: [{ id: uuid.v1() }],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -88,10 +91,7 @@ export class MetricPanelConfig extends Component {
|
|||
<EuiPanel>
|
||||
<EuiTitle size="s">
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.metric.optionsTab.dataLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.metric.optionsTab.dataLabel" defaultMessage="Data" />
|
||||
</span>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
@ -108,10 +108,12 @@ export class MetricPanelConfig extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilter')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.metric.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.metric.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<QueryBarInput
|
||||
|
@ -168,14 +170,8 @@ export class MetricPanelConfig extends Component {
|
|||
return (
|
||||
<div>
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.metric.dataTab.dataButtonLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<EuiTab isSelected={selectedTab === 'data'} onClick={() => this.switchTab('data')}>
|
||||
<FormattedMessage id="tsvb.metric.dataTab.dataButtonLabel" defaultMessage="Data" />
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
|
@ -192,7 +188,6 @@ export class MetricPanelConfig extends Component {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MetricPanelConfig.propTypes = {
|
||||
|
|
|
@ -67,7 +67,7 @@ export class TablePanelConfig extends Component {
|
|||
this.setState({ selectedTab });
|
||||
}
|
||||
|
||||
handlePivotChange = (selectedOption) => {
|
||||
handlePivotChange = selectedOption => {
|
||||
const { fields, model } = this.props;
|
||||
const pivotId = get(selectedOption, '[0].value', null);
|
||||
const field = fields[model.index_pattern].find(field => field.name === pivotId);
|
||||
|
@ -75,7 +75,7 @@ export class TablePanelConfig extends Component {
|
|||
|
||||
this.props.onChange({
|
||||
pivot_id: pivotId,
|
||||
pivot_type: pivotType
|
||||
pivot_type: pivotType,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -111,10 +111,12 @@ export class TablePanelConfig extends Component {
|
|||
<EuiFlexItem data-test-subj="groupByField">
|
||||
<EuiFormRow
|
||||
id={htmlId('field')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.table.dataTab.groupByFieldLabel"
|
||||
defaultMessage="Group by field"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.table.dataTab.groupByFieldLabel"
|
||||
defaultMessage="Group by field"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<FieldSelect
|
||||
fields={this.props.fields}
|
||||
|
@ -128,10 +130,12 @@ export class TablePanelConfig extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('pivotLabelInput')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.table.dataTab.columnLabel"
|
||||
defaultMessage="Column label"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.table.dataTab.columnLabel"
|
||||
defaultMessage="Column label"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
|
@ -145,10 +149,9 @@ export class TablePanelConfig extends Component {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('pivotRowsInput')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.table.dataTab.rowsLabel"
|
||||
defaultMessage="Rows"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.table.dataTab.rowsLabel" defaultMessage="Rows" />
|
||||
}
|
||||
>
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
|
@ -181,25 +184,24 @@ export class TablePanelConfig extends Component {
|
|||
<EuiPanel>
|
||||
<EuiTitle size="s">
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.table.optionsTab.dataLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.table.optionsTab.dataLabel" defaultMessage="Data" />
|
||||
</span>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiFormRow
|
||||
id={htmlId('drilldownInput')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.table.optionsTab.itemUrlLabel"
|
||||
defaultMessage="Item url"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.table.optionsTab.itemUrlLabel"
|
||||
defaultMessage="Item url"
|
||||
/>
|
||||
}
|
||||
helpText={
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.table.optionsTab.itemUrlHelpText"
|
||||
defaultMessage="This supports mustache templating. {key} is set to the term."
|
||||
values={{ key: (<EuiCode>{'{{key}}'}</EuiCode>) }}
|
||||
values={{ key: <EuiCode>{'{{key}}'}</EuiCode> }}
|
||||
/>
|
||||
</span>
|
||||
}
|
||||
|
@ -224,15 +226,19 @@ export class TablePanelConfig extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilterInput')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.table.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.table.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<QueryBarInput
|
||||
query={{
|
||||
language: model.filter.language ? model.filter.language : getDefaultQueryLanguage(),
|
||||
language: model.filter.language
|
||||
? model.filter.language
|
||||
: getDefaultQueryLanguage(),
|
||||
query: model.filter.query || '',
|
||||
}}
|
||||
onChange={filter => this.props.onChange({ filter })}
|
||||
|
@ -265,19 +271,10 @@ export class TablePanelConfig extends Component {
|
|||
return (
|
||||
<div>
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.table.dataTab.columnsButtonLabel"
|
||||
defaultMessage="Columns"
|
||||
/>
|
||||
<EuiTab isSelected={selectedTab === 'data'} onClick={() => this.switchTab('data')}>
|
||||
<FormattedMessage id="tsvb.table.dataTab.columnsButtonLabel" defaultMessage="Columns" />
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
>
|
||||
<EuiTab isSelected={selectedTab === 'options'} onClick={() => this.switchTab('options')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.table.optionsTab.panelOptionsButtonLabel"
|
||||
defaultMessage="Panel options"
|
||||
|
@ -288,7 +285,6 @@ export class TablePanelConfig extends Component {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TablePanelConfig.propTypes = {
|
||||
|
|
|
@ -63,7 +63,7 @@ class TimeseriesPanelConfigUi extends Component {
|
|||
axis_max: '',
|
||||
axis_min: '',
|
||||
legend_position: 'right',
|
||||
show_grid: 1
|
||||
show_grid: 1,
|
||||
};
|
||||
const model = { ...defaults, ...this.props.model };
|
||||
const { selectedTab } = this.state;
|
||||
|
@ -74,43 +74,64 @@ class TimeseriesPanelConfigUi extends Component {
|
|||
|
||||
const positionOptions = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.timeseries.positionOptions.rightLabel', defaultMessage: 'Right' }),
|
||||
value: 'right'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.timeseries.positionOptions.rightLabel',
|
||||
defaultMessage: 'Right',
|
||||
}),
|
||||
value: 'right',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.timeseries.positionOptions.leftLabel', defaultMessage: 'Left' }),
|
||||
value: 'left'
|
||||
}
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.timeseries.positionOptions.leftLabel',
|
||||
defaultMessage: 'Left',
|
||||
}),
|
||||
value: 'left',
|
||||
},
|
||||
];
|
||||
const selectedPositionOption = positionOptions.find(option => {
|
||||
return model.axis_position === option.value;
|
||||
});
|
||||
const scaleOptions = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.timeseries.scaleOptions.normalLabel', defaultMessage: 'Normal' }),
|
||||
value: 'normal'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.timeseries.scaleOptions.normalLabel',
|
||||
defaultMessage: 'Normal',
|
||||
}),
|
||||
value: 'normal',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.timeseries.scaleOptions.logLabel', defaultMessage: 'Log' }),
|
||||
value: 'log'
|
||||
}
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.timeseries.scaleOptions.logLabel',
|
||||
defaultMessage: 'Log',
|
||||
}),
|
||||
value: 'log',
|
||||
},
|
||||
];
|
||||
const selectedAxisScaleOption = scaleOptions.find(option => {
|
||||
return model.axis_scale === option.value;
|
||||
});
|
||||
const legendPositionOptions = [
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.timeseries.legendPositionOptions.rightLabel', defaultMessage: 'Right' }),
|
||||
value: 'right'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.timeseries.legendPositionOptions.rightLabel',
|
||||
defaultMessage: 'Right',
|
||||
}),
|
||||
value: 'right',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.timeseries.legendPositionOptions.leftLabel', defaultMessage: 'Left' }),
|
||||
value: 'left'
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.timeseries.legendPositionOptions.leftLabel',
|
||||
defaultMessage: 'Left',
|
||||
}),
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.timeseries.legendPositionOptions.bottomLabel', defaultMessage: 'Bottom' }),
|
||||
value: 'bottom'
|
||||
}
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.timeseries.legendPositionOptions.bottomLabel',
|
||||
defaultMessage: 'Bottom',
|
||||
}),
|
||||
value: 'bottom',
|
||||
},
|
||||
];
|
||||
const selectedLegendPosOption = legendPositionOptions.find(option => {
|
||||
return model.legend_position === option.value;
|
||||
|
@ -142,10 +163,7 @@ class TimeseriesPanelConfigUi extends Component {
|
|||
<EuiPanel>
|
||||
<EuiTitle size="s">
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.dataLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.timeseries.optionsTab.dataLabel" defaultMessage="Data" />
|
||||
</span>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
@ -162,10 +180,12 @@ class TimeseriesPanelConfigUi extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilter')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<QueryBarInput
|
||||
|
@ -214,38 +234,38 @@ class TimeseriesPanelConfigUi extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('axisMin')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.axisMinLabel"
|
||||
defaultMessage="Axis min"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.axisMinLabel"
|
||||
defaultMessage="Axis min"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('axis_min')}
|
||||
value={model.axis_min}
|
||||
/>
|
||||
<EuiFieldText onChange={handleTextChange('axis_min')} value={model.axis_min} />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('axisMax')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.axisMaxLabel"
|
||||
defaultMessage="Axis max"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.axisMaxLabel"
|
||||
defaultMessage="Axis max"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('axis_max')}
|
||||
value={model.axis_max}
|
||||
/>
|
||||
<EuiFieldText onChange={handleTextChange('axis_max')} value={model.axis_max} />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('axisPos')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.axisPositionLabel"
|
||||
defaultMessage="Axis position"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.axisPositionLabel"
|
||||
defaultMessage="Axis position"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
|
@ -259,10 +279,12 @@ class TimeseriesPanelConfigUi extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('axisScale')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.axisScaleLabel"
|
||||
defaultMessage="Axis scale"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.axisScaleLabel"
|
||||
defaultMessage="Axis scale"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
|
@ -335,11 +357,7 @@ class TimeseriesPanelConfigUi extends Component {
|
|||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<YesNo
|
||||
value={model.show_grid}
|
||||
name="show_grid"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
<YesNo value={model.show_grid} name="show_grid" onChange={this.props.onChange} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
|
@ -349,19 +367,10 @@ class TimeseriesPanelConfigUi extends Component {
|
|||
return (
|
||||
<div>
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.timeseries.dataTab.dataButtonLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<EuiTab isSelected={selectedTab === 'data'} onClick={() => this.switchTab('data')}>
|
||||
<FormattedMessage id="tsvb.timeseries.dataTab.dataButtonLabel" defaultMessage="Data" />
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
>
|
||||
<EuiTab isSelected={selectedTab === 'options'} onClick={() => this.switchTab('options')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.timeseries.optionsTab.panelOptionsButtonLabel"
|
||||
defaultMessage="Panel options"
|
||||
|
|
|
@ -49,7 +49,6 @@ const { QueryBarInput } = data.query.ui;
|
|||
const localStorage = new Storage(window.localStorage);
|
||||
|
||||
export class TopNPanelConfig extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { selectedTab: 'data' };
|
||||
|
@ -70,7 +69,10 @@ export class TopNPanelConfig extends Component {
|
|||
|
||||
render() {
|
||||
const { selectedTab } = this.state;
|
||||
const defaults = { drilldown_url: '', filter: { query: '', language: getDefaultQueryLanguage() } };
|
||||
const defaults = {
|
||||
drilldown_url: '',
|
||||
filter: { query: '', language: getDefaultQueryLanguage() },
|
||||
};
|
||||
const model = { ...defaults, ...this.props.model };
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleTextChange = createTextHandler(this.props.onChange);
|
||||
|
@ -92,25 +94,24 @@ export class TopNPanelConfig extends Component {
|
|||
<EuiPanel>
|
||||
<EuiTitle size="s">
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.topN.optionsTab.dataLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.topN.optionsTab.dataLabel" defaultMessage="Data" />
|
||||
</span>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiFormRow
|
||||
id={htmlId('itemUrl')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.topN.optionsTab.itemUrlLabel"
|
||||
defaultMessage="Item url"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.topN.optionsTab.itemUrlLabel"
|
||||
defaultMessage="Item url"
|
||||
/>
|
||||
}
|
||||
helpText={
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.topN.optionsTab.itemUrlDescription"
|
||||
defaultMessage="This supports mustache templating. {key} is set to the term."
|
||||
values={{ key: (<EuiCode>{'{{key}}'}</EuiCode>) }}
|
||||
values={{ key: <EuiCode>{'{{key}}'}</EuiCode> }}
|
||||
/>
|
||||
</span>
|
||||
}
|
||||
|
@ -135,15 +136,19 @@ export class TopNPanelConfig extends Component {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilter')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.topN.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.topN.optionsTab.panelFilterLabel"
|
||||
defaultMessage="Panel filter"
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<QueryBarInput
|
||||
query={{
|
||||
language: model.filter.language ? model.filter.language : getDefaultQueryLanguage(),
|
||||
language: model.filter.language
|
||||
? model.filter.language
|
||||
: getDefaultQueryLanguage(),
|
||||
query: model.filter.query || '',
|
||||
}}
|
||||
onChange={filter => this.props.onChange({ filter })}
|
||||
|
@ -175,10 +180,7 @@ export class TopNPanelConfig extends Component {
|
|||
<EuiPanel>
|
||||
<EuiTitle size="s">
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.topN.optionsTab.styleLabel"
|
||||
defaultMessage="Style"
|
||||
/>
|
||||
<FormattedMessage id="tsvb.topN.optionsTab.styleLabel" defaultMessage="Style" />
|
||||
</span>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
@ -227,19 +229,10 @@ export class TopNPanelConfig extends Component {
|
|||
return (
|
||||
<div>
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.topN.dataTab.dataButtonLabel"
|
||||
defaultMessage="Data"
|
||||
/>
|
||||
<EuiTab isSelected={selectedTab === 'data'} onClick={() => this.switchTab('data')}>
|
||||
<FormattedMessage id="tsvb.topN.dataTab.dataButtonLabel" defaultMessage="Data" />
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
>
|
||||
<EuiTab isSelected={selectedTab === 'options'} onClick={() => this.switchTab('options')}>
|
||||
<FormattedMessage
|
||||
id="tsvb.topN.optionsTab.panelOptionsButtonLabel"
|
||||
defaultMessage="Panel options"
|
||||
|
@ -250,7 +243,6 @@ export class TopNPanelConfig extends Component {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TopNPanelConfig.propTypes = {
|
||||
|
|
|
@ -51,11 +51,11 @@ export class Series extends Component {
|
|||
this.visDataSubscription = null;
|
||||
}
|
||||
|
||||
switchTab = (selectedTab) => {
|
||||
switchTab = selectedTab => {
|
||||
this.setState({ selectedTab });
|
||||
};
|
||||
|
||||
handleChange = (part) => {
|
||||
handleChange = part => {
|
||||
if (this.props.onChange) {
|
||||
const { model } = this.props;
|
||||
const doc = assign({}, model, part);
|
||||
|
@ -71,7 +71,7 @@ export class Series extends Component {
|
|||
});
|
||||
};
|
||||
|
||||
toggleVisible = (e) => {
|
||||
toggleVisible = e => {
|
||||
e.preventDefault();
|
||||
|
||||
this.setState({
|
||||
|
@ -81,10 +81,11 @@ export class Series extends Component {
|
|||
|
||||
componentDidMount() {
|
||||
if (this.props.visData$) {
|
||||
this.visDataSubscription = this.props.visData$
|
||||
.subscribe(visData => this.setState({
|
||||
this.visDataSubscription = this.props.visData$.subscribe(visData =>
|
||||
this.setState({
|
||||
uiRestrictions: get(visData, 'uiRestrictions'),
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,13 +115,15 @@ export class Series extends Component {
|
|||
dragHandleProps: this.props.dragHandleProps,
|
||||
indexPatternForQuery: panel.index_pattern || panel.default_index_pattern,
|
||||
};
|
||||
return Boolean(Component) ?
|
||||
(<Component {...params}/>) :
|
||||
(<FormattedMessage
|
||||
return Boolean(Component) ? (
|
||||
<Component {...params} />
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="tsvb.seriesConfig.missingSeriesComponentDescription"
|
||||
defaultMessage="Missing Series component for panel type: {panelType}"
|
||||
values={{ panelType: panel.type }}
|
||||
/>);
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
|
|
@ -48,31 +48,29 @@ export const SeriesConfig = props => {
|
|||
const handleSelectChange = createSelectHandler(props.onChange);
|
||||
const handleTextChange = createTextHandler(props.onChange);
|
||||
const htmlId = htmlIdGenerator();
|
||||
const seriesIndexPattern = (props.model.override_index_pattern && props.model.series_index_pattern) ?
|
||||
props.model.series_index_pattern : props.indexPatternForQuery;
|
||||
const seriesIndexPattern =
|
||||
props.model.override_index_pattern && props.model.series_index_pattern
|
||||
? props.model.series_index_pattern
|
||||
: props.indexPatternForQuery;
|
||||
|
||||
return (
|
||||
<div className="tvbAggRow">
|
||||
|
||||
<DataFormatPicker
|
||||
onChange={handleSelectChange('formatter')}
|
||||
value={model.formatter}
|
||||
/>
|
||||
<DataFormatPicker onChange={handleSelectChange('formatter')} value={model.formatter} />
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiFormRow
|
||||
id={htmlId('series_filter')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.seriesConfig.filterLabel"
|
||||
defaultMessage="Filter"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.seriesConfig.filterLabel" defaultMessage="Filter" />}
|
||||
fullWidth
|
||||
>
|
||||
<QueryBarInput
|
||||
query={{
|
||||
language: (model.filter && model.filter.language) ? model.filter.language : getDefaultQueryLanguage(),
|
||||
query: (model.filter && model.filter.query) ? model.filter.query : ''
|
||||
language:
|
||||
model.filter && model.filter.language
|
||||
? model.filter.language
|
||||
: getDefaultQueryLanguage(),
|
||||
query: model.filter && model.filter.query ? model.filter.query : '',
|
||||
}}
|
||||
onChange={filter => props.onChange({ filter })}
|
||||
appName={'VisEditor'}
|
||||
|
@ -88,19 +86,18 @@ export const SeriesConfig = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('template')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.seriesConfig.templateLabel"
|
||||
defaultMessage="Template"
|
||||
/>)}
|
||||
helpText={(
|
||||
label={
|
||||
<FormattedMessage id="tsvb.seriesConfig.templateLabel" defaultMessage="Template" />
|
||||
}
|
||||
helpText={
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="tsvb.seriesConfig.templateHelpText"
|
||||
defaultMessage="eg. {templateExample}"
|
||||
values={{ templateExample: (<EuiCode>{'{{value}}/s'}</EuiCode>) }}
|
||||
values={{ templateExample: <EuiCode>{'{{value}}/s'}</EuiCode> }}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
|
@ -113,11 +110,13 @@ export const SeriesConfig = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('offsetSeries')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.seriesConfig.offsetSeriesTimeLabel"
|
||||
defaultMessage="Offset series time by (1m, 1h, 1w, 1d)"
|
||||
description="1m, 1h, 1w and 1d are required values and must not be translated."
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.seriesConfig.offsetSeriesTimeLabel"
|
||||
defaultMessage="Offset series time by (1m, 1h, 1w, 1d)"
|
||||
description="1m, 1h, 1w and 1d are required values and must not be translated."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="offsetTimeSeries"
|
||||
|
@ -155,7 +154,6 @@ export const SeriesConfig = props => {
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -22,11 +22,7 @@ import React, { Component } from 'react';
|
|||
import { find } from 'lodash';
|
||||
import { reIdSeries } from './lib/re_id_series';
|
||||
import { Series } from './series';
|
||||
import {
|
||||
handleAdd,
|
||||
handleDelete,
|
||||
handleChange,
|
||||
} from './lib/collection_actions';
|
||||
import { handleAdd, handleDelete, handleChange } from './lib/collection_actions';
|
||||
import { newSeriesFn } from './lib/new_series_fn';
|
||||
import { EuiDragDropContext, EuiDroppable, EuiDraggable } from '@elastic/eui';
|
||||
import { reorder } from './lib/reorder';
|
||||
|
@ -34,7 +30,6 @@ import { reorder } from './lib/reorder';
|
|||
const DROPPABLE_ID = 'series_editor_dnd';
|
||||
|
||||
export class SeriesEditor extends Component {
|
||||
|
||||
handleClone = series => {
|
||||
const newSeries = reIdSeries(series);
|
||||
|
||||
|
@ -52,10 +47,9 @@ export class SeriesEditor extends Component {
|
|||
};
|
||||
|
||||
getSortFunction = ({ destination, source }) =>
|
||||
(destination.droppableId === source.droppableId && source.droppableId === DROPPABLE_ID ?
|
||||
this.sortSeries :
|
||||
this.sortAggregations
|
||||
);
|
||||
destination.droppableId === source.droppableId && source.droppableId === DROPPABLE_ID
|
||||
? this.sortSeries
|
||||
: this.sortAggregations;
|
||||
|
||||
sortSeries = ({ destination, source }) => {
|
||||
this.props.onChange({
|
||||
|
@ -82,16 +76,11 @@ export class SeriesEditor extends Component {
|
|||
|
||||
render() {
|
||||
const { limit, model, name, fields, colorPicker } = this.props;
|
||||
const list = model[name]
|
||||
.filter((val, index) => index < (limit || Infinity));
|
||||
const list = model[name].filter((val, index) => index < (limit || Infinity));
|
||||
|
||||
return (
|
||||
<EuiDragDropContext onDragEnd={this.sortHandler}>
|
||||
<EuiDroppable
|
||||
droppableId={DROPPABLE_ID}
|
||||
spacing="l"
|
||||
type="MACRO"
|
||||
>
|
||||
<EuiDroppable droppableId={DROPPABLE_ID} spacing="l" type="MACRO">
|
||||
{list.map((row, idx) => (
|
||||
<EuiDraggable
|
||||
spacing="m"
|
||||
|
@ -109,7 +98,7 @@ export class SeriesEditor extends Component {
|
|||
disableDelete={model[name].length < 2}
|
||||
fields={fields}
|
||||
onAdd={() => handleAdd(this.props, newSeriesFn)}
|
||||
onChange={(doc) => handleChange(this.props, doc)}
|
||||
onChange={doc => handleChange(this.props, doc)}
|
||||
onClone={() => this.handleClone(row)}
|
||||
onDelete={() => handleDelete(this.props, row)}
|
||||
visData$={this.props.visData$}
|
||||
|
|
|
@ -37,7 +37,6 @@ const SPLIT_MODES = {
|
|||
};
|
||||
|
||||
export class Split extends Component {
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { model } = nextProps;
|
||||
if (model.split_mode === 'filters' && !model.split_filters) {
|
||||
|
@ -48,8 +47,8 @@ export class Split extends Component {
|
|||
id: uuid.v1(),
|
||||
filter: {
|
||||
query: '',
|
||||
language: getDefaultQueryLanguage()
|
||||
}
|
||||
language: getDefaultQueryLanguage(),
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -75,7 +74,8 @@ export class Split extends Component {
|
|||
|
||||
render() {
|
||||
const { model, panel, uiRestrictions } = this.props;
|
||||
const indexPattern = (model.override_index_pattern && model.series_index_pattern) ||
|
||||
const indexPattern =
|
||||
(model.override_index_pattern && model.series_index_pattern) ||
|
||||
(panel.index_pattern || panel.default_index_pattern);
|
||||
|
||||
const splitMode = get(this.props, 'model.split_mode', SPLIT_MODES.EVERYTHING);
|
||||
|
|
|
@ -24,7 +24,7 @@ import React from 'react';
|
|||
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
export const SplitByEverything = (props) => {
|
||||
export const SplitByEverything = props => {
|
||||
const { onChange, model, uiRestrictions } = props;
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleSelectChange = createSelectHandler(onChange);
|
||||
|
@ -33,10 +33,9 @@ export const SplitByEverything = (props) => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('group')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.everything.groupByLabel"
|
||||
defaultMessage="Group by"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.splits.everything.groupByLabel" defaultMessage="Group by" />
|
||||
}
|
||||
>
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
|
@ -54,5 +53,3 @@ SplitByEverything.propTypes = {
|
|||
onChange: PropTypes.func,
|
||||
uiRestrictions: PropTypes.object,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -40,10 +40,9 @@ export const SplitByFilter = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('group')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.filter.groupByLabel"
|
||||
defaultMessage="Group by"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.splits.filter.groupByLabel" defaultMessage="Group by" />
|
||||
}
|
||||
>
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
|
@ -55,10 +54,12 @@ export const SplitByFilter = props => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('query')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.filter.queryStringLabel"
|
||||
defaultMessage="Query string"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.splits.filter.queryStringLabel"
|
||||
defaultMessage="Query string"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<QueryBarInput
|
||||
query={{
|
||||
|
|
|
@ -38,22 +38,24 @@ class FilterItemsUi extends Component {
|
|||
}
|
||||
|
||||
handleChange(item, name) {
|
||||
return (e) => {
|
||||
return e => {
|
||||
const handleChange = collectionActions.handleChange.bind(null, this.props);
|
||||
handleChange(_.assign({}, item, {
|
||||
[name]: _.get(e, 'value', _.get(e, 'target.value'))
|
||||
}));
|
||||
handleChange(
|
||||
_.assign({}, item, {
|
||||
[name]: _.get(e, 'value', _.get(e, 'target.value')),
|
||||
})
|
||||
);
|
||||
};
|
||||
}
|
||||
handleQueryChange = (model, filter) => {
|
||||
const part = { filter };
|
||||
collectionActions.handleChange(this.props, _.assign({}, model, part));
|
||||
}
|
||||
};
|
||||
renderRow(row, i, items) {
|
||||
const indexPatterns = this.props.indexPatterns;
|
||||
const defaults = { filter: '', label: '' };
|
||||
const model = { ...defaults, ...row };
|
||||
const handleChange = (part) => {
|
||||
const handleChange = part => {
|
||||
const fn = collectionActions.handleChange.bind(null, this.props);
|
||||
fn(_.assign({}, model, part));
|
||||
};
|
||||
|
@ -63,13 +65,11 @@ class FilterItemsUi extends Component {
|
|||
id: uuid.v1(),
|
||||
filter: { language: model.filter.language || getDefaultQueryLanguage(), query: '' },
|
||||
});
|
||||
const handleAdd = collectionActions.handleAdd
|
||||
.bind(null, this.props, newFilter);
|
||||
const handleDelete = collectionActions.handleDelete
|
||||
.bind(null, this.props, model);
|
||||
const handleAdd = collectionActions.handleAdd.bind(null, this.props, newFilter);
|
||||
const handleDelete = collectionActions.handleDelete.bind(null, this.props, model);
|
||||
const { intl } = this.props;
|
||||
|
||||
return (
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="s" className="tvbAggRow" alignItems="center" key={model.id}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ColorPicker
|
||||
|
@ -85,7 +85,7 @@ class FilterItemsUi extends Component {
|
|||
language: model.filter.language || getDefaultQueryLanguage(),
|
||||
query: model.filter.query || '',
|
||||
}}
|
||||
onChange={(query) => this.handleQueryChange(model, query)}
|
||||
onChange={query => this.handleQueryChange(model, query)}
|
||||
appName={'VisEditor'}
|
||||
indexPatterns={[indexPatterns]}
|
||||
store={localStorage}
|
||||
|
@ -93,8 +93,14 @@ class FilterItemsUi extends Component {
|
|||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
placeholder={intl.formatMessage({ id: 'tsvb.splits.filterItems.labelPlaceholder', defaultMessage: 'Label' })}
|
||||
aria-label={intl.formatMessage({ id: 'tsvb.splits.filterItems.labelAriaLabel', defaultMessage: 'Label' })}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'tsvb.splits.filterItems.labelPlaceholder',
|
||||
defaultMessage: 'Label',
|
||||
})}
|
||||
aria-label={intl.formatMessage({
|
||||
id: 'tsvb.splits.filterItems.labelAriaLabel',
|
||||
defaultMessage: 'Label',
|
||||
})}
|
||||
onChange={this.handleChange(model, 'label')}
|
||||
value={model.label}
|
||||
fullWidth
|
||||
|
@ -114,15 +120,10 @@ class FilterItemsUi extends Component {
|
|||
|
||||
render() {
|
||||
const { model, name } = this.props;
|
||||
if (!model[name]) return (<div/>);
|
||||
if (!model[name]) return <div />;
|
||||
const rows = model[name].map(this.renderRow);
|
||||
return (
|
||||
<div>
|
||||
{ rows }
|
||||
</div>
|
||||
);
|
||||
return <div>{rows}</div>;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FilterItemsUi.propTypes = {
|
||||
|
|
|
@ -25,7 +25,7 @@ import React from 'react';
|
|||
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
export const SplitByFilters = (props) => {
|
||||
export const SplitByFilters = props => {
|
||||
const { onChange, model, uiRestrictions, indexPattern } = props;
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleSelectChange = createSelectHandler(onChange);
|
||||
|
@ -35,10 +35,9 @@ export const SplitByFilters = (props) => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('group')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.filters.groupByLabel"
|
||||
defaultMessage="Group by"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.splits.filters.groupByLabel" defaultMessage="Group by" />
|
||||
}
|
||||
>
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
|
@ -63,5 +62,5 @@ SplitByFilters.propTypes = {
|
|||
model: PropTypes.object,
|
||||
onChange: PropTypes.func,
|
||||
uiRestrictions: PropTypes.object,
|
||||
indexPatterns: PropTypes.array
|
||||
indexPatterns: PropTypes.array,
|
||||
};
|
||||
|
|
|
@ -19,15 +19,13 @@
|
|||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiComboBox,
|
||||
} from '@elastic/eui';
|
||||
import { EuiComboBox } from '@elastic/eui';
|
||||
import { injectI18n } from '@kbn/i18n/react';
|
||||
import { isGroupByFieldsEnabled } from '../../lib/check_ui_restrictions';
|
||||
|
||||
function GroupBySelectUi(props) {
|
||||
const { intl, uiRestrictions } = props;
|
||||
const modeOptions = ([
|
||||
const modeOptions = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.splits.groupBySelect.modeOptions.everythingLabel',
|
||||
|
@ -36,7 +34,10 @@ function GroupBySelectUi(props) {
|
|||
value: 'everything',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.splits.groupBySelect.modeOptions.filterLabel', defaultMessage: 'Filter' }),
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.splits.groupBySelect.modeOptions.filterLabel',
|
||||
defaultMessage: 'Filter',
|
||||
}),
|
||||
value: 'filter',
|
||||
},
|
||||
{
|
||||
|
@ -47,10 +48,13 @@ function GroupBySelectUi(props) {
|
|||
value: 'filters',
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({ id: 'tsvb.splits.groupBySelect.modeOptions.termsLabel', defaultMessage: 'Terms' }),
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.splits.groupBySelect.modeOptions.termsLabel',
|
||||
defaultMessage: 'Terms',
|
||||
}),
|
||||
value: 'terms',
|
||||
},
|
||||
]).map(field => ({
|
||||
].map(field => ({
|
||||
...field,
|
||||
disabled: !isGroupByFieldsEnabled(field.value, uiRestrictions),
|
||||
}));
|
||||
|
|
|
@ -32,14 +32,21 @@ import {
|
|||
EuiFormRow,
|
||||
EuiFieldNumber,
|
||||
EuiComboBox,
|
||||
EuiFieldText
|
||||
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, uiRestrictions }) => {
|
||||
export const SplitByTermsUI = ({
|
||||
onChange,
|
||||
indexPattern,
|
||||
intl,
|
||||
model: seriesModel,
|
||||
fields,
|
||||
uiRestrictions,
|
||||
}) => {
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleTextChange = createTextHandler(onChange);
|
||||
const handleSelectChange = createSelectHandler(onChange);
|
||||
|
@ -47,21 +54,30 @@ export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesMode
|
|||
const { metrics } = model;
|
||||
const defaultCount = {
|
||||
value: '_count',
|
||||
label: intl.formatMessage({ id: 'tsvb.splits.terms.defaultCountLabel', defaultMessage: 'Doc Count (default)' })
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.splits.terms.defaultCountLabel',
|
||||
defaultMessage: 'Doc Count (default)',
|
||||
}),
|
||||
};
|
||||
const terms = {
|
||||
value: '_key',
|
||||
label: intl.formatMessage({ id: 'tsvb.splits.terms.termsLabel', defaultMessage: 'Terms' })
|
||||
label: intl.formatMessage({ id: 'tsvb.splits.terms.termsLabel', defaultMessage: 'Terms' }),
|
||||
};
|
||||
|
||||
const dirOptions = [
|
||||
{
|
||||
value: 'desc',
|
||||
label: intl.formatMessage({ id: 'tsvb.splits.terms.dirOptions.descendingLabel', defaultMessage: 'Descending' })
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.splits.terms.dirOptions.descendingLabel',
|
||||
defaultMessage: 'Descending',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'asc',
|
||||
label: intl.formatMessage({ id: 'tsvb.splits.terms.dirOptions.ascendingLabel', defaultMessage: 'Ascending' })
|
||||
label: intl.formatMessage({
|
||||
id: 'tsvb.splits.terms.dirOptions.ascendingLabel',
|
||||
defaultMessage: 'Ascending',
|
||||
}),
|
||||
},
|
||||
];
|
||||
const selectedDirectionOption = dirOptions.find(option => {
|
||||
|
@ -76,10 +92,9 @@ export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesMode
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('group')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.terms.groupByLabel"
|
||||
defaultMessage="Group by"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.splits.terms.groupByLabel" defaultMessage="Group by" />
|
||||
}
|
||||
>
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
|
@ -91,11 +106,13 @@ export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesMode
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('by')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.terms.byLabel"
|
||||
defaultMessage="By"
|
||||
description="This labels a field selector allowing the user to chose 'by' which field to group."
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.splits.terms.byLabel"
|
||||
defaultMessage="By"
|
||||
description="This labels a field selector allowing the user to chose 'by' which field to group."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<FieldSelect
|
||||
indexPattern={indexPattern}
|
||||
|
@ -114,23 +131,27 @@ export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesMode
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('include')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.terms.includeLabel"
|
||||
defaultMessage="Include"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.splits.terms.includeLabel" defaultMessage="Include" />
|
||||
}
|
||||
>
|
||||
<EuiFieldText value={model.terms_include} onChange={handleTextChange('terms_include')} />
|
||||
<EuiFieldText
|
||||
value={model.terms_include}
|
||||
onChange={handleTextChange('terms_include')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('exclude')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.terms.excludeLabel"
|
||||
defaultMessage="Exclude"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.splits.terms.excludeLabel" defaultMessage="Exclude" />
|
||||
}
|
||||
>
|
||||
<EuiFieldText value={model.terms_exclude} onChange={handleTextChange('terms_exclude')} />
|
||||
<EuiFieldText
|
||||
value={model.terms_exclude}
|
||||
onChange={handleTextChange('terms_exclude')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
@ -140,13 +161,13 @@ export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesMode
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('top')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.terms.topLabel"
|
||||
defaultMessage="Top"
|
||||
/>)}
|
||||
label={<FormattedMessage id="tsvb.splits.terms.topLabel" defaultMessage="Top" />}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
placeholder={intl.formatMessage({ id: 'tsvb.splits.terms.sizePlaceholder', defaultMessage: 'Size' })}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'tsvb.splits.terms.sizePlaceholder',
|
||||
defaultMessage: 'Size',
|
||||
})}
|
||||
value={Number(model.terms_size)}
|
||||
onChange={handleTextChange('terms_size')}
|
||||
/>
|
||||
|
@ -155,10 +176,9 @@ export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesMode
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('order')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.terms.orderByLabel"
|
||||
defaultMessage="Order by"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.splits.terms.orderByLabel" defaultMessage="Order by" />
|
||||
}
|
||||
>
|
||||
<MetricSelect
|
||||
metrics={metrics}
|
||||
|
@ -173,10 +193,9 @@ export const SplitByTermsUI = ({ onChange, indexPattern, intl, model: seriesMode
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('direction')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.terms.directionLabel"
|
||||
defaultMessage="Direction"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.splits.terms.directionLabel" defaultMessage="Direction" />
|
||||
}
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
|
|
|
@ -40,12 +40,12 @@ describe('src/legacy/core_plugins/metrics/public/components/splits/terms.test.js
|
|||
formatMessage: jest.fn(),
|
||||
},
|
||||
model: {
|
||||
terms_field: 'OriginCityName'
|
||||
terms_field: 'OriginCityName',
|
||||
},
|
||||
onChange: jest.fn(),
|
||||
indexPattern: 'kibana_sample_data_flights',
|
||||
fields: {
|
||||
'kibana_sample_data_flights': [
|
||||
kibana_sample_data_flights: [
|
||||
{
|
||||
aggregatable: true,
|
||||
name: 'OriginCityName',
|
||||
|
@ -53,8 +53,8 @@ describe('src/legacy/core_plugins/metrics/public/components/splits/terms.test.js
|
|||
searchable: true,
|
||||
type: 'string',
|
||||
esTypes: ['keyword'],
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
@ -21,11 +21,18 @@ 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 {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiCode,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
export const SplitUnsupported = (props) => {
|
||||
export const SplitUnsupported = props => {
|
||||
const { onChange, model, uiRestrictions } = props;
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleSelectChange = createSelectHandler(onChange);
|
||||
|
@ -34,10 +41,9 @@ export const SplitUnsupported = (props) => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('group')}
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.splits.everything.groupByLabel"
|
||||
defaultMessage="Group by"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage id="tsvb.splits.everything.groupByLabel" defaultMessage="Group by" />
|
||||
}
|
||||
>
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
|
@ -52,7 +58,7 @@ export const SplitUnsupported = (props) => {
|
|||
<FormattedMessage
|
||||
id="tsvb.unsupportedSplit.splitIsUnsupportedDescription"
|
||||
defaultMessage="Split by {modelType} is unsupported."
|
||||
values={{ modelType: (<EuiCode>{model.split_mode}</EuiCode>) }}
|
||||
values={{ modelType: <EuiCode>{model.split_mode}</EuiCode> }}
|
||||
/>
|
||||
</span>
|
||||
</EuiTitle>
|
||||
|
@ -66,5 +72,3 @@ SplitUnsupported.propTypes = {
|
|||
onChange: PropTypes.func,
|
||||
uiRestrictions: PropTypes.object,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ export class VisEditor extends Component {
|
|||
this.props.vis.updateState();
|
||||
}, VIS_STATE_DEBOUNCE_DELAY);
|
||||
|
||||
isValidKueryQuery = (filterQuery) => {
|
||||
isValidKueryQuery = filterQuery => {
|
||||
if (filterQuery && filterQuery.language === 'kuery') {
|
||||
try {
|
||||
fromKueryExpression(filterQuery.query, { allowLeadingWildcards: queryOptions });
|
||||
|
@ -99,11 +99,12 @@ export class VisEditor extends Component {
|
|||
if (this.props.isEditorMode) {
|
||||
const extractedIndexPatterns = extractIndexPatterns(nextModel);
|
||||
if (!isEqual(this.state.extractedIndexPatterns, extractedIndexPatterns)) {
|
||||
fetchFields(extractedIndexPatterns)
|
||||
.then(visFields => this.setState({
|
||||
fetchFields(extractedIndexPatterns).then(visFields =>
|
||||
this.setState({
|
||||
visFields,
|
||||
extractedIndexPatterns,
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +119,7 @@ export class VisEditor extends Component {
|
|||
this.setState({ dirty: false });
|
||||
};
|
||||
|
||||
handleAutoApplyToggle = (event) => {
|
||||
handleAutoApplyToggle = event => {
|
||||
this.setState({ autoApply: event.target.checked });
|
||||
};
|
||||
|
||||
|
@ -150,7 +151,7 @@ export class VisEditor extends Component {
|
|||
return (
|
||||
<div className="tvbEditor" data-test-subj="tvbVisEditor">
|
||||
<div className="tvbEditor--hideForReporting">
|
||||
<VisPicker model={model} onChange={this.handleChange}/>
|
||||
<VisPicker model={model} onChange={this.handleChange} />
|
||||
</div>
|
||||
<VisEditorVisualization
|
||||
dirty={this.state.dirty}
|
||||
|
|
|
@ -22,7 +22,13 @@ import { get, isEqual } from 'lodash';
|
|||
import { keyCodes, EuiFlexGroup, EuiFlexItem, EuiButton, EuiText, EuiSwitch } from '@elastic/eui';
|
||||
import { getVisualizeLoader } from 'ui/visualize/loader/visualize_loader';
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
import { getInterval, convertIntervalIntoUnit, isIntervalValid, isGteInterval, AUTO_INTERVAL } from './lib/get_interval';
|
||||
import {
|
||||
getInterval,
|
||||
convertIntervalIntoUnit,
|
||||
isIntervalValid,
|
||||
isGteInterval,
|
||||
AUTO_INTERVAL,
|
||||
} from './lib/get_interval';
|
||||
import { PANEL_TYPES } from '../../common/panel_types';
|
||||
|
||||
const MIN_CHART_HEIGHT = 250;
|
||||
|
@ -50,9 +56,9 @@ class VisEditorVisualizationUI extends Component {
|
|||
this.setState({ dragging: false });
|
||||
};
|
||||
|
||||
handleMouseMove = (event) => {
|
||||
handleMouseMove = event => {
|
||||
if (this.state.dragging) {
|
||||
this.setState((prevState) => ({
|
||||
this.setState(prevState => ({
|
||||
height: Math.max(MIN_CHART_HEIGHT, prevState.height + event.movementY),
|
||||
}));
|
||||
}
|
||||
|
@ -66,13 +72,7 @@ class VisEditorVisualizationUI extends Component {
|
|||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
uiState,
|
||||
timeRange,
|
||||
appState,
|
||||
savedObj,
|
||||
onDataChange,
|
||||
} = this.props;
|
||||
const { uiState, timeRange, appState, savedObj, onDataChange } = this.props;
|
||||
|
||||
this._handler = loader.embedVisualizationWithSavedObject(this._visEl.current, savedObj, {
|
||||
listenOnChange: false,
|
||||
|
@ -81,7 +81,7 @@ class VisEditorVisualizationUI extends Component {
|
|||
appState,
|
||||
});
|
||||
|
||||
this._subscription = this._handler.data$.subscribe((data) => {
|
||||
this._subscription = this._handler.data$.subscribe(data => {
|
||||
this.setPanelInterval(data.visData);
|
||||
onDataChange(data);
|
||||
});
|
||||
|
@ -101,11 +101,11 @@ class VisEditorVisualizationUI extends Component {
|
|||
* We use 15px steps to do the scaling and make sure the chart has at least its
|
||||
* defined minimum width (MIN_CHART_HEIGHT).
|
||||
*/
|
||||
onSizeHandleKeyDown = (ev) => {
|
||||
onSizeHandleKeyDown = ev => {
|
||||
const { keyCode } = ev;
|
||||
if (keyCode === keyCodes.UP || keyCode === keyCodes.DOWN) {
|
||||
ev.preventDefault();
|
||||
this.setState((prevState) => {
|
||||
this.setState(prevState => {
|
||||
const newHeight = prevState.height + (keyCode === keyCodes.UP ? -15 : 15);
|
||||
return {
|
||||
height: Math.max(MIN_CHART_HEIGHT, newHeight),
|
||||
|
@ -118,14 +118,16 @@ class VisEditorVisualizationUI extends Component {
|
|||
const type = get(this.props, 'model.type', '');
|
||||
const interval = get(this.props, 'model.interval', AUTO_INTERVAL);
|
||||
|
||||
return [
|
||||
PANEL_TYPES.METRIC,
|
||||
PANEL_TYPES.TOP_N,
|
||||
PANEL_TYPES.GAUGE,
|
||||
PANEL_TYPES.MARKDOWN,
|
||||
PANEL_TYPES.TABLE,
|
||||
].includes(type) && (interval === AUTO_INTERVAL
|
||||
|| isGteInterval(interval) || !isIntervalValid(interval));
|
||||
return (
|
||||
[
|
||||
PANEL_TYPES.METRIC,
|
||||
PANEL_TYPES.TOP_N,
|
||||
PANEL_TYPES.GAUGE,
|
||||
PANEL_TYPES.MARKDOWN,
|
||||
PANEL_TYPES.TABLE,
|
||||
].includes(type) &&
|
||||
(interval === AUTO_INTERVAL || isGteInterval(interval) || !isIntervalValid(interval))
|
||||
);
|
||||
}
|
||||
|
||||
getFormattedPanelInterval() {
|
||||
|
@ -159,14 +161,7 @@ class VisEditorVisualizationUI extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
dirty,
|
||||
autoApply,
|
||||
title,
|
||||
description,
|
||||
onToggleAutoApply,
|
||||
onCommit,
|
||||
} = this.props;
|
||||
const { dirty, autoApply, title, description, onToggleAutoApply, onCommit } = this.props;
|
||||
const style = { height: this.state.height };
|
||||
|
||||
if (this.state.dragging) {
|
||||
|
@ -175,68 +170,81 @@ class VisEditorVisualizationUI extends Component {
|
|||
|
||||
const panelInterval = this.hasShowPanelIntervalValue() && this.getFormattedPanelInterval();
|
||||
|
||||
let applyMessage = (<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.changesSuccessfullyAppliedMessage"
|
||||
defaultMessage="The latest changes have been applied."
|
||||
/>);
|
||||
let applyMessage = (
|
||||
<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.changesSuccessfullyAppliedMessage"
|
||||
defaultMessage="The latest changes have been applied."
|
||||
/>
|
||||
);
|
||||
if (dirty) {
|
||||
applyMessage = (<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.changesHaveNotBeenAppliedMessage"
|
||||
defaultMessage="The changes to this visualization have not been applied."
|
||||
/>);
|
||||
applyMessage = (
|
||||
<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.changesHaveNotBeenAppliedMessage"
|
||||
defaultMessage="The changes to this visualization have not been applied."
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (autoApply) {
|
||||
applyMessage = (<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.changesWillBeAutomaticallyAppliedMessage"
|
||||
defaultMessage="The changes will be automatically applied."
|
||||
/>);
|
||||
applyMessage = (
|
||||
<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.changesWillBeAutomaticallyAppliedMessage"
|
||||
defaultMessage="The changes will be automatically applied."
|
||||
/>
|
||||
);
|
||||
}
|
||||
const applyButton = (
|
||||
<EuiFlexGroup className="tvbEditorVisualization__apply" alignItems="center">
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiSwitch
|
||||
id="tsvbAutoApplyInput"
|
||||
label={(<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.autoApplyLabel"
|
||||
defaultMessage="Auto apply"
|
||||
/>)}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.autoApplyLabel"
|
||||
defaultMessage="Auto apply"
|
||||
/>
|
||||
}
|
||||
checked={autoApply}
|
||||
onChange={onToggleAutoApply}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{panelInterval &&
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText color="default" size="xs">
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.panelInterval"
|
||||
defaultMessage="Interval: {panelInterval}"
|
||||
values={{ panelInterval }}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
}
|
||||
{panelInterval && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText color="default" size="xs">
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.panelInterval"
|
||||
defaultMessage="Interval: {panelInterval}"
|
||||
values={{ panelInterval }}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText color={dirty ? 'default' : 'subdued'} size="xs">
|
||||
<p>
|
||||
{applyMessage}
|
||||
</p>
|
||||
<p>{applyMessage}</p>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
|
||||
{!autoApply &&
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton iconType="play" fill size="s" onClick={onCommit} disabled={!dirty} data-test-subj="applyBtn">
|
||||
<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.applyChangesLabel"
|
||||
defaultMessage="Apply changes"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
}
|
||||
{!autoApply && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
iconType="play"
|
||||
fill
|
||||
size="s"
|
||||
onClick={onCommit}
|
||||
disabled={!dirty}
|
||||
data-test-subj="applyBtn"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="tsvb.visEditorVisualization.applyChangesLabel"
|
||||
defaultMessage="Apply changes"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
|
||||
|
@ -262,7 +270,7 @@ class VisEditorVisualizationUI extends Component {
|
|||
defaultMessage: 'Press up/down to adjust the chart size',
|
||||
})}
|
||||
>
|
||||
<i className="fa fa-ellipsis-h"/>
|
||||
<i className="fa fa-ellipsis-h" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -31,8 +31,8 @@ describe('getVisualizeLoader', () => {
|
|||
const handlerMock = {
|
||||
update: updateStub,
|
||||
data$: {
|
||||
subscribe: () => {}
|
||||
}
|
||||
subscribe: () => {},
|
||||
},
|
||||
};
|
||||
const loaderMock = {
|
||||
embedVisualizationWithSavedObject: () => handlerMock,
|
||||
|
@ -41,16 +41,14 @@ describe('getVisualizeLoader', () => {
|
|||
});
|
||||
|
||||
it('should not call _handler.update until getVisualizeLoader returns _handler', async () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<VisEditorVisualization />
|
||||
);
|
||||
const wrapper = mountWithIntl(<VisEditorVisualization />);
|
||||
|
||||
// Set prop to force DOM change and componentDidUpdate to be triggered
|
||||
wrapper.setProps({
|
||||
timeRange: {
|
||||
from: '2019-03-20T20:35:37.637Z',
|
||||
to: '2019-03-23T18:40:16.486Z'
|
||||
}
|
||||
to: '2019-03-23T18:40:16.486Z',
|
||||
},
|
||||
});
|
||||
|
||||
expect(updateStub).not.toHaveBeenCalled();
|
||||
|
@ -62,8 +60,8 @@ describe('getVisualizeLoader', () => {
|
|||
wrapper.setProps({
|
||||
timeRange: {
|
||||
from: 'now/d',
|
||||
to: 'now/d'
|
||||
}
|
||||
to: 'now/d',
|
||||
},
|
||||
});
|
||||
|
||||
expect(updateStub).toHaveBeenCalled();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue