Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Use KibanaThemeProvider in ML plugin #120892

Merged
merged 2 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions x-pack/plugins/ml/public/application/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -99,14 +100,16 @@ const App: FC<AppProps> = ({ coreStart, deps, appMountParams }) => {
<RedirectAppLinks application={coreStart.application}>
<ApplicationUsageTrackingProvider>
<I18nContext>
<KibanaContextProvider
services={{
...services,
mlServices: getMlGlobalServices(coreStart.http, deps.usageCollection),
}}
>
<MlRouter pageDeps={pageDeps} />
</KibanaContextProvider>
<KibanaThemeProvider theme$={appMountParams.theme$}>
<KibanaContextProvider
services={{
...services,
mlServices: getMlGlobalServices(coreStart.http, deps.usageCollection),
}}
>
<MlRouter pageDeps={pageDeps} />
</KibanaContextProvider>
</KibanaThemeProvider>
</I18nContext>
</ApplicationUsageTrackingProvider>
</RedirectAppLinks>
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -20,8 +20,15 @@ export function showExpiredLicenseWarning() {
});
// Only show the banner once with no way to dismiss it
const overlays = getOverlays();
const theme = getTheme();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually can avoid using dependency cache here by passing overlays and a theme as arguments. First to MlClientLicense constructor and then to this function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MlClientLicense would need to keep a local reference to overlays and theme for use later, which is no different to the dependency cache keeping references to them.
At least with the dependency cache they are all in the same place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. @jgowdyelastic and I discussed this and decided that keeping a copy in the cache rather than a copy in the licence is simpler for now.


expiredLicenseBannerId = overlays.banners.add(
toMountPoint(<EuiCallOut iconType="iInCircle" color="warning" title={message} />)
toMountPoint(
wrapWithTheme(
<EuiCallOut iconType="iInCircle" color="warning" title={message} />,
theme.theme$
)
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -139,6 +140,7 @@ export const JobsListPage: FC<{
const tabs = useTabs(isMlEnabledInSpace, spacesApi);
const [currentTabId, setCurrentTabId] = useState<JobType>('anomaly-detector');
const I18nContext = coreStart.i18n.Context;
const theme$ = coreStart.theme.theme$;

const check = async () => {
try {
Expand Down Expand Up @@ -219,69 +221,71 @@ export const JobsListPage: FC<{
return (
<RedirectAppLinks application={coreStart.application}>
<I18nContext>
<KibanaContextProvider
services={{
...coreStart,
share,
data,
usageCollection,
mlServices: getMlGlobalServices(coreStart.http, usageCollection),
}}
>
<ContextWrapper feature={PLUGIN_ID}>
<Router history={history}>
<EuiPageHeader
pageTitle={
<FormattedMessage
id="xpack.ml.management.jobsList.jobsListTitle"
defaultMessage="Machine Learning Jobs"
/>
}
description={
<FormattedMessage
id="xpack.ml.management.jobsList.jobsListTagline"
defaultMessage="View, export, and import machine learning analytics and anomaly detection jobs."
/>
}
rightSideItems={[docsLink]}
bottomBorder
/>
<KibanaThemeProvider theme$={theme$}>
<KibanaContextProvider
services={{
...coreStart,
share,
data,
usageCollection,
mlServices: getMlGlobalServices(coreStart.http, usageCollection),
}}
>
<ContextWrapper feature={PLUGIN_ID}>
<Router history={history}>
<EuiPageHeader
pageTitle={
<FormattedMessage
id="xpack.ml.management.jobsList.jobsListTitle"
defaultMessage="Machine Learning Jobs"
/>
}
description={
<FormattedMessage
id="xpack.ml.management.jobsList.jobsListTagline"
defaultMessage="View, export, and import machine learning analytics and anomaly detection jobs."
/>
}
rightSideItems={[docsLink]}
bottomBorder
/>

<EuiSpacer size="l" />
<EuiSpacer size="l" />

<EuiPageContentBody
id="kibanaManagementMLSection"
data-test-subj="mlPageStackManagementJobsList"
>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
{spacesEnabled && (
<>
<EuiButtonEmpty
onClick={() => setShowSyncFlyout(true)}
data-test-subj="mlStackMgmtSyncButton"
>
{i18n.translate('xpack.ml.management.jobsList.syncFlyoutButton', {
defaultMessage: 'Synchronize saved objects',
})}
</EuiButtonEmpty>
{showSyncFlyout && <JobSpacesSyncFlyout onClose={onCloseSyncFlyout} />}
<EuiSpacer size="s" />
</>
)}
</EuiFlexItem>
<EuiFlexItem grow={false}>
<ExportJobsFlyout isDisabled={false} currentTab={currentTabId} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<ImportJobsFlyout isDisabled={false} />
</EuiFlexItem>
</EuiFlexGroup>
{renderTabs()}
</EuiPageContentBody>
</Router>
</ContextWrapper>
</KibanaContextProvider>
<EuiPageContentBody
id="kibanaManagementMLSection"
data-test-subj="mlPageStackManagementJobsList"
>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
{spacesEnabled && (
<>
<EuiButtonEmpty
onClick={() => setShowSyncFlyout(true)}
data-test-subj="mlStackMgmtSyncButton"
>
{i18n.translate('xpack.ml.management.jobsList.syncFlyoutButton', {
defaultMessage: 'Synchronize saved objects',
})}
</EuiButtonEmpty>
{showSyncFlyout && <JobSpacesSyncFlyout onClose={onCloseSyncFlyout} />}
<EuiSpacer size="s" />
</>
)}
</EuiFlexItem>
<EuiFlexItem grow={false}>
<ExportJobsFlyout isDisabled={false} currentTab={currentTabId} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<ImportJobsFlyout isDisabled={false} />
</EuiFlexItem>
</EuiFlexGroup>
{renderTabs()}
</EuiPageContentBody>
</Router>
</ContextWrapper>
</KibanaContextProvider>
</KibanaThemeProvider>
</I18nContext>
</RedirectAppLinks>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -64,22 +64,25 @@ export const ForceStopModelConfirmDialog: FC<ForceStopModelConfirmDialogProps> =
};

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(
<ForceStopModelConfirmDialog
model={forceStopModel}
onCancel={() => {
modalSession.close();
resolve(false);
}}
onConfirm={() => {
modalSession.close();
resolve(true);
}}
/>
wrapWithTheme(
<ForceStopModelConfirmDialog
model={forceStopModel}
onCancel={() => {
modalSession.close();
resolve(false);
}}
onConfirm={() => {
modalSession.close();
resolve(true);
}}
/>,
theme.theme$
)
)
);
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export const ModelsList: FC = () => {
services: {
application: { navigateToUrl, capabilities },
overlays,
theme,
},
} = useMlKibana();
const urlLocator = useMlLocator()!;
Expand Down Expand Up @@ -112,7 +113,7 @@ export const ModelsList: FC = () => {
{}
);

const getUserConfirmation = useMemo(() => getUserConfirmationProvider(overlays), []);
const getUserConfirmation = useMemo(() => getUserConfirmationProvider(overlays, theme), []);

const navigateToPath = useNavigateToPath();

Expand Down
11 changes: 11 additions & 0 deletions x-pack/plugins/ml/public/application/util/dependency_cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
DocLinksStart,
ToastsStart,
OverlayStart,
ThemeServiceStart,
ChromeRecentlyAccessed,
IBasePath,
} from 'kibana/public';
Expand All @@ -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;
Expand All @@ -57,6 +59,7 @@ const cache: DependencyCache = {
docLinks: null,
toastNotifications: null,
overlays: null,
theme: null,
recentlyAccessed: null,
fieldFormats: null,
autocomplete: null,
Expand All @@ -80,6 +83,7 @@ export function setDependencyCache(deps: Partial<DependencyCache>) {
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;
Expand Down Expand Up @@ -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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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(
<I18nContext>
<KibanaContextProvider services={{ ...this.services[0] }}>
<Suspense fallback={<EmbeddableLoading />}>
<EmbeddableAnomalyChartsContainer
id={this.input.id}
embeddableContext={this}
embeddableInput={this.getInput$()}
services={this.services}
refresh={this.reload$.asObservable()}
onInputChange={this.updateInput.bind(this)}
onOutputChange={this.updateOutput.bind(this)}
/>
</Suspense>
</KibanaContextProvider>
<KibanaThemeProvider theme$={theme$}>
<KibanaContextProvider services={{ ...this.services[0] }}>
<Suspense fallback={<EmbeddableLoading />}>
<EmbeddableAnomalyChartsContainer
id={this.input.id}
embeddableContext={this}
embeddableInput={this.getInput$()}
services={this.services}
refresh={this.reload$.asObservable()}
onInputChange={this.updateInput.bind(this)}
onOutputChange={this.updateOutput.bind(this)}
/>
</Suspense>
</KibanaContextProvider>
</KibanaThemeProvider>
</I18nContext>,
node
);
Expand Down
Loading