mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Exploratory View] Embedddable component (#113108)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
93d1a7fbcc
commit
b8cdc6fd1b
16 changed files with 501 additions and 43 deletions
5
x-pack/examples/exploratory_view_example/.eslintrc.json
Normal file
5
x-pack/examples/exploratory_view_example/.eslintrc.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"rules": {
|
||||
"@typescript-eslint/consistent-type-definitions": 0
|
||||
}
|
||||
}
|
8
x-pack/examples/exploratory_view_example/README.md
Normal file
8
x-pack/examples/exploratory_view_example/README.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Embedded Observability exploratory view example
|
||||
|
||||
To run this example plugin, use the command `yarn start --run-examples`.
|
||||
|
||||
This example shows how to embed Exploratory view into other observability solution applications. Using the exploratory view `EmbeddableComponent` of the `observability` start plugin,
|
||||
you can pass in a valid Exploratory view series attributes which will get rendered the same way exploratory view works using Lens Embeddable. Updating the
|
||||
configuration will reload the embedded visualization.
|
||||
|
20
x-pack/examples/exploratory_view_example/kibana.json
Normal file
20
x-pack/examples/exploratory_view_example/kibana.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"id": "exploratoryViewExample",
|
||||
"version": "0.0.1",
|
||||
"kibanaVersion": "kibana",
|
||||
"configPath": ["exploratory_view_example"],
|
||||
"server": false,
|
||||
"ui": true,
|
||||
"requiredPlugins": [
|
||||
"observability",
|
||||
"data",
|
||||
"embeddable",
|
||||
"developerExamples"
|
||||
],
|
||||
"optionalPlugins": [],
|
||||
"requiredBundles": [],
|
||||
"owner": {
|
||||
"name": "`Synthetics team`",
|
||||
"githubTeam": "uptime"
|
||||
}
|
||||
}
|
14
x-pack/examples/exploratory_view_example/package.json
Normal file
14
x-pack/examples/exploratory_view_example/package.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "exploratory_view_example",
|
||||
"version": "1.0.0",
|
||||
"main": "target/examples/exploratory_view_example",
|
||||
"kibana": {
|
||||
"version": "kibana",
|
||||
"templateVersion": "1.0.0"
|
||||
},
|
||||
"license": "Elastic License 2.0",
|
||||
"scripts": {
|
||||
"kbn": "node ../../../scripts/kbn.js",
|
||||
"build": "rm -rf './target' && ../../../node_modules/.bin/tsc"
|
||||
}
|
||||
}
|
89
x-pack/examples/exploratory_view_example/public/app.tsx
Normal file
89
x-pack/examples/exploratory_view_example/public/app.tsx
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiButton,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiPage,
|
||||
EuiPageBody,
|
||||
EuiPageContent,
|
||||
EuiPageContentBody,
|
||||
EuiPageHeader,
|
||||
EuiPageHeaderSection,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import { IndexPattern } from 'src/plugins/data/public';
|
||||
import { CoreStart } from 'kibana/public';
|
||||
import { StartDependencies } from './plugin';
|
||||
import { AllSeries } from '../../../plugins/observability/public';
|
||||
|
||||
export const App = (props: {
|
||||
core: CoreStart;
|
||||
plugins: StartDependencies;
|
||||
defaultIndexPattern: IndexPattern | null;
|
||||
}) => {
|
||||
const ExploratoryViewComponent = props.plugins.observability.ExploratoryViewEmbeddable;
|
||||
|
||||
const seriesList: AllSeries = [
|
||||
{
|
||||
name: 'Monitors response duration',
|
||||
time: {
|
||||
from: 'now-5d',
|
||||
to: 'now',
|
||||
},
|
||||
reportDefinitions: {
|
||||
'monitor.id': ['ALL_VALUES'],
|
||||
},
|
||||
breakdown: 'observer.geo.name',
|
||||
operationType: 'average',
|
||||
dataType: 'synthetics',
|
||||
seriesType: 'line',
|
||||
selectedMetricField: 'monitor.duration.us',
|
||||
},
|
||||
];
|
||||
|
||||
const hrefLink = props.plugins.observability.createExploratoryViewUrl(
|
||||
{ reportType: 'kpi-over-time', allSeries: seriesList },
|
||||
props.core.http.basePath.get()
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiPage>
|
||||
<EuiPageBody style={{ maxWidth: 1200, margin: '0 auto' }}>
|
||||
<EuiPageHeader>
|
||||
<EuiPageHeaderSection>
|
||||
<EuiTitle size="l">
|
||||
<h1>Observability Exploratory View Example</h1>
|
||||
</EuiTitle>
|
||||
</EuiPageHeaderSection>
|
||||
</EuiPageHeader>
|
||||
<EuiPageContent>
|
||||
<EuiPageContentBody style={{ maxWidth: 800, margin: '0 auto', height: '70vh' }}>
|
||||
<p>
|
||||
This app embeds an Observability Exploratory view as embeddable component. Make sure
|
||||
you have data in heartbeat-* index within last 5 days for this demo to work.
|
||||
</p>
|
||||
<EuiFlexGroup justifyContent="flexEnd">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton aria-label="Open in exploratory view" href={hrefLink} target="_blank">
|
||||
Edit in exploratory view (new tab)
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<ExploratoryViewComponent
|
||||
attributes={seriesList}
|
||||
reportType="kpi-over-time"
|
||||
title={'Monitor response duration'}
|
||||
/>
|
||||
</EuiPageContentBody>
|
||||
</EuiPageContent>
|
||||
</EuiPageBody>
|
||||
</EuiPage>
|
||||
);
|
||||
};
|
10
x-pack/examples/exploratory_view_example/public/index.ts
Normal file
10
x-pack/examples/exploratory_view_example/public/index.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ExploratoryViewExamplePlugin } from './plugin';
|
||||
|
||||
export const plugin = () => new ExploratoryViewExamplePlugin();
|
35
x-pack/examples/exploratory_view_example/public/mount.tsx
Normal file
35
x-pack/examples/exploratory_view_example/public/mount.tsx
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { CoreSetup, AppMountParameters } from 'kibana/public';
|
||||
import { StartDependencies } from './plugin';
|
||||
|
||||
export const mount =
|
||||
(coreSetup: CoreSetup<StartDependencies>) =>
|
||||
async ({ element }: AppMountParameters) => {
|
||||
const [core, plugins] = await coreSetup.getStartServices();
|
||||
const { App } = await import('./app');
|
||||
|
||||
const deps = {
|
||||
core,
|
||||
plugins,
|
||||
};
|
||||
|
||||
const defaultIndexPattern = await plugins.data.indexPatterns.getDefault();
|
||||
|
||||
const i18nCore = core.i18n;
|
||||
|
||||
const reactElement = (
|
||||
<i18nCore.Context>
|
||||
<App {...deps} defaultIndexPattern={defaultIndexPattern} />
|
||||
</i18nCore.Context>
|
||||
);
|
||||
render(reactElement, element);
|
||||
return () => unmountComponentAtNode(element);
|
||||
};
|
46
x-pack/examples/exploratory_view_example/public/plugin.ts
Normal file
46
x-pack/examples/exploratory_view_example/public/plugin.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, AppNavLinkStatus } from '../../../../src/core/public';
|
||||
import { DataPublicPluginStart } from '../../../../src/plugins/data/public';
|
||||
import { ObservabilityPublicStart } from '../../../plugins/observability/public';
|
||||
import { DeveloperExamplesSetup } from '../../../../examples/developer_examples/public';
|
||||
import { mount } from './mount';
|
||||
|
||||
export interface SetupDependencies {
|
||||
developerExamples: DeveloperExamplesSetup;
|
||||
}
|
||||
|
||||
export interface StartDependencies {
|
||||
data: DataPublicPluginStart;
|
||||
observability: ObservabilityPublicStart;
|
||||
}
|
||||
|
||||
export class ExploratoryViewExamplePlugin
|
||||
implements Plugin<void, void, SetupDependencies, StartDependencies>
|
||||
{
|
||||
public setup(core: CoreSetup<StartDependencies>, { developerExamples }: SetupDependencies) {
|
||||
core.application.register({
|
||||
id: 'exploratory_view_example',
|
||||
title: 'Observability Exploratory View example',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
mount: mount(core),
|
||||
order: 1000,
|
||||
});
|
||||
|
||||
developerExamples.register({
|
||||
appId: 'exploratory_view_example',
|
||||
title: 'Observability Exploratory View',
|
||||
description:
|
||||
'Embed Observability exploratory view in your observability solution app to render common visualizations',
|
||||
});
|
||||
}
|
||||
|
||||
public start() {}
|
||||
|
||||
public stop() {}
|
||||
}
|
21
x-pack/examples/exploratory_view_example/tsconfig.json
Normal file
21
x-pack/examples/exploratory_view_example/tsconfig.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target/types"
|
||||
},
|
||||
"include": [
|
||||
"index.ts",
|
||||
"public/**/*.ts",
|
||||
"public/**/*.tsx",
|
||||
"server/**/*.ts",
|
||||
"../../../typings/**/*"
|
||||
],
|
||||
"exclude": [],
|
||||
"references": [
|
||||
{ "path": "../../../src/core/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/data/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/embeddable/tsconfig.json" },
|
||||
{ "path": "../../plugins/observability/tsconfig.json" },
|
||||
{ "path": "../../../examples/developer_examples/tsconfig.json" },
|
||||
]
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle } from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
import { AllSeries, useTheme } from '../../../..';
|
||||
import { LayerConfig, LensAttributes } from '../configurations/lens_attributes';
|
||||
import { ReportViewType } from '../types';
|
||||
import { getLayerConfigs } from '../hooks/use_lens_attributes';
|
||||
import { LensPublicStart } from '../../../../../../lens/public';
|
||||
import { OperationTypeComponent } from '../series_editor/columns/operation_type_select';
|
||||
import { IndexPatternState } from '../hooks/use_app_index_pattern';
|
||||
|
||||
export interface ExploratoryEmbeddableProps {
|
||||
reportType: ReportViewType;
|
||||
attributes: AllSeries;
|
||||
appendTitle?: JSX.Element;
|
||||
title: string | JSX.Element;
|
||||
showCalculationMethod?: boolean;
|
||||
}
|
||||
|
||||
export interface ExploratoryEmbeddableComponentProps extends ExploratoryEmbeddableProps {
|
||||
lens: LensPublicStart;
|
||||
indexPatterns: IndexPatternState;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function Embeddable({
|
||||
reportType,
|
||||
attributes,
|
||||
title,
|
||||
appendTitle,
|
||||
indexPatterns,
|
||||
lens,
|
||||
showCalculationMethod = false,
|
||||
}: ExploratoryEmbeddableComponentProps) {
|
||||
const LensComponent = lens?.EmbeddableComponent;
|
||||
|
||||
const series = Object.entries(attributes)[0][1];
|
||||
|
||||
const [operationType, setOperationType] = useState(series?.operationType);
|
||||
const theme = useTheme();
|
||||
|
||||
const layerConfigs: LayerConfig[] = getLayerConfigs(attributes, reportType, theme, indexPatterns);
|
||||
|
||||
if (layerConfigs.length < 1) {
|
||||
return null;
|
||||
}
|
||||
const lensAttributes = new LensAttributes(layerConfigs);
|
||||
|
||||
if (!LensComponent) {
|
||||
return <EuiText>No lens component</EuiText>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiTitle size="s">
|
||||
<h3>{title}</h3>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
{showCalculationMethod && (
|
||||
<EuiFlexItem grow={false} style={{ minWidth: 150 }}>
|
||||
<OperationTypeComponent
|
||||
operationType={operationType}
|
||||
onChange={(val) => {
|
||||
setOperationType(val);
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{appendTitle}
|
||||
</EuiFlexGroup>
|
||||
<LensComponent
|
||||
id="exploratoryView"
|
||||
style={{ height: '100%' }}
|
||||
timeRange={series?.time}
|
||||
attributes={lensAttributes.getJSON()}
|
||||
onBrushEnd={({ range }) => {}}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
height: 100%;
|
||||
&&& {
|
||||
> :nth-child(2) {
|
||||
height: calc(100% - 56px);
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { EuiLoadingSpinner } from '@elastic/eui';
|
||||
import { CoreStart } from 'kibana/public';
|
||||
import type { ExploratoryEmbeddableProps, ExploratoryEmbeddableComponentProps } from './embeddable';
|
||||
import { ObservabilityIndexPatterns } from '../utils/observability_index_patterns';
|
||||
import { ObservabilityPublicPluginsStart } from '../../../../plugin';
|
||||
import type { IndexPatternState } from '../hooks/use_app_index_pattern';
|
||||
import { EuiThemeProvider } from '../../../../../../../../src/plugins/kibana_react/common';
|
||||
|
||||
const Embeddable = React.lazy(() => import('./embeddable'));
|
||||
|
||||
function ExploratoryViewEmbeddable(props: ExploratoryEmbeddableComponentProps) {
|
||||
return (
|
||||
<React.Suspense fallback={<EuiLoadingSpinner />}>
|
||||
<Embeddable {...props} />
|
||||
</React.Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export function getExploratoryViewEmbeddable(
|
||||
core: CoreStart,
|
||||
plugins: ObservabilityPublicPluginsStart
|
||||
) {
|
||||
return (props: ExploratoryEmbeddableProps) => {
|
||||
const [indexPatterns, setIndexPatterns] = useState<IndexPatternState>({} as IndexPatternState);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const series = props.attributes[0];
|
||||
|
||||
const isDarkMode = core.uiSettings.get('theme:darkMode');
|
||||
|
||||
const loadIndexPattern = useCallback(async ({ dataType }) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const obsvIndexP = new ObservabilityIndexPatterns(plugins.data);
|
||||
const indPattern = await obsvIndexP.getIndexPattern(dataType, 'heartbeat-*');
|
||||
setIndexPatterns((prevState) => ({ ...(prevState ?? {}), [dataType]: indPattern }));
|
||||
|
||||
setLoading(false);
|
||||
} catch (e) {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
loadIndexPattern({ dataType: series.dataType });
|
||||
}, [series.dataType, loadIndexPattern]);
|
||||
|
||||
if (Object.keys(indexPatterns).length === 0 || loading) {
|
||||
return <EuiLoadingSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiThemeProvider darkMode={isDarkMode}>
|
||||
<ExploratoryViewEmbeddable {...props} indexPatterns={indexPatterns} lens={plugins.lens} />
|
||||
</EuiThemeProvider>
|
||||
);
|
||||
};
|
||||
}
|
|
@ -17,10 +17,11 @@ import {
|
|||
} from './use_series_storage';
|
||||
import { getDefaultConfigs } from '../configurations/default_configs';
|
||||
|
||||
import { SeriesUrl, UrlFilter } from '../types';
|
||||
import { useAppIndexPatternContext } from './use_app_index_pattern';
|
||||
import { ReportViewType, SeriesUrl, UrlFilter } from '../types';
|
||||
import { IndexPatternState, useAppIndexPatternContext } from './use_app_index_pattern';
|
||||
import { ALL_VALUES_SELECTED } from '../../field_value_suggestions/field_value_combobox';
|
||||
import { useTheme } from '../../../../hooks/use_theme';
|
||||
import { EuiTheme } from '../../../../../../../../src/plugins/kibana_react/common';
|
||||
|
||||
export const getFiltersFromDefs = (reportDefinitions: SeriesUrl['reportDefinitions']) => {
|
||||
return Object.entries(reportDefinitions ?? {})
|
||||
|
@ -33,6 +34,54 @@ export const getFiltersFromDefs = (reportDefinitions: SeriesUrl['reportDefinitio
|
|||
.filter(({ values }) => !values.includes(ALL_VALUES_SELECTED)) as UrlFilter[];
|
||||
};
|
||||
|
||||
export function getLayerConfigs(
|
||||
allSeries: AllSeries,
|
||||
reportType: ReportViewType,
|
||||
theme: EuiTheme,
|
||||
indexPatterns: IndexPatternState
|
||||
) {
|
||||
const layerConfigs: LayerConfig[] = [];
|
||||
|
||||
allSeries.forEach((series, seriesIndex) => {
|
||||
const indexPattern = indexPatterns?.[series?.dataType];
|
||||
|
||||
if (
|
||||
indexPattern &&
|
||||
!isEmpty(series.reportDefinitions) &&
|
||||
!series.hidden &&
|
||||
series.selectedMetricField
|
||||
) {
|
||||
const seriesConfig = getDefaultConfigs({
|
||||
reportType,
|
||||
indexPattern,
|
||||
dataType: series.dataType,
|
||||
});
|
||||
|
||||
const filters: UrlFilter[] = (series.filters ?? []).concat(
|
||||
getFiltersFromDefs(series.reportDefinitions)
|
||||
);
|
||||
|
||||
const color = `euiColorVis${seriesIndex}`;
|
||||
|
||||
layerConfigs.push({
|
||||
filters,
|
||||
indexPattern,
|
||||
seriesConfig,
|
||||
time: series.time,
|
||||
name: series.name,
|
||||
breakdown: series.breakdown,
|
||||
seriesType: series.seriesType,
|
||||
operationType: series.operationType,
|
||||
reportDefinitions: series.reportDefinitions ?? {},
|
||||
selectedMetricField: series.selectedMetricField,
|
||||
color: series.color ?? (theme.eui as unknown as Record<string, string>)[color],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return layerConfigs;
|
||||
}
|
||||
|
||||
export const useLensAttributes = (): TypedLensByValueInput['attributes'] | null => {
|
||||
const { storage, allSeries, lastRefresh, reportType } = useSeriesStorage();
|
||||
|
||||
|
@ -47,44 +96,7 @@ export const useLensAttributes = (): TypedLensByValueInput['attributes'] | null
|
|||
|
||||
const allSeriesT: AllSeries = convertAllShortSeries(storage.get(allSeriesKey) ?? []);
|
||||
|
||||
const layerConfigs: LayerConfig[] = [];
|
||||
|
||||
allSeriesT.forEach((series, seriesIndex) => {
|
||||
const indexPattern = indexPatterns?.[series?.dataType];
|
||||
|
||||
if (
|
||||
indexPattern &&
|
||||
!isEmpty(series.reportDefinitions) &&
|
||||
!series.hidden &&
|
||||
series.selectedMetricField
|
||||
) {
|
||||
const seriesConfig = getDefaultConfigs({
|
||||
reportType,
|
||||
indexPattern,
|
||||
dataType: series.dataType,
|
||||
});
|
||||
|
||||
const filters: UrlFilter[] = (series.filters ?? []).concat(
|
||||
getFiltersFromDefs(series.reportDefinitions)
|
||||
);
|
||||
|
||||
const color = `euiColorVis${seriesIndex}`;
|
||||
|
||||
layerConfigs.push({
|
||||
filters,
|
||||
indexPattern,
|
||||
seriesConfig,
|
||||
time: series.time,
|
||||
name: series.name,
|
||||
breakdown: series.breakdown,
|
||||
seriesType: series.seriesType,
|
||||
operationType: series.operationType,
|
||||
reportDefinitions: series.reportDefinitions ?? {},
|
||||
selectedMetricField: series.selectedMetricField,
|
||||
color: series.color ?? (theme.eui as unknown as Record<string, string>)[color],
|
||||
});
|
||||
}
|
||||
});
|
||||
const layerConfigs = getLayerConfigs(allSeriesT, reportType, theme, indexPatterns);
|
||||
|
||||
if (layerConfigs.length < 1) {
|
||||
return null;
|
||||
|
|
|
@ -36,6 +36,24 @@ export function OperationTypeSelect({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultOperationType]);
|
||||
|
||||
return (
|
||||
<OperationTypeComponent
|
||||
onChange={onChange}
|
||||
showLabel={true}
|
||||
operationType={operationType || defaultOperationType}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function OperationTypeComponent({
|
||||
operationType,
|
||||
onChange,
|
||||
showLabel = false,
|
||||
}: {
|
||||
operationType?: OperationType;
|
||||
onChange: (value: OperationType) => void;
|
||||
showLabel?: boolean;
|
||||
}) {
|
||||
const options = [
|
||||
{
|
||||
value: 'average' as OperationType,
|
||||
|
@ -83,9 +101,17 @@ export function OperationTypeSelect({
|
|||
|
||||
return (
|
||||
<EuiSuperSelect
|
||||
compressed
|
||||
fullWidth
|
||||
prepend={
|
||||
showLabel
|
||||
? i18n.translate('xpack.observability.expView.operationType.label', {
|
||||
defaultMessage: 'Calculation',
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
data-test-subj="operationTypeSelect"
|
||||
valueOfSelected={operationType || defaultOperationType}
|
||||
valueOfSelected={operationType}
|
||||
options={options}
|
||||
onChange={onChange}
|
||||
/>
|
||||
|
|
|
@ -71,6 +71,7 @@ export { getApmTraceUrl } from './utils/get_apm_trace_url';
|
|||
export { createExploratoryViewUrl } from './components/shared/exploratory_view/configurations/utils';
|
||||
export { ALL_VALUES_SELECTED } from './components/shared/field_value_suggestions/field_value_combobox';
|
||||
export { FilterValueLabel } from './components/shared/filter_value_label/filter_value_label';
|
||||
export type { AllSeries } from './components/shared/exploratory_view/hooks/use_series_storage';
|
||||
export type { SeriesUrl } from './components/shared/exploratory_view/types';
|
||||
|
||||
export type {
|
||||
|
@ -79,3 +80,4 @@ export type {
|
|||
ObservabilityRuleTypeRegistry,
|
||||
} from './rules/create_observability_rule_type_registry';
|
||||
export { createObservabilityRuleTypeRegistryMock } from './rules/observability_rule_type_registry_mock';
|
||||
export type { ExploratoryEmbeddableProps } from './components/shared/exploratory_view/embeddable/embeddable';
|
||||
|
|
|
@ -43,6 +43,8 @@ import { createObservabilityRuleTypeRegistry } from './rules/create_observabilit
|
|||
import { createCallObservabilityApi } from './services/call_observability_api';
|
||||
import { createNavigationRegistry, NavigationEntry } from './services/navigation_registry';
|
||||
import { updateGlobalNavigation } from './update_global_navigation';
|
||||
import { getExploratoryViewEmbeddable } from './components/shared/exploratory_view/embeddable';
|
||||
import { createExploratoryViewUrl } from './components/shared/exploratory_view/configurations/utils';
|
||||
|
||||
export type ObservabilityPublicSetup = ReturnType<Plugin['setup']>;
|
||||
|
||||
|
@ -233,7 +235,9 @@ export class Plugin
|
|||
};
|
||||
}
|
||||
|
||||
public start({ application }: CoreStart) {
|
||||
public start(coreStart: CoreStart, pluginsStart: ObservabilityPublicPluginsStart) {
|
||||
const { application } = coreStart;
|
||||
|
||||
const config = this.initializerContext.config.get();
|
||||
|
||||
updateGlobalNavigation({
|
||||
|
@ -254,6 +258,8 @@ export class Plugin
|
|||
navigation: {
|
||||
PageTemplate,
|
||||
},
|
||||
createExploratoryViewUrl,
|
||||
ExploratoryViewEmbeddable: getExploratoryViewEmbeddable(coreStart, pluginsStart),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,4 +38,4 @@
|
|||
"githubTeam": "uptime"
|
||||
},
|
||||
"description": "This plugin visualizes data from Synthetics and Heartbeat, and integrates with other Observability solutions."
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue