diff --git a/src/plugins/saved_objects_finder/public/finder/saved_object_finder.test.tsx b/src/plugins/saved_objects_finder/public/finder/saved_object_finder.test.tsx
index 7e560906b8ae9..1c8ed33853c87 100644
--- a/src/plugins/saved_objects_finder/public/finder/saved_object_finder.test.tsx
+++ b/src/plugins/saved_objects_finder/public/finder/saved_object_finder.test.tsx
@@ -10,7 +10,14 @@ const nextTick = () => new Promise((res) => process.nextTick(res));
import lodash from 'lodash';
jest.spyOn(lodash, 'debounce').mockImplementation((fn: any) => fn);
-import { EuiInMemoryTable, EuiLink, EuiSearchBarProps, Query } from '@elastic/eui';
+import {
+ EuiInMemoryTable,
+ EuiLink,
+ EuiSearchBarProps,
+ EuiText,
+ EuiButton,
+ Query,
+} from '@elastic/eui';
import { IconType } from '@elastic/eui';
import { mount, shallow } from 'enzyme';
import React from 'react';
@@ -133,63 +140,130 @@ describe('SavedObjectsFinder', () => {
});
});
- it('should list initial items', async () => {
- const core = coreMock.createStart();
- (core.http.get as any as jest.SpyInstance).mockImplementation(() =>
- Promise.resolve({ saved_objects: [doc] })
- );
- core.uiSettings.get.mockImplementation(() => 10);
+ describe('render', () => {
+ it('lists initial items', async () => {
+ const core = coreMock.createStart();
+ (core.http.get as any as jest.SpyInstance).mockImplementation(() =>
+ Promise.resolve({ saved_objects: [doc] })
+ );
+ core.uiSettings.get.mockImplementation(() => 10);
- const wrapper = shallow(
-
- );
+ const wrapper = shallow(
+
+ );
- wrapper.instance().componentDidMount!();
- await nextTick();
- expect(
- wrapper
- .find(EuiInMemoryTable)
- .prop('items')
- .map((item: any) => item.attributes)
- ).toEqual([doc.attributes]);
- });
+ wrapper.instance().componentDidMount!();
+ await nextTick();
+ expect(
+ wrapper
+ .find(EuiInMemoryTable)
+ .prop('items')
+ .map((item: any) => item.attributes)
+ ).toEqual([doc.attributes]);
+ });
- it('should call onChoose on item click', async () => {
- const chooseStub = sinon.stub();
- const core = coreMock.createStart();
- (core.http.get as any as jest.SpyInstance).mockImplementation(() =>
- Promise.resolve({ saved_objects: [doc] })
- );
- core.uiSettings.get.mockImplementation(() => 10);
+ it('calls onChoose on item click', async () => {
+ const chooseStub = sinon.stub();
+ const core = coreMock.createStart();
+ (core.http.get as any as jest.SpyInstance).mockImplementation(() =>
+ Promise.resolve({ saved_objects: [doc] })
+ );
+ core.uiSettings.get.mockImplementation(() => 10);
- const wrapper = mount(
-
- );
+ const wrapper = mount(
+
+ );
- wrapper.instance().componentDidMount!();
- await nextTick();
- wrapper.update();
- findTestSubject(wrapper, 'savedObjectTitleExample-title').simulate('click');
- expect(chooseStub.calledWith('1', 'search', `${doc.attributes.title} (Search)`, doc)).toEqual(
- true
- );
+ wrapper.instance().componentDidMount!();
+ await nextTick();
+ wrapper.update();
+ findTestSubject(wrapper, 'savedObjectTitleExample-title').simulate('click');
+ expect(chooseStub.calledWith('1', 'search', `${doc.attributes.title} (Search)`, doc)).toEqual(
+ true
+ );
+ });
+
+ it('with help text', async () => {
+ const core = coreMock.createStart();
+ (core.http.get as any as jest.SpyInstance).mockImplementation(() =>
+ Promise.resolve({ saved_objects: [doc] })
+ );
+ core.uiSettings.get.mockImplementation(() => 10);
+
+ const wrapper = shallow(
+
+ );
+
+ wrapper.instance().componentDidMount!();
+ await nextTick();
+ expect(wrapper.find(EuiText).childAt(0).text()).toEqual(
+ 'This is some description about the action'
+ );
+ });
+
+ it('with left button', async () => {
+ const core = coreMock.createStart();
+ (core.http.get as any as jest.SpyInstance).mockImplementation(() =>
+ Promise.resolve({ saved_objects: [doc] })
+ );
+ core.uiSettings.get.mockImplementation(() => 10);
+ const button = Hello;
+ const wrapper = shallow(
+
+ );
+
+ wrapper.instance().componentDidMount!();
+ await nextTick();
+ const searchBar = wrapper.find(EuiInMemoryTable).prop('search') as EuiSearchBarProps;
+ const toolsLeft = searchBar!.toolsLeft;
+ expect(toolsLeft).toMatchInlineSnapshot(
+ `
+
+
+ Hello
+
+
+ `
+ );
+ });
});
describe('sorting', () => {
diff --git a/src/plugins/saved_objects_finder/public/finder/saved_object_finder.tsx b/src/plugins/saved_objects_finder/public/finder/saved_object_finder.tsx
index 2db81716876c9..56f8b203f694c 100644
--- a/src/plugins/saved_objects_finder/public/finder/saved_object_finder.tsx
+++ b/src/plugins/saved_objects_finder/public/finder/saved_object_finder.tsx
@@ -8,7 +8,7 @@
import { debounce } from 'lodash';
import PropTypes from 'prop-types';
-import React from 'react';
+import React, { ReactElement, ReactNode } from 'react';
import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import {
@@ -22,6 +22,9 @@ import {
SearchFilterConfig,
Query,
PropertySort,
+ EuiFlexItem,
+ EuiFlexGroup,
+ EuiText,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
@@ -69,9 +72,11 @@ interface BaseSavedObjectFinder {
name: string,
savedObject: SavedObjectCommon
) => void;
- noItemsMessage?: React.ReactNode;
+ noItemsMessage?: ReactNode;
savedObjectMetaData: Array>;
showFilter?: boolean;
+ leftChildren?: ReactElement | ReactElement[];
+ helpText?: string;
}
interface SavedObjectFinderFixedPage extends BaseSavedObjectFinder {
@@ -355,23 +360,35 @@ export class SavedObjectFinderUi extends React.Component<
]
: undefined,
toolsRight: this.props.children ? <>{this.props.children}> : undefined,
+ toolsLeft: this.props.leftChildren ? <>{this.props.leftChildren}> : undefined,
};
return (
- {
- this.setState({ sort });
- }}
- />
+
+ {this.props.helpText ? (
+
+
+ {this.props.helpText}
+
+
+ ) : undefined}
+
+ {
+ this.setState({ sort });
+ }}
+ />
+
+
);
}
}
diff --git a/x-pack/plugins/cases/kibana.jsonc b/x-pack/plugins/cases/kibana.jsonc
index afed1cd7631f8..a37320379b76d 100644
--- a/x-pack/plugins/cases/kibana.jsonc
+++ b/x-pack/plugins/cases/kibana.jsonc
@@ -27,6 +27,8 @@
"notifications",
"ruleRegistry",
"files",
+ "savedObjectsFinder",
+ "savedObjectsManagement"
],
"optionalPlugins": [
"home",
@@ -34,9 +36,7 @@
"usageCollection",
"spaces"
],
- "requiredBundles": [
- "savedObjects"
- ],
+ "requiredBundles": [],
"extraPublicDirs": [
"common"
]
diff --git a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx
index ae88e17637627..996d3d757186d 100644
--- a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx
+++ b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx
@@ -14,7 +14,6 @@ import {
EuiModalHeaderTitle,
EuiMarkdownContext,
EuiModalFooter,
- EuiButtonEmpty,
EuiButton,
EuiFlexItem,
EuiFlexGroup,
@@ -28,7 +27,7 @@ import styled from 'styled-components';
import type { TypedLensByValueInput } from '@kbn/lens-plugin/public';
import type { EmbeddablePackageState } from '@kbn/embeddable-plugin/public';
-import { SavedObjectFinderUi } from '@kbn/saved-objects-plugin/public';
+import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
import { useKibana } from '../../../../common/lib/kibana';
import { DRAFT_COMMENT_STORAGE_ID, ID } from './constants';
import { CommentEditorContext } from '../../context';
@@ -74,6 +73,7 @@ const LensEditorComponent: LensEuiMarkdownEditorUiPlugin['editor'] = ({
storage,
http,
uiSettings,
+ savedObjectsManagement,
data: {
query: {
timefilter: { timefilter },
@@ -85,7 +85,6 @@ const LensEditorComponent: LensEuiMarkdownEditorUiPlugin['editor'] = ({
const commentEditorContext = useContext(CommentEditorContext);
const markdownContext = useContext(EuiMarkdownContext);
const isMainApplication = useIsMainApplication();
-
const handleClose = useCallback(() => {
if (currentAppId) {
embeddable?.getStateTransfer().getIncomingEmbeddablePackage(currentAppId, true);
@@ -225,45 +224,6 @@ const LensEditorComponent: LensEuiMarkdownEditorUiPlugin['editor'] = ({
[]
);
- const euiFieldSearchProps = useMemo(
- () => ({
- prepend: i18n.translate(
- 'xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputPrependLabel',
- {
- defaultMessage: 'Template',
- }
- ),
- }),
- []
- );
-
- const euiFormRowProps = useMemo(
- () => ({
- label: i18n.translate(
- 'xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputLabel',
- {
- defaultMessage: 'Select lens',
- }
- ),
- labelAppend: (
-
-
-
- ),
- helpText: i18n.translate(
- 'xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputHelpText',
- {
- defaultMessage:
- 'Insert lens from existing templates or creating a new one. You will only create lens for this comment and won’t change Visualize Library.',
- }
- ),
- }),
- [handleCreateInLensClick]
- );
-
useEffect(() => {
if (node?.attributes && currentAppId) {
handleEditInLensClick(node.attributes, node.timeRange);
@@ -318,6 +278,15 @@ const LensEditorComponent: LensEuiMarkdownEditorUiPlugin['editor'] = ({
}
}, [embeddable, storage, timefilter, currentAppId, handleAdd, handleUpdate, draftComment]);
+ const createLensButton = (
+
+
+
+ );
+
return (
@@ -349,7 +318,7 @@ const LensEditorComponent: LensEuiMarkdownEditorUiPlugin['editor'] = ({
-
diff --git a/x-pack/plugins/cases/public/types.ts b/x-pack/plugins/cases/public/types.ts
index f430b99ae17f2..a72f9e5449a95 100644
--- a/x-pack/plugins/cases/public/types.ts
+++ b/x-pack/plugins/cases/public/types.ts
@@ -23,6 +23,7 @@ import type { DistributiveOmit } from '@elastic/eui';
import type { ApmBase } from '@elastic/apm-rum';
import type { LicensingPluginStart } from '@kbn/licensing-plugin/public';
import type { FilesSetup, FilesStart } from '@kbn/files-plugin/public';
+import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import type {
CasesByAlertId,
CasesByAlertIDRequest,
@@ -69,6 +70,7 @@ export interface CasesPluginStart {
security: SecurityPluginStart;
spaces?: SpacesPluginStart;
apm?: ApmBase;
+ savedObjectsManagement: SavedObjectsManagementPluginStart;
}
/**
diff --git a/x-pack/plugins/cases/tsconfig.json b/x-pack/plugins/cases/tsconfig.json
index 5ba7e85918975..7c703b9819300 100644
--- a/x-pack/plugins/cases/tsconfig.json
+++ b/x-pack/plugins/cases/tsconfig.json
@@ -25,7 +25,6 @@
"@kbn/es-ui-shared-plugin",
"@kbn/kibana-react-plugin",
"@kbn/kibana-utils-plugin",
- "@kbn/saved-objects-plugin",
"@kbn/i18n",
"@kbn/utility-types",
"@kbn/securitysolution-io-ts-utils",
@@ -58,6 +57,8 @@
"@kbn/shared-ux-router",
"@kbn/files-plugin",
"@kbn/shared-ux-file-types",
+ "@kbn/saved-objects-finder-plugin",
+ "@kbn/saved-objects-management-plugin",
],
"exclude": [
"target/**/*",
diff --git a/x-pack/plugins/security_solution/kibana.jsonc b/x-pack/plugins/security_solution/kibana.jsonc
index 85418bdeb31b7..9401b69d11657 100644
--- a/x-pack/plugins/security_solution/kibana.jsonc
+++ b/x-pack/plugins/security_solution/kibana.jsonc
@@ -40,7 +40,8 @@
"unifiedSearch",
"files",
"controls",
- "dataViews"
+ "dataViews",
+ "savedObjectsManagement",
],
"optionalPlugins": [
"cloudExperiments",
diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx
index 634e488bf14ce..17ba2940e94d9 100644
--- a/x-pack/plugins/security_solution/public/plugin.tsx
+++ b/x-pack/plugins/security_solution/public/plugin.tsx
@@ -167,6 +167,7 @@ export class Plugin implements IPlugin SecuritySolutionTemplateWrapper,
},
+ savedObjectsManagement: startPluginsDeps.savedObjectsManagement,
telemetry: this.telemetry.start(),
};
return services;
diff --git a/x-pack/plugins/security_solution/public/types.ts b/x-pack/plugins/security_solution/public/types.ts
index 9ee21755d61ad..2c7aa6340a5cf 100644
--- a/x-pack/plugins/security_solution/public/types.ts
+++ b/x-pack/plugins/security_solution/public/types.ts
@@ -44,6 +44,7 @@ import type { ThreatIntelligencePluginStart } from '@kbn/threat-intelligence-plu
import type { CloudExperimentsPluginStart } from '@kbn/cloud-experiments-plugin/common';
import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public';
import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public';
+import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import type { ResolverPluginSetup } from './resolver/types';
import type { Inspect } from '../common/search_strategy';
import type { Detections } from './detections';
@@ -101,6 +102,7 @@ export interface StartPlugins {
}
export interface StartPluginsDependencies extends StartPlugins {
+ savedObjectsManagement: SavedObjectsManagementPluginStart;
savedObjectsTaggingOss: SavedObjectTaggingOssPluginStart;
}
@@ -119,6 +121,7 @@ export type StartServices = CoreStart &
securityLayout: {
getPluginWrapper: () => typeof SecuritySolutionTemplateWrapper;
};
+ savedObjectsManagement: SavedObjectsManagementPluginStart;
telemetry: TelemetryClientStart;
};
diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json
index 346b2bf3289cf..02bef283becca 100644
--- a/x-pack/plugins/security_solution/tsconfig.json
+++ b/x-pack/plugins/security_solution/tsconfig.json
@@ -147,6 +147,7 @@
"@kbn/alerts-as-data-utils",
"@kbn/expandable-flyout",
"@kbn/securitysolution-grouping",
+ "@kbn/saved-objects-management-plugin",
"@kbn/core-analytics-server",
"@kbn/analytics-client",
"@kbn/security-solution-side-nav",
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index 20fc7bd776ea8..7cfe353fa7d70 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -9641,8 +9641,6 @@
"xpack.cases.markdownEditor.plugins.lens.insertLensSavedObjectModal.searchSelection.savedObjectType.lens": "Lens",
"xpack.cases.markdownEditor.plugins.lens.openVisualizationButtonLabel": "Visualisation ouverte",
"xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputHelpText": "Insérez un Lens à partir de modèles existants ou en créant un nouveau modèle. Vous créerez un Lens uniquement pour ce commentaire et ne changerez pas la Bibliothèque Visualize.",
- "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputLabel": "Sélectionner un Lens",
- "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputPrependLabel": "Modèle",
"xpack.cases.markdownEditor.plugins.lens.visualizationButtonLabel": "Visualisation",
"xpack.cases.markdownEditor.plugins.timeline.noParenthesesErrorMsg": "Parenthèses gauches attendues",
"xpack.cases.markdownEditor.preview": "Aperçu",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 9e5e7bf984ed3..bcec1b92c60c8 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -9630,8 +9630,6 @@
"xpack.cases.markdownEditor.plugins.lens.insertLensSavedObjectModal.searchSelection.savedObjectType.lens": "レンズ",
"xpack.cases.markdownEditor.plugins.lens.openVisualizationButtonLabel": "ビジュアライゼーションを開く",
"xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputHelpText": "既存のテンプレートからLensを挿入するか、新しく作成します。このコメントでのみLensが作成されます。Visualize Libraryは変更されません。",
- "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputLabel": "Lensを選択",
- "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputPrependLabel": "テンプレート",
"xpack.cases.markdownEditor.plugins.lens.visualizationButtonLabel": "ビジュアライゼーション",
"xpack.cases.markdownEditor.plugins.timeline.noParenthesesErrorMsg": "想定される左括弧",
"xpack.cases.markdownEditor.preview": "プレビュー",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index e12dddbfe5468..87416dd48c7ab 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -9645,8 +9645,6 @@
"xpack.cases.markdownEditor.plugins.lens.insertLensSavedObjectModal.searchSelection.savedObjectType.lens": "Lens",
"xpack.cases.markdownEditor.plugins.lens.openVisualizationButtonLabel": "打开可视化",
"xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputHelpText": "通过现有模板或创建新模板来插入 Lens。您将仅为此注释创建 Lens,并且不会更改可视化库。",
- "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputLabel": "选择 Lens",
- "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputPrependLabel": "模板",
"xpack.cases.markdownEditor.plugins.lens.visualizationButtonLabel": "可视化",
"xpack.cases.markdownEditor.plugins.timeline.noParenthesesErrorMsg": "应为左括号",
"xpack.cases.markdownEditor.preview": "预览",