[Visualizations] Remove usage of deprecated React rendering utilities (#181491)

## Summary

Partially addresses https://github.com/elastic/kibana-team/issues/805

These changes come up from searching in the code and finding where
certain kinds of deprecated AppEx-SharedUX modules are imported.
**Reviewers: Please interact with critical paths through the UI
components touched in this PR, ESPECIALLY in terms of testing dark mode
and i18n.**

This focuses on code within **Visualization team**.

<img width="1196" alt="image"
src="7f8d3707-94f0-4746-8dd5-dd858ce027f9">

Note: this also makes inclusion of `i18n` and `analytics` dependencies
consistent. Analytics is an optional dependency for the SharedUX
modules, which wrap `KibanaErrorBoundaryProvider` and is designed to
capture telemetry about errors that are caught in the error boundary.

### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [ ] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)
This commit is contained in:
Tim Sullivan 2024-04-26 10:55:55 -07:00 committed by GitHub
parent 920334298c
commit f21d6e436e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 263 additions and 262 deletions

View file

@ -19,8 +19,7 @@
"usageCollection"
],
"requiredBundles": [
"kibanaUtils",
"kibanaReact"
"kibanaUtils"
],
"extraPublicDirs": [
"common"

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { PersistedState } from '@kbn/visualizations-plugin/public';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
import { StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
import { METRIC_TYPE } from '@kbn/analytics';
@ -90,7 +90,7 @@ export const gaugeRenderer: (
const { GaugeComponent } = await import('../components/gauge_component');
render(
<KibanaThemeProvider theme$={core.theme.theme$}>
<KibanaRenderContextProvider {...core}>
<div className="gauge-container" data-test-subj="gaugeChart">
<GaugeComponent
{...config}
@ -102,7 +102,7 @@ export const gaugeRenderer: (
uiState={handlers.uiState as PersistedState}
/>
</div>
</KibanaThemeProvider>,
</KibanaRenderContextProvider>,
domNode
);
},

View file

@ -23,10 +23,10 @@
"@kbn/test-jest-helpers",
"@kbn/i18n-react",
"@kbn/kibana-utils-plugin",
"@kbn/kibana-react-plugin",
"@kbn/analytics",
"@kbn/chart-icons",
"@kbn/chart-expressions-common",
"@kbn/react-kibana-context-render",
],
"exclude": [
"target/**/*",

View file

@ -19,8 +19,7 @@
"usageCollection"
],
"requiredBundles": [
"kibanaUtils",
"kibanaReact"
"kibanaUtils"
],
"extraPublicDirs": [
"common"

View file

@ -10,7 +10,7 @@ import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { getTimeZone } from '@kbn/visualization-utils';
import type { PersistedState } from '@kbn/visualizations-plugin/public';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
import { StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
import { METRIC_TYPE } from '@kbn/analytics';
@ -19,7 +19,6 @@ import {
extractContainerType,
extractVisualizationType,
} from '@kbn/chart-expressions-common';
import { I18nProvider } from '@kbn/i18n-react';
import { MultiFilterEvent } from '../../common/types';
import { ExpressionHeatmapPluginStart } from '../plugin';
import {
@ -99,29 +98,27 @@ export const heatmapRenderer: (
const { isInteractive } = handlers;
render(
<KibanaThemeProvider theme$={core.theme.theme$}>
<I18nProvider>
<div className="heatmap-container" data-test-subj="heatmapChart">
<HeatmapComponent
{...config}
onClickValue={onClickValue}
onSelectRange={onSelectRange}
timeZone={timeZone}
datatableUtilities={getDatatableUtilities()}
formatFactory={getFormatService().deserialize}
chartsThemeService={plugins.charts.theme}
paletteService={getPaletteService()}
renderComplete={renderComplete}
uiState={handlers.uiState as PersistedState}
interactive={isInteractive()}
chartsActiveCursorService={plugins.charts.activeCursor}
syncTooltips={config.syncTooltips}
syncCursor={config.syncCursor}
onClickMultiValue={onClickMultiValue}
/>
</div>
</I18nProvider>
</KibanaThemeProvider>,
<KibanaRenderContextProvider {...core}>
<div className="heatmap-container" data-test-subj="heatmapChart">
<HeatmapComponent
{...config}
onClickValue={onClickValue}
onSelectRange={onSelectRange}
timeZone={timeZone}
datatableUtilities={getDatatableUtilities()}
formatFactory={getFormatService().deserialize}
chartsThemeService={plugins.charts.theme}
paletteService={getPaletteService()}
renderComplete={renderComplete}
uiState={handlers.uiState as PersistedState}
interactive={isInteractive()}
chartsActiveCursorService={plugins.charts.activeCursor}
syncTooltips={config.syncTooltips}
syncCursor={config.syncCursor}
onClickMultiValue={onClickMultiValue}
/>
</div>
</KibanaRenderContextProvider>,
domNode
);
},

View file

@ -24,11 +24,10 @@
"@kbn/kibana-utils-plugin",
"@kbn/test-jest-helpers",
"@kbn/chart-icons",
"@kbn/kibana-react-plugin",
"@kbn/analytics",
"@kbn/chart-expressions-common",
"@kbn/i18n-react",
"@kbn/visualization-utils",
"@kbn/react-kibana-context-render",
],
"exclude": [
"target/**/*",

View file

@ -19,8 +19,7 @@
"usageCollection"
],
"requiredBundles": [
"kibanaUtils",
"kibanaReact"
"kibanaUtils"
]
}
}

View file

@ -9,7 +9,7 @@
import React, { lazy } from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { METRIC_TYPE } from '@kbn/analytics';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import {
ExpressionValueVisDimension,
VisualizationContainer,
@ -109,7 +109,7 @@ export const getMetricVisRenderer: (
handlers.event(chartSizeEvent);
render(
<KibanaThemeProvider theme$={core.theme.theme$}>
<KibanaRenderContextProvider {...core}>
<VisualizationContainer
data-test-subj="legacyMtrVis"
className="legacyMtrVis"
@ -125,7 +125,7 @@ export const getMetricVisRenderer: (
filterable={filterable}
/>
</VisualizationContainer>
</KibanaThemeProvider>,
</KibanaRenderContextProvider>,
domNode
);
},

View file

@ -23,9 +23,9 @@
"@kbn/utility-types",
"@kbn/kibana-utils-plugin",
"@kbn/analytics",
"@kbn/kibana-react-plugin",
"@kbn/ui-theme",
"@kbn/chart-expressions-common",
"@kbn/react-kibana-context-render",
],
"exclude": [
"target/**/*",

View file

@ -19,8 +19,7 @@
"usageCollection"
],
"requiredBundles": [
"kibanaUtils",
"kibanaReact"
"kibanaUtils"
]
}
}

View file

@ -9,7 +9,7 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
import { css } from '@emotion/react';
import { StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
@ -85,7 +85,7 @@ export const getMetricVisRenderer = (
const { MetricVis } = await import('../components/metric_vis');
render(
<KibanaThemeProvider theme$={core.theme.theme$}>
<KibanaRenderContextProvider {...core}>
<div
data-test-subj="mtrVis"
css={css`
@ -105,7 +105,7 @@ export const getMetricVisRenderer = (
overrides={overrides}
/>
</div>
</KibanaThemeProvider>,
</KibanaRenderContextProvider>,
domNode
);
},

View file

@ -23,9 +23,9 @@
"@kbn/coloring",
"@kbn/kibana-utils-plugin",
"@kbn/ui-theme",
"@kbn/kibana-react-plugin",
"@kbn/analytics",
"@kbn/chart-expressions-common",
"@kbn/react-kibana-context-render",
],
"exclude": [
"target/**/*",

View file

@ -19,8 +19,7 @@
"usageCollection"
],
"requiredBundles": [
"kibanaUtils",
"kibanaReact"
"kibanaUtils"
],
"extraPublicDirs": [
"common"

View file

@ -8,7 +8,6 @@
import React, { lazy } from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nProvider } from '@kbn/i18n-react';
import { css } from '@emotion/react';
import { i18n } from '@kbn/i18n';
import type {
@ -18,7 +17,7 @@ import type {
} from '@kbn/expressions-plugin/public';
import type { PersistedState } from '@kbn/visualizations-plugin/public';
import { withSuspense } from '@kbn/presentation-util-plugin/public';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { METRIC_TYPE } from '@kbn/analytics';
import { getColumnByAccessor } from '@kbn/visualizations-plugin/common/utils';
import {
@ -130,28 +129,26 @@ export const getPartitionVisRenderer: (
handlers.event(chartSizeEvent);
render(
<I18nProvider>
<KibanaThemeProvider theme$={core.theme.theme$}>
<div css={partitionVisRenderer}>
<PartitionVisComponent
chartsThemeService={plugins.charts.theme}
palettesRegistry={palettesRegistry}
visParams={visConfig}
visData={visData}
visType={visConfig.isDonut ? ChartTypes.DONUT : visType}
renderComplete={renderComplete}
fireEvent={handlers.event}
interactive={handlers.isInteractive()}
uiState={handlers.uiState as PersistedState}
services={{ data: plugins.data, fieldFormats: plugins.fieldFormats }}
syncColors={syncColors}
columnCellValueActions={columnCellValueActions}
overrides={overrides}
hasOpenedOnAggBasedEditor={hasOpenedOnAggBasedEditor}
/>
</div>
</KibanaThemeProvider>
</I18nProvider>,
<KibanaRenderContextProvider {...core}>
<div css={partitionVisRenderer}>
<PartitionVisComponent
chartsThemeService={plugins.charts.theme}
palettesRegistry={palettesRegistry}
visParams={visConfig}
visData={visData}
visType={visConfig.isDonut ? ChartTypes.DONUT : visType}
renderComplete={renderComplete}
fireEvent={handlers.event}
interactive={handlers.isInteractive()}
uiState={handlers.uiState as PersistedState}
services={{ data: plugins.data, fieldFormats: plugins.fieldFormats }}
syncColors={syncColors}
columnCellValueActions={columnCellValueActions}
overrides={overrides}
hasOpenedOnAggBasedEditor={hasOpenedOnAggBasedEditor}
/>
</div>
</KibanaRenderContextProvider>,
domNode
);
},

View file

@ -25,11 +25,11 @@
"@kbn/kibana-utils-plugin",
"@kbn/test-jest-helpers",
"@kbn/i18n-react",
"@kbn/kibana-react-plugin",
"@kbn/analytics",
"@kbn/chart-icons",
"@kbn/chart-expressions-common",
"@kbn/cell-actions",
"@kbn/react-kibana-context-render",
],
"exclude": [
"target/**/*",

View file

@ -19,8 +19,7 @@
"usageCollection"
],
"requiredBundles": [
"kibanaUtils",
"kibanaReact"
"kibanaUtils"
],
"extraPublicDirs": [
"common"

View file

@ -8,10 +8,9 @@
import React, { lazy } from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nProvider } from '@kbn/i18n-react';
import { ClassNames } from '@emotion/react';
import { i18n } from '@kbn/i18n';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { VisualizationContainer } from '@kbn/visualizations-plugin/public';
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
import { METRIC_TYPE } from '@kbn/analytics';
@ -91,31 +90,29 @@ export const tagcloudRenderer: (
.unsubscribe();
render(
<KibanaThemeProvider theme$={core.theme.theme$}>
<I18nProvider>
<ClassNames>
{({ css, cx }) => (
<VisualizationContainer
handlers={handlers}
// Class `tagCloudContainer` is generated by `@emotion/react` and passed as a defined class to `VisualizationContainer`.
// It is used for rendering at `Canvas`.
className={cx('tagCloudContainer', css(tagCloudVisClass))}
<KibanaRenderContextProvider {...core}>
<ClassNames>
{({ css, cx }) => (
<VisualizationContainer
handlers={handlers}
// Class `tagCloudContainer` is generated by `@emotion/react` and passed as a defined class to `VisualizationContainer`.
// It is used for rendering at `Canvas`.
className={cx('tagCloudContainer', css(tagCloudVisClass))}
renderComplete={renderComplete}
>
<TagCloudChart
{...config}
palettesRegistry={palettesRegistry}
renderComplete={renderComplete}
>
<TagCloudChart
{...config}
palettesRegistry={palettesRegistry}
renderComplete={renderComplete}
fireEvent={handlers.event}
syncColors={config.syncColors}
overrides={config.overrides}
isDarkMode={isDarkMode}
/>
</VisualizationContainer>
)}
</ClassNames>
</I18nProvider>
</KibanaThemeProvider>,
fireEvent={handlers.event}
syncColors={config.syncColors}
overrides={config.overrides}
isDarkMode={isDarkMode}
/>
</VisualizationContainer>
)}
</ClassNames>
</KibanaRenderContextProvider>,
domNode
);
},

View file

@ -23,11 +23,11 @@
"@kbn/coloring",
"@kbn/i18n",
"@kbn/i18n-react",
"@kbn/kibana-react-plugin",
"@kbn/analytics",
"@kbn/chart-expressions-common",
"@kbn/chart-icons",
"@kbn/data-plugin",
"@kbn/react-kibana-context-render",
],
"exclude": [
"target/**/*",

View file

@ -19,8 +19,6 @@
"optionalPlugins": [
"usageCollection"
],
"requiredBundles": [
"kibanaReact"
]
"requiredBundles": []
}
}

View file

@ -7,8 +7,6 @@
*/
import { i18n } from '@kbn/i18n';
import { I18nProvider } from '@kbn/i18n-react';
import { ThemeServiceStart } from '@kbn/core/public';
import { css } from '@emotion/react';
import React from 'react';
import ReactDOM from 'react-dom';
@ -23,7 +21,7 @@ import type {
IInterpreterRenderHandlers,
} from '@kbn/expressions-plugin/common';
import { FormatFactory } from '@kbn/field-formats-plugin/common';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
import { getColumnByAccessor } from '@kbn/visualizations-plugin/common/utils';
import {
@ -41,6 +39,7 @@ import type {
FilterEvent,
GetCompatibleCellValueActions,
MultiFilterEvent,
StartServices,
} from '../types';
export type GetStartDepsFn = () => Promise<{
@ -51,10 +50,10 @@ export type GetStartDepsFn = () => Promise<{
paletteService: PaletteRegistry;
timeZone: string;
useLegacyTimeAxis: boolean;
kibanaTheme: ThemeServiceStart;
eventAnnotationService: EventAnnotationServiceType;
usageCollection?: UsageCollectionStart;
timeFormat: string;
startServices: StartServices;
}>;
interface XyChartRendererDeps {
@ -260,37 +259,35 @@ export const getXyChartRenderer = ({
});
ReactDOM.render(
<KibanaThemeProvider theme$={deps.kibanaTheme.theme$}>
<I18nProvider>
<div css={chartContainerStyle} data-test-subj="xyVisChart">
<XYChartReportable
{...config}
data={deps.data}
formatFactory={deps.formatFactory}
chartsActiveCursorService={deps.activeCursor}
chartsThemeService={deps.theme}
paletteService={deps.paletteService}
timeZone={deps.timeZone}
timeFormat={deps.timeFormat}
eventAnnotationService={deps.eventAnnotationService}
useLegacyTimeAxis={deps.useLegacyTimeAxis}
minInterval={calculateMinInterval(deps.data.datatableUtilities, config)}
interactive={handlers.isInteractive()}
onClickValue={onClickValue}
onClickMultiValue={onClickMultiValue}
layerCellValueActions={layerCellValueActions}
onSelectRange={onSelectRange}
renderMode={handlers.getRenderMode()}
syncColors={config.syncColors}
syncTooltips={config.syncTooltips}
syncCursor={config.syncCursor}
uiState={handlers.uiState as PersistedState}
renderComplete={renderComplete}
setChartSize={setChartSize}
/>
</div>
</I18nProvider>
</KibanaThemeProvider>,
<KibanaRenderContextProvider {...deps.startServices}>
<div css={chartContainerStyle} data-test-subj="xyVisChart">
<XYChartReportable
{...config}
data={deps.data}
formatFactory={deps.formatFactory}
chartsActiveCursorService={deps.activeCursor}
chartsThemeService={deps.theme}
paletteService={deps.paletteService}
timeZone={deps.timeZone}
timeFormat={deps.timeFormat}
eventAnnotationService={deps.eventAnnotationService}
useLegacyTimeAxis={deps.useLegacyTimeAxis}
minInterval={calculateMinInterval(deps.data.datatableUtilities, config)}
interactive={handlers.isInteractive()}
onClickValue={onClickValue}
onClickMultiValue={onClickMultiValue}
layerCellValueActions={layerCellValueActions}
onSelectRange={onSelectRange}
renderMode={handlers.getRenderMode()}
syncColors={config.syncColors}
syncTooltips={config.syncTooltips}
syncCursor={config.syncCursor}
uiState={handlers.uiState as PersistedState}
renderComplete={renderComplete}
setChartSize={setChartSize}
/>
</div>
</KibanaRenderContextProvider>,
domNode
);
},

View file

@ -53,7 +53,7 @@ export function getTimeZone(uiSettings: IUiSettingsClient) {
export class ExpressionXyPlugin {
public setup(
core: CoreSetup<XYPluginStartDependencies>,
{ expressions, charts }: SetupDeps
{ expressions, charts: _charts }: SetupDeps
): ExpressionXyPluginSetup {
expressions.registerFunction(yAxisConfigFunction);
expressions.registerFunction(dataDecorationConfigFunction);
@ -98,13 +98,14 @@ export class ExpressionXyPlugin {
eventAnnotationService,
timeZone: getTimeZone(core.uiSettings),
timeFormat: core.uiSettings.get('dateFormat'),
startServices: coreStart,
};
};
expressions.registerRenderer(getXyChartRenderer({ getStartDeps }));
}
public start(core: CoreStart): ExpressionXyPluginStart {}
public start(_core: CoreStart): ExpressionXyPluginStart {}
public stop() {}
}

View file

@ -18,6 +18,7 @@ import type {
MultiValueClickContext,
} from '@kbn/embeddable-plugin/public';
import { ExpressionsServiceStart, ExpressionsSetup } from '@kbn/expressions-plugin/public';
import { CoreStart } from '@kbn/core/public';
export interface SetupDeps {
expressions: ExpressionsSetup;
@ -30,6 +31,8 @@ export interface StartDeps {
expression: ExpressionsServiceStart;
}
export type StartServices = Pick<CoreStart, 'analytics' | 'i18n' | 'theme'>;
export type ExpressionXyPluginSetup = void;
export type ExpressionXyPluginStart = void;

View file

@ -29,12 +29,12 @@
"@kbn/chart-icons",
"@kbn/ui-theme",
"@kbn/analytics",
"@kbn/kibana-react-plugin",
"@kbn/chart-expressions-common",
"@kbn/event-annotation-common",
"@kbn/visualization-ui-components",
"@kbn/es-query",
"@kbn/cell-actions",
"@kbn/react-kibana-context-render",
],
"exclude": [
"target/**/*",

View file

@ -7,8 +7,8 @@
*/
import { i18n } from '@kbn/i18n';
import { ThemeServiceSetup } from '@kbn/core/public';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { CoreSetup } from '@kbn/core/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
import { IncompatibleActionError, UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
// for cleanup esFilters need to fix the issue https://github.com/elastic/kibana/issues/131292
import { FilterManager, TimefilterContract } from '@kbn/data-plugin/public';
@ -38,7 +38,7 @@ async function isCompatible(context: ApplyGlobalFilterActionContext) {
export function createFilterAction(
filterManager: FilterManager,
timeFilter: TimefilterContract,
theme: ThemeServiceSetup,
core: CoreSetup,
id: string = ACTION_GLOBAL_APPLY_FILTER,
type: string = ACTION_GLOBAL_APPLY_FILTER
): UiActionsActionDefinition<ApplyGlobalFilterActionContext> {
@ -65,6 +65,7 @@ export function createFilterAction(
let selectedFilters: Filter[] = filters;
if (selectedFilters.length > 1) {
const [coreStart] = await core.getStartServices();
const indexPatterns = await Promise.all(
filters.map((filter) => {
return getIndexPatterns().get(filter.meta.index!);
@ -86,7 +87,7 @@ export function createFilterAction(
resolve(filterSelection);
}
),
{ theme$: theme.theme$ }
coreStart
),
{
'data-test-subj': 'test',

View file

@ -12,7 +12,7 @@ import { APPLY_FILTER_TRIGGER } from '@kbn/data-plugin/public';
import { createQueryStringInput } from './query_string_input/get_query_string_input';
import { UPDATE_FILTER_REFERENCES_TRIGGER, updateFilterReferencesTrigger } from './triggers';
import { ConfigSchema } from '../config';
import { setIndexPatterns, setTheme, setOverlays } from './services';
import { setIndexPatterns, setTheme, setOverlays, setAnalytics, setI18n } from './services';
import { AutocompleteService } from './autocomplete/autocomplete_service';
import { createSearchBar } from './search_bar/create_search_bar';
import { createIndexPatternSelect } from './index_pattern_select';
@ -52,7 +52,7 @@ export class UnifiedSearchPublicPlugin
uiActions.registerTrigger(updateFilterReferencesTrigger);
uiActions.registerAction(
createFilterAction(query.filterManager, query.timefilter.timefilter, core.theme)
createFilterAction(query.filterManager, query.timefilter.timefilter, core)
);
uiActions.registerAction(createUpdateFilterReferencesAction(query.filterManager));
@ -70,6 +70,8 @@ export class UnifiedSearchPublicPlugin
core: CoreStart,
{ data, dataViews, uiActions, screenshotMode }: UnifiedSearchStartDependencies
): UnifiedSearchPublicPluginStart {
setAnalytics(core.analytics);
setI18n(core.i18n);
setTheme(core.theme);
setOverlays(core.overlays);
setIndexPatterns(dataViews);

View file

@ -38,7 +38,7 @@ import {
KIBANA_USER_QUERY_LANGUAGE_KEY,
KQL_TELEMETRY_ROUTE_LATEST_VERSION,
} from '@kbn/data-plugin/common';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public';
import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
import { buildQueryFromFilters, Filter } from '@kbn/es-query';
@ -55,7 +55,7 @@ import { SuggestionsComponent } from '../typeahead';
import { onRaf } from '../utils';
import { FilterButtonGroup } from '../filter_bar/filter_button_group/filter_button_group';
import { AutocompleteService, QuerySuggestion, QuerySuggestionTypes } from '../autocomplete';
import { getTheme } from '../services';
import { getAnalytics, getI18n, getTheme } from '../services';
import './query_string_input.scss';
export const strings = {
@ -563,7 +563,7 @@ export default class QueryStringInputUI extends PureComponent<QueryStringInputPr
</EuiFlexItem>
</EuiFlexGroup>
</div>,
{ theme$: getTheme().theme$ }
{ analytics: getAnalytics(), i18n: getI18n(), theme: getTheme() }
),
});
}
@ -666,7 +666,7 @@ export default class QueryStringInputUI extends PureComponent<QueryStringInputPr
: getQueryLog(uiSettings, this.props.deps.storage, appName, this.props.query.language);
};
public onMouseEnterSuggestion = (suggestion: QuerySuggestion, index: number) => {
public onMouseEnterSuggestion = (_suggestion: QuerySuggestion, index: number) => {
this.setState({ index });
};

View file

@ -6,13 +6,22 @@
* Side Public License, v 1.
*/
import { ThemeServiceStart, OverlayStart } from '@kbn/core/public';
import {
ThemeServiceStart,
OverlayStart,
AnalyticsServiceStart,
I18nStart,
} from '@kbn/core/public';
import { createGetterSetter } from '@kbn/kibana-utils-plugin/public';
import { DataViewsContract } from '@kbn/data-views-plugin/public';
export const [getIndexPatterns, setIndexPatterns] =
createGetterSetter<DataViewsContract>('IndexPatterns');
export const [getAnalytics, setAnalytics] = createGetterSetter<AnalyticsServiceStart>('Analytics');
export const [getI18n, setI18n] = createGetterSetter<I18nStart>('I18n');
export const [getTheme, setTheme] = createGetterSetter<ThemeServiceStart>('Theme');
export const [getOverlays, setOverlays] = createGetterSetter<OverlayStart>('Overlays');

View file

@ -46,7 +46,8 @@
"@kbn/calculate-width-from-char-count",
"@kbn/react-kibana-context-render",
"@kbn/data-view-utils",
"@kbn/esql-utils"
"@kbn/esql-utils",
"@kbn/react-kibana-mount"
],
"exclude": [
"target/**/*",

View file

@ -31,7 +31,8 @@ import { TableListViewKibanaProvider } from '@kbn/content-management-table-list-
import './index.scss';
import { SpacesApi } from '@kbn/spaces-plugin/public';
import { KibanaThemeProvider, toMountPoint } from '@kbn/kibana-react-plugin/public';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { ContentClient, ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import { GraphSavePolicy } from './types';
@ -78,7 +79,6 @@ export type GraphServices = Omit<GraphDependencies, 'element' | 'history'>;
export const renderApp = ({ history, element, ...deps }: GraphDependencies) => {
const { chrome, capabilities, core } = deps;
const { theme$ } = core.theme;
if (!capabilities.graph.save) {
chrome.setBadge({
@ -117,7 +117,7 @@ export const renderApp = ({ history, element, ...deps }: GraphDependencies) => {
});
const app = (
<KibanaThemeProvider theme$={theme$}>
<KibanaRenderContextProvider {...core}>
<TableListViewKibanaProvider
{...{
core,
@ -127,7 +127,7 @@ export const renderApp = ({ history, element, ...deps }: GraphDependencies) => {
>
{graphRouter(deps)}
</TableListViewKibanaProvider>
</KibanaThemeProvider>
</KibanaRenderContextProvider>
);
ReactDOM.render(app, element);
element.setAttribute('class', 'gphAppWrapper');

View file

@ -7,7 +7,7 @@
import React, { Fragment, useCallback, useEffect } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage, I18nProvider } from '@kbn/i18n-react';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiEmptyPrompt, EuiLink, EuiButton } from '@elastic/eui';
import { ApplicationStart } from '@kbn/core/public';
import { useHistory, useLocation } from 'react-router-dom';
@ -89,34 +89,32 @@ export function ListingRoute({
);
return (
<I18nProvider>
<TableListView<GraphUserContent>
id="graph"
headingId="graphListingHeading"
createItem={capabilities.graph.save ? createItem : undefined}
findItems={findItems}
deleteItems={capabilities.graph.delete ? deleteItems : undefined}
editItem={capabilities.graph.save ? editItem : undefined}
listingLimit={listingLimit}
initialFilter={initialFilter}
initialPageSize={initialPageSize}
emptyPrompt={getNoItemsMessage(
capabilities.graph.save === false,
createItem,
coreStart.application
)}
entityName={i18n.translate('xpack.graph.listing.table.entityName', {
defaultMessage: 'graph',
})}
entityNamePlural={i18n.translate('xpack.graph.listing.table.entityNamePlural', {
defaultMessage: 'graphs',
})}
title={i18n.translate('xpack.graph.listing.graphsTitle', {
defaultMessage: 'Graphs',
})}
getDetailViewLink={({ id }) => getEditUrl(addBasePath, { id })}
/>
</I18nProvider>
<TableListView<GraphUserContent>
id="graph"
headingId="graphListingHeading"
createItem={capabilities.graph.save ? createItem : undefined}
findItems={findItems}
deleteItems={capabilities.graph.delete ? deleteItems : undefined}
editItem={capabilities.graph.save ? editItem : undefined}
listingLimit={listingLimit}
initialFilter={initialFilter}
initialPageSize={initialPageSize}
emptyPrompt={getNoItemsMessage(
capabilities.graph.save === false,
createItem,
coreStart.application
)}
entityName={i18n.translate('xpack.graph.listing.table.entityName', {
defaultMessage: 'graph',
})}
entityNamePlural={i18n.translate('xpack.graph.listing.table.entityNamePlural', {
defaultMessage: 'graphs',
})}
title={i18n.translate('xpack.graph.listing.graphsTitle', {
defaultMessage: 'Graphs',
})}
getDetailViewLink={({ id }) => getEditUrl(addBasePath, { id })}
/>
);
}

View file

@ -6,7 +6,6 @@
*/
import React, { useMemo, useRef, useState } from 'react';
import { I18nProvider } from '@kbn/i18n-react';
import { Provider } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
@ -29,7 +28,6 @@ export const WorkspaceRoute = ({
coreStart,
contentClient,
graphSavePolicy,
chrome,
canEditDrillDownUrls,
overlays,
navigation,
@ -107,15 +105,12 @@ export const WorkspaceRoute = ({
return createdWorkspace;
},
getWorkspace: () => workspaceRef.current,
notifications: coreStart.notifications,
http: coreStart.http,
overlays: coreStart.overlays,
savePolicy: graphSavePolicy,
contentClient,
changeUrl: (newUrl) => history.push(newUrl),
notifyReact: () => setRenderCounter((cur) => cur + 1),
chrome,
handleSearchQueryError,
...coreStart,
})
);
@ -135,29 +130,27 @@ export const WorkspaceRoute = ({
const { savedWorkspace, sharingSavedObjectProps } = loaded;
return (
<I18nProvider>
<KibanaContextProvider services={services}>
<Provider store={store}>
<WorkspaceLayout
spaces={spaces}
sharingSavedObjectProps={sharingSavedObjectProps}
renderCounter={renderCounter}
workspace={workspaceRef.current}
loading={loading}
setHeaderActionMenu={setHeaderActionMenu}
graphSavePolicy={graphSavePolicy}
navigation={navigation}
capabilities={capabilities}
coreStart={coreStart}
canEditDrillDownUrls={canEditDrillDownUrls}
overlays={overlays}
savedWorkspace={savedWorkspace}
indexPatternProvider={indexPatternProvider}
inspect={inspect}
requestAdapter={requestAdapter}
/>
</Provider>
</KibanaContextProvider>
</I18nProvider>
<KibanaContextProvider services={services}>
<Provider store={store}>
<WorkspaceLayout
spaces={spaces}
sharingSavedObjectProps={sharingSavedObjectProps}
renderCounter={renderCounter}
workspace={workspaceRef.current}
loading={loading}
setHeaderActionMenu={setHeaderActionMenu}
graphSavePolicy={graphSavePolicy}
navigation={navigation}
capabilities={capabilities}
coreStart={coreStart}
canEditDrillDownUrls={canEditDrillDownUrls}
overlays={overlays}
savedWorkspace={savedWorkspace}
indexPatternProvider={indexPatternProvider}
inspect={inspect}
requestAdapter={requestAdapter}
/>
</Provider>
</KibanaContextProvider>
);
};

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import type { OverlayStart } from '@kbn/core/public';
import type { CoreStart } from '@kbn/core/public';
import { ContentClient } from '@kbn/content-management-plugin/public';
import type { GraphWorkspaceSavedObject } from '../../types';
import { SAVE_DUPLICATE_REJECTED } from './constants';
@ -26,11 +26,10 @@ export async function checkForDuplicateTitle(
isTitleDuplicateConfirmed: boolean,
onTitleDuplicate: (() => void) | undefined,
services: {
overlays: OverlayStart;
contentClient: ContentClient;
}
} & Pick<CoreStart, 'overlays' | 'analytics' | 'i18n' | 'theme'>
): Promise<boolean> {
const { overlays, contentClient } = services;
const { contentClient, ...startServices } = services;
// Don't check for duplicates if user has already confirmed save with duplicate title
if (isTitleDuplicateConfirmed) {
return true;
@ -55,5 +54,5 @@ export async function checkForDuplicateTitle(
// TODO: make onTitleDuplicate a required prop and remove UI components from this class
// Need to leave here until all users pass onTitleDuplicate.
return displayDuplicateTitleConfirmModal(savedObject, overlays);
return displayDuplicateTitleConfirmModal(savedObject, startServices);
}

View file

@ -7,22 +7,22 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import type { OverlayStart } from '@kbn/core/public';
import type { CoreStart } from '@kbn/core/public';
import { EuiConfirmModal } from '@elastic/eui';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
export function confirmModalPromise(
message = '',
title = '',
confirmBtnText = '',
overlays: OverlayStart
startServices: Pick<CoreStart, 'overlays' | 'analytics' | 'i18n' | 'theme'>
): Promise<boolean> {
return new Promise((resolve, reject) => {
const cancelButtonText = i18n.translate('xpack.graph.confirmModal.cancelButtonLabel', {
defaultMessage: 'Cancel',
});
const modal = overlays.openModal(
const modal = startServices.overlays.openModal(
toMountPoint(
<EuiConfirmModal
onCancel={() => {
@ -38,7 +38,8 @@ export function confirmModalPromise(
title={title}
>
{message}
</EuiConfirmModal>
</EuiConfirmModal>,
startServices
)
);
});

View file

@ -6,14 +6,14 @@
*/
import { i18n } from '@kbn/i18n';
import type { OverlayStart } from '@kbn/core/public';
import type { CoreStart } from '@kbn/core/public';
import type { GraphWorkspaceSavedObject } from '../../types';
import { SAVE_DUPLICATE_REJECTED } from './constants';
import { confirmModalPromise } from './confirm_modal_promise';
export function displayDuplicateTitleConfirmModal(
savedObject: Pick<GraphWorkspaceSavedObject, 'title'>,
overlays: OverlayStart
startServices: Pick<CoreStart, 'overlays' | 'analytics' | 'i18n' | 'theme'>
): Promise<boolean> {
const confirmTitle = i18n.translate('xpack.graph.confirmModal.saveDuplicateConfirmationTitle', {
defaultMessage: `This visualization already exists`,
@ -32,7 +32,7 @@ export function displayDuplicateTitleConfirmModal(
});
try {
return confirmModalPromise(confirmMessage, confirmTitle, confirmButtonText, overlays);
return confirmModalPromise(confirmMessage, confirmTitle, confirmButtonText, startServices);
} catch {
return Promise.reject(new Error(SAVE_DUPLICATE_REJECTED));
}

View file

@ -7,7 +7,7 @@
import { get } from 'lodash';
import { i18n } from '@kbn/i18n';
import type { SavedObjectsCreateOptions, OverlayStart } from '@kbn/core/public';
import type { CoreStart, SavedObjectsCreateOptions } from '@kbn/core/public';
import { ContentClient } from '@kbn/content-management-plugin/public';
import { CONTENT_ID, GraphCreateIn, GraphCreateOut } from '../../../common/content_management';
import { OVERWRITE_REJECTED } from './constants';
@ -32,9 +32,12 @@ export async function saveWithConfirmation(
source: GraphSavedObjectAttributes,
savedObject: Pick<GraphWorkspaceSavedObject, 'title' | 'getEsType' | 'displayName'>,
options: SavedObjectsCreateOptions,
services: { overlays: OverlayStart; contentClient: ContentClient }
services: { contentClient: ContentClient } & Pick<
CoreStart,
'overlays' | 'analytics' | 'i18n' | 'theme'
>
): Promise<{ item: GraphSavedObject }> {
const { overlays, contentClient } = services;
const { contentClient, ...startServices } = services;
try {
return await contentClient.create<GraphCreateIn, GraphCreateOut>({
contentTypeId: CONTENT_ID,
@ -60,7 +63,7 @@ export async function saveWithConfirmation(
defaultMessage: 'Overwrite',
});
return confirmModalPromise(confirmMessage, title, confirmButtonText, overlays)
return confirmModalPromise(confirmMessage, title, confirmButtonText, startServices)
.then(() =>
contentClient.create<GraphCreateIn, GraphCreateOut>({
contentTypeId: CONTENT_ID,

View file

@ -29,10 +29,10 @@ describe('saved_workspace_utils', () => {
savedWorkspace,
{},
{
...core,
contentClient: {
create: jest.fn().mockReturnValue(Promise.resolve({ item: { id: '456' } })),
} as unknown as ContentClient,
overlays: core.overlays,
}
);
expect(savedWorkspace.id).toBe(undefined);

View file

@ -7,7 +7,7 @@
import { cloneDeep, assign, defaults, forOwn } from 'lodash';
import { i18n } from '@kbn/i18n';
import { IBasePath, OverlayStart, SavedObjectAttributes } from '@kbn/core/public';
import { CoreStart, IBasePath, SavedObjectAttributes } from '@kbn/core/public';
import { SavedObjectSaveOpts, isErrorNonFatal } from '@kbn/saved-objects-plugin/public';
import { SavedObjectNotFound } from '@kbn/kibana-utils-plugin/public';
@ -167,8 +167,7 @@ export async function saveSavedWorkspace(
}: SavedObjectSaveOpts = {},
services: {
contentClient: ContentClient;
overlays: OverlayStart;
}
} & Pick<CoreStart, 'overlays' | 'analytics' | 'i18n' | 'theme'>
) {
let attributes: SavedObjectAttributes = {};

View file

@ -6,15 +6,15 @@
*/
import React from 'react';
import { OverlayStart } from '@kbn/core/public';
import { SaveResult } from '@kbn/saved-objects-plugin/public';
import { showSaveModal } from '@kbn/saved-objects-plugin/public';
import { ContentClient } from '@kbn/content-management-plugin/public';
import { CoreStart } from '@kbn/core/public';
import { GraphWorkspaceSavedObject, GraphSavePolicy } from '../types';
import { SaveModal, OnSaveGraphProps } from '../components/save_modal';
export interface SaveWorkspaceServices {
overlays: OverlayStart;
export interface SaveWorkspaceServices
extends Pick<CoreStart, 'overlays' | 'analytics' | 'i18n' | 'theme'> {
contentClient: ContentClient;
}

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import { coreMock } from '@kbn/core/public/mocks';
import { NotificationsStart, HttpStart, OverlayStart } from '@kbn/core/public';
import createSagaMiddleware from 'redux-saga';
import { createStore, applyMiddleware, AnyAction } from 'redux';
@ -36,6 +37,7 @@ export function createMockGraphStore({
mockedDepsOverwrites?: Partial<jest.Mocked<GraphStoreDependencies>>;
initialStateOverwrites?: Partial<GraphState>;
}): MockedGraphEnvironment {
const coreStart = coreMock.createStart();
const workspaceMock = {
runLayout: jest.fn(),
simpleSearch: jest.fn(),
@ -46,6 +48,7 @@ export function createMockGraphStore({
} as unknown as Workspace;
const mockedDeps: jest.Mocked<GraphStoreDependencies> = {
...coreStart,
basePath: '',
addBasePath: jest.fn((url: string) => url),
changeUrl: jest.fn(),

View file

@ -230,9 +230,6 @@ function showModal(
hasData: workspace.nodes.length > 0 || workspace.blocklistedNodes.length > 0,
workspace: savedWorkspace,
saveWorkspace: saveWorkspaceHandler,
services: {
contentClient: deps.contentClient,
overlays: deps.overlays,
},
services: deps,
});
}

View file

@ -7,7 +7,7 @@
import createSagaMiddleware, { SagaMiddleware } from 'redux-saga';
import { combineReducers, createStore, Store, AnyAction, Dispatch, applyMiddleware } from 'redux';
import { ChromeStart, OverlayStart } from '@kbn/core/public';
import { ChromeStart } from '@kbn/core/public';
import { CoreStart } from '@kbn/core/public';
import { ContentClient } from '@kbn/content-management-plugin/public';
import {
@ -39,14 +39,14 @@ export interface GraphState {
workspace: WorkspaceState;
}
export interface GraphStoreDependencies {
export interface GraphStoreDependencies
extends Pick<CoreStart, 'overlays' | 'analytics' | 'i18n' | 'theme'> {
addBasePath: (url: string) => string;
indexPatternProvider: IndexPatternProvider;
createWorkspace: (index: string, advancedSettings: AdvancedSettings) => Workspace;
getWorkspace: () => Workspace | undefined;
notifications: CoreStart['notifications'];
http: CoreStart['http'];
overlays: OverlayStart;
contentClient: ContentClient;
savePolicy: GraphSavePolicy;
changeUrl: (newUrl: string) => void;

View file

@ -50,6 +50,7 @@
"@kbn/logging",
"@kbn/content-management-table-list-view-common",
"@kbn/visualization-utils",
"@kbn/react-kibana-context-render",
],
"exclude": [
"target/**/*",

View file

@ -8,6 +8,7 @@
import { CELL_VALUE_TRIGGER } from '@kbn/embeddable-plugin/public';
import type { History } from 'history';
import { SEARCH_EMBEDDABLE_CELL_ACTIONS_TRIGGER_ID } from '@kbn/discover-plugin/public';
import type { CoreSetup } from '@kbn/core/public';
import type { SecurityAppStore } from '../common/store/types';
import type { StartServices } from '../types';
import {
@ -45,13 +46,14 @@ import { createFilterOutLensAction } from './filter/lens/filter_out';
export const registerUIActions = (
store: SecurityAppStore,
history: History,
coreSetup: CoreSetup,
services: StartServices
) => {
registerLensEmbeddableActions(store, services);
registerDiscoverCellActions(store, services);
registerCellActions(store, history, services);
// TODO: Remove discover histogram actions when timeline esql tab is extracted from discover
registerDiscoverHistogramActions(store, history, services);
registerDiscoverHistogramActions(store, history, coreSetup, services);
};
const registerLensEmbeddableActions = (store: SecurityAppStore, services: StartServices) => {
@ -105,7 +107,7 @@ const registerDiscoverCellActions = (store: SecurityAppStore, services: StartSer
const registerCellActions = (
store: SecurityAppStore,
history: History,
_history: History,
services: StartServices
) => {
const { uiActions } = services;

View file

@ -7,19 +7,21 @@
import { createFilterAction } from '@kbn/unified-search-plugin/public';
import type { History } from 'history';
import type { CoreSetup } from '@kbn/core/public';
import type { SecurityAppStore } from '../common/store';
import type { StartServices } from '../types';
import { EsqlInTimelineTrigger, EsqlInTimelineAction } from './constants';
const createDiscoverHistogramCustomFilterAction = (
store: SecurityAppStore,
history: History,
_store: SecurityAppStore,
_history: History,
coreSetup: CoreSetup,
services: StartServices
) => {
const histogramApplyFilter = createFilterAction(
services.customDataService.query.filterManager,
services.customDataService.query.timefilter.timefilter,
services.theme,
coreSetup,
EsqlInTimelineAction.VIS_FILTER_ACTION,
EsqlInTimelineAction.VIS_FILTER_ACTION
);
@ -29,8 +31,8 @@ const createDiscoverHistogramCustomFilterAction = (
};
const createDiscoverHistogramCustomTrigger = (
store: SecurityAppStore,
history: History,
_store: SecurityAppStore,
_history: History,
services: StartServices
) => {
services.uiActions.registerTrigger({
@ -41,11 +43,17 @@ const createDiscoverHistogramCustomTrigger = (
export const registerDiscoverHistogramActions = (
store: SecurityAppStore,
history: History,
coreSetup: CoreSetup,
services: StartServices
) => {
createDiscoverHistogramCustomTrigger(store, history, services);
const histogramApplyFilter = createDiscoverHistogramCustomFilterAction(store, history, services);
const histogramApplyFilter = createDiscoverHistogramCustomFilterAction(
store,
history,
coreSetup,
services
);
services.uiActions.attachAction(EsqlInTimelineTrigger.HISTOGRAM_TRIGGER, histogramApplyFilter.id);
};

View file

@ -148,7 +148,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
const subPlugins = await this.startSubPlugins(this.storage, coreStart, startPlugins);
const store = await this.store(coreStart, startPlugins, subPlugins);
const services = await this.services.generateServices(coreStart, startPlugins);
await this.registerActions(store, params.history, services);
await this.registerActions(store, params.history, core, services);
const { renderApp } = await this.lazyApplicationDependencies();
const { ManagementSettings } = await this.lazyAssistantSettingsManagement();
@ -175,7 +175,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
const { renderApp } = await this.lazyApplicationDependencies();
const { getSubPluginRoutesByCapabilities } = await this.lazyHelpersForRoutes();
await this.registerActions(store, params.history, services);
await this.registerActions(store, params.history, core, services);
await this.registerAlertsTableConfiguration(triggersActionsUi);
const subPluginRoutes = getSubPluginRoutesByCapabilities(subPlugins, services);
@ -201,7 +201,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
appRoute: 'app/siem',
title: 'SIEM',
visibleIn: [],
mount: async (params: AppMountParameters) => {
mount: async (_params: AppMountParameters) => {
const [coreStart] = await core.getStartServices();
const { manageOldSiemRoutes } = await this.lazyHelpersForRoutes();
@ -388,11 +388,12 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
private async registerActions(
store: SecurityAppStore,
history: H.History,
coreSetup: CoreSetup,
services: StartServices
) {
if (!this._actionsRegistered) {
const { registerActions } = await this.lazyActions();
registerActions(store, history, services);
registerActions(store, history, coreSetup, services);
this._actionsRegistered = true;
}
}