Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions x-pack/plugins/cases/common/api/cases/comment/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ export const FileAttachmentMetadataRt = rt.strict({

export type FileAttachmentMetadata = rt.TypeOf<typeof FileAttachmentMetadataRt>;

export const FILE_ATTACHMENT_TYPE = '.files';

const MIN_DELETE_IDS = 1;

export const BulkDeleteFileAttachmentsRequestRt = rt.strict({
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/cases/common/constants/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* 2.0.
*/

export const FILE_ATTACHMENT_TYPE = '.files';

export const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 MiB
export const MAX_IMAGE_FILE_SIZE = 10 * 1024 * 1024; // 10 MiB
export const MAX_FILES_PER_CASE = 100;
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/cases/common/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { CasesFeaturesAllRequired } from '../ui/types';
export * from './owners';
export * from './files';
export * from './application';
export { LENS_ATTACHMENT_TYPE } from './visualizations';

export const DEFAULT_DATE_FORMAT = 'dateFormat' as const;
export const DEFAULT_DATE_FORMAT_TZ = 'dateFormat:tz' as const;
Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/cases/common/constants/visualizations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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 const LENS_ATTACHMENT_TYPE = '.lens';
1 change: 1 addition & 0 deletions x-pack/plugins/cases/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export {
READ_CASES_CAPABILITY,
UPDATE_CASES_CAPABILITY,
INTERNAL_BULK_GET_CASES_URL,
LENS_ATTACHMENT_TYPE,
} from './constants';

export {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ export enum AttachmentActionType {

interface BaseAttachmentAction {
type: AttachmentActionType;
label: string;
isPrimary?: boolean;
disabled?: boolean;
}

interface ButtonAttachmentAction extends BaseAttachmentAction {
label: string;
type: AttachmentActionType.BUTTON;
onClick: () => void;
iconType: string;
Expand All @@ -48,6 +48,7 @@ export interface AttachmentViewObject<Props = {}> {
}

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

Expand All @@ -67,7 +68,6 @@ export interface AttachmentType<Props> {
displayName: string;
getAttachmentViewObject: (props: Props) => AttachmentViewObject<Props>;
getAttachmentRemovalObject?: (props: Props) => Pick<AttachmentViewObject<Props>, 'event'>;
hideDefaultActions?: boolean;
}

export type ExternalReferenceAttachmentType = AttachmentType<ExternalReferenceAttachmentViewProps>;
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/cases/public/components/files/add_file.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import type { UploadedFile } from '@kbn/shared-ux-file-upload/src/file_upload';
import { FILE_SO_TYPE } from '@kbn/files-plugin/common';
import { FileUpload } from '@kbn/shared-ux-file-upload';

import { FILE_ATTACHMENT_TYPE } from '../../../common/constants';
import { constructFileKindIdByOwner } from '../../../common/files';
import type { Owner } from '../../../common/constants/types';

import { CommentType, ExternalReferenceStorageType } from '../../../common';
import { FILE_ATTACHMENT_TYPE } from '../../../common/api';
import { useCasesToast } from '../../common/use_cases_toast';
import { useCreateAttachments } from '../../containers/use_create_attachments';
import { useCasesContext } from '../cases_context/use_cases_context';
Expand Down
34 changes: 15 additions & 19 deletions x-pack/plugins/cases/public/components/files/file_type.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@
* 2.0.
*/
import type { JsonValue } from '@kbn/utility-types';

import userEvent from '@testing-library/user-event';
import { screen } from '@testing-library/react';

import type { ExternalReferenceAttachmentViewProps } from '../../client/attachment_framework/types';
import type { AppMockRenderer } from '../../common/mock';

import { AttachmentActionType } from '../../client/attachment_framework/types';
import { FILE_ATTACHMENT_TYPE } from '../../../common/api';
import { createAppMockRenderer } from '../../common/mock';
import { basicCase, basicFileMock } from '../../containers/mock';
import { getFileType } from './file_type';
import userEvent from '@testing-library/user-event';
import { FILE_ATTACHMENT_TYPE } from '../../../common/constants';

describe('getFileType', () => {
const fileType = getFileType();
Expand All @@ -25,7 +24,7 @@ describe('getFileType', () => {
expect(fileType).toStrictEqual({
id: FILE_ATTACHMENT_TYPE,
icon: 'document',
displayName: 'File Attachment Type',
displayName: 'Files',
getAttachmentViewObject: expect.any(Function),
getAttachmentRemovalObject: expect.any(Function),
});
Expand All @@ -34,11 +33,12 @@ describe('getFileType', () => {
describe('getFileAttachmentViewObject', () => {
let appMockRender: AppMockRenderer;

const attachmentViewProps = {
const attachmentViewProps: ExternalReferenceAttachmentViewProps = {
externalReferenceId: basicFileMock.id,
// @ts-expect-error: files is a proper JSON
externalReferenceMetadata: { files: [basicFileMock] },
caseData: { title: basicCase.title, id: basicCase.id },
} as unknown as ExternalReferenceAttachmentViewProps;
};

beforeEach(() => {
jest.clearAllMocks();
Expand All @@ -47,7 +47,7 @@ describe('getFileType', () => {
it('event renders a clickable name if the file is an image', async () => {
appMockRender = createAppMockRenderer();

// @ts-ignore
// @ts-expect-error: event is defined
appMockRender.render(fileType.getAttachmentViewObject({ ...attachmentViewProps }).event);

expect(await screen.findByText('my-super-cool-screenshot.png')).toBeInTheDocument();
Expand All @@ -57,7 +57,7 @@ describe('getFileType', () => {
it('clicking the name rendered in event opens the file preview', async () => {
appMockRender = createAppMockRenderer();

// @ts-ignore
// @ts-expect-error: event is a React element
appMockRender.render(fileType.getAttachmentViewObject({ ...attachmentViewProps }).event);

userEvent.click(await screen.findByText('my-super-cool-screenshot.png'));
Expand All @@ -71,18 +71,17 @@ describe('getFileType', () => {

expect(attachmentViewObject).not.toBeUndefined();

// @ts-ignore
// @ts-expect-error: object is defined
const actions = attachmentViewObject.getActions();

expect(actions.length).toBe(2);
expect(actions[0]).toStrictEqual({
type: AttachmentActionType.CUSTOM,
isPrimary: false,
label: 'Download file',
render: expect.any(Function),
});

// @ts-ignore
// @ts-expect-error: render exists on CustomAttachmentAction
appMockRender.render(actions[0].render());

expect(await screen.findByTestId('cases-files-download-button')).toBeInTheDocument();
Expand All @@ -95,18 +94,17 @@ describe('getFileType', () => {

expect(attachmentViewObject).not.toBeUndefined();

// @ts-ignore
// @ts-expect-error: object is defined
const actions = attachmentViewObject.getActions();

expect(actions.length).toBe(2);
expect(actions[1]).toStrictEqual({
type: AttachmentActionType.CUSTOM,
isPrimary: false,
label: 'Delete file',
render: expect.any(Function),
});

// @ts-ignore
// @ts-expect-error: render exists on CustomAttachmentAction
appMockRender.render(actions[1].render());

expect(await screen.findByTestId('cases-files-delete-button')).toBeInTheDocument();
Expand All @@ -119,18 +117,17 @@ describe('getFileType', () => {

expect(attachmentViewObject).not.toBeUndefined();

// @ts-ignore
// @ts-expect-error: object is defined
const actions = attachmentViewObject.getActions();

expect(actions.length).toBe(2);
expect(actions[1]).toStrictEqual({
type: AttachmentActionType.CUSTOM,
isPrimary: false,
label: 'Delete file',
render: expect.any(Function),
});

// @ts-ignore
// @ts-expect-error: render exists on CustomAttachmentAction
appMockRender.render(actions[1].render());

const deleteButton = await screen.findByTestId('cases-files-delete-button');
Expand All @@ -149,7 +146,6 @@ describe('getFileType', () => {
event: 'added an unknown file',
hideDefaultActions: true,
timelineAvatar: 'document',
type: 'regular',
getActions: expect.any(Function),
});
});
Expand Down Expand Up @@ -188,7 +184,7 @@ describe('getFileType', () => {

describe('getFileAttachmentRemovalObject', () => {
it('event renders the right message', async () => {
// @ts-ignore
// @ts-expect-error: object is defined
expect(fileType.getAttachmentRemovalObject().event).toBe('removed file');
});
});
Expand Down
15 changes: 7 additions & 8 deletions x-pack/plugins/cases/public/components/files/file_type.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
import React, { Suspense, lazy } from 'react';

import { EuiLoadingSpinner } from '@elastic/eui';
import { FILE_ATTACHMENT_TYPE } from '../../../common/constants';
import type {
AttachmentViewObject,
ExternalReferenceAttachmentType,
ExternalReferenceAttachmentViewProps,
} from '../../client/attachment_framework/types';

import { AttachmentActionType } from '../../client/attachment_framework/types';
import { FILE_ATTACHMENT_TYPE } from '../../../common/api';
import * as i18n from './translations';
import { isImage, isValidFileExternalReferenceMetadata } from './utils';

Expand Down Expand Up @@ -47,31 +48,29 @@ const getFileAttachmentActions = ({ caseId, fileId }: { caseId: string; fileId:
{
type: AttachmentActionType.CUSTOM as const,
render: () => getFileDownloadButton(fileId),
label: i18n.DOWNLOAD_FILE,
isPrimary: false,
},
{
type: AttachmentActionType.CUSTOM as const,
render: () => getFileDeleteButton(caseId, fileId),
label: i18n.DELETE_FILE,
isPrimary: false,
},
];

const getFileAttachmentViewObject = (props: ExternalReferenceAttachmentViewProps) => {
const getFileAttachmentViewObject = (
props: ExternalReferenceAttachmentViewProps
): AttachmentViewObject<ExternalReferenceAttachmentViewProps> => {
const caseId = props.caseData.id;
const fileId = props.externalReferenceId;

if (!isValidFileExternalReferenceMetadata(props.externalReferenceMetadata)) {
return {
type: 'regular',
event: i18n.ADDED_UNKNOWN_FILE,
timelineAvatar: 'document',
getActions: () => [
{
type: AttachmentActionType.CUSTOM as const,
type: AttachmentActionType.CUSTOM,
render: () => getFileDeleteButton(caseId, fileId),
label: i18n.DELETE_FILE,
isPrimary: false,
},
],
Expand Down Expand Up @@ -100,7 +99,7 @@ const getFileAttachmentViewObject = (props: ExternalReferenceAttachmentViewProps
export const getFileType = (): ExternalReferenceAttachmentType => ({
id: FILE_ATTACHMENT_TYPE,
icon: 'document',
displayName: 'File Attachment Type',
displayName: 'Files',
getAttachmentViewObject: getFileAttachmentViewObject,
getAttachmentRemovalObject: () => ({ event: i18n.REMOVED_FILE }),
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { plugin } from './plugin';
import { LensParser } from './parser';
import { LensMarkDownRenderer } from './processor';
import { VISUALIZATION } from './translations';
import { LensRenderer } from '../../../visualizations/lens_renderer';

export { plugin, LensParser as parser, LensMarkDownRenderer as renderer, VISUALIZATION };
export { plugin, LensParser as parser, LensRenderer as renderer, VISUALIZATION };
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
*/

import { useCallback } from 'react';
import { i18n } from '@kbn/i18n';

import type { TypedLensByValueInput } from '@kbn/lens-plugin/public';

import { AttachmentActionType } from '../../../../client/attachment_framework/types';
Expand All @@ -16,6 +14,7 @@ import {
parseCommentString,
getLensVisualizations,
} from '../../../../../common/utils/markdown_plugins/utils';
import { OPEN_IN_VISUALIZATION } from '../../../visualizations/translations';

export const useLensOpenVisualization = ({ comment }: { comment: string }) => {
const parsedComment = parseCommentString(comment);
Expand Down Expand Up @@ -46,12 +45,7 @@ export const useLensOpenVisualization = ({ comment }: { comment: string }) => {
: {
type: AttachmentActionType.BUTTON as const,
iconType: 'lensApp',
label: i18n.translate(
'xpack.cases.markdownEditor.plugins.lens.openVisualizationButtonLabel',
{
defaultMessage: 'Open visualization',
}
),
label: OPEN_IN_VISUALIZATION,
onClick: handleClick,
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export const PropertyActions = React.memo<PropertyActionsProps>(
gutterSize="none"
>
{propertyActions.map((action, key) => (
<EuiFlexItem grow={false} key={`${action.label}${key}`}>
<EuiFlexItem grow={false} key={`${action.type}-${key}`}>
<span>
{(action.type === AttachmentActionType.BUTTON && (
<PropertyActionButton
Expand Down
Loading