Skip to content

Commit

Permalink
Search synonyms empty prompt (#205723)
Browse files Browse the repository at this point in the history
## Summary

Implement empty prompt for the Synonyms page.

<img width="1044" alt="Screenshot 2025-01-07 at 13 56 09"
src="https://github.com/user-attachments/assets/d61c5251-afdb-4e34-bf18-a20ab1044800"
/>

### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: Liam Thompson <[email protected]>
Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
3 people authored Jan 8, 2025
1 parent efe44b2 commit 5323067
Show file tree
Hide file tree
Showing 11 changed files with 329 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1020,5 +1020,8 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
cases: {
legacyApiDeprecations: `${KIBANA_DOCS}breaking-changes-summary.html#breaking-201004`,
},
synonyms: {
synonymsAPIDocumentation: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/current/synonyms-apis.html`,
},
});
};
3 changes: 3 additions & 0 deletions src/platform/packages/shared/kbn-doc-links/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,9 @@ export interface DocLinks {
readonly cases: {
readonly legacyApiDeprecations: string;
};
readonly synonyms: {
readonly synonymsAPIDocumentation: string;
};
}

export type BuildFlavor = 'serverless' | 'traditional';
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 { DocLinks } from '@kbn/doc-links';

class SynonymsDocLinks {
public synonymsApi: string = '';

constructor() {}

setDocLinks(newDocLinks: DocLinks) {
this.synonymsApi = newDocLinks.synonyms.synonymsAPIDocumentation;
}
}

export const docLinks = new SynonymsDocLinks();
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import { CoreStart } from '@kbn/core/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { I18nProvider } from '@kbn/i18n-react';
import { Router } from '@kbn/shared-ux-router';
import { Route, Router, Routes } from '@kbn/shared-ux-router';
import { AppPluginStartDependencies } from './types';
import { SearchSynonymsOverview } from './components/overview/overview';

export const renderApp = async (
core: CoreStart,
Expand All @@ -24,7 +25,11 @@ export const renderApp = async (
<KibanaContextProvider services={{ ...core, ...services }}>
<I18nProvider>
<Router history={services.history}>
<div>Synonyms</div>
<Routes>
<Route path="/">
<SearchSynonymsOverview />
</Route>
</Routes>
</Router>
</I18nProvider>
</KibanaContextProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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 { EmptyPrompt } from './empty_prompt';
import { render, screen } from '@testing-library/react';
import { I18nProvider } from '@kbn/i18n-react';

jest.mock('../../../common/doc_links', () => ({
docLinks: {
synonymsApi: 'documentation-url',
},
}));
const Wrapper = ({ children }: { children?: React.ReactNode }) => (
<I18nProvider>{children}</I18nProvider>
);

describe('Synonyms Overview Empty Prompt', () => {
it('renders', () => {
render(
<Wrapper>
<EmptyPrompt />
</Wrapper>
);
expect(screen.getByTestId('searchSynonymsEmptyPromptGetStartedButton')).toBeInTheDocument();
expect(screen.getByTestId('searchSynonymsEmptyPromptFooterLink').getAttribute('href')).toBe(
'documentation-url'
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/*
* 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 {
EuiButton,
EuiFlexGrid,
EuiFlexGroup,
EuiFlexItem,
EuiHorizontalRule,
EuiIcon,
EuiLink,
EuiSpacer,
EuiSplitPanel,
EuiText,
EuiTitle,
useEuiTheme,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { css } from '@emotion/react';
import { docLinks } from '../../../common/doc_links';

export const EmptyPrompt: React.FC = () => {
const { euiTheme } = useEuiTheme();
return (
<EuiFlexGroup direction="row" gutterSize="l" alignItems="center" justifyContent="center">
<EuiFlexItem grow={false}>
<div
css={css`
max-width: calc(${euiTheme.size.base} * 50);
`}
>
<EuiSplitPanel.Outer grow={false}>
<EuiSplitPanel.Inner paddingSize="l">
<EuiSpacer size="m" />
<EuiTitle size="l">
<h2>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.title"
defaultMessage="Search with synonyms"
/>
</h2>
</EuiTitle>
<EuiSpacer size="m" />
<EuiFlexGroup direction="column" gutterSize="m">
<EuiFlexItem grow={false}>
<EuiText size="m">
<p>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.subtitle"
defaultMessage="Improve search relevance by matching terms that express the same concept."
/>
</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<div>
<EuiButton
data-test-subj="searchSynonymsEmptyPromptGetStartedButton"
color="primary"
fill
>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.getStartedButton"
defaultMessage="Get started"
/>
</EuiButton>
</div>
</EuiFlexItem>
<EuiHorizontalRule margin="m" />
<EuiFlexItem grow={false}>
<EuiFlexGrid columns={3} direction="row">
<EuiFlexItem grow={false}>
<EuiFlexGroup responsive={false} gutterSize="xs" direction="column">
<EuiFlexItem grow={false}>
<EuiFlexGroup responsive={false} gutterSize="s">
<EuiFlexItem grow={false}>
<EuiIcon type="check" />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiTitle size="xxs">
<h5>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.improveSearchRelevance.title"
defaultMessage="Expand search coverage"
/>
</h5>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<EuiText size="s" color="subdued">
<p>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.improveSearchRelevance.description"
defaultMessage="Include related terms your users actually use."
/>
</p>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<EuiFlexGroup responsive={false} gutterSize="xs" direction="column">
<EuiFlexItem grow={false}>
<EuiFlexGroup responsive={false} gutterSize="s">
<EuiFlexItem grow={false}>
<EuiIcon type="check" />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiTitle size="xxs">
<h5>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.domainSpecific.title"
defaultMessage="Match domain-specific terms"
/>
</h5>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<EuiText size="s" color="subdued">
<p>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.domainSpecific.description"
defaultMessage="Connect industry terms with common search phrases."
/>
</p>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<EuiFlexGroup responsive={false} gutterSize="xs" direction="column">
<EuiFlexItem grow={false}>
<EuiFlexGroup responsive={false} gutterSize="s">
<EuiFlexItem grow={false}>
<EuiIcon type="check" />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiTitle size="xxs">
<h5>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.improvePerformance.title"
defaultMessage="Optimize performance"
/>
</h5>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<EuiText size="s" color="subdued">
<p>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.improvedPerformance.description"
defaultMessage="Uses the built-in synonyms API for improved performance and flexibility."
/>
</p>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGrid>
</EuiFlexItem>
</EuiFlexGroup>
</EuiSplitPanel.Inner>
<EuiSplitPanel.Inner color="subdued" paddingSize="l">
<>
<EuiTitle size="xxs">
<span>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.footer"
defaultMessage="Prefer to use the APIs?"
/>
</span>
</EuiTitle>
&nbsp;
<EuiLink
data-test-subj="searchSynonymsEmptyPromptFooterLink"
href={docLinks.synonymsApi}
target="_blank"
external
>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.footerLink"
defaultMessage="Synonyms API documentation"
/>
</EuiLink>
</>
</EuiSplitPanel.Inner>
</EuiSplitPanel.Outer>
</div>
</EuiFlexItem>
</EuiFlexGroup>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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, { useMemo } from 'react';

import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
import { useKibana } from '../../hooks/use_kibana';
import { EmptyPrompt } from '../empty_prompt/empty_prompt';

export const SearchSynonymsOverview = () => {
const {
services: { console: consolePlugin, history, searchNavigation },
} = useKibana();

const embeddableConsole = useMemo(
() => (consolePlugin?.EmbeddableConsole ? <consolePlugin.EmbeddableConsole /> : null),
[consolePlugin]
);
return (
<KibanaPageTemplate
offset={0}
restrictWidth={false}
grow={false}
data-test-subj="searchSynonymsOverviewPage"
solutionNav={searchNavigation?.useClassicNavigation(history)}
>
<EmptyPrompt />
{embeddableConsole}
</KibanaPageTemplate>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* 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 { useKibana as _useKibana } from '@kbn/kibana-react-plugin/public';
import { AppServicesContext } from '../types';

export const useKibana = () => _useKibana<AppServicesContext>();
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import type { CoreSetup, Plugin, AppMountParameters } from '@kbn/core/public';
import type { CoreSetup, Plugin, AppMountParameters, CoreStart } from '@kbn/core/public';
import { PLUGIN_ID, PLUGIN_NAME, PLUGIN_TITLE } from '../common';
import {
AppPluginSetupDependencies,
Expand All @@ -14,6 +14,7 @@ import {
SearchSynonymsPluginStart,
} from './types';
import { SYNONYMS_UI_FLAG } from '../common/ui_flags';
import { docLinks } from '../common/doc_links';

export class SearchSynonymsPlugin
implements Plugin<SearchSynonymsPluginSetup, SearchSynonymsPluginStart>
Expand Down Expand Up @@ -60,7 +61,8 @@ export class SearchSynonymsPlugin
return {};
}

public start(): SearchSynonymsPluginStart {
public start(core: CoreStart): SearchSynonymsPluginStart {
docLinks.setDocLinks(core.docLinks.links);
return {};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { SearchNavigationPluginStart } from '@kbn/search-navigation/public';
import { AppMountParameters } from '@kbn/core/public';
import { AppMountParameters, CoreStart } from '@kbn/core/public';
import type { ConsolePluginStart } from '@kbn/console-plugin/public';

export * from '../common/types';
Expand All @@ -15,3 +15,5 @@ export interface AppPluginStartDependencies {
console?: ConsolePluginStart;
searchNavigation?: SearchNavigationPluginStart;
}

export type AppServicesContext = CoreStart & AppPluginStartDependencies;
Loading

0 comments on commit 5323067

Please sign in to comment.