mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Migrate doc view part of discover (#58094)
This commit is contained in:
parent
6de7f2a62b
commit
3e26777965
65 changed files with 606 additions and 168 deletions
|
@ -3,6 +3,7 @@
|
|||
"common.ui": "src/legacy/ui",
|
||||
"console": "src/plugins/console",
|
||||
"core": "src/core",
|
||||
"discover": "src/plugins/discover",
|
||||
"dashboard": "src/plugins/dashboard",
|
||||
"data": "src/plugins/data",
|
||||
"embeddableApi": "src/plugins/embeddable",
|
||||
|
|
|
@ -1233,11 +1233,11 @@ This table shows where these uiExports have moved to in the New Platform. In mos
|
|||
| `chromeNavControls` | [`core.chrome.navControls.register{Left,Right}`](/docs/development/core/public/kibana-plugin-public.chromenavcontrols.md) | |
|
||||
| `contextMenuActions` | | Should be an API on the devTools plugin. |
|
||||
| `devTools` | | |
|
||||
| `docViews` | | |
|
||||
| `docViews` | [`plugins.discover.docViews.addDocView`](./src/plugins/discover/public/doc_views) | Should be an API on the discover plugin. |
|
||||
| `embeddableActions` | | Should be an API on the embeddables plugin. |
|
||||
| `embeddableFactories` | | Should be an API on the embeddables plugin. |
|
||||
| `fieldFormatEditors` | | |
|
||||
| `fieldFormats` | [`plugins.data.fieldFormats`](./src/plugins/data/public/field_formats) | |
|
||||
| `fieldFormatEditors` | | |
|
||||
| `fieldFormats` | [`plugins.data.fieldFormats`](./src/plugins/data/public/field_formats) | |
|
||||
| `hacks` | n/a | Just run the code in your plugin's `start` method. |
|
||||
| `home` | [`plugins.home.featureCatalogue.register`](./src/plugins/home/public/feature_catalogue) | Must add `home` as a dependency in your kibana.json. |
|
||||
| `indexManagement` | | Should be an API on the indexManagement plugin. |
|
||||
|
|
|
@ -35,10 +35,13 @@ import {
|
|||
|
||||
import { DiscoverStartPlugins } from './plugin';
|
||||
import { SharePluginStart } from '../../../../../plugins/share/public';
|
||||
import { DocViewsRegistry } from './np_ready/doc_views/doc_views_registry';
|
||||
import { ChartsPluginStart } from '../../../../../plugins/charts/public';
|
||||
import { VisualizationsStart } from '../../../visualizations/public';
|
||||
import { createSavedSearchesLoader, SavedSearch } from '../../../../../plugins/discover/public';
|
||||
import {
|
||||
createSavedSearchesLoader,
|
||||
DocViewerComponent,
|
||||
SavedSearch,
|
||||
} from '../../../../../plugins/discover/public';
|
||||
|
||||
export interface DiscoverServices {
|
||||
addBasePath: (path: string) => string;
|
||||
|
@ -47,7 +50,7 @@ export interface DiscoverServices {
|
|||
core: CoreStart;
|
||||
data: DataPublicPluginStart;
|
||||
docLinks: DocLinksStart;
|
||||
docViewsRegistry: DocViewsRegistry;
|
||||
DocViewer: DocViewerComponent;
|
||||
history: History;
|
||||
theme: ChartsPluginStart['theme'];
|
||||
filterManager: FilterManager;
|
||||
|
@ -64,8 +67,7 @@ export interface DiscoverServices {
|
|||
}
|
||||
export async function buildServices(
|
||||
core: CoreStart,
|
||||
plugins: DiscoverStartPlugins,
|
||||
docViewsRegistry: DocViewsRegistry
|
||||
plugins: DiscoverStartPlugins
|
||||
): Promise<DiscoverServices> {
|
||||
const services = {
|
||||
savedObjectsClient: core.savedObjects.client,
|
||||
|
@ -81,7 +83,7 @@ export async function buildServices(
|
|||
core,
|
||||
data: plugins.data,
|
||||
docLinks: core.docLinks,
|
||||
docViewsRegistry,
|
||||
DocViewer: plugins.discover.docViews.DocViewer,
|
||||
history: createHashHistory(),
|
||||
theme: plugins.charts.theme,
|
||||
filterManager: plugins.data.query.filterManager,
|
||||
|
|
|
@ -75,7 +75,6 @@ export {
|
|||
EsQuerySortValue,
|
||||
SortDirection,
|
||||
} from '../../../../../plugins/data/public';
|
||||
export { ElasticSearchHit } from './np_ready/doc_views/doc_views_types';
|
||||
export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities';
|
||||
// @ts-ignore
|
||||
export { buildPointSeriesData } from 'ui/agg_response/point_series/point_series';
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { FieldName } from './field_name/field_name';
|
||||
import { FieldName } from '../../../../../../../../plugins/discover/public';
|
||||
import { getServices, wrapInI18nContext } from '../../../kibana_services';
|
||||
|
||||
export function FieldNameDirectiveProvider(reactDirective) {
|
||||
|
|
|
@ -17,11 +17,15 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { DocViewer } from '../components/doc_viewer/doc_viewer';
|
||||
import React from 'react';
|
||||
import { getServices } from '../../kibana_services';
|
||||
|
||||
export function createDocViewerDirective(reactDirective: any) {
|
||||
return reactDirective(
|
||||
DocViewer,
|
||||
(props: any) => {
|
||||
const { DocViewer } = getServices();
|
||||
return <DocViewer {...props} />;
|
||||
},
|
||||
[
|
||||
'hit',
|
||||
['indexPattern', { watchDepth: 'reference' }],
|
|
@ -1,3 +1,2 @@
|
|||
@import 'fetch_error/index';
|
||||
@import 'field_chooser/index';
|
||||
@import 'doc_viewer/index';
|
||||
|
|
|
@ -24,19 +24,13 @@ import { ReactWrapper } from 'enzyme';
|
|||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { Doc, DocProps } from './doc';
|
||||
|
||||
jest.mock('../doc_viewer/doc_viewer', () => ({
|
||||
DocViewer: () => null,
|
||||
}));
|
||||
|
||||
jest.mock('../../../kibana_services', () => {
|
||||
return {
|
||||
getServices: () => ({
|
||||
metadata: {
|
||||
branch: 'test',
|
||||
},
|
||||
getDocViewsSorted: () => {
|
||||
return [];
|
||||
},
|
||||
DocViewer: () => null,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
|
|
@ -20,9 +20,9 @@ import React from 'react';
|
|||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { EuiCallOut, EuiLink, EuiLoadingSpinner, EuiPageContent } from '@elastic/eui';
|
||||
import { IndexPatternsContract } from 'src/plugins/data/public';
|
||||
import { DocViewer } from '../doc_viewer/doc_viewer';
|
||||
import { ElasticRequestState, useEsDocSearch } from './use_es_doc_search';
|
||||
import { ElasticSearchHit, getServices } from '../../../kibana_services';
|
||||
import { getServices } from '../../../kibana_services';
|
||||
import { ElasticSearchHit } from '../../../../../../../../plugins/discover/public';
|
||||
|
||||
export interface ElasticSearchResult {
|
||||
hits: {
|
||||
|
@ -61,6 +61,7 @@ export interface DocProps {
|
|||
}
|
||||
|
||||
export function Doc(props: DocProps) {
|
||||
const { DocViewer } = getServices();
|
||||
const [reqState, hit, indexPattern] = useEsDocSearch(props);
|
||||
|
||||
return (
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
* under the License.
|
||||
*/
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ElasticSearchHit, IndexPattern } from '../../../kibana_services';
|
||||
import { IndexPattern } from '../../../kibana_services';
|
||||
import { DocProps } from './doc';
|
||||
import { ElasticSearchHit } from '../../../../../../../../plugins/discover/public';
|
||||
|
||||
export enum ElasticRequestState {
|
||||
Loading,
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from 'kibana/public';
|
||||
import angular, { auto } from 'angular';
|
||||
import { UiActionsSetup, UiActionsStart } from 'src/plugins/ui_actions/public';
|
||||
|
@ -41,10 +40,7 @@ import {
|
|||
KibanaLegacySetup,
|
||||
AngularRenderedAppUpdater,
|
||||
} from '../../../../../plugins/kibana_legacy/public';
|
||||
import { DocViewsRegistry } from './np_ready/doc_views/doc_views_registry';
|
||||
import { DocViewInput, DocViewInputFn } from './np_ready/doc_views/doc_views_types';
|
||||
import { DocViewTable } from './np_ready/components/table/table';
|
||||
import { JsonCodeBlock } from './np_ready/components/json_code_block/json_code_block';
|
||||
import { DiscoverSetup, DiscoverStart } from '../../../../../plugins/discover/public';
|
||||
import { HomePublicPluginSetup } from '../../../../../plugins/home/public';
|
||||
import {
|
||||
VisualizationsStart,
|
||||
|
@ -52,15 +48,6 @@ import {
|
|||
} from '../../../visualizations/public/np_ready/public';
|
||||
import { createKbnUrlTracker } from '../../../../../plugins/kibana_utils/public';
|
||||
|
||||
/**
|
||||
* These are the interfaces with your public contracts. You should export these
|
||||
* for other plugins to use in _their_ `SetupDeps`/`StartDeps` interfaces.
|
||||
* @public
|
||||
*/
|
||||
export interface DiscoverSetup {
|
||||
addDocView(docViewRaw: DocViewInput | DocViewInputFn): void;
|
||||
}
|
||||
export type DiscoverStart = void;
|
||||
export interface DiscoverSetupPlugins {
|
||||
uiActions: UiActionsSetup;
|
||||
embeddable: EmbeddableSetup;
|
||||
|
@ -68,6 +55,7 @@ export interface DiscoverSetupPlugins {
|
|||
home: HomePublicPluginSetup;
|
||||
visualizations: VisualizationsSetup;
|
||||
data: DataPublicPluginSetup;
|
||||
discover: DiscoverSetup;
|
||||
}
|
||||
export interface DiscoverStartPlugins {
|
||||
uiActions: UiActionsStart;
|
||||
|
@ -78,6 +66,7 @@ export interface DiscoverStartPlugins {
|
|||
share: SharePluginStart;
|
||||
inspector: any;
|
||||
visualizations: VisualizationsStart;
|
||||
discover: DiscoverStart;
|
||||
}
|
||||
const innerAngularName = 'app/discover';
|
||||
const embeddableAngularName = 'app/discoverEmbeddable';
|
||||
|
@ -87,10 +76,9 @@ const embeddableAngularName = 'app/discoverEmbeddable';
|
|||
* There are 2 kinds of Angular bootstrapped for rendering, additionally to the main Angular
|
||||
* Discover provides embeddables, those contain a slimmer Angular
|
||||
*/
|
||||
export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> {
|
||||
export class DiscoverPlugin implements Plugin<void, void> {
|
||||
private servicesInitialized: boolean = false;
|
||||
private innerAngularInitialized: boolean = false;
|
||||
private docViewsRegistry: DocViewsRegistry | null = null;
|
||||
private embeddableInjector: auto.IInjectorService | null = null;
|
||||
private getEmbeddableInjector: (() => Promise<auto.IInjectorService>) | null = null;
|
||||
private appStateUpdater = new BehaviorSubject<AngularRenderedAppUpdater>(() => ({}));
|
||||
|
@ -103,7 +91,7 @@ export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> {
|
|||
public initializeInnerAngular?: () => void;
|
||||
public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>;
|
||||
|
||||
setup(core: CoreSetup<DiscoverStartPlugins>, plugins: DiscoverSetupPlugins): DiscoverSetup {
|
||||
setup(core: CoreSetup<DiscoverStartPlugins>, plugins: DiscoverSetupPlugins) {
|
||||
const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({
|
||||
baseUrl: core.http.basePath.prepend('/app/kibana'),
|
||||
defaultSubUrl: '#/discover',
|
||||
|
@ -130,21 +118,7 @@ export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> {
|
|||
};
|
||||
|
||||
this.getEmbeddableInjector = this.getInjector.bind(this);
|
||||
this.docViewsRegistry = new DocViewsRegistry(this.getEmbeddableInjector);
|
||||
this.docViewsRegistry.addDocView({
|
||||
title: i18n.translate('kbn.discover.docViews.table.tableTitle', {
|
||||
defaultMessage: 'Table',
|
||||
}),
|
||||
order: 10,
|
||||
component: DocViewTable,
|
||||
});
|
||||
this.docViewsRegistry.addDocView({
|
||||
title: i18n.translate('kbn.discover.docViews.json.jsonTitle', {
|
||||
defaultMessage: 'JSON',
|
||||
}),
|
||||
order: 20,
|
||||
component: JsonCodeBlock,
|
||||
});
|
||||
plugins.discover.docViews.setAngularInjectorGetter(this.getEmbeddableInjector);
|
||||
plugins.kibanaLegacy.registerLegacyApp({
|
||||
id: 'discover',
|
||||
title: 'Discover',
|
||||
|
@ -172,14 +146,10 @@ export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> {
|
|||
},
|
||||
});
|
||||
registerFeature(plugins.home);
|
||||
|
||||
this.registerEmbeddable(core, plugins);
|
||||
return {
|
||||
addDocView: this.docViewsRegistry.addDocView.bind(this.docViewsRegistry),
|
||||
};
|
||||
}
|
||||
|
||||
start(core: CoreStart, plugins: DiscoverStartPlugins): DiscoverStart {
|
||||
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
|
||||
|
@ -198,7 +168,7 @@ export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> {
|
|||
if (this.servicesInitialized) {
|
||||
return { core, plugins };
|
||||
}
|
||||
const services = await buildServices(core, plugins, this.docViewsRegistry!);
|
||||
const services = await buildServices(core, plugins);
|
||||
setServices(services);
|
||||
this.servicesInitialized = true;
|
||||
|
||||
|
|
|
@ -271,6 +271,12 @@ export const npSetup = {
|
|||
}),
|
||||
},
|
||||
},
|
||||
discover: {
|
||||
docViews: {
|
||||
addDocView: sinon.fake(),
|
||||
setAngularInjectorGetter: sinon.fake(),
|
||||
},
|
||||
},
|
||||
visTypeVega: {
|
||||
config: sinon.fake(),
|
||||
},
|
||||
|
@ -459,6 +465,11 @@ export const npStart = {
|
|||
useChartsTheme: sinon.fake(),
|
||||
},
|
||||
},
|
||||
discover: {
|
||||
docViews: {
|
||||
DocViewer: () => null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ import {
|
|||
NavigationPublicPluginStart,
|
||||
} from '../../../../plugins/navigation/public';
|
||||
import { VisTypeVegaSetup } from '../../../../plugins/vis_type_vega/public';
|
||||
import { DiscoverSetup, DiscoverStart } from '../../../../plugins/discover/public';
|
||||
|
||||
export interface PluginsSetup {
|
||||
bfetch: BfetchPublicSetup;
|
||||
|
@ -83,6 +84,7 @@ export interface PluginsSetup {
|
|||
advancedSettings: AdvancedSettingsSetup;
|
||||
management: ManagementSetup;
|
||||
visTypeVega: VisTypeVegaSetup;
|
||||
discover: DiscoverSetup;
|
||||
telemetry?: TelemetryPluginSetup;
|
||||
}
|
||||
|
||||
|
@ -100,6 +102,7 @@ export interface PluginsStart {
|
|||
share: SharePluginStart;
|
||||
management: ManagementStart;
|
||||
advancedSettings: AdvancedSettingsStart;
|
||||
discover: DiscoverStart;
|
||||
telemetry?: TelemetryPluginStart;
|
||||
}
|
||||
|
||||
|
|
6
src/plugins/discover/kibana.json
Normal file
6
src/plugins/discover/kibana.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"id": "discover",
|
||||
"version": "kibana",
|
||||
"server": false,
|
||||
"ui": true
|
||||
}
|
1
src/plugins/discover/public/components/_index.scss
Normal file
1
src/plugins/discover/public/components/_index.scss
Normal file
|
@ -0,0 +1 @@
|
|||
@import 'doc_viewer/index';
|
|
@ -21,37 +21,33 @@ import { mount, shallow } from 'enzyme';
|
|||
import { DocViewer } from './doc_viewer';
|
||||
// @ts-ignore
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { getServices } from '../../../kibana_services';
|
||||
import { getDocViewsRegistry } from '../../services';
|
||||
import { DocViewRenderProps } from '../../doc_views/doc_views_types';
|
||||
|
||||
jest.mock('../../../kibana_services', () => {
|
||||
jest.mock('../../services', () => {
|
||||
let registry: any[] = [];
|
||||
return {
|
||||
getServices: () => ({
|
||||
docViewsRegistry: {
|
||||
addDocView(view: any) {
|
||||
registry.push(view);
|
||||
},
|
||||
getDocViewsSorted() {
|
||||
return registry;
|
||||
},
|
||||
getDocViewsRegistry: () => ({
|
||||
addDocView(view: any) {
|
||||
registry.push(view);
|
||||
},
|
||||
getDocViewsSorted() {
|
||||
return registry;
|
||||
},
|
||||
resetRegistry: () => {
|
||||
registry = [];
|
||||
},
|
||||
}),
|
||||
formatMsg: (x: any) => String(x),
|
||||
formatStack: (x: any) => String(x),
|
||||
};
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
(getServices() as any).resetRegistry();
|
||||
(getDocViewsRegistry() as any).resetRegistry();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('Render <DocViewer/> with 3 different tabs', () => {
|
||||
const registry = getServices().docViewsRegistry;
|
||||
const registry = getDocViewsRegistry();
|
||||
registry.addDocView({ order: 10, title: 'Render function', render: jest.fn() });
|
||||
registry.addDocView({ order: 20, title: 'React component', component: () => <div>test</div> });
|
||||
registry.addDocView({ order: 30, title: 'Invalid doc view' });
|
||||
|
@ -69,7 +65,7 @@ test('Render <DocViewer/> with 1 tab displaying error message', () => {
|
|||
return null;
|
||||
}
|
||||
|
||||
const registry = getServices().docViewsRegistry;
|
||||
const registry = getDocViewsRegistry();
|
||||
registry.addDocView({
|
||||
order: 10,
|
||||
title: 'React component',
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { EuiTabbedContent } from '@elastic/eui';
|
||||
import { getServices } from '../../../kibana_services';
|
||||
import { getDocViewsRegistry } from '../../services';
|
||||
import { DocViewerTab } from './doc_viewer_tab';
|
||||
import { DocView, DocViewRenderProps } from '../../doc_views/doc_views_types';
|
||||
|
||||
|
@ -29,7 +29,7 @@ import { DocView, DocViewRenderProps } from '../../doc_views/doc_views_types';
|
|||
* a `render` function.
|
||||
*/
|
||||
export function DocViewer(renderProps: DocViewRenderProps) {
|
||||
const { docViewsRegistry } = getServices();
|
||||
const docViewsRegistry = getDocViewsRegistry();
|
||||
const tabs = docViewsRegistry
|
||||
.getDocViewsSorted(renderProps.hit)
|
||||
.map(({ title, render, component }: DocView, idx: number) => {
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { EuiCallOut, EuiCodeBlock } from '@elastic/eui';
|
||||
import { formatMsg, formatStack } from '../../../kibana_services';
|
||||
import { formatMsg, formatStack } from '../../../../kibana_legacy/public';
|
||||
|
||||
interface Props {
|
||||
error: Error | string;
|
|
@ -20,8 +20,8 @@ import React from 'react';
|
|||
import classNames from 'classnames';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui';
|
||||
|
||||
import { FieldIcon, FieldIconProps } from '../../../../../../../../../plugins/kibana_react/public';
|
||||
import { shortenDottedString } from '../../../helpers';
|
||||
import { FieldIcon, FieldIconProps } from '../../../../kibana_react/public';
|
||||
import { shortenDottedString } from '../../helpers';
|
||||
import { getFieldTypeName } from './field_type_name';
|
||||
|
||||
// property field is provided at discover's field chooser
|
|
@ -21,52 +21,52 @@ import { i18n } from '@kbn/i18n';
|
|||
export function getFieldTypeName(type: string) {
|
||||
switch (type) {
|
||||
case 'boolean':
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.booleanAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.booleanAriaLabel', {
|
||||
defaultMessage: 'Boolean field',
|
||||
});
|
||||
case 'conflict':
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.conflictFieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.conflictFieldAriaLabel', {
|
||||
defaultMessage: 'Conflicting field',
|
||||
});
|
||||
case 'date':
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.dateFieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.dateFieldAriaLabel', {
|
||||
defaultMessage: 'Date field',
|
||||
});
|
||||
case 'geo_point':
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.geoPointFieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.geoPointFieldAriaLabel', {
|
||||
defaultMessage: 'Geo point field',
|
||||
});
|
||||
case 'geo_shape':
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.geoShapeFieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.geoShapeFieldAriaLabel', {
|
||||
defaultMessage: 'Geo shape field',
|
||||
});
|
||||
case 'ip':
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.ipAddressFieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.ipAddressFieldAriaLabel', {
|
||||
defaultMessage: 'IP address field',
|
||||
});
|
||||
case 'murmur3':
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.murmur3FieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.murmur3FieldAriaLabel', {
|
||||
defaultMessage: 'Murmur3 field',
|
||||
});
|
||||
case 'number':
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.numberFieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.numberFieldAriaLabel', {
|
||||
defaultMessage: 'Number field',
|
||||
});
|
||||
case 'source':
|
||||
// Note that this type is currently not provided, type for _source is undefined
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.sourceFieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.sourceFieldAriaLabel', {
|
||||
defaultMessage: 'Source field',
|
||||
});
|
||||
case 'string':
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.stringFieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.stringFieldAriaLabel', {
|
||||
defaultMessage: 'String field',
|
||||
});
|
||||
case 'nested':
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.nestedFieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.nestedFieldAriaLabel', {
|
||||
defaultMessage: 'Nested field',
|
||||
});
|
||||
default:
|
||||
return i18n.translate('kbn.discover.fieldNameIcons.unknownFieldAriaLabel', {
|
||||
return i18n.translate('discover.fieldNameIcons.unknownFieldAriaLabel', {
|
||||
defaultMessage: 'Unknown field',
|
||||
});
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { JsonCodeBlock } from './json_code_block';
|
||||
import { IndexPattern } from '../../../kibana_services';
|
||||
import { IndexPattern } from '../../../../data/public';
|
||||
|
||||
it('returns the `JsonCodeEditor` component', () => {
|
||||
const props = {
|
|
@ -22,7 +22,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { DocViewRenderProps } from '../../doc_views/doc_views_types';
|
||||
|
||||
export function JsonCodeBlock({ hit }: DocViewRenderProps) {
|
||||
const label = i18n.translate('kbn.discover.docViews.json.codeEditorAriaLabel', {
|
||||
const label = i18n.translate('discover.docViews.json.codeEditorAriaLabel', {
|
||||
defaultMessage: 'Read only JSON view of an elasticsearch document',
|
||||
});
|
||||
return (
|
|
@ -21,10 +21,7 @@ import { mount } from 'enzyme';
|
|||
// @ts-ignore
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { DocViewTable } from './table';
|
||||
|
||||
import { IndexPattern, indexPatterns } from '../../../kibana_services';
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
import { indexPatterns, IndexPattern } from '../../../../data/public';
|
||||
|
||||
const indexPattern = {
|
||||
fields: [
|
|
@ -26,7 +26,7 @@ import { DocViewTableRowBtnCollapse } from './table_row_btn_collapse';
|
|||
import { DocViewTableRowBtnFilterExists } from './table_row_btn_filter_exists';
|
||||
import { DocViewTableRowIconNoMapping } from './table_row_icon_no_mapping';
|
||||
import { DocViewTableRowIconUnderscore } from './table_row_icon_underscore';
|
||||
import { FieldName } from '../../angular/directives/field_name/field_name';
|
||||
import { FieldName } from '../field_name/field_name';
|
||||
|
||||
export interface Props {
|
||||
field: string;
|
|
@ -26,7 +26,7 @@ export interface Props {
|
|||
}
|
||||
|
||||
export function DocViewTableRowBtnCollapse({ onClick, isCollapsed }: Props) {
|
||||
const label = i18n.translate('kbn.discover.docViews.table.toggleFieldDetails', {
|
||||
const label = i18n.translate('discover.docViews.table.toggleFieldDetails', {
|
||||
defaultMessage: 'Toggle field details',
|
||||
});
|
||||
return (
|
|
@ -29,12 +29,12 @@ export interface Props {
|
|||
export function DocViewTableRowBtnFilterAdd({ onClick, disabled = false }: Props) {
|
||||
const tooltipContent = disabled ? (
|
||||
<FormattedMessage
|
||||
id="kbn.discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip"
|
||||
id="discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip"
|
||||
defaultMessage="Unindexed fields can not be searched"
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="kbn.discover.docViews.table.filterForValueButtonTooltip"
|
||||
id="discover.docViews.table.filterForValueButtonTooltip"
|
||||
defaultMessage="Filter for value"
|
||||
/>
|
||||
);
|
||||
|
@ -42,7 +42,7 @@ export function DocViewTableRowBtnFilterAdd({ onClick, disabled = false }: Props
|
|||
return (
|
||||
<EuiToolTip content={tooltipContent}>
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate('kbn.discover.docViews.table.filterForValueButtonAriaLabel', {
|
||||
aria-label={i18n.translate('discover.docViews.table.filterForValueButtonAriaLabel', {
|
||||
defaultMessage: 'Filter for value',
|
||||
})}
|
||||
className="kbnDocViewer__actionButton"
|
|
@ -35,18 +35,18 @@ export function DocViewTableRowBtnFilterExists({
|
|||
const tooltipContent = disabled ? (
|
||||
scripted ? (
|
||||
<FormattedMessage
|
||||
id="kbn.discover.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip"
|
||||
id="discover.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip"
|
||||
defaultMessage="Unable to filter for presence of scripted fields"
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="kbn.discover.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip"
|
||||
id="discover.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip"
|
||||
defaultMessage="Unable to filter for presence of meta fields"
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="kbn.discover.docViews.table.filterForFieldPresentButtonTooltip"
|
||||
id="discover.docViews.table.filterForFieldPresentButtonTooltip"
|
||||
defaultMessage="Filter for field present"
|
||||
/>
|
||||
);
|
||||
|
@ -54,12 +54,9 @@ export function DocViewTableRowBtnFilterExists({
|
|||
return (
|
||||
<EuiToolTip content={tooltipContent}>
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate(
|
||||
'kbn.discover.docViews.table.filterForFieldPresentButtonAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Filter for field present',
|
||||
}
|
||||
)}
|
||||
aria-label={i18n.translate('discover.docViews.table.filterForFieldPresentButtonAriaLabel', {
|
||||
defaultMessage: 'Filter for field present',
|
||||
})}
|
||||
onClick={onClick}
|
||||
className="kbnDocViewer__actionButton"
|
||||
data-test-subj="addExistsFilterButton"
|
|
@ -29,12 +29,12 @@ export interface Props {
|
|||
export function DocViewTableRowBtnFilterRemove({ onClick, disabled = false }: Props) {
|
||||
const tooltipContent = disabled ? (
|
||||
<FormattedMessage
|
||||
id="kbn.discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip"
|
||||
id="discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip"
|
||||
defaultMessage="Unindexed fields can not be searched"
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="kbn.discover.docViews.table.filterOutValueButtonTooltip"
|
||||
id="discover.docViews.table.filterOutValueButtonTooltip"
|
||||
defaultMessage="Filter out value"
|
||||
/>
|
||||
);
|
||||
|
@ -42,7 +42,7 @@ export function DocViewTableRowBtnFilterRemove({ onClick, disabled = false }: Pr
|
|||
return (
|
||||
<EuiToolTip content={tooltipContent}>
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate('kbn.discover.docViews.table.filterOutValueButtonAriaLabel', {
|
||||
aria-label={i18n.translate('discover.docViews.table.filterOutValueButtonAriaLabel', {
|
||||
defaultMessage: 'Filter out value',
|
||||
})}
|
||||
className="kbnDocViewer__actionButton"
|
|
@ -31,12 +31,9 @@ export function DocViewTableRowBtnToggleColumn({ onClick, active, disabled = fal
|
|||
if (disabled) {
|
||||
return (
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate(
|
||||
'kbn.discover.docViews.table.toggleColumnInTableButtonAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Toggle column in table',
|
||||
}
|
||||
)}
|
||||
aria-label={i18n.translate('discover.docViews.table.toggleColumnInTableButtonAriaLabel', {
|
||||
defaultMessage: 'Toggle column in table',
|
||||
})}
|
||||
className="kbnDocViewer__actionButton"
|
||||
data-test-subj="toggleColumnButton"
|
||||
disabled
|
||||
|
@ -49,18 +46,15 @@ export function DocViewTableRowBtnToggleColumn({ onClick, active, disabled = fal
|
|||
<EuiToolTip
|
||||
content={
|
||||
<FormattedMessage
|
||||
id="kbn.discover.docViews.table.toggleColumnInTableButtonTooltip"
|
||||
id="discover.docViews.table.toggleColumnInTableButtonTooltip"
|
||||
defaultMessage="Toggle column in table"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate(
|
||||
'kbn.discover.docViews.table.toggleColumnInTableButtonAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Toggle column in table',
|
||||
}
|
||||
)}
|
||||
aria-label={i18n.translate('discover.docViews.table.toggleColumnInTableButtonAriaLabel', {
|
||||
defaultMessage: 'Toggle column in table',
|
||||
})}
|
||||
aria-pressed={active}
|
||||
onClick={onClick}
|
||||
className="kbnDocViewer__actionButton"
|
|
@ -21,14 +21,11 @@ import { EuiIconTip } from '@elastic/eui';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export function DocViewTableRowIconNoMapping() {
|
||||
const ariaLabel = i18n.translate(
|
||||
'kbn.discover.docViews.table.noCachedMappingForThisFieldAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Warning',
|
||||
}
|
||||
);
|
||||
const ariaLabel = i18n.translate('discover.docViews.table.noCachedMappingForThisFieldAriaLabel', {
|
||||
defaultMessage: 'Warning',
|
||||
});
|
||||
const tooltipContent = i18n.translate(
|
||||
'kbn.discover.docViews.table.noCachedMappingForThisFieldTooltip',
|
||||
'discover.docViews.table.noCachedMappingForThisFieldTooltip',
|
||||
{
|
||||
defaultMessage:
|
||||
'No cached mapping for this field. Refresh field list from the Management > Index Patterns page',
|
|
@ -22,13 +22,13 @@ import { i18n } from '@kbn/i18n';
|
|||
|
||||
export function DocViewTableRowIconUnderscore() {
|
||||
const ariaLabel = i18n.translate(
|
||||
'kbn.discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedAriaLabel',
|
||||
'discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Warning',
|
||||
}
|
||||
);
|
||||
const tooltipContent = i18n.translate(
|
||||
'kbn.discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedTooltip',
|
||||
'discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedTooltip',
|
||||
{
|
||||
defaultMessage: 'Field names beginning with {underscoreSign} are not supported',
|
||||
values: { underscoreSign: '_' },
|
|
@ -23,8 +23,11 @@ import { DocView, DocViewInput, ElasticSearchHit, DocViewInputFn } from './doc_v
|
|||
|
||||
export class DocViewsRegistry {
|
||||
private docViews: DocView[] = [];
|
||||
private angularInjectorGetter: (() => Promise<auto.IInjectorService>) | null = null;
|
||||
|
||||
constructor(private getInjector: () => Promise<auto.IInjectorService>) {}
|
||||
setAngularInjectorGetter(injectorGetter: () => Promise<auto.IInjectorService>) {
|
||||
this.angularInjectorGetter = injectorGetter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends and adds the given doc view to the registry array
|
||||
|
@ -33,7 +36,12 @@ export class DocViewsRegistry {
|
|||
const docView = typeof docViewRaw === 'function' ? docViewRaw() : docViewRaw;
|
||||
if (docView.directive) {
|
||||
// convert angular directive to render function for backwards compatibility
|
||||
docView.render = convertDirectiveToRenderFn(docView.directive, this.getInjector);
|
||||
docView.render = convertDirectiveToRenderFn(docView.directive, () => {
|
||||
if (!this.angularInjectorGetter) {
|
||||
throw new Error('Angular was not initialized');
|
||||
}
|
||||
return this.angularInjectorGetter();
|
||||
});
|
||||
}
|
||||
if (typeof docView.shouldShow !== 'function') {
|
||||
docView.shouldShow = () => true;
|
|
@ -18,10 +18,10 @@
|
|||
*/
|
||||
import { ComponentType } from 'react';
|
||||
import { IScope } from 'angular';
|
||||
import { IndexPattern } from '../../kibana_services';
|
||||
import { IndexPattern } from '../../../data/public';
|
||||
|
||||
export interface AngularDirective {
|
||||
controller: (scope: AngularScope) => void;
|
||||
controller: (...injectedServices: any[]) => void;
|
||||
template: string;
|
||||
}
|
||||
|
||||
|
@ -51,13 +51,14 @@ export interface DocViewRenderProps {
|
|||
onAddColumn?: (columnName: string) => void;
|
||||
onRemoveColumn?: (columnName: string) => void;
|
||||
}
|
||||
export type DocViewerComponent = ComponentType<DocViewRenderProps>;
|
||||
export type DocViewRenderFn = (
|
||||
domeNode: HTMLDivElement,
|
||||
renderProps: DocViewRenderProps
|
||||
) => () => void;
|
||||
|
||||
export interface DocViewInput {
|
||||
component?: ComponentType<DocViewRenderProps>;
|
||||
component?: DocViewerComponent;
|
||||
directive?: AngularDirective;
|
||||
order: number;
|
||||
render?: DocViewRenderFn;
|
20
src/plugins/discover/public/helpers/index.ts
Normal file
20
src/plugins/discover/public/helpers/index.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { shortenDottedString } from './shorten_dotted_string';
|
26
src/plugins/discover/public/helpers/shorten_dotted_string.ts
Normal file
26
src/plugins/discover/public/helpers/shorten_dotted_string.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
const DOT_PREFIX_RE = /(.).+?\./g;
|
||||
|
||||
/**
|
||||
* Convert a dot.notated.string into a short
|
||||
* version (d.n.string)
|
||||
*/
|
||||
export const shortenDottedString = (input: string) => input.replace(DOT_PREFIX_RE, '$1.');
|
1
src/plugins/discover/public/index.scss
Normal file
1
src/plugins/discover/public/index.scss
Normal file
|
@ -0,0 +1 @@
|
|||
@import 'components/index';
|
|
@ -17,5 +17,18 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { DiscoverPlugin } from './plugin';
|
||||
|
||||
export { DiscoverSetup, DiscoverStart } from './plugin';
|
||||
export { DocViewTable } from './components/table/table';
|
||||
export { JsonCodeBlock } from './components/json_code_block/json_code_block';
|
||||
export { DocViewInput, DocViewInputFn, DocViewerComponent } from './doc_views/doc_views_types';
|
||||
export { FieldName } from './components/field_name/field_name';
|
||||
export * from './doc_views/doc_views_types';
|
||||
|
||||
export function plugin() {
|
||||
return new DiscoverPlugin();
|
||||
}
|
||||
|
||||
export { createSavedSearchesLoader } from './saved_searches/saved_searches';
|
||||
export { SavedSearchLoader, SavedSearch } from './saved_searches/types';
|
||||
|
|
47
src/plugins/discover/public/mocks.ts
Normal file
47
src/plugins/discover/public/mocks.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { DiscoverSetup, DiscoverStart } from '.';
|
||||
|
||||
export type Setup = jest.Mocked<DiscoverSetup>;
|
||||
export type Start = jest.Mocked<DiscoverStart>;
|
||||
|
||||
const createSetupContract = (): Setup => {
|
||||
const setupContract: Setup = {
|
||||
docViews: {
|
||||
addDocView: jest.fn(),
|
||||
setAngularInjectorGetter: jest.fn(),
|
||||
},
|
||||
};
|
||||
return setupContract;
|
||||
};
|
||||
|
||||
const createStartContract = (): Start => {
|
||||
const startContract: Start = {
|
||||
docViews: {
|
||||
DocViewer: jest.fn(() => null),
|
||||
},
|
||||
};
|
||||
return startContract;
|
||||
};
|
||||
|
||||
export const discoverPluginMock = {
|
||||
createSetupContract,
|
||||
createStartContract,
|
||||
};
|
110
src/plugins/discover/public/plugin.ts
Normal file
110
src/plugins/discover/public/plugin.ts
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { auto } from 'angular';
|
||||
import { CoreSetup, Plugin } from 'kibana/public';
|
||||
import { DocViewInput, DocViewInputFn, DocViewRenderProps } from './doc_views/doc_views_types';
|
||||
import { DocViewsRegistry } from './doc_views/doc_views_registry';
|
||||
import { DocViewTable } from './components/table/table';
|
||||
import { JsonCodeBlock } from './components/json_code_block/json_code_block';
|
||||
import { DocViewer } from './components/doc_viewer/doc_viewer';
|
||||
import { setDocViewsRegistry } from './services';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
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;
|
||||
/**
|
||||
* Set the angular injector for bootstrapping angular doc views. This is only exposed temporarily to aid
|
||||
* migration to the new platform and will be removed soon.
|
||||
* @deprecated
|
||||
* @param injectorGetter
|
||||
*/
|
||||
setAngularInjectorGetter(injectorGetter: () => Promise<auto.IInjectorService>): void;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface DiscoverStart {
|
||||
docViews: {
|
||||
/**
|
||||
* Component rendering all the doc views for a given document.
|
||||
* This is only exposed temporarily to aid migration to the new platform and will be removed soon.
|
||||
* @deprecated
|
||||
*/
|
||||
DocViewer: React.ComponentType<DocViewRenderProps>;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> {
|
||||
private docViewsRegistry: DocViewsRegistry | null = null;
|
||||
|
||||
setup(core: CoreSetup): DiscoverSetup {
|
||||
this.docViewsRegistry = new DocViewsRegistry();
|
||||
setDocViewsRegistry(this.docViewsRegistry);
|
||||
this.docViewsRegistry.addDocView({
|
||||
title: i18n.translate('discover.docViews.table.tableTitle', {
|
||||
defaultMessage: 'Table',
|
||||
}),
|
||||
order: 10,
|
||||
component: DocViewTable,
|
||||
});
|
||||
this.docViewsRegistry.addDocView({
|
||||
title: i18n.translate('discover.docViews.json.jsonTitle', {
|
||||
defaultMessage: 'JSON',
|
||||
}),
|
||||
order: 20,
|
||||
component: JsonCodeBlock,
|
||||
});
|
||||
|
||||
return {
|
||||
docViews: {
|
||||
addDocView: this.docViewsRegistry.addDocView.bind(this.docViewsRegistry),
|
||||
setAngularInjectorGetter: this.docViewsRegistry.setAngularInjectorGetter.bind(
|
||||
this.docViewsRegistry
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
start() {
|
||||
return {
|
||||
docViews: {
|
||||
DocViewer,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
|
@ -16,7 +16,11 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { createSavedObjectClass, SavedObjectKibanaServices } from '../../../saved_objects/public';
|
||||
import {
|
||||
createSavedObjectClass,
|
||||
SavedObject,
|
||||
SavedObjectKibanaServices,
|
||||
} from '../../../saved_objects/public';
|
||||
|
||||
export function createSavedSearchClass(services: SavedObjectKibanaServices) {
|
||||
const SavedObjectClass = createSavedObjectClass(services);
|
||||
|
@ -66,5 +70,5 @@ export function createSavedSearchClass(services: SavedObjectKibanaServices) {
|
|||
}
|
||||
}
|
||||
|
||||
return SavedSearch;
|
||||
return SavedSearch as new (id: string) => SavedObject;
|
||||
}
|
||||
|
|
25
src/plugins/discover/public/services.ts
Normal file
25
src/plugins/discover/public/services.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { createGetterSetter } from '../../kibana_utils/common';
|
||||
import { DocViewsRegistry } from './doc_views/doc_views_registry';
|
||||
|
||||
export const [getDocViewsRegistry, setDocViewsRegistry] = createGetterSetter<DocViewsRegistry>(
|
||||
'DocViewsRegistry'
|
||||
);
|
|
@ -39,6 +39,7 @@ export default async function({ readConfigFile }) {
|
|||
require.resolve('./test_suites/core_plugins'),
|
||||
require.resolve('./test_suites/management'),
|
||||
require.resolve('./test_suites/bfetch_explorer'),
|
||||
require.resolve('./test_suites/doc_views'),
|
||||
],
|
||||
services: {
|
||||
...functionalConfig.get('services'),
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"id": "docViewPlugin",
|
||||
"version": "0.0.1",
|
||||
"kibanaVersion": "kibana",
|
||||
"server": false,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["discover"]
|
||||
}
|
17
test/plugin_functional/plugins/doc_views_plugin/package.json
Normal file
17
test/plugin_functional/plugins/doc_views_plugin/package.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "docViewPlugin",
|
||||
"version": "1.0.0",
|
||||
"main": "target/test/plugin_functional/plugins/doc_views_plugin",
|
||||
"kibana": {
|
||||
"version": "kibana",
|
||||
"templateVersion": "1.0.0"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"kbn": "node ../../../../scripts/kbn.js",
|
||||
"build": "rm -rf './target' && tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "3.7.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { DocViewsPlugin } from './plugin';
|
||||
|
||||
export const plugin = () => new DocViewsPlugin();
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
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() {}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "../../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"index.ts",
|
||||
"public/**/*.ts",
|
||||
"public/**/*.tsx",
|
||||
"../../../../typings/**/*"
|
||||
],
|
||||
"exclude": []
|
||||
}
|
57
test/plugin_functional/test_suites/doc_views/doc_views.ts
Normal file
57
test/plugin_functional/test_suites/doc_views/doc_views.ts
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function({ getService, getPageObjects }: PluginFunctionalProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
const find = getService('find');
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'timePicker']);
|
||||
|
||||
describe('custom doc views', function() {
|
||||
before(async () => {
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
await PageObjects.timePicker.setDefaultAbsoluteRange();
|
||||
});
|
||||
|
||||
it('should show custom doc views', async () => {
|
||||
await testSubjects.click('docTableExpandToggleColumn');
|
||||
const angularTab = await find.byButtonText('Angular doc view');
|
||||
const reactTab = await find.byButtonText('React doc view');
|
||||
expect(await angularTab.isDisplayed()).to.be(true);
|
||||
expect(await reactTab.isDisplayed()).to.be(true);
|
||||
});
|
||||
|
||||
it('should render angular doc view', async () => {
|
||||
const angularTab = await find.byButtonText('Angular doc view');
|
||||
await angularTab.click();
|
||||
const angularContent = await testSubjects.find('angular-docview');
|
||||
expect(await angularContent.getVisibleText()).to.be('logstash-2015.09.22');
|
||||
});
|
||||
|
||||
it('should render react doc view', async () => {
|
||||
const reactTab = await find.byButtonText('React doc view');
|
||||
await reactTab.click();
|
||||
const reactContent = await testSubjects.find('react-docview');
|
||||
expect(await reactContent.getVisibleText()).to.be('logstash-2015.09.22');
|
||||
});
|
||||
});
|
||||
}
|
31
test/plugin_functional/test_suites/doc_views/index.ts
Normal file
31
test/plugin_functional/test_suites/doc_views/index.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function({ getService, loadTestFile }: PluginFunctionalProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('doc views', function() {
|
||||
before(async () => {
|
||||
await esArchiver.loadIfNeeded('../functional/fixtures/es_archiver/discover');
|
||||
});
|
||||
|
||||
loadTestFile(require.resolve('./doc_views'));
|
||||
});
|
||||
}
|
|
@ -464,6 +464,17 @@
|
|||
"data.search.searchBar.savedQueryPopoverSavedQueryListItemDescriptionAriaLabel": "{savedQueryName} の説明",
|
||||
"data.search.searchBar.savedQueryPopoverSavedQueryListItemSelectedButtonAriaLabel": "選択されたクエリボタン {savedQueryName} を保存しました。変更を破棄するには押してください。",
|
||||
"data.search.searchBar.savedQueryPopoverTitleText": "保存されたクエリ",
|
||||
"discover.fieldNameIcons.booleanAriaLabel": "ブールフィールド",
|
||||
"discover.fieldNameIcons.conflictFieldAriaLabel": "矛盾フィールド",
|
||||
"discover.fieldNameIcons.dateFieldAriaLabel": "日付フィールド",
|
||||
"discover.fieldNameIcons.geoPointFieldAriaLabel": "地理ポイント",
|
||||
"discover.fieldNameIcons.geoShapeFieldAriaLabel": "地理情報図形",
|
||||
"discover.fieldNameIcons.ipAddressFieldAriaLabel": "IP アドレスフィールド",
|
||||
"discover.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3 フィールド",
|
||||
"discover.fieldNameIcons.numberFieldAriaLabel": "数値フィールド",
|
||||
"discover.fieldNameIcons.sourceFieldAriaLabel": "ソースフィールド",
|
||||
"discover.fieldNameIcons.stringFieldAriaLabel": "文字列フィールド",
|
||||
"discover.fieldNameIcons.unknownFieldAriaLabel": "不明なフィールド",
|
||||
"charts.colormaps.bluesText": "青",
|
||||
"charts.colormaps.greensText": "緑",
|
||||
"charts.colormaps.greenToRedText": "緑から赤",
|
||||
|
@ -1075,17 +1086,6 @@
|
|||
"kbn.discover.fieldChooser.searchPlaceHolder": "検索フィールド",
|
||||
"kbn.discover.fieldChooser.toggleFieldFilterButtonHideAriaLabel": "フィールド設定を非表示",
|
||||
"kbn.discover.fieldChooser.toggleFieldFilterButtonShowAriaLabel": "フィールド設定を表示",
|
||||
"kbn.discover.fieldNameIcons.booleanAriaLabel": "ブールフィールド",
|
||||
"kbn.discover.fieldNameIcons.conflictFieldAriaLabel": "矛盾フィールド",
|
||||
"kbn.discover.fieldNameIcons.dateFieldAriaLabel": "日付フィールド",
|
||||
"kbn.discover.fieldNameIcons.geoPointFieldAriaLabel": "地理ポイント",
|
||||
"kbn.discover.fieldNameIcons.geoShapeFieldAriaLabel": "地理情報図形",
|
||||
"kbn.discover.fieldNameIcons.ipAddressFieldAriaLabel": "IP アドレスフィールド",
|
||||
"kbn.discover.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3 フィールド",
|
||||
"kbn.discover.fieldNameIcons.numberFieldAriaLabel": "数値フィールド",
|
||||
"kbn.discover.fieldNameIcons.sourceFieldAriaLabel": "ソースフィールド",
|
||||
"kbn.discover.fieldNameIcons.stringFieldAriaLabel": "文字列フィールド",
|
||||
"kbn.discover.fieldNameIcons.unknownFieldAriaLabel": "不明なフィールド",
|
||||
"kbn.discover.histogram.partialData.bucketTooltipText": "選択された時間範囲にはこのバケット全体は含まれていませんが、一部データが含まれている可能性があります。",
|
||||
"kbn.discover.histogramOfFoundDocumentsAriaLabel": "発見されたドキュメントのヒストグラム",
|
||||
"kbn.discover.hitsPluralTitle": "{hits, plural, one {ヒット} other {ヒット}}",
|
||||
|
|
|
@ -464,6 +464,17 @@
|
|||
"data.search.searchBar.savedQueryPopoverSavedQueryListItemDescriptionAriaLabel": "{savedQueryName} 描述",
|
||||
"data.search.searchBar.savedQueryPopoverSavedQueryListItemSelectedButtonAriaLabel": "已保存查询按钮已选择 {savedQueryName}。按下可清除任何更改。",
|
||||
"data.search.searchBar.savedQueryPopoverTitleText": "已保存查询",
|
||||
"discover.fieldNameIcons.booleanAriaLabel": "布尔字段",
|
||||
"discover.fieldNameIcons.conflictFieldAriaLabel": "冲突字段",
|
||||
"discover.fieldNameIcons.dateFieldAriaLabel": "日期字段",
|
||||
"discover.fieldNameIcons.geoPointFieldAriaLabel": "地理位置点字段",
|
||||
"discover.fieldNameIcons.geoShapeFieldAriaLabel": "几何形状字段",
|
||||
"discover.fieldNameIcons.ipAddressFieldAriaLabel": "IP 地址字段",
|
||||
"discover.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3 字段",
|
||||
"discover.fieldNameIcons.numberFieldAriaLabel": "数字字段",
|
||||
"discover.fieldNameIcons.sourceFieldAriaLabel": "源字段",
|
||||
"discover.fieldNameIcons.stringFieldAriaLabel": "字符串字段",
|
||||
"discover.fieldNameIcons.unknownFieldAriaLabel": "未知字段",
|
||||
"charts.colormaps.bluesText": "蓝色",
|
||||
"charts.colormaps.greensText": "绿色",
|
||||
"charts.colormaps.greenToRedText": "绿到红",
|
||||
|
@ -1075,17 +1086,6 @@
|
|||
"kbn.discover.fieldChooser.searchPlaceHolder": "搜索字段",
|
||||
"kbn.discover.fieldChooser.toggleFieldFilterButtonHideAriaLabel": "隐藏字段设置",
|
||||
"kbn.discover.fieldChooser.toggleFieldFilterButtonShowAriaLabel": "显示字段设置",
|
||||
"kbn.discover.fieldNameIcons.booleanAriaLabel": "布尔字段",
|
||||
"kbn.discover.fieldNameIcons.conflictFieldAriaLabel": "冲突字段",
|
||||
"kbn.discover.fieldNameIcons.dateFieldAriaLabel": "日期字段",
|
||||
"kbn.discover.fieldNameIcons.geoPointFieldAriaLabel": "地理位置点字段",
|
||||
"kbn.discover.fieldNameIcons.geoShapeFieldAriaLabel": "几何形状字段",
|
||||
"kbn.discover.fieldNameIcons.ipAddressFieldAriaLabel": "IP 地址字段",
|
||||
"kbn.discover.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3 字段",
|
||||
"kbn.discover.fieldNameIcons.numberFieldAriaLabel": "数字字段",
|
||||
"kbn.discover.fieldNameIcons.sourceFieldAriaLabel": "源字段",
|
||||
"kbn.discover.fieldNameIcons.stringFieldAriaLabel": "字符串字段",
|
||||
"kbn.discover.fieldNameIcons.unknownFieldAriaLabel": "未知字段",
|
||||
"kbn.discover.histogram.partialData.bucketTooltipText": "选定的时间范围不包括此整个存储桶,其可能包含部分数据。",
|
||||
"kbn.discover.histogramOfFoundDocumentsAriaLabel": "已找到文档的直方图",
|
||||
"kbn.discover.hitsPluralTitle": "{hits, plural, one {次命中} other {次命中}}",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue