From a37e7ee01d5331ea87cc06aa774ac1f63e9427cf Mon Sep 17 00:00:00 2001 From: Constance Date: Thu, 24 Sep 2020 14:22:11 -0700 Subject: [PATCH] [Enterprise Search] Move externalUrl helper out of React Context (#78368) * Add new/simpler externalUrl helper and initialize it on renderApp - This uses a simple JS obj to store the enterpriseSearchUrl reference (once on plugin init) - This is vs. a class, which needs to be instantiated and passed around - the new obj can be imported flatly at any time - I also opted to not convert this into a Kea logic file - after some deliberation I decided against it because it felt really weird as one. It's not storing "state" per se that ever needs to be updated, it's simply a one-time set obj that contains helper functions. - There's also some hope that we might eventually not need this helper after the full migration, so the simpler it is to delete the better - Uses a getter & setter to ensure that we don't accidentally mutate said obj after initialization * Update all components using get*SearchUrl helpers * Update tests for updated components - Mostly just consists of mocking externalUrl and importing that mock * Remove old ExternalUrl class/context TODO in next commit: Address kibana_header_actions * Update Workplace Search Header Actions to use new externalUrl helper NOTE: this requires a temporary workaround of initializing externalUrl.enterpriseSearch in plugin.ts rather than in renderApp, because renderApp loads *after* the header app does. I plan on fixing this in a future PR so that setHeaderActionMenu is called AFTER renderApp has done loading (to ensure all the state in headerActions we need is available). --- .../__mocks__/enterprise_search_url.mock.ts | 9 ++++ .../__mocks__/kibana_context.mock.ts | 3 -- .../components/empty_state.test.tsx | 1 - .../components/empty_state.tsx | 7 +--- .../components/header.test.tsx | 2 +- .../engine_overview/components/header.tsx | 7 +--- .../engine_overview/engine_table.test.tsx | 2 +- .../engine_overview/engine_table.tsx | 7 +--- .../applications/app_search/index.test.tsx | 1 + .../public/applications/app_search/index.tsx | 5 +-- .../public/applications/index.test.tsx | 2 +- .../public/applications/index.tsx | 18 +++----- .../external_url.test.ts | 42 +++++++++++++++++++ .../enterprise_search_url/external_url.ts | 37 ++++++++++++++++ .../generate_external_url.test.ts | 25 ----------- .../generate_external_url.ts | 38 ----------------- .../shared/enterprise_search_url/index.ts | 7 +++- .../layout/kibana_header_actions.test.tsx | 20 ++++----- .../layout/kibana_header_actions.tsx | 11 ++--- .../components/layout/nav.test.tsx | 3 +- .../components/layout/nav.tsx | 8 +--- .../product_button/product_button.test.tsx | 1 - .../shared/product_button/product_button.tsx | 7 +--- .../views/overview/onboarding_card.test.tsx | 2 +- .../views/overview/onboarding_card.tsx | 7 +--- .../views/overview/onboarding_steps.test.tsx | 1 - .../views/overview/onboarding_steps.tsx | 7 +--- .../views/overview/recent_activity.test.tsx | 1 - .../views/overview/recent_activity.tsx | 7 +--- .../views/overview/statistic_card.test.tsx | 2 +- .../views/overview/statistic_card.tsx | 9 +--- .../enterprise_search/public/plugin.ts | 17 ++++---- 32 files changed, 147 insertions(+), 169 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/__mocks__/enterprise_search_url.mock.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/external_url.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/external_url.ts delete mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/generate_external_url.test.ts delete mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/generate_external_url.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/enterprise_search_url.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/enterprise_search_url.mock.ts new file mode 100644 index 0000000000000..47660d0a31720 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/enterprise_search_url.mock.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { externalUrl } from '../shared/enterprise_search_url'; + +externalUrl.enterpriseSearchUrl = 'http://localhost:3002'; diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts index ea3c3923cc472..ee77b0937cd82 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ExternalUrl } from '../shared/enterprise_search_url'; - /** * A set of default Kibana context values to use across component tests. * @see enterprise_search/public/index.tsx for the KibanaContext definition/import @@ -15,5 +13,4 @@ export const mockKibanaContext = { setBreadcrumbs: jest.fn(), setDocTitle: jest.fn(), config: { host: 'http://localhost:3002' }, - externalUrl: new ExternalUrl('http://localhost:3002'), }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.test.tsx index 233db7d4c5917..53f50822cf653 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.test.tsx @@ -5,7 +5,6 @@ */ import '../../../../__mocks__/kea.mock'; -import '../../../../__mocks__/shallow_usecontext.mock'; import React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.tsx index 5ed1f0b277306..cfe88d00ce14e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.tsx @@ -4,15 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; import { useValues } from 'kea'; import { EuiPageContent, EuiEmptyPrompt, EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { sendTelemetry } from '../../../../shared/telemetry'; import { HttpLogic } from '../../../../shared/http'; +import { getAppSearchUrl } from '../../../../shared/enterprise_search_url'; import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome'; -import { KibanaContext, IKibanaContext } from '../../../../index'; import { CREATE_ENGINES_PATH } from '../../../routes'; import { EngineOverviewHeader } from './header'; @@ -21,9 +21,6 @@ import './empty_state.scss'; export const EmptyState: React.FC = () => { const { http } = useValues(HttpLogic); - const { - externalUrl: { getAppSearchUrl }, - } = useContext(KibanaContext) as IKibanaContext; const buttonProps = { href: getAppSearchUrl(CREATE_ENGINES_PATH), diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.test.tsx index 8c7dfa2b7c3d6..78ee5764be5a9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.test.tsx @@ -5,7 +5,7 @@ */ import '../../../../__mocks__/kea.mock'; -import '../../../../__mocks__/shallow_usecontext.mock'; +import '../../../../__mocks__/enterprise_search_url.mock'; import React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.tsx index dca0d45a207b4..6ebb2c5bf453d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; import { useValues } from 'kea'; import { EuiPageHeader, @@ -18,13 +18,10 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { sendTelemetry } from '../../../../shared/telemetry'; import { HttpLogic } from '../../../../shared/http'; -import { KibanaContext, IKibanaContext } from '../../../../index'; +import { getAppSearchUrl } from '../../../../shared/enterprise_search_url'; export const EngineOverviewHeader: React.FC = () => { const { http } = useValues(HttpLogic); - const { - externalUrl: { getAppSearchUrl }, - } = useContext(KibanaContext) as IKibanaContext; const buttonProps = { fill: true, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.test.tsx index 8e92f21f8ffed..c66fd24fee12a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.test.tsx @@ -5,7 +5,7 @@ */ import '../../../__mocks__/kea.mock'; -import '../../../__mocks__/shallow_usecontext.mock'; +import '../../../__mocks__/enterprise_search_url.mock'; import { mockHttpValues } from '../../../__mocks__/'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.tsx index 6888be1dc2b5b..40fb313f30b31 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; import { useValues } from 'kea'; import { EuiBasicTable, EuiBasicTableColumn, EuiLink } from '@elastic/eui'; import { FormattedMessage, FormattedDate, FormattedNumber } from '@kbn/i18n/react'; @@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n'; import { sendTelemetry } from '../../../shared/telemetry'; import { HttpLogic } from '../../../shared/http'; -import { KibanaContext, IKibanaContext } from '../../../index'; +import { getAppSearchUrl } from '../../../shared/enterprise_search_url'; import { getEngineRoute } from '../../routes'; import { ENGINES_PAGE_SIZE } from '../../../../../common/constants'; @@ -43,9 +43,6 @@ export const EngineTable: React.FC = ({ pagination: { totalEngines, pageIndex, onPaginate }, }) => { const { http } = useValues(HttpLogic); - const { - externalUrl: { getAppSearchUrl }, - } = useContext(KibanaContext) as IKibanaContext; const engineLinkProps = (name: string) => ({ href: getAppSearchUrl(getEngineRoute(name)), 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 350bc97085d7b..052f4446e4409 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 @@ -6,6 +6,7 @@ import '../__mocks__/shallow_usecontext.mock'; import '../__mocks__/kea.mock'; +import '../__mocks__/enterprise_search_url.mock'; import React, { useContext } from 'react'; import { Redirect } from 'react-router-dom'; 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 c848415daf612..410f6eb524822 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 @@ -11,6 +11,7 @@ import { useActions, useValues } from 'kea'; import { i18n } from '@kbn/i18n'; import { KibanaContext, IKibanaContext } from '../index'; +import { getAppSearchUrl } from '../shared/enterprise_search_url'; import { HttpLogic } from '../shared/http'; import { AppLogic } from './app_logic'; import { IInitialAppData } from '../../../common/types'; @@ -86,10 +87,6 @@ export const AppSearchConfigured: React.FC = (props) => { }; export const AppSearchNav: React.FC = () => { - const { - externalUrl: { getAppSearchUrl }, - } = useContext(KibanaContext) as IKibanaContext; - const { myRole: { canViewSettings, canViewAccountCredentials, canViewRoleMappings }, } = useValues(AppLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx index 6ee63ee22cae2..66772f96671e8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx @@ -54,7 +54,7 @@ describe('renderHeaderActions', () => { const mockHeaderEl = document.createElement('header'); const MockHeaderActions = () => ; - const unmount = renderHeaderActions(MockHeaderActions, mockHeaderEl, {} as any); + const unmount = renderHeaderActions(MockHeaderActions, mockHeaderEl); expect(mockHeaderEl.querySelector('.hello-world')).not.toBeNull(); unmount(); diff --git a/x-pack/plugins/enterprise_search/public/applications/index.tsx b/x-pack/plugins/enterprise_search/public/applications/index.tsx index 4a25ecf6067cc..2c6bc787923e3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.tsx @@ -18,12 +18,11 @@ import { PluginsStart, ClientConfigType, ClientData } from '../plugin'; import { mountLicensingLogic } from './shared/licensing'; import { mountHttpLogic } from './shared/http'; import { mountFlashMessagesLogic } from './shared/flash_messages'; -import { IExternalUrl } from './shared/enterprise_search_url'; +import { externalUrl } from './shared/enterprise_search_url'; import { IInitialAppData } from '../../common/types'; export interface IKibanaContext { config: { host?: string }; - externalUrl: IExternalUrl; navigateToUrl: ApplicationStart['navigateToUrl']; setBreadcrumbs(crumbs: ChromeBreadcrumb[]): void; setDocTitle(title: string): void; @@ -42,7 +41,8 @@ export const renderApp = ( { params, core, plugins }: { params: AppMountParameters; core: CoreStart; plugins: PluginsStart }, { config, data }: { config: ClientConfigType; data: ClientData } ) => { - const { externalUrl, errorConnecting, ...initialData } = data; + const { publicUrl, errorConnecting, ...initialData } = data; + externalUrl.enterpriseSearchUrl = publicUrl || config.host || ''; resetContext({ createStore: true }); const store = getContext().store as Store; @@ -64,7 +64,6 @@ export const renderApp = ( , - kibanaHeaderEl: HTMLElement, - externalUrl: IExternalUrl -) => { - ReactDOM.render(, kibanaHeaderEl); +export const renderHeaderActions = (HeaderActions: React.FC, kibanaHeaderEl: HTMLElement) => { + ReactDOM.render(, kibanaHeaderEl); return () => ReactDOM.unmountComponentAtNode(kibanaHeaderEl); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/external_url.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/external_url.test.ts new file mode 100644 index 0000000000000..55c4f465d9ed4 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/external_url.test.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { externalUrl, getEnterpriseSearchUrl, getAppSearchUrl, getWorkplaceSearchUrl } from './'; + +describe('Enterprise Search external URL helpers', () => { + describe('getter/setter tests', () => { + it('defaults to an empty string', () => { + expect(externalUrl.enterpriseSearchUrl).toEqual(''); + }); + + it('sets the internal enterpriseSearchUrl value', () => { + externalUrl.enterpriseSearchUrl = 'http://localhost:3002'; + expect(externalUrl.enterpriseSearchUrl).toEqual('http://localhost:3002'); + }); + + it('does not allow mutating enterpriseSearchUrl once set', () => { + externalUrl.enterpriseSearchUrl = 'hello world'; + expect(externalUrl.enterpriseSearchUrl).toEqual('http://localhost:3002'); + }); + }); + + describe('function helpers', () => { + it('generates a public Enterprise Search URL', () => { + expect(getEnterpriseSearchUrl()).toEqual('http://localhost:3002'); + expect(getEnterpriseSearchUrl('/login')).toEqual('http://localhost:3002/login'); + }); + + it('generates a public App Search URL', () => { + expect(getAppSearchUrl()).toEqual('http://localhost:3002/as'); + expect(getAppSearchUrl('/path')).toEqual('http://localhost:3002/as/path'); + }); + + it('generates a public Workplace Search URL', () => { + expect(getWorkplaceSearchUrl()).toEqual('http://localhost:3002/ws'); + expect(getWorkplaceSearchUrl('/path')).toEqual('http://localhost:3002/ws/path'); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/external_url.ts b/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/external_url.ts new file mode 100644 index 0000000000000..80b506f31ad61 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/external_url.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** + * NOTE: The externalUrl obj holds the reference to externalUrl, which should + * only ever be updated once on plugin init. We're using a getter and setter + * here to ensure it isn't accidentally mutated. + * + * Someday (8.x+), when our UI is entirely on Kibana and no longer on + * Enterprise Search's standalone UI, we can potentially deprecate this helper. + */ +export const externalUrl = { + _enterpriseSearchUrl: '', + get enterpriseSearchUrl() { + return this._enterpriseSearchUrl; + }, + set enterpriseSearchUrl(value) { + if (this._enterpriseSearchUrl) { + // enterpriseSearchUrl is set once on plugin init - we should not mutate it + return; + } + this._enterpriseSearchUrl = value; + }, +}; + +export const getEnterpriseSearchUrl = (path: string = ''): string => { + return externalUrl.enterpriseSearchUrl + path; +}; +export const getAppSearchUrl = (path: string = ''): string => { + return getEnterpriseSearchUrl('/as' + path); +}; +export const getWorkplaceSearchUrl = (path: string = ''): string => { + return getEnterpriseSearchUrl('/ws' + path); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/generate_external_url.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/generate_external_url.test.ts deleted file mode 100644 index 1092c88cbbc11..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/generate_external_url.test.ts +++ /dev/null @@ -1,25 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ExternalUrl } from './'; - -describe('Enterprise Search external URL helper', () => { - const externalUrl = new ExternalUrl('http://localhost:3002'); - - it('exposes a public enterpriseSearchUrl string', () => { - expect(externalUrl.enterpriseSearchUrl).toEqual('http://localhost:3002'); - }); - - it('generates a public App Search URL', () => { - expect(externalUrl.getAppSearchUrl()).toEqual('http://localhost:3002/as'); - expect(externalUrl.getAppSearchUrl('/path')).toEqual('http://localhost:3002/as/path'); - }); - - it('generates a public Workplace Search URL', () => { - expect(externalUrl.getWorkplaceSearchUrl()).toEqual('http://localhost:3002/ws'); - expect(externalUrl.getWorkplaceSearchUrl('/path')).toEqual('http://localhost:3002/ws/path'); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/generate_external_url.ts b/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/generate_external_url.ts deleted file mode 100644 index 9db48d197f3bc..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/generate_external_url.ts +++ /dev/null @@ -1,38 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -/** - * Small helper for generating external public-facing URLs - * to the legacy/standalone Enterprise Search app - */ -export interface IExternalUrl { - enterpriseSearchUrl?: string; - getAppSearchUrl(path?: string): string; - getWorkplaceSearchUrl(path?: string): string; -} - -export class ExternalUrl { - public enterpriseSearchUrl: string; - - constructor(externalUrl: string) { - this.enterpriseSearchUrl = externalUrl; - - this.getAppSearchUrl = this.getAppSearchUrl.bind(this); - this.getWorkplaceSearchUrl = this.getWorkplaceSearchUrl.bind(this); - } - - private getExternalUrl(path: string): string { - return this.enterpriseSearchUrl + path; - } - - public getAppSearchUrl(path: string = ''): string { - return this.getExternalUrl('/as' + path); - } - - public getWorkplaceSearchUrl(path: string = ''): string { - return this.getExternalUrl('/ws' + path); - } -} diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/index.ts index d2d82a43c6dd9..177d8e0535c72 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/enterprise_search_url/index.ts @@ -4,4 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -export { ExternalUrl, IExternalUrl } from './generate_external_url'; +export { + externalUrl, + getEnterpriseSearchUrl, + getAppSearchUrl, + getWorkplaceSearchUrl, +} from './external_url'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx index a006c5e3775d5..0ebd59eda5be7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx @@ -4,26 +4,26 @@ * you may not use this file except in compliance with the Elastic License. */ +import { externalUrl } from '../../../shared/enterprise_search_url'; + import React from 'react'; import { shallow } from 'enzyme'; - import { EuiButtonEmpty } from '@elastic/eui'; -import { ExternalUrl } from '../../../shared/enterprise_search_url'; import { WorkplaceSearchHeaderActions } from './'; describe('WorkplaceSearchHeaderActions', () => { - const externalUrl = new ExternalUrl('http://localhost:3002'); + it('does not render without an Enterprise Search URL set', () => { + const wrapper = shallow(); - it('renders a link to the search application', () => { - const wrapper = shallow(); - - expect(wrapper.find(EuiButtonEmpty).prop('href')).toEqual('http://localhost:3002/ws/search'); + expect(wrapper.isEmptyRender()).toBe(true); }); - it('does not render without an Enterprise Search host URL set', () => { - const wrapper = shallow(); + it('renders a link to the search application', () => { + externalUrl.enterpriseSearchUrl = 'http://localhost:3002'; - expect(wrapper.isEmptyRender()).toBe(true); + const wrapper = shallow(); + + expect(wrapper.find(EuiButtonEmpty).prop('href')).toEqual('http://localhost:3002/ws/search'); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx index fa32d598f848d..b7da5b4281aa0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx @@ -8,15 +8,10 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty } from '@elastic/eui'; -import { IExternalUrl } from '../../../shared/enterprise_search_url'; +import { externalUrl, getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; -interface IProps { - externalUrl: IExternalUrl; -} - -export const WorkplaceSearchHeaderActions: React.FC = ({ externalUrl }) => { - const { enterpriseSearchUrl, getWorkplaceSearchUrl } = externalUrl; - if (!enterpriseSearchUrl) return null; +export const WorkplaceSearchHeaderActions: React.FC = () => { + if (!externalUrl.enterpriseSearchUrl) return null; return ( 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 0e85d8467cff0..2553284744e4d 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 @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../__mocks__/shallow_usecontext.mock'; +import '../../../__mocks__/enterprise_search_url.mock'; + import React from 'react'; import { shallow } from 'enzyme'; 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 9fb627ed09791..5572716391112 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 @@ -3,13 +3,13 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiSpacer } from '@elastic/eui'; import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; -import { KibanaContext, IKibanaContext } from '../../../index'; +import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; import { SideNav, SideNavLink } from '../../../shared/layout'; import { @@ -22,10 +22,6 @@ import { } from '../../routes'; export const WorkplaceSearchNav: React.FC = () => { - const { - externalUrl: { getWorkplaceSearchUrl }, - } = useContext(KibanaContext) as IKibanaContext; - // TODO: icons return ( diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.test.tsx index c73eb05ccec16..2013b2609f33b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.test.tsx @@ -5,7 +5,6 @@ */ import '../../../../__mocks__/kea.mock'; -import '../../../../__mocks__/shallow_usecontext.mock'; import React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.tsx index a80de9fd6ac82..344b442d9a678 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/product_button/product_button.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; import { useValues } from 'kea'; import { EuiButton, EuiButtonProps, EuiLinkProps } from '@elastic/eui'; @@ -12,13 +12,10 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { sendTelemetry } from '../../../../shared/telemetry'; import { HttpLogic } from '../../../../shared/http'; -import { KibanaContext, IKibanaContext } from '../../../../index'; +import { getWorkplaceSearchUrl } from '../../../../shared/enterprise_search_url'; export const ProductButton: React.FC = () => { const { http } = useValues(HttpLogic); - const { - externalUrl: { getWorkplaceSearchUrl }, - } = useContext(KibanaContext) as IKibanaContext; const buttonProps = { fill: true, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.test.tsx index c890adb8ea043..6be033d7225a8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.test.tsx @@ -5,7 +5,7 @@ */ import '../../../__mocks__/kea.mock'; -import '../../../__mocks__/shallow_usecontext.mock'; +import '../../../__mocks__/enterprise_search_url.mock'; import React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.tsx index 79be7ef1cb158..c1070d57f2856 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_card.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; import { useValues } from 'kea'; import { @@ -21,7 +21,7 @@ import { import { sendTelemetry } from '../../../shared/telemetry'; import { HttpLogic } from '../../../shared/http'; -import { KibanaContext, IKibanaContext } from '../../../index'; +import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; interface IOnboardingCardProps { title: React.ReactNode; @@ -43,9 +43,6 @@ export const OnboardingCard: React.FC = ({ complete, }) => { const { http } = useValues(HttpLogic); - const { - externalUrl: { getWorkplaceSearchUrl }, - } = useContext(KibanaContext) as IKibanaContext; const onClick = () => sendTelemetry({ diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx index 0f3eee074caef..37b3340b96a6a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../__mocks__/shallow_usecontext.mock'; import './__mocks__/overview_logic.mock'; import { setMockValues } from './__mocks__'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx index 079d981533e01..132824833909d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { useValues } from 'kea'; @@ -24,7 +24,7 @@ import { import sharedSourcesIcon from '../../components/shared/assets/share_circle.svg'; import { sendTelemetry } from '../../../shared/telemetry'; import { HttpLogic } from '../../../shared/http'; -import { KibanaContext, IKibanaContext } from '../../../index'; +import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; import { ORG_SOURCES_PATH, USERS_PATH, ORG_SETTINGS_PATH } from '../../routes'; import { ContentSection } from '../../components/shared/content_section'; @@ -137,9 +137,6 @@ export const OnboardingSteps: React.FC = () => { export const OrgNameOnboarding: React.FC = () => { const { http } = useValues(HttpLogic); - const { - externalUrl: { getWorkplaceSearchUrl }, - } = useContext(KibanaContext) as IKibanaContext; const onClick = () => sendTelemetry({ diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.test.tsx index 31613098f9fcc..989ff800483f6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.test.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../__mocks__/shallow_usecontext.mock'; import './__mocks__/overview_logic.mock'; import { setMockValues } from './__mocks__'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.tsx index dd62e6de7c046..d1b5228123d94 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; import moment from 'moment'; import { useValues } from 'kea'; @@ -15,7 +15,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { ContentSection } from '../../components/shared/content_section'; import { sendTelemetry } from '../../../shared/telemetry'; import { HttpLogic } from '../../../shared/http'; -import { KibanaContext, IKibanaContext } from '../../../index'; +import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; import { SOURCE_DETAILS_PATH, getContentSourcePath } from '../../routes'; import { AppLogic } from '../../app_logic'; @@ -95,9 +95,6 @@ export const RecentActivityItem: React.FC = ({ sourceId, }) => { const { http } = useValues(HttpLogic); - const { - externalUrl: { getWorkplaceSearchUrl }, - } = useContext(KibanaContext) as IKibanaContext; const onClick = () => sendTelemetry({ diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.test.tsx index edf266231b39e..013b23d2a9ec0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.test.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../__mocks__/shallow_usecontext.mock'; +import '../../../__mocks__/enterprise_search_url.mock'; import React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.tsx index 3e1d285698c0c..6c4f43b1a3a22 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/statistic_card.tsx @@ -4,11 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; - +import React from 'react'; import { EuiCard, EuiFlexItem, EuiTitle, EuiTextColor } from '@elastic/eui'; -import { KibanaContext, IKibanaContext } from '../../../index'; +import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; interface IStatisticCardProps { title: string; @@ -17,10 +16,6 @@ interface IStatisticCardProps { } export const StatisticCard: React.FC = ({ title, count = 0, actionPath }) => { - const { - externalUrl: { getWorkplaceSearchUrl }, - } = useContext(KibanaContext) as IKibanaContext; - const linkProps = actionPath ? { href: getWorkplaceSearchUrl(actionPath), diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts index 0e31722cc8bf8..d870127f297b4 100644 --- a/x-pack/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/plugins/enterprise_search/public/plugin.ts @@ -23,13 +23,13 @@ import { WORKPLACE_SEARCH_PLUGIN, } from '../common/constants'; import { IInitialAppData } from '../common/types'; -import { ExternalUrl, IExternalUrl } from './applications/shared/enterprise_search_url'; +import { externalUrl } from './applications/shared/enterprise_search_url'; export interface ClientConfigType { host?: string; } export interface ClientData extends IInitialAppData { - externalUrl: IExternalUrl; + publicUrl?: string; errorConnecting?: boolean; } @@ -47,7 +47,6 @@ export class EnterpriseSearchPlugin implements Plugin { constructor(initializerContext: PluginInitializerContext) { this.config = initializerContext.config.get(); - this.data.externalUrl = new ExternalUrl(this.config.host || ''); } public setup(core: CoreSetup, plugins: PluginsSetup) { @@ -114,7 +113,7 @@ export class EnterpriseSearchPlugin implements Plugin { './applications/workplace_search/components/layout' ); params.setHeaderActionMenu((element) => - renderHeaderActions(WorkplaceSearchHeaderActions, element, this.data.externalUrl) + renderHeaderActions(WorkplaceSearchHeaderActions, element) ); return renderApp(WorkplaceSearch, kibanaDeps, pluginData); @@ -174,14 +173,14 @@ export class EnterpriseSearchPlugin implements Plugin { if (this.hasInitialized) return; // We've already made an initial call try { - const { publicUrl, ...initialData } = await http.get('/api/enterprise_search/config_data'); - this.data = { ...this.data, ...initialData }; - if (publicUrl) this.data.externalUrl = new ExternalUrl(publicUrl); - + this.data = await http.get('/api/enterprise_search/config_data'); this.hasInitialized = true; + + // TODO: This is a temporary workaround to keep the WorkplaceSearchHeaderActions working. + // We'll solve this shortly by ensuring the main app store loads before the header actions. + externalUrl.enterpriseSearchUrl = this.data.publicUrl || this.config.host; } catch { this.data.errorConnecting = true; - // The plugin will attempt to re-fetch config data on page change } } }