Skip to content

Commit f633c97

Browse files
committed
case attachment tab ui
1 parent ca3d14f commit f633c97

17 files changed

Lines changed: 513 additions & 1067 deletions

File tree

x-pack/platform/plugins/private/translations/translations/de-DE.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15943,10 +15943,7 @@
1594315943
"xpack.cases.caseView.syncAlertsLabel": "Alerts synchronisieren",
1594415944
"xpack.cases.caseView.syncAlertsLowercaseLabel": "Alerts synchronisieren",
1594515945
"xpack.cases.caseView.tabs.activity": "Aktivität",
15946-
"xpack.cases.caseView.tabs.alerts": "Alerts",
1594715946
"xpack.cases.caseView.tabs.attachments": "Anhänge",
15948-
"xpack.cases.caseView.tabs.events": "Ereignisse",
15949-
"xpack.cases.caseView.tabs.files": "Dateien",
1595015947
"xpack.cases.caseView.tabs.observables": "Beobachtungsdaten",
1595115948
"xpack.cases.caseView.tabs.similar": "Ähnliche Tickets",
1595215949
"xpack.cases.caseView.tags": "Tags",

x-pack/platform/plugins/private/translations/translations/fr-FR.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15917,10 +15917,7 @@
1591715917
"xpack.cases.caseView.syncAlertsLabel": "Synchroniser les alertes",
1591815918
"xpack.cases.caseView.syncAlertsLowercaseLabel": "synchroniser les alertes",
1591915919
"xpack.cases.caseView.tabs.activity": "Activité",
15920-
"xpack.cases.caseView.tabs.alerts": "Alertes",
1592115920
"xpack.cases.caseView.tabs.attachments": "Pièces jointes",
15922-
"xpack.cases.caseView.tabs.events": "Événements",
15923-
"xpack.cases.caseView.tabs.files": "Fichiers",
1592415921
"xpack.cases.caseView.tabs.observables": "Observables",
1592515922
"xpack.cases.caseView.tabs.similar": "Cas similaires",
1592615923
"xpack.cases.caseView.tags": "Balises",

x-pack/platform/plugins/private/translations/translations/ja-JP.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15993,10 +15993,7 @@
1599315993
"xpack.cases.caseView.syncAlertsLabel": "アラートの同期",
1599415994
"xpack.cases.caseView.syncAlertsLowercaseLabel": "アラートの同期",
1599515995
"xpack.cases.caseView.tabs.activity": "アクティビティ",
15996-
"xpack.cases.caseView.tabs.alerts": "アラート",
1599715996
"xpack.cases.caseView.tabs.attachments": "添付ファイル",
15998-
"xpack.cases.caseView.tabs.events": "イベント",
15999-
"xpack.cases.caseView.tabs.files": "ファイル",
1600015997
"xpack.cases.caseView.tabs.observables": "オブザーバブル",
1600115998
"xpack.cases.caseView.tabs.similar": "類似したケース",
1600215999
"xpack.cases.caseView.tags": "タグ",

x-pack/platform/plugins/private/translations/translations/zh-CN.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15994,10 +15994,7 @@
1599415994
"xpack.cases.caseView.syncAlertsLabel": "同步告警",
1599515995
"xpack.cases.caseView.syncAlertsLowercaseLabel": "同步告警",
1599615996
"xpack.cases.caseView.tabs.activity": "活动",
15997-
"xpack.cases.caseView.tabs.alerts": "告警",
1599815997
"xpack.cases.caseView.tabs.attachments": "附件",
15999-
"xpack.cases.caseView.tabs.events": "事件",
16000-
"xpack.cases.caseView.tabs.files": "文件",
1600115998
"xpack.cases.caseView.tabs.observables": "可观察对象",
1600215999
"xpack.cases.caseView.tabs.similar": "类似案例",
1600316000
"xpack.cases.caseView.tags": "标签",

x-pack/platform/plugins/shared/cases/public/components/case_view/case_view_page.test.tsx

Lines changed: 13 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { CASE_VIEW_PAGE_TABS } from '../../../common/types';
1515
import { caseData, caseViewProps } from './mocks';
1616
import type { CaseViewPageProps } from './types';
1717
import { useCasesTitleBreadcrumbs } from '../use_breadcrumbs';
18-
import { toUnifiedAttachmentType } from '../../../common/utils/attachments/migration_utils';
1918
import { UnifiedAttachmentTypeRegistry } from '../../client/attachment_framework/unified_attachment_registry';
2019

2120
jest.mock('../../common/navigation/hooks');
@@ -31,14 +30,6 @@ jest.mock(
3130
}),
3231
{ virtual: true }
3332
);
34-
jest.mock('../../../common/utils/attachments/migration_utils', () => {
35-
const actual = jest.requireActual('../../../common/utils/attachments/migration_utils');
36-
37-
return {
38-
...actual,
39-
toUnifiedAttachmentType: jest.fn(actual.toUnifiedAttachmentType),
40-
};
41-
});
4233

4334
jest.mock('../header_page', () => ({
4435
HeaderPage: jest.fn(() => <div data-test-subj="test-case-view-header">{'Case view header'}</div>),
@@ -56,9 +47,9 @@ jest.mock('./components/case_view_activity', () => ({
5647
)),
5748
}));
5849

59-
jest.mock('./components/case_view_observables', () => ({
60-
CaseViewObservables: jest.fn(() => (
61-
<div data-test-subj="test-case-view-observables">{'Case view observables'}</div>
50+
jest.mock('./components/case_view_attachments', () => ({
51+
CaseViewAttachments: jest.fn(() => (
52+
<div data-test-subj="test-case-view-attachments">{'Case view attachments'}</div>
6253
)),
6354
}));
6455

@@ -70,9 +61,6 @@ jest.mock('./components/case_view_similar_cases', () => ({
7061

7162
const useUrlParamsMock = useUrlParams as jest.Mock;
7263
const useCasesTitleBreadcrumbsMock = useCasesTitleBreadcrumbs as jest.Mock;
73-
const toUnifiedAttachmentTypeMock = toUnifiedAttachmentType as jest.MockedFunction<
74-
typeof toUnifiedAttachmentType
75-
>;
7664

7765
const caseProps: CaseViewPageProps = {
7866
...caseViewProps,
@@ -87,40 +75,6 @@ describe('CaseViewPage', () => {
8775
jest.clearAllMocks();
8876
useUrlParamsMock.mockReturnValue({});
8977
unifiedAttachmentTypeRegistry = new UnifiedAttachmentTypeRegistry();
90-
unifiedAttachmentTypeRegistry.register({
91-
id: 'security.event',
92-
displayName: 'Event',
93-
icon: 'bell',
94-
getAttachmentViewObject: () => ({ event: 'added an event' }),
95-
getAttachmentTabViewObject: () => ({
96-
children: () => (
97-
<div data-test-subj="test-case-view-events-content">{'Events content'}</div>
98-
),
99-
}),
100-
schemaValidator: () => {},
101-
});
102-
unifiedAttachmentTypeRegistry.register({
103-
id: 'security.alert',
104-
displayName: 'Alert',
105-
icon: 'bell',
106-
getAttachmentViewObject: () => ({ event: 'added an alert' }),
107-
getAttachmentTabViewObject: () => ({
108-
children: () => (
109-
<div data-test-subj="test-case-view-alerts-content">{'Alerts content'}</div>
110-
),
111-
}),
112-
schemaValidator: () => {},
113-
});
114-
unifiedAttachmentTypeRegistry.register({
115-
id: 'file',
116-
displayName: 'File',
117-
icon: 'document',
118-
getAttachmentViewObject: () => ({ event: 'added a file' }),
119-
getAttachmentTabViewObject: () => ({
120-
children: () => <div data-test-subj="test-case-view-files">{'Case view files'}</div>,
121-
}),
122-
schemaValidator: () => {},
123-
});
12478
});
12579

12680
it('shows the header section', async () => {
@@ -153,79 +107,19 @@ describe('CaseViewPage', () => {
153107
});
154108
});
155109

156-
it('resolves event type using the full case owner', () => {
157-
const caseDataWithStringOwner = { ...caseProps.caseData, owner: 'securitySolution' };
158-
159-
renderWithTestingProviders(<CaseViewPage {...caseProps} caseData={caseDataWithStringOwner} />);
160-
161-
expect(toUnifiedAttachmentTypeMock).toHaveBeenCalledWith('event', 'securitySolution');
162-
});
163-
164-
it('does not render the events tab content when events feature is disabled', () => {
165-
useUrlParamsMock.mockReturnValue({
166-
urlParams: { tabId: CASE_VIEW_PAGE_TABS.EVENTS },
167-
});
168-
169-
renderWithTestingProviders(<CaseViewPage {...caseProps} />, {
170-
wrapperProps: {
171-
features: { events: { enabled: false } },
172-
unifiedAttachmentTypeRegistry,
173-
},
174-
});
175-
176-
expect(screen.queryByTestId('test-case-view-events-content')).not.toBeInTheDocument();
177-
});
178-
179-
it('renders the events tab content when events feature is enabled and type is registered', async () => {
180-
useUrlParamsMock.mockReturnValue({
181-
urlParams: { tabId: CASE_VIEW_PAGE_TABS.EVENTS },
182-
});
183-
184-
renderWithTestingProviders(<CaseViewPage {...caseProps} />, {
185-
wrapperProps: {
186-
features: { events: { enabled: true } },
187-
unifiedAttachmentTypeRegistry,
188-
},
189-
});
190-
191-
expect(await screen.findByTestId('test-case-view-events-content')).toBeInTheDocument();
192-
});
193-
194-
it('resolves alert type using the full case owner', () => {
195-
const caseDataWithStringOwner = { ...caseProps.caseData, owner: 'securitySolution' };
196-
197-
renderWithTestingProviders(<CaseViewPage {...caseProps} caseData={caseDataWithStringOwner} />);
198-
199-
expect(toUnifiedAttachmentTypeMock).toHaveBeenCalledWith('alert', 'securitySolution');
200-
});
201-
202-
it('does not render the alerts tab content when alerts feature is disabled', () => {
203-
useUrlParamsMock.mockReturnValue({
204-
urlParams: { tabId: CASE_VIEW_PAGE_TABS.ALERTS },
205-
});
206-
207-
renderWithTestingProviders(<CaseViewPage {...caseProps} />, {
208-
wrapperProps: {
209-
features: { alerts: { enabled: false } },
210-
unifiedAttachmentTypeRegistry,
211-
},
212-
});
213-
214-
expect(screen.queryByTestId('test-case-view-alerts-content')).not.toBeInTheDocument();
215-
});
216-
217-
it('renders the alerts tab content when alerts feature is enabled and type is registered', async () => {
218-
useUrlParamsMock.mockReturnValue({
219-
urlParams: { tabId: CASE_VIEW_PAGE_TABS.ALERTS },
220-
});
110+
it.each([
111+
CASE_VIEW_PAGE_TABS.ATTACHMENTS,
112+
CASE_VIEW_PAGE_TABS.ALERTS,
113+
CASE_VIEW_PAGE_TABS.EVENTS,
114+
CASE_VIEW_PAGE_TABS.FILES,
115+
CASE_VIEW_PAGE_TABS.OBSERVABLES,
116+
])('renders the consolidated attachments view for tabId=%s', async (tabId) => {
117+
useUrlParamsMock.mockReturnValue({ urlParams: { tabId } });
221118

222119
renderWithTestingProviders(<CaseViewPage {...caseProps} />, {
223-
wrapperProps: {
224-
features: { alerts: { enabled: true } },
225-
unifiedAttachmentTypeRegistry,
226-
},
120+
wrapperProps: { unifiedAttachmentTypeRegistry },
227121
});
228122

229-
expect(await screen.findByTestId('test-case-view-alerts-content')).toBeInTheDocument();
123+
expect(await screen.findByTestId('test-case-view-attachments')).toBeInTheDocument();
230124
});
231125
});

x-pack/platform/plugins/shared/cases/public/components/case_view/case_view_page.tsx

Lines changed: 4 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,19 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
99
import React, { useCallback, useEffect, useMemo, useState } from 'react';
1010
import { CASE_VIEW_PAGE_TABS } from '../../../common/types';
1111
import { useUrlParams } from '../../common/navigation';
12-
import { useCasesContext } from '../cases_context/use_cases_context';
1312
import { CaseActionBar } from '../case_action_bar';
1413
import { HeaderPage } from '../header_page';
1514
import { EditableTitle } from '../header_page/editable_title';
1615
import { useCasesTitleBreadcrumbs } from '../use_breadcrumbs';
1716
import { CaseViewActivity } from './components/case_view_activity';
18-
import { CaseViewObservables } from './components/case_view_observables';
1917
import { CaseViewMetrics } from './metrics';
2018
import type { CaseViewPageProps } from './types';
2119
import { useRefreshCaseViewPage } from './use_on_refresh_case_view_page';
2220
import { useOnUpdateField } from './use_on_update_field';
2321
import { CaseViewSimilarCases } from './components/case_view_similar_cases';
2422
import { CaseViewAttachments } from './components/case_view_attachments';
2523
import { filterCaseAttachmentsBySearchTerm } from './components/helpers';
26-
import { toUnifiedAttachmentType } from '../../../common/utils/attachments/migration_utils';
27-
import { FILE_ATTACHMENT_TYPE } from '../../../common/constants';
24+
import { ATTACHMENT_TAB_ALIASES } from './use_case_attachment_tabs';
2825

2926
const getActiveTabId = (tabId?: string) => {
3027
if (tabId && Object.values(CASE_VIEW_PAGE_TABS).includes(tabId as CASE_VIEW_PAGE_TABS)) {
@@ -34,16 +31,8 @@ const getActiveTabId = (tabId?: string) => {
3431
return CASE_VIEW_PAGE_TABS.ACTIVITY;
3532
};
3633

37-
const ATTACHMENT_TABS = [
38-
CASE_VIEW_PAGE_TABS.ALERTS,
39-
CASE_VIEW_PAGE_TABS.EVENTS,
40-
CASE_VIEW_PAGE_TABS.FILES,
41-
CASE_VIEW_PAGE_TABS.OBSERVABLES,
42-
];
43-
4434
export const CaseViewPage = React.memo<CaseViewPageProps>(
4535
({ caseData, refreshRef, actionsNavigation }) => {
46-
const { features, unifiedAttachmentTypeRegistry } = useCasesContext();
4736
const { urlParams } = useUrlParams();
4837
const refreshCaseViewPage = useRefreshCaseViewPage();
4938

@@ -89,31 +78,6 @@ export const CaseViewPage = React.memo<CaseViewPageProps>(
8978
}
9079
}, [isLoading, refreshRef, refreshCaseViewPage]);
9180

92-
const owner = Array.isArray(caseData.owner) ? caseData.owner[0] : caseData.owner;
93-
const EventTabComponent = useMemo(() => {
94-
const eventType = toUnifiedAttachmentType('event', owner);
95-
if (!unifiedAttachmentTypeRegistry.has(eventType)) {
96-
return undefined;
97-
}
98-
return unifiedAttachmentTypeRegistry.get(eventType)?.getAttachmentTabViewObject?.()?.children;
99-
}, [unifiedAttachmentTypeRegistry, owner]);
100-
101-
const AlertTabComponent = useMemo(() => {
102-
const alertType = toUnifiedAttachmentType('alert', owner);
103-
if (!unifiedAttachmentTypeRegistry.has(alertType)) {
104-
return undefined;
105-
}
106-
return unifiedAttachmentTypeRegistry.get(alertType)?.getAttachmentTabViewObject?.()?.children;
107-
}, [unifiedAttachmentTypeRegistry, owner]);
108-
109-
const FileTabComponent = useMemo(() => {
110-
if (!unifiedAttachmentTypeRegistry.has(FILE_ATTACHMENT_TYPE)) {
111-
return undefined;
112-
}
113-
return unifiedAttachmentTypeRegistry.get(FILE_ATTACHMENT_TYPE)?.getAttachmentTabViewObject?.()
114-
?.children;
115-
}, [unifiedAttachmentTypeRegistry]);
116-
11781
const onSubmitTitle = useCallback(
11882
(newTitle: string) =>
11983
onUpdateField({
@@ -159,43 +123,13 @@ export const CaseViewPage = React.memo<CaseViewPageProps>(
159123
actionsNavigation={actionsNavigation}
160124
/>
161125
)}
162-
{ATTACHMENT_TABS.includes(activeTabId as CASE_VIEW_PAGE_TABS) && (
126+
{ATTACHMENT_TAB_ALIASES.has(activeTabId) && (
163127
<CaseViewAttachments
164128
onSearch={onSearch}
165129
searchTerm={searchTerm}
166-
activeTab={activeTabId as CASE_VIEW_PAGE_TABS}
167130
caseData={caseWithFilteredAttachments}
168-
>
169-
<>
170-
{activeTabId === CASE_VIEW_PAGE_TABS.ALERTS &&
171-
features.alerts.enabled &&
172-
AlertTabComponent != null && (
173-
<AlertTabComponent
174-
key={caseWithFilteredAttachments.updatedAt}
175-
caseData={caseWithFilteredAttachments}
176-
/>
177-
)}
178-
{activeTabId === CASE_VIEW_PAGE_TABS.EVENTS &&
179-
features.events.enabled &&
180-
EventTabComponent != null && (
181-
<EventTabComponent caseData={caseWithFilteredAttachments} />
182-
)}
183-
{activeTabId === CASE_VIEW_PAGE_TABS.FILES && FileTabComponent != null && (
184-
<FileTabComponent
185-
caseData={caseWithFilteredAttachments}
186-
searchTerm={searchTerm}
187-
/>
188-
)}
189-
{activeTabId === CASE_VIEW_PAGE_TABS.OBSERVABLES && (
190-
<CaseViewObservables
191-
isLoading={false}
192-
caseData={caseWithFilteredAttachments}
193-
searchTerm={searchTerm}
194-
onUpdateField={onUpdateField}
195-
/>
196-
)}
197-
</>
198-
</CaseViewAttachments>
131+
onUpdateField={onUpdateField}
132+
/>
199133
)}
200134
{activeTabId === CASE_VIEW_PAGE_TABS.SIMILAR_CASES && (
201135
<CaseViewSimilarCases caseData={caseWithFilteredAttachments} searchTerm={searchTerm} />

0 commit comments

Comments
 (0)