diff --git a/package.json b/package.json index a1f5ba90dff06..af670efaa684a 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.5.0-canary.1", "@elastic/ems-client": "8.3.3", - "@elastic/eui": "71.0.0", + "@elastic/eui": "72.0.0", "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", diff --git a/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap b/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap index 19bdd11212924..087b5db023ef5 100644 --- a/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap +++ b/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap @@ -265,6 +265,7 @@ exports[`#start() returns \`Context\` component 1`] = ` "euiQuickSelect.tenseLabel": "Time tense", "euiQuickSelect.unitLabel": "Time unit", "euiQuickSelect.valueLabel": "Time value", + "euiQuickSelectPopover.buttonLabel": "Date quick select", "euiRecentlyUsed.legend": "Recently used date ranges", "euiRefreshInterval.fullDescriptionOff": [Function], "euiRefreshInterval.fullDescriptionOn": [Function], diff --git a/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx b/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx index c5237b50c2f08..143da92aae897 100644 --- a/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx +++ b/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx @@ -1323,6 +1323,9 @@ export const getEuiContextMapping = (): EuiTokensObject => { 'euiQuickSelect.valueLabel': i18n.translate('core.euiQuickSelect.valueLabel', { defaultMessage: 'Time value', }), + 'euiQuickSelectPopover.buttonLabel': i18n.translate('core.euiQuickSelectPopover.buttonLabel', { + defaultMessage: 'Date quick select', + }), 'euiRecentlyUsed.legend': i18n.translate('core.euiRecentlyUsed.legend', { defaultMessage: 'Recently used date ranges', }), diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index 45b605d824b63..fd3b925fc3f18 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -84,6 +84,6 @@ export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint '@elastic/ems-client@8.3.3': ['Elastic License 2.0'], - '@elastic/eui@71.0.0': ['SSPL-1.0 OR Elastic License 2.0'], + '@elastic/eui@72.0.0': ['SSPL-1.0 OR Elastic License 2.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry }; diff --git a/src/plugins/kibana_react/public/page_template/with_solution_nav.tsx b/src/plugins/kibana_react/public/page_template/with_solution_nav.tsx index c4fa5363461ba..842573b9d8de4 100644 --- a/src/plugins/kibana_react/public/page_template/with_solution_nav.tsx +++ b/src/plugins/kibana_react/public/page_template/with_solution_nav.tsx @@ -9,7 +9,7 @@ import React, { ComponentType, useState } from 'react'; import classNames from 'classnames'; import { useIsWithinBreakpoints } from '@elastic/eui'; -import { EuiPageSideBarProps } from '@elastic/eui/src/components/page/page_side_bar'; +import { EuiPageSideBarProps_Deprecated as EuiPageSideBarProps } from '@elastic/eui/src/components/page/page_side_bar'; import { KibanaPageTemplateSolutionNav, KibanaPageTemplateSolutionNavProps } from './solution_nav'; import { KibanaPageTemplateProps } from '.'; diff --git a/src/plugins/unified_search/public/dataview_picker/dataview_list.test.tsx b/src/plugins/unified_search/public/dataview_picker/dataview_list.test.tsx index fe6601b90d79c..af30a7650c6ca 100644 --- a/src/plugins/unified_search/public/dataview_picker/dataview_list.test.tsx +++ b/src/plugins/unified_search/public/dataview_picker/dataview_list.test.tsx @@ -30,7 +30,8 @@ function selectDataViewPickerOption(instance: ShallowWrapper, selectedLabel: str ? { ...option, checked: 'on' } : { ...option, checked: undefined } ); - return getDataViewPickerList(instance).prop('onChange')!(options, event); + const selectedOption = { label: selectedLabel }; + return getDataViewPickerList(instance).prop('onChange')!(options, event, selectedOption); } describe('DataView list component', () => { diff --git a/src/plugins/unified_search/public/dataview_picker/text_languages_list.test.tsx b/src/plugins/unified_search/public/dataview_picker/text_languages_list.test.tsx index 21b77534f90a4..1624eefac36e0 100644 --- a/src/plugins/unified_search/public/dataview_picker/text_languages_list.test.tsx +++ b/src/plugins/unified_search/public/dataview_picker/text_languages_list.test.tsx @@ -31,7 +31,8 @@ function selectTextLanguagePickerOption(instance: ShallowWrapper, selectedLabel: ? { ...option, checked: 'on' } : { ...option, checked: undefined } ); - return getTextLanguagesPickerList(instance).prop('onChange')!(options, event); + const selectedOption = { label: selectedLabel }; + return getTextLanguagesPickerList(instance).prop('onChange')!(options, event, selectedOption); } describe('Text based languages list component', () => { diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/date_picker_wrapper/date_picker_wrapper.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/date_picker_wrapper/date_picker_wrapper.tsx index a3f5dbfffe517..e0dba00ec95ee 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/date_picker_wrapper/date_picker_wrapper.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/date_picker_wrapper/date_picker_wrapper.tsx @@ -34,6 +34,7 @@ import { dataVisualizerRefresh$ } from '../../../index_data_visualizer/services/ import { useUrlState } from '../../util/url_state'; const DEFAULT_REFRESH_INTERVAL_MS = 5000; +const DATE_PICKER_MAX_WIDTH = 540; interface TimePickerQuickRange { from: string; @@ -69,10 +70,11 @@ function updateLastRefresh(timeRange?: OnRefreshProps) { } // FIXME: Consolidate this component with ML and AIOps's component -export const DatePickerWrapper: FC<{ isAutoRefreshOnly?: boolean; showRefresh?: boolean }> = ({ - isAutoRefreshOnly, - showRefresh, -}) => { +export const DatePickerWrapper: FC<{ + isAutoRefreshOnly?: boolean; + showRefresh?: boolean; + compact?: boolean; +}> = ({ isAutoRefreshOnly, showRefresh, compact = false }) => { const { services, notifications: { toasts }, @@ -242,9 +244,18 @@ export const DatePickerWrapper: FC<{ isAutoRefreshOnly?: boolean; showRefresh?: - + diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/document_count_chart.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/document_count_chart.tsx index 9b802fa768bff..9e71561f051a3 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/document_count_chart.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/document_count_chart.tsx @@ -9,7 +9,7 @@ import React, { FC, useCallback, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { Axis, - BarSeries, + HistogramBarSeries, BrushEndListener, Chart, ElementClickListener, @@ -22,7 +22,7 @@ import { import moment from 'moment'; import { IUiSettingsClient } from '@kbn/core/public'; import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; -import { EuiLoadingSpinner, EuiFlexItem } from '@elastic/eui'; +import { EuiFlexGroup, EuiLoadingSpinner, EuiFlexItem } from '@elastic/eui'; import { useDataVisualizerKibana } from '../../../../kibana_context'; export interface DocumentCountChartPoint { @@ -137,8 +137,9 @@ export const DocumentCountChart: FC = ({ const timeZone = getTimezone(uiSettings); return ( -
{loading ? ( @@ -147,6 +148,7 @@ export const DocumentCountChart: FC = ({ = ({ 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} /> - = ({ yAccessors={['value']} data={adjustedChartPoints} timeZone={timeZone} + yNice /> )} -
+
); }; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_count_panel/field_count_panel.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/field_count_panel/field_count_panel.tsx index 66db0afb8f895..c5343e4a304c3 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_count_panel/field_count_panel.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_count_panel/field_count_panel.tsx @@ -31,6 +31,7 @@ export const FieldCountPanel: FC = ({ data-test-subj="dataVisualizerFieldCountPanel" responsive={false} className="dvFieldCount__panel" + wrap > diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/fields_stats_grid.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/fields_stats_grid.tsx index 09fbc24f11764..a244aa795cc11 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/fields_stats_grid.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/fields_stats_grid.tsx @@ -85,6 +85,7 @@ export const FieldsStatsGrid: FC = ({ results }) => { gutterSize="xs" style={{ marginLeft: 4 }} data-test-subj="dataVisualizerFieldCountPanel" + responsive={true} > diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/link_card/link_card.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/link_card/link_card.tsx index 855465eeab0c8..746bcf6c5eae0 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/link_card/link_card.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/link_card/link_card.tsx @@ -17,6 +17,7 @@ import { EuiPanel, EuiLink, } from '@elastic/eui'; +import { useCurrentEuiTheme } from '../../hooks/use_current_eui_theme'; export interface LinkCardProps { icon: IconType; @@ -41,6 +42,8 @@ export const LinkCard: FC = ({ isDisabled, 'data-test-subj': dataTestSubj, }) => { + const euiTheme = useCurrentEuiTheme(); + const linkHrefAndOnClickProps = { ...(href ? { href } : {}), ...(onClick ? { onClick } : {}), @@ -62,10 +65,10 @@ export const LinkCard: FC = ({ color="subdued" {...linkHrefAndOnClickProps} > - - + + {typeof icon === 'string' ? ( - + ) : ( icon )} diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/multi_select_picker/multi_select_picker.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/multi_select_picker/multi_select_picker.tsx index 741706a9f45b9..ee737d25591d6 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/multi_select_picker/multi_select_picker.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/multi_select_picker/multi_select_picker.tsx @@ -15,10 +15,11 @@ import { EuiPopoverTitle, EuiSpacer, } from '@elastic/eui'; -import React, { FC, ReactNode, useEffect, useMemo, useState } from 'react'; +import React, { FC, ReactNode, useEffect, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { euiDarkVars as euiThemeDark, euiLightVars as euiThemeLight } from '@kbn/ui-theme'; -import { useDataVisualizerKibana } from '../../../kibana_context'; +import type { SerializedStyles } from '@emotion/react'; +import { css } from '@emotion/react'; +import { useCurrentEuiTheme } from '../../hooks/use_current_eui_theme'; export interface Option { name?: string | ReactNode; @@ -27,6 +28,8 @@ export interface Option { disabled?: boolean; } +const SELECT_PICKER_HEIGHT = '250px'; + const NoFilterItems = () => { return (
@@ -44,15 +47,10 @@ const NoFilterItems = () => { ); }; -export function useCurrentEuiTheme() { - const { services } = useDataVisualizerKibana(); - const uiSettings = services.uiSettings; - return useMemo( - () => (uiSettings.get('theme:darkMode') ? euiThemeDark : euiThemeLight), - [uiSettings] - ); +interface MultiSelectPickerStyles { + filterGroup?: SerializedStyles; + filterItemContainer?: SerializedStyles; } - export const MultiSelectPicker: FC<{ options: Option[]; onChange?: (items: string[]) => void; @@ -60,7 +58,8 @@ export const MultiSelectPicker: FC<{ checkedOptions: string[]; dataTestSubj: string; postfix?: React.ReactElement; -}> = ({ options, onChange, title, checkedOptions, dataTestSubj, postfix }) => { + cssStyles?: MultiSelectPickerStyles; +}> = ({ options, onChange, title, checkedOptions, dataTestSubj, postfix, cssStyles }) => { const euiTheme = useCurrentEuiTheme(); const [items, setItems] = useState(options); @@ -114,7 +113,7 @@ export const MultiSelectPicker: FC<{ ); return ( - + -
+
{Array.isArray(items) && items.length > 0 ? ( items.map((item, index) => { const checked = diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_count_stats/_index.scss b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_count_stats/_index.scss index 0774cb198ea90..f3c6eed07781b 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_count_stats/_index.scss +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_count_stats/_index.scss @@ -8,5 +8,5 @@ .dvFieldCount__item { max-width: 300px; - min-width: 300px; + min-width: 200px; } diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx index 081c062979f7a..7e13e981781dd 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx @@ -88,7 +88,6 @@ export const DataVisualizerTable = ({ ); const [showDistributions, setShowDistributions] = useState(showPreviewByDefault ?? true); const [dimensions, setDimensions] = useState(calculateTableColumnsDimensions()); - const [tableWidth, setTableWidth] = useState(1400); const toggleExpandAll = useCallback( (shouldExpandAll: boolean) => { @@ -109,10 +108,9 @@ export const DataVisualizerTable = ({ throttle((e: { width: number; height: number }) => { // When window or table is resized, // update the column widths and other settings accordingly - setTableWidth(e.width); setDimensions(calculateTableColumnsDimensions(e.width)); }, 500), - [tableWidth] + [] ); const toggleShowDistribution = useCallback(() => { @@ -138,6 +136,8 @@ export const DataVisualizerTable = ({ const columns = useMemo(() => { const expanderColumn: EuiTableComputedColumnType = { name: + // EUI will automatically show an expander button when table is mobile view (where width <700) + // so we need to not render any addition button dimensions.breakPoint !== 'small' ? ( { - const { euiTheme } = useCurrentEuiTheme(); + const euiTheme = useCurrentEuiTheme(); const colorRanges: Record = { [COLOR_RANGE.BLUE]: [ @@ -197,13 +196,3 @@ export const useColorRange = ( }; export type EuiThemeType = typeof euiThemeLight | typeof euiThemeDark; - -export function useCurrentEuiTheme() { - const { - services: { uiSettings }, - } = useDataVisualizerKibana(); - return useMemo( - () => ({ euiTheme: uiSettings.get('theme:darkMode') ? euiThemeDark : euiThemeLight }), - [uiSettings] - ); -} diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/hooks/use_data_viz_chart_theme.ts b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/hooks/use_data_viz_chart_theme.ts index 56b5049786aca..9e21884b6cb4d 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/hooks/use_data_viz_chart_theme.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/hooks/use_data_viz_chart_theme.ts @@ -7,9 +7,9 @@ import type { PartialTheme } from '@elastic/charts'; import { useMemo } from 'react'; -import { useCurrentEuiTheme } from './use_color_range'; +import { useCurrentEuiTheme } from '../../../hooks/use_current_eui_theme'; export const useDataVizChartTheme = (): PartialTheme => { - const { euiTheme } = useCurrentEuiTheme(); + const euiTheme = useCurrentEuiTheme(); const chartTheme = useMemo(() => { const AREA_SERIES_COLOR = euiTheme.euiColorVis0; return { diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/utils.ts b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/utils.ts index 8e2c80c307906..eeb611af477f7 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/utils.ts @@ -40,7 +40,7 @@ export const getTFPercentage = (config: FileBasedFieldVisConfig) => { // Map of DataVisualizerTable breakpoints specific to the table component // Note that the table width is not always the full width of the browser window const TABLE_BREAKPOINTS = { - small: 600, + small: 700, medium: 1000, large: Infinity, // default }; diff --git a/x-pack/plugins/data_visualizer/public/application/common/hooks/use_current_eui_theme.ts b/x-pack/plugins/data_visualizer/public/application/common/hooks/use_current_eui_theme.ts new file mode 100644 index 0000000000000..06ad27ccb21b9 --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/common/hooks/use_current_eui_theme.ts @@ -0,0 +1,19 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo } from 'react'; +import { euiDarkVars as euiThemeDark, euiLightVars as euiThemeLight } from '@kbn/ui-theme'; +import { useDataVisualizerKibana } from '../../kibana_context'; + +export function useCurrentEuiTheme() { + const { services } = useDataVisualizerKibana(); + const uiSettings = services.uiSettings; + return useMemo( + () => (uiSettings.get('theme:darkMode') ? euiThemeDark : euiThemeLight), + [uiSettings] + ); +} diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx index 27c9bc2948336..b7eb35e24ba52 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx @@ -11,6 +11,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiTitle } from '@elastic/eui'; import { DataView } from '@kbn/data-views-plugin/public'; +import { css } from '@emotion/react'; import { flatten } from 'lodash'; import { LinkCardProps } from '../../../common/components/link_card/link_card'; import { useDataVisualizerKibana } from '../../../kibana_context'; @@ -24,13 +25,17 @@ interface Props { searchString?: string | { [key: string]: any }; searchQueryLanguage?: string; getAdditionalLinks?: GetAdditionalLinks; + compact?: boolean; } +const ACTIONS_PANEL_WIDTH = '240px'; + export const ActionsPanel: FC = ({ dataView, searchString, searchQueryLanguage, getAdditionalLinks, + compact, }) => { const [globalState] = useUrlState('_g'); @@ -112,23 +117,33 @@ export const ActionsPanel: FC = ({ data.query, getAdditionalLinks, ]); + const showActionsPanel = + discoverLink || (Array.isArray(asyncHrefCards) && asyncHrefCards.length > 0); // Note we use display:none for the DataRecognizer section as it needs to be // passed the recognizerResults object, and then run the recognizer check which // controls whether the recognizer section is ultimately displayed. - return ( -
+ return showActionsPanel ? ( +
+ +

+ +

+
+ {discoverLink && ( <> - -

- -

-
- = ({ ))}
- ); + ) : null; }; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/_index.scss b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/_index.scss deleted file mode 100644 index c9b1d78320aee..0000000000000 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'index_data_visualizer_view'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/_index_data_visualizer_view.scss b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/_index_data_visualizer_view.scss deleted file mode 100644 index 2a9488da966ea..0000000000000 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/_index_data_visualizer_view.scss +++ /dev/null @@ -1,14 +0,0 @@ -.dataViewTitleHeader { - min-width: 300px; - padding: $euiSizeS 0; - display: flex; - flex-direction: row; - align-items: center; -} - -@include euiBreakpoint('xs', 's', 'm', 'l') { - .dataVisualizerPageHeader { - flex-direction: column; - align-items: flex-start; - } -} diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx index bb9095bc6f269..238ceb960de36 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FC, Fragment, useEffect, useMemo, useState, useCallback, useRef } from 'react'; +import React, { FC, useEffect, useMemo, useState, useCallback, useRef } from 'react'; import { EuiFlexGroup, EuiFlexItem, @@ -23,6 +23,7 @@ import { i18n } from '@kbn/i18n'; import { Filter, FilterStateStore, Query } from '@kbn/es-query'; import { generateFilters } from '@kbn/data-plugin/public'; import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import { useCurrentEuiTheme } from '../../../common/hooks/use_current_eui_theme'; import { DV_RANDOM_SAMPLER_PREFERENCE, useStorage } from '../../hooks/use_storage'; import { FullTimeRangeSelector } from '../full_time_range_selector'; import { usePageUrlState, useUrlState } from '../../../common/util/url_state'; @@ -46,14 +47,11 @@ import { kbnTypeToJobType } from '../../../common/util/field_types_utils'; import { SearchPanel } from '../search_panel'; import { ActionsPanel } from '../actions_panel'; import { DatePickerWrapper } from '../../../common/components/date_picker_wrapper'; -import { HelpMenu } from '../../../common/components/help_menu'; import { createMergedEsQuery } from '../../utils/saved_search_utils'; import { DataVisualizerDataViewManagement } from '../data_view_management'; import { GetAdditionalLinks } from '../../../common/components/results_links'; import { useDataVisualizerGridData } from '../../hooks/use_data_visualizer_grid_data'; import { DataVisualizerGridInput } from '../../embeddables/grid_embeddable/grid_embeddable'; -// TODO port to `@emotion/react` once `useEuiBreakpoint` is available https://github.com/elastic/eui/pull/6057 -import './_index.scss'; import { RANDOM_SAMPLER_OPTION, RandomSamplerOption } from '../../constants/random_sampler'; interface DataVisualizerPageState { @@ -116,9 +114,12 @@ export interface IndexDataVisualizerViewProps { currentSavedSearch: SavedSearchSavedObject | null; currentSessionId?: string; getAdditionalLinks?: GetAdditionalLinks; + compact?: boolean; } export const IndexDataVisualizerView: FC = (dataVisualizerProps) => { + const euiTheme = useCurrentEuiTheme(); + const [savedRandomSamplerPreference, saveRandomSamplerPreference] = useStorage( DV_RANDOM_SAMPLER_PREFERENCE, @@ -136,7 +137,7 @@ export const IndexDataVisualizerView: FC = (dataVi ); const { services } = useDataVisualizerKibana(); - const { docLinks, notifications, uiSettings, data } = services; + const { notifications, uiSettings, data } = services; const { toasts } = notifications; const [dataVisualizerListState, setDataVisualizerListState] = usePageUrlState( @@ -149,7 +150,7 @@ export const IndexDataVisualizerView: FC = (dataVi dataVisualizerProps.currentSavedSearch ); - const { currentDataView, currentSessionId, getAdditionalLinks } = dataVisualizerProps; + const { currentDataView, currentSessionId, getAdditionalLinks, compact } = dataVisualizerProps; useEffect(() => { if (dataVisualizerProps?.currentSavedSearch !== undefined) { @@ -200,7 +201,7 @@ export const IndexDataVisualizerView: FC = (dataVi queryLanguage: SearchQueryLanguage; filters: Filter[]; }) => { - // When the user loads saved search and then clear or modify the query + // When the user loads saved search and then clears or modifies the query // we should remove the saved search and replace it with the index pattern id if (currentSavedSearch !== null) { setCurrentSavedSearch(null); @@ -217,12 +218,6 @@ export const IndexDataVisualizerView: FC = (dataVi [currentSavedSearch, dataVisualizerListState, setDataVisualizerListState] ); - const samplerShardSize = - dataVisualizerListState.samplerShardSize ?? restorableDefaults.samplerShardSize; - const setSamplerShardSize = (value: number) => { - setDataVisualizerListState({ ...dataVisualizerListState, samplerShardSize: value }); - }; - const visibleFieldTypes = dataVisualizerListState.visibleFieldTypes ?? restorableDefaults.visibleFieldTypes; const setVisibleFieldTypes = (values: string[]) => { @@ -386,8 +381,6 @@ export const IndexDataVisualizerView: FC = (dataVi ] ); - const wizardPanelWidth = '280px'; - const fieldsCountStats: TotalFieldsStats | undefined = useMemo(() => { let _visibleFieldsCount = 0; let _totalFieldsCount = 0; @@ -454,131 +447,136 @@ export const IndexDataVisualizerView: FC = (dataVi () => currentDataView.timeFieldName !== undefined && currentDataView.timeFieldName !== '', [currentDataView.timeFieldName] ); - const helpLink = docLinks.links.ml.guide; - return ( - - - - - - -
- -

{currentDataView.getName()}

-
- -
-
- + + + + + - {hasValidTimeField ? ( - - - - ) : null} + +

{currentDataView.getName()}

+
+ +
+
+ + {compact ? : null} + + {hasValidTimeField ? ( - - -
-
-
- - - - - - + - - {overallStats?.totalCount !== undefined && ( - <> - - - - - - )} - - - - - - items={configs} - pageState={dataVisualizerListState} - updatePageState={setDataVisualizerListState} - getItemIdToExpandedRowMap={getItemIdToExpandedRowMap} - extendedColumns={extendedColumns} - loading={progress < 100} - overallStatsRunning={overallStatsProgress.isRunning} - showPreviewByDefault={dataVisualizerListState.showDistributions ?? true} - onChange={setDataVisualizerListState} - totalCount={overallStats.totalCount} - /> - - - - + +
+
+
+ + + + + + - - - -
- -
+ {overallStats?.totalCount !== undefined && ( + <> + + + + + + )} + + + + + + items={configs} + pageState={dataVisualizerListState} + updatePageState={setDataVisualizerListState} + getItemIdToExpandedRowMap={getItemIdToExpandedRowMap} + extendedColumns={extendedColumns} + loading={progress < 100} + overallStatsRunning={overallStatsProgress.isRunning} + showPreviewByDefault={dataVisualizerListState.showDistributions ?? true} + onChange={setDataVisualizerListState} + totalCount={overallStats.totalCount} + /> + + + {compact ? : null} + + + + + + ); }; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx index f438780e8dbe4..697aecf2bb2f6 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx @@ -8,6 +8,8 @@ import React, { FC, useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { css } from '@emotion/react'; +import { useCurrentEuiTheme } from '../../../common/hooks/use_current_eui_theme'; import { FieldTypesHelpPopover } from '../../../common/components/field_types_filter/field_types_help_popover'; import type { SupportedFieldType } from '../../../../../common/types'; import { FieldTypeIcon } from '../../../common/components/field_type_icon'; @@ -19,6 +21,7 @@ export const DataVisualizerFieldTypeFilter: FC<{ setVisibleFieldTypes(q: string[]): void; visibleFieldTypes: string[]; }> = ({ indexedFieldTypes, setVisibleFieldTypes, visibleFieldTypes }) => { + const euiTheme = useCurrentEuiTheme(); const options: Option[] = useMemo(() => { return indexedFieldTypes.map((indexedFieldName) => { const label = jobTypeLabels[indexedFieldName] ?? ''; @@ -55,6 +58,11 @@ export const DataVisualizerFieldTypeFilter: FC<{ checkedOptions={visibleFieldTypes} dataTestSubj={'dataVisualizerFieldTypeSelect'} postfix={} + cssStyles={{ + filterGroup: css` + margin-left: ${euiTheme.euiSizeS}; + `, + }} /> ); diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.scss b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.scss index 6b0624fae2757..699e76a9c58fb 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.scss +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.scss @@ -1,6 +1,5 @@ .dvSearchPanel__controls { flex-direction: row; - padding: $euiSizeS; } .dvSearchPanel__container { @@ -12,7 +11,7 @@ flex-direction: column; } .dvSearchBar { - min-width: #{'max(100%, 500px)'}; + min-width: #{'max(100%, 300px)'}; } .dvSearchPanel__controls { padding: 0; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx index 5b47bb820b9ab..df11ab8dd5cd1 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx @@ -6,12 +6,11 @@ */ import React, { FC, useEffect, useState } from 'react'; -import { EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; +import { EuiFlexItem, EuiFlexGroup, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Query, Filter } from '@kbn/es-query'; import type { TimeRange } from '@kbn/es-query'; import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; -import { css } from '@emotion/react'; import { isDefined } from '../../../common/util/is_defined'; import { DataVisualizerFieldNamesFilter } from './field_name_filter'; import { DataVisualizerFieldTypeFilter } from './field_type_filter'; @@ -26,8 +25,6 @@ interface Props { searchString: Query['query']; searchQuery: Query['query']; searchQueryLanguage: SearchQueryLanguage; - samplerShardSize: number; - setSamplerShardSize(s: number): void; overallStats: OverallStats; indexedFieldTypes: SupportedFieldType[]; setVisibleFieldTypes(q: string[]): void; @@ -47,14 +44,13 @@ interface Props { }): void; showEmptyFields: boolean; onAddFilter?: (field: DataViewField | string, value: string, type: '+' | '-') => void; + compact?: boolean; } export const SearchPanel: FC = ({ dataView, searchString, searchQueryLanguage, - samplerShardSize, - setSamplerShardSize, overallStats, indexedFieldTypes, setVisibleFieldTypes, @@ -63,6 +59,7 @@ export const SearchPanel: FC = ({ visibleFieldNames, setSearchParams, showEmptyFields, + compact, }) => { const { services: { @@ -120,7 +117,7 @@ export const SearchPanel: FC = ({ return ( = ({ /> + {compact ? : null} ; getAdditionalLinks?: GetAdditionalLinks; } @@ -70,9 +71,10 @@ export const getLocatorParams = (params: { return locatorParams; }; -export const DataVisualizerUrlStateContextProvider: FC< - DataVisualizerUrlStateContextProviderProps -> = ({ IndexDataVisualizerComponent, getAdditionalLinks }) => { +export const DataVisualizerStateContextProvider: FC = ({ + IndexDataVisualizerComponent, + getAdditionalLinks, +}) => { const { services } = useDataVisualizerKibana(); const { data: { dataViews, search }, @@ -240,15 +242,36 @@ export const DataVisualizerUrlStateContextProvider: FC< [history, urlSearchString] ); + const [panelWidth, setPanelWidth] = useState(1600); + + // eslint-disable-next-line react-hooks/exhaustive-deps + const resizeHandler = useCallback( + throttle((e: { width: number; height: number }) => { + // When window or table is resized, + // update the page body width + setPanelWidth(e.width); + }, 500), + [] + ); + const compact = useMemo(() => panelWidth <= 1024, [panelWidth]); + return ( {currentDataView ? ( - + // Needs ResizeObserver to measure window width - side bar navigation + + {(resizeRef) => ( +
+ +
+ )} +
) : (
)} @@ -293,7 +316,7 @@ export const IndexDataVisualizer: FC<{ return ( - diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_document_stats.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_document_stats.ts index 7607dc30c8130..f74a8800d2bd0 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_document_stats.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_document_stats.ts @@ -21,52 +21,6 @@ import type { const MINIMUM_RANDOM_SAMPLER_DOC_COUNT = 100000; const DEFAULT_INITIAL_RANDOM_SAMPLER_PROBABILITY = 0.000001; -export const getDocumentCountStatsRequest = (params: OverallStatsSearchStrategyParams) => { - const { - index, - timeFieldName, - earliest: earliestMs, - latest: latestMs, - runtimeFieldMap, - searchQuery, - intervalMs, - fieldsToFetch, - } = params; - - const size = 0; - const filterCriteria = buildBaseFilterCriteria(timeFieldName, earliestMs, latestMs, searchQuery); - - // Don't use the sampler aggregation as this can lead to some potentially - // confusing date histogram results depending on the date range of data amongst shards. - const aggs = { - eventRate: { - date_histogram: { - field: timeFieldName, - fixed_interval: `${intervalMs}ms`, - min_doc_count: 1, - }, - }, - }; - - const searchBody = { - query: { - bool: { - filter: filterCriteria, - }, - }, - ...(!fieldsToFetch && timeFieldName !== undefined && intervalMs !== undefined && intervalMs > 0 - ? { aggs } - : {}), - ...(isPopulatedObject(runtimeFieldMap) ? { runtime_mappings: runtimeFieldMap } : {}), - track_total_hits: true, - size, - }; - return { - index, - body: searchBody, - }; -}; - export const getDocumentCountStats = async ( search: DataPublicPluginStart['search'], params: OverallStatsSearchStrategyParams, @@ -104,7 +58,11 @@ export const getDocumentCountStats = async ( date_histogram: { field: timeFieldName, fixed_interval: `${intervalMs}ms`, - min_doc_count: 1, + min_doc_count: 0, + extended_bounds: { + min: earliestMs, + max: latestMs, + }, }, }, }; diff --git a/x-pack/plugins/fleet/server/types/rest_spec/agent.test.ts b/x-pack/plugins/fleet/server/types/rest_spec/agent.test.ts new file mode 100644 index 0000000000000..a978c2ffe9479 --- /dev/null +++ b/x-pack/plugins/fleet/server/types/rest_spec/agent.test.ts @@ -0,0 +1,27 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { GetAgentsRequestSchema } from './agent'; + +describe('GetAgentsRequestSchema', () => { + it('should allow pagination with less than 10000 agents', () => { + expect(() => + GetAgentsRequestSchema.query.validate({ + page: 500, + perPage: 20, + }) + ).not.toThrow(); + }); + it('should not allow pagination to go over 10000 agents', () => { + expect(() => + GetAgentsRequestSchema.query.validate({ + page: 501, + perPage: 20, + }) + ).toThrowError(/You cannot use page and perPage page over 10000 agents/); + }); +}); diff --git a/x-pack/plugins/fleet/server/types/rest_spec/agent.ts b/x-pack/plugins/fleet/server/types/rest_spec/agent.ts index 709e8e8d27159..305b6f16f90d6 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/agent.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/agent.ts @@ -9,18 +9,29 @@ import { schema } from '@kbn/config-schema'; import moment from 'moment'; import semverIsValid from 'semver/functions/valid'; +import { SO_SEARCH_LIMIT } from '../../constants'; + import { NewAgentActionSchema } from '../models'; export const GetAgentsRequestSchema = { - query: schema.object({ - page: schema.number({ defaultValue: 1 }), - perPage: schema.number({ defaultValue: 20 }), - kuery: schema.maybe(schema.string()), - showInactive: schema.boolean({ defaultValue: false }), - showUpgradeable: schema.boolean({ defaultValue: false }), - sortField: schema.maybe(schema.string()), - sortOrder: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), - }), + query: schema.object( + { + page: schema.number({ defaultValue: 1 }), + perPage: schema.number({ defaultValue: 20 }), + kuery: schema.maybe(schema.string()), + showInactive: schema.boolean({ defaultValue: false }), + showUpgradeable: schema.boolean({ defaultValue: false }), + sortField: schema.maybe(schema.string()), + sortOrder: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), + }, + { + validate: (request) => { + if (request.page * request.perPage > SO_SEARCH_LIMIT) { + return `You cannot use page and perPage page over ${SO_SEARCH_LIMIT} agents`; + } + }, + } + ), }; export const GetOneAgentRequestSchema = { diff --git a/x-pack/plugins/graph/public/components/field_manager/field_manager.test.tsx b/x-pack/plugins/graph/public/components/field_manager/field_manager.test.tsx index 61682f0a8cc8c..f84822129c7c3 100644 --- a/x-pack/plugins/graph/public/components/field_manager/field_manager.test.tsx +++ b/x-pack/plugins/graph/public/components/field_manager/field_manager.test.tsx @@ -111,7 +111,8 @@ describe('field_manager', () => { act(() => { getInstance().find(FieldPicker).dive().find(EuiSelectable).prop('onChange')!( [{ checked: 'on', label: 'field3' }], - event + event, + { checked: 'on', label: 'field3' } ); }); diff --git a/x-pack/plugins/lens/public/datasources/form_based/layerpanel.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/layerpanel.test.tsx index 86fd5490f383b..2b4fc7f740524 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/layerpanel.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/layerpanel.test.tsx @@ -236,7 +236,8 @@ describe('Layer Data Panel', () => { ? { ...option, checked: 'on' } : { ...option, checked: undefined } ); - return getIndexPatternPickerList(instance).prop('onChange')!(options, event); + const selectedOption = { label: selectedLabel }; + return getIndexPatternPickerList(instance).prop('onChange')!(options, event, selectedOption); } function getIndexPatternPickerOptions(instance: ShallowWrapper) { diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.tsx.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.tsx.snap index c3b0dc07f67ab..f58b60de5fb02 100644 --- a/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.tsx.snap +++ b/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.tsx.snap @@ -53,6 +53,7 @@ exports[`UploadLicense should display a modal when license requires acknowledgem