Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto interval on date histogram is getting displayed as timestamp per… #59171

Merged
merged 17 commits into from
Mar 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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() };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing scaled message when a user selects an option.

}

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