diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx index 015fb997c29ed..e088678a13562 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx @@ -10,7 +10,6 @@ import { mockUseRouteMatch } from '../../../__mocks__/react_router'; import { mockEngineValues } from '../../__mocks__'; jest.mock('../../../shared/layout', () => ({ - ...jest.requireActual('../../../shared/layout'), // TODO: Remove once side nav components are gone generateNavLink: jest.fn(({ to }) => ({ href: to })), })); @@ -20,9 +19,7 @@ import { shallow } from 'enzyme'; import { EuiBadge, EuiIcon } from '@elastic/eui'; -import { rerender } from '../../../test_helpers'; - -import { useEngineNav, EngineNav } from './engine_nav'; +import { useEngineNav } from './engine_nav'; describe('useEngineNav', () => { const values = { ...mockEngineValues, myRole: {}, dataLoading: false }; @@ -321,182 +318,3 @@ describe('useEngineNav', () => { }); }); }); - -describe('EngineNav', () => { - const values = { ...mockEngineValues, myRole: {}, dataLoading: false }; - - beforeEach(() => { - setMockValues(values); - }); - - it('does not render if async data is still loading', () => { - setMockValues({ ...values, dataLoading: true }); - const wrapper = shallow(); - expect(wrapper.isEmptyRender()).toBe(true); - }); - - it('does not render without an engine name', () => { - setMockValues({ ...values, engineName: '' }); - const wrapper = shallow(); - expect(wrapper.isEmptyRender()).toBe(true); - }); - - it('renders an engine label and badges', () => { - setMockValues({ ...values, isSampleEngine: false, isMetaEngine: false }); - const wrapper = shallow(); - const label = wrapper.find('[data-test-subj="EngineLabel"]').find('.eui-textTruncate'); - - expect(label.text()).toEqual('SOME-ENGINE'); - expect(wrapper.find(EuiBadge)).toHaveLength(0); - - setMockValues({ ...values, isSampleEngine: true }); - rerender(wrapper); - expect(wrapper.find(EuiBadge).prop('children')).toEqual('SAMPLE ENGINE'); - - setMockValues({ ...values, isMetaEngine: true }); - rerender(wrapper); - expect(wrapper.find(EuiBadge).prop('children')).toEqual('META ENGINE'); - }); - - it('renders a default engine overview link', () => { - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineOverviewLink"]')).toHaveLength(1); - }); - - it('renders an analytics link', () => { - setMockValues({ ...values, myRole: { canViewEngineAnalytics: true } }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineAnalyticsLink"]')).toHaveLength(1); - }); - - it('renders a documents link', () => { - setMockValues({ ...values, myRole: { canViewEngineDocuments: true } }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineDocumentsLink"]')).toHaveLength(1); - }); - - it('renders a schema link', () => { - setMockValues({ ...values, myRole: { canViewEngineSchema: true } }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineSchemaLink"]')).toHaveLength(1); - }); - - describe('schema nav icons', () => { - const myRole = { canViewEngineSchema: true }; - - it('renders schema errors alert icon', () => { - setMockValues({ ...values, myRole, hasSchemaErrors: true }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineNavSchemaErrors"]')).toHaveLength(1); - }); - - it('renders unconfirmed schema fields info icon', () => { - setMockValues({ ...values, myRole, hasUnconfirmedSchemaFields: true }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineNavSchemaUnconfirmedFields"]')).toHaveLength(1); - }); - - it('renders schema conflicts alert icon', () => { - setMockValues({ ...values, myRole, hasSchemaConflicts: true }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineNavSchemaConflicts"]')).toHaveLength(1); - }); - }); - - describe('crawler link', () => { - const myRole = { canViewEngineCrawler: true }; - - it('renders', () => { - setMockValues({ ...values, myRole }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineCrawlerLink"]')).toHaveLength(1); - }); - - it('does not render for meta engines', () => { - setMockValues({ ...values, myRole, isMetaEngine: true }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineCrawlerLink"]')).toHaveLength(0); - }); - }); - - describe('meta engine source engines link', () => { - const myRole = { canViewMetaEngineSourceEngines: true }; - - it('renders', () => { - setMockValues({ ...values, myRole, isMetaEngine: true }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="MetaEngineEnginesLink"]')).toHaveLength(1); - }); - - it('does not render for non meta engines', () => { - setMockValues({ ...values, myRole, isMetaEngine: false }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="MetaEngineEnginesLink"]')).toHaveLength(0); - }); - }); - - it('renders a relevance tuning link', () => { - setMockValues({ ...values, myRole: { canManageEngineRelevanceTuning: true } }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineRelevanceTuningLink"]')).toHaveLength(1); - }); - - describe('relevance tuning nav icons', () => { - const myRole = { canManageEngineRelevanceTuning: true }; - - it('renders unconfirmed schema fields info icon', () => { - const engine = { unsearchedUnconfirmedFields: true }; - setMockValues({ ...values, myRole, engine }); - const wrapper = shallow(); - expect( - wrapper.find('[data-test-subj="EngineNavRelevanceTuningUnsearchedFields"]') - ).toHaveLength(1); - }); - - it('renders schema conflicts alert icon', () => { - const engine = { invalidBoosts: true }; - setMockValues({ ...values, myRole, engine }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineNavRelevanceTuningInvalidBoosts"]')).toHaveLength( - 1 - ); - }); - - it('can render multiple icons', () => { - const engine = { invalidBoosts: true, unsearchedUnconfirmedFields: true }; - setMockValues({ ...values, myRole, engine }); - const wrapper = shallow(); - expect(wrapper.find(EuiIcon)).toHaveLength(2); - }); - }); - - it('renders a synonyms link', () => { - setMockValues({ ...values, myRole: { canManageEngineSynonyms: true } }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineSynonymsLink"]')).toHaveLength(1); - }); - - it('renders a curations link', () => { - setMockValues({ ...values, myRole: { canManageEngineCurations: true } }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineCurationsLink"]')).toHaveLength(1); - }); - - it('renders a results settings link', () => { - setMockValues({ ...values, myRole: { canManageEngineResultSettings: true } }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineResultSettingsLink"]')).toHaveLength(1); - }); - - it('renders a Search UI link', () => { - setMockValues({ ...values, myRole: { canManageEngineSearchUi: true } }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineSearchUILink"]')).toHaveLength(1); - }); - - it('renders an API logs link', () => { - setMockValues({ ...values, myRole: { canViewEngineApiLogs: true } }); - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineAPILogsLink"]')).toHaveLength(1); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx index 76e751cf4da5f..70f2d04a5123d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx @@ -10,17 +10,10 @@ import { useRouteMatch } from 'react-router-dom'; import { useValues } from 'kea'; -import { - EuiSideNavItemType, - EuiText, - EuiBadge, - EuiIcon, - EuiFlexGroup, - EuiFlexItem, -} from '@elastic/eui'; +import { EuiSideNavItemType, EuiText, EuiBadge, EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { generateNavLink, SideNavLink, SideNavItem } from '../../../shared/layout'; +import { generateNavLink } from '../../../shared/layout'; import { AppLogic } from '../../app_logic'; import { ENGINE_PATH, @@ -49,8 +42,6 @@ import { SCHEMA_TITLE } from '../schema'; import { SEARCH_UI_TITLE } from '../search_ui'; import { SYNONYMS_TITLE } from '../synonyms'; -import { EngineDetails } from './types'; - import { EngineLogic, generateEnginePath } from './'; import './engine_nav.scss'; @@ -198,7 +189,10 @@ export const useEngineNav = () => { navItems.push({ id: 'crawler', name: CRAWLER_TITLE, - ...generateNavLink({ to: generateEnginePath(ENGINE_CRAWLER_PATH) }), + ...generateNavLink({ + to: generateEnginePath(ENGINE_CRAWLER_PATH), + shouldShowActiveForSubroutes: true, + }), 'data-test-subj': 'EngineCrawlerLink', }); } @@ -301,220 +295,3 @@ export const useEngineNav = () => { return navItems; }; - -// TODO: Delete the below once page template migration is complete - -export const EngineNav: React.FC = () => { - const { - myRole: { - canViewEngineAnalytics, - canViewEngineDocuments, - canViewEngineSchema, - canViewEngineCrawler, - canViewMetaEngineSourceEngines, - canManageEngineSynonyms, - canManageEngineCurations, - canManageEngineRelevanceTuning, - canManageEngineResultSettings, - canManageEngineSearchUi, - canViewEngineApiLogs, - }, - } = useValues(AppLogic); - - const { - engineName, - dataLoading, - isSampleEngine, - isMetaEngine, - hasSchemaErrors, - hasSchemaConflicts, - hasUnconfirmedSchemaFields, - engine, - } = useValues(EngineLogic); - - if (dataLoading) return null; - if (!engineName) return null; - - const { invalidBoosts, unsearchedUnconfirmedFields } = engine as Required; - - return ( - <> - - - {engineName.toUpperCase()} - {isSampleEngine && ( - - {i18n.translate('xpack.enterpriseSearch.appSearch.engine.sampleEngineBadge', { - defaultMessage: 'SAMPLE ENGINE', - })} - - )} - {isMetaEngine && ( - - {i18n.translate('xpack.enterpriseSearch.appSearch.engine.metaEngineBadge', { - defaultMessage: 'META ENGINE', - })} - - )} - - - - {OVERVIEW_TITLE} - - {canViewEngineAnalytics && ( - - {ANALYTICS_TITLE} - - )} - {canViewEngineDocuments && ( - - {DOCUMENTS_TITLE} - - )} - {canViewEngineSchema && ( - - - {SCHEMA_TITLE} - - {hasSchemaErrors && ( - - )} - {hasUnconfirmedSchemaFields && ( - - )} - {hasSchemaConflicts && ( - - )} - - - - )} - {canViewEngineCrawler && !isMetaEngine && ( - - {CRAWLER_TITLE} - - )} - {canViewMetaEngineSourceEngines && isMetaEngine && ( - - {ENGINES_TITLE} - - )} - {canManageEngineRelevanceTuning && ( - - - {RELEVANCE_TUNING_TITLE} - - {invalidBoosts && ( - - )} - {unsearchedUnconfirmedFields && ( - - )} - - - - )} - {canManageEngineSynonyms && ( - - {SYNONYMS_TITLE} - - )} - {canManageEngineCurations && ( - - {CURATIONS_TITLE} - - )} - {canManageEngineResultSettings && ( - - {RESULT_SETTINGS_TITLE} - - )} - {canManageEngineSearchUi && ( - - {SEARCH_UI_TITLE} - - )} - {canViewEngineApiLogs && ( - - {API_LOGS_TITLE} - - )} - > - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/index.ts index 2a5b3351f41f7..86b4ff21e62d3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/index.ts @@ -6,6 +6,5 @@ */ export { EngineRouter } from './engine_router'; -export { EngineNav } from './engine_nav'; export { EngineLogic } from './engine_logic'; export { generateEnginePath, getEngineBreadcrumbs } from './utils'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx index 46596cc5d6765..6647b4032e4bc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx @@ -7,7 +7,6 @@ import { DEFAULT_INITIAL_APP_DATA } from '../../../common/__mocks__'; import { setMockValues } from '../__mocks__/kea_logic'; -import { mockUseRouteMatch } from '../__mocks__/react_router'; import '../__mocks__/shallow_useeffect.mock'; import '../__mocks__/enterprise_search_url.mock'; @@ -17,15 +16,13 @@ import { Redirect } from 'react-router-dom'; import { shallow, ShallowWrapper } from 'enzyme'; -import { SideNav, SideNavLink } from '../shared/layout'; - import { rerender } from '../test_helpers'; jest.mock('./app_logic', () => ({ AppLogic: jest.fn() })); import { AppLogic } from './app_logic'; import { Credentials } from './components/credentials'; -import { EngineRouter, EngineNav } from './components/engine'; +import { EngineRouter } from './components/engine'; import { EngineCreation } from './components/engine_creation'; import { EnginesOverview } from './components/engines'; import { ErrorConnecting } from './components/error_connecting'; @@ -35,7 +32,7 @@ import { RoleMappings } from './components/role_mappings'; import { Settings } from './components/settings'; import { SetupGuide } from './components/setup_guide'; -import { AppSearch, AppSearchUnconfigured, AppSearchConfigured, AppSearchNav } from './'; +import { AppSearch, AppSearchUnconfigured, AppSearchConfigured } from './'; describe('AppSearch', () => { it('always renders the Setup Guide', () => { @@ -142,51 +139,3 @@ describe('AppSearchConfigured', () => { }); }); }); - -describe('AppSearchNav', () => { - it('renders with the Engines link', () => { - const wrapper = shallow(); - - expect(wrapper.find(SideNav)).toHaveLength(1); - expect(wrapper.find(SideNavLink).prop('to')).toEqual('/engines'); - }); - - describe('engine subnavigation', () => { - const getEnginesLink = (wrapper: ShallowWrapper) => wrapper.find(SideNavLink).dive(); - - it('does not render the engine subnav on top-level routes', () => { - mockUseRouteMatch.mockReturnValueOnce(false); - const wrapper = shallow(); - - expect(getEnginesLink(wrapper).find(EngineNav)).toHaveLength(0); - }); - - it('renders the engine subnav if currently on an engine route', () => { - mockUseRouteMatch.mockReturnValueOnce(true); - const wrapper = shallow(); - - expect(getEnginesLink(wrapper).find(EngineNav)).toHaveLength(1); - }); - }); - - it('renders the Settings link', () => { - setMockValues({ myRole: { canViewSettings: true } }); - const wrapper = shallow(); - - expect(wrapper.find(SideNavLink).last().prop('to')).toEqual('/settings'); - }); - - it('renders the Credentials link', () => { - setMockValues({ myRole: { canViewAccountCredentials: true } }); - const wrapper = shallow(); - - expect(wrapper.find(SideNavLink).last().prop('to')).toEqual('/credentials'); - }); - - it('renders the Role Mappings link', () => { - setMockValues({ myRole: { canViewRoleMappings: true } }); - const wrapper = shallow(); - - expect(wrapper.find(SideNavLink).last().prop('to')).toEqual('/users_and_roles'); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx index 6d049b2015487..11f706bff028f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx @@ -6,30 +6,26 @@ */ import React, { useEffect } from 'react'; -import { Route, Redirect, Switch, useRouteMatch } from 'react-router-dom'; +import { Route, Redirect, Switch } from 'react-router-dom'; import { useValues } from 'kea'; -import { APP_SEARCH_PLUGIN } from '../../../common/constants'; import { InitialAppData } from '../../../common/types'; import { HttpLogic } from '../shared/http'; import { KibanaLogic } from '../shared/kibana'; -import { SideNav, SideNavLink } from '../shared/layout'; - -import { ROLE_MAPPINGS_TITLE } from '../shared/role_mapping/constants'; import { AppLogic } from './app_logic'; -import { Credentials, CREDENTIALS_TITLE } from './components/credentials'; -import { EngineNav, EngineRouter } from './components/engine'; +import { Credentials } from './components/credentials'; +import { EngineRouter } from './components/engine'; import { EngineCreation } from './components/engine_creation'; -import { EnginesOverview, ENGINES_TITLE } from './components/engines'; +import { EnginesOverview } from './components/engines'; import { ErrorConnecting } from './components/error_connecting'; import { KibanaHeaderActions } from './components/layout'; import { Library } from './components/library'; import { MetaEngineCreation } from './components/meta_engine_creation'; import { NotFound } from './components/not_found'; import { RoleMappings } from './components/role_mappings'; -import { Settings, SETTINGS_TITLE } from './components/settings'; +import { Settings } from './components/settings'; import { SetupGuide } from './components/setup_guide'; import { ENGINE_CREATION_PATH, @@ -137,28 +133,3 @@ export const AppSearchConfigured: React.FC> = (props) = ); }; - -export const AppSearchNav: React.FC = () => { - const { - myRole: { canViewSettings, canViewAccountCredentials, canViewRoleMappings }, - } = useValues(AppLogic); - - const isEngineRoute = !!useRouteMatch(ENGINE_PATH); - - return ( - - : null} isRoot> - {ENGINES_TITLE} - - {canViewSettings && {SETTINGS_TITLE}} - {canViewAccountCredentials && ( - {CREDENTIALS_TITLE} - )} - {canViewRoleMappings && ( - - {ROLE_MAPPINGS_TITLE} - - )} - - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts index 856d483e174a6..41f8869ad5f61 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts @@ -7,7 +7,3 @@ export { EnterpriseSearchPageTemplate, PageTemplateProps } from './page_template'; export { generateNavLink } from './nav_link_helpers'; - -// TODO: Delete these once KibanaPageTemplate migration is done -export { Layout } from './layout'; -export { SideNav, SideNavLink, SideNavItem } from './side_nav'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.scss b/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.scss deleted file mode 100644 index 88799406070cd..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.scss +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -.enterpriseSearchLayout { - $sideBarWidth: $euiSize * 15; - $sideBarMobileHeight: $euiSize * 4.75; - $consoleHeaderHeight: 98px; // NOTE: Keep an eye on this for changes - $pageHeight: calc(100vh - #{$consoleHeaderHeight}); - - display: block; - background-color: $euiColorEmptyShade; - min-height: $pageHeight; - position: relative; - left: $sideBarWidth; - width: calc(100% - #{$sideBarWidth}); - padding: 0; - - @include euiBreakpoint('xs', 's', 'm') { - left: auto; - width: 100%; - } - - &__sideBarToggle { - display: none; - - @include euiBreakpoint('xs', 's', 'm') { - display: block; - - position: absolute; - right: $euiSize; - top: $sideBarMobileHeight / 2; - transform: translateY(-50%) scale(.9); - - .euiButton { - min-width: 0; - } - } - } - - &__sideBar { - z-index: $euiZNavigation; - position: fixed; - margin-left: -1 * $sideBarWidth; - margin-right: 0; - overflow-y: auto; - overflow-x: hidden; - - height: $pageHeight; - width: $sideBarWidth; - - background-color: $euiColorLightestShade; - box-shadow: inset (-1 * $euiSizeXS) 0 $euiSizeS (-1 * $euiSizeXS) rgba($euiShadowColor, .25); - - @include euiBreakpoint('xs', 's', 'm') { - position: relative; - width: 100%; - height: $sideBarMobileHeight; - margin-left: 0; - overflow-y: hidden; - - border-bottom: $euiBorderThin; - box-shadow: none; - - &--isOpen { - height: auto; - overflow-y: auto; - } - } - } - - &__body { - padding: $euiSizeXXL; - - @include euiBreakpoint('m') { - padding: $euiSizeL; - } - @include euiBreakpoint('xs', 's') { - padding: $euiSize; - } - } - - &__readOnlyMode { - margin: -$euiSizeM 0 $euiSizeL; - - @include euiBreakpoint('m') { - margin: 0 0 $euiSizeL; - } - @include euiBreakpoint('xs', 's') { - margin: 0; - } - } -} diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.test.tsx deleted file mode 100644 index 28092f75cdede..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.test.tsx +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { shallow } from 'enzyme'; - -import { EuiPageSideBar, EuiButton, EuiPageBody, EuiCallOut } from '@elastic/eui'; - -import { Layout, INavContext } from './layout'; - -describe('Layout', () => { - it('renders', () => { - const wrapper = shallow(); - - expect(wrapper.find('.enterpriseSearchLayout')).toHaveLength(1); - expect(wrapper.find(EuiPageBody).prop('restrictWidth')).toBeFalsy(); - }); - - it('passes the restrictWidth prop', () => { - const wrapper = shallow(); - - expect(wrapper.find(EuiPageBody).prop('restrictWidth')).toEqual(true); - }); - - it('renders navigation', () => { - const wrapper = shallow(Hello World} />); - - expect(wrapper.find('.enterpriseSearchLayout__sideBar')).toHaveLength(1); - expect(wrapper.find('.nav-test')).toHaveLength(1); - }); - - it('renders navigation toggle state', () => { - const wrapper = shallow(Hello World} />); - expect(wrapper.find(EuiPageSideBar).prop('className')).not.toContain('--isOpen'); - expect(wrapper.find(EuiButton).prop('iconType')).toEqual('arrowRight'); - - const toggle = wrapper.find('[data-test-subj="enterpriseSearchNavToggle"]'); - toggle.simulate('click'); - - expect(wrapper.find(EuiPageSideBar).prop('className')).toContain('--isOpen'); - expect(wrapper.find(EuiButton).prop('iconType')).toEqual('arrowDown'); - }); - - it('passes down NavContext to navigation links', () => { - const wrapper = shallow(} />); - - const toggle = wrapper.find('[data-test-subj="enterpriseSearchNavToggle"]'); - toggle.simulate('click'); - expect(wrapper.find(EuiPageSideBar).prop('className')).toContain('--isOpen'); - - const context = (wrapper.find('ContextProvider').prop('value') as unknown) as INavContext; - context.closeNavigation(); - expect(wrapper.find(EuiPageSideBar).prop('className')).not.toContain('--isOpen'); - }); - - it('renders a read-only mode callout', () => { - const wrapper = shallow(); - - expect(wrapper.find(EuiCallOut)).toHaveLength(1); - }); - - it('renders children', () => { - const wrapper = shallow( - - Test - - ); - - expect(wrapper.find('.enterpriseSearchLayout__body')).toHaveLength(1); - expect(wrapper.find('.testing')).toHaveLength(1); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.tsx deleted file mode 100644 index 9cf5fccddbd5b..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.tsx +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useState } from 'react'; - -import classNames from 'classnames'; - -import { EuiPage, EuiPageSideBar, EuiPageBody, EuiButton, EuiCallOut } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import './layout.scss'; - -interface LayoutProps { - navigation: React.ReactNode; - restrictWidth?: boolean; - readOnlyMode?: boolean; -} - -export interface INavContext { - closeNavigation(): void; -} -export const NavContext = React.createContext({}); - -export const Layout: React.FC = ({ - children, - navigation, - restrictWidth, - readOnlyMode, -}) => { - const [isNavOpen, setIsNavOpen] = useState(false); - const toggleNavigation = () => setIsNavOpen(!isNavOpen); - const closeNavigation = () => setIsNavOpen(false); - - const navClasses = classNames('enterpriseSearchLayout__sideBar', { - 'enterpriseSearchLayout__sideBar--isOpen': isNavOpen, // eslint-disable-line @typescript-eslint/naming-convention - }); - - return ( - - - - - {i18n.translate('xpack.enterpriseSearch.nav.menu', { - defaultMessage: 'Menu', - })} - - - {navigation} - - - {readOnlyMode && ( - - )} - {children} - - - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.scss b/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.scss deleted file mode 100644 index f6a1ebed7ba93..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.scss +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -$euiSizeML: $euiSize * 1.25; // 20px - between medium and large ¯\_(ツ)_/¯ - -.enterpriseSearchProduct { - display: flex; - align-items: center; - padding: $euiSizeML; - - background-image: url('./side_nav_bg.svg'); - background-repeat: no-repeat; - - @include euiBreakpoint('xs', 's', 'm') { - padding: $euiSize $euiSizeML; - } - - &__icon { - display: flex; - align-items: center; - justify-content: center; - - width: $euiSizeXXL; - height: $euiSizeXXL; - margin-right: $euiSizeS; - - background-color: $euiColorEmptyShade; - border-radius: 50%; - @include euiSlightShadow(); - - .euiIcon { - width: $euiSizeML; - height: $euiSizeML; - } - } - - &__title { - .euiText { - font-weight: $euiFontWeightMedium; - } - } -} - -.enterpriseSearchNavLinks { - &__item { - display: block; - padding: $euiSizeM $euiSizeML; - font-size: $euiFontSizeS; - font-weight: $euiFontWeightMedium; - line-height: $euiFontSizeM; - - $activeBgColor: rgba($euiColorFullShade, .05); - - &--isActive { - background-color: $activeBgColor; - } - - &.euiLink { - color: $euiTextColor; - font-weight: $euiFontWeightMedium; - - &:hover { - color: $euiTextColor; - } - - &:focus { - outline: solid 0 $activeBgColor; - background-color: $activeBgColor; - } - } - } - - &__subNav { - padding-left: $euiSizeML; - - // Extends the click area of links more to the left, so that second tiers - // of subnavigation links still have the same hitbox as first tier links - .enterpriseSearchNavLinks__item { - margin-left: -$euiSizeML; - padding-left: $euiSizeXXL; - } - } -} diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.test.tsx deleted file mode 100644 index 244037d6e1382..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.test.tsx +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { mockLocation } from '../../__mocks__/react_router'; - -import React from 'react'; - -import { shallow } from 'enzyme'; - -import { EuiLink } from '@elastic/eui'; - -import { ENTERPRISE_SEARCH_PLUGIN, APP_SEARCH_PLUGIN } from '../../../../common/constants'; -import { EuiLinkTo } from '../react_router_helpers'; - -import { SideNav, SideNavLink, SideNavItem } from './'; - -describe('SideNav', () => { - it('renders link children', () => { - const wrapper = shallow( - - Hello World - - ); - - expect(wrapper.type()).toEqual('nav'); - expect(wrapper.find('.enterpriseSearchNavLinks')).toHaveLength(1); - expect(wrapper.find('.testing')).toHaveLength(1); - }); - - it('renders a custom product', () => { - const wrapper = shallow(); - - expect(wrapper.find('h3').text()).toEqual('App Search'); - expect(wrapper.find('.enterpriseSearchProduct--appSearch')).toHaveLength(1); - }); -}); - -describe('SideNavLink', () => { - it('renders', () => { - const wrapper = shallow(Link); - - expect(wrapper.type()).toEqual('li'); - expect(wrapper.find(EuiLinkTo)).toHaveLength(1); - expect(wrapper.find('.enterpriseSearchNavLinks__item')).toHaveLength(1); - }); - - it('renders an external link if isExternal is true', () => { - const wrapper = shallow( - - Link - - ); - const externalLink = wrapper.find(EuiLink); - - expect(externalLink).toHaveLength(1); - expect(externalLink.prop('href')).toEqual('http://website.com'); - expect(externalLink.prop('target')).toEqual('_blank'); - }); - - it('sets an active class if the current path matches the nav link', () => { - mockLocation.pathname = '/test/'; - - const wrapper = shallow(Link); - - expect(wrapper.find('.enterpriseSearchNavLinks__item--isActive')).toHaveLength(1); - }); - - it('sets an active class if the current path is / and the link isRoot', () => { - mockLocation.pathname = '/'; - - const wrapper = shallow( - - Link - - ); - - expect(wrapper.find('.enterpriseSearchNavLinks__item--isActive')).toHaveLength(1); - }); - - it('passes down custom classes and props', () => { - const wrapper = shallow( - - Link - - ); - - expect(wrapper.find('.testing')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="testing"]')).toHaveLength(1); - }); - - it('renders nested subnavigation', () => { - const subNav = ( - - Another link! - - ); - const wrapper = shallow( - - Link - - ); - - expect(wrapper.find('.enterpriseSearchNavLinks__subNav')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="subNav"]')).toHaveLength(1); - }); - - describe('shouldShowActiveForSubroutes', () => { - it("won't set an active class when route is a subroute of 'to'", () => { - mockLocation.pathname = '/documents/1234'; - - const wrapper = shallow( - - Link - - ); - - expect(wrapper.find('.enterpriseSearchNavLinks__item--isActive')).toHaveLength(0); - }); - - it('sets an active class if the current path is a subRoute of "to", and shouldShowActiveForSubroutes is true', () => { - mockLocation.pathname = '/documents/1234'; - - const wrapper = shallow( - - Link - - ); - - expect(wrapper.find('.enterpriseSearchNavLinks__item--isActive')).toHaveLength(1); - }); - }); -}); - -describe('SideNavItem', () => { - it('renders', () => { - const wrapper = shallow(Test); - - expect(wrapper.type()).toEqual('li'); - expect(wrapper.find('.enterpriseSearchNavLinks__item')).toHaveLength(1); - }); - - it('renders children', () => { - const wrapper = shallow( - - World - - ); - - expect(wrapper.find('[data-test-subj="hello"]').text()).toEqual('World'); - }); - - it('passes down custom classes and props', () => { - const wrapper = shallow( - - Test - - ); - - expect(wrapper.find('.testing')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="testing"]')).toHaveLength(1); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.tsx deleted file mode 100644 index 58a5c7bbb229f..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.tsx +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useContext } from 'react'; -import { useLocation } from 'react-router-dom'; - -import classNames from 'classnames'; - -import { EuiIcon, EuiTitle, EuiText, EuiLink } from '@elastic/eui'; // TODO: Remove EuiLink after full Kibana transition -import { i18n } from '@kbn/i18n'; - -import { ENTERPRISE_SEARCH_PLUGIN } from '../../../../common/constants'; -import { stripTrailingSlash } from '../../../../common/strip_slashes'; -import { EuiLinkTo } from '../react_router_helpers'; - -import { NavContext, INavContext } from './layout'; - -import './side_nav.scss'; - -/** - * Side navigation - product & icon + links wrapper - */ - -interface SideNavProps { - // Expects product plugin constants (@see common/constants.ts) - product: { - NAME: string; - ID: string; - }; -} - -export const SideNav: React.FC = ({ product, children }) => { - return ( - - - - - - - - {ENTERPRISE_SEARCH_PLUGIN.NAME} - - - {product.NAME} - - - - {children} - - ); -}; - -/** - * Side navigation link item - */ - -interface SideNavLinkProps { - to: string; - shouldShowActiveForSubroutes?: boolean; - isExternal?: boolean; - className?: string; - isRoot?: boolean; - subNav?: React.ReactNode; -} - -export const SideNavLink: React.FC = ({ - to, - shouldShowActiveForSubroutes = false, - isExternal, - children, - className, - isRoot, - subNav, - ...rest -}) => { - const { closeNavigation } = useContext(NavContext) as INavContext; - - const { pathname } = useLocation(); - const currentPath = stripTrailingSlash(pathname); - const isActive = - currentPath === to || - (shouldShowActiveForSubroutes && currentPath.startsWith(to)) || - (isRoot && currentPath === ''); - - const classes = classNames('enterpriseSearchNavLinks__item', className, { - 'enterpriseSearchNavLinks__item--isActive': !isExternal && isActive, // eslint-disable-line @typescript-eslint/naming-convention - }); - - return ( - - {isExternal ? ( - // eslint-disable-next-line @elastic/eui/href-or-on-click - - {children} - - ) : ( - - {children} - - )} - {subNav && {subNav}} - - ); -}; - -/** - * Side navigation non-link item - */ - -interface SideNavItemProps { - className?: string; -} - -export const SideNavItem: React.FC = ({ children, className, ...rest }) => { - const classes = classNames('enterpriseSearchNavLinks__item', className); - return ( - - {children} - - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav_bg.svg b/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav_bg.svg deleted file mode 100644 index a19227ab7b7eb..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav_bg.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/index.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/index.ts index 8cdc133681762..0cc39f66e3d20 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/index.ts @@ -6,7 +6,7 @@ */ export { WorkplaceSearchPageTemplate } from './page_template'; -export { useWorkplaceSearchNav, WorkplaceSearchNav } from './nav'; +export { useWorkplaceSearchNav } from './nav'; export { WorkplaceSearchHeaderActions } from './kibana_header_actions'; export { AccountHeader } from './account_header'; export { PersonalDashboardLayout } from './personal_dashboard_layout'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx index 04576e981e104..65a6a798b032a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx @@ -6,7 +6,6 @@ */ jest.mock('../../../shared/layout', () => ({ - ...jest.requireActual('../../../shared/layout'), generateNavLink: jest.fn(({ to, items }) => ({ href: to, items })), })); jest.mock('../../views/content_sources/components/source_sub_nav', () => ({ @@ -19,13 +18,7 @@ jest.mock('../../views/settings/components/settings_sub_nav', () => ({ useSettingsSubNav: () => [], })); -import React from 'react'; - -import { shallow } from 'enzyme'; - -import { SideNav, SideNavLink } from '../../../shared/layout'; - -import { useWorkplaceSearchNav, WorkplaceSearchNav } from './'; +import { useWorkplaceSearchNav } from './'; describe('useWorkplaceSearchNav', () => { it('returns an array of top-level Workplace Search nav items', () => { @@ -72,15 +65,3 @@ describe('useWorkplaceSearchNav', () => { ]); }); }); - -// TODO: Delete below once fully migrated to KibanaPageTemplate - -describe('WorkplaceSearchNav', () => { - it('renders', () => { - const wrapper = shallow(); - - expect(wrapper.find(SideNav)).toHaveLength(1); - expect(wrapper.find(SideNavLink).first().prop('to')).toEqual('/'); - expect(wrapper.find(SideNavLink)).toHaveLength(6); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx index c8d821dcdae2e..7dc005a56bf10 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx @@ -5,12 +5,9 @@ * 2.0. */ -import React from 'react'; +import { EuiSideNavItemType } from '@elastic/eui'; -import { EuiSideNavItemType, EuiSpacer } from '@elastic/eui'; - -import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; -import { generateNavLink, SideNav, SideNavLink } from '../../../shared/layout'; +import { generateNavLink } from '../../../shared/layout'; import { NAV } from '../../constants'; import { SOURCES_PATH, @@ -68,37 +65,3 @@ export const useWorkplaceSearchNav = () => { // to cause all our navItems to properly render as nav links. return [{ id: '', name: '', items: navItems }]; }; - -// TODO: Delete below once fully migrated to KibanaPageTemplate - -interface Props { - sourcesSubNav?: React.ReactNode; - groupsSubNav?: React.ReactNode; - settingsSubNav?: React.ReactNode; -} - -export const WorkplaceSearchNav: React.FC = ({ - sourcesSubNav, - groupsSubNav, - settingsSubNav, -}) => ( - - - {NAV.OVERVIEW} - - - {NAV.SOURCES} - - - {NAV.GROUPS} - - - {NAV.ROLE_MAPPINGS} - - {NAV.SECURITY} - - {NAV.SETTINGS} - - - -); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 5f86e020a0407..aab80fe308861 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7884,9 +7884,6 @@ "xpack.enterpriseSearch.featureCatalogueDescription2": "ユーザーを関連するデータにつなげます。", "xpack.enterpriseSearch.featureCatalogueDescription3": "チームの内容を統合します。", "xpack.enterpriseSearch.hiddenText": "非表示のテキスト", - "xpack.enterpriseSearch.nav.hierarchy": "セカンダリ", - "xpack.enterpriseSearch.nav.menu": "メニュー", - "xpack.enterpriseSearch.nav.toggleMenu": "セカンダリナビゲーションを切り替える", "xpack.enterpriseSearch.navTitle": "概要", "xpack.enterpriseSearch.notFound.action1": "ダッシュボードに戻す", "xpack.enterpriseSearch.notFound.action2": "サポートに問い合わせる", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index acad67a0b1c7a..d4f263b58b8ab 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7952,9 +7952,6 @@ "xpack.enterpriseSearch.featureCatalogueDescription2": "将您的用户连接到相关数据。", "xpack.enterpriseSearch.featureCatalogueDescription3": "统一您的团队内容。", "xpack.enterpriseSearch.hiddenText": "隐藏文本", - "xpack.enterpriseSearch.nav.hierarchy": "次级", - "xpack.enterpriseSearch.nav.menu": "菜单", - "xpack.enterpriseSearch.nav.toggleMenu": "切换次级导航", "xpack.enterpriseSearch.navTitle": "概览", "xpack.enterpriseSearch.notFound.action1": "返回到您的仪表板", "xpack.enterpriseSearch.notFound.action2": "联系支持人员",