[Discover] Remove Angular from doc viewer (#109368)

* Remove angular from doc viewer

* Remove types

* Remove plugin_functional for angular doc_view, since testing angular is no longer necessary
This commit is contained in:
Matthias Wilhelm 2021-08-24 10:50:22 +02:00 committed by GitHub
parent e733b6ae0d
commit 42527e4188
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 4 additions and 220 deletions

View file

@ -1052,8 +1052,7 @@
"description": [],
"signature": [
"{ addDocView(docViewRaw: ComponentDocViewInput | ",
"RenderDocViewInput",
" | DirectiveDocViewInput | ",
"RenderDocViewInput |",
"DocViewInputFn",
"): void; }"
],
@ -1391,4 +1390,4 @@
],
"objects": []
}
}
}

View file

@ -1,85 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { auto, IController } from 'angular';
import React from 'react';
import { render } from 'react-dom';
import angular, { ICompileService } from 'angular';
import { DocViewRenderProps, AngularScope, AngularDirective } from './doc_views_types';
import { DocViewerError } from '../components/doc_viewer/doc_viewer_render_error';
/**
* Compiles and injects the give angular template into the given dom node
* returns a function to cleanup the injected angular element
*/
export async function injectAngularElement(
domNode: Element,
template: string,
scopeProps: DocViewRenderProps,
Controller: IController,
getInjector: () => Promise<auto.IInjectorService>
): Promise<() => void> {
const $injector = await getInjector();
const rootScope: AngularScope = $injector.get('$rootScope');
const $compile: ICompileService = $injector.get('$compile');
const newScope = Object.assign(rootScope.$new(), scopeProps);
if (typeof Controller === 'function') {
// when a controller is defined, expose the value it produces to the view as `$ctrl`
// see: https://docs.angularjs.org/api/ng/provider/$compileProvider#component
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(newScope as any).$ctrl = $injector.instantiate(Controller, {
$scope: newScope,
});
}
const $target = angular.element(domNode);
const $element = angular.element(template);
newScope.$apply(() => {
const linkFn = $compile($element);
$target.empty().append($element);
linkFn(newScope);
});
return () => {
newScope.$destroy();
};
}
/**
* Converts a given legacy angular directive to a render function
* for usage in a react component. Note that the rendering is async
*/
export function convertDirectiveToRenderFn(
directive: AngularDirective,
getInjector: () => Promise<auto.IInjectorService>
) {
return (domNode: Element, props: DocViewRenderProps) => {
let rejected = false;
const cleanupFnPromise = injectAngularElement(
domNode,
directive.template,
props,
directive.controller,
getInjector
);
cleanupFnPromise.catch((e) => {
rejected = true;
render(<DocViewerError error={e} />, domNode);
});
return () => {
if (!rejected) {
// for cleanup
// http://roubenmeschian.com/rubo/?p=51
cleanupFnPromise.then((cleanup) => cleanup());
}
};
};
}

View file

@ -6,33 +6,16 @@
* Side Public License, v 1.
*/
import { auto } from 'angular';
import { convertDirectiveToRenderFn } from './doc_views_helpers';
import { DocView, DocViewInput, ElasticSearchHit, DocViewInputFn } from './doc_views_types';
export class DocViewsRegistry {
private docViews: DocView[] = [];
private angularInjectorGetter: (() => Promise<auto.IInjectorService>) | null = null;
setAngularInjectorGetter = (injectorGetter: () => Promise<auto.IInjectorService>) => {
this.angularInjectorGetter = injectorGetter;
};
/**
* Extends and adds the given doc view to the registry array
*/
addDocView(docViewRaw: DocViewInput | DocViewInputFn) {
const docView = typeof docViewRaw === 'function' ? docViewRaw() : docViewRaw;
if (docView.directive) {
// convert angular directive to render function for backwards compatibility
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(docView.render as any) = convertDirectiveToRenderFn(docView.directive as any, () => {
if (!this.angularInjectorGetter) {
throw new Error('Angular was not initialized');
}
return this.angularInjectorGetter();
});
}
if (typeof docView.shouldShow !== 'function') {
docView.shouldShow = () => true;
}

View file

@ -7,17 +7,10 @@
*/
import { ComponentType } from 'react';
import { IScope } from 'angular';
import type { estypes } from '@elastic/elasticsearch';
import { IndexPattern } from '../../../../data/public';
export interface AngularDirective {
controller: (...injectedServices: unknown[]) => void;
template: string;
}
export type AngularScope = IScope;
export type ElasticSearchHit<T = unknown> = estypes.SearchHit<T>;
export interface FieldMapping {
@ -67,13 +60,7 @@ interface ComponentDocViewInput extends BaseDocViewInput {
directive?: undefined;
}
interface DirectiveDocViewInput extends BaseDocViewInput {
component?: undefined;
render?: undefined;
directive: ng.IDirective;
}
export type DocViewInput = ComponentDocViewInput | RenderDocViewInput | DirectiveDocViewInput;
export type DocViewInput = ComponentDocViewInput | RenderDocViewInput;
export type DocView = DocViewInput & {
shouldShow: NonNullable<DocViewInput['shouldShow']>;

View file

@ -317,7 +317,6 @@ export class DiscoverPlugin
stopUrlTracker();
};
this.docViewsRegistry.setAngularInjectorGetter(this.getEmbeddableInjector);
core.application.register({
id: 'discover',
title: 'Discover',

View file

@ -1,8 +0,0 @@
{
"id": "docViewPlugin",
"version": "0.0.1",
"kibanaVersion": "kibana",
"server": false,
"ui": true,
"requiredPlugins": ["discover"]
}

View file

@ -1,14 +0,0 @@
{
"name": "docViewPlugin",
"version": "1.0.0",
"main": "target/test/plugin_functional/plugins/doc_views_plugin",
"kibana": {
"version": "kibana",
"templateVersion": "1.0.0"
},
"license": "SSPL-1.0 OR Elastic License 2.0",
"scripts": {
"kbn": "node ../../../../scripts/kbn.js",
"build": "rm -rf './target' && ../../../../node_modules/.bin/tsc"
}
}

View file

@ -1,11 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { DocViewsPlugin } from './plugin';
export const plugin = () => new DocViewsPlugin();

View file

@ -1,49 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import angular from 'angular';
import React from 'react';
import { Plugin, CoreSetup } from 'kibana/public';
import { DiscoverSetup } from '../../../../../src/plugins/discover/public';
angular.module('myDocView', []).directive('myHit', () => ({
restrict: 'E',
scope: {
hit: '=hit',
},
template: '<h1 data-test-subj="angular-docview">{{hit._index}}</h1>',
}));
function MyHit(props: { index: string }) {
return <h1 data-test-subj="react-docview">{props.index}</h1>;
}
export class DocViewsPlugin implements Plugin<void, void> {
public setup(core: CoreSetup, { discover }: { discover: DiscoverSetup }) {
discover.docViews.addDocView({
directive: {
controller: function MyController($injector: any) {
$injector.loadNewModules(['myDocView']);
},
template: `<my-hit hit="hit"></my-hit>`,
},
order: 1,
title: 'Angular doc view',
});
discover.docViews.addDocView({
component: (props) => {
return <MyHit index={props.hit._index as string} />;
},
order: 2,
title: 'React doc view',
});
}
public start() {}
}

View file

@ -1,17 +0,0 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./target/types"
},
"include": [
"index.ts",
"public/**/*.ts",
"public/**/*.tsx",
"../../../../typings/**/*"
],
"exclude": [],
"references": [
{ "path": "../../../../src/core/tsconfig.json" },
{ "path": "../../../../src/plugins/discover/tsconfig.json" },
]
}