From 32d0e877249121364f7adef97bd2cee530feb152 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Mon, 13 Dec 2021 10:45:02 +0000 Subject: [PATCH] [ML] Use KibanaThemeProvider in ML plugin (#120892) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/ml/public/application/app.tsx | 20 +-- .../application/license/expired_warning.tsx | 13 +- .../jobs_list_page/jobs_list_page.tsx | 126 +++++++++--------- .../models_management/force_stop_dialog.tsx | 31 +++-- .../models_management/models_list.tsx | 3 +- .../application/util/dependency_cache.ts | 11 ++ .../anomaly_charts_embeddable.tsx | 34 +++-- .../anomaly_charts_setup_flyout.tsx | 38 +++--- .../anomaly_swimlane_embeddable.tsx | 34 +++-- .../anomaly_swimlane_setup_flyout.tsx | 42 +++--- .../common/resolve_job_selection.tsx | 31 +++-- 11 files changed, 220 insertions(+), 163 deletions(-) diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index 5334f420698ab..9b9ed3a93322b 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -16,6 +16,7 @@ import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { KibanaContextProvider, + KibanaThemeProvider, RedirectAppLinks, } from '../../../../../src/plugins/kibana_react/public'; import { setDependencyCache, clearCache } from './util/dependency_cache'; @@ -99,14 +100,16 @@ const App: FC = ({ coreStart, deps, appMountParams }) => { - - - + + + + + @@ -128,6 +131,7 @@ export const renderApp = ( docLinks: coreStart.docLinks!, toastNotifications: coreStart.notifications.toasts, overlays: coreStart.overlays, + theme: coreStart.theme, recentlyAccessed: coreStart.chrome!.recentlyAccessed, basePath: coreStart.http.basePath, savedObjectsClient: coreStart.savedObjects.client, diff --git a/x-pack/plugins/ml/public/application/license/expired_warning.tsx b/x-pack/plugins/ml/public/application/license/expired_warning.tsx index c8028b641cf9a..87b69fc54fc28 100644 --- a/x-pack/plugins/ml/public/application/license/expired_warning.tsx +++ b/x-pack/plugins/ml/public/application/license/expired_warning.tsx @@ -8,8 +8,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiCallOut } from '@elastic/eui'; -import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public'; -import { getOverlays } from '../util/dependency_cache'; +import { toMountPoint, wrapWithTheme } from '../../../../../../src/plugins/kibana_react/public'; +import { getOverlays, getTheme } from '../util/dependency_cache'; let expiredLicenseBannerId: string; @@ -20,8 +20,15 @@ export function showExpiredLicenseWarning() { }); // Only show the banner once with no way to dismiss it const overlays = getOverlays(); + const theme = getTheme(); + expiredLicenseBannerId = overlays.banners.add( - toMountPoint() + toMountPoint( + wrapWithTheme( + , + theme.theme$ + ) + ) ); } } diff --git a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx index 3a969823088f1..083982e8fccd4 100644 --- a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx +++ b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx @@ -30,6 +30,7 @@ import type { ManagementAppMountParams } from '../../../../../../../../../src/pl import { checkGetManagementMlJobsResolver } from '../../../../capabilities/check_capabilities'; import { KibanaContextProvider, + KibanaThemeProvider, RedirectAppLinks, } from '../../../../../../../../../src/plugins/kibana_react/public'; @@ -139,6 +140,7 @@ export const JobsListPage: FC<{ const tabs = useTabs(isMlEnabledInSpace, spacesApi); const [currentTabId, setCurrentTabId] = useState('anomaly-detector'); const I18nContext = coreStart.i18n.Context; + const theme$ = coreStart.theme.theme$; const check = async () => { try { @@ -219,69 +221,71 @@ export const JobsListPage: FC<{ return ( - - - - - } - description={ - - } - rightSideItems={[docsLink]} - bottomBorder - /> + + + + + + } + description={ + + } + rightSideItems={[docsLink]} + bottomBorder + /> - + - - - - {spacesEnabled && ( - <> - setShowSyncFlyout(true)} - data-test-subj="mlStackMgmtSyncButton" - > - {i18n.translate('xpack.ml.management.jobsList.syncFlyoutButton', { - defaultMessage: 'Synchronize saved objects', - })} - - {showSyncFlyout && } - - - )} - - - - - - - - - {renderTabs()} - - - - + + + + {spacesEnabled && ( + <> + setShowSyncFlyout(true)} + data-test-subj="mlStackMgmtSyncButton" + > + {i18n.translate('xpack.ml.management.jobsList.syncFlyoutButton', { + defaultMessage: 'Synchronize saved objects', + })} + + {showSyncFlyout && } + + + )} + + + + + + + + + {renderTabs()} + + + + + ); diff --git a/x-pack/plugins/ml/public/application/trained_models/models_management/force_stop_dialog.tsx b/x-pack/plugins/ml/public/application/trained_models/models_management/force_stop_dialog.tsx index 86120a4003e23..30e110317148b 100644 --- a/x-pack/plugins/ml/public/application/trained_models/models_management/force_stop_dialog.tsx +++ b/x-pack/plugins/ml/public/application/trained_models/models_management/force_stop_dialog.tsx @@ -8,9 +8,9 @@ import React, { FC } from 'react'; import { EuiConfirmModal } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { OverlayStart } from 'kibana/public'; +import type { OverlayStart, ThemeServiceStart } from 'kibana/public'; import type { ModelItem } from './models_list'; -import { toMountPoint } from '../../../../../../../src/plugins/kibana_react/public'; +import { toMountPoint, wrapWithTheme } from '../../../../../../../src/plugins/kibana_react/public'; interface ForceStopModelConfirmDialogProps { model: ModelItem; @@ -64,22 +64,25 @@ export const ForceStopModelConfirmDialog: FC = }; export const getUserConfirmationProvider = - (overlays: OverlayStart) => async (forceStopModel: ModelItem) => { + (overlays: OverlayStart, theme: ThemeServiceStart) => async (forceStopModel: ModelItem) => { return new Promise(async (resolve, reject) => { try { const modalSession = overlays.openModal( toMountPoint( - { - modalSession.close(); - resolve(false); - }} - onConfirm={() => { - modalSession.close(); - resolve(true); - }} - /> + wrapWithTheme( + { + modalSession.close(); + resolve(false); + }} + onConfirm={() => { + modalSession.close(); + resolve(true); + }} + />, + theme.theme$ + ) ) ); } catch (e) { diff --git a/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx b/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx index c80ff808aa539..75659a1e3567d 100644 --- a/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx +++ b/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx @@ -82,6 +82,7 @@ export const ModelsList: FC = () => { services: { application: { navigateToUrl, capabilities }, overlays, + theme, }, } = useMlKibana(); const urlLocator = useMlLocator()!; @@ -112,7 +113,7 @@ export const ModelsList: FC = () => { {} ); - const getUserConfirmation = useMemo(() => getUserConfirmationProvider(overlays), []); + const getUserConfirmation = useMemo(() => getUserConfirmationProvider(overlays, theme), []); const navigateToPath = useNavigateToPath(); diff --git a/x-pack/plugins/ml/public/application/util/dependency_cache.ts b/x-pack/plugins/ml/public/application/util/dependency_cache.ts index 7b6b75677dddd..93d7c069d873d 100644 --- a/x-pack/plugins/ml/public/application/util/dependency_cache.ts +++ b/x-pack/plugins/ml/public/application/util/dependency_cache.ts @@ -16,6 +16,7 @@ import type { DocLinksStart, ToastsStart, OverlayStart, + ThemeServiceStart, ChromeRecentlyAccessed, IBasePath, } from 'kibana/public'; @@ -34,6 +35,7 @@ export interface DependencyCache { docLinks: DocLinksStart | null; toastNotifications: ToastsStart | null; overlays: OverlayStart | null; + theme: ThemeServiceStart | null; recentlyAccessed: ChromeRecentlyAccessed | null; fieldFormats: DataPublicPluginStart['fieldFormats'] | null; autocomplete: DataPublicPluginStart['autocomplete'] | null; @@ -57,6 +59,7 @@ const cache: DependencyCache = { docLinks: null, toastNotifications: null, overlays: null, + theme: null, recentlyAccessed: null, fieldFormats: null, autocomplete: null, @@ -80,6 +83,7 @@ export function setDependencyCache(deps: Partial) { cache.docLinks = deps.docLinks || null; cache.toastNotifications = deps.toastNotifications || null; cache.overlays = deps.overlays || null; + cache.theme = deps.theme || null; cache.recentlyAccessed = deps.recentlyAccessed || null; cache.fieldFormats = deps.fieldFormats || null; cache.autocomplete = deps.autocomplete || null; @@ -128,6 +132,13 @@ export function getOverlays() { return cache.overlays; } +export function getTheme() { + if (cache.theme === null) { + throw new Error("theme hasn't been initialized"); + } + return cache.theme; +} + export function getUiSettings() { if (cache.config === null) { throw new Error("uiSettings hasn't been initialized"); diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx index 60b7c628229b9..ce0a270c35306 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx @@ -10,7 +10,10 @@ import ReactDOM from 'react-dom'; import { CoreStart } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { Subject } from 'rxjs'; -import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public'; +import { + KibanaContextProvider, + KibanaThemeProvider, +} from '../../../../../../src/plugins/kibana_react/public'; import { Embeddable, IContainer } from '../../../../../../src/plugins/embeddable/public'; import { EmbeddableAnomalyChartsContainer } from './embeddable_anomaly_charts_container_lazy'; import type { JobId } from '../../../common/types/anomaly_detection_jobs'; @@ -96,22 +99,25 @@ export class AnomalyChartsEmbeddable extends Embeddable< this.node = node; const I18nContext = this.services[0].i18n.Context; + const theme$ = this.services[0].theme.theme$; ReactDOM.render( - - }> - - - + + + }> + + + + , node ); diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_setup_flyout.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_setup_flyout.tsx index 5090274ca7383..c4ac15ffdbe76 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_setup_flyout.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_setup_flyout.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { CoreStart } from 'kibana/public'; import { VIEW_BY_JOB_LABEL } from '../../application/explorer/explorer_constants'; -import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public'; +import { toMountPoint, wrapWithTheme } from '../../../../../../src/plugins/kibana_react/public'; import { AnomalyDetectorService } from '../../application/services/anomaly_detector_service'; import { getDefaultExplorerChartsPanelTitle } from './anomaly_charts_embeddable'; import { HttpService } from '../../application/services/http_service'; @@ -31,24 +31,28 @@ export async function resolveEmbeddableAnomalyChartsUserInput( const jobs = await anomalyDetectorService.getJobs$(jobIds).toPromise(); const influencers = anomalyDetectorService.extractInfluencers(jobs); influencers.push(VIEW_BY_JOB_LABEL); + const { theme$ } = coreStart.theme; const modalSession = overlays.openModal( toMountPoint( - { - modalSession.close(); - resolve({ - jobIds, - title: panelTitle, - maxSeriesToPlot, - }); - }} - onCancel={() => { - modalSession.close(); - reject(); - }} - /> + wrapWithTheme( + { + modalSession.close(); + resolve({ + jobIds, + title: panelTitle, + maxSeriesToPlot, + }); + }} + onCancel={() => { + modalSession.close(); + reject(); + }} + />, + theme$ + ) ) ); } catch (error) { diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx index 7f9e99f3a0c8e..e168029148006 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx @@ -10,7 +10,10 @@ import ReactDOM from 'react-dom'; import { CoreStart } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { Subject } from 'rxjs'; -import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public'; +import { + KibanaContextProvider, + KibanaThemeProvider, +} from '../../../../../../src/plugins/kibana_react/public'; import { Embeddable, IContainer } from '../../../../../../src/plugins/embeddable/public'; import { EmbeddableSwimLaneContainer } from './embeddable_swim_lane_container_lazy'; import type { JobId } from '../../../common/types/anomaly_detection_jobs'; @@ -58,22 +61,25 @@ export class AnomalySwimlaneEmbeddable extends Embeddable< this.node = node; const I18nContext = this.services[0].i18n.Context; + const theme$ = this.services[0].theme.theme$; ReactDOM.render( - - }> - - - + + + }> + + + + , node ); diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout.tsx index 5027eb6783a64..28cf197de5dfe 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { CoreStart } from 'kibana/public'; import { VIEW_BY_JOB_LABEL } from '../../application/explorer/explorer_constants'; -import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public'; +import { toMountPoint, wrapWithTheme } from '../../../../../../src/plugins/kibana_react/public'; import { AnomalySwimlaneInitializer } from './anomaly_swimlane_initializer'; import { AnomalyDetectorService } from '../../application/services/anomaly_detector_service'; import { getDefaultSwimlanePanelTitle } from './anomaly_swimlane_embeddable'; @@ -31,26 +31,30 @@ export async function resolveAnomalySwimlaneUserInput( const jobs = await anomalyDetectorService.getJobs$(jobIds).toPromise(); const influencers = anomalyDetectorService.extractInfluencers(jobs); influencers.push(VIEW_BY_JOB_LABEL); + const { theme$ } = coreStart.theme; const modalSession = overlays.openModal( toMountPoint( - { - modalSession.close(); - resolve({ - jobIds, - title: panelTitle, - swimlaneType, - viewBy, - }); - }} - onCancel={() => { - modalSession.close(); - reject(); - }} - /> + wrapWithTheme( + { + modalSession.close(); + resolve({ + jobIds, + title: panelTitle, + swimlaneType, + viewBy, + }); + }} + onCancel={() => { + modalSession.close(); + reject(); + }} + />, + theme$ + ) ) ); } catch (error) { diff --git a/x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx b/x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx index fbceeb7f7cf79..bf7ea8eac3f50 100644 --- a/x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx +++ b/x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx @@ -13,6 +13,7 @@ import { getInitialGroupsMap } from '../../application/components/job_selector/j import { KibanaContextProvider, toMountPoint, + wrapWithTheme, } from '../../../../../../src/plugins/kibana_react/public'; import { getMlGlobalServices } from '../../application/app'; import { DashboardConstants } from '../../../../../../src/plugins/dashboard/public'; @@ -34,6 +35,7 @@ export async function resolveJobSelection( const { http, uiSettings, + theme, application: { currentAppId$ }, } = coreStart; @@ -70,18 +72,23 @@ export async function resolveJobSelection( const flyoutSession = coreStart.overlays.openFlyout( toMountPoint( - - - + wrapWithTheme( + + + , + theme.theme$ + ) ), { 'data-test-subj': 'mlFlyoutJobSelector',