kibana/x-pack/plugins/lens/public/plugin.ts
Pierre Gayvallet d4b2a5145a
SavedObjects tagging MVP (#79096)
* create xpack plugin skeleton, start to implement management section

* add tag creation modal

* first implementation of the tags table

* use InMemoryTable

* add edit modal and delete action

* update plugin list

* add tag list, fix types

* add capabilities check on client-side

* add tag combo box component

* add missing i18n keys

* fix privilege FTR tests

* add base structure for FTR tests

* fix feature ftr test

* use string literals for i18n

* create savedObjectsTaggingOss plugin, move API types to oss plugin, start to wire to SO management page.

* update plugin list

* fix types

* allow to use `_find` with multiple references

* add FTR test for _find API on references fields

* add _find integration tests

* update generated doc

* start to implement tag filtering on SO management section

* update generated docs

* wire tagging API to dashboard listing page

* fix i18n namespace

* fix type & tests

* update dashboard listing snapshots

* adapt FTR listingTable service to search for parsable queries

* wite tagging API to visualize listing

* update tagging plugin limits

* add server-side and client-side validation for tag create/edit

* rename title field to name

* fix types

* fix types bis

* add removeReferencesTo API to SOR/SOC

* update generated doc

* add server-side unit test for `savedObjectsTagging` plugin

* move tagging API types to its own file

* add savedObjectsTaggingOss mock

* add tags_cache tests

* add tests for client-side tag client

* extract uiApi to distinct files

* various API improvements

* add more tests

* add link between tag and so management sections + add connection counts

* add base functional test suite for tagging

* add more FTR tests

* improve feature control func test

* update codeowners

* update generated doc

* fix access to proxy modal

* adapt SO save modal to allow to add tag field

* add SO decorator registry and tag implementation

* add unit tests for SO tag decorator

* add functional tests for visualize integration

* add tag SO read permission for vis/dash feature

* add RBAC api integ tests

* add API integration tests

* add test for getTagConnectionsUrl

* add SOM test suite

* add dashboard integration suite

* remove test line

* add missing unit tests

* improve API types doc

* fix create modal save button label

* remove console.log

* improve doc

* self review

* add refresh interval for tag cache

* improve page object doc

* minor cleanup

* address review comments

* small layout fixes

* add initial focus

* use lazy accessor for tag request handler context

* adapt SOM export and export route to handle references

* remove icon from feature config due to master changes

* fix SO table tests

* update generated docs

* sort tags by name in filter dropdown and listing component

* wire SO tagging to dashboard save modal

* fix types

* - add 'create tag' action in tag selector
- add notifications on update/create/delete from management
- delete modal wording

* add description max length validation

* remove real-time validation

* fix i18n bundle id

* update expected size of savedObjectsTagging plugin

* use own useIfMounted

* update limit again, contract components cannot be lazy loaded atm.

* math is hard

* remove single usage of lodash for bundle size

* add async imports for create/edit modal

* add FTR test for 'create tag' action from tag selector

* allow 'create new' option to prepopulate name field

* extract savedObjectToTag

* add advancedSettings read user for security api_integ suite

* add audit login for security client wrapper

* use import type when possible

* wire SO tagging to lens visualization

* fix lens jest test

* Fix `create tag` option being selected when closing the selector dropdown

* add sorting to tag column from getTableColumnDef

* address some of restrry comments

* rename tag selector's setSelected option to onTagsSelected

* fix audit logging even type for saved_object_remove_references

* update plugin size limit to current size

* adapt maxlength validation wording

* remove selection column until we have batch action menu

* remove connections link when user lack read privilege to savedObjectManagement

* forbid registering multiple SO decorators with the same priority

* add so decorator test

* extract getTagFindReferences and create API mock

* update audit-logging ascidoc

* doc nit

* throw conflict error if update returns any failure

* use refresh=true as default

* wording nits

* export: rename `references` to `hasReference`

* update generated doc

* set description max length to 100

* do not initialize tag cache on anonymous pages

* split fetchObjectsToExport into two distinct functions

* change tag client `delete` call order

* tsdoc nits

* more nits

* add README for oss plugin

* add oss plugin start tests

* SavedObject.find: rename `references` to `hasReference`

* change section description label

* remove url prefix constants

* last nits and comments

* update generated doc
2020-11-03 10:33:18 +01:00

187 lines
6.7 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { AppMountParameters, CoreSetup, CoreStart } from 'kibana/public';
import { DataPublicPluginSetup, DataPublicPluginStart } from 'src/plugins/data/public';
import { EmbeddableSetup, EmbeddableStart } from 'src/plugins/embeddable/public';
import { DashboardStart } from 'src/plugins/dashboard/public';
import { ExpressionsSetup, ExpressionsStart } from 'src/plugins/expressions/public';
import { VisualizationsSetup } from 'src/plugins/visualizations/public';
import { NavigationPublicPluginStart } from 'src/plugins/navigation/public';
import { UrlForwardingSetup } from 'src/plugins/url_forwarding/public';
import { GlobalSearchPluginSetup } from '../../global_search/public';
import { ChartsPluginSetup } from '../../../../src/plugins/charts/public';
import { EditorFrameService } from './editor_frame_service';
import {
IndexPatternDatasource,
IndexPatternDatasourceSetupPlugins,
} from './indexpattern_datasource';
import { XyVisualization, XyVisualizationPluginSetupPlugins } from './xy_visualization';
import { MetricVisualization, MetricVisualizationPluginSetupPlugins } from './metric_visualization';
import {
DatatableVisualization,
DatatableVisualizationPluginSetupPlugins,
} from './datatable_visualization';
import { PieVisualization, PieVisualizationPluginSetupPlugins } from './pie_visualization';
import { AppNavLinkStatus } from '../../../../src/core/public';
import type { SavedObjectTaggingPluginStart } from '../../saved_objects_tagging/public';
import {
UiActionsStart,
ACTION_VISUALIZE_FIELD,
VISUALIZE_FIELD_TRIGGER,
} from '../../../../src/plugins/ui_actions/public';
import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../common';
import { EditorFrameStart } from './types';
import { getLensAliasConfig } from './vis_type_alias';
import { visualizeFieldAction } from './trigger_actions/visualize_field_actions';
import { getSearchProvider } from './search_provider';
import { LensAttributeService } from './lens_attribute_service';
export interface LensPluginSetupDependencies {
urlForwarding: UrlForwardingSetup;
expressions: ExpressionsSetup;
data: DataPublicPluginSetup;
embeddable?: EmbeddableSetup;
visualizations: VisualizationsSetup;
charts: ChartsPluginSetup;
globalSearch?: GlobalSearchPluginSetup;
}
export interface LensPluginStartDependencies {
data: DataPublicPluginStart;
expressions: ExpressionsStart;
navigation: NavigationPublicPluginStart;
uiActions: UiActionsStart;
dashboard: DashboardStart;
embeddable: EmbeddableStart;
savedObjectsTagging?: SavedObjectTaggingPluginStart;
}
export class LensPlugin {
private datatableVisualization: DatatableVisualization;
private editorFrameService: EditorFrameService;
private createEditorFrame: EditorFrameStart['createInstance'] | null = null;
private attributeService: (() => Promise<LensAttributeService>) | null = null;
private indexpatternDatasource: IndexPatternDatasource;
private xyVisualization: XyVisualization;
private metricVisualization: MetricVisualization;
private pieVisualization: PieVisualization;
private stopReportManager?: () => void;
constructor() {
this.datatableVisualization = new DatatableVisualization();
this.editorFrameService = new EditorFrameService();
this.indexpatternDatasource = new IndexPatternDatasource();
this.xyVisualization = new XyVisualization();
this.metricVisualization = new MetricVisualization();
this.pieVisualization = new PieVisualization();
}
setup(
core: CoreSetup<LensPluginStartDependencies, void>,
{
urlForwarding,
expressions,
data,
embeddable,
visualizations,
charts,
globalSearch,
}: LensPluginSetupDependencies
) {
this.attributeService = async () => {
const { getLensAttributeService } = await import('./async_services');
const [coreStart, startDependencies] = await core.getStartServices();
return getLensAttributeService(coreStart, startDependencies);
};
const editorFrameSetupInterface = this.editorFrameService.setup(
core,
{
data,
embeddable,
expressions,
},
this.attributeService
);
const dependencies: IndexPatternDatasourceSetupPlugins &
XyVisualizationPluginSetupPlugins &
DatatableVisualizationPluginSetupPlugins &
MetricVisualizationPluginSetupPlugins &
PieVisualizationPluginSetupPlugins = {
expressions,
data,
charts,
editorFrame: editorFrameSetupInterface,
formatFactory: core
.getStartServices()
.then(([_, { data: dataStart }]) => dataStart.fieldFormats.deserialize),
};
this.indexpatternDatasource.setup(core, dependencies);
this.xyVisualization.setup(core, dependencies);
this.datatableVisualization.setup(core, dependencies);
this.metricVisualization.setup(core, dependencies);
this.pieVisualization.setup(core, dependencies);
visualizations.registerAlias(getLensAliasConfig());
const getByValueFeatureFlag = async () => {
const [, deps] = await core.getStartServices();
return deps.dashboard.dashboardFeatureFlagConfig;
};
core.application.register({
id: 'lens',
title: NOT_INTERNATIONALIZED_PRODUCT_NAME,
navLinkStatus: AppNavLinkStatus.hidden,
mount: async (params: AppMountParameters) => {
const { mountApp, stopReportManager } = await import('./async_services');
this.stopReportManager = stopReportManager;
return mountApp(core, params, {
createEditorFrame: this.createEditorFrame!,
attributeService: this.attributeService!,
getByValueFeatureFlag,
});
},
});
if (globalSearch) {
globalSearch.registerResultProvider(
getSearchProvider(
core.getStartServices().then(
([
{
application: { capabilities },
},
]) => capabilities
)
)
);
}
urlForwarding.forwardApp('lens', 'lens');
}
start(core: CoreStart, startDependencies: LensPluginStartDependencies) {
this.createEditorFrame = this.editorFrameService.start(core, startDependencies).createInstance;
// unregisters the Visualize action and registers the lens one
if (startDependencies.uiActions.hasAction(ACTION_VISUALIZE_FIELD)) {
startDependencies.uiActions.unregisterAction(ACTION_VISUALIZE_FIELD);
}
startDependencies.uiActions.addTriggerAction(
VISUALIZE_FIELD_TRIGGER,
visualizeFieldAction(core.application)
);
}
stop() {
if (this.stopReportManager) {
this.stopReportManager();
}
}
}