[Discover] Remove Angular (#109774)
- This PR removes a remaining Angular related code in Discover
This commit is contained in:
parent
51b0f5aa15
commit
814cf7a4fc
|
@ -1,2 +0,0 @@
|
|||
@import 'directives/index';
|
||||
@import 'context/index';
|
|
@ -1,95 +0,0 @@
|
|||
# Discover Context App Implementation Notes
|
||||
|
||||
The implementation of this app is intended to exhibit certain desirable
|
||||
properties by adhering to a set of *principles*. This document aims to explain
|
||||
those and the *concepts* employed to achieve that.
|
||||
|
||||
|
||||
## Principles
|
||||
|
||||
**Single Source of Truth**: A good user experience depends on the UI displaying
|
||||
consistent information across the whole page. To achieve this, there should
|
||||
always be a single source of truth for the application's state. In this
|
||||
application this is the `ContextAppController::state` object.
|
||||
|
||||
**Unidirectional Data Flow**: While a single state promotes rendering
|
||||
consistency, it does little to make the state changes easier to reason about.
|
||||
To avoid having state mutations scattered all over the code, this app
|
||||
implements a unidirectional data flow architecture. That means that the state
|
||||
is treated as immutable throughout the application except for actions, which
|
||||
may modify it to cause angular to re-render and watches to trigger.
|
||||
|
||||
**Unit-Testability**: Creating unit tests for large parts of the UI code is
|
||||
made easy by expressing the as much of the logic as possible as
|
||||
side-effect-free functions. The only place where side-effects are allowed are
|
||||
actions. Due to the nature of AngularJS a certain amount of impure code must be
|
||||
employed in some cases, e.g. when dealing with the isolate scope bindings in
|
||||
`ContextAppController`.
|
||||
|
||||
**Loose Coupling**: An attempt was made to couple the parts that make up this
|
||||
app as loosely as possible. This means using pure functions whenever possible
|
||||
and isolating the angular directives diligently. To that end, the app has been
|
||||
implemented as the independent `ContextApp` directive in [app.js](app.js). It
|
||||
does not access the Kibana `AppState` directly but communicates only via its
|
||||
directive properties. The binding of these attributes to the state and thereby
|
||||
to the route is performed by the `CreateAppRouteController`in
|
||||
[index.js](index.js). Similarly, the `SizePicker` directive only communicates
|
||||
with its parent via the passed properties.
|
||||
|
||||
|
||||
## Concepts
|
||||
|
||||
To adhere to the principles mentioned above, this app borrows some concepts
|
||||
from the redux architecture that forms a ciruclar unidirectional data flow:
|
||||
|
||||
```
|
||||
|
||||
|* create initial state
|
||||
v
|
||||
+->+
|
||||
| v
|
||||
| |* state
|
||||
| v
|
||||
| |* angular templates render state
|
||||
| v
|
||||
| |* angular calls actions in response to user action/system events
|
||||
| v
|
||||
| |* actions modify state
|
||||
| v
|
||||
+--+
|
||||
|
||||
```
|
||||
|
||||
**State**: The state is the single source of truth at
|
||||
`ContextAppController::state` and may only be modified by actions.
|
||||
|
||||
**Action**: Actions are functions that are called in response to user or system
|
||||
actions and may modified the state the are bound to via their closure.
|
||||
|
||||
|
||||
## Directory Structure
|
||||
|
||||
**index.js**: Defines the route and renders the `<context-app>` directive,
|
||||
binding it to the `AppState`.
|
||||
|
||||
**app.js**: Defines the `<context-app>` directive, that is at the root of the
|
||||
application. Creates the store, reducer and bound actions/selectors.
|
||||
|
||||
**query**: Exports the actions, reducers and selectors related to the
|
||||
query status and results.
|
||||
|
||||
**query_parameters**: Exports the actions, reducers and selectors related to
|
||||
the parameters used to construct the query.
|
||||
|
||||
**components/action_bar**: Defines the `<context-action-bar>`
|
||||
directive including its respective styles.
|
||||
|
||||
|
||||
**api/anchor.js**: Exports `fetchAnchor()` that creates and executes the
|
||||
query for the anchor document.
|
||||
|
||||
**api/context.js**: Exports `fetchPredecessors()`, `fetchSuccessors()`, `fetchSurroundingDocs()` that
|
||||
create and execute the queries for the preceeding and succeeding documents.
|
||||
|
||||
**api/utils**: Exports various functions used to create and transform
|
||||
queries.
|
|
@ -1,8 +0,0 @@
|
|||
// Prefix all styles with "cxt" to avoid conflicts.
|
||||
// Examples
|
||||
// cxtChart
|
||||
// cxtChart__legend
|
||||
// cxtChart__legend--small
|
||||
// cxtChart__legend-isLoading
|
||||
|
||||
@import 'components/action_bar/index';
|
|
@ -1 +0,0 @@
|
|||
@import 'action_bar';
|
|
@ -1,15 +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 { getAngularModule } from '../../../../../kibana_services';
|
||||
import { ActionBar } from './action_bar';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
getAngularModule().directive('contextActionBar', function (reactDirective: any) {
|
||||
return reactDirective(ActionBar);
|
||||
});
|
|
@ -1,9 +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 './action_bar_directive';
|
|
@ -1,52 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* WHAT NEEDS THIS WORKAROUND?
|
||||
* ===========================
|
||||
* Any directive that meets all of the following criteria:
|
||||
* - uses isolate scope bindings
|
||||
* - sets `bindToController: true`
|
||||
* - synchronously accesses the bound values in the controller constructor
|
||||
*
|
||||
*
|
||||
*
|
||||
* HOW DO I GET RID OF IT?
|
||||
* =======================
|
||||
* The quick band-aid solution:
|
||||
* Wrap your constructor logic so it doesn't access bound values
|
||||
* synchronously. This can have subtle bugs which is why I didn't
|
||||
* just wrap all of the offenders in $timeout() and made this
|
||||
* workaround instead.
|
||||
*
|
||||
* The more complete solution:
|
||||
* Use the new component lifecycle methods, like `$onInit()`, to access
|
||||
* bindings immediately after the constructor is called, which shouldn't
|
||||
* have any observable effect outside of the constructor.
|
||||
*
|
||||
* NOTE: `$onInit()` is not dependency injected, if you need controller specific
|
||||
* dependencies like `$scope` then you're probably using watchers and should
|
||||
* take a look at the new one-way data flow facilities available to
|
||||
* directives/components:
|
||||
*
|
||||
* https://docs.angularjs.org/guide/component#component-based-application-architecture
|
||||
*
|
||||
*/
|
||||
|
||||
export function callAfterBindingsWorkaround(constructor) {
|
||||
return function InitAfterBindingsWrapper($injector, $attrs, $element, $scope, $transclude) {
|
||||
this.$onInit = () => {
|
||||
$injector.invoke(constructor, this, {
|
||||
$attrs,
|
||||
$element,
|
||||
$scope,
|
||||
$transclude,
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
.dscHistogram__header--partial {
|
||||
font-weight: $euiFontWeightRegular;
|
||||
min-width: $euiSize * 12;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
@import 'histogram';
|
|
@ -1,39 +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 { getAngularModule, getServices } from '../../kibana_services';
|
||||
|
||||
const services = getServices();
|
||||
|
||||
const { history: getHistory } = getServices();
|
||||
|
||||
const app = getAngularModule();
|
||||
|
||||
app.directive('discoverApp', function () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
controllerAs: 'discoverApp',
|
||||
controller: discoverController,
|
||||
};
|
||||
});
|
||||
|
||||
function discoverController(_, $scope) {
|
||||
const history = getHistory();
|
||||
|
||||
$scope.opts = {
|
||||
history,
|
||||
services,
|
||||
navigateTo: (path) => {
|
||||
$scope.$evalAsync(() => {
|
||||
history.push(path);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
$scope.$on('$destroy', () => {});
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<discover-app>
|
||||
<discover
|
||||
angularRoute="angularRoute"
|
||||
index-pattern="indexPattern"
|
||||
opts="opts"
|
||||
reset-query="resetQuery"
|
||||
search-source="volatileSearchSource"
|
||||
set-index-pattern="setIndexPattern"
|
||||
>
|
||||
</discover>
|
||||
</discover-app>
|
|
@ -1,7 +0,0 @@
|
|||
<discover-app>
|
||||
<discover
|
||||
index-pattern="indexPattern"
|
||||
opts="opts"
|
||||
>
|
||||
</discover>
|
||||
</discover-app>
|
|
@ -1,38 +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 React from 'react';
|
||||
import { DocViewer } from '../components/doc_viewer/doc_viewer';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function createDocViewerDirective(reactDirective: any) {
|
||||
return reactDirective(
|
||||
(props: React.ComponentProps<typeof DocViewer>) => {
|
||||
return <DocViewer {...props} />;
|
||||
},
|
||||
[
|
||||
'hit',
|
||||
['indexPattern', { watchDepth: 'reference' }],
|
||||
['filter', { watchDepth: 'reference' }],
|
||||
['columns', { watchDepth: 'collection' }],
|
||||
['onAddColumn', { watchDepth: 'reference' }],
|
||||
['onRemoveColumn', { watchDepth: 'reference' }],
|
||||
],
|
||||
{
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
hit: '=',
|
||||
indexPattern: '=',
|
||||
filter: '=?',
|
||||
columns: '=?',
|
||||
onAddColumn: '=?',
|
||||
onRemoveColumn: '=?',
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
|
@ -1,142 +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.
|
||||
*/
|
||||
|
||||
// inner angular imports
|
||||
// these are necessary to bootstrap the local angular.
|
||||
// They can stay even after NP cutover
|
||||
import '../index.scss';
|
||||
import angular from 'angular';
|
||||
// required for `ngSanitize` angular module
|
||||
import 'angular-sanitize';
|
||||
import { EuiIcon } from '@elastic/eui';
|
||||
import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
|
||||
import { CoreStart, PluginInitializerContext } from 'kibana/public';
|
||||
import { DataPublicPluginStart } from 'src/plugins/data/public';
|
||||
import { Storage } from '../../../../kibana_utils/public';
|
||||
import { NavigationPublicPluginStart as NavigationStart } from '../../../../navigation/public';
|
||||
import { createContextAppLegacy } from '../components/context_app/context_app_legacy_directive';
|
||||
import { createDiscoverGridDirective } from './create_discover_grid_directive';
|
||||
import {
|
||||
configureAppAngularModule,
|
||||
PrivateProvider,
|
||||
registerListenEventListener,
|
||||
watchMultiDecorator,
|
||||
} from '../../../../kibana_legacy/public';
|
||||
import { PromiseServiceCreator } from './helpers';
|
||||
import { DiscoverStartPlugins } from '../../plugin';
|
||||
import { getScopedHistory } from '../../kibana_services';
|
||||
|
||||
/**
|
||||
* returns the main inner angular module, it contains all the parts of Angular Discover
|
||||
* needs to render, so in the end the current 'kibana' angular module is no longer necessary
|
||||
*/
|
||||
export function getInnerAngularModule(
|
||||
name: string,
|
||||
core: CoreStart,
|
||||
deps: DiscoverStartPlugins,
|
||||
context: PluginInitializerContext
|
||||
) {
|
||||
const module = initializeInnerAngularModule(name, core, deps.navigation, deps.data);
|
||||
configureAppAngularModule(module, { core, env: context.env }, true, getScopedHistory);
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a slimmer inner angular module for embeddable rendering
|
||||
*/
|
||||
export function getInnerAngularModuleEmbeddable(
|
||||
name: string,
|
||||
core: CoreStart,
|
||||
deps: DiscoverStartPlugins
|
||||
) {
|
||||
return initializeInnerAngularModule(name, core, deps.navigation, deps.data, true);
|
||||
}
|
||||
|
||||
let initialized = false;
|
||||
|
||||
export function initializeInnerAngularModule(
|
||||
name = 'app/discover',
|
||||
core: CoreStart,
|
||||
navigation: NavigationStart,
|
||||
data: DataPublicPluginStart,
|
||||
embeddable = false
|
||||
) {
|
||||
if (!initialized) {
|
||||
createLocalI18nModule();
|
||||
createLocalPrivateModule();
|
||||
createLocalPromiseModule();
|
||||
createLocalStorageModule();
|
||||
createDocTableModule();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
if (embeddable) {
|
||||
return angular
|
||||
.module(name, [
|
||||
'ngSanitize',
|
||||
'react',
|
||||
'ui.bootstrap',
|
||||
'discoverI18n',
|
||||
'discoverPrivate',
|
||||
'discoverDocTable',
|
||||
'discoverPromise',
|
||||
])
|
||||
.config(watchMultiDecorator)
|
||||
.directive('icon', (reactDirective) => reactDirective(EuiIcon));
|
||||
}
|
||||
|
||||
return angular
|
||||
.module(name, [
|
||||
'ngSanitize',
|
||||
'react',
|
||||
'ui.bootstrap',
|
||||
'discoverI18n',
|
||||
'discoverPrivate',
|
||||
'discoverPromise',
|
||||
'discoverLocalStorageProvider',
|
||||
'discoverDocTable',
|
||||
])
|
||||
.config(watchMultiDecorator)
|
||||
.run(registerListenEventListener);
|
||||
}
|
||||
|
||||
function createLocalPromiseModule() {
|
||||
angular.module('discoverPromise', []).service('Promise', PromiseServiceCreator);
|
||||
}
|
||||
|
||||
function createLocalPrivateModule() {
|
||||
angular.module('discoverPrivate', []).provider('Private', PrivateProvider);
|
||||
}
|
||||
|
||||
function createLocalI18nModule() {
|
||||
angular
|
||||
.module('discoverI18n', [])
|
||||
.provider('i18n', I18nProvider)
|
||||
.filter('i18n', i18nFilter)
|
||||
.directive('i18nId', i18nDirective);
|
||||
}
|
||||
|
||||
function createLocalStorageModule() {
|
||||
angular
|
||||
.module('discoverLocalStorageProvider', ['discoverPrivate'])
|
||||
.service('localStorage', createLocalStorageService('localStorage'))
|
||||
.service('sessionStorage', createLocalStorageService('sessionStorage'));
|
||||
}
|
||||
|
||||
const createLocalStorageService = function (type: string) {
|
||||
return function ($window: ng.IWindowService) {
|
||||
return new Storage($window[type]);
|
||||
};
|
||||
};
|
||||
|
||||
function createDocTableModule() {
|
||||
angular
|
||||
.module('discoverDocTable', ['react'])
|
||||
.directive('discoverGrid', createDiscoverGridDirective)
|
||||
.directive('contextAppLegacy', createContextAppLegacy);
|
||||
}
|
|
@ -1,10 +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.
|
||||
*/
|
||||
|
||||
export { handleSourceColumnState } from './state_helpers';
|
||||
export { PromiseServiceCreator } from './promises';
|
|
@ -1,9 +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.
|
||||
*/
|
||||
|
||||
export function PromiseServiceCreator($q: unknown, $timeout: unknown): (fn: unknown) => unknown;
|
|
@ -1,118 +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 _ from 'lodash';
|
||||
|
||||
export function PromiseServiceCreator($q, $timeout) {
|
||||
function Promise(fn) {
|
||||
if (typeof this === 'undefined')
|
||||
throw new Error('Promise constructor must be called with "new"');
|
||||
|
||||
const defer = $q.defer();
|
||||
try {
|
||||
fn(defer.resolve, defer.reject);
|
||||
} catch (e) {
|
||||
defer.reject(e);
|
||||
}
|
||||
return defer.promise;
|
||||
}
|
||||
|
||||
Promise.all = Promise.props = $q.all;
|
||||
Promise.resolve = function (val) {
|
||||
const defer = $q.defer();
|
||||
defer.resolve(val);
|
||||
return defer.promise;
|
||||
};
|
||||
Promise.reject = function (reason) {
|
||||
const defer = $q.defer();
|
||||
defer.reject(reason);
|
||||
return defer.promise;
|
||||
};
|
||||
Promise.cast = $q.when;
|
||||
Promise.delay = function (ms) {
|
||||
return $timeout(_.noop, ms);
|
||||
};
|
||||
Promise.method = function (fn) {
|
||||
return function () {
|
||||
const args = Array.prototype.slice.call(arguments);
|
||||
return Promise.try(fn, args, this);
|
||||
};
|
||||
};
|
||||
Promise.nodeify = function (promise, cb) {
|
||||
promise.then(function (val) {
|
||||
cb(void 0, val);
|
||||
}, cb);
|
||||
};
|
||||
Promise.map = function (arr, fn) {
|
||||
return Promise.all(
|
||||
arr.map(function (i, el, list) {
|
||||
return Promise.try(fn, [i, el, list]);
|
||||
})
|
||||
);
|
||||
};
|
||||
Promise.each = function (arr, fn) {
|
||||
const queue = arr.slice(0);
|
||||
let i = 0;
|
||||
return (function next() {
|
||||
if (!queue.length) return arr;
|
||||
return Promise.try(fn, [arr.shift(), i++]).then(next);
|
||||
})();
|
||||
};
|
||||
Promise.is = function (obj) {
|
||||
// $q doesn't create instances of any constructor, promises are just objects with a then function
|
||||
// https://github.com/angular/angular.js/blob/58f5da86645990ef984353418cd1ed83213b111e/src/ng/q.js#L335
|
||||
return obj && typeof obj.then === 'function';
|
||||
};
|
||||
Promise.halt = _.once(function () {
|
||||
const promise = new Promise(() => {});
|
||||
promise.then = _.constant(promise);
|
||||
promise.catch = _.constant(promise);
|
||||
return promise;
|
||||
});
|
||||
Promise.try = function (fn, args, ctx) {
|
||||
if (typeof fn !== 'function') {
|
||||
return Promise.reject(new TypeError('fn must be a function'));
|
||||
}
|
||||
|
||||
let value;
|
||||
|
||||
if (Array.isArray(args)) {
|
||||
try {
|
||||
value = fn.apply(ctx, args);
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
value = fn.call(ctx, args);
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(value);
|
||||
};
|
||||
Promise.fromNode = function (takesCbFn) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
takesCbFn(function (err, ...results) {
|
||||
if (err) reject(err);
|
||||
else if (results.length > 1) resolve(results);
|
||||
else resolve(results[0]);
|
||||
});
|
||||
});
|
||||
};
|
||||
Promise.race = function (iterable) {
|
||||
return new Promise((resolve, reject) => {
|
||||
for (const i of iterable) {
|
||||
Promise.resolve(i).then(resolve, reject);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return Promise;
|
||||
}
|
|
@ -1,13 +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.
|
||||
*/
|
||||
|
||||
// required for i18nIdDirective
|
||||
import 'angular-sanitize';
|
||||
|
||||
import './doc';
|
||||
import './context';
|
|
@ -6,11 +6,10 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import './index.scss';
|
||||
import { renderApp as renderReactApp } from './index';
|
||||
|
||||
/**
|
||||
* Here's where Discover's inner angular is mounted and rendered
|
||||
* Here's where Discover is mounted and rendered
|
||||
*/
|
||||
export async function renderApp(moduleName: string, element: HTMLElement) {
|
||||
const app = mountDiscoverApp(moduleName, element);
|
||||
|
|
|
@ -10,11 +10,8 @@ import React from 'react';
|
|||
import { mountWithIntl } from '@kbn/test/jest';
|
||||
import { ActionBar, ActionBarProps } from './action_bar';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import {
|
||||
MAX_CONTEXT_SIZE,
|
||||
MIN_CONTEXT_SIZE,
|
||||
} from '../../../../components/context_app/utils/constants';
|
||||
import { SurrDocType } from '../../api/context';
|
||||
import { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE } from '../../utils/constants';
|
||||
import { SurrDocType } from '../../services/context';
|
||||
|
||||
describe('Test Discover Context ActionBar for successor | predecessor records', () => {
|
||||
[SurrDocType.SUCCESSORS, SurrDocType.PREDECESSORS].forEach((type) => {
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import './_action_bar.scss';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
|
||||
|
@ -18,11 +19,8 @@ import {
|
|||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
import { ActionBarWarning } from './action_bar_warning';
|
||||
import { SurrDocType } from '../../api/context';
|
||||
import {
|
||||
MAX_CONTEXT_SIZE,
|
||||
MIN_CONTEXT_SIZE,
|
||||
} from '../../../../components/context_app/utils/constants';
|
||||
import { SurrDocType } from '../../services/context';
|
||||
import { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE } from '../../utils/constants';
|
||||
|
||||
export interface ActionBarProps {
|
||||
/**
|
|
@ -9,7 +9,7 @@
|
|||
import React from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { EuiCallOut } from '@elastic/eui';
|
||||
import { SurrDocType } from '../../api/context';
|
||||
import { SurrDocType } from '../../services/context';
|
||||
|
||||
export function ActionBarWarning({ docCount, type }: { docCount: number; type: SurrDocType }) {
|
||||
if (type === SurrDocType.PREDECESSORS) {
|
|
@ -10,7 +10,7 @@ import React from 'react';
|
|||
import { mountWithIntl } from '@kbn/test/jest';
|
||||
import { ReactWrapper } from 'enzyme';
|
||||
import { ContextErrorMessage } from './context_error_message';
|
||||
import { FailureReason, LoadingStatus } from '../../angular/context_query_state';
|
||||
import { FailureReason, LoadingStatus } from '../../services/context_query_state';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
|
||||
describe('loading spinner', function () {
|
|
@ -13,7 +13,7 @@ import {
|
|||
FailureReason,
|
||||
LoadingStatus,
|
||||
LoadingStatusEntry,
|
||||
} from '../../angular/context_query_state';
|
||||
} from '../../services/context_query_state';
|
||||
|
||||
export interface ContextErrorMessageProps {
|
||||
/**
|
|
@ -1,4 +1,4 @@
|
|||
@import '../../../../../../core/public/mixins';
|
||||
@import 'src/core/public/mixins';
|
||||
|
||||
.dscDocsPage {
|
||||
@include kibanaFullBodyHeight(54px); // action bar height
|
|
@ -14,17 +14,17 @@ import { EuiText, EuiPageContent, EuiPage, EuiSpacer } from '@elastic/eui';
|
|||
import { cloneDeep } from 'lodash';
|
||||
import { esFilters, SortDirection } from '../../../../../data/public';
|
||||
import { DOC_TABLE_LEGACY, SEARCH_FIELDS_FROM_SOURCE } from '../../../../common';
|
||||
import { ContextErrorMessage } from '../context_error_message';
|
||||
import { ContextErrorMessage } from './components/context_error_message';
|
||||
import { IndexPattern, IndexPatternField } from '../../../../../data/common';
|
||||
import { LoadingStatus } from '../../angular/context_query_state';
|
||||
import { LoadingStatus } from './services/context_query_state';
|
||||
import { getServices } from '../../../kibana_services';
|
||||
import { AppState, isEqualFilters } from '../../angular/context_state';
|
||||
import { AppState, isEqualFilters } from './services/context_state';
|
||||
import { useDataGridColumns } from '../../helpers/use_data_grid_columns';
|
||||
import { useContextAppState } from './use_context_app_state';
|
||||
import { useContextAppFetch } from './use_context_app_fetch';
|
||||
import { useContextAppState } from './utils/use_context_app_state';
|
||||
import { useContextAppFetch } from './utils/use_context_app_fetch';
|
||||
import { popularizeField } from '../../helpers/popularize_field';
|
||||
import { ContextAppContent } from './context_app_content';
|
||||
import { SurrDocType } from '../../angular/context/api/context';
|
||||
import { SurrDocType } from './services/context';
|
||||
import { DocViewFilterFn } from '../../doc_views/doc_views_types';
|
||||
|
||||
const ContextAppContentMemoized = memo(ContextAppContent);
|
|
@ -9,17 +9,17 @@
|
|||
import React from 'react';
|
||||
import { mountWithIntl } from '@kbn/test/jest';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { ActionBar } from '../../angular/context/components/action_bar/action_bar';
|
||||
import { AppState, GetStateReturn } from '../../angular/context_state';
|
||||
import { ActionBar } from './components/action_bar/action_bar';
|
||||
import { AppState, GetStateReturn } from './services/context_state';
|
||||
import { SortDirection } from 'src/plugins/data/common';
|
||||
import { EsHitRecordList } from '../../angular/context/api/context';
|
||||
import { ContextAppContent, ContextAppContentProps } from './context_app_content';
|
||||
import { getServices, setServices } from '../../../kibana_services';
|
||||
import { LoadingStatus } from '../../angular/context_query_state';
|
||||
import { LoadingStatus } from './services/context_query_state';
|
||||
import { indexPatternMock } from '../../../__mocks__/index_pattern';
|
||||
import { DiscoverGrid } from '../discover_grid/discover_grid';
|
||||
import { DiscoverGrid } from '../../components/discover_grid/discover_grid';
|
||||
import { discoverServiceMock } from '../../../__mocks__/services';
|
||||
import { DocTableWrapper } from '../../apps/main/components/doc_table/doc_table_wrapper';
|
||||
import { DocTableWrapper } from '../main/components/doc_table/doc_table_wrapper';
|
||||
import { EsHitRecordList } from '../../types';
|
||||
|
||||
describe('ContextAppContent test', () => {
|
||||
let hit;
|
|
@ -12,15 +12,16 @@ import { EuiHorizontalRule, EuiText } from '@elastic/eui';
|
|||
import { CONTEXT_STEP_SETTING, DOC_HIDE_TIME_COLUMN_SETTING } from '../../../../common';
|
||||
import { IndexPattern } from '../../../../../data/common';
|
||||
import { SortDirection } from '../../../../../data/public';
|
||||
import { LoadingStatus } from '../../angular/context_query_state';
|
||||
import { ActionBar } from '../../angular/context/components/action_bar/action_bar';
|
||||
import { DiscoverGrid } from '../discover_grid/discover_grid';
|
||||
import { LoadingStatus } from './services/context_query_state';
|
||||
import { ActionBar } from './components/action_bar/action_bar';
|
||||
import { DiscoverGrid } from '../../components/discover_grid/discover_grid';
|
||||
import { DocViewFilterFn, ElasticSearchHit } from '../../doc_views/doc_views_types';
|
||||
import { AppState } from '../../angular/context_state';
|
||||
import { EsHitRecordList, SurrDocType } from '../../angular/context/api/context';
|
||||
import { AppState } from './services/context_state';
|
||||
import { SurrDocType } from './services/context';
|
||||
import { DiscoverServices } from '../../../build_services';
|
||||
import { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE } from './utils/constants';
|
||||
import { DocTableContext } from '../../apps/main/components/doc_table/doc_table_context';
|
||||
import { DocTableContext } from '../main/components/doc_table/doc_table_context';
|
||||
import { EsHitRecordList } from '../../types';
|
||||
|
||||
export interface ContextAppContentProps {
|
||||
columns: string[];
|
|
@ -9,7 +9,7 @@ import React, { useEffect } from 'react';
|
|||
import { useParams } from 'react-router-dom';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { DiscoverServices } from '../../../build_services';
|
||||
import { ContextApp } from '../../components/context_app/context_app';
|
||||
import { ContextApp } from './context_app';
|
||||
import { getRootBreadcrumbs } from '../../helpers/breadcrumbs';
|
||||
import { LoadingIndicator } from '../../components/common/loading_indicator';
|
||||
import { useIndexPattern } from '../../helpers/use_index_pattern';
|
||||
|
|
|
@ -10,7 +10,7 @@ import sinon from 'sinon';
|
|||
import moment from 'moment';
|
||||
|
||||
import { IndexPatternsContract } from '../../../../../../data/public';
|
||||
import { EsHitRecordList } from './context';
|
||||
import { EsHitRecordList } from '../../../types';
|
||||
|
||||
type SortHit = {
|
||||
[key in string]: number; // timeField name
|
|
@ -9,9 +9,9 @@
|
|||
import { EsQuerySortValue, SortDirection } from '../../../../../../data/public';
|
||||
import { createIndexPatternsStub, createSearchSourceStub } from './_stubs';
|
||||
import { fetchAnchorProvider, updateSearchSource } from './anchor';
|
||||
import { EsHitRecord, EsHitRecordList } from './context';
|
||||
import { indexPatternMock } from '../../../../__mocks__/index_pattern';
|
||||
import { savedSearchMock } from '../../../../__mocks__/saved_search';
|
||||
import { EsHitRecord, EsHitRecordList } from '../../../types';
|
||||
|
||||
describe('context app', function () {
|
||||
let fetchAnchor: (
|
|
@ -15,7 +15,7 @@ import {
|
|||
EsQuerySortValue,
|
||||
IndexPattern,
|
||||
} from '../../../../../../data/public';
|
||||
import { EsHitRecord } from './context';
|
||||
import { EsHitRecord } from '../../../types';
|
||||
|
||||
export function fetchAnchorProvider(
|
||||
indexPatterns: IndexPatternsContract,
|
|
@ -9,11 +9,11 @@
|
|||
import moment from 'moment';
|
||||
import { get, last } from 'lodash';
|
||||
import { createIndexPatternsStub, createContextSearchSourceStub } from './_stubs';
|
||||
import { EsHitRecordList, fetchContextProvider, SurrDocType } from './context';
|
||||
import { fetchContextProvider, SurrDocType } from './context';
|
||||
import { setServices, SortDirection } from '../../../../kibana_services';
|
||||
import { EsHitRecord } from './context';
|
||||
import { Query } from '../../../../../../data/public';
|
||||
import { DiscoverServices } from '../../../../build_services';
|
||||
import { EsHitRecord, EsHitRecordList } from '../../../types';
|
||||
|
||||
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
||||
const ANCHOR_TIMESTAMP = new Date(MS_PER_DAY).toJSON();
|
|
@ -12,9 +12,9 @@ import { get, last } from 'lodash';
|
|||
import { createIndexPatternsStub, createContextSearchSourceStub } from './_stubs';
|
||||
import { setServices, SortDirection } from '../../../../kibana_services';
|
||||
import { Query } from '../../../../../../data/public';
|
||||
import { EsHitRecordList, fetchContextProvider, SurrDocType } from './context';
|
||||
import { EsHitRecord } from './context';
|
||||
import { fetchContextProvider, SurrDocType } from './context';
|
||||
import { DiscoverServices } from '../../../../build_services';
|
||||
import { EsHitRecord, EsHitRecordList } from '../../../types';
|
||||
|
||||
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
||||
const ANCHOR_TIMESTAMP = new Date(MS_PER_DAY).toJSON();
|
|
@ -5,32 +5,21 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { estypes } from '@elastic/elasticsearch';
|
||||
import { Filter, IndexPatternsContract, IndexPattern, SearchSource } from 'src/plugins/data/public';
|
||||
import { Filter, IndexPattern, IndexPatternsContract, SearchSource } from 'src/plugins/data/public';
|
||||
import { reverseSortDir, SortDirection } from './utils/sorting';
|
||||
import { extractNanos, convertIsoToMillis } from './utils/date_conversion';
|
||||
import { convertIsoToMillis, extractNanos } from './utils/date_conversion';
|
||||
import { fetchHitsInInterval } from './utils/fetch_hits_in_interval';
|
||||
import { generateIntervals } from './utils/generate_intervals';
|
||||
import { getEsQuerySearchAfter } from './utils/get_es_query_search_after';
|
||||
import { getEsQuerySort } from './utils/get_es_query_sort';
|
||||
import { getServices } from '../../../../kibana_services';
|
||||
import { EsHitRecord, EsHitRecordList } from '../../../types';
|
||||
|
||||
export enum SurrDocType {
|
||||
SUCCESSORS = 'successors',
|
||||
PREDECESSORS = 'predecessors',
|
||||
}
|
||||
|
||||
export type EsHitRecord = Required<
|
||||
Pick<estypes.SearchHit, '_id' | 'fields' | 'sort' | '_index' | '_version'>
|
||||
> & {
|
||||
_source?: Record<string, unknown>;
|
||||
_score?: number;
|
||||
isAnchor?: boolean;
|
||||
};
|
||||
|
||||
export type EsHitRecordList = EsHitRecord[];
|
||||
|
||||
const DAY_MILLIS = 24 * 60 * 60 * 1000;
|
||||
|
||||
// look from 1 day up to 10000 days into the past and future
|
|
@ -6,8 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { EsHitRecord } from './context/api/context';
|
||||
import { EsHitRecordList } from './context/api/context';
|
||||
import { EsHitRecord, EsHitRecordList } from '../../../types';
|
||||
|
||||
export interface ContextFetchState {
|
||||
/**
|
|
@ -9,9 +9,9 @@
|
|||
import { IUiSettingsClient } from 'kibana/public';
|
||||
import { getState } from './context_state';
|
||||
import { createBrowserHistory, History } from 'history';
|
||||
import { FilterManager, Filter } from '../../../../data/public';
|
||||
import { coreMock } from '../../../../../core/public/mocks';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE } from '../../../common';
|
||||
import { FilterManager, Filter } from '../../../../../../data/public';
|
||||
import { coreMock } from '../../../../../../../core/public/mocks';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE } from '../../../../../common';
|
||||
|
||||
const setupMock = coreMock.createSetup();
|
||||
|
|
@ -15,9 +15,9 @@ import {
|
|||
syncStates,
|
||||
withNotifyOnErrors,
|
||||
ReduxLikeStateContainer,
|
||||
} from '../../../../kibana_utils/public';
|
||||
import { esFilters, FilterManager, Filter, SortDirection } from '../../../../data/public';
|
||||
import { handleSourceColumnState } from './helpers';
|
||||
} from '../../../../../../kibana_utils/public';
|
||||
import { esFilters, FilterManager, Filter, SortDirection } from '../../../../../../data/public';
|
||||
import { handleSourceColumnState } from '../../../helpers/state_helpers';
|
||||
|
||||
export interface AppState {
|
||||
/**
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
import { ISearchSource, EsQuerySortValue, SortDirection } from '../../../../../../../data/public';
|
||||
import { convertTimeValueToIso } from './date_conversion';
|
||||
import { EsHitRecordList, EsHitRecord } from '../context';
|
||||
import { IntervalValue } from './generate_intervals';
|
||||
import { EsQuerySearchAfter } from './get_es_query_search_after';
|
||||
import { EsHitRecord, EsHitRecordList } from '../../../../types';
|
||||
|
||||
interface RangeQuery {
|
||||
format: string;
|
|
@ -6,7 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { SurrDocType, EsHitRecordList, EsHitRecord } from '../context';
|
||||
import { SurrDocType } from '../context';
|
||||
import { EsHitRecord, EsHitRecordList } from '../../../../types';
|
||||
|
||||
export type EsQuerySearchAfter = [string | number, string | number];
|
||||
|
|
@ -7,25 +7,25 @@
|
|||
*/
|
||||
|
||||
import { act, renderHook } from '@testing-library/react-hooks';
|
||||
import { setServices, getServices } from '../../../kibana_services';
|
||||
import { SortDirection } from '../../../../../data/public';
|
||||
import { createFilterManagerMock } from '../../../../../data/public/query/filter_manager/filter_manager.mock';
|
||||
import { CONTEXT_TIE_BREAKER_FIELDS_SETTING } from '../../../../common';
|
||||
import { DiscoverServices } from '../../../build_services';
|
||||
import { indexPatternMock } from '../../../__mocks__/index_pattern';
|
||||
import { indexPatternsMock } from '../../../__mocks__/index_patterns';
|
||||
import { FailureReason, LoadingStatus } from '../../angular/context_query_state';
|
||||
import { setServices, getServices } from '../../../../kibana_services';
|
||||
import { SortDirection } from '../../../../../../data/public';
|
||||
import { createFilterManagerMock } from '../../../../../../data/public/query/filter_manager/filter_manager.mock';
|
||||
import { CONTEXT_TIE_BREAKER_FIELDS_SETTING } from '../../../../../common';
|
||||
import { DiscoverServices } from '../../../../build_services';
|
||||
import { indexPatternMock } from '../../../../__mocks__/index_pattern';
|
||||
import { indexPatternsMock } from '../../../../__mocks__/index_patterns';
|
||||
import { FailureReason, LoadingStatus } from '../services/context_query_state';
|
||||
import { ContextAppFetchProps, useContextAppFetch } from './use_context_app_fetch';
|
||||
import {
|
||||
mockAnchorHit,
|
||||
mockPredecessorHits,
|
||||
mockSuccessorHits,
|
||||
} from './__mocks__/use_context_app_fetch';
|
||||
} from '../__mocks__/use_context_app_fetch';
|
||||
|
||||
const mockFilterManager = createFilterManagerMock();
|
||||
|
||||
jest.mock('../../angular/context/api/context', () => {
|
||||
const originalModule = jest.requireActual('../../angular/context/api/context');
|
||||
jest.mock('../services/context', () => {
|
||||
const originalModule = jest.requireActual('../services/context');
|
||||
return {
|
||||
...originalModule,
|
||||
fetchContextProvider: () => ({
|
||||
|
@ -39,7 +39,7 @@ jest.mock('../../angular/context/api/context', () => {
|
|||
};
|
||||
});
|
||||
|
||||
jest.mock('../../angular/context/api/anchor', () => ({
|
||||
jest.mock('../services/anchor', () => ({
|
||||
fetchAnchorProvider: () => (indexPatternId: string) => {
|
||||
if (!indexPatternId) {
|
||||
throw new Error();
|
|
@ -8,20 +8,21 @@
|
|||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { fromPairs } from 'lodash';
|
||||
import { CONTEXT_TIE_BREAKER_FIELDS_SETTING } from '../../../../common';
|
||||
import { DiscoverServices } from '../../../build_services';
|
||||
import { fetchAnchorProvider } from '../../angular/context/api/anchor';
|
||||
import { EsHitRecord, fetchContextProvider, SurrDocType } from '../../angular/context/api/context';
|
||||
import { MarkdownSimple, toMountPoint } from '../../../../../kibana_react/public';
|
||||
import { IndexPattern, SortDirection } from '../../../../../data/public';
|
||||
import { CONTEXT_TIE_BREAKER_FIELDS_SETTING } from '../../../../../common';
|
||||
import { DiscoverServices } from '../../../../build_services';
|
||||
import { fetchAnchorProvider } from '../services/anchor';
|
||||
import { fetchContextProvider, SurrDocType } from '../services/context';
|
||||
import { MarkdownSimple, toMountPoint } from '../../../../../../kibana_react/public';
|
||||
import { IndexPattern, SortDirection } from '../../../../../../data/public';
|
||||
import {
|
||||
ContextFetchState,
|
||||
FailureReason,
|
||||
getInitialContextQueryState,
|
||||
LoadingStatus,
|
||||
} from '../../angular/context_query_state';
|
||||
import { AppState } from '../../angular/context_state';
|
||||
import { getFirstSortableField } from '../../angular/context/api/utils/sorting';
|
||||
} from '../services/context_query_state';
|
||||
import { AppState } from '../services/context_state';
|
||||
import { getFirstSortableField } from '../services/utils/sorting';
|
||||
import { EsHitRecord } from '../../../types';
|
||||
|
||||
const createError = (statusKey: string, reason: FailureReason, error?: Error) => ({
|
||||
[statusKey]: { value: LoadingStatus.FAILED, error, reason },
|
|
@ -8,10 +8,10 @@
|
|||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { CONTEXT_DEFAULT_SIZE_SETTING } from '../../../../common';
|
||||
import { IndexPattern } from '../../../../../data/public';
|
||||
import { DiscoverServices } from '../../../build_services';
|
||||
import { AppState, getState } from '../../angular/context_state';
|
||||
import { CONTEXT_DEFAULT_SIZE_SETTING } from '../../../../../common';
|
||||
import { IndexPattern } from '../../../../../../data/public';
|
||||
import { DiscoverServices } from '../../../../build_services';
|
||||
import { AppState, getState } from '../services/context_state';
|
||||
|
||||
export function useContextAppState({
|
||||
indexPattern,
|
|
@ -13,11 +13,11 @@ import { mountWithIntl } from '@kbn/test/jest';
|
|||
import { ReactWrapper } from 'enzyme';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { Doc, DocProps } from './doc';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE as mockSearchFieldsFromSource } from '../../../../common';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE as mockSearchFieldsFromSource } from '../../../../../common';
|
||||
|
||||
const mockSearchApi = jest.fn();
|
||||
|
||||
jest.mock('../../../kibana_services', () => {
|
||||
jest.mock('../../../../kibana_services', () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let registry: any[] = [];
|
||||
|
|
@ -10,10 +10,10 @@ import React from 'react';
|
|||
import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
|
||||
import { EuiCallOut, EuiLink, EuiLoadingSpinner, EuiPageContent, EuiPage } from '@elastic/eui';
|
||||
import { IndexPatternsContract } from 'src/plugins/data/public';
|
||||
import { useEsDocSearch } from './use_es_doc_search';
|
||||
import { getServices } from '../../../kibana_services';
|
||||
import { DocViewer } from '../doc_viewer/doc_viewer';
|
||||
import { ElasticRequestState } from './elastic_request_state';
|
||||
import { getServices } from '../../../../kibana_services';
|
||||
import { DocViewer } from '../../../components/doc_viewer/doc_viewer';
|
||||
import { ElasticRequestState } from '../types';
|
||||
import { useEsDocSearch } from '../../../services/use_es_doc_search';
|
||||
|
||||
export interface DocProps {
|
||||
/**
|
|
@ -9,7 +9,7 @@ import React, { useEffect } from 'react';
|
|||
import { useLocation, useParams } from 'react-router-dom';
|
||||
import { DiscoverServices } from '../../../build_services';
|
||||
import { getRootBreadcrumbs } from '../../helpers/breadcrumbs';
|
||||
import { Doc } from '../../components/doc/doc';
|
||||
import { Doc } from './components/doc';
|
||||
import { LoadingIndicator } from '../../components/common/loading_indicator';
|
||||
import { useIndexPattern } from '../../helpers/use_index_pattern';
|
||||
|
||||
|
|
|
@ -7,3 +7,7 @@
|
|||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.dscHistogram__header--partial {
|
||||
font-weight: $euiFontWeightRegular;
|
||||
min-width: $euiSize * 12;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
import { Capabilities, IUiSettingsClient } from 'kibana/public';
|
||||
import { SORT_DEFAULT_ORDER_SETTING } from '../../../../../../../common';
|
||||
import { popularizeField } from '../../../../../../application/helpers/popularize_field';
|
||||
import {
|
||||
AppState as DiscoverState,
|
||||
GetStateReturn as DiscoverGetStateReturn,
|
||||
|
@ -15,8 +14,9 @@ import {
|
|||
import {
|
||||
AppState as ContextState,
|
||||
GetStateReturn as ContextGetStateReturn,
|
||||
} from '../../../../../../application/angular/context_state';
|
||||
} from '../../../../context/services/context_state';
|
||||
import { IndexPattern, IndexPatternsContract } from '../../../../../../../../data/public';
|
||||
import { popularizeField } from '../../../../../helpers/popularize_field';
|
||||
|
||||
/**
|
||||
* Helper function to provide a fallback to a single _source column if the given array of columns
|
||||
|
|
|
@ -99,13 +99,6 @@ describe('DiscoverFieldSearch', () => {
|
|||
expect(badge.text()).toEqual('0');
|
||||
});
|
||||
|
||||
test('missing switch appears with new fields api', () => {
|
||||
const component = mountComponent({ ...defaultProps, useNewFieldsApi: true });
|
||||
const btn = findTestSubject(component, 'toggleFieldFilterButton');
|
||||
btn.simulate('click');
|
||||
expect(findTestSubject(component, 'missingSwitch').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('change in filters triggers onChange', () => {
|
||||
const onChange = jest.fn();
|
||||
const component = mountComponent({ ...defaultProps, ...{ onChange } });
|
||||
|
|
|
@ -53,18 +53,13 @@ export interface Props {
|
|||
* types for the type filter
|
||||
*/
|
||||
types: string[];
|
||||
|
||||
/**
|
||||
* use new fields api
|
||||
*/
|
||||
useNewFieldsApi?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component is Discover's side bar to search of available fields
|
||||
* Additionally there's a button displayed that allows the user to show/hide more filter fields
|
||||
*/
|
||||
export function DiscoverFieldSearch({ onChange, value, types, useNewFieldsApi }: Props) {
|
||||
export function DiscoverFieldSearch({ onChange, value, types }: Props) {
|
||||
const searchPlaceholder = i18n.translate('discover.fieldChooser.searchPlaceHolder', {
|
||||
defaultMessage: 'Search field names',
|
||||
});
|
||||
|
@ -92,12 +87,6 @@ export function DiscoverFieldSearch({ onChange, value, types, useNewFieldsApi }:
|
|||
missing: true,
|
||||
});
|
||||
|
||||
if (typeof value !== 'string') {
|
||||
// at initial rendering value is undefined (angular related), this catches the warning
|
||||
// should be removed once all is react
|
||||
return null;
|
||||
}
|
||||
|
||||
const filterBtnAriaLabel = isPopoverOpen
|
||||
? i18n.translate('discover.fieldChooser.toggleFieldFilterButtonHideAriaLabel', {
|
||||
defaultMessage: 'Hide field filter settings',
|
||||
|
|
|
@ -23,7 +23,7 @@ export interface DiscoverIndexPatternProps {
|
|||
*/
|
||||
onChangeIndexPattern: (id: string) => void;
|
||||
/**
|
||||
* currently selected index pattern, due to angular issues it's undefined at first rendering
|
||||
* currently selected index pattern
|
||||
*/
|
||||
selectedIndexPattern: IndexPattern;
|
||||
}
|
||||
|
|
|
@ -338,7 +338,6 @@ export function DiscoverSidebar({
|
|||
onChange={onChangeFieldSearch}
|
||||
value={fieldFilter.name}
|
||||
types={fieldTypes}
|
||||
useNewFieldsApi={useNewFieldsApi}
|
||||
/>
|
||||
</form>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -26,7 +26,7 @@ export function SkipBottomButton({ onClick }: SkipBottomButtonProps) {
|
|||
// prevent the anchor to reload the page on click
|
||||
event.preventDefault();
|
||||
// The destinationId prop cannot be leveraged here as the table needs
|
||||
// to be updated first (angular logic)
|
||||
// to be updated firsts
|
||||
onClick();
|
||||
}}
|
||||
className="dscSkipButton"
|
||||
|
|
|
@ -34,7 +34,7 @@ import { migrateLegacyQuery } from '../../../helpers/migrate_legacy_query';
|
|||
import { DiscoverGridSettings } from '../../../components/discover_grid/types';
|
||||
import { DISCOVER_APP_URL_GENERATOR, DiscoverUrlGeneratorState } from '../../../../url_generator';
|
||||
import { SavedSearch } from '../../../../saved_searches';
|
||||
import { handleSourceColumnState } from '../../../angular/helpers';
|
||||
import { handleSourceColumnState } from '../../../helpers/state_helpers';
|
||||
|
||||
export interface AppState {
|
||||
/**
|
||||
|
|
|
@ -1,18 +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 { ContextApp } from './context_app';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function createContextAppLegacy(reactDirective: any) {
|
||||
return reactDirective(ContextApp, [
|
||||
['indexPattern', { watchDepth: 'reference' }],
|
||||
['indexPatternId', { watchDepth: 'reference' }],
|
||||
['anchorId', { watchDepth: 'reference' }],
|
||||
]);
|
||||
}
|
|
@ -12,7 +12,7 @@ import themeDark from '@elastic/eui/dist/eui_theme_dark.json';
|
|||
import themeLight from '@elastic/eui/dist/eui_theme_light.json';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { DiscoverGridContext } from './discover_grid_context';
|
||||
import { EsHitRecord } from '../../angular/context/api/context';
|
||||
import { EsHitRecord } from '../../types';
|
||||
/**
|
||||
* Button to expand a given row
|
||||
*/
|
||||
|
|
|
@ -21,7 +21,7 @@ import { ElasticSearchHit } from '../../doc_views/doc_views_types';
|
|||
import { DiscoverGridContext } from './discover_grid_context';
|
||||
import { JsonCodeEditor } from '../json_code_editor/json_code_editor';
|
||||
import { defaultMonacoEditorWidth } from './constants';
|
||||
import { EsHitRecord } from '../../angular/context/api/context';
|
||||
import { EsHitRecord } from '../../types';
|
||||
|
||||
export const getRenderCellValueFn = (
|
||||
indexPattern: IndexPattern,
|
||||
|
|
|
@ -15,7 +15,7 @@ interface Props {
|
|||
}
|
||||
/**
|
||||
* Responsible for rendering a tab provided by a render function.
|
||||
* So any other framework can be used (E.g. legacy Angular 3rd party plugin code)
|
||||
* Any other framework can be used
|
||||
* The provided `render` function is called with a reference to the
|
||||
* component's `HTMLDivElement` as 1st arg and `renderProps` as 2nd arg
|
||||
*/
|
||||
|
|
|
@ -61,7 +61,7 @@ export class DocViewerTab extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
if (render) {
|
||||
// doc view is provided by a render function, e.g. for legacy Angular code
|
||||
// doc view is provided by a render function
|
||||
return <DocViewRenderTab render={render} renderProps={renderProps} />;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ import { FieldIcon, FieldIconProps } from '../../../../../kibana_react/public';
|
|||
import { getFieldTypeName } from './field_type_name';
|
||||
import { IndexPatternField } from '../../../../../data/public';
|
||||
|
||||
// properties fieldType and fieldName are provided in kbn_doc_view
|
||||
// this should be changed when both components are deangularized
|
||||
interface Props {
|
||||
fieldName: string;
|
||||
fieldType?: string;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import React from 'react';
|
||||
import { mountWithIntl } from '@kbn/test/jest';
|
||||
import { SourceViewer } from './source_viewer';
|
||||
import * as hooks from '../doc/use_es_doc_search';
|
||||
import * as hooks from '../../services/use_es_doc_search';
|
||||
import * as useUiSettingHook from 'src/plugins/kibana_react/public/ui_settings/use_ui_setting';
|
||||
import { EuiButton, EuiEmptyPrompt, EuiLoadingSpinner } from '@elastic/eui';
|
||||
import { JsonCodeEditorCommon } from '../json_code_editor/json_code_editor_common';
|
||||
|
|
|
@ -12,11 +12,11 @@ import { FormattedMessage } from '@kbn/i18n/react';
|
|||
import { monaco } from '@kbn/monaco';
|
||||
import { EuiButton, EuiEmptyPrompt, EuiLoadingSpinner, EuiSpacer, EuiText } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useEsDocSearch } from '../doc/use_es_doc_search';
|
||||
import { JSONCodeEditorCommonMemoized } from '../json_code_editor/json_code_editor_common';
|
||||
import { ElasticRequestState } from '../doc/elastic_request_state';
|
||||
import { getServices } from '../../../../public/kibana_services';
|
||||
import { getServices } from '../../../kibana_services';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE } from '../../../../common';
|
||||
import { ElasticRequestState } from '../../apps/doc/types';
|
||||
import { useEsDocSearch } from '../../services/use_es_doc_search';
|
||||
|
||||
interface SourceViewerProps {
|
||||
id: string;
|
||||
|
|
|
@ -38,7 +38,7 @@ import {
|
|||
SORT_DEFAULT_ORDER_SETTING,
|
||||
} from '../../../common';
|
||||
import * as columnActions from '../apps/main/components/doc_table/actions/columns';
|
||||
import { handleSourceColumnState } from '../angular/helpers';
|
||||
import { handleSourceColumnState } from '../helpers/state_helpers';
|
||||
import { DiscoverGridProps } from '../components/discover_grid/discover_grid';
|
||||
import { DiscoverGridSettings } from '../components/discover_grid/types';
|
||||
import { DocTableProps } from '../apps/main/components/doc_table/doc_table_wrapper';
|
||||
|
|
|
@ -8,10 +8,7 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
DiscoverGridEmbeddable,
|
||||
DiscoverGridEmbeddableProps,
|
||||
} from '../angular/create_discover_grid_directive';
|
||||
import { DiscoverGridEmbeddable, DiscoverGridEmbeddableProps } from './saved_search_grid';
|
||||
import { DiscoverDocTableEmbeddable } from '../apps/main/components/doc_table/create_doc_table_embeddable';
|
||||
import { DocTableEmbeddableProps } from '../apps/main/components/doc_table/doc_table_embeddable';
|
||||
import { SearchProps } from './saved_search_embeddable';
|
||||
|
|
|
@ -44,28 +44,3 @@ export function DiscoverGridEmbeddable(props: DiscoverGridEmbeddableProps) {
|
|||
</I18nProvider>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* this is just needed for the embeddable
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function createDiscoverGridDirective(reactDirective: any) {
|
||||
return reactDirective(DiscoverGridEmbeddable, [
|
||||
['columns', { watchDepth: 'collection' }],
|
||||
['indexPattern', { watchDepth: 'reference' }],
|
||||
['isLoading', { watchDepth: 'reference' }],
|
||||
['onAddColumn', { watchDepth: 'reference', wrapApply: false }],
|
||||
['onFilter', { watchDepth: 'reference', wrapApply: false }],
|
||||
['onRemoveColumn', { watchDepth: 'reference', wrapApply: false }],
|
||||
['onSetColumns', { watchDepth: 'reference', wrapApply: false }],
|
||||
['onSort', { watchDepth: 'reference', wrapApply: false }],
|
||||
['rows', { watchDepth: 'collection' }],
|
||||
['sampleSize', { watchDepth: 'reference' }],
|
||||
['searchDescription', { watchDepth: 'reference' }],
|
||||
['searchTitle', { watchDepth: 'reference' }],
|
||||
['settings', { watchDepth: 'reference' }],
|
||||
['showTimeCol', { watchDepth: 'value' }],
|
||||
['sort', { watchDepth: 'value' }],
|
||||
['className', { watchDepth: 'value' }],
|
||||
]);
|
||||
}
|
|
@ -6,7 +6,6 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { auto } from 'angular';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { UiActionsStart } from 'src/plugins/ui_actions/public';
|
||||
import { getServices } from '../../kibana_services';
|
||||
|
@ -30,8 +29,6 @@ interface StartServices {
|
|||
export class SearchEmbeddableFactory
|
||||
implements EmbeddableFactoryDefinition<SearchInput, SearchOutput, SavedSearchEmbeddable> {
|
||||
public readonly type = SEARCH_EMBEDDABLE_TYPE;
|
||||
private $injector: auto.IInjectorService | null;
|
||||
private getInjector: () => Promise<auto.IInjectorService> | null;
|
||||
public readonly savedObjectMetaData = {
|
||||
name: i18n.translate('discover.savedSearch.savedObjectName', {
|
||||
defaultMessage: 'Saved search',
|
||||
|
@ -40,13 +37,7 @@ export class SearchEmbeddableFactory
|
|||
getIconForSavedObject: () => 'discoverApp',
|
||||
};
|
||||
|
||||
constructor(
|
||||
private getStartServices: () => Promise<StartServices>,
|
||||
getInjector: () => Promise<auto.IInjectorService>
|
||||
) {
|
||||
this.$injector = null;
|
||||
this.getInjector = getInjector;
|
||||
}
|
||||
constructor(private getStartServices: () => Promise<StartServices>) {}
|
||||
|
||||
public canCreateNew() {
|
||||
return false;
|
||||
|
@ -67,10 +58,6 @@ export class SearchEmbeddableFactory
|
|||
input: Partial<SearchInput> & { id: string; timeRange: TimeRange },
|
||||
parent?: Container
|
||||
): Promise<SavedSearchEmbeddable | ErrorEmbeddable> => {
|
||||
if (!this.$injector) {
|
||||
this.$injector = await this.getInjector();
|
||||
}
|
||||
|
||||
const filterManager = getServices().filterManager;
|
||||
|
||||
const url = await getServices().getSavedSearchUrlById(savedObjectId);
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { IUiSettingsClient } from 'src/core/public';
|
||||
import { IUiSettingsClient } from 'kibana/public';
|
||||
import { isEqual } from 'lodash';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE, DEFAULT_COLUMNS_SETTING } from '../../../../common';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE, DEFAULT_COLUMNS_SETTING } from '../../../common';
|
||||
|
||||
/**
|
||||
* Makes sure the current state is not referencing the source column when using the fields api
|
|
@ -11,7 +11,7 @@ import { useDataGridColumns } from './use_data_grid_columns';
|
|||
import { indexPatternMock } from '../../__mocks__/index_pattern';
|
||||
import { configMock } from '../../__mocks__/config';
|
||||
import { indexPatternsMock } from '../../__mocks__/index_patterns';
|
||||
import { AppState } from '../angular/context_state';
|
||||
import { AppState } from '../apps/context/services/context_state';
|
||||
import { Capabilities } from '../../../../../core/types';
|
||||
|
||||
describe('useDataGridColumns', () => {
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
import {
|
||||
AppState as ContextState,
|
||||
GetStateReturn as ContextGetStateReturn,
|
||||
} from '../angular/context_state';
|
||||
} from '../apps/context/services/context_state';
|
||||
import { getStateColumnActions } from '../apps/main/components/doc_table/actions/columns';
|
||||
|
||||
interface UseDataGridColumnsProps {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
@import 'angular/index';
|
|
@ -8,15 +8,15 @@
|
|||
|
||||
import { renderHook, act } from '@testing-library/react-hooks';
|
||||
import { buildSearchBody, useEsDocSearch } from './use_es_doc_search';
|
||||
import { DocProps } from './doc';
|
||||
import { Observable } from 'rxjs';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE as mockSearchFieldsFromSource } from '../../../../common';
|
||||
import { IndexPattern } from 'src/plugins/data/common';
|
||||
import { ElasticRequestState } from './elastic_request_state';
|
||||
import { DocProps } from '../apps/doc/components/doc';
|
||||
import { ElasticRequestState } from '../apps/doc/types';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE as mockSearchFieldsFromSource } from '../../../common';
|
||||
|
||||
const mockSearchResult = new Observable();
|
||||
|
||||
jest.mock('../../../kibana_services', () => ({
|
||||
jest.mock('../../kibana_services', () => ({
|
||||
getServices: () => ({
|
||||
data: {
|
||||
search: {
|
|
@ -8,11 +8,12 @@
|
|||
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import type { estypes } from '@elastic/elasticsearch';
|
||||
import { getServices, IndexPattern } from '../../../kibana_services';
|
||||
import { DocProps } from './doc';
|
||||
import { ElasticSearchHit } from '../../doc_views/doc_views_types';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE } from '../../../../common';
|
||||
import { ElasticRequestState } from './elastic_request_state';
|
||||
import { IndexPattern } from '../../../../data/common';
|
||||
import { DocProps } from '../apps/doc/components/doc';
|
||||
import { ElasticRequestState } from '../apps/doc/types';
|
||||
import { ElasticSearchHit } from '../doc_views/doc_views_types';
|
||||
import { getServices } from '../../kibana_services';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE } from '../../../common';
|
||||
|
||||
type RequestBody = Pick<estypes.SearchRequest, 'body'>;
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import type { estypes } from '@elastic/elasticsearch';
|
||||
|
||||
export enum FetchStatus {
|
||||
UNINITIALIZED = 'uninitialized',
|
||||
|
@ -13,3 +14,13 @@ export enum FetchStatus {
|
|||
COMPLETE = 'complete',
|
||||
ERROR = 'error',
|
||||
}
|
||||
|
||||
export type EsHitRecord = Required<
|
||||
Pick<estypes.SearchHit, '_id' | 'fields' | 'sort' | '_index' | '_version'>
|
||||
> & {
|
||||
_source?: Record<string, unknown>;
|
||||
_score?: number;
|
||||
// note that this a special property for Discover Context, to determine the anchor record
|
||||
isAnchor?: boolean;
|
||||
};
|
||||
export type EsHitRecordList = EsHitRecord[];
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
import { History } from 'history';
|
||||
|
||||
import type { auto } from 'angular';
|
||||
import {
|
||||
Capabilities,
|
||||
ChromeStart,
|
||||
|
@ -59,19 +58,17 @@ export interface DiscoverServices {
|
|||
toastNotifications: ToastsStart;
|
||||
getSavedSearchById: (id?: string) => Promise<SavedSearch>;
|
||||
getSavedSearchUrlById: (id: string) => Promise<string>;
|
||||
getEmbeddableInjector: () => Promise<auto.IInjectorService>;
|
||||
uiSettings: IUiSettingsClient;
|
||||
trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void;
|
||||
indexPatternFieldEditor: IndexPatternFieldEditorStart;
|
||||
http: HttpStart;
|
||||
}
|
||||
|
||||
export async function buildServices(
|
||||
export function buildServices(
|
||||
core: CoreStart,
|
||||
plugins: DiscoverStartPlugins,
|
||||
context: PluginInitializerContext,
|
||||
getEmbeddableInjector: () => Promise<auto.IInjectorService>
|
||||
): Promise<DiscoverServices> {
|
||||
context: PluginInitializerContext
|
||||
): DiscoverServices {
|
||||
const services = {
|
||||
savedObjectsClient: core.savedObjects.client,
|
||||
savedObjects: plugins.savedObjects,
|
||||
|
@ -88,7 +85,6 @@ export async function buildServices(
|
|||
docLinks: core.docLinks,
|
||||
theme: plugins.charts.theme,
|
||||
filterManager: plugins.data.query.filterManager,
|
||||
getEmbeddableInjector,
|
||||
getSavedSearchById: async (id?: string) => savedObjectService.get(id),
|
||||
getSavedSearchUrlById: async (id: string) => savedObjectService.urlFor(id),
|
||||
history: getHistory,
|
||||
|
|
|
@ -15,27 +15,9 @@ import { createGetterSetter } from '../../kibana_utils/public';
|
|||
import { search } from '../../data/public';
|
||||
import { DocViewsRegistry } from './application/doc_views/doc_views_registry';
|
||||
|
||||
let angularModule: ng.IModule | null = null;
|
||||
let services: DiscoverServices | null = null;
|
||||
let uiActions: UiActionsStart;
|
||||
|
||||
/**
|
||||
* set bootstrapped inner angular module
|
||||
*/
|
||||
export function setAngularModule(module: ng.IModule) {
|
||||
angularModule = module;
|
||||
}
|
||||
|
||||
/**
|
||||
* get boostrapped inner angular module
|
||||
*/
|
||||
export function getAngularModule(): ng.IModule {
|
||||
if (!angularModule) {
|
||||
throw new Error('Discover angular module not yet available');
|
||||
}
|
||||
return angularModule;
|
||||
}
|
||||
|
||||
export function getServices(): DiscoverServices {
|
||||
if (!services) {
|
||||
throw new Error('Discover services are not yet available');
|
||||
|
|
|
@ -8,10 +8,8 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import angular, { auto } from 'angular';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
|
||||
import {
|
||||
AppMountParameters,
|
||||
AppUpdater,
|
||||
|
@ -40,14 +38,12 @@ import { DocViewerTable } from './application/components/table/table';
|
|||
import {
|
||||
setDocViewsRegistry,
|
||||
setUrlTracker,
|
||||
setAngularModule,
|
||||
setServices,
|
||||
setHeaderActionMenuMounter,
|
||||
setUiActions,
|
||||
setScopedHistory,
|
||||
getScopedHistory,
|
||||
syncHistoryLocations,
|
||||
getServices,
|
||||
} from './kibana_services';
|
||||
import { createSavedSearchesLoader } from './saved_searches';
|
||||
import { registerFeature } from './register_feature';
|
||||
|
@ -78,7 +74,6 @@ export interface DiscoverSetup {
|
|||
docViews: {
|
||||
/**
|
||||
* Add new doc view shown along with table view and json view in the details of each document in Discover.
|
||||
* Both react and angular doc views are supported.
|
||||
* @param docViewRaw
|
||||
*/
|
||||
addDocView(docViewRaw: DocViewInput | DocViewInputFn): void;
|
||||
|
@ -121,7 +116,7 @@ export interface DiscoverStart {
|
|||
savedSearchLoader: SavedObjectLoader;
|
||||
|
||||
/**
|
||||
* @deprecated Use URL locator instead. URL generaotr will be removed.
|
||||
* @deprecated Use URL locator instead. URL generator will be removed.
|
||||
*/
|
||||
readonly urlGenerator: undefined | UrlGeneratorContract<'DISCOVER_APP_URL_GENERATOR'>;
|
||||
|
||||
|
@ -189,13 +184,9 @@ export interface DiscoverStartPlugins {
|
|||
indexPatternFieldEditor: IndexPatternFieldEditorStart;
|
||||
}
|
||||
|
||||
const innerAngularName = 'app/discover';
|
||||
const embeddableAngularName = 'app/discoverEmbeddable';
|
||||
|
||||
/**
|
||||
* Contains Discover, one of the oldest parts of Kibana
|
||||
* There are 2 kinds of Angular bootstrapped for rendering, additionally to the main Angular
|
||||
* Discover provides embeddables, those contain a slimmer Angular
|
||||
* Discover provides embeddables for Dashboards
|
||||
*/
|
||||
export class DiscoverPlugin
|
||||
implements Plugin<DiscoverSetup, DiscoverStart, DiscoverSetupPlugins, DiscoverStartPlugins> {
|
||||
|
@ -203,10 +194,7 @@ export class DiscoverPlugin
|
|||
|
||||
private appStateUpdater = new BehaviorSubject<AppUpdater>(() => ({}));
|
||||
private docViewsRegistry: DocViewsRegistry | null = null;
|
||||
private embeddableInjector: auto.IInjectorService | null = null;
|
||||
private stopUrlTracking: (() => void) | undefined = undefined;
|
||||
private servicesInitialized: boolean = false;
|
||||
private innerAngularInitialized: boolean = false;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
|
@ -214,13 +202,6 @@ export class DiscoverPlugin
|
|||
private urlGenerator?: DiscoverStart['urlGenerator'];
|
||||
private locator?: DiscoverAppLocator;
|
||||
|
||||
/**
|
||||
* why are those functions public? they are needed for some mocha tests
|
||||
* can be removed once all is Jest
|
||||
*/
|
||||
public initializeInnerAngular?: () => void;
|
||||
public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>;
|
||||
|
||||
setup(
|
||||
core: CoreSetup<DiscoverStartPlugins, DiscoverStart>,
|
||||
plugins: DiscoverSetupPlugins
|
||||
|
@ -326,12 +307,7 @@ export class DiscoverPlugin
|
|||
defaultPath: '#/',
|
||||
category: DEFAULT_APP_CATEGORIES.kibana,
|
||||
mount: async (params: AppMountParameters) => {
|
||||
if (!this.initializeServices) {
|
||||
throw Error('Discover plugin method initializeServices is undefined');
|
||||
}
|
||||
if (!this.initializeInnerAngular) {
|
||||
throw Error('Discover plugin method initializeInnerAngular is undefined');
|
||||
}
|
||||
const [, depsStart] = await core.getStartServices();
|
||||
setScopedHistory(params.history);
|
||||
setHeaderActionMenuMounter(params.setHeaderActionMenu);
|
||||
syncHistoryLocations();
|
||||
|
@ -341,17 +317,11 @@ export class DiscoverPlugin
|
|||
const unlistenParentHistory = params.history.listen(() => {
|
||||
window.dispatchEvent(new HashChangeEvent('hashchange'));
|
||||
});
|
||||
const {
|
||||
plugins: { data: dataStart },
|
||||
} = await this.initializeServices();
|
||||
await this.initializeInnerAngular();
|
||||
|
||||
// make sure the index pattern list is up to date
|
||||
await dataStart.indexPatterns.clearCache();
|
||||
await depsStart.data.indexPatterns.clearCache();
|
||||
|
||||
const { renderApp } = await import('./application/application');
|
||||
params.element.classList.add('dscAppWrapper');
|
||||
const unmount = await renderApp(innerAngularName, params.element);
|
||||
const unmount = await renderApp('discover', params.element);
|
||||
return () => {
|
||||
params.element.classList.remove('dscAppWrapper');
|
||||
unlistenParentHistory();
|
||||
|
@ -400,42 +370,13 @@ export class DiscoverPlugin
|
|||
start(core: CoreStart, plugins: DiscoverStartPlugins) {
|
||||
// we need to register the application service at setup, but to render it
|
||||
// there are some start dependencies necessary, for this reason
|
||||
// initializeInnerAngular + initializeServices are assigned at start and used
|
||||
// initializeServices are assigned at start and used
|
||||
// when the application/embeddable is mounted
|
||||
this.initializeInnerAngular = async () => {
|
||||
if (this.innerAngularInitialized) {
|
||||
return;
|
||||
}
|
||||
// this is used by application mount and tests
|
||||
const { getInnerAngularModule } = await import('./application/angular/get_inner_angular');
|
||||
await plugins.kibanaLegacy.loadAngularBootstrap();
|
||||
const module = getInnerAngularModule(
|
||||
innerAngularName,
|
||||
core,
|
||||
plugins,
|
||||
this.initializerContext
|
||||
);
|
||||
setAngularModule(module);
|
||||
this.innerAngularInitialized = true;
|
||||
};
|
||||
|
||||
setUiActions(plugins.uiActions);
|
||||
|
||||
this.initializeServices = async () => {
|
||||
if (this.servicesInitialized) {
|
||||
return { core, plugins };
|
||||
}
|
||||
const services = await buildServices(
|
||||
core,
|
||||
plugins,
|
||||
this.initializerContext,
|
||||
this.getEmbeddableInjector
|
||||
);
|
||||
setServices(services);
|
||||
this.servicesInitialized = true;
|
||||
|
||||
return { core, plugins };
|
||||
};
|
||||
const services = buildServices(core, plugins, this.initializerContext);
|
||||
setServices(services);
|
||||
|
||||
return {
|
||||
urlGenerator: this.urlGenerator,
|
||||
|
@ -453,14 +394,7 @@ export class DiscoverPlugin
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* register embeddable with a slimmer embeddable version of inner angular
|
||||
*/
|
||||
private registerEmbeddable(core: CoreSetup<DiscoverStartPlugins>, plugins: DiscoverSetupPlugins) {
|
||||
if (!this.getEmbeddableInjector) {
|
||||
throw Error('Discover plugin method getEmbeddableInjector is undefined');
|
||||
}
|
||||
|
||||
const getStartServices = async () => {
|
||||
const [coreStart, deps] = await core.getStartServices();
|
||||
return {
|
||||
|
@ -469,25 +403,7 @@ export class DiscoverPlugin
|
|||
};
|
||||
};
|
||||
|
||||
const factory = new SearchEmbeddableFactory(getStartServices, this.getEmbeddableInjector);
|
||||
const factory = new SearchEmbeddableFactory(getStartServices);
|
||||
plugins.embeddable.registerEmbeddableFactory(factory.type, factory);
|
||||
}
|
||||
|
||||
private getEmbeddableInjector = async () => {
|
||||
if (!this.embeddableInjector) {
|
||||
if (!this.initializeServices) {
|
||||
throw Error('Discover plugin getEmbeddableInjector: initializeServices is undefined');
|
||||
}
|
||||
const { core, plugins } = await this.initializeServices();
|
||||
await getServices().kibanaLegacy.loadAngularBootstrap();
|
||||
const { getInnerAngularModuleEmbeddable } = await import(
|
||||
'./application/angular/get_inner_angular'
|
||||
);
|
||||
getInnerAngularModuleEmbeddable(embeddableAngularName, core, plugins);
|
||||
const mountpoint = document.createElement('div');
|
||||
this.embeddableInjector = angular.bootstrap(mountpoint, [embeddableAngularName]);
|
||||
}
|
||||
|
||||
return this.embeddableInjector;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue