Skip to content

Commit

Permalink
[Cases] Separate Cases SO attributes from HTTP APIs (#155898)
Browse files Browse the repository at this point in the history
This PR separates the persisted SO attributes from the fields received
in the HTTP API requests.

This is to address step 2 in preparing our HTTP routes as versioned.

Issue: #153726

This PR encompasses a few PRs here which have been reviewed individually
by the cases team members:

#155325 - User actions
#155440 - Attachments
#155444 - Configure, Connector
Mappings
#155277 - Cases

The large number of files is because of renaming some types throughout
the frontend code. There shouldn't be many functionality changes, mostly
just type changes.

---------

Co-authored-by: Christos Nasikas <christos.nasikas@elastic.co>
Co-authored-by: Patryk Kopyciński <contact@patrykkopycinski.com>
  • Loading branch information
3 people authored Apr 28, 2023
1 parent 24927cb commit 6d5e245
Show file tree
Hide file tree
Showing 166 changed files with 1,720 additions and 1,449 deletions.
30 changes: 16 additions & 14 deletions x-pack/plugins/cases/common/api/cases/case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export const CasesByAlertIDRequestRt = rt.partial({
owner: rt.union([rt.array(rt.string), rt.string]),
});

export const CaseResponseRt = rt.intersection([
export const CaseRt = rt.intersection([
CaseAttributesRt,
rt.type({
id: rt.string,
Expand All @@ -264,7 +264,7 @@ export const CaseResponseRt = rt.intersection([

export const CaseResolveResponseRt = rt.intersection([
rt.type({
case: CaseResponseRt,
case: CaseRt,
outcome: rt.union([rt.literal('exactMatch'), rt.literal('aliasMatch'), rt.literal('conflict')]),
}),
rt.partial({
Expand All @@ -275,7 +275,7 @@ export const CaseResolveResponseRt = rt.intersection([

export const CasesFindResponseRt = rt.intersection([
rt.type({
cases: rt.array(CaseResponseRt),
cases: rt.array(CaseRt),
page: rt.number,
per_page: rt.number,
total: rt.number,
Expand All @@ -292,7 +292,7 @@ export const CasePatchRequestRt = rt.intersection([
]);

export const CasesPatchRequestRt = rt.type({ cases: rt.array(CasePatchRequestRt) });
export const CasesResponseRt = rt.array(CaseResponseRt);
export const CasesRt = rt.array(CaseRt);

export const CasePushRequestParamsRt = rt.type({
case_id: rt.string,
Expand Down Expand Up @@ -339,7 +339,7 @@ export const CasesBulkGetRequestRt = rt.intersection([
]);

export const CasesBulkGetResponseRt = rt.type({
cases: CasesResponseRt,
cases: CasesRt,
errors: rt.array(
rt.type({
error: rt.string,
Expand All @@ -353,9 +353,9 @@ export const CasesBulkGetResponseRt = rt.type({
export type CaseAttributes = rt.TypeOf<typeof CaseAttributesRt>;

export type CasePostRequest = rt.TypeOf<typeof CasePostRequestRt>;
export type CaseResponse = rt.TypeOf<typeof CaseResponseRt>;
export type Case = rt.TypeOf<typeof CaseRt>;
export type CaseResolveResponse = rt.TypeOf<typeof CaseResolveResponseRt>;
export type CasesResponse = rt.TypeOf<typeof CasesResponseRt>;
export type Cases = rt.TypeOf<typeof CasesRt>;
export type CasesFindRequest = rt.TypeOf<typeof CasesFindRequestRt>;
export type CasesByAlertIDRequest = rt.TypeOf<typeof CasesByAlertIDRequestRt>;
export type CasesFindResponse = rt.TypeOf<typeof CasesFindResponseRt>;
Expand All @@ -375,13 +375,15 @@ export type CasesByAlertId = rt.TypeOf<typeof CasesByAlertIdRt>;

export type CasesBulkGetRequest = rt.TypeOf<typeof CasesBulkGetRequestRt>;
export type CasesBulkGetResponse = rt.TypeOf<typeof CasesBulkGetResponseRt>;
export type CasesBulkGetRequestCertainFields<
Field extends keyof CaseResponse = keyof CaseResponse
> = Omit<CasesBulkGetRequest, 'fields'> & {
export type CasesBulkGetRequestCertainFields<Field extends keyof Case = keyof Case> = Omit<
CasesBulkGetRequest,
'fields'
> & {
fields?: Field[];
};
export type CasesBulkGetResponseCertainFields<
Field extends keyof CaseResponse = keyof CaseResponse
> = Omit<CasesBulkGetResponse, 'cases'> & {
cases: Array<Pick<CaseResponse, Field | 'id' | 'version' | 'owner'>>;
export type CasesBulkGetResponseCertainFields<Field extends keyof Case = keyof Case> = Omit<
CasesBulkGetResponse,
'cases'
> & {
cases: Array<Pick<Case, Field | 'id' | 'version' | 'owner'>>;
};
2 changes: 0 additions & 2 deletions x-pack/plugins/cases/common/api/saved_object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,3 @@ export const SavedObjectFindOptionsRt = rt.partial({
*/
sortOrder: rt.union([rt.literal('desc'), rt.literal('asc')]),
});

export type SavedObjectFindOptions = rt.TypeOf<typeof SavedObjectFindOptionsRt>;
6 changes: 4 additions & 2 deletions x-pack/plugins/cases/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ export {
} from './api';

export type {
CaseResponse,
Case,
Cases,
CasesBulkGetRequestCertainFields,
CasesBulkGetResponseCertainFields,
} from './api';

export type {
Case,
CaseUI,
CasesUI,
Ecs,
CasesFeatures,
CaseViewRefreshPropInterface,
Expand Down
10 changes: 5 additions & 5 deletions x-pack/plugins/cases/common/ui/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type {
CaseUserActionResponse,
SingleCaseMetricsResponse,
CommentResponse,
CaseResponse,
Case as CaseSnakeCase,
UserActionFindResponse,
FindTypeField as UserActionFindTypeField,
CommentResponseAlertsType,
Expand Down Expand Up @@ -92,16 +92,16 @@ export type FindCaseUserActions = Omit<SnakeToCamelCase<UserActionFindResponse>,
userActions: CaseUserActions[];
};
export type CaseUserActionsStats = SnakeToCamelCase<CaseUserActionStatsResponse>;
export type Case = Omit<SnakeToCamelCase<CaseResponse>, 'comments'> & { comments: Comment[] };
export type Cases = Omit<SnakeToCamelCase<CasesFindResponse>, 'cases'> & { cases: Case[] };
export type CaseUI = Omit<SnakeToCamelCase<CaseSnakeCase>, 'comments'> & { comments: Comment[] };
export type CasesUI = Omit<SnakeToCamelCase<CasesFindResponse>, 'cases'> & { cases: CaseUI[] };
export type CasesStatus = SnakeToCamelCase<CasesStatusResponse>;
export type CasesMetrics = SnakeToCamelCase<CasesMetricsResponse>;
export type CaseUpdateRequest = SnakeToCamelCase<CasePatchRequest>;
export type CaseConnectors = SnakeToCamelCase<GetCaseConnectorsResponse>;
export type CaseUsers = GetCaseUsersResponse;

export interface ResolvedCase {
case: Case;
case: CaseUI;
outcome: ResolvedSimpleSavedObject['outcome'];
aliasTargetId?: ResolvedSimpleSavedObject['alias_target_id'];
aliasPurpose?: ResolvedSimpleSavedObject['alias_purpose'];
Expand Down Expand Up @@ -191,7 +191,7 @@ export type UpdateKey = keyof Pick<
export interface UpdateByKey {
updateKey: UpdateKey;
updateValue: CasePatchRequest[UpdateKey];
caseData: Case;
caseData: CaseUI;
onSuccess?: () => void;
onError?: () => void;
}
Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/cases/public/api/decoders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ import type {
CasesStatusResponse,
CasesMetricsResponse,
CasesBulkGetResponseCertainFields,
CaseResponse,
Case,
} from '../../common/api';
import {
CasesFindResponseRt,
CasesStatusResponseRt,
CasesResponseRt,
CasesRt,
getTypeForCertainFieldsFromArray,
CasesMetricsResponseRt,
} from '../../common/api';
Expand All @@ -41,11 +41,11 @@ export const decodeCasesMetricsResponse = (metrics?: CasesMetricsResponse) =>
fold(throwErrors(createToasterPlainError), identity)
);

export const decodeCasesBulkGetResponse = <Field extends keyof CaseResponse = keyof CaseResponse>(
export const decodeCasesBulkGetResponse = <Field extends keyof Case = keyof Case>(
res: CasesBulkGetResponseCertainFields<Field>,
fields?: string[]
) => {
const typeToDecode = getTypeForCertainFieldsFromArray(CasesResponseRt, fields);
const typeToDecode = getTypeForCertainFieldsFromArray(CasesRt, fields);
pipe(typeToDecode.decode(res.cases), fold(throwErrors(createToasterPlainError), identity));

return res;
Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/cases/public/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
*/

import type { HttpStart } from '@kbn/core/public';
import type { Cases, CasesStatus, CasesMetrics } from '../../common/ui';
import type { CasesUI, CasesStatus, CasesMetrics } from '../../common/ui';
import {
CASE_FIND_URL,
CASE_METRICS_URL,
CASE_STATUS_URL,
INTERNAL_BULK_GET_CASES_URL,
} from '../../common/constants';
import type {
CaseResponse,
Case,
CasesBulkGetRequestCertainFields,
CasesBulkGetResponseCertainFields,
CasesFindRequest,
Expand All @@ -41,7 +41,7 @@ export const getCases = async ({
http,
signal,
query,
}: HTTPService & { query: CasesFindRequest }): Promise<Cases> => {
}: HTTPService & { query: CasesFindRequest }): Promise<CasesUI> => {
const res = await http.get<CasesFindResponse>(CASE_FIND_URL, { query, signal });
return convertAllCasesToCamel(decodeCasesFindResponse(res));
};
Expand All @@ -68,7 +68,7 @@ export const getCasesMetrics = async ({
return convertToCamelCase(decodeCasesMetricsResponse(res));
};

export const bulkGetCases = async <Field extends keyof CaseResponse = keyof CaseResponse>({
export const bulkGetCases = async <Field extends keyof Case = keyof Case>({
http,
signal,
params,
Expand Down
14 changes: 7 additions & 7 deletions x-pack/plugins/cases/public/api/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ import {
} from '../../common/utils/attachments';
import type {
CasesFindResponse,
CaseResponse,
Case,
CaseUserActionsResponse,
CommentRequest,
CommentResponse,
CaseResolveResponse,
CasesResponse,
Cases,
} from '../../common/api';
import { isCommentUserAction } from '../../common/utils/user_actions';
import type { Cases, Case, Comment, ResolvedCase } from '../containers/types';
import type { CasesUI, CaseUI, Comment, ResolvedCase } from '../containers/types';

export const convertArrayToCamelCase = (arrayOfSnakes: unknown[]): unknown[] =>
arrayOfSnakes.reduce((acc: unknown[], value) => {
Expand All @@ -46,15 +46,15 @@ export const convertToCamelCase = <T, U extends {}>(obj: T): U =>
return acc;
}, {} as U);

export const convertCaseToCamelCase = (theCase: CaseResponse): Case => {
export const convertCaseToCamelCase = (theCase: Case): CaseUI => {
const { comments, ...restCase } = theCase;
return {
...convertToCamelCase<CaseResponse, Case>(restCase),
...convertToCamelCase<Case, CaseUI>(restCase),
...(comments != null ? { comments: convertAttachmentsToCamelCase(comments) } : {}),
};
};

export const convertCasesToCamelCase = (cases: CasesResponse): Case[] =>
export const convertCasesToCamelCase = (cases: Cases): CaseUI[] =>
cases.map(convertCaseToCamelCase);

export const convertCaseResolveToCamelCase = (res: CaseResolveResponse): ResolvedCase => {
Expand Down Expand Up @@ -113,7 +113,7 @@ const convertAttachmentToCamelExceptProperty = (
} as Comment;
};

export const convertAllCasesToCamel = (snakeCases: CasesFindResponse): Cases => ({
export const convertAllCasesToCamel = (snakeCases: CasesFindResponse): CasesUI => ({
cases: convertCasesToCamelCase(snakeCases.cases),
countOpenCases: snakeCases.count_open_cases,
countInProgressCases: snakeCases.count_in_progress_cases,
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/cases/public/client/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import type {
CasesMetricsRequest,
} from '../../../common/api';
import { getCasesFromAlertsUrl } from '../../../common/api';
import type { Cases, CasesStatus, CasesMetrics } from '../../../common/ui';
import type { CasesUI, CasesStatus, CasesMetrics } from '../../../common/ui';
import { bulkGetCases, getCases, getCasesMetrics, getCasesStatus } from '../../api';
import type { CasesUiStart } from '../../types';

Expand All @@ -26,7 +26,7 @@ export const createClientAPI = ({ http }: { http: HttpStart }): CasesUiStart['ap
): Promise<CasesByAlertId> =>
http.get<CasesByAlertId>(getCasesFromAlertsUrl(alertId), { query }),
cases: {
find: (query: CasesFindRequest, signal?: AbortSignal): Promise<Cases> =>
find: (query: CasesFindRequest, signal?: AbortSignal): Promise<CasesUI> =>
getCases({ http, query, signal }),
getCasesStatus: (query: CasesStatusRequest, signal?: AbortSignal): Promise<CasesStatus> =>
getCasesStatus({ http, query, signal }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type {
CommentRequestExternalReferenceType,
CommentRequestPersistableStateType,
} from '../../../common/api';
import type { Case } from '../../containers/types';
import type { CaseUI } from '../../containers/types';

export enum AttachmentActionType {
BUTTON = 'button',
Expand Down Expand Up @@ -48,7 +48,7 @@ export interface AttachmentViewObject<Props = {}> {
}

export interface CommonAttachmentViewProps {
caseData: Pick<Case, 'id' | 'title'>;
caseData: Pick<CaseUI, 'id' | 'title'>;
}

export interface ExternalReferenceAttachmentViewProps extends CommonAttachmentViewProps {
Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/cases/public/common/use_cases_toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import React from 'react';
import styled from 'styled-components';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { isValidOwner } from '../../common/utils/owner';
import type { Case } from '../../common';
import type { CaseUI } from '../../common';
import { CommentType } from '../../common';
import { useKibana, useToasts } from './lib/kibana';
import { generateCaseViewPath } from './navigation';
Expand Down Expand Up @@ -61,7 +61,7 @@ function getToastTitle({
title,
attachments,
}: {
theCase: Case;
theCase: CaseUI;
title?: string;
attachments?: CaseAttachmentsWithoutOwner;
}): string {
Expand All @@ -82,7 +82,7 @@ function getToastContent({
content,
attachments,
}: {
theCase: Case;
theCase: CaseUI;
content?: string;
attachments?: CaseAttachmentsWithoutOwner;
}): string | undefined {
Expand Down Expand Up @@ -131,7 +131,7 @@ export const useCasesToast = () => {
title,
content,
}: {
theCase: Case;
theCase: CaseUI;
attachments?: CaseAttachmentsWithoutOwner;
title?: string;
content?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ import {
EuiTitle,
} from '@elastic/eui';

import type { Case } from '../../../../common';
import type { CaseUI } from '../../../../common';
import { EditAssigneesSelectable } from './edit_assignees_selectable';
import * as i18n from './translations';
import type { ItemsSelectionState } from '../types';

interface Props {
selectedCases: Case[];
selectedCases: CaseUI[];
onClose: () => void;
onSaveAssignees: (args: ItemsSelectionState) => void;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { getUserDisplayName } from '@kbn/user-profile-components';
import { useBulkGetUserProfiles } from '../../../containers/user_profiles/use_bulk_get_user_profiles';
import { useIsUserTyping } from '../../../common/use_is_user_typing';
import { useSuggestUserProfiles } from '../../../containers/user_profiles/use_suggest_user_profiles';
import type { Case } from '../../../../common';
import type { CaseUI } from '../../../../common';
import * as i18n from './translations';
import { useItemsState } from '../use_items_state';
import type { ItemSelectableOption, ItemsSelectionState } from '../types';
Expand All @@ -38,7 +38,7 @@ import { SmallUserAvatar } from '../../user_profiles/small_user_avatar';
import { NoSelectedAssignees } from './no_selected_assignees';

interface Props {
selectedCases: Case[];
selectedCases: CaseUI[];
onChangeAssignees: (args: ItemsSelectionState) => void;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@

import { EuiIcon } from '@elastic/eui';
import React from 'react';
import type { Case } from '../../../../common';
import type { CaseUI } from '../../../../common';
import type { UseActionProps } from '../types';
import { useItemsAction } from '../use_items_action';
import * as i18n from './translations';

export const useAssigneesAction = ({ onAction, onActionSuccess, isDisabled }: UseActionProps) => {
const { isFlyoutOpen, onFlyoutClosed, onSaveItems, openFlyout, isActionDisabled } =
useItemsAction<Case['assignees']>({
useItemsAction<CaseUI['assignees']>({
fieldKey: 'assignees',
isDisabled,
onAction,
Expand All @@ -27,7 +27,7 @@ export const useAssigneesAction = ({ onAction, onActionSuccess, isDisabled }: Us
})),
});

const getAction = (selectedCases: Case[]) => {
const getAction = (selectedCases: CaseUI[]) => {
return {
name: i18n.EDIT_ASSIGNEES,
onClick: () => openFlyout(selectedCases),
Expand Down
Loading

0 comments on commit 6d5e245

Please sign in to comment.