Skip to content

Commit

Permalink
[Security Solution] Case ui enhancement (#91863) (#93387)
Browse files Browse the repository at this point in the history
* ui enhancement

* fix actions

* unit test

* update row actions

* add case status all

* update find status

* fix type

* remove all case count from dropdown

* fix type error

* fix unit test

* disable bulk actions on status all

* clean up

* fix types

* fix cypress tests

* review

* review

* update status is only available for individual cases

* update available actions on status all

* fix unit test

* remove lodash get

* rename status all

* omit status if it is set to all

* do not sent status if itis set to all

* Remove all status from the backend

* Hide actions on all status

* fix unit test

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Christos Nasikas <christos.nasikas@elastic.co>
# Conflicts:
#	x-pack/plugins/security_solution/public/cases/containers/api.ts
  • Loading branch information
angorayc authored Mar 3, 2021
1 parent de14241 commit 1106195
Show file tree
Hide file tree
Showing 24 changed files with 315 additions and 86 deletions.
2 changes: 0 additions & 2 deletions x-pack/plugins/case/server/routes/api/cases/find_cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export function initFindCasesApi({ caseService, router, logger }: RouteDeps) {
CasesFindRequestRt.decode(request.query),
fold(throwErrors(Boom.badRequest), identity)
);

const queryArgs = {
tags: queryParams.tags,
reporters: queryParams.reporters,
Expand All @@ -47,7 +46,6 @@ export function initFindCasesApi({ caseService, router, logger }: RouteDeps) {
};

const caseQueries = constructQueryOptions(queryArgs);

const cases = await caseService.findCasesGroupedByID({
client,
caseOptions: { ...queryParams, ...caseQueries.case },
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/case/server/routes/api/cases/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const addStatusFilter = ({
appendFilter,
type = CASE_SAVED_OBJECT,
}: {
status: CaseStatuses | undefined;
status?: CaseStatuses;
appendFilter?: string;
type?: string;
}) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
backToCases,
createCase,
fillCasesMandatoryfields,
filterStatusOpen,
} from '../../tasks/create_new_case';
import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';

Expand Down Expand Up @@ -74,6 +75,7 @@ describe('Cases', () => {
attachTimeline(this.mycase);
createCase();
backToCases();
filterStatusOpen();

cy.get(ALL_CASES_PAGE_TITLE).should('have.text', 'Cases');
cy.get(ALL_CASES_OPEN_CASES_STATS).should('have.text', 'Open cases1');
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/security_solution/cypress/screens/all_cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const ALL_CASES_NAME = '[data-test-subj="case-details-link"]';

export const ALL_CASES_OPEN_CASES_COUNT = '[data-test-subj="case-status-filter"]';

export const ALL_CASES_OPEN_FILTER = '[data-test-subj="case-status-filter-open"]';

export const ALL_CASES_OPEN_CASES_STATS = '[data-test-subj="openStatsHeader"]';

export const ALL_CASES_OPENED_ON = '[data-test-subj="case-table-column-createdAt"]';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ServiceNowconnectorOptions,
TestCase,
} from '../objects/case';
import { ALL_CASES_OPEN_CASES_COUNT, ALL_CASES_OPEN_FILTER } from '../screens/all_cases';

import {
BACK_TO_CASES_BTN,
Expand Down Expand Up @@ -40,6 +41,11 @@ export const backToCases = () => {
cy.get(BACK_TO_CASES_BTN).click({ force: true });
};

export const filterStatusOpen = () => {
cy.get(ALL_CASES_OPEN_CASES_COUNT).click();
cy.get(ALL_CASES_OPEN_FILTER).click();
};

export const fillCasesMandatoryfields = (newCase: TestCase) => {
cy.get(TITLE_INPUT).type(newCase.name, { force: true });
newCase.tags.forEach((tag) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,22 @@ import { Case, SubCase } from '../../containers/types';
import { UpdateCase } from '../../containers/use_get_cases';
import { statuses } from '../status';
import * as i18n from './translations';
import { isIndividual } from './helpers';

interface GetActions {
caseStatus: string;
dispatchUpdate: Dispatch<Omit<UpdateCase, 'refetchCasesStatus'>>;
deleteCaseOnClick: (deleteCase: Case) => void;
}

const hasSubCases = (subCases: SubCase[] | null | undefined) =>
subCases != null && subCases?.length > 0;

export const getActions = ({
caseStatus,
dispatchUpdate,
deleteCaseOnClick,
}: GetActions): Array<DefaultItemIconButtonAction<Case>> => {
const openCaseAction = {
available: (item: Case) => caseStatus !== CaseStatuses.open && !hasSubCases(item.subCases),
available: (item: Case | SubCase) => item.status !== CaseStatuses.open,
enabled: (item: Case | SubCase) => isIndividual(item),
description: statuses[CaseStatuses.open].actions.single.title,
icon: statuses[CaseStatuses.open].icon,
name: statuses[CaseStatuses.open].actions.single.title,
Expand All @@ -45,8 +44,8 @@ export const getActions = ({
};

const makeInProgressAction = {
available: (item: Case) =>
caseStatus !== CaseStatuses['in-progress'] && !hasSubCases(item.subCases),
available: (item: Case) => item.status !== CaseStatuses['in-progress'],
enabled: (item: Case | SubCase) => isIndividual(item),
description: statuses[CaseStatuses['in-progress']].actions.single.title,
icon: statuses[CaseStatuses['in-progress']].icon,
name: statuses[CaseStatuses['in-progress']].actions.single.title,
Expand All @@ -62,7 +61,8 @@ export const getActions = ({
};

const closeCaseAction = {
available: (item: Case) => caseStatus !== CaseStatuses.closed && !hasSubCases(item.subCases),
available: (item: Case | SubCase) => item.status !== CaseStatuses.closed,
enabled: (item: Case | SubCase) => isIndividual(item),
description: statuses[CaseStatuses.closed].actions.single.title,
icon: statuses[CaseStatuses.closed].icon,
name: statuses[CaseStatuses.closed].actions.single.title,
Expand All @@ -78,6 +78,9 @@ export const getActions = ({
};

return [
openCaseAction,
makeInProgressAction,
closeCaseAction,
{
description: i18n.DELETE_CASE,
icon: 'trash',
Expand All @@ -86,8 +89,5 @@ export const getActions = ({
type: 'icon',
'data-test-subj': 'action-delete',
},
openCaseAction,
makeInProgressAction,
closeCaseAction,
];
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services';
import styled from 'styled-components';
import { DefaultItemIconButtonAction } from '@elastic/eui/src/components/basic_table/action_types';

import { CaseStatuses } from '../../../../../case/common/api';
import { CaseStatuses, CaseType } from '../../../../../case/common/api';
import { getEmptyTagValue } from '../../../common/components/empty_value';
import { Case, SubCase } from '../../containers/types';
import { FormattedRelativePreferenceDate } from '../../../common/components/formatted_date';
Expand Down Expand Up @@ -204,7 +204,7 @@ export const getCasesColumns = (
name: i18n.STATUS,
render: (theCase: Case) => {
if (theCase?.subCases == null || theCase.subCases.length === 0) {
if (theCase.status == null) {
if (theCase.status == null || theCase.type === CaseType.collection) {
return getEmptyTagValue();
}
return <Status type={theCase.status} />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@
*/

import { filter } from 'lodash/fp';
import { AssociationType, CaseStatuses } from '../../../../../case/common/api';
import { AssociationType, CaseStatuses, CaseType } from '../../../../../case/common/api';
import { Case, SubCase } from '../../containers/types';
import { statuses } from '../status';

export const isSelectedCasesIncludeCollections = (selectedCases: Case[]) =>
selectedCases.length > 0 &&
selectedCases.some((caseObj: Case) => caseObj.type === CaseType.collection);

export const isSubCase = (theCase: Case | SubCase): theCase is SubCase =>
(theCase as SubCase).caseParentId !== undefined &&
(theCase as SubCase).associationType === AssociationType.subCase;

export const isCollection = (theCase: Case | SubCase | null | undefined) =>
theCase != null && (theCase as Case).type === CaseType.collection;

export const isIndividual = (theCase: Case | SubCase | null | undefined) =>
theCase != null && (theCase as Case).type === CaseType.individual;

export const getSubCasesStatusCountsBadges = (
subCases: SubCase[]
): Array<{ name: CaseStatuses; color: string; count: number }> => {
Expand Down
Loading

0 comments on commit 1106195

Please sign in to comment.