Preparation for High Contrast Mode, ML domain (#205540)

## Summary

**Reviewers: Please test the code paths affected by this PR. See the
"Risks" section below.**

Part of work for enabling "high contrast mode" in Kibana. See
https://github.com/elastic/kibana/issues/205411

**Background:**
Kibana will soon have a user profile setting to allow users to enable
"high contrast mode." This setting will activate a flag with
`<EuiProvider>` that causes EUI components to render with higher
contrast visual elements. Consumer plugins and packages need to be
updated selected places where `<EuiProvider>` is wrapped, to pass the
`UserProfileService` service dependency from the CoreStart contract.

**NOTE:** **EUI currently does not yet support the high-contrast mode
flag**, but support for that is expected to come soon. These first PRs
are simply preparing the code by wiring up the `UserProvideService`.

### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [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
- [X] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

### Risks

Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.

Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.

- [ ] [medium/high] The implementor of this change did not manually test
the affected code paths and relied on type-checking and functional tests
to drive the changes. Code owners for this PR need to manually test the
affected code paths.
- [ ] [medium] The `UserProfileService` dependency comes from the
CoreStart contract. If acquiring the service causes synchronous code to
become asynchronous, check for race conditions or errors in rendering
React components. Code owners for this PR need to manually test the
affected code paths.
This commit is contained in:
Tim Sullivan 2025-01-07 07:53:25 -07:00 committed by GitHub
parent 30c7ce6a15
commit bccf0c99c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 146 additions and 26 deletions

View file

@ -129,6 +129,7 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
notifications: { toasts },
uiSettings: config,
uiSettingsKeys,
userProfile,
theme,
i18n: i18nStart,
} = useDatePickerContext();
@ -221,7 +222,7 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
}}
/>
</EuiButton>,
{ theme, i18n: i18nStart }
{ theme, i18n: i18nStart, userProfile }
),
},
{ toastLifeTimeMs: 30000 }

View file

@ -9,7 +9,13 @@ import React, { createContext, useContext, type FC, type PropsWithChildren } fro
import type { UI_SETTINGS } from '@kbn/data-plugin/common';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { CoreSetup, I18nStart, IUiSettingsClient, ThemeServiceStart } from '@kbn/core/public';
import type {
CoreSetup,
I18nStart,
IUiSettingsClient,
ThemeServiceStart,
UserProfileService,
} from '@kbn/core/public';
import type { HttpStart } from '@kbn/core/public';
/**
@ -28,6 +34,10 @@ export interface DatePickerDependencies {
* notifications service
*/
notifications: CoreSetup['notifications'];
/**
* Kibana Security User Profile Service
*/
userProfile: UserProfileService;
/**
* EUI theme
*/

View file

@ -88,9 +88,17 @@ export const DataDriftDetectionAppState: FC<DataDriftDetectionAppStateProps> = (
charts,
unifiedSearch,
};
const startServices = pick(coreStart, 'analytics', 'i18n', 'theme');
const startServices = pick(coreStart, 'analytics', 'i18n', 'theme', 'userProfile');
const datePickerDeps = {
...pick(services, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(services, [
'data',
'http',
'notifications',
'i18n',
'theme',
'userProfile',
'uiSettings',
]),
uiSettingsKeys: UI_SETTINGS,
};
const location = useLocation();

View file

@ -150,7 +150,7 @@ const FieldStatisticsWrapper = (props: FieldStatisticTableEmbeddableProps) => {
const { overridableServices } = props;
const kibanaRenderServices = useMemo(
() => pick(coreStart, 'analytics', 'i18n', 'theme'),
() => pick(coreStart, 'analytics', 'i18n', 'theme', 'userProfile'),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
@ -168,6 +168,7 @@ const FieldStatisticsWrapper = (props: FieldStatisticTableEmbeddableProps) => {
'notifications',
'theme',
'uiSettings',
'userProfile',
'i18n',
]),
uiSettingsKeys: UI_SETTINGS,

View file

@ -328,9 +328,17 @@ export const IndexDataVisualizer: FC<Props> = ({
unifiedSearch,
};
const startServices = pick(coreStart, 'analytics', 'i18n', 'theme');
const startServices = pick(coreStart, 'analytics', 'i18n', 'theme', 'userProfile');
const datePickerDeps: DatePickerDependencies = {
...pick(services, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(services, [
'data',
'http',
'notifications',
'theme',
'uiSettings',
'userProfile',
'i18n',
]),
uiSettingsKeys: UI_SETTINGS,
showFrozenDataTierChoice,
};

View file

@ -27,6 +27,7 @@ import type { AppDependencies } from '../app_dependencies';
import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import { settingsServiceMock } from '@kbn/core-ui-settings-browser-mocks';
import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks';
import { userProfileServiceMock } from '@kbn/core-user-profile-browser-mocks';
const coreSetup = coreMock.createSetup();
const coreStart = coreMock.createStart();
@ -92,6 +93,7 @@ const appDependencies: AppDependencies = {
storage: { get: jest.fn() } as unknown as Storage,
overlays: coreStart.overlays,
theme: themeServiceMock.createStartContract(),
userProfile: userProfileServiceMock.createStart(),
http: coreSetup.http,
history: {} as ScopedHistory,
share: { urlGenerators: { getUrlGenerator: jest.fn() } } as unknown as SharePluginStart,

View file

@ -18,6 +18,7 @@ import type {
SavedObjectsStart,
ScopedHistory,
ThemeServiceStart,
UserProfileService,
} from '@kbn/core/public';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
@ -57,6 +58,7 @@ export interface AppDependencies {
storage: Storage;
overlays: OverlayStart;
theme: ThemeServiceStart;
userProfile: UserProfileService;
history: ScopedHistory;
share: SharePluginStart;
spaces?: SpacesPluginStart;

View file

@ -39,6 +39,7 @@ export async function mountManagementSection(
i18n,
overlays,
theme,
userProfile,
savedObjects,
uiSettings,
settings,
@ -79,6 +80,7 @@ export async function mountManagementSection(
notifications,
overlays,
theme,
userProfile,
savedObjects,
storage: localStorage,
uiSettings,

View file

@ -225,7 +225,15 @@ export const Wizard: FC<WizardProps> = React.memo(({ cloneConfig, searchItems })
const stepsConfig = [stepDefine, stepDetails, stepCreate];
const datePickerDeps: DatePickerDependencies = {
...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(appDependencies, [
'data',
'http',
'notifications',
'theme',
'uiSettings',
'userProfile',
'i18n',
]),
uiSettingsKeys: UI_SETTINGS,
showFrozenDataTierChoice: showNodeInfo,
};

View file

@ -78,7 +78,8 @@
"@kbn/monaco",
"@kbn/json-schemas",
"@kbn/ml-field-stats-flyout",
"@kbn/ml-validators"
"@kbn/ml-validators",
"@kbn/core-user-profile-browser-mocks"
],
"exclude": [
"target/**/*",

View file

@ -64,7 +64,15 @@ export const ChangePointDetectionAppState: FC<ChangePointDetectionAppStateProps>
showFrozenDataTierChoice = true,
}) => {
const datePickerDeps: DatePickerDependencies = {
...pick(appContextValue, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(appContextValue, [
'data',
'http',
'notifications',
'theme',
'uiSettings',
'userProfile',
'i18n',
]),
uiSettingsKeys: UI_SETTINGS,
showFrozenDataTierChoice,
};

View file

@ -55,7 +55,15 @@ export const LogCategorizationAppState: FC<LogCategorizationAppStateProps> = ({
}
const datePickerDeps: DatePickerDependencies = {
...pick(appContextValue, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(appContextValue, [
'data',
'http',
'notifications',
'theme',
'uiSettings',
'userProfile',
'i18n',
]),
uiSettingsKeys: UI_SETTINGS,
showFrozenDataTierChoice,
};

View file

@ -34,7 +34,15 @@ export const LogCategorizationDiscoverWrapper: FC<LogCategorizationEmbeddableWra
const I18nContext = appContextValue.i18n.Context;
const datePickerDeps = {
...pick(appContextValue, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(appContextValue, [
'data',
'http',
'notifications',
'theme',
'uiSettings',
'userProfile',
'i18n',
]),
uiSettingsKeys: UI_SETTINGS,
};

View file

@ -48,9 +48,16 @@ export async function showCategorizeFlyout(
...coreStart,
...plugins,
};
const startServices = pick(coreStart, 'analytics', 'i18n', 'theme');
const startServices = pick(coreStart, 'analytics', 'i18n', 'theme', 'userProfile');
const datePickerDeps: DatePickerDependencies = {
...pick(appContextValue, ['data', 'http', 'notifications', 'theme', 'uiSettings']),
...pick(appContextValue, [
'data',
'http',
'notifications',
'theme',
'uiSettings',
'userProfile',
]),
i18n,
uiSettingsKeys: UI_SETTINGS,
};

View file

@ -63,7 +63,15 @@ export const LogRateAnalysisAppState: FC<LogRateAnalysisAppStateProps> = ({
const casesPermissions = appContextValue.cases?.helpers.canUseCases();
const datePickerDeps: DatePickerDependencies = {
...pick(appContextValue, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(appContextValue, [
'data',
'http',
'notifications',
'theme',
'uiSettings',
'userProfile',
'i18n',
]),
uiSettingsKeys: UI_SETTINGS,
showFrozenDataTierChoice,
};

View file

@ -80,7 +80,15 @@ export const LogRateAnalysisContentWrapper: FC<LogRateAnalysisContentWrapperProp
}
const datePickerDeps = {
...pick(appContextValue, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(appContextValue, [
'data',
'http',
'notifications',
'theme',
'uiSettings',
'userProfile',
'i18n',
]),
uiSettingsKeys: UI_SETTINGS,
showFrozenDataTierChoice,
};

View file

@ -70,7 +70,15 @@ export const ChangePointChartInitializer: FC<AnomalyChartsInitializerProps> = ({
} = appContextValue;
const datePickerDeps: DatePickerDependencies = {
...pick(appContextValue, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(appContextValue, [
'data',
'http',
'notifications',
'theme',
'uiSettings',
'userProfile',
'i18n',
]),
uiSettingsKeys: UI_SETTINGS,
};

View file

@ -22,6 +22,7 @@ import type {
HttpStart,
IUiSettingsClient,
ThemeServiceStart,
UserProfileService,
} from '@kbn/core/public';
import type { LensPublicStart } from '@kbn/lens-plugin/public';
import type { EmbeddableStart } from '@kbn/embeddable-plugin/public';
@ -90,6 +91,10 @@ export interface AiopsAppContextValue {
* Usage collection.
*/
usageCollection?: UsageCollectionSetup;
/**
* User profile service.
*/
userProfile: UserProfileService;
/**
* Used to create deep links to other plugins.
*/

View file

@ -101,7 +101,7 @@ const ChangePointDetectionWrapper: FC<ChangePointDetectionPropsWithDeps> = ({
}, [coreStart, pluginStart]);
const datePickerDeps = {
...pick(deps, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(deps, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'userProfile', 'i18n']),
uiSettingsKeys: UI_SETTINGS,
};

View file

@ -90,7 +90,7 @@ const LogRateAnalysisEmbeddableWrapperWithDeps: FC<LogRateAnalysisPropsWithDeps>
}, [coreStart, pluginStart]);
const datePickerDeps = {
...pick(deps, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(deps, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'userProfile', 'i18n']),
uiSettingsKeys: UI_SETTINGS,
};

View file

@ -98,7 +98,7 @@ const PatternAnalysisWrapper: FC<PatternAnalysisPropsWithDeps> = ({
}, [coreStart, pluginStart]);
const datePickerDeps = {
...pick(deps, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(deps, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'userProfile', 'i18n']),
uiSettingsKeys: UI_SETTINGS,
};

View file

@ -72,6 +72,7 @@ export const ChangePointDetectionPage: FC = () => {
'uiSettings',
'unifiedSearch',
'usageCollection',
'userProfile',
]),
fieldStats: { useFieldStatsTrigger, FieldStatsFlyoutProvider },
}}

View file

@ -63,6 +63,7 @@ export const LogCategorizationPage: FC = () => {
'uiActions',
'uiSettings',
'unifiedSearch',
'userProfile',
'embeddable',
'cases',
]),

View file

@ -57,6 +57,7 @@ export const LogRateAnalysisPage: FC = () => {
'theme',
'uiActions',
'uiSettings',
'userProfile',
'unifiedSearch',
'observabilityAIAssistant',
'embeddable',

View file

@ -122,9 +122,17 @@ const App: FC<AppProps> = ({
if (!licenseReady || !mlCapabilities) return null;
const startServices = pick(coreStart, 'analytics', 'i18n', 'theme');
const startServices = pick(coreStart, 'analytics', 'i18n', 'theme', 'userProfile');
const datePickerDeps: DatePickerDependencies = {
...pick(services, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(services, [
'data',
'http',
'notifications',
'theme',
'uiSettings',
'userProfile',
'i18n',
]),
uiSettingsKeys: UI_SETTINGS,
showFrozenDataTierChoice: !isServerless,
};

View file

@ -840,7 +840,7 @@ export const StartUpdateDeploymentModal: FC<StartDeploymentModalProps> = ({
export const getUserInputModelDeploymentParamsProvider =
(
overlays: OverlayStart,
startServices: Pick<CoreStart, 'analytics' | 'i18n' | 'theme'>,
startServices: Pick<CoreStart, 'analytics' | 'i18n' | 'theme' | 'userProfile'>,
startModelDeploymentDocUrl: string,
cloudInfo: CloudInfo,
showNodeInfo: boolean,

View file

@ -219,7 +219,10 @@ export const StopModelDeploymentsConfirmDialog: FC<ForceStopModelConfirmDialogPr
};
export const getUserConfirmationProvider =
(overlays: OverlayStart, startServices: Pick<CoreStart, 'analytics' | 'i18n' | 'theme'>) =>
(
overlays: OverlayStart,
startServices: Pick<CoreStart, 'analytics' | 'i18n' | 'theme' | 'userProfile'>
) =>
async (forceStopModel: NLPModelItem): Promise<string[]> => {
return new Promise(async (resolve, reject) => {
try {

View file

@ -123,9 +123,9 @@ const SingleMetricViewerWrapper: FC<SingleMetricViewerPropsWithDeps> = ({
const isMounted = useMountedState();
const { mlApi, mlTimeSeriesExplorerService, toastNotificationService } = mlServices;
const startServices = pick(coreStart, 'analytics', 'i18n', 'theme');
const startServices = pick(coreStart, 'analytics', 'i18n', 'theme', 'userProfile');
const datePickerDeps: DatePickerDependencies = {
...pick(coreStart, ['http', 'notifications', 'theme', 'uiSettings', 'i18n']),
...pick(coreStart, ['http', 'notifications', 'theme', 'uiSettings', 'userProfile', 'i18n']),
data: pluginStart.data,
uiSettingsKeys: UI_SETTINGS,
showFrozenDataTierChoice: false,

View file

@ -233,6 +233,7 @@ export const LogRateAnalysis: FC<AlertDetailsLogRateAnalysisSectionProps> = ({ r
'uiSettings',
'unifiedSearch',
'theme',
'userProfile',
'lens',
'i18n',
]),

View file

@ -201,6 +201,7 @@ export function LogRateAnalysis({ alert, dataView, services }: AlertDetailsLogRa
'uiSettings',
'unifiedSearch',
'theme',
'userProfile',
'lens',
'i18n',
]),

View file

@ -302,6 +302,7 @@ export function LogRateAnalysisPanel({ slo, alert, rule }: Props) {
'uiSettings',
'unifiedSearch',
'theme',
'userProfile',
'lens',
'i18n',
]),