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 a3f5dbfffe517c1..e0dba00ec95eee0 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 9b802fa768bffbf..9e71561f051a357 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 66db0afb8f895e7..c5343e4a304c3ad 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 09fbc24f1176404..a244aa795cc11d4 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 855465eeab0c809..746bcf6c5eae0c2 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 741706a9f45b994..ee737d25591d614 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 0774cb198ea90ca..f3c6eed07781bc0 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 081c062979f7ae6..7e13e981781dd66 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 56b5049786acaf7..9e21884b6cb4d03 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 8e2c80c307906d1..eeb611af477f722 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 000000000000000..06ad27ccb21b99c --- /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 27c9bc29483364e..b7eb35e24ba526b 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 c9b1d78320aee4b..000000000000000 --- 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 2a9488da966eabe..000000000000000 --- 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 bb9095bc6f26981..238ceb960de3629 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 f438780e8dbe406..697aecf2bb2f6a6 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 6b0624fae27576f..699e76a9c58fbd3 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 5b47bb820b9ab07..df11ab8dd5cd152 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 7607dc30c81301d..f74a8800d2bd07e 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, + }, }, }, };