From 8aec4c1171f41b5254ce4b9e29316403312b7ec0 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Mon, 27 Sep 2021 10:14:05 +0200 Subject: [PATCH 1/6] add `SavedObjectType.management.displayName` --- src/core/server/saved_objects/types.ts | 4 +++ .../saved_objects_management/common/index.ts | 1 + .../saved_objects_management/common/types.ts | 11 +++++-- .../public/lib/get_allowed_types.ts | 7 +++-- .../management_section/mount_section.tsx | 9 +++--- .../objects_table/components/flyout.tsx | 1 - .../objects_table/saved_objects_table.tsx | 29 ++++++++++++------- .../saved_objects_table_page.tsx | 3 +- .../server/routes/get_allowed_types.ts | 14 +++++++-- 9 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index b2a6be38bb526..7e38a52bee0ca 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -356,6 +356,10 @@ export interface SavedObjectsTypeManagementDefinition { * Is the type importable or exportable. Defaults to `false`. */ importableAndExportable?: boolean; + /** + * When specified, will be used instead of the type's name in SO management section's labels. + */ + displayName?: string; /** * When set to false, the type will not be listed or searchable in the SO management section. * Main usage of setting this property to false for a type is when objects from the type should diff --git a/src/plugins/saved_objects_management/common/index.ts b/src/plugins/saved_objects_management/common/index.ts index efabdace329c3..bc4631d2c8e61 100644 --- a/src/plugins/saved_objects_management/common/index.ts +++ b/src/plugins/saved_objects_management/common/index.ts @@ -13,4 +13,5 @@ export type { SavedObjectRelationKind, SavedObjectInvalidRelation, SavedObjectGetRelationshipsResponse, + SavedObjectManagementTypeInfo, } from './types'; diff --git a/src/plugins/saved_objects_management/common/types.ts b/src/plugins/saved_objects_management/common/types.ts index 7899cd0938ad3..cb771a2aa0ab6 100644 --- a/src/plugins/saved_objects_management/common/types.ts +++ b/src/plugins/saved_objects_management/common/types.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import { SavedObject } from 'src/core/types'; -import { SavedObjectsNamespaceType } from 'src/core/public'; +import type { SavedObject } from 'src/core/types'; +import type { SavedObjectsNamespaceType } from 'src/core/public'; /** * The metadata injected into a {@link SavedObject | saved object} when returning @@ -52,3 +52,10 @@ export interface SavedObjectGetRelationshipsResponse { relations: SavedObjectRelation[]; invalidRelations: SavedObjectInvalidRelation[]; } + +export interface SavedObjectManagementTypeInfo { + name: string; + namespaceType: SavedObjectsNamespaceType; + hidden: boolean; + displayName: string; +} diff --git a/src/plugins/saved_objects_management/public/lib/get_allowed_types.ts b/src/plugins/saved_objects_management/public/lib/get_allowed_types.ts index e2cf7518c54e9..b2465e09a3888 100644 --- a/src/plugins/saved_objects_management/public/lib/get_allowed_types.ts +++ b/src/plugins/saved_objects_management/public/lib/get_allowed_types.ts @@ -6,13 +6,14 @@ * Side Public License, v 1. */ -import { HttpStart } from 'src/core/public'; +import type { HttpStart } from 'src/core/public'; +import type { SavedObjectManagementTypeInfo } from '../../common/types'; interface GetAllowedTypesResponse { - types: string[]; + types: SavedObjectManagementTypeInfo[]; } -export async function getAllowedTypes(http: HttpStart) { +export async function getAllowedTypes(http: HttpStart): Promise { const response = await http.get( '/api/kibana/management/saved_objects/_allowed_types' ); diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx index aa7797fbc95b5..3bbb95d408c01 100644 --- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -14,6 +14,7 @@ import { i18n } from '@kbn/i18n'; import { EuiLoadingSpinner } from '@elastic/eui'; import { CoreSetup } from 'src/core/public'; import { ManagementAppMountParams } from '../../../management/public'; +import type { SavedObjectManagementTypeInfo } from '../../common/types'; import { StartDependencies, SavedObjectsManagementPluginStart } from '../plugin'; import { ISavedObjectsManagementServiceRegistry } from '../services'; import { getAllowedTypes } from './../lib'; @@ -24,7 +25,7 @@ interface MountParams { mountParams: ManagementAppMountParams; } -let allowedObjectTypes: string[] | undefined; +let allowedObjectTypes: SavedObjectManagementTypeInfo[] | undefined; const title = i18n.translate('savedObjectsManagement.objects.savedObjectsTitle', { defaultMessage: 'Saved Objects', @@ -39,15 +40,15 @@ export const mountManagementSection = async ({ }: MountParams) => { const [coreStart, { data, savedObjectsTaggingOss, spaces: spacesApi }, pluginStart] = await core.getStartServices(); + const { capabilities } = coreStart.application; const { element, history, setBreadcrumbs } = mountParams; - if (allowedObjectTypes === undefined) { + + if (!allowedObjectTypes) { allowedObjectTypes = await getAllowedTypes(coreStart.http); } coreStart.chrome.docTitle.change(title); - const capabilities = coreStart.application.capabilities; - const RedirectToHomeIfUnauthorized: React.FunctionComponent = ({ children }) => { const allowed = capabilities?.management?.kibana?.objects ?? false; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx index 607b3aeeac275..e458b4cca430a 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx @@ -52,7 +52,6 @@ const CREATE_NEW_COPIES_DEFAULT = false; const OVERWRITE_ALL_DEFAULT = true; export interface FlyoutProps { - allowedTypes: string[]; close: () => void; done: () => void; newIndexPatternUrl: string; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 5001b52e819c2..ee46614e86f3b 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -23,6 +23,7 @@ import { import { RedirectAppLinks } from '../../../../kibana_react/public'; import { SavedObjectsTaggingApi } from '../../../../saved_objects_tagging_oss/public'; import { IndexPatternsContract } from '../../../../data/public'; +import type { SavedObjectManagementTypeInfo } from '../../../common/types'; import { parseQuery, getSavedObjectCounts, @@ -56,7 +57,7 @@ interface ExportAllOption { } export interface SavedObjectsTableProps { - allowedTypes: string[]; + allowedTypes: SavedObjectManagementTypeInfo[]; actionRegistry: SavedObjectsManagementActionServiceStart; columnRegistry: SavedObjectsManagementColumnServiceStart; savedObjectsClient: SavedObjectsClientContract; @@ -102,6 +103,7 @@ const unableFindSavedObjectNotificationMessage = i18n.translate( 'savedObjectsManagement.objectsTable.unableFindSavedObjectNotificationMessage', { defaultMessage: 'Unable to find saved object' } ); + export class SavedObjectsTable extends Component { private _isMounted = false; @@ -114,7 +116,7 @@ export class SavedObjectsTable extends Component { - typeToCountMap[type] = 0; + typeToCountMap[type.name] = 0; return typeToCountMap; }, {} as Record), activeQuery: props.initialQuery ?? Query.parse(''), @@ -146,9 +148,11 @@ export class SavedObjectsTable extends Component { - const { allowedTypes, taggingApi } = this.props; + const { taggingApi } = this.props; const { queryText, visibleTypes, selectedTags } = parseQuery(this.state.activeQuery); + const allowedTypes = this.props.allowedTypes.map((type) => type.name); + const selectedTypes = allowedTypes.filter( (type) => !visibleTypes || visibleTypes.includes(type) ); @@ -207,6 +211,11 @@ export class SavedObjectsTable extends Component type.name) + .filter((type) => !visibleTypes || visibleTypes.includes(type)); + // "searchFields" is missing from the "findOptions" but gets injected via the API. // The API extracts the fields from each uiExports.savedObjectsManagement "defaultSearchField" attribute const findOptions: SavedObjectsFindOptions = { @@ -214,7 +223,7 @@ export class SavedObjectsTable extends Component !visibleTypes || visibleTypes.includes(type)), + type: searchTypes, }; if (findOptions.type.length > 1) { findOptions.sortField = 'type'; @@ -520,8 +529,9 @@ export class SavedObjectsTable extends Component { - const { allowedTypes, http } = this.props; - return await getRelationships(http, type, id, allowedTypes); + const { http } = this.props; + const allowedTypeNames = this.props.allowedTypes.map((t) => t.name); + return await getRelationships(http, type, id, allowedTypeNames); }; renderFlyout() { @@ -540,7 +550,6 @@ export class SavedObjectsTable extends Component @@ -638,9 +647,9 @@ export class SavedObjectsTable extends Component ({ - value: type, - name: type, - view: `${type} (${savedObjectCounts[type] || 0})`, + value: type.name, + name: type.name, + view: `${type.displayName} (${savedObjectCounts[type.name] || 0})`, })); return ( diff --git a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx index dccf33efc5317..aed9a5196f341 100644 --- a/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx +++ b/src/plugins/saved_objects_management/public/management_section/saved_objects_table_page.tsx @@ -16,6 +16,7 @@ import { CoreStart, ChromeBreadcrumb } from 'src/core/public'; import type { SpacesApi, SpacesContextProps } from '../../../../../x-pack/plugins/spaces/public'; import { DataPublicPluginStart } from '../../../data/public'; import { SavedObjectsTaggingApi } from '../../../saved_objects_tagging_oss/public'; +import type { SavedObjectManagementTypeInfo } from '../../common/types'; import { ISavedObjectsManagementServiceRegistry, SavedObjectsManagementActionServiceStart, @@ -40,7 +41,7 @@ const SavedObjectsTablePage = ({ dataStart: DataPublicPluginStart; taggingApi?: SavedObjectsTaggingApi; spacesApi?: SpacesApi; - allowedTypes: string[]; + allowedTypes: SavedObjectManagementTypeInfo[]; serviceRegistry: ISavedObjectsManagementServiceRegistry; actionRegistry: SavedObjectsManagementActionServiceStart; columnRegistry: SavedObjectsManagementColumnServiceStart; diff --git a/src/plugins/saved_objects_management/server/routes/get_allowed_types.ts b/src/plugins/saved_objects_management/server/routes/get_allowed_types.ts index ce371ea590230..65465fbfa67d8 100644 --- a/src/plugins/saved_objects_management/server/routes/get_allowed_types.ts +++ b/src/plugins/saved_objects_management/server/routes/get_allowed_types.ts @@ -6,7 +6,17 @@ * Side Public License, v 1. */ -import { IRouter } from 'src/core/server'; +import { IRouter, SavedObjectsType } from 'src/core/server'; +import { SavedObjectManagementTypeInfo } from '../../common'; + +const convertType = (sot: SavedObjectsType): SavedObjectManagementTypeInfo => { + return { + name: sot.name, + namespaceType: sot.namespaceType, + hidden: sot.hidden, + displayName: sot.management?.displayName ?? sot.name, + }; +}; export const registerGetAllowedTypesRoute = (router: IRouter) => { router.get( @@ -18,7 +28,7 @@ export const registerGetAllowedTypesRoute = (router: IRouter) => { const allowedTypes = context.core.savedObjects.typeRegistry .getImportableAndExportableTypes() .filter((type) => type.management!.visibleInManagement ?? true) - .map((type) => type.name); + .map(convertType); return res.ok({ body: { From 472833fb2c0c84f46dd028e14ea8e5211063c33d Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Mon, 27 Sep 2021 11:51:28 +0200 Subject: [PATCH 2/6] fix unit tests --- .../objects_table/components/flyout.test.tsx | 1 - .../objects_table/saved_objects_table.test.tsx | 14 +++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx index acdab1db40370..8e6b5eb82bd84 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx @@ -47,7 +47,6 @@ describe('Flyout', () => { ]), } as any, http, - allowedTypes: ['search', 'index-pattern', 'visualization'], search, basePath, }; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index 025a7a320327f..9ef28e1121965 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -28,6 +28,7 @@ import { applicationServiceMock, } from '../../../../../core/public/mocks'; import { dataPluginMock } from '../../../../data/public/mocks'; +import type { SavedObjectManagementTypeInfo } from '../../../common/types'; import { actionServiceMock } from '../../services/action_service.mock'; import { columnServiceMock } from '../../services/column_service.mock'; import { @@ -38,7 +39,14 @@ import { import { Flyout, Relationships } from './components'; import { SavedObjectWithMetadata } from '../../types'; -const allowedTypes = ['index-pattern', 'visualization', 'dashboard', 'search']; +const convertType = (type: string): SavedObjectManagementTypeInfo => ({ + name: type, + displayName: type, + hidden: false, + namespaceType: 'single', +}); + +const allowedTypes = ['index-pattern', 'visualization', 'dashboard', 'search'].map(convertType); const allSavedObjects = [ { @@ -377,7 +385,7 @@ describe('SavedObjectsTable', () => { expect(fetchExportByTypeAndSearchMock).toHaveBeenCalledWith({ http, - types: allowedTypes, + types: allowedTypes.map((type) => type.name), includeReferencesDeep: true, }); expect(saveAsMock).toHaveBeenCalledWith(blob, 'export.ndjson'); @@ -406,7 +414,7 @@ describe('SavedObjectsTable', () => { expect(fetchExportByTypeAndSearchMock).toHaveBeenCalledWith({ http, - types: allowedTypes, + types: allowedTypes.map((type) => type.name), search: 'test*', includeReferencesDeep: true, }); From 83fe7872fa25ec3649bb423beca59030dde67e8e Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Mon, 27 Sep 2021 12:14:30 +0200 Subject: [PATCH 3/6] add FTR test --- .../server/plugin.ts | 18 ++++++++ .../visible_in_management.ts | 45 ++++++++++++++----- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts b/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts index 0cb6a5ba8eb5d..0fd5c467d081b 100644 --- a/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts +++ b/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts @@ -212,6 +212,24 @@ export class SavedObjectExportTransformsPlugin implements Plugin { visibleInManagement: true, }, }); + + // example of a SO type specifying a display name + savedObjects.registerType<{ enabled: boolean; title: string }>({ + name: 'test-with-display-name', + hidden: false, + namespaceType: 'single', + mappings: { + properties: { + title: { type: 'text' }, + enabled: { type: 'boolean' }, + }, + }, + management: { + defaultSearchField: 'title', + importableAndExportable: true, + displayName: 'my display name', + }, + }); } public start() {} diff --git a/test/plugin_functional/test_suites/saved_objects_management/visible_in_management.ts b/test/plugin_functional/test_suites/saved_objects_management/visible_in_management.ts index dd43ba80a8e8e..e6d8aa4189f28 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/visible_in_management.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/visible_in_management.ts @@ -11,6 +11,7 @@ import expect from '@kbn/expect'; import type { Response } from 'supertest'; import type { PluginFunctionalProviderContext } from '../../services'; import { SavedObject } from '../../../../src/core/types'; +import type { SavedObjectManagementTypeInfo } from '../../../../src/plugins/saved_objects_management/common/types'; function parseNdJson(input: string): Array> { return input.split('\n').map((str) => JSON.parse(str)); @@ -97,17 +98,39 @@ export default function ({ getService }: PluginFunctionalProviderContext) { }); describe('savedObjects management APIS', () => { - it('GET /api/kibana/management/saved_objects/_allowed_types should only return types that are `visibleInManagement: true`', async () => - await supertest - .get('/api/kibana/management/saved_objects/_allowed_types') - .set('kbn-xsrf', 'true') - .expect(200) - .then((response: Response) => { - const { types } = response.body; - expect(types.includes('test-is-exportable')).to.eql(true); - expect(types.includes('test-visible-in-management')).to.eql(true); - expect(types.includes('test-not-visible-in-management')).to.eql(false); - })); + describe('GET /api/kibana/management/saved_objects/_allowed_types', () => { + let types: SavedObjectManagementTypeInfo[]; + + before(async () => { + await supertest + .get('/api/kibana/management/saved_objects/_allowed_types') + .set('kbn-xsrf', 'true') + .expect(200) + .then((response: Response) => { + types = response.body.types as SavedObjectManagementTypeInfo[]; + }); + }); + + it('should only return types that are `visibleInManagement: true`', () => { + const typeNames = types.map((type) => type.name); + + expect(typeNames.includes('test-is-exportable')).to.eql(true); + expect(typeNames.includes('test-visible-in-management')).to.eql(true); + expect(typeNames.includes('test-not-visible-in-management')).to.eql(false); + }); + + it('should return displayName for types specifying it', () => { + const typeWithDisplayName = types.find((type) => type.name === 'test-with-display-name'); + expect(typeWithDisplayName !== undefined).to.eql(true); + expect(typeWithDisplayName!.displayName).to.eql('my display name'); + + const typeWithoutDisplayName = types.find( + (type) => type.name === 'test-visible-in-management' + ); + expect(typeWithoutDisplayName !== undefined).to.eql(true); + expect(typeWithoutDisplayName!.displayName).to.eql('test-visible-in-management'); + }); + }); }); }); } From 5ba431ba329c67e151fdf6f169289189fc3c86b3 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Mon, 27 Sep 2021 12:23:16 +0200 Subject: [PATCH 4/6] update generated doc --- ...edobjectstypemanagementdefinition.displayname.md | 13 +++++++++++++ ...e-server.savedobjectstypemanagementdefinition.md | 1 + src/core/server/server.api.md | 1 + 3 files changed, 15 insertions(+) create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.displayname.md diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.displayname.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.displayname.md new file mode 100644 index 0000000000000..71325318a68e6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.displayname.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsTypeManagementDefinition](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) > [displayName](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.displayname.md) + +## SavedObjectsTypeManagementDefinition.displayName property + +When specified, will be used instead of the type's name in SO management section's labels. + +Signature: + +```typescript +displayName?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md index 2c3dd9f3f8434..057eb6284bf9e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md @@ -17,6 +17,7 @@ export interface SavedObjectsTypeManagementDefinition | Property | Type | Description | | --- | --- | --- | | [defaultSearchField](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.defaultsearchfield.md) | string | The default search field to use for this type. Defaults to id. | +| [displayName](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.displayname.md) | string | When specified, will be used instead of the type's name in SO management section's labels. | | [getEditUrl](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md) | (savedObject: SavedObject<Attributes>) => string | Function returning the url to use to redirect to the editing page of this object. If not defined, editing will not be allowed. | | [getInAppUrl](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md) | (savedObject: SavedObject<Attributes>) => {
path: string;
uiCapabilitiesPath: string;
} | Function returning the url to use to redirect to this object from the management section. If not defined, redirecting to the object will not be allowed. | | [getTitle](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md) | (savedObject: SavedObject<Attributes>) => string | Function returning the title to display in the management table. If not defined, will use the object's type and id to generate a label. | diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 3c7aa8b992688..1ef845730e1f3 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2739,6 +2739,7 @@ export interface SavedObjectsType { // @public export interface SavedObjectsTypeManagementDefinition { defaultSearchField?: string; + displayName?: string; getEditUrl?: (savedObject: SavedObject) => string; getInAppUrl?: (savedObject: SavedObject) => { path: string; From dc14ed1345e22d51cd20275f2a42b8b2c96bd940 Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Mon, 27 Sep 2021 15:31:12 +0200 Subject: [PATCH 5/6] also update labels --- .../public/lib/get_saved_object_label.test.ts | 31 +++++++++++++++++++ .../public/lib/get_saved_object_label.ts | 17 +++++----- .../__snapshots__/flyout.test.tsx.snap | 1 + .../__snapshots__/relationships.test.tsx.snap | 8 ++--- .../components/delete_confirm_modal.test.tsx | 13 +++++++- .../components/delete_confirm_modal.tsx | 6 ++-- .../objects_table/components/flyout.test.tsx | 1 + .../objects_table/components/flyout.tsx | 4 +++ .../components/import_summary.test.tsx | 1 + .../components/import_summary.tsx | 8 +++-- .../components/relationships.test.tsx | 16 ++++++++++ .../components/relationships.tsx | 20 ++++++------ .../objects_table/components/table.test.tsx | 3 ++ .../objects_table/components/table.tsx | 8 +++-- .../objects_table/saved_objects_table.tsx | 6 ++++ 15 files changed, 113 insertions(+), 30 deletions(-) create mode 100644 src/plugins/saved_objects_management/public/lib/get_saved_object_label.test.ts diff --git a/src/plugins/saved_objects_management/public/lib/get_saved_object_label.test.ts b/src/plugins/saved_objects_management/public/lib/get_saved_object_label.test.ts new file mode 100644 index 0000000000000..d8f4f09c2bfa4 --- /dev/null +++ b/src/plugins/saved_objects_management/public/lib/get_saved_object_label.test.ts @@ -0,0 +1,31 @@ +/* + * 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 { SavedObjectManagementTypeInfo } from '../../common/types'; +import { getSavedObjectLabel } from './get_saved_object_label'; + +const toTypeInfo = (name: string, displayName?: string): SavedObjectManagementTypeInfo => ({ + name, + displayName: displayName ?? name, + hidden: false, + namespaceType: 'single', +}); + +describe('getSavedObjectLabel', () => { + it('returns the type name if no types are provided', () => { + expect(getSavedObjectLabel('foo', [])).toEqual('foo'); + }); + + it('returns the type name if type does not specify a display name', () => { + expect(getSavedObjectLabel('foo', [toTypeInfo('foo')])).toEqual('foo'); + }); + + it('returns the type display name if type does specify a display name', () => { + expect(getSavedObjectLabel('foo', [toTypeInfo('foo', 'fooDisplay')])).toEqual('fooDisplay'); + }); +}); diff --git a/src/plugins/saved_objects_management/public/lib/get_saved_object_label.ts b/src/plugins/saved_objects_management/public/lib/get_saved_object_label.ts index e86c200fb4fcc..753ffe9af6ce0 100644 --- a/src/plugins/saved_objects_management/public/lib/get_saved_object_label.ts +++ b/src/plugins/saved_objects_management/public/lib/get_saved_object_label.ts @@ -6,13 +6,12 @@ * Side Public License, v 1. */ -export function getSavedObjectLabel(type: string) { - switch (type) { - case 'index-pattern': - case 'index-patterns': - case 'indexPatterns': - return 'index patterns'; - default: - return type; - } +import type { SavedObjectManagementTypeInfo } from '../../common/types'; + +/** + * Returns the label to be used for given saved object type. + */ +export function getSavedObjectLabel(type: string, types: SavedObjectManagementTypeInfo[]) { + const typeInfo = types.find((t) => t.name === type); + return typeInfo?.displayName ?? type; } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap index 1affbd4d96463..9651b8658032e 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap @@ -395,6 +395,7 @@ exports[`Flyout should render import step 1`] = ` exports[`Flyout summary should display summary when import is complete 1`] = `

@@ -378,13 +378,13 @@ exports[`Relationships should render invalid relations 1`] = ` >

diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/delete_confirm_modal.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/delete_confirm_modal.test.tsx index 76e85c9603cc0..396ef209cc396 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/delete_confirm_modal.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/delete_confirm_modal.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { findTestSubject } from '@elastic/eui/lib/test'; import { mountWithIntl } from '@kbn/test/jest'; -import { SavedObjectWithMetadata } from '../../../../common'; +import type { SavedObjectWithMetadata, SavedObjectManagementTypeInfo } from '../../../../common'; import { DeleteConfirmModal } from './delete_confirm_modal'; interface CreateObjectOptions { @@ -32,6 +32,7 @@ const createObject = ({ }); describe('DeleteConfirmModal', () => { + const allowedTypes: SavedObjectManagementTypeInfo[] = []; let onConfirm: jest.Mock; let onCancel: jest.Mock; @@ -47,6 +48,7 @@ describe('DeleteConfirmModal', () => { onConfirm={onConfirm} onCancel={onCancel} selectedObjects={[]} + allowedTypes={allowedTypes} /> ); expect(wrapper.find('EuiLoadingElastic')).toHaveLength(1); @@ -61,6 +63,7 @@ describe('DeleteConfirmModal', () => { onConfirm={onConfirm} onCancel={onCancel} selectedObjects={objs} + allowedTypes={allowedTypes} /> ); expect(wrapper.find('.euiTableRow')).toHaveLength(3); @@ -73,6 +76,7 @@ describe('DeleteConfirmModal', () => { onConfirm={onConfirm} onCancel={onCancel} selectedObjects={[]} + allowedTypes={allowedTypes} /> ); wrapper.find('EuiButtonEmpty').simulate('click'); @@ -88,6 +92,7 @@ describe('DeleteConfirmModal', () => { onConfirm={onConfirm} onCancel={onCancel} selectedObjects={[createObject()]} + allowedTypes={allowedTypes} /> ); wrapper.find('EuiButton').simulate('click'); @@ -109,6 +114,7 @@ describe('DeleteConfirmModal', () => { onConfirm={onConfirm} onCancel={onCancel} selectedObjects={objs} + allowedTypes={allowedTypes} /> ); expect(wrapper.find('.euiTableRow')).toHaveLength(1); @@ -126,6 +132,7 @@ describe('DeleteConfirmModal', () => { onConfirm={onConfirm} onCancel={onCancel} selectedObjects={objs} + allowedTypes={allowedTypes} /> ); @@ -145,6 +152,7 @@ describe('DeleteConfirmModal', () => { onConfirm={onConfirm} onCancel={onCancel} selectedObjects={objs} + allowedTypes={allowedTypes} /> ); @@ -164,6 +172,7 @@ describe('DeleteConfirmModal', () => { onConfirm={onConfirm} onCancel={onCancel} selectedObjects={objs} + allowedTypes={allowedTypes} /> ); @@ -184,6 +193,7 @@ describe('DeleteConfirmModal', () => { onConfirm={onConfirm} onCancel={onCancel} selectedObjects={objs} + allowedTypes={allowedTypes} /> ); const callout = findTestSubject(wrapper, 'sharedObjectsWarning'); @@ -202,6 +212,7 @@ describe('DeleteConfirmModal', () => { onConfirm={onConfirm} onCancel={onCancel} selectedObjects={objs} + allowedTypes={allowedTypes} /> ); const callout = findTestSubject(wrapper, 'sharedObjectsWarning'); diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/delete_confirm_modal.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/delete_confirm_modal.tsx index e3ffc6d52a3ab..2ac3730da5142 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/delete_confirm_modal.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/delete_confirm_modal.tsx @@ -27,7 +27,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { SavedObjectWithMetadata } from '../../../../common'; +import type { SavedObjectWithMetadata, SavedObjectManagementTypeInfo } from '../../../../common'; import { getSavedObjectLabel } from '../../../lib'; export interface DeleteConfirmModalProps { @@ -35,6 +35,7 @@ export interface DeleteConfirmModalProps { onConfirm: () => void; onCancel: () => void; selectedObjects: SavedObjectWithMetadata[]; + allowedTypes: SavedObjectManagementTypeInfo[]; } export const DeleteConfirmModal: FC = ({ @@ -42,6 +43,7 @@ export const DeleteConfirmModal: FC = ({ onConfirm, onCancel, selectedObjects, + allowedTypes, }) => { const undeletableObjects = useMemo(() => { return selectedObjects.filter((obj) => obj.meta.hiddenType); @@ -145,7 +147,7 @@ export const DeleteConfirmModal: FC = ({ ), width: '50px', render: (type, { icon }) => ( - + ), diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx index 8e6b5eb82bd84..4cdacd30e83d1 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx @@ -49,6 +49,7 @@ describe('Flyout', () => { http, search, basePath, + allowedTypes: [], }; }); diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx index e458b4cca430a..92dbba2d23023 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx @@ -37,6 +37,7 @@ import { IndexPattern, DataPublicPluginStart, } from '../../../../../data/public'; +import type { SavedObjectManagementTypeInfo } from '../../../../common/types'; import { importFile, resolveImportErrors, @@ -59,6 +60,7 @@ export interface FlyoutProps { http: HttpStart; basePath: IBasePath; search: DataPublicPluginStart['search']; + allowedTypes: SavedObjectManagementTypeInfo[]; } export interface FlyoutState { @@ -407,6 +409,7 @@ export class Flyout extends Component { } renderBody() { + const { allowedTypes } = this.props; const { status, loadingMessage, @@ -438,6 +441,7 @@ export class Flyout extends Component { failedImports={failedImports} successfulImports={successfulImports} importWarnings={importWarnings ?? []} + allowedTypes={allowedTypes} /> ); } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.test.tsx index 5ac428b3e6ba3..4cbfcb06b3595 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.test.tsx @@ -24,6 +24,7 @@ describe('ImportSummary', () => { failedImports: [], successfulImports: [], importWarnings: [], + allowedTypes: [], ...parts, }); diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.tsx index c24faf4e12687..18f49407cdec1 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.tsx @@ -28,6 +28,7 @@ import type { SavedObjectsImportWarning, IBasePath, } from 'kibana/public'; +import type { SavedObjectManagementTypeInfo } from '../../../../common/types'; import { getDefaultTitle, getSavedObjectLabel, FailedImport } from '../../../lib'; import './import_summary.scss'; @@ -38,6 +39,7 @@ export interface ImportSummaryProps { successfulImports: SavedObjectsImportSuccess[]; importWarnings: SavedObjectsImportWarning[]; basePath: IBasePath; + allowedTypes: SavedObjectManagementTypeInfo[]; } interface ImportItem { @@ -244,6 +246,7 @@ export const ImportSummary: FC = ({ successfulImports, importWarnings, basePath, + allowedTypes, }) => { const importItems: ImportItem[] = useMemo( () => @@ -279,6 +282,7 @@ export const ImportSummary: FC = ({ {importItems.map((item, index) => { const { type, title, icon } = item; + const typeLabel = getSavedObjectLabel(type, allowedTypes); return ( = ({ className="savedObjectsManagementImportSummary__row" > - - + + diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx index 4716594aa669b..946602826f5a4 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { shallowWithI18nProvider } from '@kbn/test/jest'; import { httpServiceMock } from '../../../../../../core/public/mocks'; +import type { SavedObjectManagementTypeInfo } from '../../../../common/types'; import { Relationships, RelationshipsProps } from './relationships'; jest.mock('../../../lib/fetch_export_by_type_and_search', () => ({ @@ -19,6 +20,15 @@ jest.mock('../../../lib/fetch_export_objects', () => ({ fetchExportObjects: jest.fn(), })); +const allowedTypes: SavedObjectManagementTypeInfo[] = [ + { + name: 'index-pattern', + displayName: 'index-pattern', + namespaceType: 'single', + hidden: false, + }, +]; + describe('Relationships', () => { it('should render index patterns normally', async () => { const props: RelationshipsProps = { @@ -73,6 +83,7 @@ describe('Relationships', () => { }, }, }, + allowedTypes, close: jest.fn(), }; @@ -143,6 +154,7 @@ describe('Relationships', () => { }, }, }, + allowedTypes, close: jest.fn(), }; @@ -213,6 +225,7 @@ describe('Relationships', () => { }, }, }, + allowedTypes, close: jest.fn(), }; @@ -283,6 +296,7 @@ describe('Relationships', () => { }, }, }, + allowedTypes, close: jest.fn(), }; @@ -323,6 +337,7 @@ describe('Relationships', () => { }, }, }, + allowedTypes, close: jest.fn(), }; @@ -368,6 +383,7 @@ describe('Relationships', () => { }, }, }, + allowedTypes, close: jest.fn(), }; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.tsx index 8eb48ac91da66..3c518296e5ccd 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.tsx @@ -25,6 +25,7 @@ import { SearchFilterConfig } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { IBasePath } from 'src/core/public'; +import type { SavedObjectManagementTypeInfo } from '../../../../common/types'; import { getDefaultTitle, getSavedObjectLabel } from '../../../lib'; import { SavedObjectWithMetadata, @@ -41,6 +42,7 @@ export interface RelationshipsProps { close: () => void; goInspectObject: (obj: SavedObjectWithMetadata) => void; canGoInApp: (obj: SavedObjectWithMetadata) => boolean; + allowedTypes: SavedObjectManagementTypeInfo[]; } export interface RelationshipsState { @@ -213,7 +215,7 @@ export class Relationships extends Component { + const typeLabel = getSavedObjectLabel(type, allowedTypes); return ( - +

- - + +    {savedObject.meta.title || getDefaultTitle(savedObject)} diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx index 98aa29a92856e..a736c7a8a7c5e 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx @@ -36,6 +36,9 @@ const defaultProps: TableProps = { }, }, ], + allowedTypes: [ + { name: 'index-pattern', displayName: 'index-pattern', hidden: false, namespaceType: 'single' }, + ], selectionConfig: { onSelectionChange: () => {}, }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 0645c0955f7ac..75f36e20eb084 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -28,6 +28,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { SavedObjectsTaggingApi } from '../../../../../saved_objects_tagging_oss/public'; +import type { SavedObjectManagementTypeInfo } from '../../../../common/types'; import { getDefaultTitle, getSavedObjectLabel } from '../../../lib'; import { SavedObjectWithMetadata } from '../../../types'; import { @@ -39,6 +40,7 @@ import { export interface TableProps { taggingApi?: SavedObjectsTaggingApi; basePath: IBasePath; + allowedTypes: SavedObjectManagementTypeInfo[]; actionRegistry: SavedObjectsManagementActionServiceStart; columnRegistry: SavedObjectsManagementColumnServiceStart; selectedSavedObjects: SavedObjectWithMetadata[]; @@ -145,6 +147,7 @@ export class Table extends PureComponent { actionRegistry, columnRegistry, taggingApi, + allowedTypes, } = this.props; const pagination = { @@ -182,10 +185,11 @@ export class Table extends PureComponent { sortable: false, 'data-test-subj': 'savedObjectsTableRowType', render: (type: string, object: SavedObjectWithMetadata) => { + const typeLabel = getSavedObjectLabel(type, allowedTypes); return ( - + ); } @@ -569,12 +570,15 @@ export class SavedObjectsTable extends Component ); } renderDeleteConfirmModal() { const { isShowingDeleteConfirmModal, isDeleting, selectedSavedObjects } = this.state; + const { allowedTypes } = this.props; + if (!isShowingDeleteConfirmModal) { return null; } @@ -589,6 +593,7 @@ export class SavedObjectsTable extends Component ); } @@ -670,6 +675,7 @@ export class SavedObjectsTable extends Component Date: Tue, 28 Sep 2021 08:10:37 +0200 Subject: [PATCH 6/6] fix unit tests --- .../saved_objects_table.test.tsx.snap | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap index 327a9635462cc..f4325b277faba 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap @@ -2,6 +2,34 @@ exports[`SavedObjectsTable delete should show a confirm modal 1`] = `