Skip to content

Commit

Permalink
[8.x] [Synonyms UI] Search synonyms rule flyout (#208564) (#208849)
Browse files Browse the repository at this point in the history
# Backport

This will backport the following commits from `main` to `8.x`:
- [[Synonyms UI] Search synonyms rule flyout
(#208564)](#208564)

<!--- Backport version: 9.6.4 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Efe Gürkan
YALAMAN","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-01-29T21:55:52Z","message":"[Synonyms
UI] Search synonyms rule flyout (#208564)\n\n## Summary\r\n\r\nAdds
search synonym rule flyout.\r\nAdds endpoints and hooks for synonym rule
management.\r\n\r\n\r\nhttps://github.com/user-attachments/assets/e43b4a40-6452-4cfd-921f-2bde1219f219\r\n\r\n\r\n\r\n###
Checklist\r\n\r\nCheck the PR satisfies following conditions.
\r\n\r\nReviewers should verify this PR satisfies this list as
well.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\r\n-
[ ] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] The PR description includes
the appropriate Release Notes section,\r\nand the correct
`release_note:*` label is applied per
the\r\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"2cb7bea5f3e7686faa5dfbf11b8c7d270fdcdd34","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Search","backport:version","v8.18.0"],"title":"[Synonyms
UI] Search synonyms rule
flyout","number":208564,"url":"https://github.com/elastic/kibana/pull/208564","mergeCommit":{"message":"[Synonyms
UI] Search synonyms rule flyout (#208564)\n\n## Summary\r\n\r\nAdds
search synonym rule flyout.\r\nAdds endpoints and hooks for synonym rule
management.\r\n\r\n\r\nhttps://github.com/user-attachments/assets/e43b4a40-6452-4cfd-921f-2bde1219f219\r\n\r\n\r\n\r\n###
Checklist\r\n\r\nCheck the PR satisfies following conditions.
\r\n\r\nReviewers should verify this PR satisfies this list as
well.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\r\n-
[ ] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] The PR description includes
the appropriate Release Notes section,\r\nand the correct
`release_note:*` label is applied per
the\r\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"2cb7bea5f3e7686faa5dfbf11b8c7d270fdcdd34"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/208564","number":208564,"mergeCommit":{"message":"[Synonyms
UI] Search synonyms rule flyout (#208564)\n\n## Summary\r\n\r\nAdds
search synonym rule flyout.\r\nAdds endpoints and hooks for synonym rule
management.\r\n\r\n\r\nhttps://github.com/user-attachments/assets/e43b4a40-6452-4cfd-921f-2bde1219f219\r\n\r\n\r\n\r\n###
Checklist\r\n\r\nCheck the PR satisfies following conditions.
\r\n\r\nReviewers should verify this PR satisfies this list as
well.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\r\n-
[ ] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] The PR description includes
the appropriate Release Notes section,\r\nand the correct
`release_note:*` label is applied per
the\r\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"2cb7bea5f3e7686faa5dfbf11b8c7d270fdcdd34"}},{"branch":"8.x","label":"v8.18.0","branchLabelMappingKey":"^v8.18.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->
  • Loading branch information
efegurkan authored Jan 30, 2025
1 parent 2cac185 commit 7638b23
Show file tree
Hide file tree
Showing 30 changed files with 1,193 additions and 59 deletions.
1 change: 1 addition & 0 deletions config/serverless.oblt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ xpack.securitySolution.enabled: false
xpack.search.notebooks.enabled: false
xpack.searchPlayground.enabled: false
xpack.searchInferenceEndpoints.enabled: false
xpack.searchSynonyms.enabled: false

## Fine-tune the observability solution feature privileges. Also, refer to `serverless.yml` for the project-agnostic overrides.
xpack.features.overrides:
Expand Down
3 changes: 2 additions & 1 deletion config/serverless.security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ xpack.observabilityAIAssistant.enabled: false
xpack.search.notebooks.enabled: false
xpack.searchPlayground.enabled: false
xpack.searchInferenceEndpoints.enabled: false
xpack.searchSynonyms.enabled: false

## Fine-tune the security solution feature privileges. Also, refer to `serverless.yml` for the project-agnostic overrides.
xpack.features.overrides:
Expand Down Expand Up @@ -154,6 +155,6 @@ xpack.index_management.enableProjectLevelRetentionChecks: true
# Experimental Security Solution features

# These features are disabled in Serverless until fully tested
xpack.securitySolution.enableExperimental:
xpack.securitySolution.enableExperimental:
- entityStoreDisabled
- siemMigrationsDisabled
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export enum APIRoutes {
SYNONYM_SETS = '/internal/search_synonyms/synonyms',
SYNONYM_SET_ID = '/internal/search_synonyms/synonyms/{synonymsSetId}',
SYNONYM_SET_ID_RULE_ID = '/internal/search_synonyms/synonyms/{synonymsSetId}/{ruleId}',
GENERATE_SYNONYM_RULE_ID = '/internal/search_synonyms/synonyms/{synonymsSetId}/generate',
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

export const DEFAULT_PAGE_VALUE: Page = {
from: 0,
size: 10,
size: 25,
};

export interface Pagination {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('Synonyms Overview Empty Prompt', () => {
it('renders', () => {
render(
<Wrapper>
<EmptyPrompt />
<EmptyPrompt getStartedAction={() => {}} />
</Wrapper>
);
expect(screen.getByTestId('searchSynonymsEmptyPromptGetStartedButton')).toBeInTheDocument();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { css } from '@emotion/react';
import { docLinks } from '../../../common/doc_links';

export const EmptyPrompt: React.FC = () => {
interface EmptyPromptProps {
getStartedAction: () => void;
}
export const EmptyPrompt: React.FC<EmptyPromptProps> = ({ getStartedAction }) => {
const { euiTheme } = useEuiTheme();
return (
<EuiFlexGroup direction="row" gutterSize="l" alignItems="center" justifyContent="center">
Expand Down Expand Up @@ -64,6 +67,7 @@ export const EmptyPrompt: React.FC = () => {
data-test-subj="searchSynonymsEmptyPromptGetStartedButton"
color="primary"
fill
onClick={getStartedAction}
>
<FormattedMessage
id="xpack.searchSynonyms.emptyPrompt.getStartedButton"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { useMemo } from 'react';
import React, { useMemo, useState } from 'react';

import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
import {
Expand All @@ -21,12 +21,14 @@ import { useKibana } from '../../hooks/use_kibana';
import { SynonymSets } from '../synonym_sets/synonym_sets';
import { useFetchSynonymsSets } from '../../hooks/use_fetch_synonyms_sets';
import { EmptyPrompt } from '../empty_prompt/empty_prompt';
import { CreateSynonymsSetModal } from '../synonym_sets/create_new_set_modal';

export const SearchSynonymsOverview = () => {
const {
services: { console: consolePlugin, history, searchNavigation },
} = useKibana();
const { data: synonymsData, isInitialLoading } = useFetchSynonymsSets();
const [isCreateModalVisible, setIsCreateModalVisible] = useState(false);

const embeddableConsole = useMemo(
() => (consolePlugin?.EmbeddableConsole ? <consolePlugin.EmbeddableConsole /> : null),
Expand All @@ -48,15 +50,22 @@ export const SearchSynonymsOverview = () => {
rightSideItems={[
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
<EuiLink>
<EuiLink data-test-subj="searchSynonymsSearchSynonymsOverviewApiDocumentationLink">
<FormattedMessage
id="xpack.searchSynonyms.synonymsSetDetail.documentationLink"
defaultMessage="API Documentation"
/>
</EuiLink>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton fill iconType="plusInCircle">
<EuiButton
data-test-subj="searchSynonymsSearchSynonymsOverviewCreateButton"
fill
iconType="plusInCircle"
onClick={() => {
setIsCreateModalVisible(true);
}}
>
<FormattedMessage
id="xpack.searchSynonyms.synonymsSetDetail.createButton"
defaultMessage="Create"
Expand All @@ -74,13 +83,24 @@ export const SearchSynonymsOverview = () => {
</EuiText>
</KibanaPageTemplate.Header>
<KibanaPageTemplate.Section restrictWidth>
{isCreateModalVisible && (
<CreateSynonymsSetModal
onClose={() => {
setIsCreateModalVisible(false);
}}
/>
)}
{isInitialLoading && <EuiLoadingSpinner />}

{!isInitialLoading && synonymsData && synonymsData._meta.totalItemCount > 0 && (
<SynonymSets />
)}
{!isInitialLoading && synonymsData && synonymsData._meta.totalItemCount === 0 && (
<EmptyPrompt />
<EmptyPrompt
getStartedAction={() => {
setIsCreateModalVisible(true);
}}
/>
)}
</KibanaPageTemplate.Section>
{embeddableConsole}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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 {
EuiButton,
EuiButtonEmpty,
EuiFieldText,
EuiForm,
EuiFormRow,
EuiModal,
EuiModalBody,
EuiModalFooter,
EuiModalHeader,
EuiModalHeaderTitle,
useGeneratedHtmlId,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
import { formatSynonymsSetName } from '../../utils/synonyms_utils';
import { usePutSynonymsSet } from '../../hooks/use_put_synonyms_set';

interface CreateSynonymsSetModalProps {
onClose: () => void;
}
export const CreateSynonymsSetModal = ({ onClose }: CreateSynonymsSetModalProps) => {
const titleId = useGeneratedHtmlId({ prefix: 'createSynonymsSetModalTitle' });
const formId = useGeneratedHtmlId({ prefix: 'createSynonymsSetModalForm' });

const [name, setName] = useState('');
const [rawName, setRawName] = useState('');
const { mutate: createSynonymsSet } = usePutSynonymsSet(() => {
onClose();
});
return (
<EuiModal onClose={onClose}>
<EuiModalHeader>
<EuiModalHeaderTitle id={titleId}>
<FormattedMessage
id="xpack.searchSynonyms.createSynonymsSetModal.title"
defaultMessage="Name your synonyms set"
/>
</EuiModalHeaderTitle>
</EuiModalHeader>

<EuiModalBody>
<EuiForm
id={formId}
component="form"
onSubmit={(e) => {
e.preventDefault();
createSynonymsSet({ synonymsSetId: name });
}}
>
<EuiFormRow
label={i18n.translate('xpack.searchSynonyms.createSynonymsSetModal.nameLabel', {
defaultMessage: 'Name',
})}
helpText={
!!rawName
? i18n.translate('xpack.searchSynonyms.createSynonymsSetModal.nameHelpText', {
defaultMessage: 'Your synonyms set will be named: {name}',
values: { name },
})
: undefined
}
>
<EuiFieldText
data-test-subj="searchSynonymsCreateSynonymsSetModalFieldText"
value={rawName}
onChange={(e) => {
setRawName(e.target.value);
setName(formatSynonymsSetName(e.target.value));
}}
/>
</EuiFormRow>
</EuiForm>
</EuiModalBody>

<EuiModalFooter>
<EuiButtonEmpty
data-test-subj="searchSynonymsCreateSynonymsSetModalCancelButton"
onClick={onClose}
>
<FormattedMessage
id="xpack.searchSynonyms.createSynonymsSetModal.cancelButton"
defaultMessage="Cancel"
/>
</EuiButtonEmpty>
<EuiButton
data-test-subj="searchSynonymsCreateSynonymsSetModalCreateButton"
form={formId}
fill
disabled={!name}
onClick={() => {
createSynonymsSet({ synonymsSetId: name });
}}
>
<FormattedMessage
id="xpack.searchSynonyms.createSynonymsSetModal.createButton"
defaultMessage="Create"
/>
</EuiButton>
</EuiModalFooter>
</EuiModal>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,33 @@
* 2.0.
*/

import React, { useState } from 'react';

import { SynonymsGetSynonymsSetsSynonymsSetItem } from '@elastic/elasticsearch/lib/api/types';
import { EuiBasicTable, EuiBasicTableColumn, EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useState } from 'react';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { useKibana } from '../../hooks/use_kibana';
import { PLUGIN_ROUTE_ROOT } from '../../../common/api_routes';
import { DEFAULT_PAGE_VALUE, paginationToPage } from '../../../common/pagination';
import { useFetchSynonymsSets } from '../../hooks/use_fetch_synonyms_sets';
import { DeleteSynonymsSetModal } from './delete_synonyms_set_modal';

export const SynonymSets = () => {
const {
services: { application },
services: { application, http },
} = useKibana();
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(DEFAULT_PAGE_VALUE.size);
const { from } = paginationToPage({ pageIndex, pageSize, totalItemCount: 0 });
const { data: synonyms } = useFetchSynonymsSets({ from, size: pageSize });
const [synonymsSetToDelete, setSynonymsSetToDelete] = React.useState<string | null>(null);
const [synonymsSetToDelete, setSynonymsSetToDelete] = useState<string | null>(null);

if (!synonyms) {
return null;
}

const pagination = {
initialPageSize: 10,
initialPageSize: 25,
pageSizeOptions: [10, 25, 50],
...synonyms._meta,
pageSize,
Expand All @@ -44,7 +45,12 @@ export const SynonymSets = () => {
}),
render: (name: string) => (
<div data-test-subj="synonyms-set-item-name">
<EuiLink onClick={() => application?.navigateToUrl(`${PLUGIN_ROUTE_ROOT}/sets/${name}`)}>
<EuiLink
data-test-subj="searchSynonymsColumnsLink"
onClick={() =>
application.navigateToUrl(http.basePath.prepend(`${PLUGIN_ROUTE_ROOT}/sets/${name}`))
}
>
{name}
</EuiLink>
</div>
Expand Down Expand Up @@ -90,7 +96,9 @@ export const SynonymSets = () => {
color: 'text',
type: 'icon',
onClick: (synonymsSet: SynonymsGetSynonymsSetsSynonymsSetItem) =>
application?.navigateToUrl(`${PLUGIN_ROUTE_ROOT}/sets/${synonymsSet.synonyms_set}`),
application.navigateToUrl(
http.basePath.prepend(`${PLUGIN_ROUTE_ROOT}/sets/${synonymsSet.synonyms_set}`)
),
},
],
},
Expand Down
Loading

0 comments on commit 7638b23

Please sign in to comment.