[Discover] Fix time zone for field popover histogram and remove getTimeZone duplicates (#172705)

- Closes https://github.com/elastic/kibana/issues/172570

## Summary

This PR creates a new package `@kbn/visualization-utils` and moves
`getTimeZone` helper into it. Also the PR removes duplicates of other
similar helpers.

And the histogram in the field popover has now the same time zone
configuration as the the main hits histogram:

<img width="500" alt="Screenshot 2023-12-06 at 18 46 25"
src="2d350c91-1a41-419a-9d80-f203f1c90327">

## For testing

Change `dateFormat:tz` in Advanced Settings and check if histograms are
rendered accordingly.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Julia Rechkunova 2023-12-09 15:05:21 +01:00 committed by GitHub
parent d41889bf39
commit 8362b85885
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 113 additions and 73 deletions

1
.github/CODEOWNERS vendored
View file

@ -854,6 +854,7 @@ src/plugins/vis_types/vega @elastic/kibana-visualizations
src/plugins/vis_types/vislib @elastic/kibana-visualizations
src/plugins/vis_types/xy @elastic/kibana-visualizations
packages/kbn-visualization-ui-components @elastic/kibana-visualizations
packages/kbn-visualization-utils @elastic/kibana-visualizations
src/plugins/visualizations @elastic/kibana-visualizations
x-pack/plugins/watcher @elastic/platform-deployment-management
packages/kbn-web-worker-stub @elastic/kibana-operations

View file

@ -842,6 +842,7 @@
"@kbn/vis-type-vislib-plugin": "link:src/plugins/vis_types/vislib",
"@kbn/vis-type-xy-plugin": "link:src/plugins/vis_types/xy",
"@kbn/visualization-ui-components": "link:packages/kbn-visualization-ui-components",
"@kbn/visualization-utils": "link:packages/kbn-visualization-utils",
"@kbn/visualizations-plugin": "link:src/plugins/visualizations",
"@kbn/watcher-plugin": "link:x-pack/plugins/watcher",
"@kbn/xstate-utils": "link:packages/kbn-xstate-utils",

View file

@ -8,6 +8,7 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
import { getTimeZone } from '@kbn/visualization-utils';
import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types';
import { getEsQueryConfig } from '@kbn/data-service/src/es_query';
import type { IUiSettingsClient } from '@kbn/core/public';
@ -518,7 +519,7 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
yAccessors={['count']}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
timeZone="local"
timeZone={getTimeZone(uiSettings)}
/>
</Chart>
</div>

View file

@ -32,6 +32,7 @@
"@kbn/shared-ux-button-toolbar",
"@kbn/field-utils",
"@kbn/ml-ui-actions",
"@kbn/visualization-utils",
],
"exclude": ["target/**/*"]
}

View file

@ -0,0 +1,3 @@
# @kbn/visualization-utils
Utils for visualizations.

View file

@ -6,4 +6,4 @@
* Side Public License, v 1.
*/
export { getTimezone } from './get_timezone';
export { getTimeZone } from './src/get_timezone';

View file

@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
module.exports = {
preset: '@kbn/test',
rootDir: '../..',
roots: ['<rootDir>/packages/kbn-visualization-utils'],
};

View file

@ -0,0 +1,5 @@
{
"type": "shared-common",
"id": "@kbn/visualization-utils",
"owner": "@elastic/kibana-visualizations"
}

View file

@ -0,0 +1,7 @@
{
"name": "@kbn/visualization-utils",
"private": true,
"version": "1.0.0",
"license": "SSPL-1.0 OR Elastic License 2.0",
"sideEffects": false
}

View file

@ -0,0 +1,44 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import moment from 'moment-timezone';
import { IUiSettingsClient } from '@kbn/core/public';
import { getTimeZone } from './get_timezone';
describe('getTimeZone', () => {
const originalTimezone = moment.tz.guess();
beforeAll(() => {
moment.tz.setDefault('America/New_York');
});
afterAll(() => {
if (originalTimezone) {
moment.tz.setDefault(originalTimezone);
}
});
it('returns local time zone when uiSettings returns Browser', () => {
expect(
getTimeZone({
get: () => 'Browser',
isDefault: () => true,
} as unknown as IUiSettingsClient)
).toEqual('America/New_York');
});
it('returns timezone defined on uiSettings', () => {
const timezone = 'America/Toronto';
expect(
getTimeZone({
get: () => timezone,
isDefault: () => false,
} as unknown as IUiSettingsClient)
).toEqual(timezone);
});
});

View file

@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"include": ["*.ts", "src/**/*", "__mocks__/**/*.ts"],
"compilerOptions": {
"outDir": "target/types"
},
"exclude": [
"target/**/*"
],
"kbn_references": [
"@kbn/core",
]
}

View file

@ -8,6 +8,7 @@
import { i18n } from '@kbn/i18n';
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { getTimeZone } from '@kbn/visualization-utils';
import type { PersistedState } from '@kbn/visualizations-plugin/public';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
@ -29,7 +30,6 @@ import {
getPaletteService,
getUISettings,
} from '../services';
import { getTimeZone } from '../utils/get_timezone';
interface ExpressioHeatmapRendererDependencies {
getStartDeps: StartServicesGetter<ExpressionHeatmapPluginStart>;

View file

@ -28,6 +28,7 @@
"@kbn/analytics",
"@kbn/chart-expressions-common",
"@kbn/i18n-react",
"@kbn/visualization-utils",
],
"exclude": [
"target/**/*",

View file

@ -1,20 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import moment from 'moment-timezone';
import { IUiSettingsClient } from '@kbn/core/public';
export function getTimezone(config: IUiSettingsClient) {
if (config.isDefault('dateFormat:tz')) {
const detectedTimezone = moment.tz.guess();
if (detectedTimezone) return detectedTimezone;
else return moment().format('Z');
} else {
return config.get('dateFormat:tz', 'Browser');
}
}

View file

@ -11,8 +11,8 @@ import type { KibanaExecutionContext } from '@kbn/core/public';
import { DataView } from '@kbn/data-plugin/common';
import { Filter, buildEsQuery, TimeRange, Query } from '@kbn/es-query';
import { KibanaContext, getEsQueryConfig } from '@kbn/data-plugin/public';
import { getTimeZone } from '@kbn/visualization-utils';
import { TimelionVisDependencies } from '../plugin';
import { getTimezone } from './get_timezone';
import { TimelionVisParams } from '../timelion_vis_fn';
import { getDataSearch, getIndexPatterns } from './plugin_services';
import { VisSeries } from '../../common/vis_data';
@ -58,7 +58,7 @@ export function getTimelionRequestHandler({
}: TimelionVisDependencies & {
expressionAbortSignal: AbortSignal;
}) {
const timezone = getTimezone(uiSettings);
const timezone = getTimeZone(uiSettings);
return async function ({
timeRange,

View file

@ -31,6 +31,7 @@
"@kbn/expect",
"@kbn/std",
"@kbn/timelion-grammar",
"@kbn/visualization-utils",
],
"exclude": [
"target/**/*",

View file

@ -1,20 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import moment from 'moment-timezone';
import { IUiSettingsClient } from '@kbn/core/public';
export function getTimezone(config: IUiSettingsClient) {
if (config.isDefault('dateFormat:tz')) {
const detectedTimezone = moment.tz.guess();
if (detectedTimezone) return detectedTimezone;
else return moment().format('Z');
} else {
return config.get('dateFormat:tz', 'Browser');
}
}

View file

@ -28,7 +28,7 @@ import {
Tooltip,
} from '@elastic/charts';
import { EuiIcon } from '@elastic/eui';
import { getTimezone } from '../../../lib/get_timezone';
import { getTimeZone } from '@kbn/visualization-utils';
import { getUISettings, getCharts } from '../../../../services';
import { GRID_LINE_CONFIG, ICON_TYPES_MAP, STACKED_OPTIONS } from '../../constants';
import { AreaSeriesDecorator } from './decorators/area_decorator';
@ -121,7 +121,7 @@ export const TimeSeries = ({
}
const uiSettings = getUISettings();
const timeZone = getTimezone(uiSettings);
const timeZone = getTimeZone(uiSettings);
const hasBarChart = series.some(({ bars }) => bars?.show);
// apply legend style change if bgColor is configured

View file

@ -8,7 +8,7 @@
import type { KibanaExecutionContext } from '@kbn/core/public';
import type { Adapters } from '@kbn/inspector-plugin/common';
import { KibanaContext } from '@kbn/data-plugin/public';
import { getTimezone } from './application/lib/get_timezone';
import { getTimeZone } from '@kbn/visualization-utils';
import { getUISettings, getDataStart, getCoreStart } from './services';
import { ROUTES } from '../common/constants';
@ -44,7 +44,7 @@ export const metricsRequestHandler = async ({
expressionAbortSignal.addEventListener('abort', expressionAbortHandler);
const timezone = getTimezone(config);
const timezone = getTimeZone(config);
const uiStateObj = uiState[visParams.type] ?? {};
const dataSearch = data.search;
const parsedTimeRange = data.query.timefilter.timefilter.calculateBounds(input?.timeRange!);

View file

@ -45,6 +45,7 @@
"@kbn/home-plugin",
"@kbn/std",
"@kbn/tinymath",
"@kbn/visualization-utils",
],
"exclude": [
"target/**/*",

View file

@ -1702,6 +1702,8 @@
"@kbn/vis-type-xy-plugin/*": ["src/plugins/vis_types/xy/*"],
"@kbn/visualization-ui-components": ["packages/kbn-visualization-ui-components"],
"@kbn/visualization-ui-components/*": ["packages/kbn-visualization-ui-components/*"],
"@kbn/visualization-utils": ["packages/kbn-visualization-utils"],
"@kbn/visualization-utils/*": ["packages/kbn-visualization-utils/*"],
"@kbn/visualizations-plugin": ["src/plugins/visualizations"],
"@kbn/visualizations-plugin/*": ["src/plugins/visualizations/*"],
"@kbn/watcher-plugin": ["x-pack/plugins/watcher"],

View file

@ -24,7 +24,7 @@ import {
BarStyleAccessor,
RectAnnotationSpec,
} from '@elastic/charts/dist/chart_types/xy_chart/utils/specs';
import { getTimeZone } from '@kbn/visualization-utils';
import { i18n } from '@kbn/i18n';
import { IUiSettingsClient } from '@kbn/core/public';
import {
@ -146,16 +146,6 @@ enum VIEW_MODE {
BRUSH = 'brush',
}
function getTimezone(uiSettings: IUiSettingsClient) {
if (uiSettings.isDefault('dateFormat:tz')) {
const detectedTimezone = moment.tz.guess();
if (detectedTimezone) return detectedTimezone;
else return moment().format('Z');
} else {
return uiSettings.get('dateFormat:tz', 'Browser');
}
}
function getBaselineBadgeOverflow(
windowParametersAsPixels: WindowParameters,
baselineBadgeWidth: number
@ -297,7 +287,7 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = (props) => {
timefilterUpdateHandler({ from, to });
};
const timeZone = getTimezone(uiSettings);
const timeZone = getTimeZone(uiSettings);
const [originalWindowParameters, setOriginalWindowParameters] = useState<
WindowParameters | undefined

View file

@ -26,6 +26,7 @@
"@kbn/charts-plugin",
"@kbn/data-plugin",
"@kbn/field-formats-plugin",
"@kbn/visualization-utils",
],
"exclude": [
"target/**/*",

View file

@ -20,7 +20,7 @@ import {
XYBrushEvent,
} from '@elastic/charts';
import moment from 'moment';
import { IUiSettingsClient } from '@kbn/core/public';
import { getTimeZone } from '@kbn/visualization-utils';
import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common';
import type { LogRateHistogramItem } from '@kbn/aiops-utils';
@ -38,16 +38,6 @@ interface Props {
const SPEC_ID = 'document_count';
function getTimezone(uiSettings: IUiSettingsClient) {
if (uiSettings.isDefault('dateFormat:tz')) {
const detectedTimezone = moment.tz.guess();
if (detectedTimezone) return detectedTimezone;
else return moment().format('Z');
} else {
return uiSettings.get('dateFormat:tz', 'Browser');
}
}
export function LoadingSpinner() {
return (
<EuiFlexItem style={{ alignItems: 'center' }}>
@ -126,7 +116,7 @@ export const DocumentCountChart: FC<Props> = ({
timefilterUpdateHandler(range);
};
const timeZone = getTimezone(uiSettings);
const timeZone = getTimeZone(uiSettings);
return (
<EuiFlexGroup

View file

@ -69,6 +69,7 @@
"@kbn/ebt-tools",
"@kbn/ml-chi2test",
"@kbn/field-utils",
"@kbn/visualization-utils",
],
"exclude": [
"target/**/*",

View file

@ -6339,6 +6339,10 @@
version "0.0.0"
uid ""
"@kbn/visualization-utils@link:packages/kbn-visualization-utils":
version "0.0.0"
uid ""
"@kbn/visualizations-plugin@link:src/plugins/visualizations":
version "0.0.0"
uid ""