Decouples saved objects management from legacy saved objects loaders (#113031)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Christiane (Tina) Heiligers 2021-09-27 10:36:05 -07:00 committed by GitHub
parent add8f130cf
commit 96379a5be3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 4 additions and 647 deletions

View file

@ -8,7 +8,7 @@
"server": true,
"ui": true,
"requiredPlugins": ["management", "data"],
"optionalPlugins": ["dashboard", "visualizations", "discover", "home", "savedObjectsTaggingOss", "spaces"],
"optionalPlugins": ["home", "savedObjectsTaggingOss", "spaces"],
"extraPublicDirs": ["public/lib"],
"requiredBundles": ["kibanaReact", "home"]
}

View file

@ -18,8 +18,6 @@ export {
SavedObjectsManagementColumnServiceStart,
SavedObjectsManagementColumn,
SavedObjectsManagementRecord,
ISavedObjectsManagementServiceRegistry,
SavedObjectsManagementServiceRegistryEntry,
} from './services';
export { ProcessedImportResponse, processImportResponse, FailedImport } from './lib';
export { SavedObjectRelation, SavedObjectWithMetadata, SavedObjectMetadata } from './types';

View file

@ -1,178 +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 { SimpleSavedObject, SavedObjectReference } from '../../../../core/public';
import { savedObjectsServiceMock } from '../../../../core/public/mocks';
import { createFieldList } from './create_field_list';
const savedObjectClientMock = savedObjectsServiceMock.createStartContract().client;
const createObject = <T>(
attributes: T,
references: SavedObjectReference[] = []
): SimpleSavedObject<T> =>
new SimpleSavedObject<T>(savedObjectClientMock, {
id: 'id',
type: 'type',
migrationVersion: {},
attributes,
references,
});
describe('createFieldList', () => {
it('generate fields based on the object attributes', () => {
const obj = createObject({
textField: 'some text',
numberField: 12,
boolField: true,
});
expect(createFieldList(obj)).toMatchInlineSnapshot(`
Array [
Object {
"name": "textField",
"type": "text",
"value": "some text",
},
Object {
"name": "numberField",
"type": "number",
"value": 12,
},
Object {
"name": "boolField",
"type": "boolean",
"value": true,
},
Object {
"name": "references",
"type": "array",
"value": "[]",
},
]
`);
});
it('detects json fields', () => {
const obj = createObject({
jsonField: `{"data": "value"}`,
});
expect(createFieldList(obj)).toMatchInlineSnapshot(`
Array [
Object {
"name": "jsonField",
"type": "json",
"value": "{
\\"data\\": \\"value\\"
}",
},
Object {
"name": "references",
"type": "array",
"value": "[]",
},
]
`);
});
it('handles array fields', () => {
const obj = createObject({
someArray: [1, 2, 3],
});
expect(createFieldList(obj)).toMatchInlineSnapshot(`
Array [
Object {
"name": "someArray",
"type": "array",
"value": "[
1,
2,
3
]",
},
Object {
"name": "references",
"type": "array",
"value": "[]",
},
]
`);
});
it(`generates a field for the object's references`, () => {
const obj = createObject(
{
someString: 'foo',
},
[
{ id: 'ref1', type: 'type', name: 'Ref 1' },
{ id: 'ref12', type: 'other-type', name: 'Ref 2' },
]
);
expect(createFieldList(obj)).toMatchInlineSnapshot(`
Array [
Object {
"name": "someString",
"type": "text",
"value": "foo",
},
Object {
"name": "references",
"type": "array",
"value": "[
{
\\"id\\": \\"ref1\\",
\\"type\\": \\"type\\",
\\"name\\": \\"Ref 1\\"
},
{
\\"id\\": \\"ref12\\",
\\"type\\": \\"other-type\\",
\\"name\\": \\"Ref 2\\"
}
]",
},
]
`);
});
it('recursively collect nested fields', () => {
const obj = createObject({
firstLevel: {
firstLevelField: 'foo',
secondLevel: {
secondLevelFieldA: 'A',
secondLevelFieldB: 'B',
},
},
});
expect(createFieldList(obj)).toMatchInlineSnapshot(`
Array [
Object {
"name": "firstLevel.firstLevelField",
"type": "text",
"value": "foo",
},
Object {
"name": "firstLevel.secondLevel.secondLevelFieldA",
"type": "text",
"value": "A",
},
Object {
"name": "firstLevel.secondLevel.secondLevelFieldB",
"type": "text",
"value": "B",
},
Object {
"name": "references",
"type": "array",
"value": "[]",
},
]
`);
});
});

View file

@ -1,128 +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 { forOwn, keyBy, isNumber, isBoolean, isPlainObject, isString } from 'lodash';
import { SimpleSavedObject } from '../../../../core/public';
import { castEsToKbnFieldTypeName } from '../../../data/public';
import { ObjectField } from '../management_section/types';
import { SavedObjectLoader } from '../../../saved_objects/public';
import { SavedObjectWithMetadata } from '../types';
const maxRecursiveIterations = 20;
export function createFieldList(
object: SimpleSavedObject | SavedObjectWithMetadata,
service?: SavedObjectLoader
): ObjectField[] {
let fields = Object.entries(object.attributes as Record<string, any>).reduce(
(objFields, [key, value]) => {
return [...objFields, ...createFields(key, value)];
},
[] as ObjectField[]
);
// Special handling for references which isn't within "attributes"
fields = [...fields, ...createFields('references', object.references)];
if (service && (service as any).Class) {
addFieldsFromClass((service as any).Class, fields);
}
return fields;
}
/**
* Creates a field definition and pushes it to the memo stack. This function
* is designed to be used in conjunction with _.reduce(). If the
* values is plain object it will recurse through all the keys till it hits
* a string, number or an array.
*
* @param {string} key The key of the field
* @param {mixed} value The value of the field
* @param {array} parents The parent keys to the field
* @returns {array}
*/
const createFields = (key: string, value: any, parents: string[] = []): ObjectField[] => {
const path = [...parents, key];
if (path.length > maxRecursiveIterations) {
return [];
}
const field: ObjectField = { type: 'text', name: path.join('.'), value };
if (isString(field.value)) {
try {
field.value = JSON.stringify(JSON.parse(field.value), undefined, 2);
field.type = 'json';
} catch (err) {
field.type = 'text';
}
} else if (isNumber(field.value)) {
field.type = 'number';
} else if (Array.isArray(field.value)) {
field.type = 'array';
field.value = JSON.stringify(field.value, undefined, 2);
} else if (isBoolean(field.value)) {
field.type = 'boolean';
} else if (isPlainObject(field.value)) {
let fields: ObjectField[] = [];
forOwn(field.value, (childValue, childKey) => {
fields = [...fields, ...createFields(childKey as string, childValue, path)];
});
return fields;
}
return [field];
};
const addFieldsFromClass = function (
Class: { mapping: Record<string, string>; searchSource: any },
fields: ObjectField[]
) {
const fieldMap = keyBy(fields, 'name');
forOwn(Class.mapping, (esType, name) => {
if (!name || fieldMap[name]) {
return;
}
const getFieldTypeFromEsType = () => {
switch (castEsToKbnFieldTypeName(esType)) {
case 'string':
return 'text';
case 'number':
return 'number';
case 'boolean':
return 'boolean';
default:
return 'json';
}
};
fields.push({
name,
type: getFieldTypeFromEsType(),
value: undefined,
});
});
if (Class.searchSource && !fieldMap['kibanaSavedObjectMeta.searchSourceJSON']) {
fields.push({
name: 'kibanaSavedObjectMeta.searchSourceJSON',
type: 'json',
value: '{}',
});
}
if (!fieldMap.references) {
fields.push({
name: 'references',
type: 'array',
value: '[]',
});
}
};

View file

@ -1,115 +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 { Capabilities } from '../../../../core/public';
import { canViewInApp } from './in_app_url';
const createCapabilities = (sections: Record<string, any>): Capabilities => {
return {
navLinks: {},
management: {},
catalogue: {},
...sections,
};
};
describe('canViewInApp', () => {
it('should handle saved searches', () => {
let uiCapabilities = createCapabilities({
discover: {
show: true,
},
});
expect(canViewInApp(uiCapabilities, 'search')).toEqual(true);
expect(canViewInApp(uiCapabilities, 'searches')).toEqual(true);
uiCapabilities = createCapabilities({
discover: {
show: false,
},
});
expect(canViewInApp(uiCapabilities, 'search')).toEqual(false);
expect(canViewInApp(uiCapabilities, 'searches')).toEqual(false);
});
it('should handle visualizations', () => {
let uiCapabilities = createCapabilities({
visualize: {
show: true,
},
});
expect(canViewInApp(uiCapabilities, 'visualization')).toEqual(true);
expect(canViewInApp(uiCapabilities, 'visualizations')).toEqual(true);
uiCapabilities = createCapabilities({
visualize: {
show: false,
},
});
expect(canViewInApp(uiCapabilities, 'visualization')).toEqual(false);
expect(canViewInApp(uiCapabilities, 'visualizations')).toEqual(false);
});
it('should handle index patterns', () => {
let uiCapabilities = createCapabilities({
management: {
kibana: {
indexPatterns: true,
},
},
});
expect(canViewInApp(uiCapabilities, 'index-pattern')).toEqual(true);
expect(canViewInApp(uiCapabilities, 'index-patterns')).toEqual(true);
expect(canViewInApp(uiCapabilities, 'indexPatterns')).toEqual(true);
uiCapabilities = createCapabilities({
management: {
kibana: {
indexPatterns: false,
},
},
});
expect(canViewInApp(uiCapabilities, 'index-pattern')).toEqual(false);
expect(canViewInApp(uiCapabilities, 'index-patterns')).toEqual(false);
expect(canViewInApp(uiCapabilities, 'indexPatterns')).toEqual(false);
});
it('should handle dashboards', () => {
let uiCapabilities = createCapabilities({
dashboard: {
show: true,
},
});
expect(canViewInApp(uiCapabilities, 'dashboard')).toEqual(true);
expect(canViewInApp(uiCapabilities, 'dashboards')).toEqual(true);
uiCapabilities = createCapabilities({
dashboard: {
show: false,
},
});
expect(canViewInApp(uiCapabilities, 'dashboard')).toEqual(false);
expect(canViewInApp(uiCapabilities, 'dashboards')).toEqual(false);
});
it('should have a default case', () => {
let uiCapabilities = createCapabilities({
foo: {
show: true,
},
});
expect(canViewInApp(uiCapabilities, 'foo')).toEqual(true);
uiCapabilities = createCapabilities({
foo: {
show: false,
},
});
expect(canViewInApp(uiCapabilities, 'foo')).toEqual(false);
});
});

View file

@ -1,29 +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 { Capabilities } from 'src/core/public';
export function canViewInApp(uiCapabilities: Capabilities, type: string): boolean {
switch (type) {
case 'search':
case 'searches':
return uiCapabilities.discover.show as boolean;
case 'visualization':
case 'visualizations':
return uiCapabilities.visualize.show as boolean;
case 'index-pattern':
case 'index-patterns':
case 'indexPatterns':
return uiCapabilities.management.kibana.indexPatterns as boolean;
case 'dashboard':
case 'dashboards':
return uiCapabilities.dashboard.show as boolean;
default:
return uiCapabilities[type].show as boolean;
}
}

View file

@ -8,7 +8,6 @@
export { fetchExportByTypeAndSearch } from './fetch_export_by_type_and_search';
export { fetchExportObjects } from './fetch_export_objects';
export { canViewInApp } from './in_app_url';
export { getRelationships } from './get_relationships';
export { getSavedObjectCounts } from './get_saved_object_counts';
export { getSavedObjectLabel } from './get_saved_object_label';
@ -24,6 +23,5 @@ export { getDefaultTitle } from './get_default_title';
export { findObjects } from './find_objects';
export { bulkGetObjects } from './bulk_get_objects';
export { extractExportDetails, SavedObjectsExportResultDetails } from './extract_export_details';
export { createFieldList } from './create_field_list';
export { getAllowedTypes } from './get_allowed_types';
export { getTagFindReferences } from './get_tag_references';

View file

@ -15,12 +15,10 @@ import { EuiLoadingSpinner } from '@elastic/eui';
import { CoreSetup } from 'src/core/public';
import { ManagementAppMountParams } from '../../../management/public';
import { StartDependencies, SavedObjectsManagementPluginStart } from '../plugin';
import { ISavedObjectsManagementServiceRegistry } from '../services';
import { getAllowedTypes } from './../lib';
interface MountParams {
core: CoreSetup<StartDependencies, SavedObjectsManagementPluginStart>;
serviceRegistry: ISavedObjectsManagementServiceRegistry;
mountParams: ManagementAppMountParams;
}
@ -32,11 +30,7 @@ const title = i18n.translate('savedObjectsManagement.objects.savedObjectsTitle',
const SavedObjectsEditionPage = lazy(() => import('./saved_objects_edition_page'));
const SavedObjectsTablePage = lazy(() => import('./saved_objects_table_page'));
export const mountManagementSection = async ({
core,
mountParams,
serviceRegistry,
}: MountParams) => {
export const mountManagementSection = async ({ core, mountParams }: MountParams) => {
const [coreStart, { data, savedObjectsTaggingOss, spaces: spacesApi }, pluginStart] =
await core.getStartServices();
const { element, history, setBreadcrumbs } = mountParams;
@ -81,7 +75,6 @@ export const mountManagementSection = async ({
taggingApi={savedObjectsTaggingOss?.getTaggingApi()}
spacesApi={spacesApi}
dataStart={data}
serviceRegistry={serviceRegistry}
actionRegistry={pluginStart.actions}
columnRegistry={pluginStart.columns}
allowedTypes={allowedObjectTypes}

View file

@ -85,7 +85,6 @@ exports[`Relationships should render dashboards normally 1`] = `
Object {
"id": "1",
"meta": Object {
"editUrl": "/management/kibana/objects/savedVisualizations/1",
"icon": "visualizeApp",
"inAppUrl": Object {
"path": "/app/visualize#/edit/1",
@ -99,7 +98,6 @@ exports[`Relationships should render dashboards normally 1`] = `
Object {
"id": "2",
"meta": Object {
"editUrl": "/management/kibana/objects/savedVisualizations/2",
"icon": "visualizeApp",
"inAppUrl": Object {
"path": "/app/visualize#/edit/2",
@ -288,7 +286,6 @@ exports[`Relationships should render index patterns normally 1`] = `
Object {
"id": "1",
"meta": Object {
"editUrl": "/management/kibana/objects/savedSearches/1",
"icon": "search",
"inAppUrl": Object {
"path": "/app/discover#//1",
@ -302,7 +299,6 @@ exports[`Relationships should render index patterns normally 1`] = `
Object {
"id": "2",
"meta": Object {
"editUrl": "/management/kibana/objects/savedVisualizations/2",
"icon": "visualizeApp",
"inAppUrl": Object {
"path": "/app/visualize#/edit/2",
@ -645,7 +641,6 @@ exports[`Relationships should render searches normally 1`] = `
Object {
"id": "2",
"meta": Object {
"editUrl": "/management/kibana/objects/savedVisualizations/2",
"icon": "visualizeApp",
"inAppUrl": Object {
"path": "/app/visualize#/edit/2",
@ -794,7 +789,6 @@ exports[`Relationships should render visualizations normally 1`] = `
Object {
"id": "1",
"meta": Object {
"editUrl": "/management/kibana/objects/savedDashboards/1",
"icon": "dashboardApp",
"inAppUrl": Object {
"path": "/app/kibana#/dashboard/1",
@ -808,7 +802,6 @@ exports[`Relationships should render visualizations normally 1`] = `
Object {
"id": "2",
"meta": Object {
"editUrl": "/management/kibana/objects/savedDashboards/2",
"icon": "dashboardApp",
"inAppUrl": Object {
"path": "/app/kibana#/dashboard/2",

View file

@ -32,7 +32,6 @@ describe('Relationships', () => {
id: '1',
relationship: 'parent',
meta: {
editUrl: '/management/kibana/objects/savedSearches/1',
icon: 'search',
inAppUrl: {
path: '/app/discover#//1',
@ -46,7 +45,6 @@ describe('Relationships', () => {
id: '2',
relationship: 'parent',
meta: {
editUrl: '/management/kibana/objects/savedVisualizations/2',
icon: 'visualizeApp',
inAppUrl: {
path: '/app/visualize#/edit/2',
@ -116,7 +114,6 @@ describe('Relationships', () => {
id: '2',
relationship: 'parent',
meta: {
editUrl: '/management/kibana/objects/savedVisualizations/2',
icon: 'visualizeApp',
inAppUrl: {
path: '/app/visualize#/edit/2',
@ -136,7 +133,6 @@ describe('Relationships', () => {
meta: {
title: 'MySearch',
icon: 'search',
editUrl: '/management/kibana/objects/savedSearches/1',
inAppUrl: {
path: '/discover/1',
uiCapabilitiesPath: 'discover.show',
@ -172,7 +168,6 @@ describe('Relationships', () => {
id: '1',
relationship: 'parent',
meta: {
editUrl: '/management/kibana/objects/savedDashboards/1',
icon: 'dashboardApp',
inAppUrl: {
path: '/app/kibana#/dashboard/1',
@ -186,7 +181,6 @@ describe('Relationships', () => {
id: '2',
relationship: 'parent',
meta: {
editUrl: '/management/kibana/objects/savedDashboards/2',
icon: 'dashboardApp',
inAppUrl: {
path: '/app/kibana#/dashboard/2',
@ -206,7 +200,6 @@ describe('Relationships', () => {
meta: {
title: 'MyViz',
icon: 'visualizeApp',
editUrl: '/management/kibana/objects/savedVisualizations/1',
inAppUrl: {
path: '/edit/1',
uiCapabilitiesPath: 'visualize.show',
@ -242,7 +235,6 @@ describe('Relationships', () => {
id: '1',
relationship: 'child',
meta: {
editUrl: '/management/kibana/objects/savedVisualizations/1',
icon: 'visualizeApp',
inAppUrl: {
path: '/app/visualize#/edit/1',
@ -256,7 +248,6 @@ describe('Relationships', () => {
id: '2',
relationship: 'child',
meta: {
editUrl: '/management/kibana/objects/savedVisualizations/2',
icon: 'visualizeApp',
inAppUrl: {
path: '/app/visualize#/edit/2',
@ -276,7 +267,6 @@ describe('Relationships', () => {
meta: {
title: 'MyDashboard',
icon: 'dashboardApp',
editUrl: '/management/kibana/objects/savedDashboards/1',
inAppUrl: {
path: '/dashboard/1',
uiCapabilitiesPath: 'dashboard.show',
@ -316,7 +306,6 @@ describe('Relationships', () => {
meta: {
title: 'MyDashboard',
icon: 'dashboardApp',
editUrl: '/management/kibana/objects/savedDashboards/1',
inAppUrl: {
path: '/dashboard/1',
uiCapabilitiesPath: 'dashboard.show',

View file

@ -17,7 +17,6 @@ import type { SpacesApi, SpacesContextProps } from '../../../../../x-pack/plugin
import { DataPublicPluginStart } from '../../../data/public';
import { SavedObjectsTaggingApi } from '../../../saved_objects_tagging_oss/public';
import {
ISavedObjectsManagementServiceRegistry,
SavedObjectsManagementActionServiceStart,
SavedObjectsManagementColumnServiceStart,
} from '../services';
@ -31,7 +30,6 @@ const SavedObjectsTablePage = ({
taggingApi,
spacesApi,
allowedTypes,
serviceRegistry,
actionRegistry,
columnRegistry,
setBreadcrumbs,
@ -41,7 +39,6 @@ const SavedObjectsTablePage = ({
taggingApi?: SavedObjectsTaggingApi;
spacesApi?: SpacesApi;
allowedTypes: string[];
serviceRegistry: ISavedObjectsManagementServiceRegistry;
actionRegistry: SavedObjectsManagementActionServiceStart;
columnRegistry: SavedObjectsManagementColumnServiceStart;
setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void;

View file

@ -1,27 +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 { SavedObjectReference } from '../../../../core/types';
export interface ObjectField {
type: FieldType;
name: string;
value: any;
}
export type FieldType = 'text' | 'number' | 'boolean' | 'array' | 'json';
export interface FieldState {
value?: any;
invalid?: boolean;
}
export interface SubmittedFormData {
attributes: any;
references: SavedObjectReference[];
}

View file

@ -8,14 +8,12 @@
import { actionServiceMock } from './services/action_service.mock';
import { columnServiceMock } from './services/column_service.mock';
import { serviceRegistryMock } from './services/service_registry.mock';
import { SavedObjectsManagementPluginSetup, SavedObjectsManagementPluginStart } from './plugin';
const createSetupContractMock = (): jest.Mocked<SavedObjectsManagementPluginSetup> => {
const mock = {
actions: actionServiceMock.createSetup(),
columns: columnServiceMock.createSetup(),
serviceRegistry: serviceRegistryMock.create(),
};
return mock;
};
@ -29,7 +27,6 @@ const createStartContractMock = (): jest.Mocked<SavedObjectsManagementPluginStar
};
export const savedObjectsManagementPluginMock = {
createServiceRegistry: serviceRegistryMock.create,
createSetupContract: createSetupContractMock,
createStartContract: createStartContractMock,
};

View file

@ -11,10 +11,7 @@ import { CoreSetup, CoreStart, Plugin } from 'src/core/public';
import type { SpacesPluginStart } from '../../../../x-pack/plugins/spaces/public';
import { ManagementSetup } from '../../management/public';
import { DataPublicPluginStart } from '../../data/public';
import { DashboardStart } from '../../dashboard/public';
import { DiscoverStart } from '../../discover/public';
import { HomePublicPluginSetup, FeatureCatalogueCategory } from '../../home/public';
import { VisualizationsStart } from '../../visualizations/public';
import { SavedObjectTaggingOssPluginStart } from '../../saved_objects_tagging_oss/public';
import {
SavedObjectsManagementActionService,
@ -23,15 +20,11 @@ import {
SavedObjectsManagementColumnService,
SavedObjectsManagementColumnServiceSetup,
SavedObjectsManagementColumnServiceStart,
SavedObjectsManagementServiceRegistry,
ISavedObjectsManagementServiceRegistry,
} from './services';
import { registerServices } from './register_services';
export interface SavedObjectsManagementPluginSetup {
actions: SavedObjectsManagementActionServiceSetup;
columns: SavedObjectsManagementColumnServiceSetup;
serviceRegistry: ISavedObjectsManagementServiceRegistry;
}
export interface SavedObjectsManagementPluginStart {
@ -46,9 +39,6 @@ export interface SetupDependencies {
export interface StartDependencies {
data: DataPublicPluginStart;
dashboard?: DashboardStart;
visualizations?: VisualizationsStart;
discover?: DiscoverStart;
savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart;
spaces?: SpacesPluginStart;
}
@ -64,7 +54,6 @@ export class SavedObjectsManagementPlugin
{
private actionService = new SavedObjectsManagementActionService();
private columnService = new SavedObjectsManagementColumnService();
private serviceRegistry = new SavedObjectsManagementServiceRegistry();
public setup(
core: CoreSetup<StartDependencies, SavedObjectsManagementPluginStart>,
@ -80,8 +69,7 @@ export class SavedObjectsManagementPlugin
defaultMessage: 'Saved Objects',
}),
description: i18n.translate('savedObjectsManagement.objects.savedObjectsDescription', {
defaultMessage:
'Import, export, and manage your saved searches, visualizations, and dashboards.',
defaultMessage: 'Import, export, and manage your saved objects.',
}),
icon: 'savedObjectsApp',
path: '/app/management/kibana/objects',
@ -101,19 +89,14 @@ export class SavedObjectsManagementPlugin
const { mountManagementSection } = await import('./management_section');
return mountManagementSection({
core,
serviceRegistry: this.serviceRegistry,
mountParams,
});
},
});
// depends on `getStartServices`, should not be awaited
registerServices(this.serviceRegistry, core.getStartServices);
return {
actions: actionSetup,
columns: columnSetup,
serviceRegistry: this.serviceRegistry,
};
}

View file

@ -1,42 +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 { StartServicesAccessor } from '../../../core/public';
import { SavedObjectsManagementPluginStart, StartDependencies } from './plugin';
import { ISavedObjectsManagementServiceRegistry } from './services';
export const registerServices = async (
registry: ISavedObjectsManagementServiceRegistry,
getStartServices: StartServicesAccessor<StartDependencies, SavedObjectsManagementPluginStart>
) => {
const [, { dashboard, visualizations, discover }] = await getStartServices();
if (dashboard) {
registry.register({
id: 'savedDashboards',
title: 'dashboards',
service: dashboard.getSavedDashboardLoader(),
});
}
if (visualizations) {
registry.register({
id: 'savedVisualizations',
title: 'visualizations',
service: visualizations.savedVisualizationsLoader,
});
}
if (discover) {
registry.register({
id: 'savedSearches',
title: 'searches',
service: discover.savedSearchLoader,
});
}
};

View file

@ -16,11 +16,6 @@ export {
SavedObjectsManagementColumnServiceStart,
SavedObjectsManagementColumnServiceSetup,
} from './column_service';
export {
SavedObjectsManagementServiceRegistry,
ISavedObjectsManagementServiceRegistry,
SavedObjectsManagementServiceRegistryEntry,
} from './service_registry';
export {
SavedObjectsManagementAction,
SavedObjectsManagementColumn,

View file

@ -1,25 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 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 { ISavedObjectsManagementServiceRegistry } from './service_registry';
const createRegistryMock = (): jest.Mocked<ISavedObjectsManagementServiceRegistry> => {
const mock = {
register: jest.fn(),
all: jest.fn(),
get: jest.fn(),
};
mock.all.mockReturnValue([]);
return mock;
};
export const serviceRegistryMock = {
create: createRegistryMock,
};

View file

@ -1,38 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 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 type { PublicMethodsOf } from '@kbn/utility-types';
import { SavedObjectLoader } from '../../../saved_objects/public';
export interface SavedObjectsManagementServiceRegistryEntry {
id: string;
service: SavedObjectLoader;
title: string;
}
export type ISavedObjectsManagementServiceRegistry =
PublicMethodsOf<SavedObjectsManagementServiceRegistry>;
export class SavedObjectsManagementServiceRegistry {
private readonly registry = new Map<string, SavedObjectsManagementServiceRegistryEntry>();
public register(entry: SavedObjectsManagementServiceRegistryEntry) {
if (this.registry.has(entry.id)) {
throw new Error('');
}
this.registry.set(entry.id, entry);
}
public all(): SavedObjectsManagementServiceRegistryEntry[] {
return [...this.registry.values()];
}
public get(id: string): SavedObjectsManagementServiceRegistryEntry | undefined {
return this.registry.get(id);
}
}

View file

@ -13,13 +13,11 @@
],
"references": [
{ "path": "../../core/tsconfig.json" },
{ "path": "../dashboard/tsconfig.json" },
{ "path": "../data/tsconfig.json" },
{ "path": "../discover/tsconfig.json" },
{ "path": "../home/tsconfig.json" },
{ "path": "../kibana_react/tsconfig.json" },
{ "path": "../management/tsconfig.json" },
{ "path": "../visualizations/tsconfig.json" },
{ "path": "../saved_objects_tagging_oss/tsconfig.json" },
{ "path": "../../../x-pack/plugins/spaces/tsconfig.json" },
]
}

View file

@ -4382,7 +4382,6 @@
"savedObjectsManagement.importSummary.overwrittenOutcomeLabel": "上書き",
"savedObjectsManagement.importSummary.warnings.defaultButtonLabel": "Go",
"savedObjectsManagement.managementSectionLabel": "保存されたオブジェクト",
"savedObjectsManagement.objects.savedObjectsDescription": "保存された検索、ビジュアライゼーション、ダッシュボードのインポート、エクスポート、管理を行います。",
"savedObjectsManagement.objects.savedObjectsTitle": "保存されたオブジェクト",
"savedObjectsManagement.objectsTable.deleteConfirmModal.sharedObjectsCallout.content": "共有オブジェクトは属しているすべてのスペースから削除されます。",
"savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel": "キャンセル",

View file

@ -4423,7 +4423,6 @@
"savedObjectsManagement.importSummary.overwrittenOutcomeLabel": "已覆盖",
"savedObjectsManagement.importSummary.warnings.defaultButtonLabel": "执行",
"savedObjectsManagement.managementSectionLabel": "已保存对象",
"savedObjectsManagement.objects.savedObjectsDescription": "导入、导出和管理您的已保存搜索、可视化和仪表板。",
"savedObjectsManagement.objects.savedObjectsTitle": "已保存对象",
"savedObjectsManagement.objectsTable.deleteConfirmModal.sharedObjectsCallout.content": "共享对象已从其所在的各个工作区中移除。",
"savedObjectsManagement.objectsTable.deleteConfirmModal.sharedObjectsCallout.title": "{sharedObjectsCount, plural, one {# 个已保存对象已共享} other {您的已保存对象有 # 个已共享}}",