mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Co-authored-by: Anton Dosov <dosantappdev@gmail.com> Co-authored-by: Marta Bondyra <marta.bondyra@gmail.com> # Conflicts: # x-pack/plugins/lens/public/embeddable/embeddable.tsx
This commit is contained in:
parent
5a16e3e93a
commit
a55ba0a093
17 changed files with 262 additions and 164 deletions
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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';
|
||||
|
@ -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 };
|
||||
});
|
||||
|
@ -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 () => {
|
||||
|
@ -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' },
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -29,13 +29,28 @@ 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<
|
||||
|
@ -43,7 +58,8 @@ export class AttributeService<
|
|||
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,
|
||||
|
@ -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) {
|
||||
|
@ -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(
|
||||
|
@ -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 (
|
||||
|
|
|
@ -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<{
|
||||
|
|
|
@ -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>);
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
@ -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> => {
|
||||
|
@ -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,
|
||||
},
|
||||
} as ResolvedLensSavedObjectAttributes);
|
||||
metaInfo: {
|
||||
sharingSavedObjectProps: {
|
||||
outcome: 'exactMatch',
|
||||
},
|
||||
},
|
||||
} as LensUnwrapResult);
|
||||
});
|
||||
service.wrapAttributes = jest.fn();
|
||||
return service;
|
||||
|
@ -92,9 +100,10 @@ describe('embeddable', () => {
|
|||
let trigger: { exec: jest.Mock };
|
||||
let basePath: IBasePath;
|
||||
let attributeService: AttributeService<
|
||||
ResolvedLensSavedObjectAttributes,
|
||||
LensSavedObjectAttributes,
|
||||
LensByValueInput,
|
||||
LensByReferenceInput
|
||||
LensByReferenceInput,
|
||||
LensUnwrapMetaInfo
|
||||
>;
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -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,
|
||||
},
|
||||
} as ResolvedLensSavedObjectAttributes);
|
||||
metaInfo: {
|
||||
sharingSavedObjectProps: {
|
||||
outcome: 'conflict',
|
||||
sourceId: '1',
|
||||
aliasTargetId: '2',
|
||||
},
|
||||
},
|
||||
} as LensUnwrapResult);
|
||||
}
|
||||
);
|
||||
const embeddable = new Embeddable(
|
||||
|
|
|
@ -63,10 +63,16 @@ import { SharingSavedObjectProps } from '../types';
|
|||
import type { SpacesPluginStart } from '../../../spaces/public';
|
||||
|
||||
export type LensSavedObjectAttributes = Omit<Document, 'savedObjectId' | 'type'>;
|
||||
export interface ResolvedLensSavedObjectAttributes extends LensSavedObjectAttributes {
|
||||
|
||||
export interface LensUnwrapMetaInfo {
|
||||
sharingSavedObjectProps?: SharingSavedObjectProps;
|
||||
}
|
||||
|
||||
export interface LensUnwrapResult {
|
||||
attributes: LensSavedObjectAttributes;
|
||||
metaInfo?: LensUnwrapMetaInfo;
|
||||
}
|
||||
|
||||
interface LensBaseEmbeddableInput extends EmbeddableInput {
|
||||
filters?: Filter[];
|
||||
query?: Query;
|
||||
|
@ -82,7 +88,7 @@ interface LensBaseEmbeddableInput extends EmbeddableInput {
|
|||
}
|
||||
|
||||
export type LensByValueInput = {
|
||||
attributes: ResolvedLensSavedObjectAttributes;
|
||||
attributes: LensSavedObjectAttributes;
|
||||
} & LensBaseEmbeddableInput;
|
||||
|
||||
export type LensByReferenceInput = SavedObjectEmbeddableInput & LensBaseEmbeddableInput;
|
||||
|
@ -260,28 +266,14 @@ export class Embeddable
|
|||
return this.lensInspector.adapters;
|
||||
}
|
||||
|
||||
async initializeSavedVis(input: LensEmbeddableInput) {
|
||||
const attrs: ResolvedLensSavedObjectAttributes | false = await this.deps.attributeService
|
||||
.unwrapAttributes(input)
|
||||
.catch((e: Error) => {
|
||||
this.onFatalError(e);
|
||||
return false;
|
||||
});
|
||||
if (!attrs || this.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
private maybeAddConflictError(
|
||||
errors?: ErrorMessage[],
|
||||
sharingSavedObjectProps?: SharingSavedObjectProps
|
||||
) {
|
||||
const ret = [...(errors || [])];
|
||||
|
||||
const { sharingSavedObjectProps, ...attributes } = attrs;
|
||||
|
||||
this.savedVis = {
|
||||
...attributes,
|
||||
type: this.type,
|
||||
savedObjectId: (input as LensByReferenceInput)?.savedObjectId,
|
||||
};
|
||||
const { ast, errors } = await this.deps.documentToExpression(this.savedVis);
|
||||
this.errors = errors;
|
||||
if (sharingSavedObjectProps?.outcome === 'conflict' && this.deps.spaces) {
|
||||
const conflictError = {
|
||||
if (sharingSavedObjectProps?.outcome === 'conflict' && !!this.deps.spaces) {
|
||||
ret.push({
|
||||
shortMessage: i18n.translate('xpack.lens.embeddable.legacyURLConflict.shortMessage', {
|
||||
defaultMessage: `You've encountered a URL conflict`,
|
||||
}),
|
||||
|
@ -291,9 +283,32 @@ export class Embeddable
|
|||
sourceId={sharingSavedObjectProps.sourceId!}
|
||||
/>
|
||||
),
|
||||
};
|
||||
this.errors = this.errors ? [...this.errors, conflictError] : [conflictError];
|
||||
});
|
||||
}
|
||||
|
||||
return ret?.length ? ret : undefined;
|
||||
}
|
||||
|
||||
async initializeSavedVis(input: LensEmbeddableInput) {
|
||||
const unwrapResult: LensUnwrapResult | false = await this.deps.attributeService
|
||||
.unwrapAttributes(input)
|
||||
.catch((e: Error) => {
|
||||
this.onFatalError(e);
|
||||
return false;
|
||||
});
|
||||
if (!unwrapResult || this.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { metaInfo, attributes } = unwrapResult;
|
||||
|
||||
this.savedVis = {
|
||||
...attributes,
|
||||
type: this.type,
|
||||
savedObjectId: (input as LensByReferenceInput)?.savedObjectId,
|
||||
};
|
||||
const { ast, errors } = await this.deps.documentToExpression(this.savedVis);
|
||||
this.errors = this.maybeAddConflictError(errors, metaInfo?.sharingSavedObjectProps);
|
||||
this.expression = ast ? toExpression(ast) : null;
|
||||
if (this.errors) {
|
||||
this.logError('validation');
|
||||
|
|
|
@ -9,8 +9,10 @@ import type { CoreStart } from '../../../../src/core/public';
|
|||
import type { LensPluginStartDependencies } from './plugin';
|
||||
import type { AttributeService } from '../../../../src/plugins/embeddable/public';
|
||||
import type {
|
||||
ResolvedLensSavedObjectAttributes,
|
||||
LensSavedObjectAttributes,
|
||||
LensByValueInput,
|
||||
LensUnwrapMetaInfo,
|
||||
LensUnwrapResult,
|
||||
LensByReferenceInput,
|
||||
} from './embeddable/embeddable';
|
||||
import { SavedObjectIndexStore } from './persistence';
|
||||
|
@ -18,9 +20,10 @@ import { checkForDuplicateTitle, OnSaveProps } from '../../../../src/plugins/sav
|
|||
import { DOC_TYPE } from '../common/constants';
|
||||
|
||||
export type LensAttributeService = AttributeService<
|
||||
ResolvedLensSavedObjectAttributes,
|
||||
LensSavedObjectAttributes,
|
||||
LensByValueInput,
|
||||
LensByReferenceInput
|
||||
LensByReferenceInput,
|
||||
LensUnwrapMetaInfo
|
||||
>;
|
||||
|
||||
export function getLensAttributeService(
|
||||
|
@ -29,20 +32,20 @@ export function getLensAttributeService(
|
|||
): LensAttributeService {
|
||||
const savedObjectStore = new SavedObjectIndexStore(core.savedObjects.client);
|
||||
return startDependencies.embeddable.getAttributeService<
|
||||
ResolvedLensSavedObjectAttributes,
|
||||
LensSavedObjectAttributes,
|
||||
LensByValueInput,
|
||||
LensByReferenceInput
|
||||
LensByReferenceInput,
|
||||
LensUnwrapMetaInfo
|
||||
>(DOC_TYPE, {
|
||||
saveMethod: async (attributes: ResolvedLensSavedObjectAttributes, savedObjectId?: string) => {
|
||||
const { sharingSavedObjectProps, ...attributesToSave } = attributes;
|
||||
saveMethod: async (attributes: LensSavedObjectAttributes, savedObjectId?: string) => {
|
||||
const savedDoc = await savedObjectStore.save({
|
||||
...attributesToSave,
|
||||
...attributes,
|
||||
savedObjectId,
|
||||
type: DOC_TYPE,
|
||||
});
|
||||
return { id: savedDoc.savedObjectId };
|
||||
},
|
||||
unwrapMethod: async (savedObjectId: string): Promise<ResolvedLensSavedObjectAttributes> => {
|
||||
unwrapMethod: async (savedObjectId: string): Promise<LensUnwrapResult> => {
|
||||
const {
|
||||
saved_object: savedObject,
|
||||
outcome,
|
||||
|
@ -61,8 +64,12 @@ export function getLensAttributeService(
|
|||
};
|
||||
|
||||
return {
|
||||
sharingSavedObjectProps,
|
||||
...document,
|
||||
attributes: {
|
||||
...document,
|
||||
},
|
||||
metaInfo: {
|
||||
sharingSavedObjectProps,
|
||||
},
|
||||
};
|
||||
},
|
||||
checkForDuplicateTitle: (props: OnSaveProps) => {
|
||||
|
|
|
@ -18,7 +18,8 @@ import { dashboardPluginMock } from '../../../../../src/plugins/dashboard/public
|
|||
import type {
|
||||
LensByValueInput,
|
||||
LensByReferenceInput,
|
||||
ResolvedLensSavedObjectAttributes,
|
||||
LensSavedObjectAttributes,
|
||||
LensUnwrapMetaInfo,
|
||||
} from '../embeddable/embeddable';
|
||||
import {
|
||||
mockAttributeService,
|
||||
|
@ -49,7 +50,9 @@ export const defaultDoc = {
|
|||
} as unknown as Document;
|
||||
|
||||
export const exactMatchDoc = {
|
||||
...defaultDoc,
|
||||
attributes: {
|
||||
...defaultDoc,
|
||||
},
|
||||
sharingSavedObjectProps: {
|
||||
outcome: 'exactMatch',
|
||||
},
|
||||
|
@ -83,9 +86,10 @@ export function makeDefaultServices(
|
|||
|
||||
function makeAttributeService(): LensAttributeService {
|
||||
const attributeServiceMock = mockAttributeService<
|
||||
ResolvedLensSavedObjectAttributes,
|
||||
LensSavedObjectAttributes,
|
||||
LensByValueInput,
|
||||
LensByReferenceInput
|
||||
LensByReferenceInput,
|
||||
LensUnwrapMetaInfo
|
||||
>(
|
||||
DOC_TYPE,
|
||||
{
|
||||
|
|
|
@ -21,36 +21,38 @@ Object {
|
|||
"isSaveable": true,
|
||||
"persistedDoc": Object {
|
||||
"exactMatchDoc": Object {
|
||||
"expression": "definitely a valid expression",
|
||||
"references": Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
"name": "index-pattern-0",
|
||||
"type": "index-pattern",
|
||||
"attributes": Object {
|
||||
"expression": "definitely a valid expression",
|
||||
"references": Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
"name": "index-pattern-0",
|
||||
"type": "index-pattern",
|
||||
},
|
||||
],
|
||||
"savedObjectId": "1234",
|
||||
"state": Object {
|
||||
"datasourceStates": Object {
|
||||
"testDatasource": "datasource",
|
||||
},
|
||||
"filters": Array [
|
||||
Object {
|
||||
"query": Object {
|
||||
"match_phrase": Object {
|
||||
"src": "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"query": "kuery",
|
||||
"visualization": Object {},
|
||||
},
|
||||
],
|
||||
"savedObjectId": "1234",
|
||||
"title": "An extremely cool default document!",
|
||||
"visualizationType": "testVis",
|
||||
},
|
||||
"sharingSavedObjectProps": Object {
|
||||
"outcome": "exactMatch",
|
||||
},
|
||||
"state": Object {
|
||||
"datasourceStates": Object {
|
||||
"testDatasource": "datasource",
|
||||
},
|
||||
"filters": Array [
|
||||
Object {
|
||||
"query": Object {
|
||||
"match_phrase": Object {
|
||||
"src": "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"query": "kuery",
|
||||
"visualization": Object {},
|
||||
},
|
||||
"title": "An extremely cool default document!",
|
||||
"visualizationType": "testVis",
|
||||
},
|
||||
"references": Array [],
|
||||
"savedObjectId": "1234",
|
||||
|
|
|
@ -45,7 +45,8 @@ export const getPersisted = async ({
|
|||
},
|
||||
};
|
||||
}
|
||||
const { sharingSavedObjectProps, ...attributes } = result;
|
||||
const { metaInfo, attributes } = result;
|
||||
const sharingSavedObjectProps = metaInfo?.sharingSavedObjectProps;
|
||||
if (spaces && sharingSavedObjectProps?.outcome === 'aliasMatch' && history) {
|
||||
// We found this object by a legacy URL alias from its old ID; redirect the user to the page with its new ID, preserving any URL hash
|
||||
const newObjectId = sharingSavedObjectProps?.aliasTargetId; // This is always defined if outcome === 'aliasMatch'
|
||||
|
|
|
@ -64,19 +64,21 @@ describe('Initializing the store', () => {
|
|||
const datasource2State = { datasource2: '' };
|
||||
const services = makeDefaultServices();
|
||||
services.attributeService.unwrapAttributes = jest.fn().mockResolvedValue({
|
||||
exactMatchDoc,
|
||||
visualizationType: 'testVis',
|
||||
title: '',
|
||||
state: {
|
||||
datasourceStates: {
|
||||
testDatasource: datasource1State,
|
||||
testDatasource2: datasource2State,
|
||||
attributes: {
|
||||
exactMatchDoc,
|
||||
visualizationType: 'testVis',
|
||||
title: '',
|
||||
state: {
|
||||
datasourceStates: {
|
||||
testDatasource: datasource1State,
|
||||
testDatasource2: datasource2State,
|
||||
},
|
||||
visualization: {},
|
||||
query: { query: '', language: 'lucene' },
|
||||
filters: [],
|
||||
},
|
||||
visualization: {},
|
||||
query: { query: '', language: 'lucene' },
|
||||
filters: [],
|
||||
references: [],
|
||||
},
|
||||
references: [],
|
||||
});
|
||||
|
||||
const storeDeps = mockStoreDeps({
|
||||
|
@ -281,10 +283,14 @@ describe('Initializing the store', () => {
|
|||
it('redirects if saved object is an aliasMatch', async () => {
|
||||
const { store, deps } = makeLensStore({ preloadedState });
|
||||
deps.lensServices.attributeService.unwrapAttributes = jest.fn().mockResolvedValue({
|
||||
...defaultDoc,
|
||||
sharingSavedObjectProps: {
|
||||
outcome: 'aliasMatch',
|
||||
aliasTargetId: 'id2',
|
||||
attributes: {
|
||||
...defaultDoc,
|
||||
},
|
||||
metaInfo: {
|
||||
sharingSavedObjectProps: {
|
||||
outcome: 'aliasMatch',
|
||||
aliasTargetId: 'id2',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -22,11 +22,18 @@ export interface SharingSavedObjectProps {
|
|||
}
|
||||
|
||||
type MapDoc = MapSavedObjectAttributes & {
|
||||
sharingSavedObjectProps?: SharingSavedObjectProps;
|
||||
references?: SavedObjectReference[];
|
||||
};
|
||||
export interface MapUnwrapMetaInfo {
|
||||
sharingSavedObjectProps: SharingSavedObjectProps;
|
||||
}
|
||||
|
||||
export type MapAttributeService = AttributeService<MapDoc, MapByValueInput, MapByReferenceInput>;
|
||||
export type MapAttributeService = AttributeService<
|
||||
MapDoc,
|
||||
MapByValueInput,
|
||||
MapByReferenceInput,
|
||||
MapUnwrapMetaInfo
|
||||
>;
|
||||
|
||||
let mapAttributeService: MapAttributeService | null = null;
|
||||
|
||||
|
@ -38,7 +45,8 @@ export function getMapAttributeService(): MapAttributeService {
|
|||
mapAttributeService = getEmbeddableService().getAttributeService<
|
||||
MapDoc,
|
||||
MapByValueInput,
|
||||
MapByReferenceInput
|
||||
MapByReferenceInput,
|
||||
MapUnwrapMetaInfo
|
||||
>(MAP_SAVED_OBJECT_TYPE, {
|
||||
saveMethod: async (attributes: MapDoc, savedObjectId?: string) => {
|
||||
// AttributeService "attributes" contains "references" as a child.
|
||||
|
@ -66,7 +74,12 @@ export function getMapAttributeService(): MapAttributeService {
|
|||
));
|
||||
return { id: savedObject.id };
|
||||
},
|
||||
unwrapMethod: async (savedObjectId: string): Promise<MapDoc> => {
|
||||
unwrapMethod: async (
|
||||
savedObjectId: string
|
||||
): Promise<{
|
||||
attributes: MapDoc;
|
||||
metaInfo: MapUnwrapMetaInfo;
|
||||
}> => {
|
||||
const {
|
||||
saved_object: savedObject,
|
||||
outcome,
|
||||
|
@ -82,12 +95,16 @@ export function getMapAttributeService(): MapAttributeService {
|
|||
|
||||
const { attributes } = injectReferences(savedObject);
|
||||
return {
|
||||
...attributes,
|
||||
references: savedObject.references,
|
||||
sharingSavedObjectProps: {
|
||||
aliasTargetId,
|
||||
outcome,
|
||||
sourceId: savedObjectId,
|
||||
attributes: {
|
||||
...attributes,
|
||||
references: savedObject.references,
|
||||
},
|
||||
metaInfo: {
|
||||
sharingSavedObjectProps: {
|
||||
aliasTargetId,
|
||||
outcome,
|
||||
sourceId: savedObjectId,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
|
|
|
@ -103,11 +103,13 @@ export class SavedMap {
|
|||
description: '',
|
||||
};
|
||||
} else {
|
||||
const doc = await getMapAttributeService().unwrapAttributes(this._mapEmbeddableInput);
|
||||
const { references, sharingSavedObjectProps, ...savedObjectAttributes } = doc;
|
||||
const { attributes: doc, metaInfo } = await getMapAttributeService().unwrapAttributes(
|
||||
this._mapEmbeddableInput
|
||||
);
|
||||
const { references, ...savedObjectAttributes } = doc;
|
||||
this._attributes = savedObjectAttributes;
|
||||
if (sharingSavedObjectProps) {
|
||||
this._sharingSavedObjectProps = sharingSavedObjectProps;
|
||||
if (metaInfo?.sharingSavedObjectProps) {
|
||||
this._sharingSavedObjectProps = metaInfo.sharingSavedObjectProps;
|
||||
}
|
||||
const savedObjectsTagging = getSavedObjectsTagging();
|
||||
if (savedObjectsTagging && references && references.length) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue