Skip to content

Commit

Permalink
Auto interval on date histogram is getting displayed as timestamp per… (
Browse files Browse the repository at this point in the history
#59171) (#61992)

* Auto interval on date histogram is getting displayed as timestamp per 0 milliseconds when x-axis bucket is collapsed

Closes #57822

* Fixed incorrect interval label displaying while scaling the chart.

* Updated agg.test.tsx snapshot

* Got rid of context and refactored agg hooks

* Fixed agg.type.name check

* Added functional tests to cover the date histogram interval editing

* Fixed some expected values in tests

* Updated some test cases

* Added a new visualization to visualize archive

* Added testSubjects service to replace find where possible

* Updated tests to match updated behavior

Co-authored-by: Elastic Machine <[email protected]>

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
DianaDerevyankina and elasticmachine authored Mar 31, 2020
1 parent 30e40cc commit 0d50ea3
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import { AGGS_ACTION_KEYS, AggsAction } from './agg_group_state';
import { RowsOrColumnsControl } from './controls/rows_or_columns';
import { RadiusRatioOptionControl } from './controls/radius_ratio_option';
import { getSchemaByName } from '../schemas';
import { TimeRange } from '../../../../../plugins/data/public';
import { buildAggDescription } from './agg_params_helper';

export interface DefaultEditorAggProps extends DefaultEditorAggCommonProps {
agg: IAggConfig;
Expand All @@ -46,6 +48,7 @@ export interface DefaultEditorAggProps extends DefaultEditorAggCommonProps {
isLastBucket: boolean;
isRemovable: boolean;
setAggsState: React.Dispatch<AggsAction>;
timeRange?: TimeRange;
}

function DefaultEditorAgg({
Expand All @@ -69,6 +72,7 @@ function DefaultEditorAgg({
removeAgg,
setAggsState,
schemas,
timeRange,
}: DefaultEditorAggProps) {
const [isEditorOpen, setIsEditorOpen] = useState((agg as any).brandNew);
const [validState, setValidState] = useState(true);
Expand Down Expand Up @@ -103,18 +107,15 @@ function DefaultEditorAgg({
}
}

// A description of the aggregation, for displaying in the collapsed agg header
let aggDescription = '';
const [aggDescription, setAggDescription] = useState(buildAggDescription(agg));

if (agg.type && agg.type.makeLabel) {
try {
aggDescription = agg.type.makeLabel(agg);
} catch (e) {
// Date Histogram's `makeLabel` implementation invokes 'write' method for each param, including interval's 'write',
// which throws an error when interval is undefined.
aggDescription = '';
// This useEffect is required to update the timeRange value and initiate rerender to keep labels up to date (Issue #57822).
useEffect(() => {
if (timeRange && aggName === 'date_histogram') {
agg.aggConfigs.setTimeRange(timeRange);
}
}
setAggDescription(buildAggDescription(agg));
}, [agg, aggName, timeRange]);

useEffect(() => {
if (isLastBucketAgg && ['date_histogram', 'histogram'].includes(aggName)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ import {
} from './agg_group_helper';
import { aggGroupReducer, initAggsState, AGGS_ACTION_KEYS } from './agg_group_state';
import { Schema, getSchemasByGroup } from '../schemas';
import { TimeRange } from '../../../../../plugins/data/public';

export interface DefaultEditorAggGroupProps extends DefaultEditorAggCommonProps {
schemas: Schema[];
addSchema: AddSchema;
reorderAggs: ReorderAggs;
setValidity(modelName: string, value: boolean): void;
setTouched(isTouched: boolean): void;
timeRange?: TimeRange;
}

function DefaultEditorAggGroup({
Expand All @@ -67,6 +69,7 @@ function DefaultEditorAggGroup({
reorderAggs,
setTouched,
setValidity,
timeRange,
}: DefaultEditorAggGroupProps) {
const groupNameLabel = (search.aggs.aggGroupNamesMap() as any)[groupName];
// e.g. buckets can have no aggs
Expand Down Expand Up @@ -185,6 +188,7 @@ function DefaultEditorAggGroup({
removeAgg={removeAgg}
setAggsState={setAggsState}
schemas={schemas}
timeRange={timeRange}
/>
)}
</EuiDraggable>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,17 @@ function isInvalidParamsTouched(
return invalidParams.every(param => param.touched);
}

export { getAggParamsToRender, getAggTypeOptions, isInvalidParamsTouched };
function buildAggDescription(agg: IAggConfig) {
let description = '';
if (agg.type && agg.type.makeLabel) {
try {
description = agg.type.makeLabel(agg);
} catch (e) {
// Date Histogram's `makeLabel` implementation invokes 'write' method for each param, including interval's 'write',
// which throws an error when interval is undefined.
}
}
return description;
}

export { getAggParamsToRender, getAggTypeOptions, isInvalidParamsTouched, buildAggDescription };
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function validateInterval(
timeBase?: string
) {
if (definedOption) {
return { isValid: true };
return { isValid: true, interval: agg.buckets?.getInterval() };
}

if (!value) {
Expand Down Expand Up @@ -131,7 +131,7 @@ function TimeIntervalParamEditor({

const scaledHelpText =
interval && interval.scaled ? (
<strong className="eui-displayBlock">
<strong data-test-subj="currentlyScaledText" className="eui-displayBlock">
<FormattedMessage
id="visDefaultEditor.controls.timeInterval.scaledHelpText"
defaultMessage="Currently scaled to {bucketDescription}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
} from './state';
import { AddSchema, ReorderAggs, DefaultEditorAggCommonProps } from '../agg_common_props';
import { ISchemas } from '../../schemas';
import { TimeRange } from '../../../../../../plugins/data/public';
import { EditorVisState } from './state/reducers';

export interface DefaultEditorDataTabProps {
Expand All @@ -51,6 +52,7 @@ export interface DefaultEditorDataTabProps {
setTouched(isTouched: boolean): void;
setValidity(modelName: string, value: boolean): void;
setStateValue: DefaultEditorAggCommonProps['setStateParamValue'];
timeRange: TimeRange;
}

function DefaultEditorDataTab({
Expand All @@ -62,6 +64,7 @@ function DefaultEditorDataTab({
setTouched,
setValidity,
setStateValue,
timeRange,
}: DefaultEditorDataTabProps) {
const lastParentPipelineAgg = useMemo(
() =>
Expand Down Expand Up @@ -128,6 +131,7 @@ function DefaultEditorDataTab({
<DefaultEditorAggGroup
groupName={AggGroupNames.Buckets}
schemas={schemas.buckets}
timeRange={timeRange}
{...commonProps}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { PersistedState } from '../../../../../../plugins/visualizations/public'
import { SavedSearch } from '../../../../../../plugins/discover/public';
import { AggGroupNames } from '../../../../../../plugins/data/public';
import { getSchemasByGroup } from '../../schemas';
import { TimeRange } from '../../../../../../plugins/data/public';

interface DefaultEditorSideBarProps {
isCollapsed: boolean;
Expand All @@ -43,6 +44,7 @@ interface DefaultEditorSideBarProps {
isLinkedSearch: boolean;
eventEmitter: EventEmitter;
savedSearch?: SavedSearch;
timeRange: TimeRange;
}

function DefaultEditorSideBar({
Expand All @@ -54,6 +56,7 @@ function DefaultEditorSideBar({
isLinkedSearch,
eventEmitter,
savedSearch,
timeRange,
}: DefaultEditorSideBarProps) {
const [selectedTab, setSelectedTab] = useState(optionTabs[0].name);
const [isDirty, setDirty] = useState(false);
Expand Down Expand Up @@ -214,6 +217,7 @@ function DefaultEditorSideBar({
<Editor
isTabSelected={isTabSelected}
{...(name === 'data' ? dataTabProps : optionTabProps)}
timeRange={timeRange}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ function DefaultEditor({
uiState={uiState}
isLinkedSearch={linked}
savedSearch={savedSearch}
timeRange={timeRange}
eventEmitter={eventEmitter}
/>
</Panel>
Expand Down
71 changes: 71 additions & 0 deletions test/functional/apps/visualize/_area_chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -554,5 +554,76 @@ export default function({ getService, getPageObjects }) {
});
});
});

describe('date histogram interval', () => {
before(async () => {
await PageObjects.visualize.loadSavedVisualization('Visualization AreaChart');
await PageObjects.visChart.waitForVisualization();
});

beforeEach(async () => {
const fromTime = 'Sep 20, 2015 @ 00:00:00.000';
const toTime = 'Sep 20, 2015 @ 23:30:00.000';
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
});

it('should update collapsed accordion label when time range is changed', async () => {
const accordionLabel = await find.byCssSelector(
'[data-test-subj="visEditorAggAccordion2"] .visEditorSidebar__aggGroupAccordionButtonContent'
);
let accordionLabelText = await accordionLabel.getVisibleText();
expect(accordionLabelText).to.include.string('per 30 minutes');
const fromTime = 'Sep 20, 2015 @ 08:30:00.000';
const toTime = 'Sep 20, 2015 @ 23:30:00.000';
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
accordionLabelText = await accordionLabel.getVisibleText();
expect(accordionLabelText).to.include.string('per 10 minutes');
});

describe('expanded accordion', () => {
before(async () => await PageObjects.visEditor.toggleAccordion('visEditorAggAccordion2'));

it('should update label inside the opened accordion when scaled to milliseconds', async () => {
const isHelperScaledLabelExists = await find.existsByCssSelector(
'[data-test-subj="currentlyScaledText"]'
);
expect(isHelperScaledLabelExists).to.be(false);
await PageObjects.visEditor.setInterval('Millisecond');
const helperScaledLabelText = await testSubjects.getVisibleText('currentlyScaledText');
expect(helperScaledLabelText).to.include.string('to 10 minutes');
});

it('should display updated scaled label text after time range is changed', async () => {
await PageObjects.visEditor.setInterval('Millisecond');
const isHelperScaledLabelExists = await find.existsByCssSelector(
'[data-test-subj="currentlyScaledText"]'
);
expect(isHelperScaledLabelExists).to.be(true);
let helperScaledLabelText = await testSubjects.getVisibleText('currentlyScaledText');
expect(helperScaledLabelText).to.include.string('to 10 minutes');
const fromTime = 'Sep 20, 2015 @ 22:30:00.000';
const toTime = 'Sep 20, 2015 @ 23:30:00.000';
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
helperScaledLabelText = await testSubjects.getVisibleText('currentlyScaledText');
expect(helperScaledLabelText).to.include.string('to 30 seconds');
});

it('should update scaled label text after custom interval is set and time range is changed', async () => {
await PageObjects.visEditor.setInterval('10s', { type: 'custom' });
await testSubjects.clickWhenNotDisabled('visualizeEditorRenderButton');
const isHelperScaledLabelExists = await find.existsByCssSelector(
'[data-test-subj="currentlyScaledText"]'
);
expect(isHelperScaledLabelExists).to.be(true);
let helperScaledLabelText = await testSubjects.getVisibleText('currentlyScaledText');
expect(helperScaledLabelText).to.include.string('to 10 minutes');
const fromTime = 'Sep 20, 2015 @ 21:30:00.000';
const toTime = 'Sep 20, 2015 @ 23:30:00.000';
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
helperScaledLabelText = await testSubjects.getVisibleText('currentlyScaledText');
expect(helperScaledLabelText).to.include.string('to minute');
});
});
});
});
}
21 changes: 21 additions & 0 deletions test/functional/fixtures/es_archiver/visualize/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,27 @@
}
}

{
"type": "doc",
"value": {
"id": "visualization:Visualization-AreaChart",
"index": ".kibana",
"source": {
"type": "visualization",
"visualization": {
"description": "AreaChart",
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"index\":\"logstash-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
},
"title": "Visualization AreaChart",
"uiStateJSON": "{}",
"version": 1,
"visState": "{\"title\":\"Visualization AreaChart\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}}]}"
}
}
}
}

{
"type": "doc",
"value": {
Expand Down

0 comments on commit 0d50ea3

Please sign in to comment.