mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Lens] Remove scss from annotations plugin, visualization-ui-components and gauge expression (#208891)
## Summary part of https://github.com/elastic/kibana/issues/208908 Replaces scss to css-in-js. I've tested all the changes. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
148d47ced1
commit
91a19c0969
27 changed files with 234 additions and 251 deletions
|
@ -7,7 +7,6 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import './index.scss';
|
||||
import { isFieldLensCompatible } from '@kbn/visualization-ui-components';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -365,7 +364,6 @@ const AnnotationEditorControls = ({
|
|||
>
|
||||
<EuiFormRow
|
||||
display="rowCompressed"
|
||||
className="lnsRowCompressedMargin"
|
||||
fullWidth
|
||||
label={i18n.translate('eventAnnotationComponents.xyChart.annotation.tooltip', {
|
||||
defaultMessage: 'Show additional fields',
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
.lnsRowCompressedMargin+.lnsRowCompressedMargin {
|
||||
margin-top: $euiSizeS;
|
||||
}
|
||||
|
||||
.lnsConfigPanelAnnotations__date .euiFormControlLayout__prepend {
|
||||
min-width: $euiSize * 3.25; // makes both labels ("from" and "to") the same width
|
||||
}
|
||||
|
||||
.lnsConfigPanelAnnotations__addButton {
|
||||
margin-top: $euiSizeXS;
|
||||
}
|
||||
|
||||
.lnsConfigPanelAnnotations__fieldPicker {
|
||||
cursor: pointer;
|
||||
}
|
|
@ -19,7 +19,8 @@ import type {
|
|||
import { QueryInputServices } from '@kbn/visualization-ui-components';
|
||||
import moment from 'moment';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { EuiButtonGroup } from '@elastic/eui';
|
||||
import { EuiButtonGroup, EuiThemeProvider } from '@elastic/eui';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
|
||||
jest.mock('@kbn/unified-search-plugin/public', () => ({
|
||||
QueryStringInput: () => {
|
||||
|
@ -70,18 +71,27 @@ describe('AnnotationsPanel', () => {
|
|||
data: {},
|
||||
} as QueryInputServices;
|
||||
|
||||
describe('Dimension Editor', () => {
|
||||
test('shows correct options for line annotations', () => {
|
||||
const component = mount(
|
||||
const mountWithThemeProvider = (
|
||||
propsOverrides: Partial<typeof AnnotationEditorControls> = {}
|
||||
) => {
|
||||
return mount(
|
||||
<EuiThemeProvider>
|
||||
<AnnotationEditorControls
|
||||
annotation={customLineStaticAnnotation}
|
||||
onAnnotationChange={() => {}}
|
||||
dataView={{} as DataView}
|
||||
dataView={mockDataView}
|
||||
getDefaultRangeEnd={() => ''}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
{...propsOverrides}
|
||||
/>
|
||||
);
|
||||
</EuiThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe('Dimension Editor', () => {
|
||||
test('shows correct options for line annotations', () => {
|
||||
const component = mountWithThemeProvider();
|
||||
|
||||
expect(
|
||||
component.find('EuiDatePicker[data-test-subj="lns-xyAnnotation-time"]').prop('selected')
|
||||
|
@ -124,16 +134,7 @@ describe('AnnotationsPanel', () => {
|
|||
lineWidth: 3,
|
||||
};
|
||||
|
||||
const component = mount(
|
||||
<AnnotationEditorControls
|
||||
annotation={rangeAnnotation}
|
||||
onAnnotationChange={() => {}}
|
||||
dataView={{} as DataView}
|
||||
getDefaultRangeEnd={() => ''}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
/>
|
||||
);
|
||||
const component = mountWithThemeProvider({ annotation: rangeAnnotation });
|
||||
|
||||
expect(
|
||||
component.find('EuiDatePicker[data-test-subj="lns-xyAnnotation-fromTime"]').prop('selected')
|
||||
|
@ -156,21 +157,26 @@ describe('AnnotationsPanel', () => {
|
|||
expect(component.find('[data-test-subj="lns-xyAnnotation-fillStyle"]').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('calculates correct endTimstamp and transparent color when switching for range annotation and back', async () => {
|
||||
test('calculates correct endTimestamp and transparent color when switching for range annotation and back', async () => {
|
||||
const onAnnotationChange = jest.fn();
|
||||
const rangeEndTimestamp = new Date().toISOString();
|
||||
const component = mount(
|
||||
<AnnotationEditorControls
|
||||
annotation={customLineStaticAnnotation}
|
||||
onAnnotationChange={onAnnotationChange}
|
||||
dataView={{} as DataView}
|
||||
getDefaultRangeEnd={() => rangeEndTimestamp}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
/>
|
||||
|
||||
const { rerender } = render(
|
||||
<EuiThemeProvider>
|
||||
<AnnotationEditorControls
|
||||
annotation={customLineStaticAnnotation}
|
||||
onAnnotationChange={onAnnotationChange}
|
||||
dataView={mockDataView}
|
||||
getDefaultRangeEnd={() => rangeEndTimestamp}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
/>
|
||||
</EuiThemeProvider>
|
||||
);
|
||||
|
||||
component.find('button[data-test-subj="lns-xyAnnotation-rangeSwitch"]').simulate('click');
|
||||
act(() => {
|
||||
screen.getByTestId('lns-xyAnnotation-rangeSwitch').click();
|
||||
});
|
||||
|
||||
const expectedRangeAnnotation: RangeEventAnnotationConfig = {
|
||||
color: '#FF00001A',
|
||||
|
@ -185,19 +191,30 @@ describe('AnnotationsPanel', () => {
|
|||
},
|
||||
};
|
||||
|
||||
expect(onAnnotationChange).toBeCalledWith<EventAnnotationConfig[]>(expectedRangeAnnotation);
|
||||
expect(onAnnotationChange).toHaveBeenCalledWith(expectedRangeAnnotation);
|
||||
|
||||
rerender(
|
||||
<EuiThemeProvider>
|
||||
<AnnotationEditorControls
|
||||
annotation={expectedRangeAnnotation}
|
||||
onAnnotationChange={onAnnotationChange}
|
||||
dataView={mockDataView}
|
||||
getDefaultRangeEnd={() => rangeEndTimestamp}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
/>
|
||||
</EuiThemeProvider>
|
||||
);
|
||||
|
||||
expect(screen.getByTestId('lns-xyAnnotation-rangeSwitch').getAttribute('aria-checked')).toBe(
|
||||
'true'
|
||||
);
|
||||
|
||||
act(() => {
|
||||
component.setProps({ annotation: expectedRangeAnnotation });
|
||||
screen.getByTestId('lns-xyAnnotation-rangeSwitch').click();
|
||||
});
|
||||
|
||||
expect(
|
||||
component.find('EuiSwitch[data-test-subj="lns-xyAnnotation-rangeSwitch"]').prop('checked')
|
||||
).toEqual(true);
|
||||
|
||||
component.find('button[data-test-subj="lns-xyAnnotation-rangeSwitch"]').simulate('click');
|
||||
|
||||
expect(onAnnotationChange).toBeCalledWith<EventAnnotationConfig[]>({
|
||||
expect(onAnnotationChange).toHaveBeenCalledWith({
|
||||
color: '#FF0000',
|
||||
id: 'ann1',
|
||||
isHidden: undefined,
|
||||
|
@ -227,16 +244,7 @@ describe('AnnotationsPanel', () => {
|
|||
filter: { type: 'kibana_query', query: '', language: 'kuery' },
|
||||
};
|
||||
|
||||
const component = mount(
|
||||
<AnnotationEditorControls
|
||||
annotation={annotation}
|
||||
onAnnotationChange={() => {}}
|
||||
dataView={mockDataView}
|
||||
getDefaultRangeEnd={() => ''}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
/>
|
||||
);
|
||||
const component = mountWithThemeProvider({ annotation });
|
||||
|
||||
expect(
|
||||
component.find('[data-test-subj="lnsXY-annotation-query-based-field-picker"]').exists()
|
||||
|
@ -264,16 +272,10 @@ describe('AnnotationsPanel', () => {
|
|||
test('should prefill timeField with the default time field when switching to query based annotations', () => {
|
||||
const onAnnotationChange = jest.fn();
|
||||
|
||||
const component = mount(
|
||||
<AnnotationEditorControls
|
||||
annotation={customLineStaticAnnotation}
|
||||
onAnnotationChange={onAnnotationChange}
|
||||
dataView={mockDataView}
|
||||
getDefaultRangeEnd={() => ''}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
/>
|
||||
);
|
||||
const component = mountWithThemeProvider({
|
||||
annotation: customLineStaticAnnotation,
|
||||
onAnnotationChange,
|
||||
});
|
||||
|
||||
act(() => {
|
||||
component
|
||||
|
@ -291,16 +293,10 @@ describe('AnnotationsPanel', () => {
|
|||
test('should avoid to retain specific manual configurations when switching to query based annotations', () => {
|
||||
const onAnnotationChange = jest.fn();
|
||||
|
||||
const component = mount(
|
||||
<AnnotationEditorControls
|
||||
annotation={customLineStaticAnnotation}
|
||||
onAnnotationChange={onAnnotationChange}
|
||||
dataView={mockDataView}
|
||||
getDefaultRangeEnd={() => ''}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
/>
|
||||
);
|
||||
const component = mountWithThemeProvider({
|
||||
annotation: customLineStaticAnnotation,
|
||||
onAnnotationChange,
|
||||
});
|
||||
|
||||
act(() => {
|
||||
component
|
||||
|
@ -336,16 +332,7 @@ describe('AnnotationsPanel', () => {
|
|||
|
||||
const onAnnotationChange = jest.fn();
|
||||
|
||||
const component = mount(
|
||||
<AnnotationEditorControls
|
||||
annotation={annotation}
|
||||
onAnnotationChange={onAnnotationChange}
|
||||
dataView={mockDataView}
|
||||
getDefaultRangeEnd={() => ''}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
/>
|
||||
);
|
||||
const component = mountWithThemeProvider({ annotation, onAnnotationChange });
|
||||
|
||||
act(() => {
|
||||
component
|
||||
|
@ -379,16 +366,7 @@ describe('AnnotationsPanel', () => {
|
|||
|
||||
const onAnnotationChange = jest.fn();
|
||||
|
||||
const component = mount(
|
||||
<AnnotationEditorControls
|
||||
annotation={annotation}
|
||||
onAnnotationChange={onAnnotationChange}
|
||||
dataView={mockDataView}
|
||||
getDefaultRangeEnd={() => ''}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
/>
|
||||
);
|
||||
const component = mountWithThemeProvider({ annotation, onAnnotationChange });
|
||||
|
||||
act(() => {
|
||||
component
|
||||
|
@ -412,16 +390,11 @@ describe('AnnotationsPanel', () => {
|
|||
|
||||
test('should fallback to the first date field available in the dataView if not time-based', () => {
|
||||
const onAnnotationChange = jest.fn();
|
||||
const component = mount(
|
||||
<AnnotationEditorControls
|
||||
annotation={customLineStaticAnnotation}
|
||||
onAnnotationChange={onAnnotationChange}
|
||||
dataView={{ ...mockDataView, timeFieldName: '' } as DataView}
|
||||
getDefaultRangeEnd={() => ''}
|
||||
queryInputServices={mockQueryInputServices}
|
||||
appName="myApp"
|
||||
/>
|
||||
);
|
||||
const component = mountWithThemeProvider({
|
||||
annotation: customLineStaticAnnotation,
|
||||
onAnnotationChange,
|
||||
dataView: { ...mockDataView, timeFieldName: '' } as DataView,
|
||||
});
|
||||
|
||||
act(() => {
|
||||
component
|
||||
|
|
|
@ -70,7 +70,6 @@ export const ConfigPanelQueryAnnotation = ({
|
|||
<EuiFormRow
|
||||
hasChildLabel
|
||||
display="rowCompressed"
|
||||
className="lnsRowCompressedMargin"
|
||||
fullWidth
|
||||
label={i18n.translate('eventAnnotationComponents.xyChart.annotation.queryInput', {
|
||||
defaultMessage: 'Annotation query',
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { EuiFormRow, EuiSwitch, EuiText, EuiDatePicker } from '@elastic/eui';
|
||||
import { EuiFormRow, EuiSwitch, EuiText, EuiDatePicker, UseEuiTheme } from '@elastic/eui';
|
||||
import moment from 'moment';
|
||||
import type {
|
||||
PointInTimeEventAnnotationConfig,
|
||||
|
@ -31,7 +31,7 @@ export const ConfigPanelApplyAsRangeSwitch = ({
|
|||
}) => {
|
||||
const isRange = isRangeAnnotationConfig(annotation);
|
||||
return (
|
||||
<EuiFormRow display="columnCompressed" className="lnsRowCompressedMargin">
|
||||
<EuiFormRow display="columnCompressed">
|
||||
<EuiSwitch
|
||||
data-test-subj="lns-xyAnnotation-rangeSwitch"
|
||||
label={
|
||||
|
@ -84,6 +84,15 @@ export const ConfigPanelApplyAsRangeSwitch = ({
|
|||
);
|
||||
};
|
||||
|
||||
const RowCompressedMarginStyle = ({ euiTheme }: UseEuiTheme) => `
|
||||
& + .lnsRowCompressedMargin {
|
||||
margin-top: ${euiTheme.size.s};
|
||||
}
|
||||
.euiFormControlLayout__prepend {
|
||||
min-width: 50px; // makes both labels ("from" and "to") the same width
|
||||
}
|
||||
`;
|
||||
|
||||
export const ConfigPanelRangeDatePicker = ({
|
||||
value,
|
||||
label,
|
||||
|
@ -102,9 +111,10 @@ export const ConfigPanelRangeDatePicker = ({
|
|||
return (
|
||||
<EuiFormRow
|
||||
display="rowCompressed"
|
||||
fullWidth
|
||||
label={label}
|
||||
className="lnsConfigPanelAnnotations__date lnsRowCompressedMargin"
|
||||
fullWidth
|
||||
className="lnsRowCompressedMargin"
|
||||
css={RowCompressedMarginStyle}
|
||||
>
|
||||
<EuiDatePicker
|
||||
compressed
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { EuiFlexItem, EuiPanel, EuiText, htmlIdGenerator } from '@elastic/eui';
|
||||
import { EuiFlexItem, EuiPanel, EuiText, UseEuiTheme, htmlIdGenerator } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import fastIsEqual from 'fast-deep-equal';
|
||||
|
@ -43,6 +43,10 @@ function removeNewEmptyField(v: string) {
|
|||
|
||||
const generateId = htmlIdGenerator();
|
||||
|
||||
const NewBucketButtonStyles = ({ euiTheme }: UseEuiTheme) => `
|
||||
margin-top: ${euiTheme.size.xs};
|
||||
`;
|
||||
|
||||
interface LocalFieldEntry {
|
||||
name: string;
|
||||
id: string;
|
||||
|
@ -78,7 +82,7 @@ export function TooltipSection({ currentConfig, setConfig, dataView }: FieldInpu
|
|||
|
||||
const addFieldButton = (
|
||||
<NewBucketButton
|
||||
className="lnsConfigPanelAnnotations__addButton"
|
||||
css={NewBucketButtonStyles}
|
||||
data-test-subj={`lnsXY-annotation-tooltip-add_field`}
|
||||
onClick={() => {
|
||||
setFields([...currentFields, { name: '', id: generateId() }]);
|
||||
|
|
|
@ -3,7 +3,5 @@
|
|||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0",
|
||||
"sideEffects": [
|
||||
"*.scss"
|
||||
]
|
||||
"sideEffects": false
|
||||
}
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
{
|
||||
"extends": "../../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types",
|
||||
"types": [
|
||||
"jest",
|
||||
"node",
|
||||
"@emotion/react/types/css-prop",
|
||||
]
|
||||
"outDir": "target/types"
|
||||
},
|
||||
"include": [
|
||||
"**/*",
|
||||
"../../../../../typings/**/*",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*"
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
import React from 'react';
|
||||
import { EuiColorPaletteDisplay } from '@elastic/eui';
|
||||
import { css } from '@emotion/react';
|
||||
import { euiThemeVars } from '@kbn/ui-theme';
|
||||
import type { AccessorConfig } from './types';
|
||||
|
||||
export function PaletteIndicator({ accessorConfig }: { accessorConfig: AccessorConfig }) {
|
||||
|
@ -25,12 +24,7 @@ export function PaletteIndicator({ accessorConfig }: { accessorConfig: AccessorC
|
|||
`}
|
||||
>
|
||||
<EuiColorPaletteDisplay
|
||||
className="lnsLayerPanel__palette"
|
||||
css={css`
|
||||
height: ${euiThemeVars.euiSizeXS} / 2;
|
||||
border-radius: 0 0 (${euiThemeVars.euiBorderRadius} - 1px)
|
||||
(${euiThemeVars.euiBorderRadius} - 1px);
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
.lnsDimensionEditorSection {
|
||||
padding-top: $euiSize;
|
||||
padding-bottom: $euiSize;
|
||||
}
|
||||
|
||||
.lnsDimensionEditorSection:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.lnsDimensionEditorSection:first-child .lnsDimensionEditorSection__border {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lnsDimensionEditorSection__border {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -$euiSize;
|
||||
right: -$euiSize;
|
||||
left: -$euiSize;
|
||||
border-top: 1px solid $euiColorLightShade;
|
||||
}
|
||||
}
|
||||
|
||||
.lnsDimensionEditorSection__heading {
|
||||
padding-bottom: 16px;
|
||||
}
|
|
@ -7,9 +7,8 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { EuiTitle } from '@elastic/eui';
|
||||
import { EuiTitle, UseEuiTheme } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import './dimension_editor_section.scss';
|
||||
|
||||
export const DimensionEditorSection = ({
|
||||
children,
|
||||
|
@ -19,10 +18,14 @@ export const DimensionEditorSection = ({
|
|||
children?: React.ReactNode | React.ReactNode[];
|
||||
}) => {
|
||||
return (
|
||||
<div className="lnsDimensionEditorSection">
|
||||
<div className="lnsDimensionEditorSection__border" />
|
||||
<div css={DimensionEditorSectionStyles.self}>
|
||||
<div css={DimensionEditorSectionStyles.divider} />
|
||||
{title && (
|
||||
<EuiTitle size="xxs" className="lnsDimensionEditorSection__heading">
|
||||
<EuiTitle
|
||||
size="xxs"
|
||||
data-test-subj="lnsDimensionEditorSectionHeading"
|
||||
css={DimensionEditorSectionStyles.heading}
|
||||
>
|
||||
<h3>{title}</h3>
|
||||
</EuiTitle>
|
||||
)}
|
||||
|
@ -30,3 +33,27 @@ export const DimensionEditorSection = ({
|
|||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const DimensionEditorSectionStyles = {
|
||||
self: ({ euiTheme }: UseEuiTheme) => `
|
||||
padding-bottom: ${euiTheme.size.base};
|
||||
padding-top: ${euiTheme.size.base};
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
`,
|
||||
divider: ({ euiTheme }: UseEuiTheme) => `
|
||||
position: relative;
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -${euiTheme.size.base};
|
||||
right: -${euiTheme.size.base};
|
||||
left: -${euiTheme.size.base};
|
||||
border-top: 1px solid ${euiTheme.colors.lightShade};
|
||||
}
|
||||
`,
|
||||
heading: ({ euiTheme }: UseEuiTheme) => `
|
||||
padding-bottom: ${euiTheme.size.base};
|
||||
`,
|
||||
};
|
||||
|
|
|
@ -14,7 +14,6 @@ interface NewBucketButtonProps {
|
|||
label: string;
|
||||
onClick: () => void;
|
||||
isDisabled?: boolean;
|
||||
className?: string;
|
||||
'data-test-subj'?: string;
|
||||
}
|
||||
|
||||
|
@ -22,7 +21,6 @@ export const NewBucketButton = ({
|
|||
label,
|
||||
onClick,
|
||||
isDisabled,
|
||||
className,
|
||||
'data-test-subj': dataTestSubj = 'lns-newBucket-add',
|
||||
}: NewBucketButtonProps) => (
|
||||
<EuiButtonEmpty
|
||||
|
@ -32,7 +30,6 @@ export const NewBucketButton = ({
|
|||
onClick={onClick}
|
||||
isDisabled={isDisabled}
|
||||
flush="left"
|
||||
className={className}
|
||||
>
|
||||
{label}
|
||||
</EuiButtonEmpty>
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
.lnFieldPicker__option--incompatible {
|
||||
color: $euiColorLightShade;
|
||||
}
|
||||
|
||||
.lnFieldPicker__option--nonExistant {
|
||||
background-color: $euiColorLightestShade;
|
||||
}
|
|
@ -7,12 +7,10 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import './field_picker.scss';
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import classNames from 'classnames';
|
||||
import { comboBoxFieldOptionMatcher } from '@kbn/field-utils';
|
||||
import { EuiComboBox, EuiComboBoxOptionOption, EuiComboBoxProps } from '@elastic/eui';
|
||||
import { EuiComboBox, EuiComboBoxOptionOption, EuiComboBoxProps, useEuiTheme } from '@elastic/eui';
|
||||
import { FieldIcon } from '@kbn/field-utils/src/components/field_icon';
|
||||
import { calculateWidthFromCharCount } from '@kbn/calculate-width-from-char-count';
|
||||
import type { FieldOptionValue, FieldOption } from './types';
|
||||
|
@ -43,6 +41,7 @@ export function FieldPicker<T extends FieldOptionValue = FieldOptionValue>(
|
|||
...rest
|
||||
} = props;
|
||||
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const [selectedOption, setSelectedOption] = React.useState(activeField);
|
||||
|
||||
let maxLabelLength = 0;
|
||||
|
@ -63,10 +62,10 @@ export function FieldPicker<T extends FieldOptionValue = FieldOptionValue>(
|
|||
className="eui-alignMiddle"
|
||||
/>
|
||||
) : null,
|
||||
className: classNames({
|
||||
'lnFieldPicker__option--incompatible': !fieldOption.compatible,
|
||||
'lnFieldPicker__option--nonExistant': !fieldOptionExists,
|
||||
}),
|
||||
css: {
|
||||
color: !fieldOption.compatible ? euiTheme.colors.lightShade : undefined,
|
||||
backgroundColor: !fieldOptionExists ? euiTheme.colors.lightestShade : undefined,
|
||||
},
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
@ -77,10 +76,10 @@ export function FieldPicker<T extends FieldOptionValue = FieldOptionValue>(
|
|||
prepend: otherAttr.value.dataType ? (
|
||||
<FieldIcon type={otherAttr.value.dataType} fill="none" className="eui-alignMiddle" />
|
||||
) : null,
|
||||
className: classNames({
|
||||
'lnFieldPicker__option--incompatible': !compatible,
|
||||
'lnFieldPicker__option--nonExistant': !exists,
|
||||
}),
|
||||
css: {
|
||||
color: !compatible ? euiTheme.colors.lightShade : undefined,
|
||||
backgroundColor: !exists ? euiTheme.colors.lightestShade : undefined,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
// TODO - use emotion instead
|
||||
.filterQueryInput__popoverButton {
|
||||
@include euiTextBreakWord;
|
||||
@include euiFontSizeS;
|
||||
min-height: $euiSizeXL;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.filterQueryInput__popover {
|
||||
width: $euiSize * 60;
|
||||
}
|
|
@ -18,11 +18,14 @@ import {
|
|||
EuiFlexGroup,
|
||||
EuiIconTip,
|
||||
EuiPopoverProps,
|
||||
euiTextBreakWord,
|
||||
useEuiFontSize,
|
||||
UseEuiTheme,
|
||||
} from '@elastic/eui';
|
||||
import type { DataViewBase, Query } from '@kbn/es-query';
|
||||
import { css } from '@emotion/react';
|
||||
import { QueryInput, validateQuery } from '.';
|
||||
import type { QueryInputServices } from '.';
|
||||
import './filter_query_input.scss';
|
||||
|
||||
const filterByLabel = i18n.translate('visualizationUiComponents.filterQueryInput.label', {
|
||||
defaultMessage: 'Filter by',
|
||||
|
@ -46,6 +49,13 @@ export interface FilterQueryInputProps {
|
|||
appName: string;
|
||||
}
|
||||
|
||||
const LinkStyles = ({ euiTheme }: UseEuiTheme) => `
|
||||
${euiTextBreakWord()};
|
||||
${useEuiFontSize('s')};
|
||||
min-height: ${euiTheme.size.xl};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export function FilterQueryInput({
|
||||
inputFilter,
|
||||
onChange,
|
||||
|
@ -100,6 +110,11 @@ export function FilterQueryInput({
|
|||
isOpen={filterPopoverOpen}
|
||||
closePopover={onClosePopup}
|
||||
display="block"
|
||||
panelProps={{
|
||||
css: css`
|
||||
width: 960px;
|
||||
`,
|
||||
}}
|
||||
panelClassName="filterQueryInput__popover"
|
||||
initialFocus={dataTestSubj ? `textarea[data-test-subj='${dataTestSubj}']` : undefined}
|
||||
button={
|
||||
|
@ -113,6 +128,7 @@ export function FilterQueryInput({
|
|||
onClick={() => {
|
||||
setFilterPopoverOpen(!filterPopoverOpen);
|
||||
}}
|
||||
css={LinkStyles}
|
||||
color={isInputFilterValid ? 'text' : 'danger'}
|
||||
title={i18n.translate(
|
||||
'visualizationUiComponents.filterQueryInput.clickToEdit',
|
||||
|
|
|
@ -3,7 +3,5 @@
|
|||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0",
|
||||
"sideEffects": [
|
||||
"*.scss"
|
||||
]
|
||||
"sideEffects": false
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
},
|
||||
"include": [
|
||||
"**/*",
|
||||
"../../../../../typings/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*"
|
||||
|
|
|
@ -10,14 +10,14 @@
|
|||
import React, { ChangeEvent, FormEvent } from 'react';
|
||||
import type { EventAnnotationGroupConfig } from '@kbn/event-annotation-common';
|
||||
import { getDefaultManualAnnotation } from '@kbn/event-annotation-common';
|
||||
import { ReactWrapper } from 'enzyme';
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { ComponentType, ReactWrapper, mount } from 'enzyme';
|
||||
import { GroupEditorControls } from './group_editor_controls';
|
||||
import { EuiTextAreaProps, EuiTextProps } from '@elastic/eui';
|
||||
import { EuiTextAreaProps, EuiTextProps, EuiThemeProvider } from '@elastic/eui';
|
||||
import type { DataView } from '@kbn/data-views-plugin/common';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import type { QueryInputServices } from '@kbn/visualization-ui-components';
|
||||
import { AnnotationEditorControls } from '@kbn/event-annotation-components';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
|
||||
jest.mock('@elastic/eui', () => {
|
||||
return {
|
||||
|
@ -53,8 +53,17 @@ describe('event annotation group editor', () => {
|
|||
beforeEach(async () => {
|
||||
updateMock = jest.fn();
|
||||
setSelectedAnnotationMock = jest.fn();
|
||||
const wrappingComponent: React.FC<{
|
||||
children: React.ReactNode;
|
||||
}> = ({ children }) => {
|
||||
return (
|
||||
<EuiThemeProvider>
|
||||
<I18nProvider>{children}</I18nProvider>
|
||||
</EuiThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
wrapper = mountWithIntl(
|
||||
wrapper = mount(
|
||||
<GroupEditorControls
|
||||
group={group}
|
||||
update={updateMock}
|
||||
|
@ -72,7 +81,10 @@ describe('event annotation group editor', () => {
|
|||
queryInputServices={{} as QueryInputServices}
|
||||
showValidation={false}
|
||||
isAdHocDataView={() => false}
|
||||
/>
|
||||
/>,
|
||||
{
|
||||
wrappingComponent: wrappingComponent as ComponentType<{}>,
|
||||
}
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
"@kbn/event-annotation-common",
|
||||
"@kbn/lens-plugin",
|
||||
"@kbn/ui-theme",
|
||||
"@kbn/test-jest-helpers",
|
||||
"@kbn/expressions-plugin",
|
||||
"@kbn/es-query",
|
||||
"@kbn/core-ui-settings-browser",
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
.gauge__wrapper {
|
||||
flex: 1 1 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// it is used for rendering at `Canvas`.
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.gauge__label {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
import React, { FC, useCallback } from 'react';
|
||||
import { css } from '@emotion/react';
|
||||
import { Chart, Bullet, BulletProps, Settings } from '@elastic/charts';
|
||||
import { useEuiTheme } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
@ -38,10 +39,7 @@ import {
|
|||
computeMinMax,
|
||||
} from './utils';
|
||||
import { getGaugeIconByType } from './utils/icons';
|
||||
import './index.scss';
|
||||
import { GaugeCentralMajorMode, GaugeTicksPosition } from '../../common/types';
|
||||
|
||||
import './gauge.scss';
|
||||
import { useGaugeSizeByType } from './utils/use_gauge_size_by_type';
|
||||
|
||||
declare global {
|
||||
|
@ -366,7 +364,14 @@ export const GaugeComponent: FC<GaugeRenderProps> = ({
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="gauge__wrapper">
|
||||
<div
|
||||
css={css`
|
||||
flex: 1 1 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%; /* it is used for rendering in Canvas.*/
|
||||
`}
|
||||
>
|
||||
<Chart {...getOverridesFor(overrides, 'chart')}>
|
||||
<Settings
|
||||
noResults={<EmptyPlaceholder icon={icon} renderComplete={onRenderChange} />}
|
||||
|
@ -413,7 +418,16 @@ export const GaugeComponent: FC<GaugeRenderProps> = ({
|
|||
]}
|
||||
/>
|
||||
</Chart>
|
||||
{commonLabel && <div className="gauge__label">{commonLabel}</div>}
|
||||
{commonLabel && (
|
||||
<div
|
||||
css={css`
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
`}
|
||||
>
|
||||
{commonLabel}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
.gauge-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
// the FocusTrap is adding extra divs which are making the visualization redraw twice
|
||||
// with a visible glitch. This make the chart library resilient to this extra reflow
|
||||
overflow: hidden;
|
||||
user-select: text;
|
||||
@include euiScrollBar;
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { css } from '@emotion/react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { PersistedState } from '@kbn/visualizations-plugin/public';
|
||||
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
||||
|
@ -93,7 +94,18 @@ export const gaugeRenderer: (
|
|||
const { GaugeComponent } = await import('../components/gauge_component');
|
||||
render(
|
||||
<KibanaRenderContextProvider {...core}>
|
||||
<div className="gauge-container" data-test-subj="gaugeChart">
|
||||
<div
|
||||
className="eui-scrollBar"
|
||||
data-test-subj="gaugeChart"
|
||||
css={css`
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
// the FocusTrap is adding extra divs which are making the visualization redraw twice
|
||||
// with a visible glitch. This make the chart library resilient to this extra reflow
|
||||
overflow: hidden;
|
||||
user-select: text;
|
||||
`}
|
||||
>
|
||||
<GaugeComponent
|
||||
{...config}
|
||||
setChartSize={setChartSize}
|
||||
|
|
|
@ -62,6 +62,7 @@ import { DataLayers } from './data_layers';
|
|||
import { SplitChart } from './split_chart';
|
||||
import { LegendSize } from '@kbn/visualizations-plugin/common';
|
||||
import type { LayerCellValueActions } from '../types';
|
||||
import { EuiThemeProvider } from '@elastic/eui';
|
||||
|
||||
const onClickValue = jest.fn();
|
||||
const onClickMultiValue = jest.fn();
|
||||
|
@ -3192,21 +3193,31 @@ describe('XYChart component', () => {
|
|||
},
|
||||
]),
|
||||
]);
|
||||
const component = mount(<XYChart {...defaultProps} args={args} />);
|
||||
const component = mount(
|
||||
<EuiThemeProvider>
|
||||
<XYChart {...defaultProps} args={args} />
|
||||
</EuiThemeProvider>
|
||||
);
|
||||
const groupedAnnotation = component.find(LineAnnotation);
|
||||
|
||||
expect(groupedAnnotation.length).toEqual(1);
|
||||
// styles are passed because they are shared, dataValues is rounded to the interval
|
||||
expect(groupedAnnotation).toMatchSnapshot();
|
||||
// renders numeric icon for grouped annotations
|
||||
const marker = mount(<div>{groupedAnnotation.prop('marker') as React.ReactNode}</div>);
|
||||
const marker = mount(
|
||||
<EuiThemeProvider>
|
||||
<div>{groupedAnnotation.prop('marker') as React.ReactNode}</div>
|
||||
</EuiThemeProvider>
|
||||
);
|
||||
const numberIcon = marker.find('NumberIcon');
|
||||
expect(numberIcon.length).toEqual(1);
|
||||
expect(numberIcon.text()).toEqual('3');
|
||||
|
||||
// checking tooltip
|
||||
const renderLinks = mount(
|
||||
<div>{(groupedAnnotation.prop('customTooltip') as Function)!()}</div>
|
||||
<EuiThemeProvider>
|
||||
<div>{(groupedAnnotation.prop('customTooltip') as Function)!()}</div>
|
||||
</EuiThemeProvider>
|
||||
);
|
||||
expect(renderLinks.text()).toEqual(
|
||||
'Event 1Mar 18, 2022 @ 04:25:00.000Event 2Mar 18, 2022 @ 04:25:00.020Event 3Mar 18, 2022 @ 04:25:00.001'
|
||||
|
|
|
@ -11,7 +11,6 @@ import { FtrService } from '../ftr_provider_context';
|
|||
|
||||
export class AnnotationEditorPageObject extends FtrService {
|
||||
private readonly testSubjects = this.ctx.getService('testSubjects');
|
||||
private readonly find = this.ctx.getService('find');
|
||||
private readonly retry = this.ctx.getService('retry');
|
||||
|
||||
/**
|
||||
|
@ -58,9 +57,7 @@ export class AnnotationEditorPageObject extends FtrService {
|
|||
const queryInput = await this.testSubjects.find('annotation-query-based-query-input');
|
||||
await queryInput.type(config.query);
|
||||
|
||||
const titles = await this.find.allByCssSelector(
|
||||
'.euiFlyout h3.lnsDimensionEditorSection__heading'
|
||||
);
|
||||
const titles = await this.testSubjects.findAll(`lnsDimensionEditorSectionHeading`);
|
||||
const lastTitle = titles[titles.length - 1];
|
||||
await lastTitle.click(); // close query input pop-up
|
||||
await lastTitle.focus(); // scroll down to the bottom of the section
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ReactWrapper, ShallowWrapper, ComponentType } from 'enzyme';
|
||||
import { ReactWrapper, ShallowWrapper, ComponentType, mount } from 'enzyme';
|
||||
import React, { ChangeEvent } from 'react';
|
||||
import { screen, act, render, within } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
@ -17,6 +17,7 @@ import {
|
|||
EuiRange,
|
||||
EuiSelect,
|
||||
EuiComboBoxProps,
|
||||
EuiThemeProvider,
|
||||
} from '@elastic/eui';
|
||||
import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks';
|
||||
import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks';
|
||||
|
@ -26,7 +27,6 @@ import {
|
|||
FormBasedDimensionEditorComponent,
|
||||
FormBasedDimensionEditorProps,
|
||||
} from './dimension_panel';
|
||||
import { mount } from 'enzyme';
|
||||
import { IUiSettingsClient, HttpSetup, CoreStart, NotificationsStart } from '@kbn/core/public';
|
||||
import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public';
|
||||
import { useExistingFieldsReader } from '@kbn/unified-field-list/src/hooks/use_existing_fields';
|
||||
|
@ -167,15 +167,22 @@ const bytesColumn: GenericIndexPatternColumn = {
|
|||
params: { format: { id: 'bytes' } },
|
||||
};
|
||||
|
||||
const services = coreMock.createStart() as unknown as LensAppServices;
|
||||
const wrappingComponent: React.FC<{
|
||||
children: React.ReactNode;
|
||||
}> = ({ children }) => {
|
||||
return (
|
||||
<KibanaContextProvider services={coreMock.createStart() as unknown as LensAppServices}>
|
||||
<EuiThemeProvider>{children}</EuiThemeProvider>
|
||||
</KibanaContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
function mountWithServices(component: React.ReactElement): ReactWrapper {
|
||||
return mount(component, {
|
||||
// This is an elegant way to wrap a component in Enzyme
|
||||
// preserving the root at the component level rather than
|
||||
// at the wrapper one
|
||||
wrappingComponent: KibanaContextProvider as ComponentType<{}>,
|
||||
wrappingComponentProps: { services },
|
||||
wrappingComponent: wrappingComponent as ComponentType<{}>,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -288,7 +295,11 @@ describe('FormBasedDimensionEditor', () => {
|
|||
const Wrapper: React.FC<{
|
||||
children: React.ReactNode;
|
||||
}> = ({ children }) => {
|
||||
return <KibanaContextProvider services={services}>{children}</KibanaContextProvider>;
|
||||
return (
|
||||
<KibanaContextProvider services={coreMock.createStart() as unknown as LensAppServices}>
|
||||
{children}
|
||||
</KibanaContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const rtlRender = render(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue