Skip to content

Commit

Permalink
[Dashboard] Move Sharing Saved Object Props into Meta Object (#119913)
Browse files Browse the repository at this point in the history
Co-authored-by: Anton Dosov <dosantappdev@gmail.com>
Co-authored-by: Marta Bondyra <marta.bondyra@gmail.com>
  • Loading branch information
3 people authored Dec 1, 2021
1 parent 096fb43 commit 9f302fc
Show file tree
Hide file tree
Showing 17 changed files with 237 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export class BookEmbeddable
}

public async reload() {
this.attributes = await this.attributeService.unwrapAttributes(this.input);
this.attributes = (await this.attributeService.unwrapAttributes(this.input)).attributes;

this.updateOutput({
attributes: this.attributes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,13 @@ export class BookEmbeddableFactoryDefinition
});
}

private async unwrapMethod(savedObjectId: string): Promise<BookSavedObjectAttributes> {
private async unwrapMethod(
savedObjectId: string
): Promise<{ attributes: BookSavedObjectAttributes }> {
const { savedObjectsClient } = await this.getStartServices();
const savedObject: SimpleSavedObject<BookSavedObjectAttributes> =
await savedObjectsClient.get<BookSavedObjectAttributes>(this.type, savedObjectId);
return { ...savedObject.attributes };
return { attributes: { ...savedObject.attributes } };
}

private async saveMethod(attributes: BookSavedObjectAttributes, savedObjectId?: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,12 @@ const panelsAreEqual = (panelsA: DashboardPanelMap, panelsB: DashboardPanelMap):
}
// embeddable ids are equal so let's compare individual panels.
for (const id of embeddableIdsA) {
if (
Object.keys(
commonDiff<DashboardPanelState>(
panelsA[id] as unknown as DashboardDiffCommon,
panelsB[id] as unknown as DashboardDiffCommon,
['panelRefName']
)
).length > 0
) {
const panelCommonDiff = commonDiff<DashboardPanelState>(
panelsA[id] as unknown as DashboardDiffCommon,
panelsB[id] as unknown as DashboardDiffCommon,
['panelRefName']
);
if (Object.keys(panelCommonDiff).length > 0) {
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ export const mockAttributeService = <
V extends EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: A } = EmbeddableInput & {
[ATTRIBUTE_SERVICE_KEY]: A;
},
R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput
R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput,
M extends unknown = unknown
>(
type: string,
options: AttributeServiceOptions<A>,
options: AttributeServiceOptions<A, M>,
customCore?: jest.Mocked<CoreStart>
): AttributeService<A, V, R> => {
): AttributeService<A, V, R, M> => {
const core = customCore ? customCore : coreMock.createStart();
return new AttributeService<A, V, R>(
return new AttributeService<A, V, R, M>(
type,
jest.fn(),
core.i18n.Context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Side Public License, v 1.
*/

import { ATTRIBUTE_SERVICE_KEY } from './attribute_service';
import { ATTRIBUTE_SERVICE_KEY, AttributeServiceUnwrapResult } from './attribute_service';
import { mockAttributeService } from './attribute_service.mock';
import { coreMock } from '../../../../../core/public/mocks';
import { OnSaveProps } from 'src/plugins/saved_objects/public/save_modal';
Expand Down Expand Up @@ -35,7 +35,10 @@ describe('attributeService', () => {
return { id: '123' };
});
};
const defaultUnwrapMethod = (savedObjectId: string): Promise<TestAttributes> => {

const defaultUnwrapMethod = (
savedObjectId: string
): Promise<AttributeServiceUnwrapResult<TestAttributes>> => {
return new Promise(() => {
return { ...attributes };
});
Expand Down Expand Up @@ -104,12 +107,14 @@ describe('attributeService', () => {
saveMethod: defaultSaveMethod,
checkForDuplicateTitle: jest.fn(),
});
expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual(byReferenceInput);
expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual({
attributes: byReferenceInput,
});
});

it('returns attributes when when given value type input', async () => {
const attributeService = mockAttributeService<TestAttributes>(defaultTestType, options);
expect(await attributeService.unwrapAttributes(byValueInput)).toEqual(attributes);
expect(await attributeService.unwrapAttributes(byValueInput)).toEqual({ attributes });
});

it('runs attributes through a custom unwrap method', async () => {
Expand All @@ -118,16 +123,20 @@ describe('attributeService', () => {
unwrapMethod: (savedObjectId) => {
return new Promise((resolve) => {
return resolve({
...attributes,
testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' },
attributes: {
...attributes,
testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' },
},
});
});
},
checkForDuplicateTitle: jest.fn(),
});
expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual({
...attributes,
testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' },
attributes: {
...attributes,
testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' },
},
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,37 @@ import {
*/
export const ATTRIBUTE_SERVICE_KEY = 'attributes';

export interface AttributeServiceOptions<A extends { title: string }> {
export interface GenericAttributes {
title: string;
}
export interface AttributeServiceUnwrapResult<
SavedObjectAttributes extends GenericAttributes,
MetaInfo extends unknown = unknown
> {
attributes: SavedObjectAttributes;
metaInfo?: MetaInfo;
}
export interface AttributeServiceOptions<
SavedObjectAttributes extends GenericAttributes,
MetaInfo extends unknown = unknown
> {
saveMethod: (
attributes: A,
attributes: SavedObjectAttributes,
savedObjectId?: string
) => Promise<{ id?: string } | { error: Error }>;
checkForDuplicateTitle: (props: OnSaveProps) => Promise<true>;
unwrapMethod?: (savedObjectId: string) => Promise<A>;
unwrapMethod?: (
savedObjectId: string
) => Promise<AttributeServiceUnwrapResult<SavedObjectAttributes, MetaInfo>>;
}

export class AttributeService<
SavedObjectAttributes extends { title: string },
ValType extends EmbeddableInput & {
[ATTRIBUTE_SERVICE_KEY]: SavedObjectAttributes;
} = EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: SavedObjectAttributes },
RefType extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput
RefType extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput,
MetaInfo extends unknown = unknown
> {
constructor(
private type: string,
Expand All @@ -53,7 +69,7 @@ export class AttributeService<
) => void,
private i18nContext: I18nStart['Context'],
private toasts: NotificationsStart['toasts'],
private options: AttributeServiceOptions<SavedObjectAttributes>,
private options: AttributeServiceOptions<SavedObjectAttributes, MetaInfo>,
getEmbeddableFactory?: (embeddableFactoryId: string) => EmbeddableFactory
) {
if (getEmbeddableFactory) {
Expand All @@ -64,20 +80,21 @@ export class AttributeService<
}
}

private async defaultUnwrapMethod(input: RefType): Promise<SavedObjectAttributes> {
return new Promise<SavedObjectAttributes>((resolve) => {
// @ts-ignore
return resolve({ ...input });
});
private async defaultUnwrapMethod(
input: RefType
): Promise<AttributeServiceUnwrapResult<SavedObjectAttributes, MetaInfo>> {
return Promise.resolve({ attributes: { ...(input as unknown as SavedObjectAttributes) } });
}

public async unwrapAttributes(input: RefType | ValType): Promise<SavedObjectAttributes> {
public async unwrapAttributes(
input: RefType | ValType
): Promise<AttributeServiceUnwrapResult<SavedObjectAttributes, MetaInfo>> {
if (this.inputIsRefType(input)) {
return this.options.unwrapMethod
? await this.options.unwrapMethod(input.savedObjectId)
: await this.defaultUnwrapMethod(input);
}
return input[ATTRIBUTE_SERVICE_KEY];
return { attributes: input[ATTRIBUTE_SERVICE_KEY] };
}

public async wrapAttributes(
Expand Down Expand Up @@ -126,12 +143,12 @@ export class AttributeService<
if (!this.inputIsRefType(input)) {
return input;
}
const attributes = await this.unwrapAttributes(input);
const { attributes } = await this.unwrapAttributes(input);
const { savedObjectId, ...originalInputToPropagate } = input;
return {
...input,
savedObjectId: undefined,
...originalInputToPropagate,
attributes,
};
} as unknown as ValType;
};

getInputAsRefType = async (
Expand Down
7 changes: 4 additions & 3 deletions src/plugins/embeddable/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,12 @@ export interface EmbeddableStart extends PersistableStateService<EmbeddableState
V extends EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: A } = EmbeddableInput & {
[ATTRIBUTE_SERVICE_KEY]: A;
},
R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput
R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput,
M extends unknown = unknown
>(
type: string,
options: AttributeServiceOptions<A>
) => AttributeService<A, V, R>;
options: AttributeServiceOptions<A, M>
) => AttributeService<A, V, R, M>;
}

export type EmbeddablePanelHOC = React.FC<{
Expand Down
18 changes: 11 additions & 7 deletions x-pack/plugins/lens/public/app_plugin/app.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -400,14 +400,18 @@ describe('Lens App', () => {
savedObjectId: savedObjectId || 'aaa',
}));
services.attributeService.unwrapAttributes = jest.fn().mockResolvedValue({
sharingSavedObjectProps: {
outcome: 'exactMatch',
metaInfo: {
sharingSavedObjectProps: {
outcome: 'exactMatch',
},
},
savedObjectId: initialSavedObjectId ?? 'aaa',
references: [],
state: {
query: 'fake query',
filters: [],
attributes: {
savedObjectId: initialSavedObjectId ?? 'aaa',
references: [],
state: {
query: 'fake query',
filters: [],
},
},
} as jest.ResolvedValue<Document>);

Expand Down
49 changes: 31 additions & 18 deletions x-pack/plugins/lens/public/embeddable/embeddable.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
import {
Embeddable,
LensByValueInput,
LensUnwrapMetaInfo,
LensEmbeddableInput,
LensByReferenceInput,
LensSavedObjectAttributes,
LensEmbeddableInput,
ResolvedLensSavedObjectAttributes,
LensUnwrapResult,
} from './embeddable';
import { ReactExpressionRendererProps } from 'src/plugins/expressions/public';
import { Filter } from '@kbn/es-query';
Expand Down Expand Up @@ -52,9 +53,11 @@ const defaultSaveMethod = (
return { id: '123' };
});
};
const defaultUnwrapMethod = (savedObjectId: string): Promise<LensSavedObjectAttributes> => {
const defaultUnwrapMethod = (
savedObjectId: string
): Promise<{ attributes: LensSavedObjectAttributes }> => {
return new Promise(() => {
return { ...savedVis };
return { attributes: { ...savedVis } };
});
};
const defaultCheckForDuplicateTitle = (props: OnSaveProps): Promise<true> => {
Expand All @@ -71,17 +74,22 @@ const options = {
const attributeServiceMockFromSavedVis = (document: Document): LensAttributeService => {
const core = coreMock.createStart();
const service = new AttributeService<
ResolvedLensSavedObjectAttributes,
LensSavedObjectAttributes,
LensByValueInput,
LensByReferenceInput
LensByReferenceInput,
LensUnwrapMetaInfo
>('lens', jest.fn(), core.i18n.Context, core.notifications.toasts, options);
service.unwrapAttributes = jest.fn((input: LensByValueInput | LensByReferenceInput) => {
return Promise.resolve({
...document,
sharingSavedObjectProps: {
outcome: 'exactMatch',
attributes: {
...document,
},
metaInfo: {
sharingSavedObjectProps: {
outcome: 'exactMatch',
},
},
} as ResolvedLensSavedObjectAttributes);
} as LensUnwrapResult);
});
service.wrapAttributes = jest.fn();
return service;
Expand All @@ -94,9 +102,10 @@ describe('embeddable', () => {
let trigger: { exec: jest.Mock };
let basePath: IBasePath;
let attributeService: AttributeService<
ResolvedLensSavedObjectAttributes,
LensSavedObjectAttributes,
LensByValueInput,
LensByReferenceInput
LensByReferenceInput,
LensUnwrapMetaInfo
>;

beforeEach(() => {
Expand Down Expand Up @@ -241,13 +250,17 @@ describe('embeddable', () => {
attributeService.unwrapAttributes = jest.fn(
(input: LensByValueInput | LensByReferenceInput) => {
return Promise.resolve({
...savedVis,
sharingSavedObjectProps: {
outcome: 'conflict',
sourceId: '1',
aliasTargetId: '2',
attributes: {
...savedVis,
},
metaInfo: {
sharingSavedObjectProps: {
outcome: 'conflict',
sourceId: '1',
aliasTargetId: '2',
},
},
} as ResolvedLensSavedObjectAttributes);
} as LensUnwrapResult);
}
);
const embeddable = new Embeddable(
Expand Down
Loading

0 comments on commit 9f302fc

Please sign in to comment.