From 835abdeb106cd2592411f1f16dcb6ef51d643326 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Wed, 23 Sep 2020 17:10:21 +0100 Subject: [PATCH 01/11] Making saveMethod mandatory in attribute service --- src/plugins/dashboard/config.ts | 2 +- .../attribute_service.test.ts | 40 +++++-------------- .../attribute_service/attribute_service.tsx | 24 +++-------- .../visualize_embeddable_factory.tsx | 2 +- 4 files changed, 18 insertions(+), 50 deletions(-) diff --git a/src/plugins/dashboard/config.ts b/src/plugins/dashboard/config.ts index ff968a51679e03..da3f8a61306b89 100644 --- a/src/plugins/dashboard/config.ts +++ b/src/plugins/dashboard/config.ts @@ -20,7 +20,7 @@ import { schema, TypeOf } from '@kbn/config-schema'; export const configSchema = schema.object({ - allowByValueEmbeddables: schema.boolean({ defaultValue: false }), + allowByValueEmbeddables: schema.boolean({ defaultValue: true }), }); export type ConfigSchema = TypeOf; diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts index 06f380ca3862b6..f7a95a84bcb1d5 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts @@ -131,48 +131,30 @@ describe('attributeService', () => { expect(await attributeService.wrapAttributes(attributes, false)).toEqual({ attributes }); }); - it('updates existing saved object with new attributes when given id', async () => { + it('calls saveMethod with appropriate parameters', async () => { const core = coreMock.createStart(); + const saveMethod = jest.fn(); + saveMethod.mockReturnValueOnce({}); const attributeService = mockAttributeService( defaultTestType, - undefined, + { saveMethod }, core ); expect(await attributeService.wrapAttributes(attributes, true, byReferenceInput)).toEqual( byReferenceInput ); - expect(core.savedObjects.client.update).toHaveBeenCalledWith( - defaultTestType, - '123', - attributes - ); - }); - - it('creates new saved object with attributes when given no id', async () => { - const core = coreMock.createStart(); - core.savedObjects.client.create = jest.fn().mockResolvedValueOnce({ - id: '678', - }); - const attributeService = mockAttributeService( - defaultTestType, - undefined, - core - ); - expect(await attributeService.wrapAttributes(attributes, true)).toEqual({ - savedObjectId: '678', - }); - expect(core.savedObjects.client.create).toHaveBeenCalledWith(defaultTestType, attributes); + expect(saveMethod).toHaveBeenCalledWith(defaultTestType, attributes, '123'); }); it('uses custom save method when given an id', async () => { - const customSaveMethod = jest.fn().mockReturnValue({ id: '123' }); + const saveMethod = jest.fn().mockReturnValue({ id: '123' }); const attributeService = mockAttributeService(defaultTestType, { - customSaveMethod, + saveMethod, }); expect(await attributeService.wrapAttributes(attributes, true, byReferenceInput)).toEqual( byReferenceInput ); - expect(customSaveMethod).toHaveBeenCalledWith( + expect(saveMethod).toHaveBeenCalledWith( defaultTestType, attributes, byReferenceInput.savedObjectId @@ -180,14 +162,14 @@ describe('attributeService', () => { }); it('uses custom save method given no id', async () => { - const customSaveMethod = jest.fn().mockReturnValue({ id: '678' }); + const saveMethod = jest.fn().mockReturnValue({ id: '678' }); const attributeService = mockAttributeService(defaultTestType, { - customSaveMethod, + saveMethod, }); expect(await attributeService.wrapAttributes(attributes, true)).toEqual({ savedObjectId: '678', }); - expect(customSaveMethod).toHaveBeenCalledWith(defaultTestType, attributes, undefined); + expect(saveMethod).toHaveBeenCalledWith(defaultTestType, attributes, undefined); }); }); }); diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index 84df05154fb630..1ed892b64a2f9f 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -53,7 +53,7 @@ import { export const ATTRIBUTE_SERVICE_KEY = 'attributes'; export interface AttributeServiceOptions { - customSaveMethod?: ( + saveMethod: ( type: string, attributes: A, savedObjectId?: string @@ -118,25 +118,11 @@ export class AttributeService< return { [ATTRIBUTE_SERVICE_KEY]: newAttributes } as ValType; } try { - if (this.options?.customSaveMethod) { - const savedItem = await this.options.customSaveMethod( - this.type, - newAttributes, - savedObjectId - ); - if ('id' in savedItem) { - return { ...originalInput, savedObjectId: savedItem.id } as RefType; - } - return { ...originalInput } as RefType; + const savedItem = await this.options.saveMethod(this.type, newAttributes, savedObjectId); + if ('id' in savedItem) { + return { ...originalInput, savedObjectId: savedItem.id } as RefType; } - - if (savedObjectId) { - await this.savedObjectsClient.update(this.type, savedObjectId, newAttributes); - return { ...originalInput, savedObjectId } as RefType; - } - - const savedItem = await this.savedObjectsClient.create(this.type, newAttributes); - return { ...originalInput, savedObjectId: savedItem.id } as RefType; + return { ...originalInput } as RefType; } catch (error) { this.toasts.addDanger({ title: i18n.translate('dashboard.attributeService.saveToLibraryError', { diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index 75e53e8e92dbe5..aeb65ba0889ce3 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -129,7 +129,7 @@ export class VisualizeEmbeddableFactory VisualizeSavedObjectAttributes, VisualizeByValueInput, VisualizeByReferenceInput - >(this.type, { customSaveMethod: this.onSave }); + >(this.type, { saveMethod: this.onSave }); } return this.attributeService!; } From eac63962a4772236d450f0950330d771ae7ebf81 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Wed, 23 Sep 2020 17:45:03 +0100 Subject: [PATCH 02/11] Making unwrap method mandatory --- .../attribute_service.test.ts | 20 +++++++++++++++---- .../attribute_service/attribute_service.tsx | 10 ++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts index f7a95a84bcb1d5..f2e4628cf67a49 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts @@ -37,6 +37,10 @@ describe('attributeService', () => { let attributes: TestAttributes; let byValueInput: TestByValueInput; let byReferenceInput: { id: string; savedObjectId: string }; + const defaultSaveMethod = jest.fn(); + const defaultUnwrapMethod = (savedObjectId: string) => ({ + ...attributes, + }); beforeEach(() => { attributes = { @@ -92,7 +96,12 @@ describe('attributeService', () => { }); const attributeService = mockAttributeService( defaultTestType, - undefined, + { + saveMethod: defaultSaveMethod, + unwrapMethod: (savedObjectId) => ({ + ...attributes, + }), + }, core ); expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual(attributes); @@ -111,8 +120,9 @@ describe('attributeService', () => { const attributeService = mockAttributeService( defaultTestType, { - customUnwrapMethod: (savedObject) => ({ - ...savedObject.attributes, + saveMethod: defaultSaveMethod, + unwrapMethod: (savedObjectId) => ({ + ...attributes, testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' }, }), }, @@ -137,7 +147,7 @@ describe('attributeService', () => { saveMethod.mockReturnValueOnce({}); const attributeService = mockAttributeService( defaultTestType, - { saveMethod }, + { saveMethod, unwrapMethod: defaultUnwrapMethod }, core ); expect(await attributeService.wrapAttributes(attributes, true, byReferenceInput)).toEqual( @@ -150,6 +160,7 @@ describe('attributeService', () => { const saveMethod = jest.fn().mockReturnValue({ id: '123' }); const attributeService = mockAttributeService(defaultTestType, { saveMethod, + unwrapMethod: defaultUnwrapMethod, }); expect(await attributeService.wrapAttributes(attributes, true, byReferenceInput)).toEqual( byReferenceInput @@ -165,6 +176,7 @@ describe('attributeService', () => { const saveMethod = jest.fn().mockReturnValue({ id: '678' }); const attributeService = mockAttributeService(defaultTestType, { saveMethod, + unwrapMethod: defaultUnwrapMethod, }); expect(await attributeService.wrapAttributes(attributes, true)).toEqual({ savedObjectId: '678', diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index 1ed892b64a2f9f..46576ba866395a 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -32,7 +32,6 @@ import { } from '../embeddable_plugin'; import { SavedObjectsClientContract, - SimpleSavedObject, I18nStart, NotificationsStart, OverlayStart, @@ -58,7 +57,7 @@ export interface AttributeServiceOptions { attributes: A, savedObjectId?: string ) => Promise<{ id?: string } | { error: Error }>; - customUnwrapMethod?: (savedObject: SimpleSavedObject) => A; + unwrapMethod: (savedObjectId: string) => A; } export class AttributeService< @@ -94,12 +93,7 @@ export class AttributeService< public async unwrapAttributes(input: RefType | ValType): Promise { if (this.inputIsRefType(input)) { - const savedObject: SimpleSavedObject = await this.savedObjectsClient.get< - SavedObjectAttributes - >(this.type, input.savedObjectId); - return this.options?.customUnwrapMethod - ? this.options?.customUnwrapMethod(savedObject) - : { ...savedObject.attributes }; + return this.options.unwrapMethod(input.savedObjectId); } return input[ATTRIBUTE_SERVICE_KEY]; } From ceae41bf3aece6b01244ca80b357c3c24053abfb Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Wed, 23 Sep 2020 21:45:03 +0100 Subject: [PATCH 03/11] Making book embeddable respect new attribute service --- .../public/book/book_embeddable_factory.tsx | 32 +++++++++++++++++-- examples/embeddable_examples/public/plugin.ts | 4 ++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/examples/embeddable_examples/public/book/book_embeddable_factory.tsx b/examples/embeddable_examples/public/book/book_embeddable_factory.tsx index 292261ee16c59e..792901e1c32621 100644 --- a/examples/embeddable_examples/public/book/book_embeddable_factory.tsx +++ b/examples/embeddable_examples/public/book/book_embeddable_factory.tsx @@ -33,12 +33,17 @@ import { BookEmbeddableOutput, } from './book_embeddable'; import { CreateEditBookComponent } from './create_edit_book_component'; -import { OverlayStart } from '../../../../src/core/public'; +import { + OverlayStart, + SavedObjectsClientContract, + SimpleSavedObject, +} from '../../../../src/core/public'; import { DashboardStart, AttributeService } from '../../../../src/plugins/dashboard/public'; interface StartServices { getAttributeService: DashboardStart['getAttributeService']; openModal: OverlayStart['openModal']; + savedObjectsClient: SavedObjectsClientContract; } export type BookEmbeddableFactory = EmbeddableFactory< @@ -117,11 +122,34 @@ export class BookEmbeddableFactoryDefinition }); } + private async unwrapMethod(savedObjectId: string) { + const { savedObjectsClient } = await this.getStartServices(); + const savedObject: SimpleSavedObject = await savedObjectsClient.get< + BookSavedObjectAttributes + >(this.type, savedObjectId); + return { ...savedObject.attributes }; + } + + private async saveMethod( + type: string, + attributes: BookSavedObjectAttributes, + savedObjectId?: string + ) { + const { savedObjectsClient } = await this.getStartServices(); + if (savedObjectId) { + return savedObjectsClient.update(type, savedObjectId, attributes); + } + return savedObjectsClient.create(type, attributes); + } + private async getAttributeService() { if (!this.attributeService) { this.attributeService = await (await this.getStartServices()).getAttributeService< BookSavedObjectAttributes - >(this.type); + >(this.type, { + saveMethod: this.saveMethod.bind(this), + unwrapMethod: this.unwrapMethod.bind(this), + }); } return this.attributeService!; } diff --git a/examples/embeddable_examples/public/plugin.ts b/examples/embeddable_examples/public/plugin.ts index 0c6ed1eb3be488..0ec53c352fd34f 100644 --- a/examples/embeddable_examples/public/plugin.ts +++ b/examples/embeddable_examples/public/plugin.ts @@ -22,7 +22,7 @@ import { EmbeddableStart, CONTEXT_MENU_TRIGGER, } from '../../../src/plugins/embeddable/public'; -import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public'; +import { Plugin, CoreSetup, CoreStart, SavedObjectsClient } from '../../../src/core/public'; import { HelloWorldEmbeddableFactory, HELLO_WORLD_EMBEDDABLE, @@ -76,6 +76,7 @@ export interface EmbeddableExamplesSetupDependencies { export interface EmbeddableExamplesStartDependencies { embeddable: EmbeddableStart; dashboard: DashboardStart; + savedObjectsClient: SavedObjectsClient; } interface ExampleEmbeddableFactories { @@ -158,6 +159,7 @@ export class EmbeddableExamplesPlugin new BookEmbeddableFactoryDefinition(async () => ({ getAttributeService: (await core.getStartServices())[1].dashboard.getAttributeService, openModal: (await core.getStartServices())[0].overlays.openModal, + savedObjectsClient: (await core.getStartServices())[0].savedObjects.client, })) ); From 384653fc1fc81b1fea10b1cf429ca30e306b293f Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Mon, 28 Sep 2020 11:52:30 +0100 Subject: [PATCH 04/11] Remove savedObjectsClient from attribute service --- .../public/book/book_embeddable_factory.tsx | 4 +- .../attribute_service/attribute_service.tsx | 37 +++---------------- src/plugins/dashboard/public/plugin.tsx | 2 - .../visualize_embeddable_factory.tsx | 32 ++++++++++++++-- src/plugins/visualizations/public/plugin.ts | 2 + 5 files changed, 38 insertions(+), 39 deletions(-) diff --git a/examples/embeddable_examples/public/book/book_embeddable_factory.tsx b/examples/embeddable_examples/public/book/book_embeddable_factory.tsx index 792901e1c32621..4793379a7adf6e 100644 --- a/examples/embeddable_examples/public/book/book_embeddable_factory.tsx +++ b/examples/embeddable_examples/public/book/book_embeddable_factory.tsx @@ -144,11 +144,11 @@ export class BookEmbeddableFactoryDefinition private async getAttributeService() { if (!this.attributeService) { - this.attributeService = await (await this.getStartServices()).getAttributeService< + this.attributeService = (await this.getStartServices()).getAttributeService< BookSavedObjectAttributes >(this.type, { saveMethod: this.saveMethod.bind(this), - unwrapMethod: this.unwrapMethod.bind(this), + unwrapMethod: await this.unwrapMethod.bind(this), }); } return this.attributeService!; diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index 46576ba866395a..037efc350f0747 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -30,18 +30,8 @@ import { EmbeddableFactory, EmbeddableFactoryNotFoundError, } from '../embeddable_plugin'; -import { - SavedObjectsClientContract, - I18nStart, - NotificationsStart, - OverlayStart, -} from '../../../../core/public'; -import { - SavedObjectSaveModal, - OnSaveProps, - SaveResult, - checkForDuplicateTitle, -} from '../../../saved_objects/public'; +import { I18nStart, NotificationsStart } from '../../../../core/public'; +import { SavedObjectSaveModal, OnSaveProps, SaveResult } from '../../../saved_objects/public'; /** * The attribute service is a shared, generic service that embeddables can use to provide the functionality @@ -57,7 +47,8 @@ export interface AttributeServiceOptions { attributes: A, savedObjectId?: string ) => Promise<{ id?: string } | { error: Error }>; - unwrapMethod: (savedObjectId: string) => A; + unwrapMethod?: (savedObjectId: string) => A; + checkForDuplicateTitle: (props: OnSaveProps) => Promise; } export class AttributeService< @@ -75,8 +66,6 @@ export class AttributeService< saveModal: React.ReactElement, I18nContext: I18nStart['Context'] ) => void, - private savedObjectsClient: SavedObjectsClientContract, - private overlays: OverlayStart, private i18nContext: I18nStart['Context'], private toasts: NotificationsStart['toasts'], getEmbeddableFactory?: EmbeddableStart['getEmbeddableFactory'], @@ -92,7 +81,7 @@ export class AttributeService< } public async unwrapAttributes(input: RefType | ValType): Promise { - if (this.inputIsRefType(input)) { + if (this.inputIsRefType(input) && this.options && this.options.unwrapMethod) { return this.options.unwrapMethod(input.savedObjectId); } return input[ATTRIBUTE_SERVICE_KEY]; @@ -165,21 +154,7 @@ export class AttributeService< } return new Promise((resolve, reject) => { const onSave = async (props: OnSaveProps): Promise => { - await checkForDuplicateTitle( - { - title: props.newTitle, - copyOnSave: false, - lastSavedTitle: '', - getEsType: () => this.type, - getDisplayName: this.embeddableFactory?.getDisplayName || (() => this.type), - }, - props.isTitleDuplicateConfirmed, - props.onTitleDuplicate, - { - savedObjectsClient: this.savedObjectsClient, - overlays: this.overlays, - } - ); + await this.options.checkForDuplicateTitle(props); try { const newAttributes = { ...input[ATTRIBUTE_SERVICE_KEY] }; newAttributes.title = props.newTitle; diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 5a45229a58a7d4..9770ee75a24150 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -491,8 +491,6 @@ export class DashboardPlugin new AttributeService( type, showSaveModal, - core.savedObjects.client, - core.overlays, core.i18n.Context, core.notifications.toasts, embeddable.getEmbeddableFactory, diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index aeb65ba0889ce3..4ea1e03e0d5ba4 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -18,7 +18,7 @@ */ import { i18n } from '@kbn/i18n'; -import { SavedObjectMetaData } from 'src/plugins/saved_objects/public'; +import { SavedObjectMetaData, OnSaveProps } from 'src/plugins/saved_objects/public'; import { first } from 'rxjs/operators'; import { SavedObjectAttributes } from '../../../../core/public'; import { @@ -51,6 +51,7 @@ import { StartServicesGetter } from '../../../kibana_utils/public'; import { VisualizationsStartDeps } from '../plugin'; import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants'; import { AttributeService } from '../../../dashboard/public'; +import { checkForDuplicateTitle } from '../../../saved_objects/public'; interface VisualizationAttributes extends SavedObjectAttributes { visState: string; @@ -58,7 +59,7 @@ interface VisualizationAttributes extends SavedObjectAttributes { export interface VisualizeEmbeddableFactoryDeps { start: StartServicesGetter< - Pick + Pick >; } @@ -129,7 +130,10 @@ export class VisualizeEmbeddableFactory VisualizeSavedObjectAttributes, VisualizeByValueInput, VisualizeByReferenceInput - >(this.type, { saveMethod: this.onSave }); + >(this.type, { + saveMethod: this.saveMethod.bind(this), + checkForDuplicateTitle: this.checkTitle.bind(this), + }); } return this.attributeService!; } @@ -183,7 +187,7 @@ export class VisualizeEmbeddableFactory } } - private async onSave( + private async saveMethod( type: string, attributes: VisualizeSavedObjectAttributes ): Promise<{ id: string }> { @@ -225,4 +229,24 @@ export class VisualizeEmbeddableFactory throw error; } } + + public async checkTitle(props: OnSaveProps): Promise { + const savedObjectsClient = await this.deps.start().core.savedObjects.client; + const overlays = await this.deps.start().core.overlays; + return await checkForDuplicateTitle( + { + title: props.newTitle, + copyOnSave: false, + lastSavedTitle: '', + getEsType: () => this.type, + getDisplayName: this.getDisplayName || (() => this.type), + }, + props.isTitleDuplicateConfirmed, + props.onTitleDuplicate, + { + savedObjectsClient, + overlays, + } + ); + } } diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index 0ba80887b513f2..37a99729834212 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -25,6 +25,7 @@ import { CoreStart, Plugin, ApplicationStart, + SavedObjectsClientContract, } from '../../../core/public'; import { TypesService, TypesSetup, TypesStart } from './vis_types'; import { @@ -112,6 +113,7 @@ export interface VisualizationsStartDeps { application: ApplicationStart; dashboard: DashboardStart; getAttributeService: DashboardStart['getAttributeService']; + savedObjectsClient: SavedObjectsClientContract; } /** From c235fc7587d1a1b42c7b3f790e107b5efc9bd3e7 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Mon, 28 Sep 2020 13:17:56 +0100 Subject: [PATCH 05/11] Add checkForDuplicateTitle method to book embeddable --- examples/embeddable_examples/kibana.json | 2 +- .../public/book/book_embeddable_factory.tsx | 27 +++++++++++++++++-- examples/embeddable_examples/public/plugin.ts | 1 + .../attribute_service/attribute_service.tsx | 2 +- .../visualize_embeddable_factory.tsx | 2 +- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/examples/embeddable_examples/kibana.json b/examples/embeddable_examples/kibana.json index 0ac40ae1889de1..223b8c55a5fde1 100644 --- a/examples/embeddable_examples/kibana.json +++ b/examples/embeddable_examples/kibana.json @@ -4,7 +4,7 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["embeddable", "uiActions", "dashboard"], + "requiredPlugins": ["embeddable", "uiActions", "dashboard", "savedObjects"], "optionalPlugins": [], "extraPublicDirs": ["public/todo", "public/hello_world", "public/todo/todo_ref_embeddable"], "requiredBundles": ["kibanaReact"] diff --git a/examples/embeddable_examples/public/book/book_embeddable_factory.tsx b/examples/embeddable_examples/public/book/book_embeddable_factory.tsx index 4793379a7adf6e..a5355522821506 100644 --- a/examples/embeddable_examples/public/book/book_embeddable_factory.tsx +++ b/examples/embeddable_examples/public/book/book_embeddable_factory.tsx @@ -39,11 +39,13 @@ import { SimpleSavedObject, } from '../../../../src/core/public'; import { DashboardStart, AttributeService } from '../../../../src/plugins/dashboard/public'; +import { checkForDuplicateTitle, OnSaveProps } from '../../../../src/plugins/saved_objects/public'; interface StartServices { getAttributeService: DashboardStart['getAttributeService']; openModal: OverlayStart['openModal']; savedObjectsClient: SavedObjectsClientContract; + overlays: OverlayStart; } export type BookEmbeddableFactory = EmbeddableFactory< @@ -122,7 +124,7 @@ export class BookEmbeddableFactoryDefinition }); } - private async unwrapMethod(savedObjectId: string) { + private async unwrapMethod(savedObjectId: string): Promise { const { savedObjectsClient } = await this.getStartServices(); const savedObject: SimpleSavedObject = await savedObjectsClient.get< BookSavedObjectAttributes @@ -142,13 +144,34 @@ export class BookEmbeddableFactoryDefinition return savedObjectsClient.create(type, attributes); } + private async checkForDuplicateTitleMethod(props: OnSaveProps): Promise { + const start = await this.getStartServices(); + const { savedObjectsClient, overlays } = start; + return checkForDuplicateTitle( + { + title: props.newTitle, + copyOnSave: false, + lastSavedTitle: '', + getEsType: () => this.type, + getDisplayName: this.getDisplayName || (() => this.type), + }, + props.isTitleDuplicateConfirmed, + props.onTitleDuplicate, + { + savedObjectsClient, + overlays, + } + ); + } + private async getAttributeService() { if (!this.attributeService) { this.attributeService = (await this.getStartServices()).getAttributeService< BookSavedObjectAttributes >(this.type, { saveMethod: this.saveMethod.bind(this), - unwrapMethod: await this.unwrapMethod.bind(this), + unwrapMethod: this.unwrapMethod.bind(this), + checkForDuplicateTitle: this.checkForDuplicateTitleMethod.bind(this), }); } return this.attributeService!; diff --git a/examples/embeddable_examples/public/plugin.ts b/examples/embeddable_examples/public/plugin.ts index 0ec53c352fd34f..8f05a3de94d6d8 100644 --- a/examples/embeddable_examples/public/plugin.ts +++ b/examples/embeddable_examples/public/plugin.ts @@ -160,6 +160,7 @@ export class EmbeddableExamplesPlugin getAttributeService: (await core.getStartServices())[1].dashboard.getAttributeService, openModal: (await core.getStartServices())[0].overlays.openModal, savedObjectsClient: (await core.getStartServices())[0].savedObjects.client, + overlays: (await core.getStartServices())[0].overlays, })) ); diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index 037efc350f0747..81668c63a767e5 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -47,7 +47,7 @@ export interface AttributeServiceOptions { attributes: A, savedObjectId?: string ) => Promise<{ id?: string } | { error: Error }>; - unwrapMethod?: (savedObjectId: string) => A; + unwrapMethod?: (savedObjectId: string) => Promise; checkForDuplicateTitle: (props: OnSaveProps) => Promise; } diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index 4ea1e03e0d5ba4..87f78f5639ff0d 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -233,7 +233,7 @@ export class VisualizeEmbeddableFactory public async checkTitle(props: OnSaveProps): Promise { const savedObjectsClient = await this.deps.start().core.savedObjects.client; const overlays = await this.deps.start().core.overlays; - return await checkForDuplicateTitle( + return checkForDuplicateTitle( { title: props.newTitle, copyOnSave: false, From 487f1b168b360cba614e5edd4a4a3a5a6f4c2cbc Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Mon, 28 Sep 2020 13:29:47 +0100 Subject: [PATCH 06/11] Make options mandatory on attribute service --- .../public/attribute_service/attribute_service.tsx | 12 ++++-------- src/plugins/dashboard/public/plugin.tsx | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index 81668c63a767e5..4a3d37cf47580b 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -27,7 +27,6 @@ import { IEmbeddable, Container, EmbeddableStart, - EmbeddableFactory, EmbeddableFactoryNotFoundError, } from '../embeddable_plugin'; import { I18nStart, NotificationsStart } from '../../../../core/public'; @@ -47,8 +46,8 @@ export interface AttributeServiceOptions { attributes: A, savedObjectId?: string ) => Promise<{ id?: string } | { error: Error }>; - unwrapMethod?: (savedObjectId: string) => Promise; checkForDuplicateTitle: (props: OnSaveProps) => Promise; + unwrapMethod?: (savedObjectId: string) => Promise; } export class AttributeService< @@ -58,8 +57,6 @@ export class AttributeService< } = EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: SavedObjectAttributes }, RefType extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput > { - private embeddableFactory?: EmbeddableFactory; - constructor( private type: string, private showSaveModal: ( @@ -68,20 +65,19 @@ export class AttributeService< ) => void, private i18nContext: I18nStart['Context'], private toasts: NotificationsStart['toasts'], - getEmbeddableFactory?: EmbeddableStart['getEmbeddableFactory'], - private options?: AttributeServiceOptions + private options: AttributeServiceOptions, + getEmbeddableFactory?: EmbeddableStart['getEmbeddableFactory'] ) { if (getEmbeddableFactory) { const factory = getEmbeddableFactory(this.type); if (!factory) { throw new EmbeddableFactoryNotFoundError(this.type); } - this.embeddableFactory = factory; } } public async unwrapAttributes(input: RefType | ValType): Promise { - if (this.inputIsRefType(input) && this.options && this.options.unwrapMethod) { + if (this.inputIsRefType(input) && this.options.unwrapMethod) { return this.options.unwrapMethod(input.savedObjectId); } return input[ATTRIBUTE_SERVICE_KEY]; diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 9770ee75a24150..303f0173dd9e10 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -493,8 +493,8 @@ export class DashboardPlugin showSaveModal, core.i18n.Context, core.notifications.toasts, - embeddable.getEmbeddableFactory, - options + options, + embeddable.getEmbeddableFactory ), }; } From ec6a36fb403a5bf99bb11901da0925f3b6314c13 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Mon, 28 Sep 2020 15:03:13 +0100 Subject: [PATCH 07/11] Changing Lens attribute service --- .../lens/public/lens_attribute_service.ts | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/lens/public/lens_attribute_service.ts b/x-pack/plugins/lens/public/lens_attribute_service.ts index 3c43fd98cceb46..09dadac92afdc3 100644 --- a/x-pack/plugins/lens/public/lens_attribute_service.ts +++ b/x-pack/plugins/lens/public/lens_attribute_service.ts @@ -13,6 +13,8 @@ import { LensByReferenceInput, } from './editor_frame_service/embeddable/embeddable'; import { SavedObjectIndexStore, DOC_TYPE } from './persistence'; +import { SavedObjectAttributes } from '../../../../src/core/target/types/saved_objects'; +import { checkForDuplicateTitle, OnSaveProps } from '../../../../src/plugins/saved_objects/public'; export type LensAttributeService = AttributeService< LensSavedObjectAttributes, @@ -30,7 +32,7 @@ export function getLensAttributeService( LensByValueInput, LensByReferenceInput >(DOC_TYPE, { - customSaveMethod: async ( + saveMethod: async ( type: string, attributes: LensSavedObjectAttributes, savedObjectId?: string @@ -42,11 +44,34 @@ export function getLensAttributeService( }); return { id: savedDoc.savedObjectId }; }, - customUnwrapMethod: (savedObject) => { + unwrapMethod: async (savedObjectId: string) => { + const savedObject = await core.savedObjects.client.get( + DOC_TYPE, + savedObjectId + ); return { ...savedObject.attributes, references: savedObject.references, }; }, + checkForDuplicateTitle: (props: OnSaveProps) => { + const savedObjectsClient = core.savedObjects.client; + const overlays = core.overlays; + return checkForDuplicateTitle( + { + title: props.newTitle, + copyOnSave: false, + lastSavedTitle: '', + getEsType: () => DOC_TYPE, + getDisplayName: () => DOC_TYPE, + }, + props.isTitleDuplicateConfirmed, + props.onTitleDuplicate, + { + savedObjectsClient, + overlays, + } + ); + }, }); } From 933c3aa948bd7fea2d1dd32cc57da1bc6bd134db Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Mon, 28 Sep 2020 17:37:06 +0100 Subject: [PATCH 08/11] Somw more typescript fixes --- .../public/book/edit_book_action.tsx | 23 ++++++- examples/embeddable_examples/public/plugin.ts | 1 + .../attribute_service.mock.tsx | 11 ++-- .../attribute_service.test.ts | 63 ++++++++++++++----- .../attribute_service/attribute_service.tsx | 12 +++- src/plugins/dashboard/public/plugin.tsx | 2 +- .../lens/public/app_plugin/app.test.tsx | 5 +- 7 files changed, 87 insertions(+), 30 deletions(-) diff --git a/examples/embeddable_examples/public/book/edit_book_action.tsx b/examples/embeddable_examples/public/book/edit_book_action.tsx index 3541ace1e5e7e6..77035b6887734d 100644 --- a/examples/embeddable_examples/public/book/edit_book_action.tsx +++ b/examples/embeddable_examples/public/book/edit_book_action.tsx @@ -31,10 +31,13 @@ import { } from './book_embeddable'; import { CreateEditBookComponent } from './create_edit_book_component'; import { DashboardStart } from '../../../../src/plugins/dashboard/public'; +import { OnSaveProps } from '../../../../src/plugins/saved_objects/public'; +import { SavedObjectsClientContract } from '../../../../src/core/target/types/public/saved_objects'; interface StartServices { openModal: OverlayStart['openModal']; getAttributeService: DashboardStart['getAttributeService']; + savedObjectsClient: SavedObjectsClientContract; } interface ActionContext { @@ -56,8 +59,24 @@ export const createEditBookAction = (getStartServices: () => Promise { - const { openModal, getAttributeService } = await getStartServices(); - const attributeService = getAttributeService(BOOK_SAVED_OBJECT); + const { openModal, getAttributeService, savedObjectsClient } = await getStartServices(); + const attributeService = getAttributeService(BOOK_SAVED_OBJECT, { + saveMethod: async ( + type: string, + attributes: BookSavedObjectAttributes, + savedObjectId?: string + ) => { + if (savedObjectId) { + return savedObjectsClient.update(type, savedObjectId, attributes); + } + return savedObjectsClient.create(type, attributes); + }, + checkForDuplicateTitle: (props: OnSaveProps) => { + return new Promise(() => { + return true; + }); + }, + }); const onSave = async (attributes: BookSavedObjectAttributes, useRefType: boolean) => { const newInput = await attributeService.wrapAttributes( attributes, diff --git a/examples/embeddable_examples/public/plugin.ts b/examples/embeddable_examples/public/plugin.ts index 8f05a3de94d6d8..6d1b119e741bdb 100644 --- a/examples/embeddable_examples/public/plugin.ts +++ b/examples/embeddable_examples/public/plugin.ts @@ -167,6 +167,7 @@ export class EmbeddableExamplesPlugin const editBookAction = createEditBookAction(async () => ({ getAttributeService: (await core.getStartServices())[1].dashboard.getAttributeService, openModal: (await core.getStartServices())[0].overlays.openModal, + savedObjectsClient: (await core.getStartServices())[0].savedObjects.client, })); deps.uiActions.registerAction(editBookAction); deps.uiActions.attachAction(CONTEXT_MENU_TRIGGER, editBookAction.id); diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.mock.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.mock.tsx index 321a53361fc7aa..09d6f5b4f1e0dc 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.mock.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.mock.tsx @@ -31,19 +31,16 @@ export const mockAttributeService = < R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput >( type: string, - options?: AttributeServiceOptions, + options: AttributeServiceOptions, customCore?: jest.Mocked ): AttributeService => { const core = customCore ? customCore : coreMock.createStart(); - const service = new AttributeService( + return new AttributeService( type, jest.fn(), - core.savedObjects.client, - core.overlays, core.i18n.Context, core.notifications.toasts, - jest.fn().mockReturnValue(() => ({ getDisplayName: () => type })), - options + options, + jest.fn().mockReturnValue(() => ({ getDisplayName: () => type })) ); - return service; }; diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts index 64a1cb7511be15..ce4a65ade4d7fd 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts @@ -20,6 +20,7 @@ import { ATTRIBUTE_SERVICE_KEY } from './attribute_service'; import { mockAttributeService } from './attribute_service.mock'; import { coreMock } from '../../../../core/public/mocks'; +import { OnSaveProps } from '../../../saved_objects/public/save_modal'; interface TestAttributes { title: string; @@ -37,10 +38,30 @@ describe('attributeService', () => { let attributes: TestAttributes; let byValueInput: TestByValueInput; let byReferenceInput: { id: string; savedObjectId: string }; - const defaultSaveMethod = jest.fn(); - const defaultUnwrapMethod = (savedObjectId: string) => ({ - ...attributes, - }); + const defaultSaveMethod = ( + type: string, + testAttributes: TestAttributes, + savedObjectId?: string + ): Promise<{ id: string }> => { + return new Promise(() => { + return { id: '123' }; + }); + }; + const defaultUnwrapMethod = (savedObjectId: string): Promise => { + return new Promise(() => { + return { ...attributes }; + }); + }; + + const options = { + saveMethod: defaultSaveMethod, + unwrapMethod: defaultUnwrapMethod, + checkForDuplicateTitle: (props: OnSaveProps) => { + return new Promise(() => { + return true; + }); + }, + }; beforeEach(() => { attributes = { @@ -59,9 +80,10 @@ describe('attributeService', () => { }); describe('determining input type', () => { - const defaultAttributeService = mockAttributeService(defaultTestType); + const defaultAttributeService = mockAttributeService(defaultTestType, options); const customAttributeService = mockAttributeService( - defaultTestType + defaultTestType, + options ); it('can determine input type given default types', () => { @@ -98,9 +120,12 @@ describe('attributeService', () => { defaultTestType, { saveMethod: defaultSaveMethod, - unwrapMethod: (savedObjectId) => ({ - ...attributes, - }), + unwrapMethod: (savedObjectId) => { + return new Promise(() => { + return { ...attributes }; + }); + }, + checkForDuplicateTitle: jest.fn(), }, core ); @@ -108,8 +133,8 @@ describe('attributeService', () => { }); it('returns attributes when when given value type input', async () => { - const attributeService = mockAttributeService(defaultTestType); - expect(await attributeService.unwrapAttributes(byValueInput)).toEqual(attributes); + const attributeService = mockAttributeService(defaultTestType, options); + expect(await attributeService.unwrapAttributes(byValueInput)).toEqual(attributes, options); }); it('runs attributes through a custom unwrap method', async () => { @@ -121,10 +146,15 @@ describe('attributeService', () => { defaultTestType, { saveMethod: defaultSaveMethod, - unwrapMethod: (savedObjectId) => ({ - ...attributes, - testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' }, - }), + unwrapMethod: (savedObjectId) => { + return new Promise(() => { + return { + ...attributes, + testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' }, + }; + }); + }, + checkForDuplicateTitle: jest.fn(), }, core ); @@ -137,7 +167,7 @@ describe('attributeService', () => { describe('wrapping attributes', () => { it('returns given attributes when use ref type is false', async () => { - const attributeService = mockAttributeService(defaultTestType); + const attributeService = mockAttributeService(defaultTestType, options); expect(await attributeService.wrapAttributes(attributes, false)).toEqual({ attributes }); }); @@ -177,6 +207,7 @@ describe('attributeService', () => { const attributeService = mockAttributeService(defaultTestType, { saveMethod, unwrapMethod: defaultUnwrapMethod, + checkForDuplicateTitle: jest.fn(), }); expect(await attributeService.wrapAttributes(attributes, true)).toEqual({ savedObjectId: '678', diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index 2c6be9423b3998..fe72e51bc1e4ee 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -76,9 +76,17 @@ export class AttributeService< } } + private async defaultUnwrapMethod(input: RefType): Promise { + return new Promise(() => { + return { ...input }; + }); + } + public async unwrapAttributes(input: RefType | ValType): Promise { - if (this.inputIsRefType(input) && this.options.unwrapMethod) { - return this.options.unwrapMethod(input.savedObjectId); + if (this.inputIsRefType(input)) { + return this.options.unwrapMethod + ? await this.options.unwrapMethod(input.savedObjectId) + : await this.defaultUnwrapMethod(input); } return input[ATTRIBUTE_SERVICE_KEY]; } diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 5c53ed73dd91b5..b1437aeb3471f2 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -164,7 +164,7 @@ export interface DashboardStart { R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput >( type: string, - options?: AttributeServiceOptions + options: AttributeServiceOptions ) => AttributeService; } diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx index 24114e2b315181..14e8b33b96ad1c 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx @@ -145,8 +145,9 @@ describe('Lens App', () => { >( DOC_TYPE, { - customSaveMethod: jest.fn(), - customUnwrapMethod: jest.fn(), + saveMethod: jest.fn(), + unwrapMethod: jest.fn(), + checkForDuplicateTitle: jest.fn(), }, core ); From 4911fad6d90e8578a51eacc99c6414cc0eba818a Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Wed, 30 Sep 2020 15:47:40 +0100 Subject: [PATCH 09/11] Fixing attribute service typescript and tests --- .../attribute_service.test.ts | 74 ++++++++----------- .../attribute_service/attribute_service.tsx | 5 +- 2 files changed, 32 insertions(+), 47 deletions(-) diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts index ce4a65ade4d7fd..d7368b299c4111 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts @@ -52,15 +52,15 @@ describe('attributeService', () => { return { ...attributes }; }); }; - + const defaultCheckForDuplicateTitle = (props: OnSaveProps): Promise => { + return new Promise(() => { + return true; + }); + }; const options = { saveMethod: defaultSaveMethod, unwrapMethod: defaultUnwrapMethod, - checkForDuplicateTitle: (props: OnSaveProps) => { - return new Promise(() => { - return true; - }); - }, + checkForDuplicateTitle: defaultCheckForDuplicateTitle, }; beforeEach(() => { @@ -111,53 +111,32 @@ describe('attributeService', () => { }); describe('unwrapping attributes', () => { - it('can unwrap all default attributes when given reference type input', async () => { - const core = coreMock.createStart(); - core.savedObjects.client.get = jest.fn().mockResolvedValueOnce({ - attributes, + it('does not throw error when given reference type input with no unwrap method', async () => { + const attributeService = mockAttributeService(defaultTestType, { + saveMethod: defaultSaveMethod, + checkForDuplicateTitle: jest.fn(), }); - const attributeService = mockAttributeService( - defaultTestType, - { - saveMethod: defaultSaveMethod, - unwrapMethod: (savedObjectId) => { - return new Promise(() => { - return { ...attributes }; - }); - }, - checkForDuplicateTitle: jest.fn(), - }, - core - ); - expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual(attributes); + expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual(byReferenceInput); }); it('returns attributes when when given value type input', async () => { const attributeService = mockAttributeService(defaultTestType, options); - expect(await attributeService.unwrapAttributes(byValueInput)).toEqual(attributes, options); + expect(await attributeService.unwrapAttributes(byValueInput)).toEqual(attributes); }); it('runs attributes through a custom unwrap method', async () => { - const core = coreMock.createStart(); - core.savedObjects.client.get = jest.fn().mockResolvedValueOnce({ - attributes, - }); - const attributeService = mockAttributeService( - defaultTestType, - { - saveMethod: defaultSaveMethod, - unwrapMethod: (savedObjectId) => { - return new Promise(() => { - return { - ...attributes, - testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' }, - }; + const attributeService = mockAttributeService(defaultTestType, { + saveMethod: defaultSaveMethod, + unwrapMethod: (savedObjectId) => { + return new Promise((resolve) => { + return resolve({ + ...attributes, + testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' }, }); - }, - checkForDuplicateTitle: jest.fn(), + }); }, - core - ); + checkForDuplicateTitle: jest.fn(), + }); expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual({ ...attributes, testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' }, @@ -177,7 +156,11 @@ describe('attributeService', () => { saveMethod.mockReturnValueOnce({}); const attributeService = mockAttributeService( defaultTestType, - { saveMethod, unwrapMethod: defaultUnwrapMethod }, + { + saveMethod, + unwrapMethod: defaultUnwrapMethod, + checkForDuplicateTitle: defaultCheckForDuplicateTitle, + }, core ); expect(await attributeService.wrapAttributes(attributes, true, byReferenceInput)).toEqual( @@ -191,6 +174,7 @@ describe('attributeService', () => { const attributeService = mockAttributeService(defaultTestType, { saveMethod, unwrapMethod: defaultUnwrapMethod, + checkForDuplicateTitle: defaultCheckForDuplicateTitle, }); expect(await attributeService.wrapAttributes(attributes, true, byReferenceInput)).toEqual( byReferenceInput @@ -207,7 +191,7 @@ describe('attributeService', () => { const attributeService = mockAttributeService(defaultTestType, { saveMethod, unwrapMethod: defaultUnwrapMethod, - checkForDuplicateTitle: jest.fn(), + checkForDuplicateTitle: defaultCheckForDuplicateTitle, }); expect(await attributeService.wrapAttributes(attributes, true)).toEqual({ savedObjectId: '678', diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index fe72e51bc1e4ee..b46226ec4ab020 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -77,8 +77,9 @@ export class AttributeService< } private async defaultUnwrapMethod(input: RefType): Promise { - return new Promise(() => { - return { ...input }; + return new Promise((resolve) => { + // @ts-ignore + return resolve({ ...input }); }); } From 9c965b5d4d959d343f91336ce687f23e24f40be7 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Thu, 1 Oct 2020 10:14:47 +0100 Subject: [PATCH 10/11] Fixing typescript errors --- src/plugins/visualizations/public/mocks.ts | 1 + .../embeddable/embeddable.test.tsx | 34 ++++++++++++++----- .../lens/public/lens_attribute_service.ts | 5 ++- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts index 646acc49a6a832..90e4936a58b457 100644 --- a/src/plugins/visualizations/public/mocks.ts +++ b/src/plugins/visualizations/public/mocks.ts @@ -72,6 +72,7 @@ const createInstance = async () => { embeddable: embeddablePluginMock.createStartContract(), dashboard: dashboardPluginMock.createStartContract(), getAttributeService: jest.fn(), + savedObjectsClient: coreMock.createStart().savedObjects.client, }); return { diff --git a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx index d48f9ed713caff..cd4ae04bb6c207 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx @@ -28,6 +28,7 @@ import { IBasePath } from '../../../../../../src/core/public'; import { AttributeService } from '../../../../../../src/plugins/dashboard/public'; import { Ast } from '@kbn/interpreter/common'; import { LensAttributeService } from '../../lens_attribute_service'; +import { OnSaveProps } from '../../../../../../src/plugins/saved_objects/public/save_modal'; jest.mock('../../../../../../src/plugins/inspector/public/', () => ({ isAvailable: false, @@ -45,6 +46,30 @@ const savedVis: Document = { title: 'My title', visualizationType: '', }; +const defaultSaveMethod = ( + type: string, + testAttributes: LensSavedObjectAttributes, + savedObjectId?: string +): Promise<{ id: string }> => { + return new Promise(() => { + return { id: '123' }; + }); +}; +const defaultUnwrapMethod = (savedObjectId: string): Promise => { + return new Promise(() => { + return { ...savedVis }; + }); +}; +const defaultCheckForDuplicateTitle = (props: OnSaveProps): Promise => { + return new Promise(() => { + return true; + }); +}; +const options = { + saveMethod: defaultSaveMethod, + unwrapMethod: defaultUnwrapMethod, + checkForDuplicateTitle: defaultCheckForDuplicateTitle, +}; const attributeServiceMockFromSavedVis = (document: Document): LensAttributeService => { const core = coreMock.createStart(); @@ -52,14 +77,7 @@ const attributeServiceMockFromSavedVis = (document: Document): LensAttributeServ LensSavedObjectAttributes, LensByValueInput, LensByReferenceInput - >( - 'lens', - jest.fn(), - core.savedObjects.client, - core.overlays, - core.i18n.Context, - core.notifications.toasts - ); + >('lens', jest.fn(), core.i18n.Context, core.notifications.toasts, options); service.unwrapAttributes = jest.fn((input: LensByValueInput | LensByReferenceInput) => { return Promise.resolve({ ...document } as LensSavedObjectAttributes); }); diff --git a/x-pack/plugins/lens/public/lens_attribute_service.ts b/x-pack/plugins/lens/public/lens_attribute_service.ts index 09dadac92afdc3..9e1ce535d6675b 100644 --- a/x-pack/plugins/lens/public/lens_attribute_service.ts +++ b/x-pack/plugins/lens/public/lens_attribute_service.ts @@ -13,7 +13,6 @@ import { LensByReferenceInput, } from './editor_frame_service/embeddable/embeddable'; import { SavedObjectIndexStore, DOC_TYPE } from './persistence'; -import { SavedObjectAttributes } from '../../../../src/core/target/types/saved_objects'; import { checkForDuplicateTitle, OnSaveProps } from '../../../../src/plugins/saved_objects/public'; export type LensAttributeService = AttributeService< @@ -44,8 +43,8 @@ export function getLensAttributeService( }); return { id: savedDoc.savedObjectId }; }, - unwrapMethod: async (savedObjectId: string) => { - const savedObject = await core.savedObjects.client.get( + unwrapMethod: async (savedObjectId: string): Promise => { + const savedObject = await core.savedObjects.client.get( DOC_TYPE, savedObjectId ); From 2009a8a05afa53c021ffed337424b76c8a5833de Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Fri, 2 Oct 2020 08:01:39 +0100 Subject: [PATCH 11/11] Unsetting feature flag --- src/plugins/dashboard/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/dashboard/config.ts b/src/plugins/dashboard/config.ts index da3f8a61306b89..ff968a51679e03 100644 --- a/src/plugins/dashboard/config.ts +++ b/src/plugins/dashboard/config.ts @@ -20,7 +20,7 @@ import { schema, TypeOf } from '@kbn/config-schema'; export const configSchema = schema.object({ - allowByValueEmbeddables: schema.boolean({ defaultValue: true }), + allowByValueEmbeddables: schema.boolean({ defaultValue: false }), }); export type ConfigSchema = TypeOf;