mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
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:
parent
add8f130cf
commit
96379a5be3
21 changed files with 4 additions and 647 deletions
|
@ -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"]
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@ export {
|
|||
SavedObjectsManagementColumnServiceStart,
|
||||
SavedObjectsManagementColumn,
|
||||
SavedObjectsManagementRecord,
|
||||
ISavedObjectsManagementServiceRegistry,
|
||||
SavedObjectsManagementServiceRegistryEntry,
|
||||
} from './services';
|
||||
export { ProcessedImportResponse, processImportResponse, FailedImport } from './lib';
|
||||
export { SavedObjectRelation, SavedObjectWithMetadata, SavedObjectMetadata } from './types';
|
||||
|
|
|
@ -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": "[]",
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
|
@ -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: '[]',
|
||||
});
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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[];
|
||||
}
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
};
|
|
@ -16,11 +16,6 @@ export {
|
|||
SavedObjectsManagementColumnServiceStart,
|
||||
SavedObjectsManagementColumnServiceSetup,
|
||||
} from './column_service';
|
||||
export {
|
||||
SavedObjectsManagementServiceRegistry,
|
||||
ISavedObjectsManagementServiceRegistry,
|
||||
SavedObjectsManagementServiceRegistryEntry,
|
||||
} from './service_registry';
|
||||
export {
|
||||
SavedObjectsManagementAction,
|
||||
SavedObjectsManagementColumn,
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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" },
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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": "キャンセル",
|
||||
|
|
|
@ -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 {您的已保存对象有 # 个已共享}}",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue