mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Lens] Improved interval input (#131372)
This commit is contained in:
parent
b7d42ea04c
commit
f2f90ba9fd
5 changed files with 227 additions and 284 deletions
|
@ -8,7 +8,7 @@
|
|||
import React from 'react';
|
||||
import type { DateHistogramIndexPatternColumn } from './date_histogram';
|
||||
import { dateHistogramOperation } from '.';
|
||||
import { shallow } from 'enzyme';
|
||||
import { mount, shallow } from 'enzyme';
|
||||
import { EuiSwitch } from '@elastic/eui';
|
||||
import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks';
|
||||
import type { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from '@kbn/core/public';
|
||||
|
@ -18,6 +18,7 @@ import { dataPluginMock, getCalculateAutoTimeExpression } from '@kbn/data-plugin
|
|||
import { createMockedIndexPattern } from '../../mocks';
|
||||
import type { IndexPatternLayer, IndexPattern } from '../../types';
|
||||
import { getFieldByNameFactory } from '../../pure_helpers';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
const dataStart = dataPluginMock.createStartContract();
|
||||
const unifiedSearchStart = unifiedSearchPluginMock.createStartContract();
|
||||
|
@ -312,8 +313,9 @@ describe('date_histogram', () => {
|
|||
/>
|
||||
);
|
||||
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramValue"]').prop('value')).toEqual(42);
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').prop('value')).toEqual('w');
|
||||
expect(
|
||||
instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('selectedOptions')
|
||||
).toEqual([expect.objectContaining({ label: '42w' })]);
|
||||
});
|
||||
|
||||
it('should render current value for other index pattern', () => {
|
||||
|
@ -348,11 +350,12 @@ describe('date_histogram', () => {
|
|||
/>
|
||||
);
|
||||
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramValue"]').prop('value')).toEqual('');
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').prop('value')).toEqual('d');
|
||||
expect(
|
||||
instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('selectedOptions')
|
||||
).toEqual([expect.objectContaining({ key: 'd' })]);
|
||||
});
|
||||
|
||||
it('should render disabled switch and no time interval control for auto interval', () => {
|
||||
it('should render time interval control set to auto for auto interval', () => {
|
||||
const thirdLayer: IndexPatternLayer = {
|
||||
indexPatternId: '1',
|
||||
columnOrder: ['col1'],
|
||||
|
@ -382,9 +385,9 @@ describe('date_histogram', () => {
|
|||
indexPattern={indexPattern1}
|
||||
/>
|
||||
);
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramValue"]').exists()).toBeFalsy();
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').exists()).toBeFalsy();
|
||||
expect(instance.find(EuiSwitch).at(1).prop('checked')).toBe(false);
|
||||
expect(
|
||||
instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('selectedOptions')
|
||||
).toEqual([expect.objectContaining({ key: 'auto' })]);
|
||||
});
|
||||
|
||||
it('should allow switching to manual interval', () => {
|
||||
|
@ -461,7 +464,7 @@ describe('date_histogram', () => {
|
|||
);
|
||||
instance
|
||||
.find(EuiSwitch)
|
||||
.at(2)
|
||||
.at(1)
|
||||
.simulate('change', {
|
||||
target: { checked: false },
|
||||
});
|
||||
|
@ -502,16 +505,14 @@ describe('date_histogram', () => {
|
|||
indexPattern={{ ...indexPattern1, timeFieldName: undefined }}
|
||||
/>
|
||||
);
|
||||
instance
|
||||
.find(EuiSwitch)
|
||||
.at(1)
|
||||
.simulate('change', {
|
||||
target: { checked: false },
|
||||
});
|
||||
(
|
||||
instance
|
||||
.find('[data-test-subj="lensDateHistogramInterval"]')
|
||||
.prop('onChange') as unknown as (v: Array<{ key: string }>) => void
|
||||
)([{ key: 'auto' }]);
|
||||
expect(updateLayerSpy).toHaveBeenCalled();
|
||||
const newLayer = updateLayerSpy.mock.calls[0][0];
|
||||
expect(newLayer).toHaveProperty('columns.col1.params.ignoreTimeRange', false);
|
||||
expect(newLayer).toHaveProperty('columns.col1.params.interval', 'auto');
|
||||
});
|
||||
|
||||
it('turns off drop partial bucket on tuning off time range ignore', () => {
|
||||
|
@ -560,12 +561,14 @@ describe('date_histogram', () => {
|
|||
currentColumn={layer.columns.col1 as DateHistogramIndexPatternColumn}
|
||||
/>
|
||||
);
|
||||
instance.find('[data-test-subj="lensDateHistogramValue"]').simulate('change', {
|
||||
target: {
|
||||
value: '2',
|
||||
},
|
||||
});
|
||||
expect(updateLayerSpy).toHaveBeenCalledWith(layerWithInterval('1w'));
|
||||
(
|
||||
instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('onCreateOption') as (
|
||||
s: string
|
||||
) => void
|
||||
)('2w');
|
||||
expect(
|
||||
instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('isInvalid')
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should display error if an invalid interval is specified', () => {
|
||||
|
@ -580,7 +583,9 @@ describe('date_histogram', () => {
|
|||
currentColumn={testLayer.columns.col1 as DateHistogramIndexPatternColumn}
|
||||
/>
|
||||
);
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeTruthy();
|
||||
expect(
|
||||
instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('isInvalid')
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not display error if interval value is blank', () => {
|
||||
|
@ -595,7 +600,9 @@ describe('date_histogram', () => {
|
|||
currentColumn={testLayer.columns.col1 as DateHistogramIndexPatternColumn}
|
||||
/>
|
||||
);
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeFalsy();
|
||||
expect(
|
||||
instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('isInvalid')
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should display error if interval value is 0', () => {
|
||||
|
@ -610,12 +617,14 @@ describe('date_histogram', () => {
|
|||
currentColumn={testLayer.columns.col1 as DateHistogramIndexPatternColumn}
|
||||
/>
|
||||
);
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeTruthy();
|
||||
expect(
|
||||
instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('isInvalid')
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should update the unit', () => {
|
||||
it('should update the unit', async () => {
|
||||
const updateLayerSpy = jest.fn();
|
||||
const instance = shallow(
|
||||
const instance = mount(
|
||||
<InlineOptions
|
||||
{...defaultOptions}
|
||||
layer={layer}
|
||||
|
@ -624,19 +633,22 @@ describe('date_histogram', () => {
|
|||
currentColumn={layer.columns.col1 as DateHistogramIndexPatternColumn}
|
||||
/>
|
||||
);
|
||||
instance.find('[data-test-subj="lensDateHistogramUnit"]').simulate('change', {
|
||||
target: {
|
||||
value: 'd',
|
||||
},
|
||||
act(() => {
|
||||
(
|
||||
instance
|
||||
.find('[data-test-subj="lensDateHistogramInterval"]')
|
||||
.at(0)
|
||||
.prop('onCreateOption') as (s: string) => void
|
||||
)('42d');
|
||||
});
|
||||
expect(updateLayerSpy).toHaveBeenCalledWith(layerWithInterval('42d'));
|
||||
expect(updateLayerSpy.mock.calls[0][0](layer)).toEqual(layerWithInterval('42d'));
|
||||
});
|
||||
|
||||
it('should update the value', () => {
|
||||
const updateLayerSpy = jest.fn();
|
||||
const testLayer = layerWithInterval('42d');
|
||||
|
||||
const instance = shallow(
|
||||
const instance = mount(
|
||||
<InlineOptions
|
||||
{...defaultOptions}
|
||||
layer={testLayer}
|
||||
|
@ -645,12 +657,15 @@ describe('date_histogram', () => {
|
|||
currentColumn={testLayer.columns.col1 as DateHistogramIndexPatternColumn}
|
||||
/>
|
||||
);
|
||||
instance.find('[data-test-subj="lensDateHistogramValue"]').simulate('change', {
|
||||
target: {
|
||||
value: '9',
|
||||
},
|
||||
});
|
||||
expect(updateLayerSpy).toHaveBeenCalledWith(layerWithInterval('9d'));
|
||||
act(() =>
|
||||
(
|
||||
instance
|
||||
.find('[data-test-subj="lensDateHistogramInterval"]')
|
||||
.at(0)
|
||||
.prop('onCreateOption') as (s: string) => void
|
||||
)('9d')
|
||||
);
|
||||
expect(updateLayerSpy.mock.calls[0][0](layer)).toEqual(layerWithInterval('9d'));
|
||||
});
|
||||
|
||||
it('should not render options if they are restricted', () => {
|
||||
|
@ -695,7 +710,7 @@ describe('date_histogram', () => {
|
|||
/>
|
||||
);
|
||||
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramValue"]').exists()).toBeFalsy();
|
||||
expect(instance.find('[data-test-subj="lensDateHistogramInterval"]').exists()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should allow the drop of partial buckets', () => {
|
||||
|
@ -735,7 +750,7 @@ describe('date_histogram', () => {
|
|||
target: { checked: true },
|
||||
});
|
||||
expect(updateLayerSpy).toHaveBeenCalled();
|
||||
const newLayer = updateLayerSpy.mock.calls[0][0];
|
||||
const newLayer = updateLayerSpy.mock.calls[0][0](layer);
|
||||
expect(newLayer).toHaveProperty('columns.col1.params.dropPartials', true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,31 +5,27 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
import {
|
||||
EuiBasicTable,
|
||||
EuiCode,
|
||||
EuiFieldNumber,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiComboBox,
|
||||
EuiFormRow,
|
||||
EuiIconTip,
|
||||
EuiSelect,
|
||||
EuiSpacer,
|
||||
EuiSwitch,
|
||||
EuiSwitchEvent,
|
||||
EuiTextColor,
|
||||
} from '@elastic/eui';
|
||||
import {
|
||||
AggFunctionsMapping,
|
||||
AggParamOption,
|
||||
IndexPatternAggRestrictions,
|
||||
search,
|
||||
UI_SETTINGS,
|
||||
} from '@kbn/data-plugin/public';
|
||||
import { extendedBoundsToAst } from '@kbn/data-plugin/common';
|
||||
import { extendedBoundsToAst, intervalOptions } from '@kbn/data-plugin/common';
|
||||
import { buildExpressionFunction } from '@kbn/expressions-plugin/public';
|
||||
import { updateColumnParam } from '../layer_helpers';
|
||||
import { OperationDefinition, ParamEditorProps } from '.';
|
||||
|
@ -184,54 +180,81 @@ export const dateHistogramOperation: OperationDefinition<
|
|||
const intervalIsRestricted =
|
||||
field!.aggregationRestrictions && field!.aggregationRestrictions.date_histogram;
|
||||
|
||||
const interval = parseInterval(currentColumn.params.interval);
|
||||
const [intervalInput, setIntervalInput] = useState(currentColumn.params.interval);
|
||||
const interval = intervalInput === autoInterval ? autoInterval : parseInterval(intervalInput);
|
||||
|
||||
// We force the interval value to 1 if it's empty, since that is the ES behavior,
|
||||
// and the isValidInterval function doesn't handle the empty case properly. Fixing
|
||||
// isValidInterval involves breaking changes in other areas.
|
||||
const isValid = isValidInterval(
|
||||
`${interval.value === '' ? '1' : interval.value}${interval.unit}`,
|
||||
restrictedInterval(field!.aggregationRestrictions)
|
||||
);
|
||||
|
||||
const onChangeAutoInterval = useCallback(
|
||||
(ev: EuiSwitchEvent) => {
|
||||
const { fromDate, toDate } = dateRange;
|
||||
const value = ev.target.checked
|
||||
? data.search.aggs.calculateAutoTimeExpression({ from: fromDate, to: toDate }) || '1h'
|
||||
: autoInterval;
|
||||
updateLayer(
|
||||
updateColumnParam({
|
||||
layer: updateColumnParam({ layer, columnId, paramName: 'interval', value }),
|
||||
columnId,
|
||||
paramName: 'ignoreTimeRange',
|
||||
value: false,
|
||||
})
|
||||
);
|
||||
},
|
||||
[dateRange, data.search.aggs, updateLayer, layer, columnId]
|
||||
);
|
||||
const isValid =
|
||||
(!currentColumn.params.ignoreTimeRange && intervalInput === autoInterval) ||
|
||||
(interval !== autoInterval &&
|
||||
intervalInput !== '' &&
|
||||
isValidInterval(
|
||||
`${interval.value === '' ? '1' : interval.value}${interval.unit}`,
|
||||
restrictedInterval(field!.aggregationRestrictions)
|
||||
));
|
||||
|
||||
const onChangeDropPartialBuckets = useCallback(
|
||||
(ev: EuiSwitchEvent) => {
|
||||
updateLayer(
|
||||
updateLayer((newLayer) =>
|
||||
updateColumnParam({
|
||||
layer,
|
||||
layer: newLayer,
|
||||
columnId,
|
||||
paramName: 'dropPartials',
|
||||
value: ev.target.checked,
|
||||
})
|
||||
);
|
||||
},
|
||||
[columnId, layer, updateLayer]
|
||||
[columnId, updateLayer]
|
||||
);
|
||||
|
||||
const setInterval = (newInterval: typeof interval) => {
|
||||
const isCalendarInterval = calendarOnlyIntervals.has(newInterval.unit);
|
||||
const value = `${isCalendarInterval ? '1' : newInterval.value}${newInterval.unit || 'd'}`;
|
||||
const setInterval = useCallback(
|
||||
(newInterval: typeof interval) => {
|
||||
const isCalendarInterval =
|
||||
newInterval !== autoInterval && calendarOnlyIntervals.has(newInterval.unit);
|
||||
const value =
|
||||
newInterval === autoInterval
|
||||
? autoInterval
|
||||
: `${isCalendarInterval ? '1' : newInterval.value}${newInterval.unit || 'd'}`;
|
||||
|
||||
updateLayer(updateColumnParam({ layer, columnId, paramName: 'interval', value }));
|
||||
};
|
||||
updateLayer((newLayer) =>
|
||||
updateColumnParam({ layer: newLayer, columnId, paramName: 'interval', value })
|
||||
);
|
||||
},
|
||||
[columnId, updateLayer]
|
||||
);
|
||||
|
||||
const options = (intervalOptions || [])
|
||||
.filter((option) => option.val !== autoInterval)
|
||||
.map((option: AggParamOption) => {
|
||||
return { label: option.display, key: option.val };
|
||||
}, []);
|
||||
|
||||
options.unshift({
|
||||
label: i18n.translate('xpack.lens.indexPattern.autoIntervalLabel', {
|
||||
defaultMessage: 'Auto ({interval})',
|
||||
values: {
|
||||
interval:
|
||||
data.search.aggs.calculateAutoTimeExpression({
|
||||
from: dateRange.fromDate,
|
||||
to: dateRange.toDate,
|
||||
}) || '1h',
|
||||
},
|
||||
}),
|
||||
key: autoInterval,
|
||||
});
|
||||
|
||||
const definedOption = options.find((o) => o.key === intervalInput);
|
||||
const selectedOptions = definedOption
|
||||
? [definedOption]
|
||||
: [{ label: intervalInput, key: intervalInput }];
|
||||
|
||||
useEffect(() => {
|
||||
if (isValid && intervalInput !== currentColumn.params.interval) {
|
||||
setInterval(parseInterval(intervalInput));
|
||||
}
|
||||
}, [intervalInput, isValid, currentColumn.params.interval, setInterval]);
|
||||
|
||||
const bindToGlobalTimePickerValue =
|
||||
indexPattern.timeFieldName === field?.name || !currentColumn.params.ignoreTimeRange;
|
||||
|
@ -260,187 +283,122 @@ export const dateHistogramOperation: OperationDefinition<
|
|||
/>
|
||||
</TooltipWrapper>
|
||||
</EuiFormRow>
|
||||
{!intervalIsRestricted && (
|
||||
<EuiFormRow display="rowCompressed" hasChildLabel={false}>
|
||||
<EuiSwitch
|
||||
label={i18n.translate('xpack.lens.indexPattern.dateHistogram.autoInterval', {
|
||||
defaultMessage: 'Customize time interval',
|
||||
})}
|
||||
checked={currentColumn.params.interval !== autoInterval}
|
||||
onChange={onChangeAutoInterval}
|
||||
compressed
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.lens.indexPattern.dateHistogram.minimumInterval', {
|
||||
defaultMessage: 'Minimum interval',
|
||||
})}
|
||||
fullWidth
|
||||
display="rowCompressed"
|
||||
helpText={i18n.translate('xpack.lens.indexPattern.dateHistogram.selectOptionHelpText', {
|
||||
defaultMessage:
|
||||
'Select an option or create a custom value. Examples: 30s, 20m, 24h, 2d, 1w, 1M',
|
||||
})}
|
||||
isInvalid={!isValid}
|
||||
error={
|
||||
!isValid &&
|
||||
i18n.translate('xpack.lens.indexPattern.dateHistogram.invalidInterval', {
|
||||
defaultMessage:
|
||||
"Please pick a valid interval. It's not possible to use multiple weeks, months or years as interval.",
|
||||
})
|
||||
}
|
||||
>
|
||||
{intervalIsRestricted ? (
|
||||
<FormattedMessage
|
||||
id="xpack.lens.indexPattern.dateHistogram.restrictedInterval"
|
||||
defaultMessage="Interval fixed to {intervalValue} due to aggregation restrictions."
|
||||
values={{
|
||||
intervalValue: restrictedInterval(field!.aggregationRestrictions),
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
)}
|
||||
{currentColumn.params.interval !== autoInterval && (
|
||||
<>
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.lens.indexPattern.dateHistogram.minimumInterval', {
|
||||
defaultMessage: 'Minimum interval',
|
||||
})}
|
||||
fullWidth
|
||||
display="rowCompressed"
|
||||
>
|
||||
{intervalIsRestricted ? (
|
||||
<FormattedMessage
|
||||
id="xpack.lens.indexPattern.dateHistogram.restrictedInterval"
|
||||
defaultMessage="Interval fixed to {intervalValue} due to aggregation restrictions."
|
||||
values={{
|
||||
intervalValue: restrictedInterval(field!.aggregationRestrictions),
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<EuiFlexGroup responsive={false} gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFieldNumber
|
||||
compressed
|
||||
data-test-subj="lensDateHistogramValue"
|
||||
value={
|
||||
typeof interval.value === 'number' || interval.value === ''
|
||||
? interval.value
|
||||
: parseInt(interval.value, 10)
|
||||
}
|
||||
disabled={calendarOnlyIntervals.has(interval.unit)}
|
||||
isInvalid={!isValid}
|
||||
onChange={(e) => {
|
||||
const newInterval = {
|
||||
...interval,
|
||||
value: e.target.value,
|
||||
};
|
||||
setInterval(newInterval);
|
||||
}}
|
||||
step={1}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiSelect
|
||||
compressed
|
||||
data-test-subj="lensDateHistogramUnit"
|
||||
value={interval.unit}
|
||||
onChange={(e) => {
|
||||
const newInterval = {
|
||||
...interval,
|
||||
unit: e.target.value,
|
||||
};
|
||||
setInterval(newInterval);
|
||||
}}
|
||||
isInvalid={!isValid}
|
||||
options={[
|
||||
{
|
||||
value: 'ms',
|
||||
text: i18n.translate(
|
||||
'xpack.lens.indexPattern.dateHistogram.milliseconds',
|
||||
{
|
||||
defaultMessage: 'milliseconds',
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 's',
|
||||
text: i18n.translate('xpack.lens.indexPattern.dateHistogram.seconds', {
|
||||
defaultMessage: 'seconds',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'm',
|
||||
text: i18n.translate('xpack.lens.indexPattern.dateHistogram.minutes', {
|
||||
defaultMessage: 'minutes',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'h',
|
||||
text: i18n.translate('xpack.lens.indexPattern.dateHistogram.hours', {
|
||||
defaultMessage: 'hours',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'd',
|
||||
text: i18n.translate('xpack.lens.indexPattern.dateHistogram.days', {
|
||||
defaultMessage: 'days',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'w',
|
||||
text: i18n.translate('xpack.lens.indexPattern.dateHistogram.week', {
|
||||
defaultMessage: 'week',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'M',
|
||||
text: i18n.translate('xpack.lens.indexPattern.dateHistogram.month', {
|
||||
defaultMessage: 'month',
|
||||
}),
|
||||
},
|
||||
// Quarterly intervals appear to be unsupported by esaggs
|
||||
{
|
||||
value: 'y',
|
||||
text: i18n.translate('xpack.lens.indexPattern.dateHistogram.year', {
|
||||
defaultMessage: 'year',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
{!isValid && (
|
||||
<>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiTextColor color="danger" data-test-subj="lensDateHistogramError">
|
||||
{i18n.translate('xpack.lens.indexPattern.invalidInterval', {
|
||||
defaultMessage: 'Invalid interval value',
|
||||
})}
|
||||
</EuiTextColor>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</EuiFormRow>
|
||||
<EuiFormRow display="rowCompressed" hasChildLabel={false}>
|
||||
<EuiSwitch
|
||||
label={
|
||||
<>
|
||||
{i18n.translate(
|
||||
'xpack.lens.indexPattern.dateHistogram.bindToGlobalTimePicker',
|
||||
{
|
||||
defaultMessage: 'Bind to global time picker',
|
||||
}
|
||||
)}{' '}
|
||||
<EuiIconTip
|
||||
color="subdued"
|
||||
content={i18n.translate(
|
||||
'xpack.lens.indexPattern.dateHistogram.globalTimePickerHelp',
|
||||
{
|
||||
defaultMessage:
|
||||
"Filter the selected field by the global time picker in the top right. This setting can't be turned off for the default time field of the current data view.",
|
||||
}
|
||||
)}
|
||||
iconProps={{
|
||||
className: 'eui-alignTop',
|
||||
}}
|
||||
position="top"
|
||||
size="s"
|
||||
type="questionInCircle"
|
||||
/>
|
||||
</>
|
||||
}
|
||||
disabled={indexPattern.timeFieldName === field?.name}
|
||||
checked={bindToGlobalTimePickerValue}
|
||||
onChange={() => {
|
||||
) : (
|
||||
<EuiComboBox
|
||||
compressed
|
||||
fullWidth={true}
|
||||
data-test-subj="lensDateHistogramInterval"
|
||||
isInvalid={!isValid}
|
||||
onChange={(opts) => {
|
||||
const newValue = opts.length ? opts[0].key! : '';
|
||||
setIntervalInput(newValue);
|
||||
if (newValue === autoInterval && currentColumn.params.ignoreTimeRange) {
|
||||
updateLayer(
|
||||
updateColumnParam({
|
||||
layer,
|
||||
columnId,
|
||||
paramName: 'ignoreTimeRange',
|
||||
value: !currentColumn.params.ignoreTimeRange,
|
||||
value: false,
|
||||
})
|
||||
);
|
||||
}}
|
||||
compressed
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</>
|
||||
)}
|
||||
}
|
||||
}}
|
||||
onCreateOption={(customValue: string) => setIntervalInput(customValue.trim())}
|
||||
options={options}
|
||||
selectedOptions={selectedOptions}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
placeholder={i18n.translate(
|
||||
'xpack.lens.indexPattern.dateHistogram.selectIntervalPlaceholder',
|
||||
{
|
||||
defaultMessage: 'Select an interval',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</EuiFormRow>
|
||||
<EuiFormRow display="rowCompressed" hasChildLabel={false}>
|
||||
<EuiSwitch
|
||||
label={
|
||||
<>
|
||||
{i18n.translate('xpack.lens.indexPattern.dateHistogram.bindToGlobalTimePicker', {
|
||||
defaultMessage: 'Bind to global time picker',
|
||||
})}{' '}
|
||||
<EuiIconTip
|
||||
color="subdued"
|
||||
content={i18n.translate(
|
||||
'xpack.lens.indexPattern.dateHistogram.globalTimePickerHelp',
|
||||
{
|
||||
defaultMessage:
|
||||
"Filter the selected field by the global time picker in the top right. This setting can't be turned off for the default time field of the current data view.",
|
||||
}
|
||||
)}
|
||||
iconProps={{
|
||||
className: 'eui-alignTop',
|
||||
}}
|
||||
position="top"
|
||||
size="s"
|
||||
type="questionInCircle"
|
||||
/>
|
||||
</>
|
||||
}
|
||||
disabled={indexPattern.timeFieldName === field?.name}
|
||||
checked={bindToGlobalTimePickerValue}
|
||||
onChange={() => {
|
||||
let newLayer = updateColumnParam({
|
||||
layer,
|
||||
columnId,
|
||||
paramName: 'ignoreTimeRange',
|
||||
value: !currentColumn.params.ignoreTimeRange,
|
||||
});
|
||||
if (
|
||||
!currentColumn.params.ignoreTimeRange &&
|
||||
currentColumn.params.interval === autoInterval
|
||||
) {
|
||||
const newFixedInterval =
|
||||
data.search.aggs.calculateAutoTimeExpression({
|
||||
from: dateRange.fromDate,
|
||||
to: dateRange.toDate,
|
||||
}) || '1h';
|
||||
newLayer = updateColumnParam({
|
||||
layer: newLayer,
|
||||
columnId,
|
||||
paramName: 'interval',
|
||||
value: newFixedInterval,
|
||||
});
|
||||
setIntervalInput(newFixedInterval);
|
||||
}
|
||||
updateLayer(newLayer);
|
||||
}}
|
||||
compressed
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow display="rowCompressed" hasChildLabel={false}>
|
||||
<EuiSwitch
|
||||
label={i18n.translate('xpack.lens.indexPattern.dateHistogram.includeEmptyRows', {
|
||||
|
|
|
@ -440,27 +440,18 @@
|
|||
"xpack.lens.indexPattern.dateHistogram.autoAdvancedExplanation": "L'intervalle suit cette logique :",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoBasicExplanation": "L'histogramme des dates automatique divise un champ de données en groupes par intervalle.",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoBoundHeader": "Intervalle cible mesuré",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoInterval": "Personnaliser l'intervalle de temps",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoIntervalHeader": "Intervalle utilisé",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoLongerExplanation": "Pour choisir l'intervalle, Lens divise la plage temporelle spécifiée par le paramètre {targetBarSetting}. Lens calcule le meilleur intervalle pour vos données. Par exemple 30m, 1h et 12. Le nombre maximal de barres est défini par la valeur {maxBarSetting}.",
|
||||
"xpack.lens.indexPattern.dateHistogram.bindToGlobalTimePicker": "Lier au sélecteur d'heure globale",
|
||||
"xpack.lens.indexPattern.dateHistogram.days": "jours",
|
||||
"xpack.lens.indexPattern.dateHistogram.dropPartialBuckets": "Abandonner les compartiments partiels",
|
||||
"xpack.lens.indexPattern.dateHistogram.dropPartialBucketsHelp": "L’abandon des compartiments partiels est désactivé, car ceux-ci ne peuvent être calculés que pour un champ temporel lié au sélecteur d’heure globale en haut à droite.",
|
||||
"xpack.lens.indexPattern.dateHistogram.globalTimePickerHelp": "Filtrez le champ sélectionné à l’aide du sélecteur d’heure globale en haut à droite. Ce paramètre ne peut pas être désactivé pour le champ temporel par défaut de la vue de données actuelle.",
|
||||
"xpack.lens.indexPattern.dateHistogram.hours": "heures",
|
||||
"xpack.lens.indexPattern.dateHistogram.includeEmptyRows": "Inclure les lignes vides",
|
||||
"xpack.lens.indexPattern.dateHistogram.milliseconds": "millisecondes",
|
||||
"xpack.lens.indexPattern.dateHistogram.minimumInterval": "Intervalle minimal",
|
||||
"xpack.lens.indexPattern.dateHistogram.minutes": "minutes",
|
||||
"xpack.lens.indexPattern.dateHistogram.month": "mois",
|
||||
"xpack.lens.indexPattern.dateHistogram.moreThanYear": "Plus d'un an",
|
||||
"xpack.lens.indexPattern.dateHistogram.restrictedInterval": "Intervalle fixé à {intervalValue} en raison de restrictions d'agrégation.",
|
||||
"xpack.lens.indexPattern.dateHistogram.seconds": "secondes",
|
||||
"xpack.lens.indexPattern.dateHistogram.titleHelp": "Fonctionnement de l'histogramme des dates automatique",
|
||||
"xpack.lens.indexPattern.dateHistogram.upTo": "Jusqu'à",
|
||||
"xpack.lens.indexPattern.dateHistogram.week": "semaine",
|
||||
"xpack.lens.indexPattern.dateHistogram.year": "an",
|
||||
"xpack.lens.indexPattern.dateHistogramTimeShift": "Dans un calque unique, vous ne pouvez pas combiner un décalage de plage temporelle précédent avec des histogrammes de dates. Utilisez une durée de décalage temporel explicite dans \"{column}\" ou remplacez l’histogramme de dates.",
|
||||
"xpack.lens.indexPattern.decimalPlacesLabel": "Décimales",
|
||||
"xpack.lens.indexPattern.defaultFormatLabel": "Par défaut",
|
||||
|
@ -537,7 +528,6 @@
|
|||
"xpack.lens.indexPattern.incompleteOperation": "(incomplet)",
|
||||
"xpack.lens.indexPattern.intervals": "Intervalles",
|
||||
"xpack.lens.indexPattern.invalidFieldLabel": "Champ non valide. Vérifiez votre vue de données ou choisissez un autre champ.",
|
||||
"xpack.lens.indexPattern.invalidInterval": "Valeur d'intervalle non valide",
|
||||
"xpack.lens.indexPattern.invalidOperationLabel": "Ce champ ne fonctionne pas avec la fonction sélectionnée.",
|
||||
"xpack.lens.indexPattern.invalidReferenceConfiguration": "La dimension \"{dimensionLabel}\" n'est pas configurée correctement",
|
||||
"xpack.lens.indexPattern.invalidTimeShift": "Décalage non valide. Entrez un entier positif suivi par l'une des unités suivantes : s, m, h, d, w, M, y. Par exemple, 3h pour 3 heures",
|
||||
|
|
|
@ -442,27 +442,18 @@
|
|||
"xpack.lens.indexPattern.dateHistogram.autoAdvancedExplanation": "間隔は次のロジックに従います。",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoBasicExplanation": "自動日付ヒストグラムは、間隔でデータフィールドをバケットに分割します。",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoBoundHeader": "対象間隔の測定",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoInterval": "時間範囲のカスタマイズ",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoIntervalHeader": "使用される間隔",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoLongerExplanation": "間隔を選択するには、Lensは指定された時間範囲を{targetBarSetting}設定で除算します。Lensはデータに最適な間隔を計算します。たとえば、30分、1時間、12です。棒の最大数は{maxBarSetting}値で設定します。",
|
||||
"xpack.lens.indexPattern.dateHistogram.bindToGlobalTimePicker": "グローバル時刻ピッカーにバインド",
|
||||
"xpack.lens.indexPattern.dateHistogram.days": "日",
|
||||
"xpack.lens.indexPattern.dateHistogram.dropPartialBuckets": "不完全なバケットをドロップ",
|
||||
"xpack.lens.indexPattern.dateHistogram.dropPartialBucketsHelp": "不完全なバケットのドロップは無効です。これらは、右上のグローバル時刻ピッカーにバインドされた時刻フィールドでのみ計算できます。",
|
||||
"xpack.lens.indexPattern.dateHistogram.globalTimePickerHelp": "右上のグローバル時刻ピッカーで選択したフィールドをフィルタリングします。現在のデータビューのデフォルト時刻フィールドではこの設定をオンにできません。",
|
||||
"xpack.lens.indexPattern.dateHistogram.hours": "時間",
|
||||
"xpack.lens.indexPattern.dateHistogram.includeEmptyRows": "空の行を含める",
|
||||
"xpack.lens.indexPattern.dateHistogram.milliseconds": "ミリ秒",
|
||||
"xpack.lens.indexPattern.dateHistogram.minimumInterval": "最低間隔",
|
||||
"xpack.lens.indexPattern.dateHistogram.minutes": "分",
|
||||
"xpack.lens.indexPattern.dateHistogram.month": "月",
|
||||
"xpack.lens.indexPattern.dateHistogram.moreThanYear": "1年を超える",
|
||||
"xpack.lens.indexPattern.dateHistogram.restrictedInterval": "集約の制限により間隔は {intervalValue} に固定されています。",
|
||||
"xpack.lens.indexPattern.dateHistogram.seconds": "秒",
|
||||
"xpack.lens.indexPattern.dateHistogram.titleHelp": "自動日付ヒストグラムの仕組み",
|
||||
"xpack.lens.indexPattern.dateHistogram.upTo": "最大",
|
||||
"xpack.lens.indexPattern.dateHistogram.week": "週",
|
||||
"xpack.lens.indexPattern.dateHistogram.year": "年",
|
||||
"xpack.lens.indexPattern.dateHistogramTimeShift": "単一のレイヤーでは、前の時間範囲シフトと日付ヒストグラムを結合できません。\"{column}\"で明示的な時間シフト期間を使用するか、日付ヒストグラムを置換してください。",
|
||||
"xpack.lens.indexPattern.decimalPlacesLabel": "小数点以下",
|
||||
"xpack.lens.indexPattern.defaultFormatLabel": "デフォルト",
|
||||
|
@ -539,7 +530,6 @@
|
|||
"xpack.lens.indexPattern.incompleteOperation": "(未完了)",
|
||||
"xpack.lens.indexPattern.intervals": "間隔",
|
||||
"xpack.lens.indexPattern.invalidFieldLabel": "無効なフィールドです。データビューを確認するか、別のフィールドを選択してください。",
|
||||
"xpack.lens.indexPattern.invalidInterval": "無効な間隔値",
|
||||
"xpack.lens.indexPattern.invalidOperationLabel": "選択した関数はこのフィールドで動作しません。",
|
||||
"xpack.lens.indexPattern.invalidReferenceConfiguration": "ディメンション\"{dimensionLabel}\"の構成が正しくありません",
|
||||
"xpack.lens.indexPattern.invalidTimeShift": "無効な時間シフトです。正の整数の後に単位s、m、h、d、w、M、yのいずれかを入力します。例:3時間は3hです",
|
||||
|
|
|
@ -447,27 +447,18 @@
|
|||
"xpack.lens.indexPattern.dateHistogram.autoAdvancedExplanation": "时间间隔遵循以下逻辑:",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoBasicExplanation": "自动日期直方图按时间间隔将数据字段拆分为桶。",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoBoundHeader": "已度量目标时间间隔",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoInterval": "定制时间间隔",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoIntervalHeader": "已用时间间隔",
|
||||
"xpack.lens.indexPattern.dateHistogram.autoLongerExplanation": "要选择时间间隔,Lens 按 {targetBarSetting} 设置分割指定的时间范围。Lens 为您的数据计算最佳时间间隔。例如 30m、1h 和 12。最大条形数由 {maxBarSetting} 值设置。",
|
||||
"xpack.lens.indexPattern.dateHistogram.bindToGlobalTimePicker": "绑定到全局时间选取器",
|
||||
"xpack.lens.indexPattern.dateHistogram.days": "天",
|
||||
"xpack.lens.indexPattern.dateHistogram.dropPartialBuckets": "丢弃部分存储桶",
|
||||
"xpack.lens.indexPattern.dateHistogram.dropPartialBucketsHelp": "禁止丢弃部分存储桶,因为只可以为绑定到右上角的全局时间选取器的时间字段计算这些存储桶。",
|
||||
"xpack.lens.indexPattern.dateHistogram.globalTimePickerHelp": "按右上角的全局时间选取器筛选选定字段。不能对当前数据视图的默认时间字段关闭此设置。",
|
||||
"xpack.lens.indexPattern.dateHistogram.hours": "小时",
|
||||
"xpack.lens.indexPattern.dateHistogram.includeEmptyRows": "包括空行",
|
||||
"xpack.lens.indexPattern.dateHistogram.milliseconds": "毫秒",
|
||||
"xpack.lens.indexPattern.dateHistogram.minimumInterval": "最小时间间隔",
|
||||
"xpack.lens.indexPattern.dateHistogram.minutes": "分钟",
|
||||
"xpack.lens.indexPattern.dateHistogram.month": "个月",
|
||||
"xpack.lens.indexPattern.dateHistogram.moreThanYear": "1 年以上",
|
||||
"xpack.lens.indexPattern.dateHistogram.restrictedInterval": "由于聚合限制,时间间隔固定为 {intervalValue}。",
|
||||
"xpack.lens.indexPattern.dateHistogram.seconds": "秒",
|
||||
"xpack.lens.indexPattern.dateHistogram.titleHelp": "自动日期直方图的工作原理",
|
||||
"xpack.lens.indexPattern.dateHistogram.upTo": "最多",
|
||||
"xpack.lens.indexPattern.dateHistogram.week": "周",
|
||||
"xpack.lens.indexPattern.dateHistogram.year": "年",
|
||||
"xpack.lens.indexPattern.dateHistogramTimeShift": "在单个图层中,您无法组合上一时间范围偏移与 Date Histogram。在“{column}”中使用显式时间偏移持续时间,或替换 Date Histogram。",
|
||||
"xpack.lens.indexPattern.decimalPlacesLabel": "小数",
|
||||
"xpack.lens.indexPattern.defaultFormatLabel": "默认",
|
||||
|
@ -544,7 +535,6 @@
|
|||
"xpack.lens.indexPattern.incompleteOperation": "(不完整)",
|
||||
"xpack.lens.indexPattern.intervals": "时间间隔",
|
||||
"xpack.lens.indexPattern.invalidFieldLabel": "字段无效。检查数据视图或选取其他字段。",
|
||||
"xpack.lens.indexPattern.invalidInterval": "时间间隔值无效",
|
||||
"xpack.lens.indexPattern.invalidOperationLabel": "此字段不适用于选定函数。",
|
||||
"xpack.lens.indexPattern.invalidReferenceConfiguration": "维度“{dimensionLabel}”配置不正确",
|
||||
"xpack.lens.indexPattern.invalidTimeShift": "时间偏移无效。输入正整数数量,后跟以下单位之一:s、m、h、d、w、M、y。例如,3h 表示 3 小时",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue