Make SavedObjectFinder backward compatible (#162904)

## Summary

close https://github.com/elastic/kibana/issues/161545
close https://github.com/elastic/kibana/issues/153257

This PR makes `SavedObjectFinder` component backward compatible. It is
achieved by going through content- management layer, more technical
details
[here](https://docs.google.com/document/d/1ssYmqSEUPrsuCR4iz8DohkEWekoYrm2yL4QR_fVxXLg/edit)

### Testing

`SavedObjectFinder` is this component that allows to pick a saved object
(supports: `search` `index-pattern` `map` `visualization` `lens`
`event-annotation-group`:

![Screenshot 2023-08-07 at 16 53
32](5c283ea5-3682-4dc8-a8ff-422e6f4f3195)


It is used in the following places: 

- Dashboard 
  - Add panel
  - Replace panel 
- Discover - Open Search 
- Visualization - Select search as a source for new viz
- Graph - select source
- Cases - markdown editor add lens 
- ML (3 places) 
- Canvas - select embeddable panel 
- Transform 
- Lens > select event annotation 




### Risks / Follow up 

The `SavedObjectFinder` should stay mostly the same, the only notable
functional change is that now `SavedObjectFinder` doesn't support
`includeFields` which allowed partial saved object returns, this was
done to make the call backward-compatible without making the system even
more complicated as otherwise we'll need a way to abstract
`includeFields` from so attributes and allow to run migrations on it
before making a search. follow up issue to bring it back
https://github.com/elastic/kibana/issues/163043

The risk with that is that some client that have a lot of large objects
might run into performance issues when using `SavedObjectFinder`. This
can be mitigated by changing listing limit in advanced setting from
default 1000 to something lower
This commit is contained in:
Anton Dosov 2023-08-08 13:10:29 +02:00 committed by GitHub
parent 863ea15bde
commit 304cb256cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
98 changed files with 636 additions and 938 deletions

View file

@ -12,6 +12,7 @@
"developerExamples",
"kibanaReact",
"savedObjectsTaggingOss"
]
],
"requiredBundles": ["savedObjectsFinder"]
}
}

View file

@ -0,0 +1,70 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React from 'react';
import { ContentClientProvider, type ContentClient } from '@kbn/content-management-plugin/public';
import type { CoreStart } from '@kbn/core/public';
import { I18nProvider } from '@kbn/i18n-react';
import { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public';
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
export const FinderApp = (props: {
contentClient: ContentClient;
core: CoreStart;
savedObjectsTagging: SavedObjectTaggingOssPluginStart;
}) => {
return (
<ContentClientProvider contentClient={props.contentClient}>
<I18nProvider>
<SavedObjectFinder
showFilter={true}
services={{
savedObjectsTagging: props.savedObjectsTagging.getTaggingApi(),
contentClient: props.contentClient,
uiSettings: props.core.uiSettings,
}}
onChoose={(...args) => {
alert(JSON.stringify(args));
}}
savedObjectMetaData={[
{
type: `search`,
getIconForSavedObject: () => 'discoverApp',
name: 'Saved search',
},
{
type: 'index-pattern',
getIconForSavedObject: () => 'indexPatternApp',
name: 'Data view',
},
{
type: `visualization`,
getIconForSavedObject: () => 'visualizeApp',
name: 'Visualization',
},
{
type: 'lens',
getIconForSavedObject: () => 'lensApp',
name: 'Lens',
},
{
type: 'map',
getIconForSavedObject: () => 'logoMaps',
name: 'Map',
},
{
type: 'event-annotation-group',
getIconForSavedObject: () => 'annotation',
name: 'Annotation',
},
]}
/>
</I18nProvider>
</ContentClientProvider>
);
};

View file

@ -6,7 +6,4 @@
* Side Public License, v 1.
*/
export const registerRoutesMock = jest.fn();
jest.doMock('./routes', () => ({
registerRoutes: registerRoutesMock,
}));
export { FinderApp } from './finder_app';

View file

@ -16,6 +16,7 @@ import { AppMountParameters, CoreStart } from '@kbn/core/public';
import { StartDeps } from '../types';
import { TodoApp } from './todos';
import { MSearchApp } from './msearch';
import { FinderApp } from './finder';
export const renderApp = (
core: CoreStart,
@ -45,6 +46,12 @@ export const renderApp = (
'data-test-subj': 'msearchExample',
href: '/app/contentManagementExamples/msearch',
},
{
id: 'finder',
name: 'Finder',
'data-test-subj': 'finderExample',
href: '/app/contentManagementExamples/finder',
},
],
},
]}
@ -64,6 +71,13 @@ export const renderApp = (
savedObjectsTagging={savedObjectsTaggingOss}
/>
</Route>
<Route path="/finder">
<FinderApp
contentClient={contentManagement.client}
core={core}
savedObjectsTagging={savedObjectsTaggingOss}
/>
</Route>
</Routes>
</EuiPageTemplate.Section>
</EuiPageTemplate>

View file

@ -26,14 +26,20 @@ export const MSearchTable = () => {
const { hits, pagination } = await contentClient.mSearch<UserContentCommonSchema>({
query: {
text: searchQuery,
limit: LISTING_LIMIT,
cursor: '1',
tags: {
included: refs?.references?.map((ref) => ref.id),
excluded: refs?.referencesToExclude?.map((ref) => ref.id),
},
},
contentTypes: [{ contentTypeId: 'map' }], // TODO: improve types to not require objects here?
contentTypes: [
{ contentTypeId: 'map' },
{ contentTypeId: 'dashboard' },
{ contentTypeId: 'visualization' },
{ contentTypeId: 'lens' },
{ contentTypeId: 'search' },
{ contentTypeId: 'index-pattern' },
{ contentTypeId: 'event-annotation-group' },
], // TODO: improve types to not require objects here?
});
// TODO: needs to have logic of extracting common schema from an unknown mSearch hit: hits.map(hit => cm.convertToCommonSchema(hit))

View file

@ -29,5 +29,6 @@
"@kbn/content-management-table-list-view-table",
"@kbn/content-management-table-list-view",
"@kbn/shared-ux-router",
"@kbn/saved-objects-finder-plugin",
]
}

View file

@ -135,6 +135,7 @@ export interface SOContentStorageConstrutorParams<Types extends CMCrudTypes> {
updateArgsToSoUpdateOptions?: UpdateArgsToSoUpdateOptions<Types>;
searchArgsToSOFindOptions?: SearchArgsToSOFindOptions<Types>;
enableMSearch?: boolean;
mSearchAdditionalSearchFields?: string[];
}
export abstract class SOContentStorage<Types extends CMCrudTypes>
@ -153,6 +154,7 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
searchArgsToSOFindOptions,
enableMSearch,
allowedSavedObjectAttributes,
mSearchAdditionalSearchFields,
}: SOContentStorageConstrutorParams<Types>) {
this.savedObjectType = savedObjectType;
this.cmServicesDefinition = cmServicesDefinition;
@ -166,6 +168,7 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
if (enableMSearch) {
this.mSearch = {
savedObjectType: this.savedObjectType,
additionalSearchFields: mSearchAdditionalSearchFields,
toItemResult: (ctx: StorageContext, savedObject: SavedObjectsFindResult): Types['Item'] => {
const transforms = ctx.utils.getTransforms(this.cmServicesDefinition);
@ -201,6 +204,7 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
mSearch?: {
savedObjectType: string;
toItemResult: (ctx: StorageContext, savedObject: SavedObjectsFindResult) => Types['Item'];
additionalSearchFields?: string[];
};
async get(ctx: StorageContext, id: string): Promise<Types['GetOut']> {

View file

@ -8,12 +8,10 @@
import React, { useEffect, useState } from 'react';
import { i18n } from '@kbn/i18n';
import type { CoreStart } from '@kbn/core/public';
import { FormattedMessage } from '@kbn/i18n-react';
import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
import type { SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import type { ContentClient } from '@kbn/content-management-plugin/public';
import {
EuiButton,
EuiEmptyPrompt,
@ -24,26 +22,25 @@ import {
} from '@elastic/eui';
import { css } from '@emotion/react';
import { EVENT_ANNOTATION_GROUP_TYPE } from '@kbn/event-annotation-common';
import { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
export const EventAnnotationGroupSavedObjectFinder = ({
uiSettings,
http,
savedObjectsManagement,
fixedPageSize = 10,
checkHasAnnotationGroups,
onChoose,
onCreateNew,
contentClient,
uiSettings,
}: {
contentClient: ContentClient;
uiSettings: IUiSettingsClient;
http: CoreStart['http'];
savedObjectsManagement: SavedObjectsManagementPluginStart;
fixedPageSize?: number;
checkHasAnnotationGroups: () => Promise<boolean>;
onChoose: (value: {
id: string;
type: string;
fullName: string;
savedObject: SavedObjectCommon<unknown>;
savedObject: SavedObjectCommon;
}) => void;
onCreateNew: () => void;
}) => {
@ -115,9 +112,8 @@ export const EventAnnotationGroupSavedObjectFinder = ({
}
savedObjectMetaData={savedObjectMetaData}
services={{
contentClient,
uiSettings,
http,
savedObjectsManagement,
}}
/>
);

View file

@ -29,13 +29,12 @@
"@kbn/content-management-table-list-view-table",
"@kbn/content-management-tabbed-table-list-view",
"@kbn/event-annotation-common",
"@kbn/core",
"@kbn/i18n-react",
"@kbn/saved-objects-finder-plugin",
"@kbn/saved-objects-management-plugin",
"@kbn/core-notifications-browser-mocks",
"@kbn/core-notifications-browser",
"@kbn/core-saved-objects-api-browser",
"@kbn/expressions-plugin",
"@kbn/content-management-plugin",
]
}

View file

@ -42,7 +42,7 @@ export interface EventAnnotationServiceType {
id: string;
type: string;
fullName: string;
savedObject: SavedObjectCommon<unknown>;
savedObject: SavedObjectCommon;
}) => void;
onCreateNew: () => void;
}) => JSX.Element;

View file

@ -23,6 +23,7 @@ const createStartContract = (): ContentManagementPublicStart => {
update: jest.fn(),
delete: jest.fn(),
search: jest.fn(),
mSearch: jest.fn(),
} as unknown as ContentManagementPublicStart['client'],
registry: {
get: jest.fn(),

View file

@ -32,18 +32,15 @@ export const buildAllDashboardActions = async ({
plugins,
allowByValueEmbeddables,
}: BuildAllDashboardActionsProps) => {
const { uiSettings } = core;
const { uiActions, share, presentationUtil, savedObjectsManagement, savedObjectsTaggingOss } =
plugins;
const { uiActions, share, presentationUtil, savedObjectsTaggingOss, contentManagement } = plugins;
const clonePanelAction = new ClonePanelAction(core.savedObjects);
uiActions.registerAction(clonePanelAction);
uiActions.attachAction(CONTEXT_MENU_TRIGGER, clonePanelAction.id);
const SavedObjectFinder = getSavedObjectFinder(
uiSettings,
core.http,
savedObjectsManagement,
contentManagement.client,
core.uiSettings,
savedObjectsTaggingOss?.getTaggingApi()
);
const changeViewAction = new ReplacePanelAction(SavedObjectFinder);

View file

@ -0,0 +1,17 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { PluginServiceFactory } from '@kbn/presentation-util-plugin/public';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { contentManagementMock } from '@kbn/content-management-plugin/public/mocks';
export type ContentManagementServiceFactory = PluginServiceFactory<ContentManagementPublicStart>;
export const contentManagementServiceFactory: ContentManagementServiceFactory = () => {
return contentManagementMock.createStartContract();
};

View file

@ -0,0 +1,24 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { KibanaPluginServiceFactory } from '@kbn/presentation-util-plugin/public';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { DashboardStartDependencies } from '../../plugin';
export type ContentManagementServiceFactory = KibanaPluginServiceFactory<
ContentManagementPublicStart,
DashboardStartDependencies
>;
export const contentManagementServiceFactory: ContentManagementServiceFactory = ({
startPlugins,
}) => {
const { contentManagement } = startPlugins;
return contentManagement;
};

View file

@ -40,6 +40,7 @@ import { visualizationsServiceFactory } from './visualizations/visualizations.st
import { dashboardContentManagementServiceFactory } from './dashboard_content_management/dashboard_content_management.stub';
import { customBrandingServiceFactory } from './custom_branding/custom_branding.stub';
import { savedObjectsManagementServiceFactory } from './saved_objects_management/saved_objects_management_service.stub';
import { contentManagementServiceFactory } from './content_management/content_management_service.stub';
export const providers: PluginServiceProviders<DashboardServices> = {
dashboardContentManagement: new PluginServiceProvider(dashboardContentManagementServiceFactory),
@ -68,6 +69,7 @@ export const providers: PluginServiceProviders<DashboardServices> = {
visualizations: new PluginServiceProvider(visualizationsServiceFactory),
customBranding: new PluginServiceProvider(customBrandingServiceFactory),
savedObjectsManagement: new PluginServiceProvider(savedObjectsManagementServiceFactory),
contentManagement: new PluginServiceProvider(contentManagementServiceFactory),
};
export const registry = new PluginServiceRegistry<DashboardServices>(providers);

View file

@ -41,6 +41,7 @@ import { analyticsServiceFactory } from './analytics/analytics_service';
import { customBrandingServiceFactory } from './custom_branding/custom_branding_service';
import { savedObjectsManagementServiceFactory } from './saved_objects_management/saved_objects_management_service';
import { dashboardContentManagementServiceFactory } from './dashboard_content_management/dashboard_content_management_service';
import { contentManagementServiceFactory } from './content_management/content_management_service';
const providers: PluginServiceProviders<DashboardServices, DashboardPluginServiceParams> = {
dashboardContentManagement: new PluginServiceProvider(dashboardContentManagementServiceFactory, [
@ -82,6 +83,7 @@ const providers: PluginServiceProviders<DashboardServices, DashboardPluginServic
visualizations: new PluginServiceProvider(visualizationsServiceFactory),
customBranding: new PluginServiceProvider(customBrandingServiceFactory),
savedObjectsManagement: new PluginServiceProvider(savedObjectsManagementServiceFactory),
contentManagement: new PluginServiceProvider(contentManagementServiceFactory),
};
export const pluginServices = new PluginServices<DashboardServices>();

View file

@ -9,6 +9,7 @@
import { PluginInitializerContext } from '@kbn/core/public';
import { KibanaPluginServiceParams } from '@kbn/presentation-util-plugin/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { DashboardStartDependencies } from '../plugin';
import { DashboardAnalyticsService } from './analytics/types';
@ -68,4 +69,5 @@ export interface DashboardServices {
visualizations: DashboardVisualizationsService;
customBranding: DashboardCustomBrandingService;
savedObjectsManagement: SavedObjectsManagementPluginStart;
contentManagement: ContentManagementPublicStart;
}

View file

@ -31,6 +31,7 @@ export class DataViewsStorage extends SOContentStorage<DataViewCrudTypes> {
'allowNoIndex',
'name',
],
mSearchAdditionalSearchFields: ['name'],
});
}
}

View file

@ -25,7 +25,8 @@
"dataViewEditor",
"expressions",
"unifiedSearch",
"unifiedHistogram"
"unifiedHistogram",
"contentManagement"
],
"optionalPlugins": [
"home",
@ -36,13 +37,7 @@
"savedObjectsTaggingOss",
"lens"
],
"requiredBundles": [
"kibanaUtils",
"kibanaReact",
"unifiedSearch"
],
"extraPublicDirs": [
"common"
]
"requiredBundles": ["kibanaUtils", "kibanaReact", "unifiedSearch"],
"extraPublicDirs": ["common"]
}
}

View file

@ -42,8 +42,7 @@ exports[`OpenSearchPanel render 1`] = `
}
services={
Object {
"http": undefined,
"savedObjectsManagement": undefined,
"contentClient": undefined,
"savedObjectsTagging": undefined,
"uiSettings": undefined,
}

View file

@ -30,14 +30,8 @@ interface OpenSearchPanelProps {
}
export function OpenSearchPanel(props: OpenSearchPanelProps) {
const {
addBasePath,
capabilities,
core,
uiSettings,
savedObjectsManagement,
savedObjectsTagging,
} = useDiscoverServices();
const { addBasePath, capabilities, savedObjectsTagging, contentClient, uiSettings } =
useDiscoverServices();
const hasSavedObjectPermission =
capabilities.savedObjectsManagement?.edit || capabilities.savedObjectsManagement?.delete;
@ -56,10 +50,9 @@ export function OpenSearchPanel(props: OpenSearchPanelProps) {
<EuiFlyoutBody>
<SavedObjectFinder
services={{
http: core.http,
uiSettings,
savedObjectsManagement,
savedObjectsTagging,
contentClient,
uiSettings,
}}
noItemsMessage={
<FormattedMessage

View file

@ -51,6 +51,7 @@ import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/
import type { LensPublicStart } from '@kbn/lens-plugin/public';
import type { UiActionsStart } from '@kbn/ui-actions-plugin/public';
import type { SettingsStart } from '@kbn/core-ui-settings-browser';
import type { ContentClient } from '@kbn/content-management-plugin/public';
import { getHistory } from './kibana_services';
import { DiscoverStartPlugins } from './plugin';
import { DiscoverContextAppLocator } from './application/context/services/locator';
@ -107,6 +108,7 @@ export interface DiscoverServices {
unifiedSearch: UnifiedSearchPublicPluginStart;
lens: LensPublicStart;
uiActions: UiActionsStart;
contentClient: ContentClient;
}
export const buildServices = memoize(function (
@ -165,5 +167,6 @@ export const buildServices = memoize(function (
unifiedSearch: plugins.unifiedSearch,
lens: plugins.lens,
uiActions: plugins.uiActions,
contentClient: plugins.contentManagement.client,
};
});

View file

@ -36,6 +36,7 @@ import { DataViewsServicePublic } from '@kbn/data-views-plugin/public';
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
import { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public';
import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public';
import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
@ -209,6 +210,7 @@ export interface DiscoverStartPlugins {
savedSearch: SavedSearchPublicPluginStart;
unifiedSearch: UnifiedSearchPublicPluginStart;
lens: LensPublicStart;
contentManagement: ContentManagementPublicStart;
}
/**

View file

@ -64,7 +64,8 @@
"@kbn/shared-ux-utility",
"@kbn/core-application-browser",
"@kbn/core-saved-objects-server",
"@kbn/discover-utils"
"@kbn/discover-utils",
"@kbn/content-management-plugin",
],
"exclude": [
"target/**/*"

View file

@ -12,7 +12,8 @@
"inspector",
"uiActions",
"savedObjectsFinder",
"savedObjectsManagement"
"savedObjectsManagement",
"contentManagement"
],
"optionalPlugins": ["savedObjectsTaggingOss", "usageCollection"],
"requiredBundles": ["savedObjects", "kibanaReact", "kibanaUtils"],

View file

@ -34,7 +34,7 @@ jest.mock('@kbn/saved-objects-finder-plugin/public', () => {
'testId',
'CONTACT_CARD_EMBEDDABLE',
'test name',
{} as unknown as SavedObjectCommon<unknown>
{} as unknown as SavedObjectCommon
)
}
>

View file

@ -24,7 +24,7 @@ import {
embeddableStart,
usageCollection,
savedObjectsTaggingOss,
savedObjectsManagement,
contentManagement,
} from '../kibana_services';
import {
IContainer,
@ -85,7 +85,7 @@ export const AddPanelFlyout = ({
(embeddableFactory) =>
Boolean(embeddableFactory.savedObjectMetaData) && !embeddableFactory.isContainerType
)
.map(({ savedObjectMetaData }) => savedObjectMetaData as SavedObjectMetaData<unknown>),
.map(({ savedObjectMetaData }) => savedObjectMetaData as SavedObjectMetaData),
[factoriesBySavedObjectType]
);
@ -125,10 +125,9 @@ export const AddPanelFlyout = ({
<EuiFlyoutBody>
<SavedObjectFinder
services={{
http: core.http,
savedObjectsManagement,
uiSettings: core.uiSettings,
contentClient: contentManagement.client,
savedObjectsTagging: savedObjectsTaggingOss?.getTaggingApi(),
uiSettings: core.uiSettings,
}}
onChoose={onChoose}
savedObjectMetaData={metaData}

View file

@ -19,6 +19,7 @@ export let inspector: EmbeddableStartDependencies['inspector'];
export let usageCollection: EmbeddableStartDependencies['usageCollection'];
export let savedObjectsManagement: EmbeddableStartDependencies['savedObjectsManagement'];
export let savedObjectsTaggingOss: EmbeddableStartDependencies['savedObjectsTaggingOss'];
export let contentManagement: EmbeddableStartDependencies['contentManagement'];
const servicesReady$ = new BehaviorSubject(false);
export const untilPluginStartServicesReady = () => {
@ -45,6 +46,7 @@ export const setKibanaServices = (
usageCollection = deps.usageCollection;
savedObjectsManagement = deps.savedObjectsManagement;
savedObjectsTaggingOss = deps.savedObjectsTaggingOss;
contentManagement = deps.contentManagement;
servicesReady$.next(true);
};

View file

@ -16,6 +16,7 @@ import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks';
import { type AggregateQuery, type Filter, type Query } from '@kbn/es-query';
import { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public';
import { savedObjectsManagementPluginMock } from '@kbn/saved-objects-management-plugin/public/mocks';
import { contentManagementMock } from '@kbn/content-management-plugin/public/mocks';
import {
EmbeddableStart,
@ -141,6 +142,8 @@ const createInstance = (setupPlugins: Partial<EmbeddableSetupDependencies> = {})
savedObjectsManagement:
savedObjectsManagementMock as unknown as SavedObjectsManagementPluginStart,
usageCollection: { reportUiCounter: jest.fn() },
contentManagement:
startPlugins.contentManagement || contentManagementMock.createStartContract(),
});
return {
plugin,
@ -167,5 +170,6 @@ export const setStubKibanaServices = () => {
inspector: inspectorPluginMock.createStartContract(),
savedObjectsManagement: savedObjectsManagementPluginMock.createStartContract(),
usageCollection: { reportUiCounter: jest.fn() },
contentManagement: contentManagementMock.createStartContract(),
});
};

View file

@ -23,6 +23,7 @@ import { Storage } from '@kbn/kibana-utils-plugin/public';
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
import { migrateToLatest, PersistableStateService } from '@kbn/kibana-utils-plugin/common';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public';
import {
EmbeddableFactoryRegistry,
@ -65,6 +66,7 @@ export interface EmbeddableStartDependencies {
uiActions: UiActionsStart;
inspector: InspectorStart;
usageCollection: UsageCollectionStart;
contentManagement: ContentManagementPublicStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart;
}

View file

@ -17,6 +17,7 @@ import {
} from '@kbn/saved-objects-management-plugin/public';
import { Query } from '@kbn/es-query';
import { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public';
import { contentManagementMock } from '@kbn/content-management-plugin/public/mocks';
import { EmbeddablePublicPlugin, EmbeddableSetup, EmbeddableStart } from '../plugin';
export interface TestPluginReturn {
plugin: EmbeddablePublicPlugin;
@ -66,6 +67,7 @@ export const testPlugin = (
savedObjectsManagement:
savedObjectsManagementMock as unknown as SavedObjectsManagementPluginStart,
usageCollection: { reportUiCounter: jest.fn() },
contentManagement: contentManagementMock.createStartContract(),
});
return start;
},

View file

@ -29,7 +29,8 @@
"@kbn/analytics",
"@kbn/usage-collection-plugin",
"@kbn/ui-theme",
"@kbn/core-mount-utils-browser"
"@kbn/core-mount-utils-browser",
"@kbn/content-management-plugin"
],
"exclude": ["target/**/*"]
}

View file

@ -9,7 +9,6 @@
"browser": true,
"requiredPlugins": [
"expressions",
"savedObjectsManagement",
"data",
"presentationUtil",
"visualizations",

View file

@ -8,12 +8,11 @@
import React, { useEffect, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { CoreStart } from '@kbn/core/public';
import { FormattedMessage } from '@kbn/i18n-react';
import { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
import type { SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentClient } from '@kbn/content-management-plugin/public';
import { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
import {
EuiButton,
EuiEmptyPrompt,
@ -26,24 +25,22 @@ import { css } from '@emotion/react';
import { EVENT_ANNOTATION_GROUP_TYPE } from '@kbn/event-annotation-common';
export const EventAnnotationGroupSavedObjectFinder = ({
contentClient,
uiSettings,
http,
savedObjectsManagement,
fixedPageSize = 10,
checkHasAnnotationGroups,
onChoose,
onCreateNew,
}: {
uiSettings: IUiSettingsClient;
http: CoreStart['http'];
savedObjectsManagement: SavedObjectsManagementPluginStart;
contentClient: ContentClient;
fixedPageSize?: number;
checkHasAnnotationGroups: () => Promise<boolean>;
onChoose: (value: {
id: string;
type: string;
fullName: string;
savedObject: SavedObjectCommon<unknown>;
savedObject: SavedObjectCommon;
}) => void;
onCreateNew: () => void;
}) => {
@ -114,11 +111,7 @@ export const EventAnnotationGroupSavedObjectFinder = ({
/>
}
savedObjectMetaData={savedObjectMetaData}
services={{
uiSettings,
http,
savedObjectsManagement,
}}
services={{ contentClient, uiSettings }}
/>
);
};

View file

@ -7,7 +7,6 @@
*/
import { CoreStart } from '@kbn/core/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { EventAnnotationServiceType } from '@kbn/event-annotation-components';
export type { EventAnnotationServiceType };
@ -16,27 +15,17 @@ export class EventAnnotationService {
private eventAnnotationService?: EventAnnotationServiceType;
private core: CoreStart;
private savedObjectsManagement: SavedObjectsManagementPluginStart;
private contentManagement: ContentManagementPublicStart;
constructor(
core: CoreStart,
contentManagement: ContentManagementPublicStart,
savedObjectsManagement: SavedObjectsManagementPluginStart
) {
constructor(core: CoreStart, contentManagement: ContentManagementPublicStart) {
this.core = core;
this.contentManagement = contentManagement;
this.savedObjectsManagement = savedObjectsManagement;
}
public async getService() {
if (!this.eventAnnotationService) {
const { getEventAnnotationService } = await import('./service');
this.eventAnnotationService = getEventAnnotationService(
this.core,
this.contentManagement,
this.savedObjectsManagement
);
this.eventAnnotationService = getEventAnnotationService(this.core, this.contentManagement);
}
return this.eventAnnotationService;
}

View file

@ -9,7 +9,6 @@
import { CoreStart, SimpleSavedObject } from '@kbn/core/public';
import { ContentClient, ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { coreMock } from '@kbn/core/public/mocks';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { EventAnnotationConfig } from '@kbn/event-annotation-common';
import { getEventAnnotationService } from './service';
import { EventAnnotationServiceType } from '@kbn/event-annotation-components';
@ -161,11 +160,9 @@ describe('Event Annotation Service', () => {
hits: Object.values(annotationGroupResolveMocks),
});
(contentClient.delete as jest.Mock).mockResolvedValue({});
eventAnnotationService = getEventAnnotationService(
core,
{ client: contentClient } as ContentManagementPublicStart,
{} as SavedObjectsManagementPluginStart
);
eventAnnotationService = getEventAnnotationService(core, {
client: contentClient,
} as ContentManagementPublicStart);
});
afterEach(() => {
jest.clearAllMocks();

View file

@ -11,7 +11,6 @@ import { partition } from 'lodash';
import { queryToAst } from '@kbn/data-plugin/common';
import { ExpressionAstExpression } from '@kbn/expressions-plugin/common';
import type { CoreStart, SavedObjectReference } from '@kbn/core/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { DataViewPersistableStateService } from '@kbn/data-views-plugin/common';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { type EventAnnotationServiceType } from '@kbn/event-annotation-components';
@ -48,8 +47,7 @@ export function hasIcon(icon: string | undefined): icon is string {
export function getEventAnnotationService(
core: CoreStart,
contentManagement: ContentManagementPublicStart,
savedObjectsManagement: SavedObjectsManagementPluginStart
contentManagement: ContentManagementPublicStart
): EventAnnotationServiceType {
const client = contentManagement.client;
@ -288,9 +286,8 @@ export function getEventAnnotationService(
renderEventAnnotationGroupSavedObjectFinder: (props) => {
return (
<EventAnnotationGroupSavedObjectFinder
http={core.http}
contentClient={contentManagement.client}
uiSettings={core.uiSettings}
savedObjectsManagement={savedObjectsManagement}
checkHasAnnotationGroups={checkHasAnnotationGroups}
{...props}
/>

View file

@ -7,20 +7,15 @@
*/
import { coreMock } from '@kbn/core/public/mocks';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { getEventAnnotationService } from './event_annotation_service/service';
// not really mocking but avoiding async loading
export const eventAnnotationServiceMock = getEventAnnotationService(
coreMock.createStart(),
{
client: {
get: jest.fn(),
search: jest.fn(),
create: jest.fn(),
update: jest.fn(),
},
} as unknown as ContentManagementPublicStart,
{} as SavedObjectsManagementPluginStart
);
export const eventAnnotationServiceMock = getEventAnnotationService(coreMock.createStart(), {
client: {
get: jest.fn(),
search: jest.fn(),
create: jest.fn(),
update: jest.fn(),
},
} as unknown as ContentManagementPublicStart);

View file

@ -11,7 +11,6 @@ import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/
import type { SavedObjectTaggingPluginStart } from '@kbn/saved-objects-tagging-plugin/public';
import type { ExpressionsSetup } from '@kbn/expressions-plugin/public';
import { Storage } from '@kbn/kibana-utils-plugin/public';
import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import {
ContentManagementPublicSetup,
ContentManagementPublicStart,
@ -34,7 +33,6 @@ import { ANNOTATIONS_LISTING_VIEW_ID } from '../common/constants';
import { CONTENT_ID, LATEST_VERSION } from '../common/content_management';
export interface EventAnnotationStartDependencies {
savedObjectsManagement: SavedObjectsManagementPluginStart;
data: DataPublicPluginStart;
savedObjectsTagging: SavedObjectTaggingPluginStart;
presentationUtil: PresentationUtilPluginStart;
@ -89,8 +87,7 @@ export class EventAnnotationPlugin
const eventAnnotationService = await new EventAnnotationService(
coreStart,
pluginsStart.contentManagement,
pluginsStart.savedObjectsManagement
pluginsStart.contentManagement
).getService();
const ids = await pluginsStart.dataViews.getIds();
@ -125,10 +122,6 @@ export class EventAnnotationPlugin
core: CoreStart,
startDependencies: EventAnnotationStartDependencies
): EventAnnotationService {
return new EventAnnotationService(
core,
startDependencies.contentManagement,
startDependencies.savedObjectsManagement
);
return new EventAnnotationService(core, startDependencies.contentManagement);
}
}

View file

@ -19,7 +19,6 @@
"@kbn/core-ui-settings-browser",
"@kbn/datemath",
"@kbn/saved-objects-finder-plugin",
"@kbn/saved-objects-management-plugin",
"@kbn/saved-objects-tagging-plugin",
"@kbn/presentation-util-plugin",
"@kbn/visualizations-plugin",

View file

@ -7,4 +7,4 @@
*/
export { PER_PAGE_SETTING, LISTING_LIMIT_SETTING } from '@kbn/saved-objects-settings';
export type { SavedObjectCommon, FindQueryHTTP, FindResponseHTTP, FinderAttributes } from './types';
export type { FinderAttributes, SavedObjectCommon } from './types';

View file

@ -5,32 +5,11 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { SavedObject } from '@kbn/core-saved-objects-server';
import type { SOWithMetadata } from '@kbn/content-management-utils';
export type SavedObjectCommon<T = unknown> = SavedObject<T>;
export interface FindQueryHTTP {
perPage?: number;
page?: number;
type: string | string[];
search?: string;
searchFields?: string[];
defaultSearchOperator?: 'AND' | 'OR';
sortField?: string;
sortOrder?: 'asc' | 'desc';
fields?: string | string[];
hasReference?: string;
}
export type SavedObjectCommon<T extends FinderAttributes = FinderAttributes> = SOWithMetadata<T>;
export interface FinderAttributes {
title?: string;
name?: string;
type: string;
}
export interface FindResponseHTTP<T> {
saved_objects: Array<SavedObjectCommon<T>>;
total: number;
page: number;
per_page: number;
}

View file

@ -6,5 +6,6 @@
"id": "savedObjectsFinder",
"server": true,
"browser": true,
"requiredBundles": ["savedObjectsManagement"]
}
}

View file

@ -8,10 +8,9 @@
import { EuiDelayRender, EuiSkeletonText } from '@elastic/eui';
import React from 'react';
import { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
import { HttpStart } from '@kbn/core-http-browser';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public';
import type { ContentClient } from '@kbn/content-management-plugin/public';
import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
import type { SavedObjectFinderProps } from './saved_object_finder';
const LazySavedObjectFinder = React.lazy(() => import('./saved_object_finder'));
@ -28,16 +27,12 @@ const SavedObjectFinder = (props: SavedObjectFinderProps) => (
);
export const getSavedObjectFinder = (
contentClient: ContentClient,
uiSettings: IUiSettingsClient,
http: HttpStart,
savedObjectsManagement: SavedObjectsManagementPluginStart,
savedObjectsTagging?: SavedObjectsTaggingApi
) => {
return (props: SavedObjectFinderProps) => (
<SavedObjectFinder
{...props}
services={{ uiSettings, http, savedObjectsManagement, savedObjectsTagging }}
/>
<SavedObjectFinder {...props} services={{ savedObjectsTagging, contentClient, uiSettings }} />
);
};

View file

@ -9,44 +9,39 @@
import { debounce } from 'lodash';
import PropTypes from 'prop-types';
import React, { ReactElement, ReactNode } from 'react';
import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { getTagFindReferences, parseQuery } from '@kbn/saved-objects-management-plugin/public';
import type { ContentClient } from '@kbn/content-management-plugin/public';
import type { IUiSettingsClient } from '@kbn/core/public';
import {
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiInMemoryTable,
EuiLink,
EuiTableFieldDataColumnType,
IconType,
EuiIcon,
EuiToolTip,
EuiSearchBarProps,
SearchFilterConfig,
Query,
PropertySort,
EuiFlexItem,
EuiFlexGroup,
EuiTableFieldDataColumnType,
EuiText,
EuiToolTip,
IconType,
PropertySort,
Query,
SearchFilterConfig,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import type { IUiSettingsClient, HttpStart } from '@kbn/core/public';
import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public';
import {
SavedObjectCommon,
FindQueryHTTP,
FindResponseHTTP,
FinderAttributes,
LISTING_LIMIT_SETTING,
} from '../../common';
import { FinderAttributes, SavedObjectCommon, LISTING_LIMIT_SETTING } from '../../common';
export interface SavedObjectMetaData<T = unknown> {
export interface SavedObjectMetaData<T extends FinderAttributes = FinderAttributes> {
type: string;
name: string;
getIconForSavedObject(savedObject: SavedObjectCommon<T>): IconType;
getTooltipForSavedObject?(savedObject: SavedObjectCommon<T>): string;
showSavedObject?(savedObject: SavedObjectCommon<T>): boolean;
getSavedObjectSubType?(savedObject: SavedObjectCommon<T>): string;
/** @deprecated doesn't do anything, the full object is returned **/
includeFields?: string[];
defaultSearchField?: string;
}
interface SavedObjectFinderItem extends SavedObjectCommon {
@ -63,10 +58,9 @@ interface SavedObjectFinderState {
}
interface SavedObjectFinderServices {
http: HttpStart;
uiSettings: IUiSettingsClient;
savedObjectsManagement: SavedObjectsManagementPluginStart;
savedObjectsTagging?: SavedObjectsTaggingApi;
contentClient: ContentClient;
uiSettings: IUiSettingsClient;
}
interface BaseSavedObjectFinder {
@ -113,21 +107,9 @@ export class SavedObjectFinderUi extends React.Component<
private debouncedFetch = debounce(async (query: Query) => {
const metaDataMap = this.getSavedObjectMetaDataMap();
const { savedObjectsManagement, uiSettings, http } = this.props.services;
const { contentClient, uiSettings } = this.props.services;
const fields = Object.values(metaDataMap)
.map((metaData) => metaData.includeFields || [])
.reduce((allFields, currentFields) => allFields.concat(currentFields), ['title', 'name']);
const additionalSearchFields = Object.values(metaDataMap).reduce<string[]>((col, item) => {
if (item.defaultSearchField) {
col.push(item.defaultSearchField);
}
return col;
}, []);
const perPage = uiSettings.get(LISTING_LIMIT_SETTING);
const { queryText, visibleTypes, selectedTags } = savedObjectsManagement.parseQuery(
const { queryText, visibleTypes, selectedTags } = parseQuery(
query,
Object.values(metaDataMap).map((metadata) => ({
name: metadata.type,
@ -136,26 +118,23 @@ export class SavedObjectFinderUi extends React.Component<
displayName: metadata.name,
}))
);
const hasReference = savedObjectsManagement.getTagFindReferences({
const includeTags = getTagFindReferences({
selectedTags,
taggingApi: this.props.services.savedObjectsTagging,
})?.map(({ id, type }) => id);
const types = visibleTypes ?? Object.keys(metaDataMap);
const response = await contentClient.mSearch<SavedObjectCommon<FinderAttributes>>({
contentTypes: types.map((type) => ({ contentTypeId: type })),
query: {
text: queryText ? `${queryText}*` : undefined,
...(includeTags?.length ? { tags: { included: includeTags } } : {}),
limit: uiSettings.get(LISTING_LIMIT_SETTING), // TODO: support pagination,
},
});
const params: FindQueryHTTP = {
type: visibleTypes ?? Object.keys(metaDataMap),
search: queryText ? `${queryText}*` : undefined,
fields: [...new Set(fields)],
page: 1,
perPage,
searchFields: ['title^3', 'description', ...additionalSearchFields],
defaultSearchOperator: 'AND',
hasReference: hasReference ? JSON.stringify(hasReference) : undefined,
};
const response = (await http.get('/internal/saved-objects-finder/find', {
query: params as Record<string, any>,
})) as FindResponseHTTP<FinderAttributes>;
const savedObjects = response.saved_objects
const savedObjects = response.hits
.map((savedObject) => {
const {
attributes: { name, title },
@ -270,7 +249,7 @@ export class SavedObjectFinderUi extends React.Component<
currentSavedObjectMetaData ||
({
getIconForSavedObject: () => 'document',
} as Pick<SavedObjectMetaData<{ title: string }>, 'getIconForSavedObject'>)
} as Pick<SavedObjectMetaData, 'getIconForSavedObject'>)
).getIconForSavedObject(item.simple);
return (

View file

@ -6,8 +6,6 @@
* Side Public License, v 1.
*/
import { registerRoutesMock } from './plugin.test.mocks';
import { coreMock } from '@kbn/core/server/mocks';
import { SavedObjectsServerPlugin } from './plugin';
import { uiSettings } from './ui_settings';
@ -21,17 +19,11 @@ describe('SavedObjectsPlugin', () => {
plugin = new SavedObjectsServerPlugin();
});
afterEach(() => {
registerRoutesMock.mockReset();
});
describe('#setup', () => {
it('calls `registerRoutes` and `registerSettings` with the correct parameters', () => {
it('calls `registerSettings` with the correct parameters', () => {
plugin.setup(coreSetup);
expect(coreSetup.uiSettings.register).toHaveBeenCalledWith(uiSettings);
expect(coreSetup.http.createRouter).toHaveBeenCalledTimes(1);
expect(registerRoutesMock).toHaveBeenCalledTimes(1);
});
});
});

View file

@ -6,15 +6,12 @@
* Side Public License, v 1.
*/
import type { CoreSetup, Plugin, RequestHandlerContext } from '@kbn/core/server';
import { registerRoutes } from './routes';
import type { CoreSetup, Plugin } from '@kbn/core/server';
import { uiSettings } from './ui_settings';
export class SavedObjectsServerPlugin implements Plugin<object, object> {
public setup(core: CoreSetup) {
core.uiSettings.register(uiSettings);
const router = core.http.createRouter<RequestHandlerContext>();
registerRoutes(router);
return {};
}

View file

@ -1,63 +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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { schema } from '@kbn/config-schema';
import { SavedObjectsRouter } from '../types';
import type { SavedObjectCommon, FindResponseHTTP } from '../../common';
export const registerFindRoute = (router: SavedObjectsRouter) => {
router.get(
{
path: '/internal/saved-objects-finder/find',
validate: {
query: schema.object({
perPage: schema.number({ min: 0, defaultValue: 20 }),
page: schema.number({ min: 0, defaultValue: 1 }),
type: schema.oneOf([schema.string(), schema.arrayOf(schema.string())]),
search: schema.maybe(schema.string()),
defaultSearchOperator: schema.oneOf([schema.literal('AND'), schema.literal('OR')]),
sortField: schema.maybe(schema.string()),
sortOrder: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])),
fields: schema.oneOf([schema.string(), schema.arrayOf(schema.string())], {
defaultValue: [],
}),
searchFields: schema.maybe(schema.arrayOf(schema.string())),
hasReference: schema.maybe(schema.string()),
}),
},
options: {
authRequired: 'optional',
},
},
async (ctx, req, res) => {
const savedObjectsClient = (await ctx.core).savedObjects.client;
const { query } = req;
const searchTypes = Array.isArray(query.type) ? query.type : [query.type];
const includedFields = Array.isArray(query.fields) ? query.fields : [query.fields];
const findResponse = await savedObjectsClient.find<SavedObjectCommon<any>>({
...query,
type: searchTypes,
fields: includedFields,
hasReference: query.hasReference ? JSON.parse(query.hasReference) : undefined,
});
const savedObjects = findResponse.saved_objects;
const response: FindResponseHTTP<any> = {
saved_objects: savedObjects,
total: findResponse.total,
per_page: findResponse.per_page,
page: findResponse.page,
};
return res.ok({ body: response });
}
);
};

View file

@ -1,14 +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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { SavedObjectsRouter } from '../types';
import { registerFindRoute } from './find';
export const registerRoutes = (router: SavedObjectsRouter) => {
registerFindRoute(router);
};

View file

@ -1,10 +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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { IRouter, RequestHandlerContext } from '@kbn/core/server';
export type SavedObjectsRouter = IRouter<RequestHandlerContext>;

View file

@ -10,11 +10,11 @@
"@kbn/test-jest-helpers",
"@kbn/saved-objects-tagging-oss-plugin",
"@kbn/i18n",
"@kbn/core-saved-objects-server",
"@kbn/config-schema",
"@kbn/core-ui-settings-browser",
"@kbn/core-http-browser",
"@kbn/saved-objects-settings",
"@kbn/content-management-plugin",
"@kbn/content-management-utils",
"@kbn/core-ui-settings-browser",
],
"exclude": [
"target/**/*",

View file

@ -23,7 +23,7 @@ export type {
} from './services';
export { SavedObjectsManagementAction } from './services';
export type { ProcessedImportResponse, FailedImport } from './lib';
export { processImportResponse } from './lib';
export { processImportResponse, getTagFindReferences, parseQuery } from './lib';
export type {
SavedObjectRelation,
SavedObjectWithMetadata,

View file

@ -57,6 +57,7 @@ import { createVisEmbeddableFromObject } from './create_vis_embeddable_from_obje
import type { VisualizationsStartDeps } from '../plugin';
interface VisualizationAttributes extends SavedObjectAttributes {
title: string;
visState: string;
}

View file

@ -12,8 +12,7 @@ import { TypesStart, VisGroups, BaseVisType } from '../vis_types';
import NewVisModal from './new_vis_modal';
import { ApplicationStart, DocLinksStart } from '@kbn/core/public';
import { embeddablePluginMock } from '@kbn/embeddable-plugin/public/mocks';
import { httpServiceMock } from '@kbn/core-http-browser-mocks';
import { savedObjectsManagementPluginMock } from '@kbn/saved-objects-management-plugin/public/mocks';
import { contentManagementMock } from '@kbn/content-management-plugin/public/mocks';
describe('NewVisModal', () => {
const defaultVisTypeParams = {
@ -78,8 +77,8 @@ describe('NewVisModal', () => {
},
},
};
const http = httpServiceMock.createStartContract({ basePath: '' });
const savedObjectsManagement = savedObjectsManagementPluginMock.createStartContract();
const contentManagement = contentManagementMock.createStartContract();
beforeAll(() => {
Object.defineProperty(window, 'location', {
@ -103,8 +102,7 @@ describe('NewVisModal', () => {
uiSettings={uiSettings}
application={{} as ApplicationStart}
docLinks={docLinks as DocLinksStart}
http={http}
savedObjectsManagement={savedObjectsManagement}
contentClient={contentManagement.client}
/>
);
expect(wrapper.find('[data-test-subj="visGroup-aggbased"]').exists()).toBe(true);
@ -121,8 +119,7 @@ describe('NewVisModal', () => {
uiSettings={uiSettings}
application={{} as ApplicationStart}
docLinks={docLinks as DocLinksStart}
http={http}
savedObjectsManagement={savedObjectsManagement}
contentClient={contentManagement.client}
/>
);
expect(wrapper.find('[data-test-subj="visGroup-tools"]').exists()).toBe(true);
@ -138,8 +135,7 @@ describe('NewVisModal', () => {
uiSettings={uiSettings}
application={{} as ApplicationStart}
docLinks={docLinks as DocLinksStart}
http={http}
savedObjectsManagement={savedObjectsManagement}
contentClient={contentManagement.client}
/>
);
expect(wrapper.find('[data-test-subj="visType-vis2"]').exists()).toBe(true);
@ -156,8 +152,7 @@ describe('NewVisModal', () => {
uiSettings={uiSettings}
application={{} as ApplicationStart}
docLinks={docLinks as DocLinksStart}
http={http}
savedObjectsManagement={savedObjectsManagement}
contentClient={contentManagement.client}
/>
);
const visCard = wrapper.find('[data-test-subj="visType-vis"]').last();
@ -176,8 +171,7 @@ describe('NewVisModal', () => {
uiSettings={uiSettings}
application={{} as ApplicationStart}
docLinks={docLinks as DocLinksStart}
http={http}
savedObjectsManagement={savedObjectsManagement}
contentClient={contentManagement.client}
/>
);
const visCard = wrapper.find('[data-test-subj="visType-vis"]').last();
@ -203,8 +197,7 @@ describe('NewVisModal', () => {
application={{ navigateToApp } as unknown as ApplicationStart}
docLinks={docLinks as DocLinksStart}
stateTransfer={stateTransfer}
http={http}
savedObjectsManagement={savedObjectsManagement}
contentClient={contentManagement.client}
/>
);
const visCard = wrapper.find('[data-test-subj="visType-visWithAliasUrl"]').last();
@ -229,8 +222,7 @@ describe('NewVisModal', () => {
uiSettings={uiSettings}
application={{ navigateToApp } as unknown as ApplicationStart}
docLinks={docLinks as DocLinksStart}
http={http}
savedObjectsManagement={savedObjectsManagement}
contentClient={contentManagement.client}
/>
);
const visCard = wrapper.find('[data-test-subj="visType-visWithAliasUrl"]').last();
@ -251,8 +243,7 @@ describe('NewVisModal', () => {
uiSettings={uiSettings}
application={{} as ApplicationStart}
docLinks={docLinks as DocLinksStart}
http={http}
savedObjectsManagement={savedObjectsManagement}
contentClient={contentManagement.client}
/>
);
const aggBasedGroupCard = wrapper

View file

@ -12,9 +12,9 @@ import { EuiModal } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { METRIC_TYPE, UiCounterMetricType } from '@kbn/analytics';
import { ApplicationStart, IUiSettingsClient, DocLinksStart, HttpStart } from '@kbn/core/public';
import { ApplicationStart, DocLinksStart, IUiSettingsClient } from '@kbn/core/public';
import { EmbeddableStateTransfer } from '@kbn/embeddable-plugin/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentClient } from '@kbn/content-management-plugin/public';
import { SearchSelection } from './search_selection';
import { GroupSelection } from './group_selection';
import { AggBasedSelection } from './agg_based_selection';
@ -22,6 +22,7 @@ import type { TypesStart, BaseVisType, VisTypeAlias } from '../vis_types';
import './dialog.scss';
interface TypeSelectionProps {
contentClient: ContentClient;
isOpen: boolean;
onClose: () => void;
visTypesRegistry: TypesStart;
@ -29,14 +30,12 @@ interface TypeSelectionProps {
addBasePath: (path: string) => string;
uiSettings: IUiSettingsClient;
docLinks: DocLinksStart;
http: HttpStart;
application: ApplicationStart;
outsideVisualizeApp?: boolean;
stateTransfer?: EmbeddableStateTransfer;
originatingApp?: string;
showAggsSelection?: boolean;
selectedVisType?: BaseVisType;
savedObjectsManagement: SavedObjectsManagementPluginStart;
}
interface TypeSelectionState {
@ -88,11 +87,10 @@ class NewVisModal extends React.Component<TypeSelectionProps, TypeSelectionState
this.state.showSearchVisModal && this.state.visType ? (
<EuiModal onClose={this.onCloseModal} className="visNewVisSearchDialog">
<SearchSelection
contentClient={this.props.contentClient}
uiSettings={this.props.uiSettings}
onSearchSelected={this.onSearchSelected}
visType={this.state.visType}
uiSettings={this.props.uiSettings}
http={this.props.http}
savedObjectsManagement={this.props.savedObjectsManagement}
goBack={() => this.setState({ showSearchVisModal: false })}
/>
</EuiModal>

View file

@ -10,20 +10,18 @@ import React from 'react';
import { EuiModalBody, EuiModalHeader, EuiModalHeaderTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { IUiSettingsClient, HttpStart } from '@kbn/core/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentClient } from '@kbn/content-management-plugin/public';
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
import { IUiSettingsClient } from '@kbn/core/public';
import type { BaseVisType } from '../../vis_types';
import { DialogNavigation } from '../dialog_navigation';
import { showSavedObject } from './show_saved_object';
interface SearchSelectionProps {
contentClient: ContentClient;
uiSettings: IUiSettingsClient;
onSearchSelected: (searchId: string, searchType: string) => void;
visType: BaseVisType;
uiSettings: IUiSettingsClient;
http: HttpStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
goBack: () => void;
}
@ -81,14 +79,12 @@ export class SearchSelection extends React.Component<SearchSelectionProps> {
defaultMessage: 'Data view',
}
),
defaultSearchField: 'name',
},
]}
fixedPageSize={this.fixedPageSize}
services={{
contentClient: this.props.contentClient,
uiSettings: this.props.uiSettings,
http: this.props.http,
savedObjectsManagement: this.props.savedObjectsManagement,
}}
/>
</EuiModalBody>

View file

@ -8,12 +8,12 @@
import type { SavedObjectCommon, FinderAttributes } from '@kbn/saved-objects-finder-plugin/common';
export interface SavedSearchesAttributes extends SavedObjectCommon {
export interface SavedSearchesAttributes extends FinderAttributes {
isTextBasedQuery: boolean;
usesAdHocDataView?: boolean;
}
export const showSavedObject = (savedObject: SavedObjectCommon<FinderAttributes>) => {
const so = savedObject as unknown as SavedObjectCommon<SavedSearchesAttributes>;
export const showSavedObject = (savedObject: SavedObjectCommon) => {
const so = savedObject as SavedObjectCommon<SavedSearchesAttributes>;
return !so.attributes.isTextBasedQuery && !so.attributes.usesAdHocDataView;
};

View file

@ -14,12 +14,12 @@ import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import {
getHttp,
getTypes,
getUISettings,
getApplication,
getEmbeddable,
getDocLinks,
getTheme,
getSavedObjectsManagement,
getContentManagement,
getUISettings,
} from '../services';
import type { BaseVisType } from '../vis_types';
@ -79,10 +79,9 @@ export function showNewVisModal({
outsideVisualizeApp={outsideVisualizeApp}
editorParams={editorParams}
visTypesRegistry={getTypes()}
addBasePath={getHttp().basePath.prepend}
contentClient={getContentManagement().client}
uiSettings={getUISettings()}
http={getHttp()}
savedObjectsManagement={getSavedObjectsManagement()}
addBasePath={getHttp().basePath.prepend}
application={getApplication()}
docLinks={getDocLinks()}
showAggsSelection={showAggsSelection}

View file

@ -50,7 +50,6 @@
"@kbn/core-overlays-browser",
"@kbn/config-schema",
"@kbn/usage-collection-plugin",
"@kbn/core-http-browser-mocks",
"@kbn/shared-ux-router",
"@kbn/saved-objects-management-plugin",
"@kbn/saved-objects-finder-plugin",

View file

@ -0,0 +1,63 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import expect from '@kbn/expect';
import { PluginFunctionalProviderContext } from '../../plugin_functional/services';
// eslint-disable-next-line import/no-default-export
export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) {
const PageObjects = getPageObjects(['common', 'home', 'header']);
const log = getService('log');
const testSubjects = getService('testSubjects');
describe('Finder demo', () => {
before(async () => {
await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', {
useActualUrl: true,
});
await PageObjects.header.waitUntilLoadingHasFinished();
await PageObjects.home.addSampleDataSet('flights');
});
after(async () => {
await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', {
useActualUrl: true,
});
await PageObjects.header.waitUntilLoadingHasFinished();
await PageObjects.home.removeSampleDataSet('flights');
});
it('Finder demo works', async () => {
const appId = 'contentManagementExamples';
await PageObjects.common.navigateToApp(appId, {
path: 'finder',
});
await testSubjects.existOrFail(`savedObjectsFinderTable`);
await testSubjects.existOrFail(`savedObjectFinderTitle`);
const titles: string[] = [];
const titlesElements = await testSubjects.findAll(`savedObjectFinderTitle`);
for (let i = 0; i < titlesElements.length; i++) {
titles.push(await (await titlesElements[i].findByClassName(`euiLink`)).getVisibleText());
}
const expectExists = [
`Kibana Sample Data Flights`,
`[Flights] Airport Connections (Hover Over Airport)`,
`[Flights] Departures Count Map`,
`[Flights] Origin Time Delayed`,
`[Flights] Flight Log`,
];
expectExists.forEach((item) => {
log.debug(`Checking for ${item}`);
expect(titles.includes(item)).to.be(true);
});
});
});
}

View file

@ -13,5 +13,6 @@ export default function ({ loadTestFile }: PluginFunctionalProviderContext) {
describe('content management examples', function () {
loadTestFile(require.resolve('./todo_app'));
loadTestFile(require.resolve('./msearch'));
loadTestFile(require.resolve('./finder'));
});
}

View file

@ -6,11 +6,11 @@
* Side Public License, v 1.
*/
import expect from '@kbn/expect';
import { PluginFunctionalProviderContext } from '../../plugin_functional/services';
// eslint-disable-next-line import/no-default-export
export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) {
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['common', 'home', 'header']);
const listingTable = getService('listingTable');
@ -37,11 +37,19 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
});
await listingTable.waitUntilTableIsLoaded();
await listingTable.searchForItemWithName('Origin Time Delayed');
const items = await listingTable.getAllItemsNames();
const expectExists = [
`kibana_sample_data_flights`,
`[Flights] Airport Connections (Hover Over Airport)`,
`[Flights] Departures Count Map`,
`[Flights] Global Flight Dashboard`,
`[Flights] Origin Time Delayed`,
`[Flights] Flight Log`,
];
await testSubjects.existOrFail(
`cm-msearch-tableListingTitleLink-[Flights]-Origin-Time-Delayed`
);
expectExists.forEach((item) => {
expect(items.includes(item)).to.be(true);
});
});
});
}

View file

@ -30,7 +30,7 @@
"visualizations",
"uiActions",
"share",
"savedObjectsManagement",
"contentManagement",
"savedObjectsFinder"
],
"optionalPlugins": [

View file

@ -38,7 +38,7 @@ export const AddEmbeddableFlyout: FC<Props> = ({
const embeddablesService = useEmbeddablesService();
const platformService = usePlatformService();
const { getEmbeddableFactories } = embeddablesService;
const { getHttp, getUISettings, getSavedObjectsManagement } = platformService;
const { getContentManagement, getUISettings } = platformService;
const onAddPanel = useCallback(
(id: string, savedObjectType: string) => {
@ -83,9 +83,8 @@ export const AddEmbeddableFlyout: FC<Props> = ({
showFilter={true}
noItemsMessage={strings.getNoItemsText()}
services={{
contentClient: getContentManagement().client,
uiSettings: getUISettings(),
http: getHttp(),
savedObjectsManagement: getSavedObjectsManagement(),
}}
/>
</EuiFlyoutBody>

View file

@ -30,7 +30,7 @@ import { Start as InspectorStart } from '@kbn/inspector-plugin/public';
import { BfetchPublicSetup } from '@kbn/bfetch-plugin/public';
import { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public';
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { featureCatalogueEntry } from './feature_catalogue_entry';
import { CanvasAppLocatorDefinition } from '../common/locator';
import { SESSIONSTORAGE_LASTPATH, CANVAS_APP } from '../common/lib/constants';
@ -68,7 +68,7 @@ export interface CanvasStartDeps {
presentationUtil: PresentationUtilPluginStart;
visualizations: VisualizationsStart;
spaces?: SpacesPluginStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
contentManagement: ContentManagementPublicStart;
}
/**

View file

@ -41,6 +41,6 @@ export const platformServiceFactory: CanvaPlatformServiceFactory = ({
getLegacyUrlConflict: startPlugins.spaces?.ui.components.getLegacyUrlConflict,
getUISettings: () => coreStart.uiSettings,
getHttp: () => coreStart.http,
getSavedObjectsManagement: () => startPlugins.savedObjectsManagement,
getContentManagement: () => startPlugins.contentManagement,
};
};

View file

@ -15,7 +15,7 @@ import {
} from '@kbn/core/public';
import { SpacesPluginStart } from '@kbn/spaces-plugin/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
export interface CanvasPlatformService {
getBasePath: () => string;
@ -33,5 +33,5 @@ export interface CanvasPlatformService {
getLegacyUrlConflict?: SpacesPluginStart['ui']['components']['getLegacyUrlConflict'];
getUISettings: () => IUiSettingsClient;
getHttp: () => HttpStart;
getSavedObjectsManagement: () => SavedObjectsManagementPluginStart;
getContentManagement: () => ContentManagementPublicStart;
}

View file

@ -35,5 +35,5 @@ export const platformServiceFactory: CanvasPlatformServiceFactory = () => ({
redirectLegacyUrl: noop,
getLegacyUrlConflict: undefined,
getHttp: noop,
getSavedObjectsManagement: noop,
getContentManagement: noop,
});

View file

@ -79,9 +79,9 @@
"@kbn/babel-register",
"@kbn/shared-ux-button-toolbar",
"@kbn/saved-objects-finder-plugin",
"@kbn/saved-objects-management-plugin",
"@kbn/core-saved-objects-server",
"@kbn/discover-utils",
"@kbn/content-management-plugin",
],
"exclude": [
"target/**/*",

View file

@ -28,7 +28,7 @@
"ruleRegistry",
"files",
"savedObjectsFinder",
"savedObjectsManagement",
"contentManagement",
"uiActions",
],
"optionalPlugins": [

View file

@ -71,9 +71,8 @@ const LensEditorComponent: LensEuiMarkdownEditorUiPlugin['editor'] = ({
embeddable,
lens,
storage,
http,
contentManagement,
uiSettings,
savedObjectsManagement,
data: {
query: {
timefilter: { timefilter },
@ -331,9 +330,8 @@ const LensEditorComponent: LensEuiMarkdownEditorUiPlugin['editor'] = ({
savedObjectMetaData={savedObjectMetaData}
fixedPageSize={10}
services={{
contentClient: contentManagement.client,
uiSettings,
http,
savedObjectsManagement,
}}
leftChildren={createLensButton}
helpText={i18n.translate(

View file

@ -23,7 +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 { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import type { UiActionsStart } from '@kbn/ui-actions-plugin/public';
import type { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/public';
@ -74,7 +74,7 @@ export interface CasesPluginStart {
files: FilesStart;
lens: LensPublicStart;
licensing?: LicensingPluginStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
contentManagement: ContentManagementPublicStart;
security: SecurityPluginStart;
serverless?: ServerlessPluginStart;
spaces?: SpacesPluginStart;

View file

@ -61,7 +61,6 @@
"@kbn/shared-ux-file-upload",
"@kbn/shared-ux-file-mocks",
"@kbn/saved-objects-finder-plugin",
"@kbn/saved-objects-management-plugin",
"@kbn/utility-types-jest",
"@kbn/ui-actions-plugin",
"@kbn/core-lifecycle-browser",
@ -69,6 +68,7 @@
"@kbn/core-theme-browser",
"@kbn/serverless",
"@kbn/core-http-server",
"@kbn/content-management-plugin",
],
"exclude": [
"target/**/*",

View file

@ -33,7 +33,7 @@ import './index.scss';
import { SpacesApi } from '@kbn/spaces-plugin/public';
import { KibanaThemeProvider, toMountPoint } from '@kbn/kibana-react-plugin/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentClient } from '@kbn/content-management-plugin/public';
import { ContentClient, ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { GraphSavePolicy } from './types';
import { graphRouter } from './router';
import { checkLicense } from '../common/check_license';
@ -71,6 +71,7 @@ export interface GraphDependencies {
spaces?: SpacesApi;
inspect: InspectorPublicPluginStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
contentManagement: ContentManagementPublicStart;
}
export type GraphServices = Omit<GraphDependencies, 'element' | 'history'>;

View file

@ -44,6 +44,7 @@ export const WorkspaceRoute = ({
indexPatterns: getIndexPatternProvider,
inspect,
savedObjectsManagement,
contentManagement,
},
}: WorkspaceRouteProps) => {
/**
@ -72,9 +73,10 @@ export const WorkspaceRoute = ({
data,
unifiedSearch,
savedObjectsManagement,
contentManagement,
...coreStart,
}),
[coreStart, data, storage, unifiedSearch, savedObjectsManagement]
[coreStart, data, storage, unifiedSearch, savedObjectsManagement, contentManagement]
);
const { loading, requestAdapter, callNodeProxy, callSearchNodeProxy, handleSearchQueryError } =

View file

@ -22,6 +22,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { connect } from 'react-redux';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { IUnifiedSearchPluginServices } from '@kbn/unified-search-plugin/public/types';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import {
GraphState,
hasDatasourceSelector,
@ -75,9 +76,11 @@ function GuidancePanelComponent(props: GuidancePanelProps) {
const { onFillWorkspace, onOpenFieldPicker, onIndexPatternSelected, hasDatasource, hasFields } =
props;
const kibana = useKibana<IUnifiedSearchPluginServices>();
const kibana = useKibana<
IUnifiedSearchPluginServices & { contentManagement: ContentManagementPublicStart }
>();
const { services, overlays } = kibana;
const { http, uiSettings, application, data, savedObjectsManagement } = services;
const { application, data, contentManagement, uiSettings } = services;
const [hasDataViews, setHasDataViews] = useState<boolean>(true);
useEffect(() => {
@ -90,7 +93,7 @@ function GuidancePanelComponent(props: GuidancePanelProps) {
if (!overlays || !application) return null;
const onOpenDatasourcePicker = () => {
openSourceModal({ overlays, http, uiSettings, savedObjectsManagement }, onIndexPatternSelected);
openSourceModal({ overlays, contentManagement, uiSettings }, onIndexPatternSelected);
};
let content = (

View file

@ -15,6 +15,7 @@ import { useKibana } from '@kbn/kibana-react-plugin/public';
import { QueryStringInput } from '@kbn/unified-search-plugin/public';
import type { DataView } from '@kbn/data-views-plugin/public';
import { IUnifiedSearchPluginServices } from '@kbn/unified-search-plugin/public/types';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { IndexPatternSavedObject, IndexPatternProvider, WorkspaceField } from '../types';
import { openSourceModal } from '../services/source_modal';
import {
@ -95,7 +96,9 @@ export function SearchBarComponent(props: SearchBarStateProps & SearchBarProps)
fetchPattern();
}, [currentDatasource, indexPatternProvider, onIndexPatternChange]);
const kibana = useKibana<IUnifiedSearchPluginServices>();
const kibana = useKibana<
IUnifiedSearchPluginServices & { contentManagement: ContentManagementPublicStart }
>();
const { services, overlays } = kibana;
const {
uiSettings,
@ -107,7 +110,7 @@ export function SearchBarComponent(props: SearchBarStateProps & SearchBarProps)
notifications,
http,
docLinks,
savedObjectsManagement,
contentManagement,
} = services;
if (!overlays) return null;
return (
@ -133,7 +136,7 @@ export function SearchBarComponent(props: SearchBarStateProps & SearchBarProps)
confirmWipeWorkspace(
() =>
openSourceModal(
{ overlays, http, uiSettings, savedObjectsManagement },
{ overlays, contentManagement, uiSettings },
onIndexPatternSelected
),
i18n.translate('xpack.graph.clearWorkspace.confirmText', {

View file

@ -8,29 +8,28 @@
import { i18n } from '@kbn/i18n';
import React from 'react';
import { CoreStart } from '@kbn/core/public';
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
import { IndexPatternSavedObject } from '../types';
export interface SourcePickerProps {
onIndexPatternSelected: (indexPattern: IndexPatternSavedObject) => void;
http: CoreStart['http'];
uiSettings: CoreStart['uiSettings'];
savedObjectsManagement: SavedObjectsManagementPluginStart;
contentManagement: ContentManagementPublicStart;
uiSettings: IUiSettingsClient;
}
const fixedPageSize = 8;
export function SourcePicker({
http,
uiSettings,
savedObjectsManagement,
contentManagement,
onIndexPatternSelected,
uiSettings,
}: SourcePickerProps) {
return (
<SavedObjectFinder
services={{ http, uiSettings, savedObjectsManagement }}
services={{ contentClient: contentManagement.client, uiSettings }}
onChoose={(_id, _type, _name, indexPattern) => {
onIndexPatternSelected(indexPattern as IndexPatternSavedObject);
}}
@ -45,9 +44,9 @@ export function SourcePicker({
name: i18n.translate('xpack.graph.sourceModal.savedObjectType.dataView', {
defaultMessage: 'Data view',
}),
showSavedObject: (indexPattern) => !indexPattern.attributes.type,
showSavedObject: (indexPattern: SavedObjectCommon<{ type?: string; title: string }>) =>
!indexPattern.attributes.type,
includeFields: ['type'],
defaultSearchField: 'name',
},
]}
fixedPageSize={fixedPageSize}

View file

@ -132,6 +132,7 @@ export class GraphPlugin
spaces: pluginsStart.spaces,
inspect: pluginsStart.inspector,
savedObjectsManagement: pluginsStart.savedObjectsManagement,
contentManagement: pluginsStart.contentManagement,
});
},
});

View file

@ -5,32 +5,29 @@
* 2.0.
*/
import { CoreStart } from '@kbn/core/public';
import React from 'react';
import { KibanaReactOverlays } from '@kbn/kibana-react-plugin/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
import { SourceModal } from '../components/source_modal';
import { IndexPatternSavedObject } from '../types';
export function openSourceModal(
{
overlays,
http,
contentManagement,
uiSettings,
savedObjectsManagement,
}: {
overlays: KibanaReactOverlays;
http: CoreStart['http'];
uiSettings: CoreStart['uiSettings'];
savedObjectsManagement: SavedObjectsManagementPluginStart;
contentManagement: ContentManagementPublicStart;
uiSettings: IUiSettingsClient;
},
onSelected: (indexPattern: IndexPatternSavedObject) => void
) {
const modalRef = overlays.openModal(
<SourceModal
http={http}
contentManagement={contentManagement}
uiSettings={uiSettings}
savedObjectsManagement={savedObjectsManagement}
onIndexPatternSelected={(indexPattern) => {
onSelected(indexPattern);
modalRef.close();

View file

@ -45,6 +45,7 @@
"@kbn/object-versioning",
"@kbn/content-management-table-list-view-table",
"@kbn/content-management-table-list-view",
"@kbn/core-ui-settings-browser",
],
"exclude": [
"target/**/*",

View file

@ -7,10 +7,7 @@
"id": "ml",
"server": true,
"browser": true,
"configPath": [
"xpack",
"ml"
],
"configPath": ["xpack", "ml"],
"requiredPlugins": [
"aiops",
"charts",
@ -30,7 +27,8 @@
"uiActions",
"unifiedSearch",
"savedObjectsManagement",
"savedSearch"
"savedSearch",
"contentManagement"
],
"optionalPlugins": [
"alerting",
@ -58,8 +56,6 @@
"usageCollection",
"unifiedSearch"
],
"extraPublicDirs": [
"common"
]
"extraPublicDirs": ["common"]
}
}

View file

@ -101,6 +101,7 @@ const App: FC<AppProps> = ({ coreStart, deps, appMountParams }) => {
lens: deps.lens,
savedObjectsManagement: deps.savedObjectsManagement,
savedSearch: deps.savedSearch,
contentManagement: deps.contentManagement,
...coreStart,
mlServices: getMlGlobalServices(coreStart.http, deps.usageCollection),
};

View file

@ -26,6 +26,7 @@ import type { CasesUiStart } from '@kbn/cases-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import type { LensPublicStart } from '@kbn/lens-plugin/public';
import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import type { SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public';
import type { MlServicesContext } from '../../app';
@ -51,6 +52,7 @@ interface StartPlugins {
lens: LensPublicStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
savedSearch: SavedSearchPublicPluginStart;
contentManagement: ContentManagementPublicStart;
}
export type StartServices = CoreStart &
StartPlugins & {

View file

@ -79,6 +79,7 @@ jest.mock('../../../../../contexts/kibana', () => ({
savedObjectsManagement: {},
data: { dataViews: jest.fn() },
savedSearch: jest.fn(),
contentManagement: {},
},
}),
useNavigateToPath: () => mockNavigateToPath,

View file

@ -31,11 +31,10 @@ const fixedPageSize: number = 20;
export const SourceSelection: FC = () => {
const {
services: {
http,
uiSettings,
savedObjectsManagement,
savedSearch: savedSearchService,
data: { dataViews: dataViewsService },
contentManagement,
uiSettings,
},
} = useMlKibana();
const navigateToPath = useNavigateToPath();
@ -159,14 +158,12 @@ export const SourceSelection: FC = () => {
defaultMessage: 'Data view',
}
),
defaultSearchField: 'name',
},
]}
fixedPageSize={fixedPageSize}
services={{
contentClient: contentManagement.client,
uiSettings,
http,
savedObjectsManagement,
}}
/>
</EuiPageContent>

View file

@ -55,10 +55,9 @@ interface Props {
export const ChangeDataViewModal: FC<Props> = ({ onClose }) => {
const {
services: {
http,
uiSettings,
data: { dataViews },
savedObjectsManagement,
contentManagement,
uiSettings,
},
} = useMlKibana();
const navigateToPath = useNavigateToPath();
@ -168,15 +167,10 @@ export const ChangeDataViewModal: FC<Props> = ({ onClose }) => {
defaultMessage: 'Data view',
}
),
defaultSearchField: 'name',
},
]}
fixedPageSize={fixedPageSize}
services={{
uiSettings,
http,
savedObjectsManagement,
}}
services={{ contentClient: contentManagement.client, uiSettings }}
/>
</>
)}

View file

@ -19,7 +19,7 @@ export interface PageProps {
export const Page: FC<PageProps> = ({ nextStepPath }) => {
const RESULTS_PER_PAGE = 20;
const { uiSettings, http, savedObjectsManagement } = useMlKibana().services;
const { contentManagement, uiSettings } = useMlKibana().services;
const navigateToPath = useNavigateToPath();
const onObjectSelection = (id: string, type: string) => {
@ -67,14 +67,12 @@ export const Page: FC<PageProps> = ({ nextStepPath }) => {
defaultMessage: 'Data view',
}
),
defaultSearchField: 'name',
},
]}
fixedPageSize={RESULTS_PER_PAGE}
services={{
contentClient: contentManagement.client,
uiSettings,
http,
savedObjectsManagement,
}}
/>
</EuiPageContent>

View file

@ -32,6 +32,7 @@ import type { LicenseManagementUIPluginSetup } from '@kbn/license-management-plu
import type { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/public';
import type { SecurityPluginStart } from '@kbn/security-plugin/public';
import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import type { MapsStartApi, MapsSetupApi } from '@kbn/maps-plugin/public';
import {
@ -73,6 +74,7 @@ export interface MlStartDependencies {
security: SecurityPluginStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
savedSearch: SavedSearchPublicPluginStart;
contentManagement: ContentManagementPublicStart;
}
export interface MlSetupDependencies {
@ -142,6 +144,7 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
cases: pluginsStart.cases,
savedObjectsManagement: pluginsStart.savedObjectsManagement,
savedSearch: pluginsStart.savedSearch,
contentManagement: pluginsStart.contentManagement,
},
params
);

View file

@ -100,6 +100,7 @@
"@kbn/core-notifications-browser-mocks",
"@kbn/unified-field-list",
"@kbn/core-ui-settings-browser",
"@kbn/content-management-plugin",
"@kbn/ml-in-memory-table",
],
}

View file

@ -25,7 +25,8 @@
"unifiedSearch",
"charts",
"savedObjectsFinder",
"savedObjectsManagement"
"savedObjectsManagement",
"contentManagement",
],
"optionalPlugins": [
"security",

View file

@ -25,6 +25,7 @@ import type { Storage } from '@kbn/kibana-utils-plugin/public';
import type { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import { savedSearchPluginMock } from '@kbn/saved-search-plugin/public/mocks';
import { contentManagementMock } from '@kbn/content-management-plugin/public/mocks';
import type { AppDependencies } from '../app_dependencies';
import { MlSharedContext } from './shared_context';
@ -96,6 +97,7 @@ const appDependencies: AppDependencies = {
savedObjectsManagement: {} as jest.Mocked<SavedObjectsManagementPluginStart>,
settings: settingsServiceMock.createStartContract(),
savedSearch: savedSearchPluginMock.createStartContract(),
contentManagement: contentManagementMock.createStartContract(),
};
export const useAppDependencies = () => {

View file

@ -26,6 +26,7 @@ import type { SharePluginStart } from '@kbn/share-plugin/public';
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import type { SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public';
import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import type { Storage } from '@kbn/kibana-utils-plugin/public';
@ -66,6 +67,7 @@ export interface AppDependencies {
usageCollection?: UsageCollectionStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
settings: SettingsStart;
contentManagement: ContentManagementPublicStart;
}
export const useAppDependencies = () => {

View file

@ -52,6 +52,7 @@ export async function mountManagementSection(
fieldFormats,
savedObjectsManagement,
savedSearch,
contentManagement,
} = plugins;
const { docTitle } = chrome;
@ -88,6 +89,7 @@ export async function mountManagementSection(
fieldFormats,
savedObjectsManagement,
savedSearch,
contentManagement,
};
const unmountAppCallback = renderApp(element, appDependencies);

View file

@ -19,7 +19,7 @@ interface SearchSelectionProps {
const fixedPageSize: number = 8;
export const SearchSelection: FC<SearchSelectionProps> = ({ onSearchSelected }) => {
const { uiSettings, http, savedObjectsManagement } = useAppDependencies();
const { contentManagement, uiSettings } = useAppDependencies();
return (
<>
@ -67,15 +67,10 @@ export const SearchSelection: FC<SearchSelectionProps> = ({ onSearchSelected })
defaultMessage: 'Data view',
}
),
defaultSearchField: 'name',
},
]}
fixedPageSize={fixedPageSize}
services={{
uiSettings,
http,
savedObjectsManagement,
}}
services={{ contentClient: contentManagement.client, uiSettings }}
/>
</EuiModalBody>
</>

View file

@ -21,6 +21,7 @@ import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public/plugin';
import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public';
import { registerFeature } from './register_feature';
import { getTransformHealthRuleType } from './alerting';
@ -40,6 +41,7 @@ export interface PluginsDependencies {
triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
fieldFormats: FieldFormatsStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
contentManagement: ContentManagementPublicStart;
}
export class TransformUiPlugin {

View file

@ -66,7 +66,8 @@
"@kbn/ml-date-utils",
"@kbn/saved-search-plugin",
"@kbn/unified-field-list",
"@kbn/ebt-tools"
"@kbn/ebt-tools",
"@kbn/content-management-plugin"
],
"exclude": [
"target/**/*",