mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
[Security Solution] Remove usage of deprecated modules for mounting React, Part II (#182061)
## 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 is the **2nd** PR to focus on code within **Security Solution**,
following https://github.com/elastic/kibana/pull/181099.
<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:
parent
b7057ce083
commit
a6ddf518e2
26 changed files with 330 additions and 271 deletions
|
@ -36,14 +36,14 @@ export const DetectionRuleCounter = ({ tags, createRuleFn }: DetectionRuleCounte
|
|||
const [isCreateRuleLoading, setIsCreateRuleLoading] = useState(false);
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const { http, notifications } = useKibana().services;
|
||||
const { http, notifications, analytics, i18n, theme } = useKibana().services;
|
||||
|
||||
const history = useHistory();
|
||||
|
||||
const [, setRulesTable] = useSessionStorage(RULES_TABLE_SESSION_STORAGE_KEY);
|
||||
|
||||
const rulePageNavigation = useCallback(async () => {
|
||||
await setRulesTable({
|
||||
setRulesTable({
|
||||
tags,
|
||||
});
|
||||
history.push({
|
||||
|
@ -58,14 +58,15 @@ export const DetectionRuleCounter = ({ tags, createRuleFn }: DetectionRuleCounte
|
|||
}, [history]);
|
||||
|
||||
const createDetectionRuleOnClick = useCallback(async () => {
|
||||
const startServices = { analytics, notifications, i18n, theme };
|
||||
setIsCreateRuleLoading(true);
|
||||
const ruleResponse = await createRuleFn(http);
|
||||
setIsCreateRuleLoading(false);
|
||||
showCreateDetectionRuleSuccessToast(notifications, http, ruleResponse);
|
||||
showCreateDetectionRuleSuccessToast(startServices, http, ruleResponse);
|
||||
// Triggering a refetch of rules and alerts to update the UI
|
||||
queryClient.invalidateQueries([DETECTION_ENGINE_RULES_KEY]);
|
||||
queryClient.invalidateQueries([DETECTION_ENGINE_ALERTS_KEY]);
|
||||
}, [createRuleFn, http, notifications, queryClient]);
|
||||
}, [createRuleFn, http, analytics, notifications, i18n, theme, queryClient]);
|
||||
|
||||
return (
|
||||
<EuiSkeletonText
|
||||
|
|
|
@ -16,14 +16,15 @@ import {
|
|||
EuiText,
|
||||
useGeneratedHtmlId,
|
||||
} from '@elastic/eui';
|
||||
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
import type { HttpSetup, NotificationsStart } from '@kbn/core/public';
|
||||
import { toMountPoint } from '@kbn/react-kibana-mount';
|
||||
import type { HttpSetup } from '@kbn/core/public';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { QueryClient, useQueryClient } from '@tanstack/react-query';
|
||||
import type { RuleResponse } from '../common/types';
|
||||
import { CREATE_RULE_ACTION_SUBJ, TAKE_ACTION_SUBJ } from './test_subjects';
|
||||
import { useKibana } from '../common/hooks/use_kibana';
|
||||
import { DETECTION_ENGINE_ALERTS_KEY, DETECTION_ENGINE_RULES_KEY } from '../common/constants';
|
||||
import { CloudSecurityPostureStartServices } from '../types';
|
||||
|
||||
const RULE_PAGE_PATH = '/app/security/rules/id/';
|
||||
|
||||
|
@ -35,10 +36,13 @@ interface TakeActionProps {
|
|||
}
|
||||
|
||||
export const showCreateDetectionRuleSuccessToast = (
|
||||
notifications: NotificationsStart,
|
||||
cloudSecurityStartServices: CloudSecurityPostureStartServices,
|
||||
http: HttpSetup,
|
||||
ruleResponse: RuleResponse
|
||||
) => {
|
||||
const { notifications, analytics, i18n, theme } = cloudSecurityStartServices;
|
||||
const startServices = { analytics, i18n, theme };
|
||||
|
||||
return notifications.toasts.addSuccess({
|
||||
toastLifeTimeMs: 10000,
|
||||
color: 'success',
|
||||
|
@ -60,7 +64,8 @@ export const showCreateDetectionRuleSuccessToast = (
|
|||
defaultMessage="Add rule actions to get notified when alerts are generated."
|
||||
/>
|
||||
</EuiText>
|
||||
</div>
|
||||
</div>,
|
||||
startServices
|
||||
),
|
||||
text: toMountPoint(
|
||||
<div>
|
||||
|
@ -78,19 +83,23 @@ export const showCreateDetectionRuleSuccessToast = (
|
|||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
</div>,
|
||||
startServices
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
export const showChangeBenchmarkRuleStatesSuccessToast = (
|
||||
notifications: NotificationsStart,
|
||||
cloudSecurityStartServices: CloudSecurityPostureStartServices,
|
||||
isBenchmarkRuleMuted: boolean,
|
||||
data: {
|
||||
numberOfRules: number;
|
||||
numberOfDetectionRules: number;
|
||||
}
|
||||
) => {
|
||||
const { notifications, analytics, i18n, theme } = cloudSecurityStartServices;
|
||||
const startServices = { analytics, i18n, theme };
|
||||
|
||||
return notifications.toasts.addSuccess({
|
||||
toastLifeTimeMs: 10000,
|
||||
color: 'success',
|
||||
|
@ -111,7 +120,8 @@ export const showChangeBenchmarkRuleStatesSuccessToast = (
|
|||
/>
|
||||
)}
|
||||
</strong>
|
||||
</EuiText>
|
||||
</EuiText>,
|
||||
startServices
|
||||
),
|
||||
text: toMountPoint(
|
||||
<div>
|
||||
|
@ -145,7 +155,8 @@ export const showChangeBenchmarkRuleStatesSuccessToast = (
|
|||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>,
|
||||
startServices
|
||||
),
|
||||
});
|
||||
};
|
||||
|
@ -171,8 +182,6 @@ export const TakeAction = ({
|
|||
prefix: 'smallContextMenuPopover',
|
||||
});
|
||||
|
||||
const { http, notifications } = useKibana().services;
|
||||
|
||||
const button = (
|
||||
<EuiButton
|
||||
isLoading={isLoading}
|
||||
|
@ -193,8 +202,6 @@ export const TakeAction = ({
|
|||
createRuleFn={createRuleFn}
|
||||
setIsLoading={setIsLoading}
|
||||
closePopover={closePopover}
|
||||
notifications={notifications}
|
||||
http={http}
|
||||
queryClient={queryClient}
|
||||
isCreateDetectionRuleDisabled={isCreateDetectionRuleDisabled}
|
||||
/>
|
||||
|
@ -206,9 +213,6 @@ export const TakeAction = ({
|
|||
enableBenchmarkRuleFn={enableBenchmarkRuleFn}
|
||||
setIsLoading={setIsLoading}
|
||||
closePopover={closePopover}
|
||||
notifications={notifications}
|
||||
http={http}
|
||||
queryClient={queryClient}
|
||||
/>
|
||||
);
|
||||
if (disableBenchmarkRuleFn)
|
||||
|
@ -218,9 +222,6 @@ export const TakeAction = ({
|
|||
disableBenchmarkRuleFn={disableBenchmarkRuleFn}
|
||||
setIsLoading={setIsLoading}
|
||||
closePopover={closePopover}
|
||||
notifications={notifications}
|
||||
http={http}
|
||||
queryClient={queryClient}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -243,19 +244,17 @@ const CreateDetectionRule = ({
|
|||
createRuleFn,
|
||||
setIsLoading,
|
||||
closePopover,
|
||||
notifications,
|
||||
http,
|
||||
queryClient,
|
||||
isCreateDetectionRuleDisabled = false,
|
||||
}: {
|
||||
createRuleFn: (http: HttpSetup) => Promise<RuleResponse>;
|
||||
setIsLoading: (isLoading: boolean) => void;
|
||||
closePopover: () => void;
|
||||
notifications: NotificationsStart;
|
||||
http: HttpSetup;
|
||||
queryClient: QueryClient;
|
||||
isCreateDetectionRuleDisabled: boolean;
|
||||
}) => {
|
||||
const { http, ...startServices } = useKibana().services;
|
||||
|
||||
return (
|
||||
<EuiContextMenuItem
|
||||
key="createRule"
|
||||
|
@ -265,7 +264,7 @@ const CreateDetectionRule = ({
|
|||
setIsLoading(true);
|
||||
const ruleResponse = await createRuleFn(http);
|
||||
setIsLoading(false);
|
||||
showCreateDetectionRuleSuccessToast(notifications, http, ruleResponse);
|
||||
showCreateDetectionRuleSuccessToast(startServices, http, ruleResponse);
|
||||
// Triggering a refetch of rules and alerts to update the UI
|
||||
queryClient.invalidateQueries([DETECTION_ENGINE_RULES_KEY]);
|
||||
queryClient.invalidateQueries([DETECTION_ENGINE_ALERTS_KEY]);
|
||||
|
@ -284,14 +283,10 @@ const EnableBenchmarkRule = ({
|
|||
enableBenchmarkRuleFn,
|
||||
setIsLoading,
|
||||
closePopover,
|
||||
notifications,
|
||||
}: {
|
||||
enableBenchmarkRuleFn: () => Promise<void>;
|
||||
setIsLoading: (isLoading: boolean) => void;
|
||||
closePopover: () => void;
|
||||
notifications: NotificationsStart;
|
||||
http: HttpSetup;
|
||||
queryClient: QueryClient;
|
||||
}) => {
|
||||
return (
|
||||
<EuiContextMenuItem
|
||||
|
@ -313,14 +308,10 @@ const DisableBenchmarkRule = ({
|
|||
disableBenchmarkRuleFn,
|
||||
setIsLoading,
|
||||
closePopover,
|
||||
notifications,
|
||||
}: {
|
||||
disableBenchmarkRuleFn: () => Promise<void>;
|
||||
setIsLoading: (isLoading: boolean) => void;
|
||||
closePopover: () => void;
|
||||
notifications: NotificationsStart;
|
||||
http: HttpSetup;
|
||||
queryClient: QueryClient;
|
||||
}) => {
|
||||
return (
|
||||
<EuiContextMenuItem
|
||||
|
|
|
@ -71,8 +71,10 @@ export const RuleFlyout = ({ onClose, rule, refetchRulesStates }: RuleFlyoutProp
|
|||
const { data: rulesData } = useFetchDetectionRulesByTags(
|
||||
getFindingsDetectionRuleSearchTags(rule.metadata)
|
||||
);
|
||||
const { notifications, analytics, i18n: i18nStart, theme } = useKibana().services;
|
||||
const startServices = { notifications, analytics, i18n: i18nStart, theme };
|
||||
const isRuleMuted = rule?.state === 'muted';
|
||||
const { notifications } = useKibana().services;
|
||||
|
||||
const switchRuleStates = async () => {
|
||||
if (rule.metadata.benchmark.rule_number) {
|
||||
const rulesObjectRequest = {
|
||||
|
@ -83,8 +85,8 @@ export const RuleFlyout = ({ onClose, rule, refetchRulesStates }: RuleFlyoutProp
|
|||
};
|
||||
const nextRuleStates = isRuleMuted ? 'unmute' : 'mute';
|
||||
await postRequestChangeRulesStates(nextRuleStates, [rulesObjectRequest]);
|
||||
await refetchRulesStates();
|
||||
await showChangeBenchmarkRuleStatesSuccessToast(notifications, isRuleMuted, {
|
||||
refetchRulesStates();
|
||||
showChangeBenchmarkRuleStatesSuccessToast(startServices, isRuleMuted, {
|
||||
numberOfRules: 1,
|
||||
numberOfDetectionRules: rulesData?.total || 0,
|
||||
});
|
||||
|
|
|
@ -20,8 +20,9 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { uniqBy } from 'lodash';
|
||||
import { CoreStart, HttpSetup, NotificationsStart } from '@kbn/core/public';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { HttpSetup } from '@kbn/core/public';
|
||||
import { CloudSecurityPostureStartServices } from '../../types';
|
||||
import { useKibana } from '../../common/hooks/use_kibana';
|
||||
import { getFindingsDetectionRuleSearchTags } from '../../../common/utils/detection_rules';
|
||||
import { ColumnNameWithTooltip } from '../../components/column_name_with_tooltip';
|
||||
import type { CspBenchmarkRulesWithStates, RulesState } from './rules_container';
|
||||
|
@ -61,8 +62,8 @@ type GetColumnProps = Pick<
|
|||
currentPageRulesArray: CspBenchmarkRulesWithStates[],
|
||||
selectedRulesArray: CspBenchmarkRulesWithStates[]
|
||||
) => boolean;
|
||||
notifications: NotificationsStart;
|
||||
http: HttpSetup;
|
||||
startServices: CloudSecurityPostureStartServices;
|
||||
};
|
||||
|
||||
export const RulesTable = ({
|
||||
|
@ -132,40 +133,42 @@ export const RulesTable = ({
|
|||
return true;
|
||||
};
|
||||
|
||||
const { http, notifications } = useKibana<CoreStart>().services;
|
||||
const { http, notifications, analytics, i18n: i18nStart, theme } = useKibana().services;
|
||||
useEffect(() => {
|
||||
if (selectedRules.length >= items.length && items.length > 0 && selectedRules.length > 0)
|
||||
setIsAllRulesSelectedThisPage(true);
|
||||
else setIsAllRulesSelectedThisPage(false);
|
||||
}, [items.length, selectedRules.length]);
|
||||
|
||||
const columns = useMemo(
|
||||
() =>
|
||||
getColumns({
|
||||
refetchRulesStates,
|
||||
postRequestChangeRulesStates,
|
||||
selectedRules,
|
||||
setSelectedRules,
|
||||
items,
|
||||
setIsAllRulesSelectedThisPage,
|
||||
isAllRulesSelectedThisPage,
|
||||
isCurrentPageRulesASubset,
|
||||
onRuleClick,
|
||||
notifications,
|
||||
http,
|
||||
}),
|
||||
[
|
||||
const columns = useMemo(() => {
|
||||
const startServices = { notifications, analytics, i18n: i18nStart, theme };
|
||||
return getColumns({
|
||||
refetchRulesStates,
|
||||
postRequestChangeRulesStates,
|
||||
selectedRules,
|
||||
setSelectedRules,
|
||||
items,
|
||||
setIsAllRulesSelectedThisPage,
|
||||
isAllRulesSelectedThisPage,
|
||||
isCurrentPageRulesASubset,
|
||||
onRuleClick,
|
||||
notifications,
|
||||
http,
|
||||
]
|
||||
);
|
||||
startServices,
|
||||
});
|
||||
}, [
|
||||
refetchRulesStates,
|
||||
postRequestChangeRulesStates,
|
||||
selectedRules,
|
||||
setSelectedRules,
|
||||
items,
|
||||
isAllRulesSelectedThisPage,
|
||||
onRuleClick,
|
||||
notifications,
|
||||
http,
|
||||
analytics,
|
||||
i18nStart,
|
||||
theme,
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -194,8 +197,8 @@ const getColumns = ({
|
|||
isAllRulesSelectedThisPage,
|
||||
isCurrentPageRulesASubset,
|
||||
onRuleClick,
|
||||
notifications,
|
||||
http,
|
||||
startServices,
|
||||
}: GetColumnProps): Array<EuiTableFieldDataColumnType<CspBenchmarkRulesWithStates>> => [
|
||||
{
|
||||
field: 'action',
|
||||
|
@ -203,7 +206,7 @@ const getColumns = ({
|
|||
<EuiCheckbox
|
||||
id={RULES_ROW_SELECT_ALL_CURRENT_PAGE}
|
||||
checked={isCurrentPageRulesASubset(items, selectedRules) && isAllRulesSelectedThisPage}
|
||||
onChange={(e) => {
|
||||
onChange={() => {
|
||||
const uniqueSelectedRules = uniqBy([...selectedRules, ...items], 'metadata.id');
|
||||
const onChangeSelectAllThisPageFn = () => {
|
||||
setSelectedRules(uniqueSelectedRules);
|
||||
|
@ -227,7 +230,7 @@ const getColumns = ({
|
|||
),
|
||||
width: '40px',
|
||||
sortable: false,
|
||||
render: (rules, item: CspBenchmarkRulesWithStates) => {
|
||||
render: (_rules, item: CspBenchmarkRulesWithStates) => {
|
||||
return (
|
||||
<EuiCheckbox
|
||||
checked={selectedRules.some(
|
||||
|
@ -300,7 +303,7 @@ const getColumns = ({
|
|||
align: 'right',
|
||||
width: '100px',
|
||||
truncateText: true,
|
||||
render: (name, rule: CspBenchmarkRulesWithStates) => {
|
||||
render: (_name, rule: CspBenchmarkRulesWithStates) => {
|
||||
const rulesObjectRequest = {
|
||||
benchmark_id: rule?.metadata.benchmark.id,
|
||||
benchmark_version: rule?.metadata.benchmark.version,
|
||||
|
@ -320,9 +323,9 @@ const getColumns = ({
|
|||
http
|
||||
)
|
||||
).total;
|
||||
await postRequestChangeRulesStates(nextRuleState, [rulesObjectRequest]);
|
||||
await refetchRulesStates();
|
||||
await showChangeBenchmarkRuleStatesSuccessToast(notifications, isRuleMuted, {
|
||||
postRequestChangeRulesStates(nextRuleState, [rulesObjectRequest]);
|
||||
refetchRulesStates();
|
||||
showChangeBenchmarkRuleStatesSuccessToast(startServices, isRuleMuted, {
|
||||
numberOfRules: 1,
|
||||
numberOfDetectionRules: detectionRuleCount || 0,
|
||||
});
|
||||
|
|
|
@ -254,7 +254,8 @@ const CurrentPageOfTotal = ({
|
|||
{ match: 'any' }
|
||||
);
|
||||
|
||||
const { notifications } = useKibana().services;
|
||||
const { notifications, analytics, i18n: i18nStart, theme } = useKibana().services;
|
||||
const startServices = { notifications, analytics, i18n: i18nStart, theme };
|
||||
|
||||
const postRequestChangeRulesState = useChangeCspRuleState();
|
||||
const changeRulesState = async (state: 'mute' | 'unmute') => {
|
||||
|
@ -269,9 +270,9 @@ const CurrentPageOfTotal = ({
|
|||
// Only do the API Call IF there are no undefined value for rule number in the selected rules
|
||||
if (!bulkSelectedRules.some((rule) => rule.rule_number === undefined)) {
|
||||
await postRequestChangeRulesState(state, bulkSelectedRules);
|
||||
await refetchRulesStates();
|
||||
await setIsPopoverOpen(false);
|
||||
await showChangeBenchmarkRuleStatesSuccessToast(notifications, state !== 'mute', {
|
||||
refetchRulesStates();
|
||||
setIsPopoverOpen(false);
|
||||
showChangeBenchmarkRuleStatesSuccessToast(startServices, state !== 'mute', {
|
||||
numberOfRules: bulkSelectedRules.length,
|
||||
numberOfDetectionRules: rulesData?.total || 0,
|
||||
});
|
||||
|
|
|
@ -47,7 +47,7 @@ export class CspPlugin
|
|||
private isCloudEnabled?: boolean;
|
||||
|
||||
public setup(
|
||||
core: CoreSetup<CspClientPluginStartDeps, CspClientPluginStart>,
|
||||
_core: CoreSetup<CspClientPluginStartDeps, CspClientPluginStart>,
|
||||
plugins: CspClientPluginSetupDeps
|
||||
): CspClientPluginSetup {
|
||||
this.isCloudEnabled = plugins.cloud.isCloudEnabled;
|
||||
|
|
|
@ -14,7 +14,7 @@ import { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
|||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public';
|
||||
import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { ToastsStart } from '@kbn/core/public';
|
||||
import { CoreStart, ToastsStart } from '@kbn/core/public';
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
|
@ -84,3 +84,8 @@ export interface CspSecuritySolutionContext {
|
|||
state?: Record<string, string | undefined>;
|
||||
}>;
|
||||
}
|
||||
|
||||
export type CloudSecurityPostureStartServices = Pick<
|
||||
CoreStart,
|
||||
'notifications' | 'analytics' | 'i18n' | 'theme'
|
||||
>;
|
||||
|
|
|
@ -63,7 +63,8 @@
|
|||
"@kbn/alerting-plugin",
|
||||
"@kbn/code-editor",
|
||||
"@kbn/code-editor-mock",
|
||||
"@kbn/search-types"
|
||||
"@kbn/search-types",
|
||||
"@kbn/react-kibana-mount"
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Router } from '@kbn/shared-ux-router';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
import { QueryClientProvider } from '@tanstack/react-query';
|
||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
||||
|
||||
|
@ -20,17 +18,17 @@ import { OsqueryApp } from './components/app';
|
|||
import { PLUGIN_NAME } from '../common';
|
||||
import { KibanaContextProvider } from './common/lib/kibana';
|
||||
import { queryClient } from './query_client';
|
||||
import { KibanaThemeProvider } from './shared_imports';
|
||||
import { KibanaRenderContextProvider } from './shared_imports';
|
||||
|
||||
export const renderApp = (
|
||||
core: CoreStart,
|
||||
services: AppPluginStartDependencies,
|
||||
{ element, history, theme$ }: AppMountParameters,
|
||||
{ element, history }: AppMountParameters,
|
||||
storage: Storage,
|
||||
kibanaVersion: string
|
||||
) => {
|
||||
ReactDOM.render(
|
||||
<KibanaThemeProvider theme$={theme$}>
|
||||
<KibanaRenderContextProvider {...core}>
|
||||
<KibanaContextProvider
|
||||
// eslint-disable-next-line react-perf/jsx-no-new-object-as-prop
|
||||
services={{
|
||||
|
@ -41,18 +39,14 @@ export const renderApp = (
|
|||
storage,
|
||||
}}
|
||||
>
|
||||
<EuiErrorBoundary>
|
||||
<Router history={history}>
|
||||
<I18nProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<OsqueryApp />
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
</QueryClientProvider>
|
||||
</I18nProvider>
|
||||
</Router>
|
||||
</EuiErrorBoundary>
|
||||
<Router history={history}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<OsqueryApp />
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
</QueryClientProvider>
|
||||
</Router>
|
||||
</KibanaContextProvider>
|
||||
</KibanaThemeProvider>,
|
||||
</KibanaRenderContextProvider>,
|
||||
element
|
||||
);
|
||||
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiComment, EuiErrorBoundary } from '@elastic/eui';
|
||||
import { EuiComment } from '@elastic/eui';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { FormattedRelative } from '@kbn/i18n-react';
|
||||
|
||||
import type { CoreStart } from '@kbn/core-lifecycle-browser';
|
||||
import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
||||
import { QueryClientProvider } from '@tanstack/react-query';
|
||||
import { EmptyPrompt } from '../../routes/components/empty_prompt';
|
||||
import { useKibana } from '../../common/lib/kibana';
|
||||
|
@ -72,15 +73,13 @@ const OsqueryActionResultWrapperComponent: React.FC<OsqueryActionResultsWrapperP
|
|||
services,
|
||||
...restProps
|
||||
}) => (
|
||||
<KibanaThemeProvider theme$={services.theme.theme$}>
|
||||
<KibanaRenderContextProvider {...services}>
|
||||
<KibanaContextProvider services={services}>
|
||||
<EuiErrorBoundary>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<OsqueryActionResult {...restProps} />
|
||||
</QueryClientProvider>
|
||||
</EuiErrorBoundary>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<OsqueryActionResult {...restProps} />
|
||||
</QueryClientProvider>
|
||||
</KibanaContextProvider>
|
||||
</KibanaThemeProvider>
|
||||
</KibanaRenderContextProvider>
|
||||
);
|
||||
|
||||
const OsqueryActionResultWrapper = React.memo(OsqueryActionResultWrapperComponent);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary, EuiSpacer } from '@elastic/eui';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { QueryClientProvider } from '@tanstack/react-query';
|
||||
import type { CoreStart } from '@kbn/core/public';
|
||||
|
@ -14,7 +14,7 @@ import { EmptyPrompt } from '../../routes/components/empty_prompt';
|
|||
import { KibanaContextProvider, useKibana } from '../../common/lib/kibana';
|
||||
|
||||
import { queryClient } from '../../query_client';
|
||||
import { KibanaThemeProvider } from '../../shared_imports';
|
||||
import { KibanaRenderContextProvider } from '../../shared_imports';
|
||||
import type { StartPlugins } from '../../types';
|
||||
import type { OsqueryActionResultsProps } from './types';
|
||||
import { OsqueryResult } from './osquery_result';
|
||||
|
@ -61,15 +61,13 @@ const OsqueryActionResultsWrapperComponent: React.FC<OsqueryActionResultsWrapper
|
|||
services,
|
||||
...restProps
|
||||
}) => (
|
||||
<KibanaThemeProvider theme$={services.theme.theme$}>
|
||||
<KibanaRenderContextProvider {...services}>
|
||||
<KibanaContextProvider services={services}>
|
||||
<EuiErrorBoundary>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<OsqueryActionResults {...restProps} />
|
||||
</QueryClientProvider>
|
||||
</EuiErrorBoundary>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<OsqueryActionResults {...restProps} />
|
||||
</QueryClientProvider>
|
||||
</KibanaContextProvider>
|
||||
</KibanaThemeProvider>
|
||||
</KibanaRenderContextProvider>
|
||||
);
|
||||
|
||||
const OsqueryActionResultsWrapper = React.memo(OsqueryActionResultsWrapperComponent);
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { QueryClientProvider } from '@tanstack/react-query';
|
||||
import type { CoreStart } from '@kbn/core/public';
|
||||
import { KibanaContextProvider } from '../common/lib/kibana';
|
||||
|
||||
import { queryClient } from '../query_client';
|
||||
import { KibanaThemeProvider } from '../shared_imports';
|
||||
import { KibanaRenderContextProvider } from '../shared_imports';
|
||||
import type { StartPlugins } from '../types';
|
||||
|
||||
export interface ServicesWrapperProps {
|
||||
|
@ -21,13 +20,11 @@ export interface ServicesWrapperProps {
|
|||
}
|
||||
|
||||
const ServicesWrapperComponent: React.FC<ServicesWrapperProps> = ({ services, children }) => (
|
||||
<KibanaThemeProvider theme$={services.theme.theme$}>
|
||||
<KibanaRenderContextProvider {...services}>
|
||||
<KibanaContextProvider services={services}>
|
||||
<EuiErrorBoundary>
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
</EuiErrorBoundary>
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
</KibanaContextProvider>
|
||||
</KibanaThemeProvider>
|
||||
</KibanaRenderContextProvider>
|
||||
);
|
||||
|
||||
const ServicesWrapper = React.memo(ServicesWrapperComponent);
|
||||
|
|
|
@ -45,4 +45,5 @@ export {
|
|||
export { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers';
|
||||
export type { ERROR_CODE } from '@kbn/es-ui-shared-plugin/static/forms/helpers/field_validators/types';
|
||||
|
||||
export { useUiSetting$, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
export { useUiSetting$ } from '@kbn/kibana-react-plugin/public';
|
||||
export { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
||||
|
|
|
@ -22,7 +22,8 @@ export interface AddToTimelineButtonProps {
|
|||
|
||||
export const SECURITY_APP_NAME = 'Security';
|
||||
export const AddToTimelineButton = (props: AddToTimelineButtonProps) => {
|
||||
const { timelines, appName } = useKibana().services;
|
||||
const { timelines, appName, analytics, i18n, theme } = useKibana().services;
|
||||
const startServices = { analytics, i18n, theme };
|
||||
const { field, value, isIcon, iconProps } = props;
|
||||
|
||||
const queryIds = isArray(value) ? value : [value];
|
||||
|
@ -60,5 +61,6 @@ export const AddToTimelineButton = (props: AddToTimelineButtonProps) => {
|
|||
...(isIcon
|
||||
? { showTooltip: true, Component: TimelineIconComponent }
|
||||
: { Component: TimelineComponent }),
|
||||
startServices,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
"@kbn/shared-ux-page-kibana-template",
|
||||
"@kbn/openapi-generator",
|
||||
"@kbn/code-editor",
|
||||
"@kbn/search-types"
|
||||
"@kbn/search-types",
|
||||
"@kbn/react-kibana-context-render"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ export const useHoverActionItems = ({
|
|||
}: UseHoverActionItemsProps): UseHoverActionItems => {
|
||||
const kibana = useKibana();
|
||||
const dispatch = useDispatch();
|
||||
const { timelines, timelineFilterManager } = kibana.services;
|
||||
const { timelines, timelineFilterManager, analytics, i18n, theme } = kibana.services;
|
||||
const dataViewId = useDataViewId(getSourcererScopeId(scopeId ?? ''));
|
||||
|
||||
// Common actions used by the alert table and alert flyout
|
||||
|
@ -168,127 +168,130 @@ export const useHoverActionItems = ({
|
|||
]
|
||||
);
|
||||
|
||||
const allItems = useMemo(
|
||||
() =>
|
||||
[
|
||||
showFilters ? (
|
||||
<div data-test-subj="hover-actions-filter-for" key="hover-actions-filter-for">
|
||||
{getFilterForValueButton({
|
||||
defaultFocusedButtonRef,
|
||||
field,
|
||||
filterManager,
|
||||
keyboardEvent: stKeyboardEvent,
|
||||
onClick: handleHoverActionClicked,
|
||||
onFilterAdded,
|
||||
ownFocus,
|
||||
showTooltip: enableOverflowButton ? false : true,
|
||||
value: values,
|
||||
dataViewId,
|
||||
})}
|
||||
</div>
|
||||
) : null,
|
||||
showFilters ? (
|
||||
<div data-test-subj="hover-actions-filter-out" key="hover-actions-filter-out">
|
||||
{getFilterOutValueButton({
|
||||
field,
|
||||
filterManager,
|
||||
keyboardEvent: stKeyboardEvent,
|
||||
onFilterAdded,
|
||||
ownFocus,
|
||||
onClick: handleHoverActionClicked,
|
||||
showTooltip: enableOverflowButton ? false : true,
|
||||
value: values,
|
||||
dataViewId,
|
||||
})}
|
||||
</div>
|
||||
) : null,
|
||||
toggleColumn && !shouldDisableColumnToggle ? (
|
||||
<div data-test-subj="hover-actions-toggle-column" key="hover-actions-toggle-column">
|
||||
{getColumnToggleButton({
|
||||
Component: enableOverflowButton ? EuiContextMenuItem : undefined,
|
||||
field,
|
||||
isDisabled: isObjectArray && dataType !== 'geo_point',
|
||||
isObjectArray,
|
||||
keyboardEvent: stKeyboardEvent,
|
||||
ownFocus,
|
||||
onClick: handleHoverActionClicked,
|
||||
showTooltip: enableOverflowButton ? false : true,
|
||||
toggleColumn,
|
||||
value: values,
|
||||
})}
|
||||
</div>
|
||||
) : null,
|
||||
values != null && (draggableId != null || !isEmpty(dataProvider)) && !hideAddToTimeline ? (
|
||||
<div data-test-subj="hover-actions-add-timeline" key="hover-actions-add-timeline">
|
||||
{getAddToTimelineButton({
|
||||
Component: enableOverflowButton ? EuiContextMenuItem : undefined,
|
||||
dataProvider,
|
||||
draggableId,
|
||||
field,
|
||||
keyboardEvent: stKeyboardEvent,
|
||||
ownFocus,
|
||||
onClick: onAddToTimelineClicked,
|
||||
showTooltip: enableOverflowButton ? false : true,
|
||||
value: values,
|
||||
})}
|
||||
</div>
|
||||
) : null,
|
||||
allowTopN({
|
||||
fieldType,
|
||||
isAggregatable,
|
||||
fieldName: field,
|
||||
hideTopN,
|
||||
})
|
||||
? showTopNBtn
|
||||
: null,
|
||||
field != null ? (
|
||||
<div data-test-subj="hover-actions-copy-button" key="hover-actions-copy-button">
|
||||
{getCopyButton({
|
||||
Component: enableOverflowButton ? EuiContextMenuItem : undefined,
|
||||
field,
|
||||
isHoverAction: true,
|
||||
keyboardEvent: stKeyboardEvent,
|
||||
ownFocus,
|
||||
onClick: handleHoverActionClicked,
|
||||
showTooltip: enableOverflowButton ? false : true,
|
||||
value: values,
|
||||
})}
|
||||
</div>
|
||||
) : null,
|
||||
].filter((item) => {
|
||||
return item != null;
|
||||
}),
|
||||
[
|
||||
dataProvider,
|
||||
dataType,
|
||||
defaultFocusedButtonRef,
|
||||
draggableId,
|
||||
enableOverflowButton,
|
||||
field,
|
||||
fieldType,
|
||||
isAggregatable,
|
||||
filterManager,
|
||||
getAddToTimelineButton,
|
||||
getColumnToggleButton,
|
||||
getCopyButton,
|
||||
getFilterForValueButton,
|
||||
getFilterOutValueButton,
|
||||
handleHoverActionClicked,
|
||||
onAddToTimelineClicked,
|
||||
hideAddToTimeline,
|
||||
hideTopN,
|
||||
isObjectArray,
|
||||
onFilterAdded,
|
||||
ownFocus,
|
||||
shouldDisableColumnToggle,
|
||||
showFilters,
|
||||
showTopNBtn,
|
||||
stKeyboardEvent,
|
||||
toggleColumn,
|
||||
values,
|
||||
dataViewId,
|
||||
]
|
||||
) as JSX.Element[];
|
||||
const allItems = useMemo(() => {
|
||||
const startServices = { analytics, i18n, theme };
|
||||
return [
|
||||
showFilters ? (
|
||||
<div data-test-subj="hover-actions-filter-for" key="hover-actions-filter-for">
|
||||
{getFilterForValueButton({
|
||||
defaultFocusedButtonRef,
|
||||
field,
|
||||
filterManager,
|
||||
keyboardEvent: stKeyboardEvent,
|
||||
onClick: handleHoverActionClicked,
|
||||
onFilterAdded,
|
||||
ownFocus,
|
||||
showTooltip: enableOverflowButton ? false : true,
|
||||
value: values,
|
||||
dataViewId,
|
||||
})}
|
||||
</div>
|
||||
) : null,
|
||||
showFilters ? (
|
||||
<div data-test-subj="hover-actions-filter-out" key="hover-actions-filter-out">
|
||||
{getFilterOutValueButton({
|
||||
field,
|
||||
filterManager,
|
||||
keyboardEvent: stKeyboardEvent,
|
||||
onFilterAdded,
|
||||
ownFocus,
|
||||
onClick: handleHoverActionClicked,
|
||||
showTooltip: enableOverflowButton ? false : true,
|
||||
value: values,
|
||||
dataViewId,
|
||||
})}
|
||||
</div>
|
||||
) : null,
|
||||
toggleColumn && !shouldDisableColumnToggle ? (
|
||||
<div data-test-subj="hover-actions-toggle-column" key="hover-actions-toggle-column">
|
||||
{getColumnToggleButton({
|
||||
Component: enableOverflowButton ? EuiContextMenuItem : undefined,
|
||||
field,
|
||||
isDisabled: isObjectArray && dataType !== 'geo_point',
|
||||
isObjectArray,
|
||||
keyboardEvent: stKeyboardEvent,
|
||||
ownFocus,
|
||||
onClick: handleHoverActionClicked,
|
||||
showTooltip: enableOverflowButton ? false : true,
|
||||
toggleColumn,
|
||||
value: values,
|
||||
})}
|
||||
</div>
|
||||
) : null,
|
||||
values != null && (draggableId != null || !isEmpty(dataProvider)) && !hideAddToTimeline ? (
|
||||
<div data-test-subj="hover-actions-add-timeline" key="hover-actions-add-timeline">
|
||||
{getAddToTimelineButton({
|
||||
Component: enableOverflowButton ? EuiContextMenuItem : undefined,
|
||||
dataProvider,
|
||||
draggableId,
|
||||
field,
|
||||
keyboardEvent: stKeyboardEvent,
|
||||
ownFocus,
|
||||
onClick: onAddToTimelineClicked,
|
||||
showTooltip: enableOverflowButton ? false : true,
|
||||
value: values,
|
||||
startServices,
|
||||
})}
|
||||
</div>
|
||||
) : null,
|
||||
allowTopN({
|
||||
fieldType,
|
||||
isAggregatable,
|
||||
fieldName: field,
|
||||
hideTopN,
|
||||
})
|
||||
? showTopNBtn
|
||||
: null,
|
||||
field != null ? (
|
||||
<div data-test-subj="hover-actions-copy-button" key="hover-actions-copy-button">
|
||||
{getCopyButton({
|
||||
Component: enableOverflowButton ? EuiContextMenuItem : undefined,
|
||||
field,
|
||||
isHoverAction: true,
|
||||
keyboardEvent: stKeyboardEvent,
|
||||
ownFocus,
|
||||
onClick: handleHoverActionClicked,
|
||||
showTooltip: enableOverflowButton ? false : true,
|
||||
value: values,
|
||||
})}
|
||||
</div>
|
||||
) : null,
|
||||
].filter((item) => {
|
||||
return item != null;
|
||||
});
|
||||
}, [
|
||||
dataProvider,
|
||||
dataType,
|
||||
defaultFocusedButtonRef,
|
||||
draggableId,
|
||||
enableOverflowButton,
|
||||
field,
|
||||
fieldType,
|
||||
isAggregatable,
|
||||
filterManager,
|
||||
getAddToTimelineButton,
|
||||
getColumnToggleButton,
|
||||
getCopyButton,
|
||||
getFilterForValueButton,
|
||||
getFilterOutValueButton,
|
||||
handleHoverActionClicked,
|
||||
onAddToTimelineClicked,
|
||||
hideAddToTimeline,
|
||||
hideTopN,
|
||||
isObjectArray,
|
||||
onFilterAdded,
|
||||
ownFocus,
|
||||
shouldDisableColumnToggle,
|
||||
showFilters,
|
||||
showTopNBtn,
|
||||
stKeyboardEvent,
|
||||
toggleColumn,
|
||||
values,
|
||||
dataViewId,
|
||||
analytics,
|
||||
i18n,
|
||||
theme,
|
||||
]) as JSX.Element[];
|
||||
|
||||
const overflowActionItems = useMemo(
|
||||
() =>
|
||||
|
|
|
@ -29,8 +29,8 @@ jest.mock('../../lib/kibana', () => {
|
|||
useKibana: () => mockedUseKibana,
|
||||
};
|
||||
});
|
||||
jest.mock('@kbn/kibana-react-plugin/public', () => {
|
||||
const original = jest.requireActual('@kbn/kibana-react-plugin/public');
|
||||
jest.mock('@kbn/react-kibana-mount', () => {
|
||||
const original = jest.requireActual('@kbn/react-kibana-mount');
|
||||
|
||||
return {
|
||||
...original,
|
||||
|
|
|
@ -878,7 +878,7 @@ export interface ResolverPluginSetup {
|
|||
|
||||
/**
|
||||
* The Resolver component without the required Providers.
|
||||
* You must wrap this component in: `I18nProvider`, `Router` (from react-router,) `KibanaContextProvider`,
|
||||
* You must wrap this component in: `KibanaRenderContextProvider`, `Router` (from react-router,) `KibanaContextProvider`,
|
||||
* and the `Provider` component provided by this object.
|
||||
*/
|
||||
ResolverWithoutProviders: React.MemoExoticComponent<
|
||||
|
|
|
@ -94,8 +94,9 @@ export const AddToTimelineButtonEmpty: VFC<AddToTimelineProps> = ({
|
|||
|
||||
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const addToTimelineButton =
|
||||
useKibana().services.timelines.getHoverActions().getAddToTimelineButton;
|
||||
const { timelines, analytics, i18n: i18nStart, theme } = useKibana().services;
|
||||
const startServices = { analytics, i18n: i18nStart, theme };
|
||||
const addToTimelineButton = timelines.getHoverActions().getAddToTimelineButton;
|
||||
|
||||
const { key, value } =
|
||||
typeof data === 'string' ? { key: field, value: data } : getIndicatorFieldAndValue(data, field);
|
||||
|
@ -110,6 +111,7 @@ export const AddToTimelineButtonEmpty: VFC<AddToTimelineProps> = ({
|
|||
dataProvider,
|
||||
field: key,
|
||||
ownFocus: false,
|
||||
startServices,
|
||||
};
|
||||
|
||||
// Use case is for the barchart legend (for example).
|
||||
|
@ -153,8 +155,10 @@ export const AddToTimelineContextMenu: VFC<AddToTimelineProps> = ({
|
|||
|
||||
const contextMenuRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const addToTimelineButton =
|
||||
useKibana().services.timelines.getHoverActions().getAddToTimelineButton;
|
||||
const { timelines, analytics, i18n: i18nStart, theme } = useKibana().services;
|
||||
const startServices = { analytics, i18n: i18nStart, theme };
|
||||
|
||||
const addToTimelineButton = timelines.getHoverActions().getAddToTimelineButton;
|
||||
|
||||
const { key, value } =
|
||||
typeof data === 'string' ? { key: field, value: data } : getIndicatorFieldAndValue(data, field);
|
||||
|
@ -169,6 +173,7 @@ export const AddToTimelineContextMenu: VFC<AddToTimelineProps> = ({
|
|||
dataProvider,
|
||||
field: key,
|
||||
ownFocus: false,
|
||||
startServices,
|
||||
};
|
||||
|
||||
// Use case is for the barchart legend (for example).
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { DataProvider } from '@kbn/timelines-plugin/common';
|
||||
import { AddToTimelineButtonProps } from '@kbn/timelines-plugin/public';
|
||||
import { useKibana } from '../../../hooks/use_kibana';
|
||||
import { generateDataProvider } from '../utils/data_provider';
|
||||
import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../indicators/utils/field_value';
|
||||
import { Indicator } from '../../../../common/types/indicator';
|
||||
|
@ -38,6 +39,9 @@ export const useAddToTimeline = ({
|
|||
indicator,
|
||||
field,
|
||||
}: UseAddToTimelineParam): UseAddToTimelineValue => {
|
||||
const { analytics, i18n, theme } = useKibana().services;
|
||||
const startServices = { analytics, i18n, theme };
|
||||
|
||||
const { key, value } =
|
||||
typeof indicator === 'string'
|
||||
? { key: field, value: indicator }
|
||||
|
@ -53,6 +57,7 @@ export const useAddToTimeline = ({
|
|||
dataProvider,
|
||||
field: key,
|
||||
ownFocus: false,
|
||||
startServices,
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -56,7 +56,7 @@ export const createApp =
|
|||
|
||||
export class ThreatIntelligencePlugin implements Plugin<void, void> {
|
||||
public async setup(
|
||||
core: CoreSetup,
|
||||
_core: CoreSetup,
|
||||
plugins: SetupPlugins
|
||||
): Promise<ThreatIntelligencePluginSetup> {
|
||||
const externalAttachmentType: ExternalReferenceAttachmentType = generateAttachmentType();
|
||||
|
@ -73,11 +73,11 @@ export class ThreatIntelligencePlugin implements Plugin<void, void> {
|
|||
storage: new Storage(localStorage),
|
||||
};
|
||||
|
||||
const services = {
|
||||
const services: Services = {
|
||||
...localPluginServices,
|
||||
...core,
|
||||
...plugins,
|
||||
} as Services;
|
||||
};
|
||||
|
||||
return {
|
||||
getComponent: createApp(services),
|
||||
|
|
|
@ -45,18 +45,17 @@ export interface ThreatIntelligencePluginStart {
|
|||
|
||||
export interface ThreatIntelligencePluginStartDeps {
|
||||
data: DataPublicPluginStart;
|
||||
}
|
||||
|
||||
export type Services = {
|
||||
cases: CasesPublicStart;
|
||||
data: DataPublicPluginStart;
|
||||
storage: Storage;
|
||||
dataViews: DataViewsPublicPluginStart;
|
||||
triggersActionsUi: TriggersActionsStart;
|
||||
timelines: TimelinesUIStart;
|
||||
securityLayout: any;
|
||||
inspector: InspectorPluginStart;
|
||||
} & CoreStart;
|
||||
}
|
||||
|
||||
export interface Services extends CoreStart, ThreatIntelligencePluginStartDeps {
|
||||
storage: Storage;
|
||||
}
|
||||
|
||||
export interface LicenseAware {
|
||||
isEnterprise(): boolean;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { EuiButtonEmpty } from '@elastic/eui';
|
||||
import { act, fireEvent, render, screen } from '@testing-library/react';
|
||||
import { coreMock } from '@kbn/core/public/mocks';
|
||||
import React from 'react';
|
||||
|
||||
import AddToTimelineButton, {
|
||||
|
@ -18,6 +19,8 @@ import { DataProvider, IS_OPERATOR } from '../../../../common/types';
|
|||
import { TestProviders } from '../../../mock';
|
||||
import * as i18n from './translations';
|
||||
|
||||
const coreStart = coreMock.createStart();
|
||||
|
||||
const mockAddSuccess = jest.fn();
|
||||
jest.mock('../../../hooks/use_app_toasts', () => ({
|
||||
useAppToasts: () => ({
|
||||
|
@ -93,7 +96,7 @@ describe('add to timeline', () => {
|
|||
beforeEach(() => {
|
||||
render(
|
||||
<TestProviders>
|
||||
<AddToTimelineButton field={field} ownFocus={false} />
|
||||
<AddToTimelineButton field={field} ownFocus={false} startServices={coreStart} />
|
||||
</TestProviders>
|
||||
);
|
||||
});
|
||||
|
@ -111,7 +114,12 @@ describe('add to timeline', () => {
|
|||
beforeEach(() => {
|
||||
render(
|
||||
<TestProviders>
|
||||
<AddToTimelineButton Component={EuiButtonEmpty} field={field} ownFocus={false} />
|
||||
<AddToTimelineButton
|
||||
Component={EuiButtonEmpty}
|
||||
field={field}
|
||||
ownFocus={false}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
});
|
||||
|
@ -128,7 +136,12 @@ describe('add to timeline', () => {
|
|||
test('it renders a tooltip when `showTooltip` is true', () => {
|
||||
const { container } = render(
|
||||
<TestProviders>
|
||||
<AddToTimelineButton field={field} ownFocus={false} showTooltip={true} />
|
||||
<AddToTimelineButton
|
||||
field={field}
|
||||
ownFocus={false}
|
||||
showTooltip={true}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
@ -138,7 +151,7 @@ describe('add to timeline', () => {
|
|||
test('it does NOT render a tooltip when `showTooltip` is false (default)', () => {
|
||||
const { container } = render(
|
||||
<TestProviders>
|
||||
<AddToTimelineButton field={field} ownFocus={false} />
|
||||
<AddToTimelineButton field={field} ownFocus={false} startServices={coreStart} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
@ -151,7 +164,12 @@ describe('add to timeline', () => {
|
|||
test('it starts dragging to timeline when a `draggableId` is provided', () => {
|
||||
render(
|
||||
<TestProviders>
|
||||
<AddToTimelineButton draggableId={draggableId} field={field} ownFocus={false} />
|
||||
<AddToTimelineButton
|
||||
draggableId={draggableId}
|
||||
field={field}
|
||||
ownFocus={false}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
@ -163,7 +181,7 @@ describe('add to timeline', () => {
|
|||
test('it does NOT start dragging to timeline when a `draggableId` is NOT provided', () => {
|
||||
render(
|
||||
<TestProviders>
|
||||
<AddToTimelineButton field={field} ownFocus={false} />
|
||||
<AddToTimelineButton field={field} ownFocus={false} startServices={coreStart} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
@ -175,7 +193,12 @@ describe('add to timeline', () => {
|
|||
test('it dispatches a single `addProviderToTimeline` action when a single, non-array `dataProvider` is provided', () => {
|
||||
render(
|
||||
<TestProviders>
|
||||
<AddToTimelineButton dataProvider={providerA} field={field} ownFocus={false} />
|
||||
<AddToTimelineButton
|
||||
dataProvider={providerA}
|
||||
field={field}
|
||||
ownFocus={false}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
@ -209,6 +232,7 @@ describe('add to timeline', () => {
|
|||
dataProvider={[providerA, providerB]}
|
||||
field={field}
|
||||
ownFocus={false}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
@ -217,7 +241,7 @@ describe('add to timeline', () => {
|
|||
|
||||
expect(mockDispatch).toHaveBeenCalledTimes(2);
|
||||
|
||||
providers.forEach((p, i) =>
|
||||
providers.forEach((_p, i) =>
|
||||
expect(mockDispatch).toHaveBeenNthCalledWith(i + 1, {
|
||||
payload: {
|
||||
dataProvider: {
|
||||
|
@ -241,7 +265,12 @@ describe('add to timeline', () => {
|
|||
|
||||
render(
|
||||
<TestProviders>
|
||||
<AddToTimelineButton field={field} onClick={onClick} ownFocus={false} />
|
||||
<AddToTimelineButton
|
||||
field={field}
|
||||
onClick={onClick}
|
||||
ownFocus={false}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
@ -273,6 +302,7 @@ describe('add to timeline', () => {
|
|||
keyboardEvent={keyboardEvent}
|
||||
ownFocus={true}
|
||||
showTooltip={true}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
@ -290,6 +320,7 @@ describe('add to timeline', () => {
|
|||
keyboardEvent={keyboardEvent}
|
||||
ownFocus={true}
|
||||
showTooltip={true}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
@ -308,6 +339,7 @@ describe('add to timeline', () => {
|
|||
keyboardEvent={keyboardEvent}
|
||||
ownFocus={true}
|
||||
showTooltip={true}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
@ -338,6 +370,7 @@ describe('add to timeline', () => {
|
|||
keyboardEvent={keyboardEvent}
|
||||
ownFocus={true}
|
||||
showTooltip={true}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
@ -355,6 +388,7 @@ describe('add to timeline', () => {
|
|||
keyboardEvent={keyboardEvent}
|
||||
ownFocus={true}
|
||||
showTooltip={true}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
@ -373,6 +407,7 @@ describe('add to timeline', () => {
|
|||
keyboardEvent={keyboardEvent}
|
||||
ownFocus={true}
|
||||
showTooltip={true}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
@ -387,7 +422,12 @@ describe('add to timeline', () => {
|
|||
test('Add success is called with "timeline" if timeline type is timeline', () => {
|
||||
render(
|
||||
<TestProviders>
|
||||
<AddToTimelineButton dataProvider={providerA} field={field} ownFocus={false} />
|
||||
<AddToTimelineButton
|
||||
dataProvider={providerA}
|
||||
field={field}
|
||||
ownFocus={false}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
|
@ -408,6 +448,7 @@ describe('add to timeline', () => {
|
|||
field={field}
|
||||
ownFocus={false}
|
||||
timelineType={'template'}
|
||||
startServices={coreStart}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
|
|
|
@ -11,7 +11,8 @@ import { DraggableId } from '@hello-pangea/dnd';
|
|||
import { isEmpty } from 'lodash';
|
||||
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
import { toMountPoint } from '@kbn/react-kibana-mount';
|
||||
import { TimelinesStartServices } from '../../..';
|
||||
import { TimelineId } from '../../../store/timeline';
|
||||
import { addProviderToTimeline } from '../../../store/timeline/actions';
|
||||
import { stopPropagationAndPreventDefault } from '../../../../common/utils/accessibility';
|
||||
|
@ -63,6 +64,7 @@ export interface AddToTimelineButtonProps extends HoverActionComponentProps {
|
|||
draggableId?: DraggableId;
|
||||
dataProvider?: DataProvider[] | DataProvider;
|
||||
timelineType?: string;
|
||||
startServices: TimelinesStartServices;
|
||||
}
|
||||
|
||||
const AddToTimelineButton: React.FC<AddToTimelineButtonProps> = React.memo(
|
||||
|
@ -78,6 +80,7 @@ const AddToTimelineButton: React.FC<AddToTimelineButtonProps> = React.memo(
|
|||
showTooltip = false,
|
||||
value,
|
||||
timelineType = 'default',
|
||||
startServices,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const { addSuccess } = useAppToasts();
|
||||
|
@ -103,7 +106,8 @@ const AddToTimelineButton: React.FC<AddToTimelineButtonProps> = React.memo(
|
|||
provider.name,
|
||||
timelineType === 'default'
|
||||
)}
|
||||
</AddSuccessMessage>
|
||||
</AddSuccessMessage>,
|
||||
startServices
|
||||
),
|
||||
});
|
||||
}
|
||||
|
@ -121,6 +125,7 @@ const AddToTimelineButton: React.FC<AddToTimelineButtonProps> = React.memo(
|
|||
onClick,
|
||||
startDragToTimeline,
|
||||
timelineType,
|
||||
startServices,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
// first download since the other plugins/areas of your code can directly pull from the package in their async imports.
|
||||
// See: https://docs.elastic.dev/kibana-dev-docs/key-concepts/platform-intro#public-plugin-api
|
||||
|
||||
import type { CoreStart } from '@kbn/core/public';
|
||||
|
||||
import { TimelinesPlugin } from './plugin';
|
||||
|
||||
export type { TimelinesUIStart } from './types';
|
||||
|
@ -49,3 +51,5 @@ export function plugin() {
|
|||
}
|
||||
|
||||
export type { AddToTimelineButtonProps } from './components/hover_actions/actions/add_to_timeline';
|
||||
|
||||
export type TimelinesStartServices = Pick<CoreStart, 'analytics' | 'i18n' | 'theme'>;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types",
|
||||
"outDir": "target/types"
|
||||
},
|
||||
"include": [
|
||||
"common/**/*",
|
||||
|
@ -36,8 +36,9 @@
|
|||
"@kbn/logging",
|
||||
"@kbn/search-errors",
|
||||
"@kbn/search-types",
|
||||
"@kbn/react-kibana-mount"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
"target/**/*"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue