Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.0] [Dashboard] Move Sharing Saved Object Props into Meta Object (#119913) #120176

Merged
merged 1 commit into from
Dec 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 { Query, TimeRange, Filter, IndexPatternsContract } from 'src/plugins/data/public';
Expand Down Expand Up @@ -50,9 +51,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 @@ -69,17 +72,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 @@ -92,9 +100,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 @@ -233,13 +242,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