Skip to content

Commit

Permalink
[Visualization] Get rid of saved object loader and use savedObjectCli…
Browse files Browse the repository at this point in the history
…ent resolve (#113121)

* First step: create saved_visualize_utils, starting use new get/save methods

* Use new util methods in embeddable

* move findListItem in utils

* some clean up

* clean up

* Some fixes

* Fix saved object tags

* Some types fixes

* Fix unit tests

* Clean up code

* Add unit tests for new utils

* Fix lint

* Fix tagging

* Add unit tests

* Some fixes

* Clean up code

* Fix lint

* Fix types

* put new methods in start contract

* Fix imports

* Fix lint

* Fix comments

* Fix lint

* Fix CI

* use local url instead of full path

* Fix unit test

* Some clean up

* Fix nits

* fix types

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
VladLasitsa and kibanamachine authored Oct 11, 2021
1 parent 2dece3d commit 41c813b
Show file tree
Hide file tree
Showing 31 changed files with 1,291 additions and 124 deletions.
2 changes: 1 addition & 1 deletion src/plugins/visualizations/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"inspector",
"savedObjects"
],
"optionalPlugins": ["usageCollection"],
"optionalPlugins": ["usageCollection", "spaces", "savedObjectsTaggingOss"],
"requiredBundles": ["kibanaUtils", "discover"],
"extraPublicDirs": ["common/constants", "common/prepare_log_table", "common/expression_functions"],
"owner": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,10 @@ import {
AttributeService,
} from '../../../../plugins/embeddable/public';
import { DisabledLabEmbeddable } from './disabled_lab_embeddable';
import {
getSavedVisualizationsLoader,
getUISettings,
getHttp,
getTimeFilter,
getCapabilities,
} from '../services';
import { getUISettings, getHttp, getTimeFilter, getCapabilities } from '../services';
import { urlFor } from '../utils/saved_visualize_utils';
import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory';
import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants';
import { SavedVisualizationsLoader } from '../saved_visualizations';
import { IndexPattern } from '../../../data/public';
import { createVisualizeEmbeddableAsync } from './visualize_embeddable_async';

Expand All @@ -38,24 +32,19 @@ export const createVisEmbeddableFromObject =
async (
vis: Vis,
input: Partial<VisualizeInput> & { id: string },
savedVisualizationsLoader?: SavedVisualizationsLoader,
attributeService?: AttributeService<
VisualizeSavedObjectAttributes,
VisualizeByValueInput,
VisualizeByReferenceInput
>,
parent?: IContainer
): Promise<VisualizeEmbeddable | ErrorEmbeddable | DisabledLabEmbeddable> => {
const savedVisualizations = getSavedVisualizationsLoader();

try {
const visId = vis.id as string;

const editPath = visId ? savedVisualizations.urlFor(visId) : '#/edit_by_value';
const editPath = visId ? urlFor(visId) : '#/edit_by_value';

const editUrl = visId
? getHttp().basePath.prepend(`/app/visualize${savedVisualizations.urlFor(visId)}`)
: '';
const editUrl = visId ? getHttp().basePath.prepend(`/app/visualize${urlFor(visId)}`) : '';
const isLabsEnabled = getUISettings().get<boolean>(VISUALIZE_ENABLE_LABS_SETTING);

if (!isLabsEnabled && vis.type.stage === 'experimental') {
Expand Down Expand Up @@ -87,7 +76,6 @@ export const createVisEmbeddableFromObject =
},
input,
attributeService,
savedVisualizationsLoader,
parent
);
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { getExpressions, getUiActions } from '../services';
import { VIS_EVENT_TO_TRIGGER } from './events';
import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory';
import { SavedObjectAttributes } from '../../../../core/types';
import { SavedVisualizationsLoader } from '../saved_visualizations';
import { getSavedVisualization } from '../utils/saved_visualize_utils';
import { VisSavedObject } from '../types';
import { toExpressionAst } from './to_ast';

Expand Down Expand Up @@ -108,7 +108,6 @@ export class VisualizeEmbeddable
VisualizeByValueInput,
VisualizeByReferenceInput
>;
private savedVisualizationsLoader?: SavedVisualizationsLoader;

constructor(
timefilter: TimefilterContract,
Expand All @@ -119,7 +118,6 @@ export class VisualizeEmbeddable
VisualizeByValueInput,
VisualizeByReferenceInput
>,
savedVisualizationsLoader?: SavedVisualizationsLoader,
parent?: IContainer
) {
super(
Expand All @@ -144,7 +142,6 @@ export class VisualizeEmbeddable
this.vis.uiState.on('change', this.uiStateChangeHandler);
this.vis.uiState.on('reload', this.reload);
this.attributeService = attributeService;
this.savedVisualizationsLoader = savedVisualizationsLoader;

if (this.attributeService) {
const isByValue = !this.inputIsRefType(initialInput);
Expand Down Expand Up @@ -455,7 +452,15 @@ export class VisualizeEmbeddable
};

getInputAsRefType = async (): Promise<VisualizeByReferenceInput> => {
const savedVis = await this.savedVisualizationsLoader?.get({});
const { savedObjectsClient, data, spaces, savedObjectsTaggingOss } = await this.deps.start()
.plugins;
const savedVis = await getSavedVisualization({
savedObjectsClient,
search: data.search,
dataViews: data.dataViews,
spaces,
savedObjectsTagging: savedObjectsTaggingOss?.getTaggingApi(),
});
if (!savedVis) {
throw new Error('Error creating a saved vis object');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,20 @@ import type {
import { VISUALIZE_EMBEDDABLE_TYPE } from './constants';
import type { SerializedVis, Vis } from '../vis';
import { createVisAsync } from '../vis_async';
import {
getCapabilities,
getTypes,
getUISettings,
getSavedVisualizationsLoader,
} from '../services';
import { getCapabilities, getTypes, getUISettings } from '../services';
import { showNewVisModal } from '../wizard';
import { convertToSerializedVis } from '../saved_visualizations/_saved_vis';
import {
convertToSerializedVis,
getSavedVisualization,
saveVisualization,
getFullPath,
} from '../utils/saved_visualize_utils';
import {
extractControlsReferences,
extractTimeSeriesReferences,
injectTimeSeriesReferences,
injectControlsReferences,
} from '../saved_visualizations/saved_visualization_references';
} from '../utils/saved_visualization_references';
import { createVisEmbeddableFromObject } from './create_vis_embeddable_from_object';
import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants';
import { checkForDuplicateTitle } from '../../../saved_objects/public';
Expand All @@ -59,7 +59,15 @@ interface VisualizationAttributes extends SavedObjectAttributes {

export interface VisualizeEmbeddableFactoryDeps {
start: StartServicesGetter<
Pick<VisualizationsStartDeps, 'inspector' | 'embeddable' | 'savedObjectsClient'>
Pick<
VisualizationsStartDeps,
| 'inspector'
| 'embeddable'
| 'savedObjectsClient'
| 'data'
| 'savedObjectsTaggingOss'
| 'spaces'
>
>;
}

Expand Down Expand Up @@ -147,17 +155,36 @@ export class VisualizeEmbeddableFactory
input: Partial<VisualizeInput> & { id: string },
parent?: IContainer
): Promise<VisualizeEmbeddable | ErrorEmbeddable | DisabledLabEmbeddable> {
const savedVisualizations = getSavedVisualizationsLoader();
const startDeps = await this.deps.start();

try {
const savedObject = await savedVisualizations.get(savedObjectId);
const savedObject = await getSavedVisualization(
{
savedObjectsClient: startDeps.core.savedObjects.client,
search: startDeps.plugins.data.search,
dataViews: startDeps.plugins.data.dataViews,
spaces: startDeps.plugins.spaces,
savedObjectsTagging: startDeps.plugins.savedObjectsTaggingOss?.getTaggingApi(),
},
savedObjectId
);

if (savedObject.sharingSavedObjectProps?.outcome === 'conflict') {
return new ErrorEmbeddable(
i18n.translate('visualizations.embeddable.legacyURLConflict.errorMessage', {
defaultMessage: `This visualization has the same URL as a legacy alias. Disable the alias to resolve this error : {json}`,
values: { json: savedObject.sharingSavedObjectProps?.errorJSON },
}),
input,
parent
);
}
const visState = convertToSerializedVis(savedObject);
const vis = await createVisAsync(savedObject.visState.type, visState);

return createVisEmbeddableFromObject(this.deps)(
vis,
input,
savedVisualizations,
await this.getAttributeService(),
parent
);
Expand All @@ -173,11 +200,9 @@ export class VisualizeEmbeddableFactory
if (input.savedVis) {
const visState = input.savedVis;
const vis = await createVisAsync(visState.type, visState);
const savedVisualizations = getSavedVisualizationsLoader();
return createVisEmbeddableFromObject(this.deps)(
vis,
input,
savedVisualizations,
await this.getAttributeService(),
parent
);
Expand All @@ -201,9 +226,9 @@ export class VisualizeEmbeddableFactory
confirmOverwrite: false,
returnToOrigin: true,
isTitleDuplicateConfirmed: true,
copyOnSave: false,
};
savedVis.title = title;
savedVis.copyOnSave = false;
savedVis.description = '';
savedVis.searchSourceFields = visObj?.data.searchSource?.getSerializedFields();
const serializedVis = (visObj as unknown as Vis).serialize();
Expand All @@ -217,14 +242,20 @@ export class VisualizeEmbeddableFactory
if (visObj) {
savedVis.uiStateJSON = visObj?.uiState.toString();
}
const id = await savedVis.save(saveOptions);
const { core, plugins } = await this.deps.start();
const id = await saveVisualization(savedVis, saveOptions, {
savedObjectsClient: core.savedObjects.client,
overlays: core.overlays,
savedObjectsTagging: plugins.savedObjectsTaggingOss?.getTaggingApi(),
});
if (!id || id === '') {
throw new Error(
i18n.translate('visualizations.savingVisualizationFailed.errorMsg', {
defaultMessage: 'Saving a visualization failed',
})
);
}
core.chrome.recentlyAccessed.add(getFullPath(id), savedVis.title, String(id));
return { id };
} catch (error) {
throw error;
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/visualizations/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export {
VisToExpressionAst,
VisToExpressionAstParams,
VisEditorOptionsProps,
GetVisOptions,
} from './types';
export { VisualizationListItem, VisualizationStage } from './vis_types/vis_type_alias_registry';
export { VISUALIZE_ENABLE_LABS_SETTING } from '../common/constants';
Expand All @@ -49,3 +50,4 @@ export {
FakeParams,
HistogramParams,
} from '../common/expression_functions/xy_dimension';
export { urlFor, getFullPath } from './utils/saved_visualize_utils';
7 changes: 7 additions & 0 deletions src/plugins/visualizations/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { PluginInitializerContext } from '../../../core/public';
import { Schema, VisualizationsSetup, VisualizationsStart } from './';
import { Schemas } from './vis_types';
import { VisualizationsPlugin } from './plugin';
import { spacesPluginMock } from '../../../../x-pack/plugins/spaces/public/mocks';
import { coreMock, applicationServiceMock } from '../../../core/public/mocks';
import { embeddablePluginMock } from '../../../plugins/embeddable/public/mocks';
import { expressionsPluginMock } from '../../../plugins/expressions/public/mocks';
Expand All @@ -18,6 +19,7 @@ import { usageCollectionPluginMock } from '../../../plugins/usage_collection/pub
import { uiActionsPluginMock } from '../../../plugins/ui_actions/public/mocks';
import { inspectorPluginMock } from '../../../plugins/inspector/public/mocks';
import { savedObjectsPluginMock } from '../../../plugins/saved_objects/public/mocks';
import { savedObjectTaggingOssPluginMock } from '../../saved_objects_tagging_oss/public/mocks';

const createSetupContract = (): VisualizationsSetup => ({
createBaseVisualization: jest.fn(),
Expand All @@ -34,6 +36,9 @@ const createStartContract = (): VisualizationsStart => ({
savedVisualizationsLoader: {
get: jest.fn(),
} as any,
getSavedVisualization: jest.fn(),
saveVisualization: jest.fn(),
findListItems: jest.fn(),
showNewVisModal: jest.fn(),
createVis: jest.fn(),
convertFromSerializedVis: jest.fn(),
Expand Down Expand Up @@ -61,9 +66,11 @@ const createInstance = async () => {
uiActions: uiActionsPluginMock.createStartContract(),
application: applicationServiceMock.createStartContract(),
embeddable: embeddablePluginMock.createStartContract(),
spaces: spacesPluginMock.createStartContract(),
getAttributeService: jest.fn(),
savedObjectsClient: coreMock.createStart().savedObjects.client,
savedObjects: savedObjectsPluginMock.createStartContract(),
savedObjectsTaggingOss: savedObjectTaggingOssPluginMock.createStart(),
});

return {
Expand Down
Loading

0 comments on commit 41c813b

Please sign in to comment.