mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Cases] Export getRelatedCases API from cases client (#127065)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
74659aff4f
commit
60d5a993b6
41 changed files with 310 additions and 200 deletions
|
@ -18,7 +18,6 @@ This plugin provides cases management in Kibana
|
|||
- [Cases API](#cases-api)
|
||||
- [Cases Client API](#cases-client-api)
|
||||
- [Cases UI](#cases-ui)
|
||||
- [Case Action Type](#case-action-type) _feature in development, disabled by default_
|
||||
|
||||
## Cases API
|
||||
|
||||
|
@ -30,7 +29,7 @@ This plugin provides cases management in Kibana
|
|||
|
||||
## Cases UI
|
||||
|
||||
#### Embed Cases UI components in any Kibana plugin
|
||||
### Embed Cases UI components in any Kibana plugin
|
||||
|
||||
- Add `CasesUiStart` to Kibana plugin `StartServices` dependencies:
|
||||
|
||||
|
@ -38,7 +37,7 @@ This plugin provides cases management in Kibana
|
|||
cases: CasesUiStart;
|
||||
```
|
||||
|
||||
#### CasesContext setup
|
||||
### CasesContext setup
|
||||
|
||||
To use any of the Cases UI hooks you must first initialize `CasesContext` in your plugin.
|
||||
|
||||
|
@ -64,14 +63,25 @@ To initialize the `CasesContext` you can use this code:
|
|||
props:
|
||||
|
||||
| prop | type | description |
|
||||
|-----------------------|-----------------|----------------------------------------------------------------|
|
||||
| --------------------- | --------------- | -------------------------------------------------------------- |
|
||||
| PLUGIN_CASES_OWNER_ID | `string` | The owner string for your plugin. e.g: securitySolution |
|
||||
| CASES_USER_CAN_CRUD | `boolean` | Defines if the user has access to cases to CRUD |
|
||||
| CASES_FEATURES | `CasesFeatures` | `CasesFeatures` object defining the features to enable/disable |
|
||||
|
||||
#### Cases UI Methods
|
||||
|
||||
- From the UI component, get the component from the `useKibana` hook start services
|
||||
### Cases UI client
|
||||
|
||||
The cases UI client exports the following contract:
|
||||
|
||||
| Property | Description | Type |
|
||||
| -------- | -------------------------------- | ------ |
|
||||
| api | Methods related to the Cases API | object |
|
||||
| ui | Cases UI components | object |
|
||||
| hooks | Cases React hooks | object |
|
||||
| helpers | Cases helpers | object |
|
||||
|
||||
|
||||
You can get the cases UI client from the `useKibana` hook start services. Example:
|
||||
|
||||
```tsx
|
||||
const { cases } = useKibana().services;
|
||||
|
@ -94,55 +104,76 @@ cases.getCases({
|
|||
});
|
||||
```
|
||||
|
||||
##### Methods:
|
||||
### api
|
||||
|
||||
### `getCases`
|
||||
#### `getRelatedCases`
|
||||
|
||||
Returns all cases where the alert is attached to.
|
||||
|
||||
Arguments
|
||||
|
||||
| Property | Description | Type |
|
||||
| -------- | ------------ | ------ |
|
||||
| alertId | The alert ID | string |
|
||||
|
||||
Response
|
||||
|
||||
An array of:
|
||||
|
||||
| Property | Description | Type |
|
||||
| -------- | --------------------- | ------ |
|
||||
| id | The ID of the case | string |
|
||||
| title | The title of the case | string |
|
||||
|
||||
### ui
|
||||
|
||||
#### `getCases`
|
||||
|
||||
Arguments:
|
||||
|
||||
| Property | Description |
|
||||
| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| userCanCrud | `boolean;` user permissions to crud |
|
||||
| owner | `string[];` owner ids of the cases |
|
||||
| basePath | `string;` path to mount the Cases router on top of |
|
||||
| useFetchAlertData | `(alertIds: string[]) => [boolean, Record<string, unknown>];` fetch alerts |
|
||||
| disableAlerts? | `boolean` (default: false) flag to not show alerts information |
|
||||
| actionsNavigation? | <code>CasesNavigation<string, 'configurable'></code> |
|
||||
| ruleDetailsNavigation? | <code>CasesNavigation<string | null | undefined, 'configurable'></code> |
|
||||
| onComponentInitialized? | `() => void;` callback when component has initialized |
|
||||
| showAlertDetails? | `(alertId: string, index: string) => void;` callback to show alert details |
|
||||
| features? | `CasesFeatures` object defining the features to enable/disable |
|
||||
| features?.alerts.sync | `boolean` (default: `true`) defines wether the alert sync action should be enabled/disabled |
|
||||
| Property | Description |
|
||||
| -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| userCanCrud | `boolean;` user permissions to crud |
|
||||
| owner | `string[];` owner ids of the cases |
|
||||
| basePath | `string;` path to mount the Cases router on top of |
|
||||
| useFetchAlertData | `(alertIds: string[]) => [boolean, Record<string, unknown>];` fetch alerts |
|
||||
| disableAlerts? | `boolean` (default: false) flag to not show alerts information |
|
||||
| actionsNavigation? | <code>CasesNavigation<string, 'configurable'></code> |
|
||||
| ruleDetailsNavigation? | <code>CasesNavigation<string | null | undefined, 'configurable'></code> |
|
||||
| onComponentInitialized? | `() => void;` callback when component has initialized |
|
||||
| showAlertDetails? | `(alertId: string, index: string) => void;` callback to show alert details |
|
||||
| features? | `CasesFeatures` object defining the features to enable/disable |
|
||||
| features?.alerts.sync | `boolean` (default: `true`) defines wether the alert sync action should be enabled/disabled |
|
||||
| features?.metrics | `string[]` (default: `[]`) defines the metrics to show in the Case Detail View. Allowed metrics: "alerts.count", "alerts.users", "alerts.hosts", "connectors", "lifespan". |
|
||||
| timelineIntegration?.editor_plugins | Plugins needed for integrating timeline into markdown editor. |
|
||||
| timelineIntegration?.editor_plugins.parsingPlugin | `Plugin;` |
|
||||
| timelineIntegration?.editor_plugins.processingPluginRenderer | `React.FC<TimelineProcessingPluginRendererProps & { position: EuiMarkdownAstNodePosition }>` |
|
||||
| timelineIntegration?.editor_plugins.uiPlugin? | `EuiMarkdownEditorUiPlugin` |
|
||||
| timelineIntegration?.hooks.useInsertTimeline | `(value: string, onChange: (newValue: string) => void): UseInsertTimelineReturn` |
|
||||
| timelineIntegration?.ui?.renderInvestigateInTimelineActionComponent? | `(alertIds: string[]) => JSX.Element;` space to render `InvestigateInTimelineActionComponent` |
|
||||
| timelineIntegration?.ui?renderTimelineDetailsPanel? | `() => JSX.Element;` space to render `TimelineDetailsPanel` |
|
||||
| timelineIntegration?.editor_plugins | Plugins needed for integrating timeline into markdown editor. |
|
||||
| timelineIntegration?.editor_plugins.parsingPlugin | `Plugin;` |
|
||||
| timelineIntegration?.editor_plugins.processingPluginRenderer | `React.FC<TimelineProcessingPluginRendererProps & { position: EuiMarkdownAstNodePosition }>` |
|
||||
| timelineIntegration?.editor_plugins.uiPlugin? | `EuiMarkdownEditorUiPlugin` |
|
||||
| timelineIntegration?.hooks.useInsertTimeline | `(value: string, onChange: (newValue: string) => void): UseInsertTimelineReturn` |
|
||||
| timelineIntegration?.ui?.renderInvestigateInTimelineActionComponent? | `(alertIds: string[]) => JSX.Element;` space to render `InvestigateInTimelineActionComponent` |
|
||||
| timelineIntegration?.ui?renderTimelineDetailsPanel? | `() => JSX.Element;` space to render `TimelineDetailsPanel` |
|
||||
|
||||
UI component:
|
||||
![All Cases Component][all-cases-img]
|
||||
|
||||
### `getAllCasesSelectorModal`
|
||||
#### `getAllCasesSelectorModal`
|
||||
|
||||
Arguments:
|
||||
|
||||
| Property | Description |
|
||||
| --------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| userCanCrud | `boolean;` user permissions to crud |
|
||||
| owner | `string[];` owner ids of the cases |
|
||||
| alertData? | `Omit<CommentRequestAlertType, 'type'>;` alert data to post to case |
|
||||
| hiddenStatuses? | `CaseStatuses[];` array of hidden statuses |
|
||||
| Property | Description |
|
||||
| --------------- | ---------------------------------------------------------------------------------- |
|
||||
| userCanCrud | `boolean;` user permissions to crud |
|
||||
| owner | `string[];` owner ids of the cases |
|
||||
| alertData? | `Omit<CommentRequestAlertType, 'type'>;` alert data to post to case |
|
||||
| hiddenStatuses? | `CaseStatuses[];` array of hidden statuses |
|
||||
| onRowClick | <code>(theCase?: Case) => void;</code> callback for row click, passing case in row |
|
||||
| updateCase? | <code>(theCase: Case) => void;</code> callback after case has been updated |
|
||||
| onClose? | `() => void` called when the modal is closed without selecting a case |
|
||||
| onClose? | `() => void` called when the modal is closed without selecting a case |
|
||||
|
||||
UI component:
|
||||
![All Cases Selector Modal Component][all-cases-modal-img]
|
||||
|
||||
### `getCreateCaseFlyout`
|
||||
#### `getCreateCaseFlyout`
|
||||
|
||||
Arguments:
|
||||
|
||||
|
@ -158,7 +189,7 @@ Arguments:
|
|||
UI component:
|
||||
![Create Component][create-img]
|
||||
|
||||
### `getRecentCases`
|
||||
#### `getRecentCases`
|
||||
|
||||
Arguments:
|
||||
|
||||
|
@ -203,31 +234,40 @@ You can use this hook to prompt the user to select a case and get the selected c
|
|||
|
||||
Arguments:
|
||||
|
||||
| Property | Description |
|
||||
| --------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| onRowClick | <code>(theCase?: Case) => void;</code> callback for row click, passing case in row |
|
||||
| updateCase? | <code>(theCase: Case) => void;</code> callback after case has been updated |
|
||||
| onClose? | `() => void` called when the modal is closed without selecting a case |
|
||||
| attachments? | `CaseAttachments`; array of `SupportedCaseAttachment` (see types) that will be attached to the newly created case |
|
||||
| Property | Description |
|
||||
| ------------ | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| onRowClick | <code>(theCase?: Case) => void;</code> callback for row click, passing case in row |
|
||||
| updateCase? | <code>(theCase: Case) => void;</code> callback after case has been updated |
|
||||
| onClose? | `() => void` called when the modal is closed without selecting a case |
|
||||
| attachments? | `CaseAttachments`; array of `SupportedCaseAttachment` (see types) that will be attached to the newly created case |
|
||||
|
||||
### helpers
|
||||
|
||||
#### canUseCases
|
||||
|
||||
Returns the Cases capabilities for the current user. Specifically:
|
||||
|
||||
| Property | Description | Type |
|
||||
| -------- | -------------------------------------------- | ------- |
|
||||
| crud | Denotes if the user has all access to Cases | boolean |
|
||||
| read? | Denotes if the user has read access to Cases | boolean |
|
||||
|
||||
#### getRuleIdFromEvent
|
||||
|
||||
Returns an object with a rule `id` and `name` of the event passed. This helper method is necessary to bridge the gap between previous events schema and new ones.
|
||||
|
||||
Arguments:
|
||||
|
||||
| property | description |
|
||||
|----------|----------------------------------------------------------------------------------------------|
|
||||
| event | Event containing an `ecs` attribute with ecs data and a `data` attribute with `nonEcs` data. |
|
||||
| property | Description | Type |
|
||||
| -------- | -------------------------------------------------------------------------------------------- | ------ |
|
||||
| event | Event containing an `ecs` attribute with ecs data and a `data` attribute with `nonEcs` data. | object |
|
||||
|
||||
<!-- MARKDOWN LINKS & IMAGES -->
|
||||
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
|
||||
|
||||
[pr-shield]: https://img.shields.io/github/issues-pr/elastic/kibana/Team:Threat%20Hunting:Cases?label=pull%20requests&style=for-the-badge
|
||||
[pr-url]: https://github.com/elastic/kibana/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc+label%3A%22Team%3AThreat+Hunting%3ACases%22
|
||||
[issues-shield]: https://img.shields.io/github/issues-search?label=issue&query=repo%3Aelastic%2Fkibana%20is%3Aissue%20is%3Aopen%20label%3A%22Team%3AThreat%20Hunting%3ACases%22&style=for-the-badge
|
||||
[pr-shield]: https://img.shields.io/github/issues-pr/elastic/kibana/Feature:Cases?label=pull%20requests&style=for-the-badge
|
||||
[pr-url]: https://github.com/elastic/kibana/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc+label%3A%22Feature%3ACases%22
|
||||
[issues-shield]: https://img.shields.io/github/issues-search?label=issue&query=repo%3Aelastic%2Fkibana%20is%3Aissue%20is%3Aopen%20label%3A%22Feature%3ACases%22&style=for-the-badge
|
||||
[issues-url]: https://github.com/elastic/kibana/issues?q=is%3Aopen+is%3Aissue+label%3AFeature%3ACases
|
||||
[cases-logo]: images/logo.png
|
||||
[configure-img]: images/configure.png
|
||||
|
|
37
x-pack/plugins/cases/public/client/api/index.test.ts
Normal file
37
x-pack/plugins/cases/public/client/api/index.test.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { httpServiceMock } from '../../../../../../src/core/public/mocks';
|
||||
import { createClientAPI } from '.';
|
||||
|
||||
describe('createClientAPI', () => {
|
||||
const http = httpServiceMock.createStartContract({ basePath: '' });
|
||||
const api = createClientAPI({ http });
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('getRelatedCases', () => {
|
||||
const res = [
|
||||
{
|
||||
id: 'test-id',
|
||||
title: 'test',
|
||||
},
|
||||
];
|
||||
http.get.mockResolvedValue(res);
|
||||
|
||||
it('should return the correct response', async () => {
|
||||
expect(await api.getRelatedCases('alert-id')).toEqual(res);
|
||||
});
|
||||
|
||||
it('should have been called with the correct path', async () => {
|
||||
await api.getRelatedCases('alert-id');
|
||||
expect(http.get).toHaveBeenCalledWith('/api/cases/alerts/alert-id');
|
||||
});
|
||||
});
|
||||
});
|
16
x-pack/plugins/cases/public/client/api/index.ts
Normal file
16
x-pack/plugins/cases/public/client/api/index.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { HttpStart } from 'kibana/public';
|
||||
import { CasesByAlertId, getCasesFromAlertsUrl } from '../../../common/api';
|
||||
|
||||
export const createClientAPI = ({ http }: { http: HttpStart }) => {
|
||||
return {
|
||||
getRelatedCases: async (alertId: string): Promise<CasesByAlertId> =>
|
||||
http.get<CasesByAlertId>(getCasesFromAlertsUrl(alertId)),
|
||||
};
|
||||
};
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import type { ApplicationStart } from 'kibana/public';
|
||||
import { OBSERVABILITY_OWNER, SECURITY_SOLUTION_OWNER } from '../../common/constants';
|
||||
import { OBSERVABILITY_OWNER, SECURITY_SOLUTION_OWNER } from '../../../common/constants';
|
||||
|
||||
export type CasesOwners = typeof SECURITY_SOLUTION_OWNER | typeof OBSERVABILITY_OWNER;
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils';
|
||||
import { get } from 'lodash/fp';
|
||||
import { Ecs } from '../../common';
|
||||
import { Ecs } from '../../../common';
|
||||
|
||||
type Maybe<T> = T | null;
|
||||
interface Event {
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import { EuiLoadingSpinner } from '@elastic/eui';
|
||||
import { AllCasesSelectorModalProps } from '../components/all_cases/selector_modal';
|
||||
import { CasesProvider, CasesContextProps } from '../components/cases_context';
|
||||
import { AllCasesSelectorModalProps } from '../../components/all_cases/selector_modal';
|
||||
import { CasesProvider, CasesContextProps } from '../../components/cases_context';
|
||||
|
||||
export type GetAllCasesSelectorModalProps = AllCasesSelectorModalProps & CasesContextProps;
|
||||
|
||||
const AllCasesSelectorModalLazy: React.FC<AllCasesSelectorModalProps> = lazy(
|
||||
() => import('../components/all_cases/selector_modal')
|
||||
() => import('../../components/all_cases/selector_modal')
|
||||
);
|
||||
export const getAllCasesSelectorModalLazy = ({
|
||||
owner,
|
|
@ -7,12 +7,12 @@
|
|||
|
||||
import { EuiLoadingSpinner } from '@elastic/eui';
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import type { CasesProps } from '../components/app';
|
||||
import { CasesProvider, CasesContextProps } from '../components/cases_context';
|
||||
import type { CasesProps } from '../../components/app';
|
||||
import { CasesProvider, CasesContextProps } from '../../components/cases_context';
|
||||
|
||||
export type GetCasesProps = CasesProps & CasesContextProps;
|
||||
|
||||
const CasesRoutesLazy: React.FC<CasesProps> = lazy(() => import('../components/app/routes'));
|
||||
const CasesRoutesLazy: React.FC<CasesProps> = lazy(() => import('../../components/app/routes'));
|
||||
|
||||
export const getCasesLazy = ({
|
||||
owner,
|
|
@ -7,12 +7,12 @@
|
|||
|
||||
import { EuiLoadingSpinner } from '@elastic/eui';
|
||||
import React, { lazy, ReactNode, Suspense } from 'react';
|
||||
import { CasesContextProps } from '../components/cases_context';
|
||||
import { CasesContextProps } from '../../components/cases_context';
|
||||
|
||||
export type GetCasesContextProps = CasesContextProps;
|
||||
|
||||
const CasesProviderLazy: React.FC<{ value: GetCasesContextProps }> = lazy(
|
||||
() => import('../components/cases_context')
|
||||
() => import('../../components/cases_context')
|
||||
);
|
||||
|
||||
const CasesProviderLazyWrapper = ({
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import { EuiLoadingSpinner } from '@elastic/eui';
|
||||
import type { CreateCaseFlyoutProps } from '../components/create/flyout';
|
||||
import { CasesProvider, CasesContextProps } from '../components/cases_context';
|
||||
import type { CreateCaseFlyoutProps } from '../../components/create/flyout';
|
||||
import { CasesProvider, CasesContextProps } from '../../components/cases_context';
|
||||
|
||||
export type GetCreateCaseFlyoutProps = CreateCaseFlyoutProps & CasesContextProps;
|
||||
|
||||
export const CreateCaseFlyoutLazy: React.FC<CreateCaseFlyoutProps> = lazy(
|
||||
() => import('../components/create/flyout')
|
||||
() => import('../../components/create/flyout')
|
||||
);
|
||||
export const getCreateCaseFlyoutLazy = ({
|
||||
owner,
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
import { EuiLoadingSpinner } from '@elastic/eui';
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import { CasesProvider, CasesContextProps } from '../components/cases_context';
|
||||
import { RecentCasesProps } from '../components/recent_cases';
|
||||
import { CasesProvider, CasesContextProps } from '../../components/cases_context';
|
||||
import { RecentCasesProps } from '../../components/recent_cases';
|
||||
|
||||
export type GetRecentCasesProps = RecentCasesProps & CasesContextProps;
|
||||
|
||||
const RecentCasesLazy: React.FC<RecentCasesProps> = lazy(
|
||||
() => import('../components/recent_cases')
|
||||
() => import('../../components/recent_cases')
|
||||
);
|
||||
export const getRecentCasesLazy = ({ owner, userCanCrud, maxCasesToShow }: GetRecentCasesProps) => (
|
||||
<CasesProvider value={{ owner, userCanCrud }}>
|
|
@ -39,8 +39,8 @@ import { StatusContextMenu } from '../case_action_bar/status_context_menu';
|
|||
import { TruncatedText } from '../truncated_text';
|
||||
import { getConnectorIcon } from '../utils';
|
||||
import { PostComment } from '../../containers/use_post_comment';
|
||||
import type { CasesOwners } from '../../methods/can_use_cases';
|
||||
import { CaseAttachments } from '../../types';
|
||||
import type { CasesOwners } from '../../client/helpers/can_use_cases';
|
||||
|
||||
export type CasesColumns =
|
||||
| EuiTableActionsColumnType<Case>
|
||||
|
|
|
@ -13,7 +13,6 @@ import { TestProviders } from '../../../common/mock';
|
|||
import { AllCasesList } from '../all_cases_list';
|
||||
import { SECURITY_SOLUTION_OWNER } from '../../../../common/constants';
|
||||
|
||||
jest.mock('../../../methods');
|
||||
jest.mock('../all_cases_list');
|
||||
|
||||
const onRowClick = jest.fn();
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
import React from 'react';
|
||||
import { APP_OWNER } from '../../../common/constants';
|
||||
import { getCasesLazy } from '../../client/ui/get_cases';
|
||||
import { useApplicationCapabilities } from '../../common/lib/kibana';
|
||||
|
||||
import { getCasesLazy } from '../../methods';
|
||||
import { Wrapper } from '../wrappers';
|
||||
import { CasesRoutesProps } from './types';
|
||||
|
||||
|
|
|
@ -6,15 +6,14 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { getAllCasesSelectorModalNoProviderLazy } from '../../client/ui/get_all_cases_selector_modal';
|
||||
import { getCreateCaseFlyoutLazyNoProvider } from '../../client/ui/get_create_case_flyout';
|
||||
import { AppMockRenderer, createAppMockRenderer } from '../../common/mock';
|
||||
import {
|
||||
getAllCasesSelectorModalNoProviderLazy,
|
||||
getCreateCaseFlyoutLazyNoProvider,
|
||||
} from '../../methods';
|
||||
import { getInitialCasesContextState } from './cases_context_reducer';
|
||||
import { CasesGlobalComponents } from './cases_global_components';
|
||||
|
||||
jest.mock('../../methods');
|
||||
jest.mock('../../client/ui/get_create_case_flyout');
|
||||
jest.mock('../../client/ui/get_all_cases_selector_modal');
|
||||
|
||||
const getCreateCaseFlyoutLazyNoProviderMock = getCreateCaseFlyoutLazyNoProvider as jest.Mock;
|
||||
const getAllCasesSelectorModalNoProviderLazyMock =
|
||||
|
|
|
@ -6,10 +6,8 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
getAllCasesSelectorModalNoProviderLazy,
|
||||
getCreateCaseFlyoutLazyNoProvider,
|
||||
} from '../../methods';
|
||||
import { getAllCasesSelectorModalNoProviderLazy } from '../../client/ui/get_all_cases_selector_modal';
|
||||
import { getCreateCaseFlyoutLazyNoProvider } from '../../client/ui/get_create_case_flyout';
|
||||
import { CasesContextState } from './cases_context_reducer';
|
||||
|
||||
export const CasesGlobalComponents = React.memo(({ state }: { state: CasesContextState }) => {
|
||||
|
|
|
@ -16,10 +16,10 @@ export { DRAFT_COMMENT_STORAGE_ID } from './components/markdown_editor/plugins/l
|
|||
|
||||
export type { CasesUiPlugin };
|
||||
export type { CasesUiStart } from './types';
|
||||
export type { GetCasesProps } from './methods/get_cases';
|
||||
export type { GetCreateCaseFlyoutProps } from './methods/get_create_case_flyout';
|
||||
export type { GetAllCasesSelectorModalProps } from './methods/get_all_cases_selector_modal';
|
||||
export type { GetRecentCasesProps } from './methods/get_recent_cases';
|
||||
export type { GetCasesProps } from './client/ui/get_cases';
|
||||
export type { GetCreateCaseFlyoutProps } from './client/ui/get_create_case_flyout';
|
||||
export type { GetAllCasesSelectorModalProps } from './client/ui/get_all_cases_selector_modal';
|
||||
export type { GetRecentCasesProps } from './client/ui/get_recent_cases';
|
||||
|
||||
export type { CaseAttachments, SupportedCaseAttachment } from './types';
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export * from './can_use_cases';
|
||||
export * from './get_cases';
|
||||
export * from './get_recent_cases';
|
||||
export * from './get_all_cases_selector_modal';
|
||||
export * from './get_create_case_flyout';
|
|
@ -8,20 +8,40 @@
|
|||
import { mockCasesContext } from './mocks/mock_cases_context';
|
||||
import { CasesUiStart } from './types';
|
||||
|
||||
export const mockCasesContract = (): jest.Mocked<CasesUiStart> => ({
|
||||
canUseCases: jest.fn(),
|
||||
const apiMock: jest.Mocked<CasesUiStart['api']> = {
|
||||
getRelatedCases: jest.fn(),
|
||||
};
|
||||
|
||||
const uiMock: jest.Mocked<CasesUiStart['ui']> = {
|
||||
getCases: jest.fn(),
|
||||
getCasesContext: jest.fn().mockImplementation(() => mockCasesContext),
|
||||
getAllCasesSelectorModal: jest.fn(),
|
||||
getCreateCaseFlyout: jest.fn(),
|
||||
getRecentCases: jest.fn(),
|
||||
hooks: {
|
||||
getUseCasesAddToNewCaseFlyout: jest.fn(),
|
||||
getUseCasesAddToExistingCaseModal: jest.fn(),
|
||||
},
|
||||
helpers: {
|
||||
getRuleIdFromEvent: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
const hooksMock: jest.Mocked<CasesUiStart['hooks']> = {
|
||||
getUseCasesAddToNewCaseFlyout: jest.fn(),
|
||||
getUseCasesAddToExistingCaseModal: jest.fn(),
|
||||
};
|
||||
|
||||
const helpersMock: jest.Mocked<CasesUiStart['helpers']> = {
|
||||
canUseCases: jest.fn(),
|
||||
getRuleIdFromEvent: jest.fn(),
|
||||
};
|
||||
|
||||
export interface CaseUiClientMock {
|
||||
api: jest.Mocked<CasesUiStart['api']>;
|
||||
ui: jest.Mocked<CasesUiStart['ui']>;
|
||||
hooks: jest.Mocked<CasesUiStart['hooks']>;
|
||||
helpers: jest.Mocked<CasesUiStart['helpers']>;
|
||||
}
|
||||
|
||||
export const mockCasesContract = (): CaseUiClientMock => ({
|
||||
api: apiMock,
|
||||
ui: uiMock,
|
||||
hooks: hooksMock,
|
||||
helpers: helpersMock,
|
||||
});
|
||||
|
||||
export const casesPluginMock = {
|
||||
|
|
|
@ -8,23 +8,22 @@
|
|||
import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'src/core/public';
|
||||
import { CasesUiStart, CasesPluginSetup, CasesPluginStart } from './types';
|
||||
import { KibanaServices } from './common/lib/kibana';
|
||||
import {
|
||||
getCasesLazy,
|
||||
getRecentCasesLazy,
|
||||
getAllCasesSelectorModalLazy,
|
||||
getCreateCaseFlyoutLazy,
|
||||
canUseCases,
|
||||
} from './methods';
|
||||
import { CasesUiConfigType } from '../common/ui/types';
|
||||
import { APP_ID, APP_PATH } from '../common/constants';
|
||||
import { APP_TITLE, APP_DESC } from './common/translations';
|
||||
import { FeatureCatalogueCategory } from '../../../../src/plugins/home/public';
|
||||
import { ManagementAppMountParams } from '../../../../src/plugins/management/public';
|
||||
import { Storage } from '../../../../src/plugins/kibana_utils/public';
|
||||
import { getCasesContextLazy } from './methods/get_cases_context';
|
||||
import { useCasesAddToExistingCaseModal } from './components/all_cases/selector_modal/use_cases_add_to_existing_case_modal';
|
||||
import { useCasesAddToNewCaseFlyout } from './components/create/flyout/use_cases_add_to_new_case_flyout';
|
||||
import { getRuleIdFromEvent } from './methods/get_rule_id_from_event';
|
||||
import { createClientAPI } from './client/api';
|
||||
import { canUseCases } from './client/helpers/can_use_cases';
|
||||
import { getRuleIdFromEvent } from './client/helpers/get_rule_id_from_event';
|
||||
import { getAllCasesSelectorModalLazy } from './client/ui/get_all_cases_selector_modal';
|
||||
import { getCasesLazy } from './client/ui/get_cases';
|
||||
import { getCasesContextLazy } from './client/ui/get_cases_context';
|
||||
import { getCreateCaseFlyoutLazy } from './client/ui/get_create_case_flyout';
|
||||
import { getRecentCasesLazy } from './client/ui/get_recent_cases';
|
||||
|
||||
/**
|
||||
* @public
|
||||
|
@ -87,19 +86,22 @@ export class CasesUiPlugin
|
|||
const config = this.initializerContext.config.get<CasesUiConfigType>();
|
||||
KibanaServices.init({ ...core, ...plugins, kibanaVersion: this.kibanaVersion, config });
|
||||
return {
|
||||
canUseCases: canUseCases(core.application.capabilities),
|
||||
getCases: getCasesLazy,
|
||||
getCasesContext: getCasesContextLazy,
|
||||
getRecentCases: getRecentCasesLazy,
|
||||
// @deprecated Please use the hook getUseCasesAddToNewCaseFlyout
|
||||
getCreateCaseFlyout: getCreateCaseFlyoutLazy,
|
||||
// @deprecated Please use the hook getUseCasesAddToExistingCaseModal
|
||||
getAllCasesSelectorModal: getAllCasesSelectorModalLazy,
|
||||
api: createClientAPI({ http: core.http }),
|
||||
ui: {
|
||||
getCases: getCasesLazy,
|
||||
getCasesContext: getCasesContextLazy,
|
||||
getRecentCases: getRecentCasesLazy,
|
||||
// @deprecated Please use the hook getUseCasesAddToNewCaseFlyout
|
||||
getCreateCaseFlyout: getCreateCaseFlyoutLazy,
|
||||
// @deprecated Please use the hook getUseCasesAddToExistingCaseModal
|
||||
getAllCasesSelectorModal: getAllCasesSelectorModalLazy,
|
||||
},
|
||||
hooks: {
|
||||
getUseCasesAddToNewCaseFlyout: useCasesAddToNewCaseFlyout,
|
||||
getUseCasesAddToExistingCaseModal: useCasesAddToExistingCaseModal,
|
||||
},
|
||||
helpers: {
|
||||
canUseCases: canUseCases(core.application.capabilities),
|
||||
getRuleIdFromEvent,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -20,19 +20,16 @@ import type { LensPublicStart } from '../../lens/public';
|
|||
import type { SecurityPluginSetup } from '../../security/public';
|
||||
import type { SpacesPluginStart } from '../../spaces/public';
|
||||
import type { TriggersAndActionsUIPublicPluginStart as TriggersActionsStart } from '../../triggers_actions_ui/public';
|
||||
import { CommentRequestAlertType, CommentRequestUserType } from '../common/api';
|
||||
import { CasesByAlertId, CommentRequestAlertType, CommentRequestUserType } from '../common/api';
|
||||
import { UseCasesAddToExistingCaseModal } from './components/all_cases/selector_modal/use_cases_add_to_existing_case_modal';
|
||||
import { UseCasesAddToNewCaseFlyout } from './components/create/flyout/use_cases_add_to_new_case_flyout';
|
||||
|
||||
import type {
|
||||
CasesOwners,
|
||||
GetAllCasesSelectorModalProps,
|
||||
GetCasesProps,
|
||||
GetCreateCaseFlyoutProps,
|
||||
GetRecentCasesProps,
|
||||
} from './methods';
|
||||
import { GetCasesContextProps } from './methods/get_cases_context';
|
||||
import { getRuleIdFromEvent } from './methods/get_rule_id_from_event';
|
||||
import type { CasesOwners } from './client/helpers/can_use_cases';
|
||||
import { getRuleIdFromEvent } from './client/helpers/get_rule_id_from_event';
|
||||
import type { GetCasesContextProps } from './client/ui/get_cases_context';
|
||||
import type { GetCasesProps } from './client/ui/get_cases';
|
||||
import { GetAllCasesSelectorModalProps } from './client/ui/get_all_cases_selector_modal';
|
||||
import { GetCreateCaseFlyoutProps } from './client/ui/get_create_case_flyout';
|
||||
import { GetRecentCasesProps } from './client/ui/get_recent_cases';
|
||||
|
||||
export interface CasesPluginSetup {
|
||||
security: SecurityPluginSetup;
|
||||
|
@ -70,49 +67,56 @@ export interface RenderAppProps {
|
|||
}
|
||||
|
||||
export interface CasesUiStart {
|
||||
/**
|
||||
* Returns an object denoting the current user's ability to read and crud cases.
|
||||
* If any owner(securitySolution, Observability) is found with crud or read capability respectively,
|
||||
* then crud or read is set to true.
|
||||
* Permissions for specific owners can be found by passing an owner array
|
||||
* @param owners an array of CaseOwners that should be queried for permission
|
||||
* @returns An object denoting the case permissions of the current user
|
||||
*/
|
||||
canUseCases: (owners?: CasesOwners[]) => { crud: boolean; read: boolean };
|
||||
/**
|
||||
* Get cases
|
||||
* @param props GetCasesProps
|
||||
* @return {ReactElement<GetCasesProps>}
|
||||
*/
|
||||
getCases: (props: GetCasesProps) => ReactElement<GetCasesProps>;
|
||||
getCasesContext: () => (
|
||||
props: GetCasesContextProps & { children: ReactNode }
|
||||
) => ReactElement<GetCasesContextProps>;
|
||||
/**
|
||||
* Modal to select a case in a list of all owner cases
|
||||
* @param props GetAllCasesSelectorModalProps
|
||||
* @returns A react component that is a modal for selecting a case
|
||||
*/
|
||||
getAllCasesSelectorModal: (
|
||||
props: GetAllCasesSelectorModalProps
|
||||
) => ReactElement<GetAllCasesSelectorModalProps>;
|
||||
/**
|
||||
* Flyout with the form to create a case for the owner
|
||||
* @param props GetCreateCaseFlyoutProps
|
||||
* @returns A react component that is a flyout for creating a case
|
||||
*/
|
||||
getCreateCaseFlyout: (props: GetCreateCaseFlyoutProps) => ReactElement<GetCreateCaseFlyoutProps>;
|
||||
/**
|
||||
* Get the recent cases component
|
||||
* @param props GetRecentCasesProps
|
||||
* @returns A react component for showing recent cases
|
||||
*/
|
||||
getRecentCases: (props: GetRecentCasesProps) => ReactElement<GetRecentCasesProps>;
|
||||
api: {
|
||||
getRelatedCases: (alertId: string) => Promise<CasesByAlertId>;
|
||||
};
|
||||
ui: {
|
||||
/**
|
||||
* Get cases
|
||||
* @param props GetCasesProps
|
||||
* @return {ReactElement<GetCasesProps>}
|
||||
*/
|
||||
getCases: (props: GetCasesProps) => ReactElement<GetCasesProps>;
|
||||
getCasesContext: () => (
|
||||
props: GetCasesContextProps & { children: ReactNode }
|
||||
) => ReactElement<GetCasesContextProps>;
|
||||
/**
|
||||
* Modal to select a case in a list of all owner cases
|
||||
* @param props GetAllCasesSelectorModalProps
|
||||
* @returns A react component that is a modal for selecting a case
|
||||
*/
|
||||
getAllCasesSelectorModal: (
|
||||
props: GetAllCasesSelectorModalProps
|
||||
) => ReactElement<GetAllCasesSelectorModalProps>;
|
||||
/**
|
||||
* Flyout with the form to create a case for the owner
|
||||
* @param props GetCreateCaseFlyoutProps
|
||||
* @returns A react component that is a flyout for creating a case
|
||||
*/
|
||||
getCreateCaseFlyout: (
|
||||
props: GetCreateCaseFlyoutProps
|
||||
) => ReactElement<GetCreateCaseFlyoutProps>;
|
||||
/**
|
||||
* Get the recent cases component
|
||||
* @param props GetRecentCasesProps
|
||||
* @returns A react component for showing recent cases
|
||||
*/
|
||||
getRecentCases: (props: GetRecentCasesProps) => ReactElement<GetRecentCasesProps>;
|
||||
};
|
||||
hooks: {
|
||||
getUseCasesAddToNewCaseFlyout: UseCasesAddToNewCaseFlyout;
|
||||
getUseCasesAddToExistingCaseModal: UseCasesAddToExistingCaseModal;
|
||||
};
|
||||
helpers: {
|
||||
/**
|
||||
* Returns an object denoting the current user's ability to read and crud cases.
|
||||
* If any owner(securitySolution, Observability) is found with crud or read capability respectively,
|
||||
* then crud or read is set to true.
|
||||
* Permissions for specific owners can be found by passing an owner array
|
||||
* @param owners an array of CaseOwners that should be queried for permission
|
||||
* @returns An object denoting the case permissions of the current user
|
||||
*/
|
||||
canUseCases: (owners?: CasesOwners[]) => { crud: boolean; read: boolean };
|
||||
getRuleIdFromEvent: typeof getRuleIdFromEvent;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -102,8 +102,8 @@ describe('AddToCaseAction', function () {
|
|||
);
|
||||
fireEvent.click(await findByText('Add to case'));
|
||||
|
||||
expect(core?.cases?.getAllCasesSelectorModal).toHaveBeenCalledTimes(1);
|
||||
expect(core?.cases?.getAllCasesSelectorModal).toHaveBeenCalledWith(
|
||||
expect(core?.cases?.ui.getAllCasesSelectorModal).toHaveBeenCalledTimes(1);
|
||||
expect(core?.cases?.ui.getAllCasesSelectorModal).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
owner: ['observability'],
|
||||
userCanCrud: true,
|
||||
|
|
|
@ -114,7 +114,7 @@ export function AddToCaseAction({
|
|||
)}
|
||||
{isCasesOpen &&
|
||||
lensAttributes &&
|
||||
cases.getAllCasesSelectorModal(getAllCasesSelectorModalProps)}
|
||||
cases.ui.getAllCasesSelectorModal(getAllCasesSelectorModalProps)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ function AlertsPage() {
|
|||
const hasData = hasAnyData === true || (isAllRequestsComplete === false ? undefined : false);
|
||||
|
||||
const kibana = useKibana<ObservabilityAppServices>();
|
||||
const CasesContext = kibana.services.cases.getCasesContext();
|
||||
const CasesContext = kibana.services.cases.ui.getCasesContext();
|
||||
const userPermissions = useGetUserCasesPermissions();
|
||||
|
||||
if (!hasAnyData && !isAllRequestsComplete) {
|
||||
|
|
|
@ -19,7 +19,7 @@ interface CasesProps {
|
|||
}
|
||||
export const Cases = React.memo<CasesProps>(({ userCanCrud }) => {
|
||||
const {
|
||||
cases: casesUi,
|
||||
cases,
|
||||
application: { getUrlForApp, navigateToApp },
|
||||
} = useKibana().services;
|
||||
const { observabilityRuleTypeRegistry } = usePluginContext();
|
||||
|
@ -42,7 +42,7 @@ export const Cases = React.memo<CasesProps>(({ userCanCrud }) => {
|
|||
/>
|
||||
</Suspense>
|
||||
)}
|
||||
{casesUi.getCases({
|
||||
{cases.ui.getCases({
|
||||
basePath: CASES_PATH,
|
||||
userCanCrud,
|
||||
owner: [CASES_OWNER],
|
||||
|
|
|
@ -90,7 +90,7 @@ export function OverviewPage({ routeParams }: Props) {
|
|||
}, []);
|
||||
|
||||
const kibana = useKibana<ObservabilityAppServices>();
|
||||
const CasesContext = kibana.services.cases.getCasesContext();
|
||||
const CasesContext = kibana.services.cases.ui.getCasesContext();
|
||||
const userPermissions = useGetUserCasesPermissions();
|
||||
|
||||
if (hasAnyData === undefined) {
|
||||
|
|
|
@ -43,7 +43,7 @@ const TimelineDetailsPanel = () => {
|
|||
};
|
||||
|
||||
const CaseContainerComponent: React.FC = () => {
|
||||
const { cases: casesUi } = useKibana().services;
|
||||
const { cases } = useKibana().services;
|
||||
const { getAppUrl, navigateTo } = useNavigation();
|
||||
const userPermissions = useGetUserCasesPermissions();
|
||||
const dispatch = useDispatch();
|
||||
|
@ -98,7 +98,7 @@ const CaseContainerComponent: React.FC = () => {
|
|||
return (
|
||||
<SecuritySolutionPageWrapper noPadding>
|
||||
<CaseDetailsRefreshContext.Provider value={refreshRef}>
|
||||
{casesUi.getCases({
|
||||
{cases.ui.getCases({
|
||||
basePath: CASES_PATH,
|
||||
owner: [APP_ID],
|
||||
features: {
|
||||
|
|
|
@ -109,7 +109,7 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
|
|||
unit,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const { timelines: timelinesUi, cases: casesUi } = useKibana().services;
|
||||
const { timelines: timelinesUi, cases } = useKibana().services;
|
||||
const {
|
||||
browserFields,
|
||||
dataViewId,
|
||||
|
@ -184,7 +184,7 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
|
|||
});
|
||||
|
||||
const casesPermissions = useGetUserCasesPermissions();
|
||||
const CasesContext = casesUi.getCasesContext();
|
||||
const CasesContext = cases.ui.getCasesContext();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -357,7 +357,7 @@ export const AlertsTableComponent: React.FC<AlertsTableComponentProps> = ({
|
|||
const leadingControlColumns = useMemo(() => getDefaultControlColumn(ACTION_BUTTON_COUNT), []);
|
||||
|
||||
const casesPermissions = useGetUserCasesPermissions();
|
||||
const CasesContext = kibana.services.cases.getCasesContext();
|
||||
const CasesContext = kibana.services.cases.ui.getCasesContext();
|
||||
|
||||
if (loading || isEmpty(selectedPatterns)) {
|
||||
return null;
|
||||
|
|
|
@ -74,7 +74,7 @@ jest.mock('../../../common/lib/kibana', () => {
|
|||
},
|
||||
},
|
||||
cases: {
|
||||
getCasesContext: mockCasesContext,
|
||||
ui: { getCasesContext: mockCasesContext },
|
||||
},
|
||||
uiSettings: {
|
||||
get: jest.fn(),
|
||||
|
|
|
@ -12,11 +12,11 @@ import { APP_ID } from '../../../../common/constants';
|
|||
|
||||
const MAX_CASES_TO_SHOW = 3;
|
||||
const RecentCasesComponent = () => {
|
||||
const { cases: casesUi } = useKibana().services;
|
||||
const { cases } = useKibana().services;
|
||||
|
||||
const userCanCrud = useGetUserCasesPermissions()?.crud ?? false;
|
||||
|
||||
return casesUi.getRecentCases({
|
||||
return cases.ui.getRecentCases({
|
||||
userCanCrud,
|
||||
maxCasesToShow: MAX_CASES_TO_SHOW,
|
||||
owner: [APP_ID],
|
||||
|
|
|
@ -11,19 +11,18 @@ import { waitFor } from '@testing-library/react';
|
|||
import { TestProviders } from '../../../common/mock';
|
||||
import { Sidebar } from './sidebar';
|
||||
import { useGetUserCasesPermissions, useKibana } from '../../../common/lib/kibana';
|
||||
import { casesPluginMock } from '../../../../../cases/public/mocks';
|
||||
import { CasesUiStart } from '../../../../../cases/public';
|
||||
import { casesPluginMock, CaseUiClientMock } from '../../../../../cases/public/mocks';
|
||||
|
||||
jest.mock('../../../common/lib/kibana');
|
||||
|
||||
const useKibanaMock = useKibana as jest.MockedFunction<typeof useKibana>;
|
||||
|
||||
describe('Sidebar', () => {
|
||||
let casesMock: jest.Mocked<CasesUiStart>;
|
||||
let casesMock: CaseUiClientMock;
|
||||
|
||||
beforeEach(() => {
|
||||
casesMock = casesPluginMock.createStartContract();
|
||||
casesMock.getRecentCases.mockImplementation(() => <>{'test'}</>);
|
||||
casesMock.ui.getRecentCases.mockImplementation(() => <>{'test'}</>);
|
||||
useKibanaMock.mockReturnValue({
|
||||
services: {
|
||||
cases: casesMock,
|
||||
|
@ -50,7 +49,7 @@ describe('Sidebar', () => {
|
|||
)
|
||||
);
|
||||
|
||||
expect(casesMock.getRecentCases).not.toHaveBeenCalled();
|
||||
expect(casesMock.ui.getRecentCases).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does render the recently created cases section when the user has read permissions', async () => {
|
||||
|
@ -67,6 +66,6 @@ describe('Sidebar', () => {
|
|||
)
|
||||
);
|
||||
|
||||
expect(casesMock.getRecentCases).toHaveBeenCalled();
|
||||
expect(casesMock.ui.getRecentCases).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -47,7 +47,7 @@ describe('AddToCaseButton', () => {
|
|||
|
||||
it('navigates to the correct path without id', async () => {
|
||||
const here = jest.fn();
|
||||
useKibanaMock().services.cases.getAllCasesSelectorModal = here.mockImplementation(
|
||||
useKibanaMock().services.cases.ui.getAllCasesSelectorModal = here.mockImplementation(
|
||||
({ onRowClick }) => {
|
||||
onRowClick();
|
||||
return <></>;
|
||||
|
@ -69,7 +69,7 @@ describe('AddToCaseButton', () => {
|
|||
});
|
||||
|
||||
it('navigates to the correct path with id', async () => {
|
||||
useKibanaMock().services.cases.getAllCasesSelectorModal = jest
|
||||
useKibanaMock().services.cases.ui.getAllCasesSelectorModal = jest
|
||||
.fn()
|
||||
.mockImplementation(({ onRowClick }) => {
|
||||
onRowClick({ id: 'case-id' });
|
||||
|
|
|
@ -161,7 +161,7 @@ const AddToCaseButtonComponent: React.FC<Props> = ({ timelineId }) => {
|
|||
<EuiContextMenuPanel items={items} />
|
||||
</EuiPopover>
|
||||
{isCaseModalOpen &&
|
||||
cases.getAllCasesSelectorModal({
|
||||
cases.ui.getAllCasesSelectorModal({
|
||||
onRowClick,
|
||||
userCanCrud: userPermissions?.crud ?? false,
|
||||
owner: [APP_ID],
|
||||
|
|
|
@ -137,7 +137,9 @@ describe('event details footer component', () => {
|
|||
get: jest.fn().mockReturnValue([]),
|
||||
},
|
||||
cases: {
|
||||
getCasesContext: () => mockCasesContext,
|
||||
ui: {
|
||||
getCasesContext: () => mockCasesContext,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -100,7 +100,7 @@ const EventDetailsPanelComponent: React.FC<EventDetailsPanelProps> = ({
|
|||
services: { cases },
|
||||
} = useKibana();
|
||||
|
||||
const CasesContext = cases.getCasesContext();
|
||||
const CasesContext = cases.ui.getCasesContext();
|
||||
const casesPermissions = useGetUserCasesPermissions();
|
||||
|
||||
const [isIsolateActionSuccessBannerVisible, setIsIsolateActionSuccessBannerVisible] =
|
||||
|
|
|
@ -125,7 +125,7 @@ describe('Details Panel Component', () => {
|
|||
navigateToApp: jest.fn(),
|
||||
},
|
||||
cases: {
|
||||
getCasesContext: () => mockCasesContext,
|
||||
ui: { getCasesContext: () => mockCasesContext },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -229,7 +229,7 @@ export const BodyComponent = React.memo<StatefulBodyProps>(
|
|||
);
|
||||
const kibana = useKibana();
|
||||
const casesPermissions = useGetUserCasesPermissions();
|
||||
const CasesContext = kibana.services.cases.getCasesContext();
|
||||
const CasesContext = kibana.services.cases.ui.getCasesContext();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -58,7 +58,9 @@ jest.mock('../../../../common/lib/kibana', () => {
|
|||
getUrlForApp: jest.fn(),
|
||||
},
|
||||
cases: {
|
||||
getCasesContext: () => mockCasesContext,
|
||||
ui: {
|
||||
getCasesContext: () => mockCasesContext,
|
||||
},
|
||||
},
|
||||
docLinks: { links: { query: { eql: 'url-eql_doc' } } },
|
||||
uiSettings: {
|
||||
|
|
|
@ -53,7 +53,9 @@ jest.mock('../../../../common/lib/kibana', () => {
|
|||
getUrlForApp: jest.fn(),
|
||||
},
|
||||
cases: {
|
||||
getCasesContext: () => mockCasesContext,
|
||||
ui: {
|
||||
getCasesContext: () => mockCasesContext,
|
||||
},
|
||||
},
|
||||
uiSettings: {
|
||||
get: jest.fn(),
|
||||
|
|
|
@ -61,7 +61,9 @@ jest.mock('../../../../common/lib/kibana', () => {
|
|||
getUrlForApp: jest.fn(),
|
||||
},
|
||||
cases: {
|
||||
getCasesContext: () => mockCasesContext,
|
||||
ui: {
|
||||
getCasesContext: () => mockCasesContext,
|
||||
},
|
||||
},
|
||||
uiSettings: {
|
||||
get: jest.fn(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue