diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index 1e84ae309bd..7546b49620a 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -539,6 +539,8 @@ export interface AppMountParameters { * Optional datasource id to pass while mounting app */ dataSourceId?: string; + + optionalRef?: Record>; } /** diff --git a/src/plugins/data/public/ui/search_bar/search_bar.tsx b/src/plugins/data/public/ui/search_bar/search_bar.tsx index 11914f13444..c753c9c5c69 100644 --- a/src/plugins/data/public/ui/search_bar/search_bar.tsx +++ b/src/plugins/data/public/ui/search_bar/search_bar.tsx @@ -96,6 +96,7 @@ export interface SearchBarOwnProps { onRefresh?: (payload: { dateRange: TimeRange }) => void; indicateNoData?: boolean; + datePickkerRef?: any; } export type SearchBarProps = SearchBarOwnProps & SearchBarInjectedDeps; diff --git a/src/plugins/data_explorer/public/components/app_container.scss b/src/plugins/data_explorer/public/components/app_container.scss index 7bd5ed6f69f..d4fc344e273 100644 --- a/src/plugins/data_explorer/public/components/app_container.scss +++ b/src/plugins/data_explorer/public/components/app_container.scss @@ -20,3 +20,9 @@ $osdHeaderOffset: $euiHeaderHeightCompensation; .headerIsExpanded .deLayout { height: calc(100vh - #{$osdHeaderOffset * 2}); } + +.mainPage { + width: 100%; + overflow-x: hidden; + overflow-y: auto; +} diff --git a/src/plugins/data_explorer/public/components/app_container.tsx b/src/plugins/data_explorer/public/components/app_container.tsx index bf4a02bd223..080d16ed341 100644 --- a/src/plugins/data_explorer/public/components/app_container.tsx +++ b/src/plugins/data_explorer/public/components/app_container.tsx @@ -3,8 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { memo } from 'react'; -import { EuiPage, EuiPageBody, EuiResizableContainer, useIsWithinBreakpoints } from '@elastic/eui'; +import React, { memo, useRef } from 'react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiPage, + EuiPageBody, + EuiResizableContainer, + useIsWithinBreakpoints, +} from '@elastic/eui'; import { Suspense } from 'react'; import { AppMountParameters } from '../../../../core/public'; import { Sidebar } from './sidebar'; @@ -17,6 +24,8 @@ export const AppContainer = React.memo( ({ view, params }: { view?: View; params: AppMountParameters }) => { const isMobile = useIsWithinBreakpoints(['xs', 's', 'm']); // TODO: Make this more robust. + const topLinkRef = useRef(null); + const datePickerRef = useRef(null); if (!view) { return ; } @@ -26,38 +35,59 @@ export const AppContainer = React.memo( const MemoizedPanel = memo(Panel); const MemoizedCanvas = memo(Canvas); + params.optionalRef = { + topLinkRef, + datePickerRef, + }; + // Render the application DOM. return ( - - {/* TODO: improve fallback state */} - Loading...}> - - - {(EuiResizablePanel, EuiResizableButton) => ( - <> - - - - - - +
+ + +
+ + +
+ + + + + {/* TODO: improve fallback state */} + Loading...
}> + + + {(EuiResizablePanel, EuiResizableButton) => ( + <> + + + + + + - - - - - - - )} - - - - + + + + + + + )} + + + + +
); }, (prevProps, nextProps) => { diff --git a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx index 6a5f815f9b3..f3b141ea987 100644 --- a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx +++ b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx @@ -29,7 +29,8 @@ import { OpenSearchPanel } from './open_search_panel'; export const getTopNavLinks = ( services: DiscoverViewServices, inspectorAdapters: Adapters, - savedSearch: SavedSearch + savedSearch: SavedSearch, + isEnhancementEnabled: boolean = false ) => { const { history, @@ -44,7 +45,7 @@ export const getTopNavLinks = ( osdUrlStateStorage, } = services; - const newSearch = { + const newSearch: TopNavMenuData = { id: 'new', label: i18n.translate('discover.localMenu.localMenu.newSearchTitle', { defaultMessage: 'New', @@ -61,6 +62,7 @@ export const getTopNavLinks = ( ariaLabel: i18n.translate('discover.topNav.discoverNewButtonLabel', { defaultMessage: `New Search`, }), + iconType: 'plusInCircle', }; const saveSearch: TopNavMenuData = { @@ -160,9 +162,10 @@ export const getTopNavLinks = ( ); showSaveModal(saveModal, core.i18n.Context); }, + iconType: 'save', }; - const openSearch = { + const openSearch: TopNavMenuData = { id: 'open', label: i18n.translate('discover.localMenu.openTitle', { defaultMessage: 'Open', @@ -190,6 +193,7 @@ export const getTopNavLinks = ( ) ); }, + iconType: 'folderOpen', }; const shareSearch: TopNavMenuData = { @@ -225,9 +229,10 @@ export const getTopNavLinks = ( isDirty: !savedSearch.id || state.isDirty || false, }); }, + iconType: 'share', }; - const inspectSearch = { + const inspectSearch: TopNavMenuData = { id: 'inspect', label: i18n.translate('discover.localMenu.inspectTitle', { defaultMessage: 'Inspect', @@ -244,15 +249,28 @@ export const getTopNavLinks = ( title: savedSearch?.title, }); }, + iconType: 'inspect', }; - return [ + const topNavLinksArray = [ newSearch, ...(capabilities.discover?.save ? [saveSearch] : []), openSearch, ...(share ? [shareSearch] : []), // Show share option only if share plugin is available inspectSearch, ]; + + if (!isEnhancementEnabled) { + return topNavLinksArray.map((topNavLink) => { + if (topNavLink) { + const { iconType, ...rest } = topNavLink; // Removing the Icon Type property to maintain consistency with older Nav Bar + return rest; + } + return topNavLink; + }); + } + + return topNavLinksArray; }; // TODO: This does not seem to affect the share menu. need to look into it in future diff --git a/src/plugins/discover/public/application/view_components/canvas/discover_canvas.scss b/src/plugins/discover/public/application/view_components/canvas/discover_canvas.scss index 2c2c8dfe8eb..e0ab20a1529 100644 --- a/src/plugins/discover/public/application/view_components/canvas/discover_canvas.scss +++ b/src/plugins/discover/public/application/view_components/canvas/discover_canvas.scss @@ -45,3 +45,9 @@ } } } + +.topNav { + .hidden { + display: none; + } +} diff --git a/src/plugins/discover/public/application/view_components/canvas/index.tsx b/src/plugins/discover/public/application/view_components/canvas/index.tsx index 9511448f025..149fa3490de 100644 --- a/src/plugins/discover/public/application/view_components/canvas/index.tsx +++ b/src/plugins/discover/public/application/view_components/canvas/index.tsx @@ -26,7 +26,7 @@ import './discover_canvas.scss'; import { getNewDiscoverSetting, setNewDiscoverSetting } from '../../components/utils/local_storage'; // eslint-disable-next-line import/no-default-export -export default function DiscoverCanvas({ setHeaderActionMenu, history }: ViewProps) { +export default function DiscoverCanvas({ setHeaderActionMenu, history, optionalRef }: ViewProps) { const panelRef = useRef(null); const { data$, refetch$, indexPattern } = useDiscoverContext(); const { @@ -40,6 +40,7 @@ export default function DiscoverCanvas({ setHeaderActionMenu, history }: ViewPro columns: stateColumns !== undefined ? stateColumns : buildColumns([]), }; }); + const isEnhancementsEnabled = uiSettings.get('query:enhancements:enabled'); const filteredColumns = filterColumns( columns, indexPattern, @@ -165,12 +166,15 @@ export default function DiscoverCanvas({ setHeaderActionMenu, history }: ViewPro className="dscCanvas" > + {fetchState.status === ResultStatus.NO_RESULTS && ( )} diff --git a/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx b/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx index adb4152cc40..aedd96da78e 100644 --- a/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx +++ b/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx @@ -5,6 +5,8 @@ import React, { useEffect, useMemo, useState } from 'react'; import { Query, TimeRange } from 'src/plugins/data/common'; +import { createPortal } from 'react-dom'; +import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { AppMountParameters } from '../../../../../../core/public'; import { connectStorageToQueryState, opensearchFilters } from '../../../../../data/public'; import { useOpenSearchDashboards } from '../../../../../opensearch_dashboards_react/public'; @@ -15,16 +17,19 @@ import { getTopNavLinks } from '../../components/top_nav/get_top_nav_links'; import { getRootBreadcrumbs } from '../../helpers/breadcrumbs'; import { useDiscoverContext } from '../context'; import { useDispatch, setSavedQuery, useSelector } from '../../utils/state_management'; +import './discover_canvas.scss'; export interface TopNavProps { opts: { setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; onQuerySubmit: (payload: { dateRange: TimeRange; query?: Query }, isUpdate?: boolean) => void; + optionalRef?: Record>; }; showSaveQuery: boolean; + isEnhancementsEnabled?: boolean; } -export const TopNav = ({ opts, showSaveQuery }: TopNavProps) => { +export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavProps) => { const { services } = useOpenSearchDashboards(); const { inspectorAdapters, savedSearch, indexPattern } = useDiscoverContext(); const [indexPatterns, setIndexPatterns] = useState(undefined); @@ -43,7 +48,9 @@ export const TopNav = ({ opts, showSaveQuery }: TopNavProps) => { osdUrlStateStorage, } = services; - const topNavLinks = savedSearch ? getTopNavLinks(services, inspectorAdapters, savedSearch) : []; + const topNavLinks = savedSearch + ? getTopNavLinks(services, inspectorAdapters, savedSearch, isEnhancementsEnabled) + : []; connectStorageToQueryState(services.data.query, osdUrlStateStorage, { filters: opensearchFilters.FilterStateStore.APP_STATE, @@ -88,22 +95,43 @@ export const TopNav = ({ opts, showSaveQuery }: TopNavProps) => { }; return ( - + <> + {isEnhancementsEnabled && + !!opts?.optionalRef?.topLinkRef?.current && + createPortal( + + {topNavLinks.map((topNavLink) => ( + + { + topNavLink.run(event.currentTarget); + }} + iconType={topNavLink.iconType} + aria-label={topNavLink.ariaLabel} + /> + + ))} + , + opts.optionalRef.topLinkRef.current + )} + + ); }; diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx index 322ed11d639..c7a3220a896 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx @@ -30,7 +30,6 @@ import { EuiButtonProps } from '@elastic/eui'; import { EuiIconType } from '@elastic/eui/src/components/icon/icon'; -import { string } from 'mathjs'; export type TopNavMenuAction = (anchorElement: HTMLElement) => void;