mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
Update @elastic/charts to v70, remove legacy time axis support (#210579)
## Summary Part of #193683. Replaces renovate bot PR #216102 for Elastic Charts v70 (see that PR for fully embedded release notes). - Upgrade Elastic Charts from v69 to v70 - Remove `MULTILAYER_TIME_AXIS_STYLE` constants and imports - Remove `timeAxisLayerCount` parameters from Axis components - Add explanatory comments to all `xScaleType={ScaleType.Time}` usages - Fix a regression in data visualizer column charts by disabling grid lines close https://github.com/elastic/kibana/issues/221509 ### Release Notes Updates time based charts to use the multi-layer time axis by default, providing a better time window context and improved label positioning. Before:  After:  ### Remove Legacy Time Axis Support - This PR leaves the advanced setting `visualization:useLegacyTimeAxis` in place but the setting will no longer be picked up in the UI and charts with time axis will be rendered using the multi layer time axis. [The removal of the advanced setting will be done in a follow up](https://github.com/elastic/kibana/issues/213780) - Removes the `MULTILAYER_TIME_AXIS_STYLE` constant and related styling, this is now covered by Elastic Charts itself. Code that was previously using custom styles and settings to use the multilayer time axis, now updated to use the multi layer time axis by default now: - vis_types/xy - vis_types/timeseries - chart_expressions/expression_xy - lens/xy - ML: Data visualizer components - ML: AIOps document count histogram ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) ### Identify risks Risk of layout regressions because of removal of the legacy time axis. This PR needs manual testing of the affected components. ### For Reviewers If you are pinged, is probably do to the changes we are doing at the timeseries chart level. These are visual changes that, without our direct ping on code, can probably go unnoticed. So we kindle ask you to pull the PR locally and verify if the timeseries charts within your solutions/apps looks ok. Thanks --------- Co-authored-by: Marco Vettorello <marco.vettorello@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
de49917e1e
commit
5af2dc6b05
92 changed files with 211 additions and 352 deletions
|
@ -25,6 +25,9 @@ if [[ "$IS_TEST_EXECUTION_STEP" == "true" ]]; then
|
|||
buildkite-agent artifact upload 'test/**/screenshots/diff/*.png'
|
||||
buildkite-agent artifact upload 'test/**/screenshots/failure/*.png'
|
||||
buildkite-agent artifact upload 'test/**/screenshots/session/*.png'
|
||||
buildkite-agent artifact upload 'src/platform/test/**/screenshots/diff/*.png'
|
||||
buildkite-agent artifact upload 'src/platform/test/**/screenshots/failure/*.png'
|
||||
buildkite-agent artifact upload 'src/platform/test/**/screenshots/session/*.png'
|
||||
buildkite-agent artifact upload 'src/platform/test/functional/failure_debug/html/*.html'
|
||||
buildkite-agent artifact upload 'x-pack/test/**/screenshots/diff/*.png'
|
||||
buildkite-agent artifact upload 'x-pack/test/**/screenshots/failure/*.png'
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
"@elastic/apm-rum": "^5.17.0",
|
||||
"@elastic/apm-rum-core": "^5.23.0",
|
||||
"@elastic/apm-rum-react": "^2.0.6",
|
||||
"@elastic/charts": "69.2.2",
|
||||
"@elastic/charts": "70.0.1",
|
||||
"@elastic/datemath": "5.0.3",
|
||||
"@elastic/ebt": "^1.2.0",
|
||||
"@elastic/ecs": "^8.11.5",
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
import React from 'react';
|
||||
import moment from 'moment';
|
||||
|
||||
import { Chart, Settings, BarSeries, Axis } from '@elastic/charts';
|
||||
import { Chart, ScaleType, Settings, BarSeries, Axis } from '@elastic/charts';
|
||||
import { formatDate } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -47,32 +47,12 @@ export const ViewsChart = ({ data }: { data: Array<[week: number, views: number]
|
|||
enableHistogramMode={true}
|
||||
yNice={true}
|
||||
minBarHeight={1}
|
||||
xScaleType="time"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
timeZone={momentTz}
|
||||
/>
|
||||
|
||||
<Axis
|
||||
id="time"
|
||||
position="bottom"
|
||||
tickFormat={weekOfFormatter}
|
||||
timeAxisLayerCount={2}
|
||||
style={{
|
||||
tickLabel: {
|
||||
visible: true,
|
||||
padding: 0,
|
||||
rotation: 0,
|
||||
alignment: {
|
||||
vertical: 'bottom',
|
||||
horizontal: 'left',
|
||||
},
|
||||
},
|
||||
tickLine: {
|
||||
visible: true,
|
||||
size: 0,
|
||||
padding: 4,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Axis id="time" position="bottom" tickFormat={weekOfFormatter} />
|
||||
<Axis id="views" position="left" maximumFractionDigits={0} />
|
||||
</Chart>
|
||||
);
|
||||
|
|
|
@ -177,7 +177,6 @@ export const TIMELION_TARGET_BUCKETS_ID = 'timelion:target_buckets';
|
|||
|
||||
// Visualization settings
|
||||
export const VISUALIZATION_HEATMAP_MAX_BUCKETS_ID = 'visualization:heatmap:maxBuckets';
|
||||
export const VISUALIZATION_USE_LEGACY_TIME_AXIS_ID = 'visualization:useLegacyTimeAxis';
|
||||
export const VISUALIZATION_LEGACY_GAUGE_CHARTS_LIBRARY_ID =
|
||||
'visualization:visualize:legacyGaugeChartsLibrary';
|
||||
export const VISUALIZATION_LEGACY_HEATMAP_CHARTS_LIBRARY_ID =
|
||||
|
|
|
@ -495,6 +495,7 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
|||
id={specId}
|
||||
xAccessor={'key'}
|
||||
yAccessors={['count']}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
timeZone={getTimeZone(uiSettings)}
|
||||
|
|
|
@ -71,6 +71,7 @@ export const AreaSeriesComponent = ({ index, groupId, visData }: AreaSeriesCompo
|
|||
id={index + visData.label}
|
||||
groupId={groupId}
|
||||
name={visData.label}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={0}
|
||||
|
|
|
@ -43,6 +43,7 @@ export const BarSeriesComponent = ({ index, groupId, visData }: BarSeriesCompone
|
|||
id={index + visData.label}
|
||||
groupId={groupId}
|
||||
name={visData.label}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={0}
|
||||
|
|
|
@ -60,7 +60,7 @@ exports[`CategoryAxisPanel component should init with the default set of props 1
|
|||
"truncate": 0,
|
||||
}
|
||||
}
|
||||
disableSingleLayerAxisControls={false}
|
||||
disableAxisControls={false}
|
||||
setAxisLabel={[Function]}
|
||||
/>
|
||||
</EuiPanel>
|
||||
|
|
|
@ -152,9 +152,9 @@ exports[`MetricsAxisOptions component should init with the default set of props
|
|||
"type": "category",
|
||||
}
|
||||
}
|
||||
disableAxisControls={false}
|
||||
onPositionChanged={[Function]}
|
||||
setCategoryAxis={[Function]}
|
||||
useMultiLayerAxis={false}
|
||||
/>
|
||||
</Fragment>
|
||||
`;
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('CategoryAxisPanel component', () => {
|
|||
axis,
|
||||
onPositionChanged,
|
||||
setCategoryAxis,
|
||||
useMultiLayerAxis: false,
|
||||
disableAxisControls: false,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -59,8 +59,8 @@ describe('CategoryAxisPanel component', () => {
|
|||
expect(onPositionChanged).toBeCalledWith(value);
|
||||
});
|
||||
|
||||
it('should disable label options with multilayer axis', () => {
|
||||
const comp = shallow(<CategoryAxisPanel {...defaultProps} useMultiLayerAxis={true} />);
|
||||
it('should disable label options with disableAxisControls prop', () => {
|
||||
const comp = shallow(<CategoryAxisPanel {...defaultProps} disableAxisControls={true} />);
|
||||
const labelOptions = comp.find(LabelOptions).dive();
|
||||
const rotateLabelsOption = labelOptions.find({ paramName: 'rotate' });
|
||||
const filterLabelOption = labelOptions.find({ paramName: 'filter' });
|
||||
|
|
|
@ -26,14 +26,14 @@ export interface CategoryAxisPanelProps {
|
|||
axis: CategoryAxis;
|
||||
onPositionChanged: (position: Position) => void;
|
||||
setCategoryAxis: (value: CategoryAxis) => void;
|
||||
useMultiLayerAxis: boolean;
|
||||
disableAxisControls: boolean;
|
||||
}
|
||||
|
||||
function CategoryAxisPanel({
|
||||
axis,
|
||||
onPositionChanged,
|
||||
setCategoryAxis,
|
||||
useMultiLayerAxis,
|
||||
disableAxisControls,
|
||||
}: CategoryAxisPanelProps) {
|
||||
const setAxis = useCallback(
|
||||
<T extends keyof CategoryAxis>(paramName: T, value: CategoryAxis[T]) => {
|
||||
|
@ -102,7 +102,7 @@ function CategoryAxisPanel({
|
|||
axisLabels={axis.labels}
|
||||
axisFilterCheckboxName={`xAxisFilterLabelsCheckbox${axis.id}`}
|
||||
setAxisLabel={setAxisLabel}
|
||||
disableSingleLayerAxisControls={useMultiLayerAxis}
|
||||
disableAxisControls={disableAxisControls}
|
||||
/>
|
||||
)}
|
||||
</EuiPanel>
|
||||
|
|
|
@ -14,8 +14,6 @@ import { EuiSpacer } from '@elastic/eui';
|
|||
import { Position } from '@elastic/charts';
|
||||
|
||||
import { BUCKET_TYPES, IAggConfig } from '@kbn/data-plugin/public';
|
||||
import { LEGACY_TIME_AXIS } from '@kbn/charts-plugin/common';
|
||||
import { getUISettings } from '../../../../services';
|
||||
|
||||
import { VisParams, ValueAxis, SeriesParam, CategoryAxis } from '../../../../types';
|
||||
import { ValidationVisOptionsProps } from '../../common';
|
||||
|
@ -298,12 +296,10 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps<VisParams>) {
|
|||
const xAxisIsHorizontal =
|
||||
stateParams.categoryAxes[0].position === Position.Bottom ||
|
||||
stateParams.categoryAxes[0].position === Position.Top;
|
||||
const useLegacyTimeAxis = getUISettings().get(LEGACY_TIME_AXIS, false);
|
||||
const linearOrStackedBars = stateParams.seriesParams.every(
|
||||
({ mode, type }) => type !== 'histogram' || (type === 'histogram' && mode === 'stacked')
|
||||
);
|
||||
const useMultiLayerAxis =
|
||||
xAxisIsHorizontal && isTimeViz && !useLegacyTimeAxis && linearOrStackedBars;
|
||||
const disableAxisControls = xAxisIsHorizontal && isTimeViz && linearOrStackedBars;
|
||||
|
||||
return isTabSelected ? (
|
||||
<>
|
||||
|
@ -329,7 +325,7 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps<VisParams>) {
|
|||
axis={stateParams.categoryAxes[0]}
|
||||
onPositionChanged={onCategoryAxisPositionChanged}
|
||||
setCategoryAxis={setCategoryAxis}
|
||||
useMultiLayerAxis={useMultiLayerAxis}
|
||||
disableAxisControls={disableAxisControls}
|
||||
/>
|
||||
</>
|
||||
) : null;
|
||||
|
|
|
@ -24,14 +24,14 @@ export interface LabelOptionsProps {
|
|||
axisLabels: Labels;
|
||||
axisFilterCheckboxName: string;
|
||||
setAxisLabel: SetAxisLabel;
|
||||
disableSingleLayerAxisControls?: boolean;
|
||||
disableAxisControls?: boolean;
|
||||
}
|
||||
|
||||
function LabelOptions({
|
||||
axisLabels,
|
||||
axisFilterCheckboxName,
|
||||
setAxisLabel,
|
||||
disableSingleLayerAxisControls,
|
||||
disableAxisControls,
|
||||
}: LabelOptionsProps) {
|
||||
const setAxisLabelRotate = useCallback(
|
||||
(paramName: 'rotate', value: Labels['rotate']) => {
|
||||
|
@ -42,7 +42,7 @@ function LabelOptions({
|
|||
);
|
||||
|
||||
const rotateOptions = useMemo(getRotateOptions, []);
|
||||
const multilayerAxisTooltipText = disableSingleLayerAxisControls
|
||||
const axisTooltipText = disableAxisControls
|
||||
? i18n.translate(
|
||||
'visTypeXy.controls.pointSeries.categoryAxis.axisLabelsOptionsMultilayer.disabled',
|
||||
{
|
||||
|
@ -50,8 +50,7 @@ function LabelOptions({
|
|||
}
|
||||
)
|
||||
: undefined;
|
||||
const axisLabelControlDisabled = !axisLabels.show || disableSingleLayerAxisControls;
|
||||
|
||||
const axisLabelControlDisabled = !axisLabels.show || disableAxisControls;
|
||||
return (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
|
@ -82,14 +81,14 @@ function LabelOptions({
|
|||
paramName="filter"
|
||||
value={axisLabels.filter}
|
||||
setValue={setAxisLabel}
|
||||
tooltip={multilayerAxisTooltipText}
|
||||
tooltip={axisTooltipText}
|
||||
/>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiToolTip content={multilayerAxisTooltipText} delay="long" position="right">
|
||||
<EuiToolTip content={axisTooltipText} delay="long" position="right">
|
||||
<SelectOption
|
||||
disabled={axisLabelControlDisabled}
|
||||
label={i18n.translate('visTypeXy.controls.pointSeries.categoryAxis.alignLabel', {
|
||||
|
@ -104,7 +103,7 @@ function LabelOptions({
|
|||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiToolTip content={multilayerAxisTooltipText} delay="long" position="right">
|
||||
<EuiToolTip content={axisTooltipText} delay="long" position="right">
|
||||
<TruncateLabelsOption
|
||||
disabled={axisLabelControlDisabled}
|
||||
value={axisLabels.truncate}
|
||||
|
|
|
@ -1175,7 +1175,6 @@ exports[`XYChart component it renders area 1`] = `
|
|||
}
|
||||
}
|
||||
tickFormat={[Function]}
|
||||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Component
|
||||
|
@ -2733,7 +2732,6 @@ exports[`XYChart component it renders bar 1`] = `
|
|||
}
|
||||
}
|
||||
tickFormat={[Function]}
|
||||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Component
|
||||
|
@ -4291,7 +4289,6 @@ exports[`XYChart component it renders horizontal bar 1`] = `
|
|||
}
|
||||
}
|
||||
tickFormat={[Function]}
|
||||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Component
|
||||
|
@ -5849,7 +5846,6 @@ exports[`XYChart component it renders line 1`] = `
|
|||
}
|
||||
}
|
||||
tickFormat={[Function]}
|
||||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Component
|
||||
|
@ -7407,7 +7403,6 @@ exports[`XYChart component it renders stacked area 1`] = `
|
|||
}
|
||||
}
|
||||
tickFormat={[Function]}
|
||||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Component
|
||||
|
@ -8965,7 +8960,6 @@ exports[`XYChart component it renders stacked bar 1`] = `
|
|||
}
|
||||
}
|
||||
tickFormat={[Function]}
|
||||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Component
|
||||
|
@ -10523,7 +10517,6 @@ exports[`XYChart component it renders stacked horizontal bar 1`] = `
|
|||
}
|
||||
}
|
||||
tickFormat={[Function]}
|
||||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Component
|
||||
|
@ -12114,7 +12107,6 @@ exports[`XYChart component split chart should render split chart if both, splitR
|
|||
}
|
||||
}
|
||||
tickFormat={[Function]}
|
||||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<SplitChart
|
||||
|
@ -13916,7 +13908,6 @@ exports[`XYChart component split chart should render split chart if splitColumnA
|
|||
}
|
||||
}
|
||||
tickFormat={[Function]}
|
||||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<SplitChart
|
||||
|
@ -15711,7 +15702,6 @@ exports[`XYChart component split chart should render split chart if splitRowAcce
|
|||
}
|
||||
}
|
||||
tickFormat={[Function]}
|
||||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<SplitChart
|
||||
|
|
|
@ -147,7 +147,6 @@ describe('XYChart component', () => {
|
|||
syncColors: false,
|
||||
syncTooltips: false,
|
||||
syncCursor: true,
|
||||
useLegacyTimeAxis: false,
|
||||
eventAnnotationService: eventAnnotationServiceMock,
|
||||
renderComplete: jest.fn(),
|
||||
timeFormat: 'MMM D, YYYY @ HH:mm:ss.SSS',
|
||||
|
@ -324,7 +323,8 @@ describe('XYChart component', () => {
|
|||
|
||||
const axisStyle = instance.find(Axis).first().prop('timeAxisLayerCount');
|
||||
|
||||
expect(axisStyle).toBe(0);
|
||||
// This prop is no longer set, since v70 Elastic Charts takes care of this internally.
|
||||
expect(axisStyle).toBe(undefined);
|
||||
});
|
||||
test('it should enable the new time axis for a line time layer when isHistogram is set to true', () => {
|
||||
const timeLayerArgs = createArgsWithLayers([defaultTimeLayer]);
|
||||
|
@ -344,7 +344,8 @@ describe('XYChart component', () => {
|
|||
|
||||
const axisStyle = instance.find(Axis).first().prop('timeAxisLayerCount');
|
||||
|
||||
expect(axisStyle).toBe(2);
|
||||
// This prop is no longer set, since v70 Elastic Charts takes care of this internally.
|
||||
expect(axisStyle).toBe(undefined);
|
||||
});
|
||||
test('it should disable the new time axis for a vertical bar with break down dimension', () => {
|
||||
const timeLayer: DataLayerConfig = {
|
||||
|
@ -368,7 +369,8 @@ describe('XYChart component', () => {
|
|||
|
||||
const axisStyle = instance.find(Axis).first().prop('timeAxisLayerCount');
|
||||
|
||||
expect(axisStyle).toBe(0);
|
||||
// This prop is no longer set, since v70 Elastic Charts takes care of this internally.
|
||||
expect(axisStyle).toBe(undefined);
|
||||
});
|
||||
|
||||
test('it should enable the new time axis for a stacked vertical bar with break down dimension', () => {
|
||||
|
@ -394,7 +396,8 @@ describe('XYChart component', () => {
|
|||
|
||||
const axisStyle = instance.find(Axis).first().prop('timeAxisLayerCount');
|
||||
|
||||
expect(axisStyle).toBe(2);
|
||||
// This prop is no longer set, since v70 Elastic Charts takes care of this internally.
|
||||
expect(axisStyle).toBe(undefined);
|
||||
});
|
||||
});
|
||||
describe('endzones', () => {
|
||||
|
|
|
@ -46,7 +46,6 @@ import { EmptyPlaceholder, LegendToggle } from '@kbn/charts-plugin/public';
|
|||
import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public';
|
||||
import { PointEventAnnotationRow } from '@kbn/event-annotation-plugin/common';
|
||||
import { ChartsPluginSetup, ChartsPluginStart, useActiveCursor } from '@kbn/charts-plugin/public';
|
||||
import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common';
|
||||
import {
|
||||
getAccessorByDimension,
|
||||
getColumnByAccessor,
|
||||
|
@ -130,6 +129,8 @@ declare global {
|
|||
}
|
||||
}
|
||||
|
||||
const MULTILAYER_TIME_AXIS_TICKLINE_PADDING = 4;
|
||||
|
||||
export type XYChartRenderProps = Omit<XYChartProps, 'canNavigateToLens'> & {
|
||||
chartsThemeService: ChartsPluginSetup['theme'];
|
||||
chartsActiveCursorService: ChartsPluginStart['activeCursor'];
|
||||
|
@ -137,7 +138,6 @@ export type XYChartRenderProps = Omit<XYChartProps, 'canNavigateToLens'> & {
|
|||
paletteService: PaletteRegistry;
|
||||
formatFactory: FormatFactory;
|
||||
timeZone: string;
|
||||
useLegacyTimeAxis: boolean;
|
||||
minInterval: number | undefined;
|
||||
interactive?: boolean;
|
||||
onClickValue: (data: FilterEvent['data']) => void;
|
||||
|
@ -214,7 +214,6 @@ export function XYChart({
|
|||
syncColors,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
useLegacyTimeAxis,
|
||||
renderComplete,
|
||||
uiState,
|
||||
timeFormat,
|
||||
|
@ -688,8 +687,7 @@ export function XYChart({
|
|||
isHistogram && (isStacked || seriesType !== SeriesTypes.BAR || !chartHasMoreThanOneBarSeries)
|
||||
);
|
||||
|
||||
const shouldUseNewTimeAxis =
|
||||
isTimeViz && isHistogramModeEnabled && !useLegacyTimeAxis && !shouldRotate;
|
||||
const isHorizontalTimeAxis = isTimeViz && isHistogramModeEnabled && !shouldRotate;
|
||||
|
||||
const defaultXAxisPosition = shouldRotate ? Position.Left : Position.Bottom;
|
||||
|
||||
|
@ -697,16 +695,13 @@ export function XYChart({
|
|||
visible: xAxisConfig?.showGridLines,
|
||||
strokeWidth: 1,
|
||||
};
|
||||
const xAxisStyle: RecursivePartial<AxisStyle> = shouldUseNewTimeAxis
|
||||
const xAxisStyle: RecursivePartial<AxisStyle> = isHorizontalTimeAxis
|
||||
? {
|
||||
...MULTILAYER_TIME_AXIS_STYLE,
|
||||
tickLabel: {
|
||||
...MULTILAYER_TIME_AXIS_STYLE.tickLabel,
|
||||
visible: Boolean(xAxisConfig?.showLabels),
|
||||
fill: xAxisConfig?.labelColor,
|
||||
},
|
||||
tickLine: {
|
||||
...MULTILAYER_TIME_AXIS_STYLE.tickLine,
|
||||
visible: Boolean(xAxisConfig?.showLabels),
|
||||
},
|
||||
axisTitle: {
|
||||
|
@ -944,7 +939,6 @@ export function XYChart({
|
|||
style={xAxisStyle}
|
||||
showOverlappingLabels={xAxisConfig?.showOverlappingLabels}
|
||||
showDuplicatedTicks={xAxisConfig?.showDuplicates}
|
||||
timeAxisLayerCount={shouldUseNewTimeAxis ? 2 : 0}
|
||||
{...getOverridesFor(overrides, 'axisX')}
|
||||
/>
|
||||
{isSplitChart && splitTable && (
|
||||
|
@ -1055,9 +1049,8 @@ export function XYChart({
|
|||
outsideDimension={
|
||||
rangeAnnotations.length && shouldHideDetails
|
||||
? OUTSIDE_RECT_ANNOTATION_WIDTH_SUGGESTION
|
||||
: shouldUseNewTimeAxis
|
||||
? Number(MULTILAYER_TIME_AXIS_STYLE.tickLine?.padding ?? 0) +
|
||||
chartBaseTheme.axes.tickLabel.fontSize
|
||||
: isHorizontalTimeAxis
|
||||
? MULTILAYER_TIME_AXIS_TICKLINE_PADDING + chartBaseTheme.axes.tickLabel.fontSize
|
||||
: Math.max(chartBaseTheme.axes.tickLine.size, OUTSIDE_RECT_ANNOTATION_WIDTH)
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -59,7 +59,6 @@ export interface GetStartDeps {
|
|||
activeCursor: ChartsPluginStart['activeCursor'];
|
||||
paletteService: PaletteRegistry;
|
||||
timeZone: string;
|
||||
useLegacyTimeAxis: boolean;
|
||||
eventAnnotationService: EventAnnotationServiceType;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
timeFormat: string;
|
||||
|
@ -295,7 +294,6 @@ export const getXyChartRenderer = ({
|
|||
timeZone={deps.timeZone}
|
||||
timeFormat={deps.timeFormat}
|
||||
eventAnnotationService={deps.eventAnnotationService}
|
||||
useLegacyTimeAxis={deps.useLegacyTimeAxis}
|
||||
minInterval={calculateMinInterval(deps.data.datatableUtilities, config)}
|
||||
interactive={handlers.isInteractive()}
|
||||
onClickValue={onClickValue}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
import { LEGACY_TIME_AXIS } from '@kbn/charts-plugin/common';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
|
@ -85,7 +84,6 @@ export class ExpressionXyPlugin {
|
|||
|
||||
const { theme: kibanaTheme } = coreStart;
|
||||
const eventAnnotationService = await eventAnnotation.getService();
|
||||
const useLegacyTimeAxis = core.uiSettings.get(LEGACY_TIME_AXIS);
|
||||
|
||||
return {
|
||||
data,
|
||||
|
@ -95,7 +93,6 @@ export class ExpressionXyPlugin {
|
|||
usageCollection,
|
||||
activeCursor,
|
||||
paletteService,
|
||||
useLegacyTimeAxis,
|
||||
eventAnnotationService,
|
||||
timeZone: getTimeZone(core.uiSettings),
|
||||
timeFormat: core.uiSettings.get('dateFormat'),
|
||||
|
|
|
@ -33,7 +33,6 @@ export {
|
|||
ColorMode,
|
||||
LabelRotation,
|
||||
defaultCountLabel,
|
||||
MULTILAYER_TIME_AXIS_STYLE,
|
||||
} from './static';
|
||||
|
||||
export type { ColorSchemaParams, Labels, Style } from './types';
|
||||
|
|
|
@ -11,5 +11,4 @@ export type { ColorSchema, RawColorSchema, ColorMap } from './color_maps';
|
|||
export { ColorSchemas, vislibColorMaps, colorSchemas, getHeatmapColors } from './color_maps';
|
||||
|
||||
export { ColorMode, LabelRotation, defaultCountLabel } from './components';
|
||||
export * from './styles';
|
||||
export type { AllowedSettingsOverrides, AllowedChartOverrides } from './overrides';
|
||||
|
|
|
@ -1,10 +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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
export * from './multilayer_timeaxis';
|
|
@ -1,27 +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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { Position, type RecursivePartial, type AxisStyle } from '@elastic/charts';
|
||||
|
||||
export const MULTILAYER_TIME_AXIS_STYLE: RecursivePartial<AxisStyle> = {
|
||||
tickLabel: {
|
||||
visible: true,
|
||||
padding: 0,
|
||||
rotation: 0,
|
||||
alignment: {
|
||||
vertical: Position.Bottom,
|
||||
horizontal: Position.Left,
|
||||
},
|
||||
},
|
||||
tickLine: {
|
||||
visible: true,
|
||||
size: 0,
|
||||
padding: 4,
|
||||
},
|
||||
};
|
|
@ -34,7 +34,6 @@ export {
|
|||
ColorPicker,
|
||||
LegendToggleLazy,
|
||||
LegendToggle,
|
||||
MULTILAYER_TIME_AXIS_STYLE,
|
||||
} from './static';
|
||||
export { lightenColor } from './services/palettes/lighten_color';
|
||||
export { decreaseOpacity } from './services/palettes/decrease_opacity';
|
||||
|
|
|
@ -9,4 +9,3 @@
|
|||
|
||||
export * from './colors';
|
||||
export * from './components';
|
||||
export * from '../../common/static/styles';
|
||||
|
|
|
@ -20,7 +20,6 @@ import { createFieldFormatter } from '../../lib/create_field_formatter';
|
|||
import { checkIfSeriesHaveSameFormatters } from '../../lib/check_if_series_have_same_formatters';
|
||||
import { TimeSeries } from '../../../visualizations/views/timeseries';
|
||||
import { Markdown } from '@kbn/shared-ux-markdown';
|
||||
import { LEGACY_TIME_AXIS } from '@kbn/charts-plugin/common';
|
||||
import { replaceVars } from '../../lib/replace_vars';
|
||||
import { getInterval } from '../../lib/get_interval';
|
||||
import { createIntervalBasedFormatter } from '../../lib/create_interval_based_formatter';
|
||||
|
@ -282,7 +281,6 @@ class TimeseriesVisualization extends Component {
|
|||
palettesService={palettesService}
|
||||
interval={interval}
|
||||
initialRender={initialRender}
|
||||
useLegacyTimeAxis={getConfig(LEGACY_TIME_AXIS, false)}
|
||||
isLastBucketDropped={Boolean(
|
||||
model.drop_last_bucket ||
|
||||
model.series.some((series) => series.series_drop_last_bucket)
|
||||
|
|
|
@ -16,7 +16,6 @@ import { createFieldFormatter } from '../../lib/create_field_formatter';
|
|||
import { FORMATS_UI_SETTINGS } from '@kbn/field-formats-plugin/common';
|
||||
import { METRIC_TYPES } from '@kbn/data-plugin/common';
|
||||
import { getFieldFormatsRegistry } from '@kbn/data-plugin/public/test_utils';
|
||||
import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/public';
|
||||
|
||||
jest.mock('@kbn/data-plugin/public/services', () => ({
|
||||
getUiSettings: () => ({ get: jest.fn() }),
|
||||
|
@ -113,19 +112,6 @@ describe('TimeseriesVisualization', () => {
|
|||
return renderShallow(formatters, valueTemplates).find(TimeSeries).props();
|
||||
};
|
||||
|
||||
test('should enable new time axis if ignore daylight time setting is switched off', () => {
|
||||
const component = renderShallow(['byte'], undefined, { ignore_daylight_time: false });
|
||||
console.log(component.find('TimeSeries').dive().debug());
|
||||
const xAxis = component.find('TimeSeries').dive().find('[id="bottom"]');
|
||||
expect(xAxis.prop('style')).toEqual(MULTILAYER_TIME_AXIS_STYLE);
|
||||
});
|
||||
|
||||
test('should disable new time axis for ignore daylight time setting', () => {
|
||||
const component = renderShallow(['byte'], undefined, { ignore_daylight_time: true });
|
||||
const xAxis = component.find('TimeSeries').dive().find('[id="bottom"]');
|
||||
expect(xAxis.prop('style')).toBeUndefined();
|
||||
});
|
||||
|
||||
test('should return byte formatted value from yAxis formatter for single byte series', () => {
|
||||
const timeSeriesProps = setupTimeSeriesProps(['byte']);
|
||||
|
||||
|
|
|
@ -24,11 +24,7 @@ import {
|
|||
Placement,
|
||||
Tooltip,
|
||||
} from '@elastic/charts';
|
||||
import {
|
||||
MULTILAYER_TIME_AXIS_STYLE,
|
||||
renderEndzoneTooltip,
|
||||
useActiveCursor,
|
||||
} from '@kbn/charts-plugin/public';
|
||||
import { renderEndzoneTooltip, useActiveCursor } from '@kbn/charts-plugin/public';
|
||||
import { EuiIcon } from '@elastic/eui';
|
||||
import { getTimeZone } from '@kbn/visualization-utils';
|
||||
import { getUISettings, getCharts } from '../../../../services';
|
||||
|
@ -81,8 +77,6 @@ export const TimeSeries = ({
|
|||
palettesService,
|
||||
interval,
|
||||
isLastBucketDropped,
|
||||
useLegacyTimeAxis,
|
||||
ignoreDaylightTime,
|
||||
initialRender,
|
||||
}) => {
|
||||
// If the color isn't configured by the user, use the color mapping service
|
||||
|
@ -163,13 +157,6 @@ export const TimeSeries = ({
|
|||
visible: showGrid,
|
||||
};
|
||||
|
||||
const shouldUseNewTimeAxis =
|
||||
series.every(
|
||||
({ stack, bars, lines }) => (bars?.show && stack !== STACKED_OPTIONS.NONE) || lines?.show
|
||||
) &&
|
||||
!useLegacyTimeAxis &&
|
||||
!ignoreDaylightTime;
|
||||
|
||||
return (
|
||||
<Chart ref={chartRef} renderer="canvas" className={classes}>
|
||||
<Tooltip
|
||||
|
@ -353,8 +340,6 @@ export const TimeSeries = ({
|
|||
title={getAxisLabelString(interval)}
|
||||
tickFormat={xAxisFormatter}
|
||||
gridLine={gridLineStyle}
|
||||
style={shouldUseNewTimeAxis ? MULTILAYER_TIME_AXIS_STYLE : undefined}
|
||||
timeAxisLayerCount={shouldUseNewTimeAxis ? 2 : 0}
|
||||
/>
|
||||
</Chart>
|
||||
);
|
||||
|
@ -380,5 +365,4 @@ TimeSeries.propTypes = {
|
|||
annotations: PropTypes.array,
|
||||
interval: PropTypes.number,
|
||||
isLastBucketDropped: PropTypes.bool,
|
||||
useLegacyTimeAxis: PropTypes.bool,
|
||||
};
|
||||
|
|
|
@ -266,8 +266,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
// chart and time picker updated
|
||||
await elasticChart.waitForRenderingCount(renderingCount + 1);
|
||||
const updatedTimeConfig = await timePicker.getTimeConfigAsAbsoluteTimes();
|
||||
expect(updatedTimeConfig.start).to.be('Sep 20, 2015 @ 08:41:22.854');
|
||||
expect(updatedTimeConfig.end).to.be('Sep 21, 2015 @ 04:14:56.951');
|
||||
expect(updatedTimeConfig.start).to.be('Sep 20, 2015 @ 08:23:44.196');
|
||||
expect(updatedTimeConfig.end).to.be('Sep 21, 2015 @ 02:32:51.702');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -103,15 +103,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await discover.clickHistogramBar();
|
||||
await discover.waitUntilSearchingHasFinished();
|
||||
const time = await timePicker.getTimeConfig();
|
||||
expect(time.start).to.be('Sep 21, 2015 @ 12:00:00.000');
|
||||
expect(time.end).to.be('Sep 21, 2015 @ 15:00:00.000');
|
||||
expect(time.start).to.be('Sep 21, 2015 @ 09:00:00.000');
|
||||
expect(time.end).to.be('Sep 21, 2015 @ 12:00:00.000');
|
||||
await retry.waitForWithTimeout(
|
||||
'table to contain the right search result',
|
||||
3000,
|
||||
async () => {
|
||||
const rowData = await discover.getDocTableField(1);
|
||||
log.debug(`The first timestamp value in doc table: ${rowData}`);
|
||||
return rowData.includes('Sep 21, 2015 @ 14:59:08.840');
|
||||
return rowData.includes('Sep 21, 2015 @ 11:59:22.316');
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -98,7 +98,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
return actualCount <= expectedCount;
|
||||
});
|
||||
const newDurationHours = await timePicker.getTimeDurationInHours();
|
||||
expect(Math.round(newDurationHours)).to.be(24); // might fail if histogram's width changes
|
||||
expect(Math.round(newDurationHours)).to.be(23); // might fail if histogram's width changes
|
||||
|
||||
await retry.waitFor('doc table containing the documents of the brushed range', async () => {
|
||||
const rowData = await discover.getDocTableField(1);
|
||||
|
|
|
@ -212,7 +212,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
include: 'win 7',
|
||||
exclude: 'ios',
|
||||
});
|
||||
await act('viz_1', { x: 105, y: 115 });
|
||||
await act('viz_1', { x: 143, y: 123 });
|
||||
const hasMachineRawFilter = await filterBar.hasFilter('machine.os.raw', 'win 7');
|
||||
expect(hasMachineRawFilter).to.be(true);
|
||||
});
|
||||
|
@ -229,7 +229,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
await visualBuilder.clickPanelOptions('timeSeries');
|
||||
await visualBuilder.setIntervalValue('1w');
|
||||
|
||||
await act('vis_2', { x: -100, y: 10 });
|
||||
await act('vis_2', { x: -130, y: 10 });
|
||||
|
||||
const filterPills = await filterBar.getFiltersLabel();
|
||||
expect(filterPills).to.eql(expectedFilterPills);
|
||||
|
|
|
@ -90,12 +90,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('should show correct chart', async function () {
|
||||
const xAxisLabels = [
|
||||
'2015-09-20 00:00',
|
||||
'2015-09-21 00:00',
|
||||
'2015-09-22 00:00',
|
||||
'2015-09-23 00:00',
|
||||
];
|
||||
const xAxisLabels = ['September 2015', '19th', '20th', '21st', '22nd', '23rd'];
|
||||
const yAxisLabels = ['0', '200', '400', '600', '800', '1,000', '1,200', '1,400'];
|
||||
const expectedAreaChartData = [
|
||||
37, 202, 740, 1437, 1371, 751, 188, 31, 42, 202, 683, 1361, 1415, 707, 177, 27, 32, 175,
|
||||
|
|
|
@ -233,24 +233,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
describe('timezones', function () {
|
||||
it('should show round labels in default timezone', async function () {
|
||||
const expectedLabels = [
|
||||
'2015-09-20 00:00',
|
||||
'2015-09-21 00:00',
|
||||
'2015-09-22 00:00',
|
||||
'2015-09-23 00:00',
|
||||
];
|
||||
const expectedLabels = ['September 2015', '19th', '20th', '21st', '22nd', '23rd'];
|
||||
await initChart();
|
||||
const labels = await visChart.getXAxisLabels(xyChartSelector);
|
||||
expect(labels.join()).to.contain(expectedLabels.join());
|
||||
});
|
||||
|
||||
it('should show round labels in different timezone', async function () {
|
||||
const expectedLabels = [
|
||||
'2015-09-20 00:00',
|
||||
'2015-09-21 00:00',
|
||||
'2015-09-22 00:00',
|
||||
'2015-09-23 00:00',
|
||||
];
|
||||
const expectedLabels = ['September 2015', '19th', '20th', '21st', '22nd', '23rd'];
|
||||
|
||||
await kibanaServer.uiSettings.update({ 'dateFormat:tz': 'America/Phoenix' });
|
||||
await browser.refresh();
|
||||
|
@ -277,20 +267,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
log.debug(`Labels: ${labels}`);
|
||||
|
||||
const xLabels = [
|
||||
'09:30',
|
||||
'September 22, 2015',
|
||||
'09:00',
|
||||
'10:00',
|
||||
'10:30',
|
||||
'11:00',
|
||||
'11:30',
|
||||
'12:00',
|
||||
'12:30',
|
||||
'13:00',
|
||||
'13:30',
|
||||
'14:00',
|
||||
'14:30',
|
||||
'15:00',
|
||||
'15:30',
|
||||
'16:00',
|
||||
];
|
||||
return labels.toString() === xLabels.toString();
|
||||
}
|
||||
|
@ -343,20 +327,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
log.debug(`Labels: ${labels2}`);
|
||||
|
||||
const xLabels2 = [
|
||||
'16:30',
|
||||
'September 22, 2015',
|
||||
'16:00',
|
||||
'17:00',
|
||||
'17:30',
|
||||
'18:00',
|
||||
'18:30',
|
||||
'19:00',
|
||||
'19:30',
|
||||
'20:00',
|
||||
'20:30',
|
||||
'21:00',
|
||||
'21:30',
|
||||
'22:00',
|
||||
'22:30',
|
||||
'23:00',
|
||||
];
|
||||
return labels2.toString() === xLabels2.toString();
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ export default async function ({ readConfigFile }) {
|
|||
defaults: {
|
||||
'accessibility:disableAnimations': true,
|
||||
'dateFormat:tz': 'UTC',
|
||||
'visualization:useLegacyTimeAxis': true,
|
||||
},
|
||||
},
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 64 KiB |
Binary file not shown.
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 45 KiB |
|
@ -34,7 +34,6 @@ import {
|
|||
type WindowParameters,
|
||||
} from '@kbn/aiops-log-rate-analysis';
|
||||
import { type BrushSelectionUpdatePayload } from '@kbn/aiops-log-rate-analysis/state';
|
||||
import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
|
@ -202,7 +201,6 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = (props) => {
|
|||
const barColors = useLogRateAnalysisBarColors();
|
||||
|
||||
const xAxisFormatter = fieldFormats.deserialize({ id: 'date' });
|
||||
const useLegacyTimeAxis = uiSettings.get('visualization:useLegacyTimeAxis', false);
|
||||
|
||||
const overallSeriesName = i18n.translate(
|
||||
'xpack.aiops.dataGrid.field.documentCountChart.seriesLabel',
|
||||
|
@ -510,14 +508,13 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = (props) => {
|
|||
position={Position.Bottom}
|
||||
showOverlappingTicks={true}
|
||||
tickFormat={(value) => xAxisFormatter.convert(value)}
|
||||
labelFormat={useLegacyTimeAxis ? undefined : () => ''}
|
||||
timeAxisLayerCount={useLegacyTimeAxis ? 0 : 2}
|
||||
style={useLegacyTimeAxis ? {} : MULTILAYER_TIME_AXIS_STYLE}
|
||||
labelFormat={() => ''}
|
||||
/>
|
||||
{adjustedChartPoints?.length && (
|
||||
<HistogramBarSeries
|
||||
id={SPEC_ID}
|
||||
name={chartPointsSplit ? overallSeriesNameWithSplit : overallSeriesName}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="time"
|
||||
|
@ -534,6 +531,7 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = (props) => {
|
|||
<HistogramBarSeries
|
||||
id={`${SPEC_ID}_split`}
|
||||
name={chartPointsSplitLabel}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="time"
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
LineAnnotation,
|
||||
LineAnnotationStyle,
|
||||
PartialTheme,
|
||||
ScaleType,
|
||||
Settings,
|
||||
Tooltip,
|
||||
TooltipType,
|
||||
|
@ -63,7 +64,8 @@ export const LogCategoriesGridHistogramCell: React.FC<LogCategoriesGridHistogram
|
|||
data={logCategory.histogram}
|
||||
id="documentCount"
|
||||
xAccessor={timestampAccessor}
|
||||
xScaleType="time"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yAccessors={['documentCount']}
|
||||
yScaleType="linear"
|
||||
enableHistogramMode
|
||||
|
|
|
@ -106,6 +106,7 @@ export const ChartPanel: React.FC<ChartPanelProps> = ({
|
|||
id="Total"
|
||||
name="Total"
|
||||
data={totalSeries}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
|
@ -121,6 +122,7 @@ export const ChartPanel: React.FC<ChartPanelProps> = ({
|
|||
id={`${metricType}-${stream.name}`}
|
||||
name={stream.name}
|
||||
data={stream.data}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
|
|
|
@ -20,7 +20,6 @@ import { useEuiTheme, EuiFlexGroup, EuiLoadingSpinner, EuiFlexItem } from '@elas
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { getTimeZone } from '@kbn/visualization-utils';
|
||||
import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common';
|
||||
import type { LogRateHistogramItem } from '@kbn/aiops-log-rate-analysis';
|
||||
|
||||
import { useDataVisualizerKibana } from '../../../../kibana_context';
|
||||
|
@ -60,7 +59,6 @@ export const DocumentCountChart: FC<Props> = ({
|
|||
const chartBaseTheme = charts.theme.useChartsBaseTheme();
|
||||
|
||||
const xAxisFormatter = fieldFormats.deserialize({ id: 'date' });
|
||||
const useLegacyTimeAxis = uiSettings.get('visualization:useLegacyTimeAxis', false);
|
||||
|
||||
const seriesName = i18n.translate(
|
||||
'xpack.dataVisualizer.dataGrid.field.documentCountChart.seriesLabel',
|
||||
|
@ -142,15 +140,12 @@ export const DocumentCountChart: FC<Props> = ({
|
|||
position={Position.Bottom}
|
||||
showOverlappingTicks={true}
|
||||
tickFormat={(value) => xAxisFormatter.convert(value)}
|
||||
// temporary fix to reduce horizontal chart margin until fixed in Elastic Charts itself
|
||||
labelFormat={useLegacyTimeAxis ? undefined : () => ''}
|
||||
timeAxisLayerCount={useLegacyTimeAxis ? 0 : 2}
|
||||
style={useLegacyTimeAxis ? {} : MULTILAYER_TIME_AXIS_STYLE}
|
||||
/>
|
||||
<Axis id="left" position={Position.Left} />
|
||||
<HistogramBarSeries
|
||||
id={SPEC_ID}
|
||||
name={seriesName}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="time"
|
||||
|
|
|
@ -52,7 +52,7 @@ export const BooleanContent: FC<FieldDataRowProps> = ({ config, onAddFilter }) =
|
|||
const chartBaseTheme = useElasticChartsTheme();
|
||||
const fieldFormat = 'fieldFormat' in config ? config.fieldFormat : undefined;
|
||||
const formattedPercentages = useMemo(() => getTFPercentage(config), [config]);
|
||||
const theme = useDataVizChartTheme();
|
||||
const theme = useDataVizChartTheme({ disableGridLines: true });
|
||||
if (!formattedPercentages) return null;
|
||||
|
||||
const { count } = formattedPercentages;
|
||||
|
|
|
@ -51,6 +51,7 @@ export const ColumnChart: FC<Props> = ({
|
|||
chartMargins: zeroSize,
|
||||
chartPaddings: zeroSize,
|
||||
crosshair: { band: { visible: false } },
|
||||
axes: { gridLine: { horizontal: { visible: false }, vertical: { visible: false } } },
|
||||
}}
|
||||
locale={i18n.getLocale()}
|
||||
/>
|
||||
|
|
|
@ -63,7 +63,7 @@ export const MetricDistributionChart: FC<Props> = ({
|
|||
}
|
||||
);
|
||||
|
||||
const theme = useDataVizChartTheme();
|
||||
const theme = useDataVizChartTheme({ disableGridLines: true });
|
||||
|
||||
const styles = useColumnChartStyles();
|
||||
|
||||
|
|
|
@ -10,7 +10,11 @@ import { useMemo } from 'react';
|
|||
import type { PartialTheme } from '@elastic/charts';
|
||||
import { useEuiFontSize, useEuiTheme } from '@elastic/eui';
|
||||
|
||||
export const useDataVizChartTheme = (): PartialTheme => {
|
||||
interface DataVizChartThemeOptions {
|
||||
disableGridLines?: boolean;
|
||||
}
|
||||
|
||||
export const useDataVizChartTheme = (options: DataVizChartThemeOptions = {}): PartialTheme => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const euiFontSizeXS = useEuiFontSize('xs', { unit: 'px' }).fontSize as string;
|
||||
const chartTheme = useMemo<PartialTheme>(() => {
|
||||
|
@ -23,6 +27,9 @@ export const useDataVizChartTheme = (): PartialTheme => {
|
|||
fontFamily: euiTheme.font.family,
|
||||
fontStyle: 'italic',
|
||||
},
|
||||
...(options.disableGridLines
|
||||
? { gridLine: { horizontal: { visible: false }, vertical: { visible: false } } }
|
||||
: {}),
|
||||
},
|
||||
background: { color: 'transparent' },
|
||||
chartMargins: {
|
||||
|
@ -54,6 +61,6 @@ export const useDataVizChartTheme = (): PartialTheme => {
|
|||
area: { visible: true, opacity: 1 },
|
||||
},
|
||||
};
|
||||
}, [euiFontSizeXS, euiTheme]);
|
||||
}, [euiFontSizeXS, euiTheme, options.disableGridLines]);
|
||||
return chartTheme;
|
||||
};
|
||||
|
|
|
@ -25,7 +25,6 @@ import { getTimeZone } from '@kbn/visualization-utils';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import type { IUiSettingsClient } from '@kbn/core/public';
|
||||
import { type LogRateHistogramItem } from '@kbn/aiops-log-rate-analysis';
|
||||
import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
|
@ -181,7 +180,6 @@ export const DocumentCountChartWithBrush: FC<DocumentCountChartProps> = (props)
|
|||
const chartBaseTheme = charts.theme.useChartsBaseTheme();
|
||||
|
||||
const xAxisFormatter = fieldFormats.deserialize({ id: 'date' });
|
||||
const useLegacyTimeAxis = uiSettings.get('visualization:useLegacyTimeAxis', false);
|
||||
|
||||
const overallSeriesName = i18n.translate('xpack.dataVisualizer.dataDriftt.seriesLabel', {
|
||||
defaultMessage: 'document count',
|
||||
|
@ -444,14 +442,13 @@ export const DocumentCountChartWithBrush: FC<DocumentCountChartProps> = (props)
|
|||
position={Position.Bottom}
|
||||
showOverlappingTicks={true}
|
||||
tickFormat={(value) => xAxisFormatter.convert(value)}
|
||||
labelFormat={useLegacyTimeAxis ? undefined : () => ''}
|
||||
timeAxisLayerCount={useLegacyTimeAxis ? 0 : 2}
|
||||
style={useLegacyTimeAxis ? {} : MULTILAYER_TIME_AXIS_STYLE}
|
||||
labelFormat={() => ''}
|
||||
/>
|
||||
{adjustedChartPoints?.length && (
|
||||
<HistogramBarSeries
|
||||
id={SPEC_ID}
|
||||
name={chartPointsSplit ? overallSeriesNameWithSplit : overallSeriesName}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="time"
|
||||
|
@ -468,6 +465,7 @@ export const DocumentCountChartWithBrush: FC<DocumentCountChartProps> = (props)
|
|||
<HistogramBarSeries
|
||||
id={`${SPEC_ID}_split`}
|
||||
name={chartPointsSplitLabel}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="time"
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import type { FC } from 'react';
|
||||
import React from 'react';
|
||||
import { Axis, Position } from '@elastic/charts';
|
||||
import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common';
|
||||
import type { LineChartPoint } from './event_rate_chart';
|
||||
import { useDataVisualizerKibana } from '../../../kibana_context';
|
||||
|
||||
|
@ -24,9 +23,8 @@ function tickFormatter(d: number): string {
|
|||
export const Axes: FC<Props> = ({ chartData }) => {
|
||||
const yDomain = getYRange(chartData);
|
||||
const {
|
||||
services: { fieldFormats, uiSettings },
|
||||
services: { fieldFormats },
|
||||
} = useDataVisualizerKibana();
|
||||
const useLegacyTimeAxis = uiSettings.get('visualization:useLegacyTimeAxis', false);
|
||||
const xAxisFormatter = fieldFormats.deserialize({ id: 'date' });
|
||||
|
||||
return (
|
||||
|
@ -36,9 +34,7 @@ export const Axes: FC<Props> = ({ chartData }) => {
|
|||
position={Position.Bottom}
|
||||
showOverlappingTicks={true}
|
||||
tickFormat={(value) => xAxisFormatter.convert(value)}
|
||||
labelFormat={useLegacyTimeAxis ? undefined : () => ''}
|
||||
timeAxisLayerCount={useLegacyTimeAxis ? 0 : 2}
|
||||
style={useLegacyTimeAxis ? {} : MULTILAYER_TIME_AXIS_STYLE}
|
||||
labelFormat={() => ''}
|
||||
/>
|
||||
<Axis id="left" position={Position.Left} tickFormat={tickFormatter} domain={yDomain} />
|
||||
</>
|
||||
|
|
|
@ -71,6 +71,7 @@ export const EventRateChart: FC<Props> = ({ eventRateChartData, height, width })
|
|||
|
||||
<HistogramBarSeries
|
||||
id="event_rate"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={'time'}
|
||||
|
|
|
@ -243,6 +243,7 @@ export const WatchVisualization = () => {
|
|||
<LineSeries
|
||||
key={key}
|
||||
id={key}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
data={watchVisualizationData[key]}
|
||||
|
|
|
@ -111,6 +111,7 @@ export const MiniHistogram: FC<MiniHistogramProps> = ({
|
|||
/>
|
||||
<BarSeries
|
||||
id="doc_count_overall"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={'key'}
|
||||
|
@ -121,6 +122,7 @@ export const MiniHistogram: FC<MiniHistogramProps> = ({
|
|||
/>
|
||||
<BarSeries
|
||||
id={label}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={'key'}
|
||||
|
|
|
@ -9,7 +9,6 @@ import type { CoreSetup } from '@kbn/core/public';
|
|||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import type { ExpressionsSetup } from '@kbn/expressions-plugin/public';
|
||||
import type { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
||||
import { LEGACY_TIME_AXIS } from '@kbn/charts-plugin/common';
|
||||
import type { EditorFrameSetup } from '../../types';
|
||||
import type { LensPluginStartDependencies } from '../../plugin';
|
||||
import type { FormatFactory } from '../../../common/types';
|
||||
|
@ -44,7 +43,6 @@ export class XyVisualization {
|
|||
charts.palettes.getPalettes(),
|
||||
eventAnnotation.getService(),
|
||||
]);
|
||||
const useLegacyTimeAxis = core.uiSettings.get(LEGACY_TIME_AXIS);
|
||||
return getXyVisualization({
|
||||
core: coreStart,
|
||||
data,
|
||||
|
@ -52,7 +50,6 @@ export class XyVisualization {
|
|||
paletteService,
|
||||
eventAnnotationService,
|
||||
fieldFormats,
|
||||
useLegacyTimeAxis,
|
||||
kibanaTheme: core.theme,
|
||||
unifiedSearch,
|
||||
dataViewsService: dataViews,
|
||||
|
|
|
@ -27,7 +27,6 @@ describe('#toExpression', () => {
|
|||
paletteService: chartPluginMock.createPaletteRegistry(),
|
||||
fieldFormats: fieldFormatsServiceMock.createStartContract(),
|
||||
kibanaTheme: themeServiceMock.createStartContract(),
|
||||
useLegacyTimeAxis: false,
|
||||
eventAnnotationService: eventAnnotationServiceMock,
|
||||
core: coreMock.createStart(),
|
||||
storage: {} as IStorageWrapper,
|
||||
|
|
|
@ -109,7 +109,6 @@ set(core, 'application.capabilities.visualize_v2.save', true);
|
|||
const xyVisualization = getXyVisualization({
|
||||
paletteService: paletteServiceMock,
|
||||
fieldFormats: fieldFormatsMock,
|
||||
useLegacyTimeAxis: false,
|
||||
kibanaTheme: themeServiceMock.createStartContract(),
|
||||
eventAnnotationService: eventAnnotationServiceMock,
|
||||
core,
|
||||
|
|
|
@ -149,7 +149,6 @@ export const getXyVisualization = ({
|
|||
data,
|
||||
paletteService,
|
||||
fieldFormats,
|
||||
useLegacyTimeAxis,
|
||||
kibanaTheme,
|
||||
eventAnnotationService,
|
||||
unifiedSearch,
|
||||
|
@ -162,7 +161,6 @@ export const getXyVisualization = ({
|
|||
paletteService: PaletteRegistry;
|
||||
eventAnnotationService: EventAnnotationServiceType;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
useLegacyTimeAxis: boolean;
|
||||
kibanaTheme: ThemeServiceStart;
|
||||
unifiedSearch: UnifiedSearchPublicPluginStart;
|
||||
dataViewsService: DataViewsPublicPluginStart;
|
||||
|
@ -743,7 +741,7 @@ export const getXyVisualization = ({
|
|||
},
|
||||
|
||||
ToolbarComponent(props) {
|
||||
return <XyToolbar {...props} useLegacyTimeAxis={useLegacyTimeAxis} />;
|
||||
return <XyToolbar {...props} />;
|
||||
},
|
||||
|
||||
DimensionEditorComponent(props) {
|
||||
|
|
|
@ -287,10 +287,8 @@ const defaultLegendTitle = i18n.translate('xpack.lens.xyChart.legendTitle', {
|
|||
defaultMessage: 'Legend',
|
||||
});
|
||||
|
||||
export const XyToolbar = memo(function XyToolbar(
|
||||
props: VisualizationToolbarProps<State> & { useLegacyTimeAxis?: boolean }
|
||||
) {
|
||||
const { state, setState, frame, useLegacyTimeAxis } = props;
|
||||
export const XyToolbar = memo(function XyToolbar(props: VisualizationToolbarProps<State>) {
|
||||
const { state, setState, frame } = props;
|
||||
const dataLayers = getDataLayers(state?.layers);
|
||||
const shouldRotate = state?.layers.length ? isHorizontalChart(state.layers) : false;
|
||||
const axisGroups = getAxesConfiguration(dataLayers, shouldRotate, frame.activeData);
|
||||
|
@ -584,9 +582,7 @@ export const XyToolbar = memo(function XyToolbar(
|
|||
setCurrentTimeMarkerVisibility={onChangeCurrentTimeMarkerVisibility}
|
||||
hasBarOrAreaOnAxis={false}
|
||||
hasPercentageAxis={false}
|
||||
useMultilayerTimeAxis={
|
||||
isTimeHistogramModeEnabled && !useLegacyTimeAxis && !shouldRotate
|
||||
}
|
||||
useMultilayerTimeAxis={isTimeHistogramModeEnabled && !shouldRotate}
|
||||
extent={hasNumberHistogram ? state?.xExtent || { mode: 'dataBounds' } : undefined}
|
||||
setExtent={setExtentFn('xExtent')}
|
||||
dataBounds={xDataBounds}
|
||||
|
|
|
@ -46,22 +46,10 @@ describe('XY Toolbar', () => {
|
|||
};
|
||||
});
|
||||
|
||||
const renderToolbar = (
|
||||
overrideProps?: Partial<
|
||||
VisualizationToolbarProps<XYState> & {
|
||||
useLegacyTimeAxis?: boolean;
|
||||
}
|
||||
>
|
||||
) => {
|
||||
const renderToolbar = (overrideProps?: Partial<VisualizationToolbarProps<XYState>>) => {
|
||||
const state = testState();
|
||||
const rtlRender = render(
|
||||
<XyToolbar
|
||||
frame={frame}
|
||||
setState={jest.fn()}
|
||||
state={state}
|
||||
{...overrideProps}
|
||||
useLegacyTimeAxis={false}
|
||||
/>
|
||||
<XyToolbar frame={frame} setState={jest.fn()} state={state} {...overrideProps} />
|
||||
);
|
||||
return rtlRender;
|
||||
};
|
||||
|
|
|
@ -37,6 +37,7 @@ export const ModelBounds: FC<Props> = ({ modelData }) => {
|
|||
return (
|
||||
<AreaSeries
|
||||
id={SPEC_ID}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={'time'}
|
||||
|
|
|
@ -34,6 +34,7 @@ export const Scatter: FC<Props> = ({ chartData }) => {
|
|||
return (
|
||||
<LineSeries
|
||||
id={SPEC_ID}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={'time'}
|
||||
|
|
|
@ -108,6 +108,7 @@ export const EventRateChart: FC<Props> = ({
|
|||
<Anomalies anomalyData={anomalyData} />
|
||||
<HistogramBarSeries
|
||||
id="event_rate"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={'time'}
|
||||
|
|
|
@ -289,6 +289,7 @@ export const ThresholdVisualization: React.FunctionComponent<Props> = ({
|
|||
<LineSeries
|
||||
key={key}
|
||||
id={key}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
data={visualizationData[key]}
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
EuiIconTip,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { AreaSeries, Axis, BarSeries, Chart, Settings } from '@elastic/charts';
|
||||
import { AreaSeries, Axis, BarSeries, Chart, ScaleType, Settings } from '@elastic/charts';
|
||||
import { useElasticChartsTheme } from '@kbn/charts-theme';
|
||||
import { TimeState } from '@kbn/es-query';
|
||||
import { DataStreamStats } from './hooks/use_data_stream_stats';
|
||||
|
@ -133,7 +133,8 @@ function ChartAreaSeries({
|
|||
name="Ingestion rate"
|
||||
data={ingestionRate.buckets}
|
||||
color="#61A2FF"
|
||||
xScaleType="time"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
xAccessor={'key'}
|
||||
yAccessors={['value']}
|
||||
/>
|
||||
|
@ -200,7 +201,8 @@ function ChartBarSeries({
|
|||
name={capitalize(tier)}
|
||||
data={buckets}
|
||||
color={ilmPhases[tier as PhaseName].color}
|
||||
xScaleType="time"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
xAccessor={'key'}
|
||||
yAccessors={['value']}
|
||||
stackAccessors={[0]}
|
||||
|
|
|
@ -183,6 +183,7 @@ export function ControlledEsqlChart<T extends string>({
|
|||
key={serie.id}
|
||||
color="#61A2FF"
|
||||
id={serie.id}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
|
|
|
@ -129,6 +129,7 @@ export function DocumentsColumn({
|
|||
<BarSeries
|
||||
key={serie.id}
|
||||
id={serie.id}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
|
|
|
@ -121,6 +121,7 @@ export const AlertSummaryWidgetCompact = ({
|
|||
/>
|
||||
<LineSeries
|
||||
id={'activeAlertsChart'}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="key"
|
||||
|
|
|
@ -98,14 +98,9 @@ export const AlertSummaryWidgetFullSize = ({
|
|||
<Axis
|
||||
id="bottom"
|
||||
position={Position.Bottom}
|
||||
timeAxisLayerCount={2}
|
||||
gridLine={{
|
||||
visible: true,
|
||||
}}
|
||||
style={{
|
||||
tickLine: { size: 0, padding: 4 },
|
||||
tickLabel: { alignment: { horizontal: Position.Left, vertical: Position.Bottom } },
|
||||
}}
|
||||
/>
|
||||
<Axis
|
||||
id="left"
|
||||
|
@ -124,6 +119,7 @@ export const AlertSummaryWidgetFullSize = ({
|
|||
/>
|
||||
<LineSeries
|
||||
id="Active"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="key"
|
||||
|
|
|
@ -165,6 +165,7 @@ export function SparkPlotItem({
|
|||
<>
|
||||
<LineSeries
|
||||
id="Sparkline"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={'x'}
|
||||
|
@ -176,6 +177,7 @@ export function SparkPlotItem({
|
|||
{hasComparisonSeries && (
|
||||
<AreaSeries
|
||||
id="comparisonSeries"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={'x'}
|
||||
|
|
|
@ -232,6 +232,7 @@ export function TimeseriesChart({
|
|||
key={serie.title}
|
||||
id={serie.id || serie.title}
|
||||
groupId={serie.groupId}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
|
|
|
@ -247,6 +247,7 @@ const CriterionPreviewChart: React.FC<ChartProps> = ({
|
|||
<Chart>
|
||||
<BarSeries
|
||||
id="criterion-preview"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="timestamp"
|
||||
|
|
|
@ -53,6 +53,7 @@ export const SingleMetricSparkline: React.FunctionComponent<{
|
|||
id="metric"
|
||||
data={metric}
|
||||
xAccessor={timestampAccessor}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yAccessors={valueAccessor}
|
||||
timeZone={timeZone}
|
||||
|
|
|
@ -44,6 +44,7 @@ export const AreaChart = ({ id, color, series, name, type, stack }: Props) => {
|
|||
<AreaSeries
|
||||
id={id}
|
||||
name={name}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="timestamp"
|
||||
|
@ -73,6 +74,7 @@ export const BarChart = ({ id, color, series, name, stack }: Props) => {
|
|||
<BarSeries
|
||||
id={id}
|
||||
name={name}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="timestamp"
|
||||
|
|
|
@ -63,6 +63,7 @@ export const MetricsExplorerAreaChart = ({ metric, id, series, type, stack, opac
|
|||
id={chartId}
|
||||
key={chartId}
|
||||
name={createMetricLabel(metric)}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="timestamp"
|
||||
|
@ -101,6 +102,7 @@ export const MetricsExplorerBarChart = ({ metric, id, series, stack }: Props) =>
|
|||
id={chartId}
|
||||
key={chartId}
|
||||
name={createMetricLabel(metric)}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="timestamp"
|
||||
|
|
|
@ -153,6 +153,7 @@ export function AnnotationsListChart({
|
|||
/>
|
||||
<BarSeries
|
||||
id="bars"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
|
|
|
@ -98,6 +98,7 @@ export function SparkPlot({
|
|||
) : (
|
||||
<LineSeries
|
||||
id="Sparkline"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor={'x'}
|
||||
|
|
|
@ -135,6 +135,7 @@ export function StackedBarChart({
|
|||
yAccessors={['Count']}
|
||||
stackAccessors={['true']}
|
||||
stackMode={asPercentages ? StackMode.Percentage : undefined}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
timeZone={timeZone}
|
||||
/>
|
||||
|
|
|
@ -74,6 +74,7 @@ export function HostBreakdownChart({ data = [] }: Props) {
|
|||
timeZone={timeZone}
|
||||
key={serie.title}
|
||||
id={serie.title}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
|
|
|
@ -128,6 +128,7 @@ export function GoodBadEventsChart({ data, slo, onBrushed }: Props) {
|
|||
rect: { fill: euiTheme.colors.success },
|
||||
displayValue: { fill: euiTheme.colors.success },
|
||||
}}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="key"
|
||||
|
@ -146,6 +147,7 @@ export function GoodBadEventsChart({ data, slo, onBrushed }: Props) {
|
|||
rect: { fill: euiTheme.colors.danger },
|
||||
displayValue: { fill: euiTheme.colors.danger },
|
||||
}}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="key"
|
||||
|
|
|
@ -130,6 +130,7 @@ export function WideChart({ chart, data, id, isLoading, state, onBrushed, slo }:
|
|||
point: { visible: 'never' },
|
||||
}}
|
||||
xAccessor="key"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yAccessors={['value']}
|
||||
yScaleType={ScaleType.Linear}
|
||||
|
|
|
@ -287,23 +287,12 @@ export function DataPreviewChart({
|
|||
})}
|
||||
tickFormat={(d) => moment(d).format(dateFormat)}
|
||||
position={Position.Bottom}
|
||||
timeAxisLayerCount={2}
|
||||
gridLine={{ visible: true }}
|
||||
style={{
|
||||
tickLine: { size: 0, padding: 4, visible: true },
|
||||
tickLabel: {
|
||||
alignment: {
|
||||
horizontal: Position.Left,
|
||||
vertical: Position.Bottom,
|
||||
},
|
||||
padding: 0,
|
||||
offset: { x: 0, y: 0 },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
<LineSeries
|
||||
id="All groups"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="date"
|
||||
|
@ -319,6 +308,7 @@ export function DataPreviewChart({
|
|||
<LineSeries
|
||||
key={group}
|
||||
id={group}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="date"
|
||||
|
|
|
@ -85,6 +85,7 @@ export function SloSparkline({ chart, data, id, isLoading, size, state }: Props)
|
|||
point: { visible: 'never' },
|
||||
}}
|
||||
xAccessor={'key'}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yAccessors={['value']}
|
||||
yScaleType={ScaleType.Linear}
|
||||
|
|
|
@ -65,6 +65,7 @@ export const MonitorBarSeries = ({ histogramSeries, minInterval }: MonitorBarSer
|
|||
})}
|
||||
timeZone="local"
|
||||
xAccessor={0}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yAccessors={[1]}
|
||||
yScaleType={ScaleType.Linear}
|
||||
|
|
|
@ -27,6 +27,7 @@ export const DurationLineSeriesList = ({ monitorType, lines }: Props) => (
|
|||
key={`loc-line-${name}`}
|
||||
name={name}
|
||||
xAccessor={0}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yAccessors={[1]}
|
||||
yScaleType={ScaleType.Linear}
|
||||
|
|
|
@ -103,6 +103,7 @@ export const MonitorBarSeries = ({ histogramSeries, minInterval }: MonitorBarSer
|
|||
})}
|
||||
timeZone="local"
|
||||
xAccessor={0}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yAccessors={[1]}
|
||||
yScaleType={ScaleType.Linear}
|
||||
|
|
|
@ -182,6 +182,7 @@ export const PingHistogramComponent: React.FC<PingHistogramComponentProps> = ({
|
|||
splitSeriesAccessors={['type']}
|
||||
timeZone={timeZone}
|
||||
xAccessor="x"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yAccessors={['y']}
|
||||
yScaleType={ScaleType.Linear}
|
||||
|
|
|
@ -168,6 +168,7 @@ export const AnalyticsCollectionChart: React.FC<
|
|||
},
|
||||
}}
|
||||
yNice
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Sqrt}
|
||||
curve={CurveType.CURVE_MONOTONE_X}
|
||||
|
|
|
@ -205,6 +205,7 @@ export const AnalyticsCollectionCard: React.FC<
|
|||
data={data}
|
||||
xAccessor={0}
|
||||
yAccessors={[1]}
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
curve={CurveType.CURVE_BASIS}
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
Axis,
|
||||
Chart,
|
||||
niceTimeFormatByDay,
|
||||
ScaleType,
|
||||
Settings,
|
||||
timeFormatter,
|
||||
Tooltip,
|
||||
|
@ -231,7 +232,8 @@ const ComplianceTrendChart = ({ trend }: { trend: PostureTrend[] }) => {
|
|||
// EuiChart is using this id in the tooltip label
|
||||
id="Posture Score"
|
||||
data={epochTimeTrend}
|
||||
xScaleType="time"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
xAccessor={'timestamp'}
|
||||
yAccessors={['postureScore']}
|
||||
/>
|
||||
|
|
|
@ -16,32 +16,32 @@ import type { ChartSeries } from '../../services/fetch_aggregated_indicators';
|
|||
|
||||
const mockIndicators: ChartSeries[] = [
|
||||
{
|
||||
x: '1 Jan 2022 00:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 00:00:00 GMT').getTime(),
|
||||
y: 2,
|
||||
g: '[Filebeat] AbuseCH Malware',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 00:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 00:00:00 GMT').getTime(),
|
||||
y: 10,
|
||||
g: '[Filebeat] AbuseCH MalwareBazaar',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 06:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 06:00:00 GMT').getTime(),
|
||||
y: 0,
|
||||
g: '[Filebeat] AbuseCH Malware',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 06:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 06:00:00 GMT').getTime(),
|
||||
y: 0,
|
||||
g: '[Filebeat] AbuseCH MalwareBazaar',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 12:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 12:00:00 GMT').getTime(),
|
||||
y: 25,
|
||||
g: '[Filebeat] AbuseCH Malware',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 18:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 18:00:00 GMT').getTime(),
|
||||
y: 15,
|
||||
g: '[Filebeat] AbuseCH MalwareBazaar',
|
||||
},
|
||||
|
|
|
@ -21,22 +21,22 @@ describe('<IndicatorsBarChart />', () => {
|
|||
it('should render barchart', () => {
|
||||
const mockIndicators: ChartSeries[] = [
|
||||
{
|
||||
x: '1 Jan 2022 00:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 00:00:00 GMT').getTime(),
|
||||
y: 0,
|
||||
g: '[Filebeat] AbuseCH Malware',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 00:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 00:00:00 GMT').getTime(),
|
||||
y: 10,
|
||||
g: '[Filebeat] AbuseCH MalwareBazaar',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 12:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 12:00:00 GMT').getTime(),
|
||||
y: 25,
|
||||
g: '[Filebeat] AbuseCH Malware',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 18:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 18:00:00 GMT').getTime(),
|
||||
y: 15,
|
||||
g: '[Filebeat] AbuseCH MalwareBazaar',
|
||||
},
|
||||
|
@ -63,34 +63,30 @@ describe('<IndicatorsBarChart />', () => {
|
|||
|
||||
expect(container).toMatchInlineSnapshot(`
|
||||
<div>
|
||||
<span
|
||||
class="euiThemeProvider emotion-euiColorMode-LIGHT"
|
||||
<div
|
||||
class="echChart"
|
||||
style="width: 100%; height: 200px;"
|
||||
>
|
||||
<div
|
||||
class="echChart"
|
||||
style="width: 100%; height: 200px;"
|
||||
class="echChartContent"
|
||||
>
|
||||
<div
|
||||
class="echChartContent"
|
||||
>
|
||||
<div
|
||||
class="echChartBackground"
|
||||
style="background-color: transparent;"
|
||||
/>
|
||||
<div
|
||||
class="echChartStatus"
|
||||
data-ech-render-complete="false"
|
||||
data-ech-render-count="0"
|
||||
/>
|
||||
<div
|
||||
class="echChartResizer"
|
||||
/>
|
||||
<div
|
||||
class="echContainer"
|
||||
/>
|
||||
</div>
|
||||
class="echChartBackground"
|
||||
style="background-color: transparent;"
|
||||
/>
|
||||
<div
|
||||
class="echChartStatus"
|
||||
data-ech-render-complete="false"
|
||||
data-ech-render-count="0"
|
||||
/>
|
||||
<div
|
||||
class="echChartResizer"
|
||||
/>
|
||||
<div
|
||||
class="echContainer"
|
||||
/>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
import React, { type FC } from 'react';
|
||||
import { Axis, BarSeries, Chart, Position, ScaleType, Settings } from '@elastic/charts';
|
||||
import { useElasticChartsTheme } from '@kbn/charts-theme';
|
||||
import { type EuiComboBoxOptionOption, EuiThemeProvider } from '@elastic/eui';
|
||||
import { type EuiComboBoxOptionOption } from '@elastic/eui';
|
||||
import { type TimeRangeBounds } from '@kbn/data-plugin/common';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { IndicatorBarchartLegendAction } from './legend_action';
|
||||
import { barChartTimeAxisLabelFormatter } from '../../../../utils/dates';
|
||||
import type { ChartSeries } from '../../services/fetch_aggregated_indicators';
|
||||
import { useTimeZone } from '../../../../hooks/use_kibana_ui_settings';
|
||||
|
||||
const ID = 'tiIndicator';
|
||||
const DEFAULT_CHART_HEIGHT = '200px';
|
||||
|
@ -49,35 +50,37 @@ export const IndicatorsBarChart: FC<IndicatorsBarChartProps> = ({
|
|||
height = DEFAULT_CHART_HEIGHT,
|
||||
}) => {
|
||||
const chartBaseTheme = useElasticChartsTheme();
|
||||
const timeZone = useTimeZone();
|
||||
|
||||
return (
|
||||
<EuiThemeProvider>
|
||||
<Chart size={{ width: DEFAULT_CHART_WIDTH, height }}>
|
||||
<Settings
|
||||
baseTheme={chartBaseTheme}
|
||||
showLegend
|
||||
legendPosition={Position.Right}
|
||||
legendSize={DEFAULT_LEGEND_SIZE}
|
||||
legendAction={({ label }) => <IndicatorBarchartLegendAction field={field} data={label} />}
|
||||
locale={i18n.getLocale()}
|
||||
/>
|
||||
<Axis
|
||||
id={`${ID}TimeAxis`}
|
||||
position={Position.Bottom}
|
||||
labelFormat={barChartTimeAxisLabelFormatter(dateRange)}
|
||||
/>
|
||||
<Axis id={`${ID}IndicatorAxis`} position={Position.Left} />
|
||||
<BarSeries
|
||||
id={`${ID}BarChart`}
|
||||
name="Indicators"
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
yAccessors={['y']}
|
||||
stackAccessors={['x']}
|
||||
splitSeriesAccessors={['g']}
|
||||
data={indicators}
|
||||
/>
|
||||
</Chart>
|
||||
</EuiThemeProvider>
|
||||
<Chart size={{ width: DEFAULT_CHART_WIDTH, height }}>
|
||||
<Settings
|
||||
baseTheme={chartBaseTheme}
|
||||
showLegend
|
||||
legendPosition={Position.Right}
|
||||
legendSize={DEFAULT_LEGEND_SIZE}
|
||||
legendAction={({ label }) => <IndicatorBarchartLegendAction field={field} data={label} />}
|
||||
locale={i18n.getLocale()}
|
||||
/>
|
||||
<Axis
|
||||
id={`${ID}TimeAxis`}
|
||||
position={Position.Bottom}
|
||||
tickFormat={barChartTimeAxisLabelFormatter(dateRange)}
|
||||
/>
|
||||
<Axis id={`${ID}IndicatorAxis`} position={Position.Left} />
|
||||
<BarSeries
|
||||
id={`${ID}BarChart`}
|
||||
name="Indicators"
|
||||
// Defaults to multi layer time axis as of Elastic Charts v70
|
||||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
yAccessors={['y']}
|
||||
stackAccessors={['x']}
|
||||
splitSeriesAccessors={['g']}
|
||||
data={indicators}
|
||||
timeZone={timeZone}
|
||||
/>
|
||||
</Chart>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -164,22 +164,22 @@ export const UpdatingData: StoryObj = {
|
|||
render: () => {
|
||||
const mockIndicators: ChartSeries[] = [
|
||||
{
|
||||
x: '1 Jan 2022 06:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 06:00:00 GMT').getTime(),
|
||||
y: 0,
|
||||
g: '[Filebeat] AbuseCH Malware',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 06:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 06:00:00 GMT').getTime(),
|
||||
y: 0,
|
||||
g: '[Filebeat] AbuseCH MalwareBazaar',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 12:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 12:00:00 GMT').getTime(),
|
||||
y: 25,
|
||||
g: '[Filebeat] AbuseCH Malware',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 18:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 18:00:00 GMT').getTime(),
|
||||
y: 15,
|
||||
g: '[Filebeat] AbuseCH MalwareBazaar',
|
||||
},
|
||||
|
|
|
@ -163,22 +163,22 @@ describe('convertAggregationToChartSeries', () => {
|
|||
)
|
||||
).toEqual([
|
||||
{
|
||||
x: '1 Jan 2022 06:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 06:00:00 GMT').getTime(),
|
||||
y: 0,
|
||||
g: '[Filebeat] AbuseCH Malware',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 12:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 12:00:00 GMT').getTime(),
|
||||
y: 10,
|
||||
g: '[Filebeat] AbuseCH Malware',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 06:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 06:00:00 GMT').getTime(),
|
||||
y: 20,
|
||||
g: '[Filebeat] AbuseCH MalwareBazaar',
|
||||
},
|
||||
{
|
||||
x: '1 Jan 2022 12:00:00 GMT',
|
||||
x: new Date('1 Jan 2022 12:00:00 GMT').getTime(),
|
||||
y: 8,
|
||||
g: '[Filebeat] AbuseCH MalwareBazaar',
|
||||
},
|
||||
|
|
|
@ -45,7 +45,7 @@ export interface RawAggregatedIndicatorsResponse {
|
|||
}
|
||||
|
||||
export interface ChartSeries {
|
||||
x: string;
|
||||
x: number;
|
||||
y: number;
|
||||
g: string;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ export const convertAggregationToChartSeries = (
|
|||
(accumulated: ChartSeries[], current: Aggregation) =>
|
||||
accumulated.concat(
|
||||
current.events.buckets.map((val: AggregationValue) => ({
|
||||
x: val.key_as_string,
|
||||
x: val.key,
|
||||
y: val.doc_count,
|
||||
g:
|
||||
field.value === 'date'
|
||||
|
|
|
@ -2057,10 +2057,10 @@
|
|||
dependencies:
|
||||
object-hash "^1.3.0"
|
||||
|
||||
"@elastic/charts@69.2.2":
|
||||
version "69.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-69.2.2.tgz#14a7f9251ddb54187d27f0eb47b378553dfb5847"
|
||||
integrity sha512-x65An5hDytnxR6/ZAWbDdbarpL7Lg3Muxq+xddP8/6lFL8OzTnb060bvrkhUcz3LPk8z6tkBzuX2t++w891vSw==
|
||||
"@elastic/charts@70.0.1":
|
||||
version "70.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-70.0.1.tgz#fa76b1486bfc71ba399adacd7507aa7c18b76c24"
|
||||
integrity sha512-hxQ+RbHZJoijQ0iiZb/IG9WIuhPSFxQs6b45mWZNpHe6FtGBcGdr0umXB2pD6fpL8DBDE3/9e13YEQqJElwJ1g==
|
||||
dependencies:
|
||||
"@popperjs/core" "^2.11.8"
|
||||
"@reduxjs/toolkit" "1.9.7"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue