mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
# Backport This will backport the following commits from `main` to `8.8`: - [[Cases] Fix lens visualization in comment and description markdown (#155897)](https://github.com/elastic/kibana/pull/155897) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Janki Salvi","email":"117571355+js-jankisalvi@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-04-28T15:21:00Z","message":"[Cases] Fix lens visualization in comment and description markdown (#155897)\n\n## Summary\r\n\r\nThis PR fixes issues with lens visualization in case view page for\r\ncomment and description.\r\n\r\nFixes: #155631\r\n\r\n**Description:**\r\n\r\n\r\n234858215
-feaac6c7-5579-4a00-bb97-00e0b23f5cfe.mov\r\n\r\n### Checklist\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n**Flakey Test runner:**\r\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2182\r\n\r\nNext one after update:\r\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2183\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"0c0e02277f6c0d52dd4906e7421edcbd4c0dd962","branchLabelMapping":{"^v8.9.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:skip","Team:ResponseOps","Feature:Cases","v8.7.0","v8.8.0","v8.9.0"],"number":155897,"url":"https://github.com/elastic/kibana/pull/155897","mergeCommit":{"message":"[Cases] Fix lens visualization in comment and description markdown (#155897)\n\n## Summary\r\n\r\nThis PR fixes issues with lens visualization in case view page for\r\ncomment and description.\r\n\r\nFixes: #155631\r\n\r\n**Description:**\r\n\r\n\r\n234858215
-feaac6c7-5579-4a00-bb97-00e0b23f5cfe.mov\r\n\r\n### Checklist\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n**Flakey Test runner:**\r\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2182\r\n\r\nNext one after update:\r\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2183\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"0c0e02277f6c0d52dd4906e7421edcbd4c0dd962"}},"sourceBranch":"main","suggestedTargetBranches":["8.7","8.8"],"targetPullRequestStates":[{"branch":"8.7","label":"v8.7.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.8","label":"v8.8.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.9.0","labelRegex":"^v8.9.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/155897","number":155897,"mergeCommit":{"message":"[Cases] Fix lens visualization in comment and description markdown (#155897)\n\n## Summary\r\n\r\nThis PR fixes issues with lens visualization in case view page for\r\ncomment and description.\r\n\r\nFixes: #155631\r\n\r\n**Description:**\r\n\r\n\r\n234858215
-feaac6c7-5579-4a00-bb97-00e0b23f5cfe.mov\r\n\r\n### Checklist\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n**Flakey Test runner:**\r\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2182\r\n\r\nNext one after update:\r\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2183\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"0c0e02277f6c0d52dd4906e7421edcbd4c0dd962"}}]}] BACKPORT--> Co-authored-by: Janki Salvi <117571355+js-jankisalvi@users.noreply.github.com> Co-authored-by: Lisa Cawley <lcawley@elastic.co>
This commit is contained in:
parent
edd78ba55e
commit
52c79188e3
8 changed files with 169 additions and 55 deletions
|
@ -17,8 +17,6 @@ import { schema } from './schema';
|
|||
import type { AppMockRenderer } from '../../common/mock';
|
||||
import { createAppMockRenderer } from '../../common/mock';
|
||||
|
||||
jest.mock('../markdown_editor/plugins/lens/use_lens_draft_comment');
|
||||
|
||||
describe('Description', () => {
|
||||
let globalForm: FormHook;
|
||||
let appMockRender: AppMockRenderer;
|
||||
|
|
|
@ -5,14 +5,9 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { memo, useEffect, useRef } from 'react';
|
||||
import {
|
||||
UseField,
|
||||
useFormContext,
|
||||
useFormData,
|
||||
} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
|
||||
import React, { memo, useRef } from 'react';
|
||||
import { UseField, useFormData } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
|
||||
import { MarkdownEditorForm } from '../markdown_editor';
|
||||
import { useLensDraftComment } from '../markdown_editor/plugins/lens/use_lens_draft_comment';
|
||||
import { ID as LensPluginId } from '../markdown_editor/plugins/lens/constants';
|
||||
|
||||
interface Props {
|
||||
|
@ -23,33 +18,10 @@ interface Props {
|
|||
export const fieldName = 'description';
|
||||
|
||||
const DescriptionComponent: React.FC<Props> = ({ isLoading, draftStorageKey }) => {
|
||||
const { draftComment, hasIncomingLensState, openLensModal, clearDraftComment } =
|
||||
useLensDraftComment();
|
||||
const { setFieldValue } = useFormContext();
|
||||
const [{ title, tags }] = useFormData({ watch: ['title', 'tags'] });
|
||||
const editorRef = useRef<Record<string, unknown>>();
|
||||
const disabledUiPlugins = [LensPluginId];
|
||||
|
||||
useEffect(() => {
|
||||
if (draftComment?.commentId === fieldName && editorRef.current) {
|
||||
setFieldValue(fieldName, draftComment.comment);
|
||||
|
||||
if (draftComment.caseTitle) {
|
||||
setFieldValue('title', draftComment.caseTitle);
|
||||
}
|
||||
|
||||
if (draftComment.caseTags && draftComment.caseTags.length > 0) {
|
||||
setFieldValue('tags', draftComment.caseTags);
|
||||
}
|
||||
|
||||
if (hasIncomingLensState) {
|
||||
openLensModal({ editorRef: editorRef.current });
|
||||
} else {
|
||||
clearDraftComment();
|
||||
}
|
||||
}
|
||||
}, [clearDraftComment, draftComment, hasIncomingLensState, openLensModal, setFieldValue]);
|
||||
|
||||
return (
|
||||
<UseField
|
||||
path={fieldName}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useRef, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { css } from '@emotion/react';
|
||||
import {
|
||||
|
@ -21,12 +21,17 @@ import { getMarkdownEditorStorageKey } from '../markdown_editor/utils';
|
|||
import * as i18n from '../user_actions/translations';
|
||||
import { useCasesContext } from '../cases_context/use_cases_context';
|
||||
import { useLensDraftComment } from '../markdown_editor/plugins/lens/use_lens_draft_comment';
|
||||
import type { EditableMarkdownRefObject, EuiMarkdownEditorRef } from '../markdown_editor';
|
||||
import { EditableMarkdown, ScrollableMarkdown } from '../markdown_editor';
|
||||
import type { Case } from '../../containers/types';
|
||||
import type { OnUpdateFields } from '../case_view/types';
|
||||
import { schema } from './schema';
|
||||
|
||||
const DESCRIPTION_ID = 'description';
|
||||
|
||||
export interface DescriptionMarkdownRefObject extends EditableMarkdownRefObject {
|
||||
editor: EuiMarkdownEditorRef | null;
|
||||
}
|
||||
export interface DescriptionProps {
|
||||
caseData: Case;
|
||||
isLoadingDescription: boolean;
|
||||
|
@ -73,6 +78,13 @@ const getDraftDescription = (
|
|||
return sessionStorage.getItem(draftStorageKey);
|
||||
};
|
||||
|
||||
const isCommentRef = (
|
||||
ref: EditableMarkdownRefObject | null | undefined
|
||||
): ref is EditableMarkdownRefObject => {
|
||||
const commentRef = ref as EditableMarkdownRefObject;
|
||||
return commentRef?.setComment != null;
|
||||
};
|
||||
|
||||
export const Description = ({
|
||||
caseData,
|
||||
onUpdateField,
|
||||
|
@ -82,6 +94,8 @@ export const Description = ({
|
|||
const [isEditable, setIsEditable] = useState<boolean>(false);
|
||||
|
||||
const descriptionRef = useRef(null);
|
||||
const descriptionMarkdownRef = useRef<DescriptionMarkdownRefObject | null>(null);
|
||||
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const { appId, permissions } = useCasesContext();
|
||||
|
||||
|
@ -89,6 +103,7 @@ export const Description = ({
|
|||
clearDraftComment: clearLensDraftComment,
|
||||
draftComment: lensDraftComment,
|
||||
hasIncomingLensState,
|
||||
openLensModal,
|
||||
} = useLensDraftComment();
|
||||
|
||||
const handleOnChangeEditable = useCallback(() => {
|
||||
|
@ -117,6 +132,22 @@ export const Description = ({
|
|||
setIsEditable(true);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isCommentRef(descriptionMarkdownRef.current) &&
|
||||
descriptionMarkdownRef.current.editor?.textarea &&
|
||||
lensDraftComment &&
|
||||
lensDraftComment.commentId === DESCRIPTION_ID
|
||||
) {
|
||||
descriptionMarkdownRef.current.setComment(lensDraftComment.comment);
|
||||
if (hasIncomingLensState) {
|
||||
openLensModal({ editorRef: descriptionMarkdownRef.current.editor });
|
||||
} else {
|
||||
clearLensDraftComment();
|
||||
}
|
||||
}
|
||||
}, [clearLensDraftComment, lensDraftComment, hasIncomingLensState, openLensModal]);
|
||||
|
||||
const hasUnsavedChanges =
|
||||
draftDescription && draftDescription !== caseData.description && !isLoadingDescription;
|
||||
|
||||
|
@ -131,6 +162,7 @@ export const Description = ({
|
|||
editorRef={descriptionRef}
|
||||
fieldName="content"
|
||||
formSchema={schema}
|
||||
ref={descriptionMarkdownRef}
|
||||
/>
|
||||
) : (
|
||||
<Panel hasShadow={false} hasBorder={true} data-test-subj="description">
|
||||
|
|
|
@ -46,10 +46,17 @@ const MyEuiCommentFooter = styled(EuiText)`
|
|||
`}
|
||||
`;
|
||||
|
||||
const hasDraftComment = (appId = '', caseId: string, commentId: string): boolean => {
|
||||
const draftStorageKey = getMarkdownEditorStorageKey(appId, caseId, commentId);
|
||||
const hasDraftComment = (
|
||||
applicationId = '',
|
||||
caseId: string,
|
||||
commentId: string,
|
||||
comment: string
|
||||
): boolean => {
|
||||
const draftStorageKey = getMarkdownEditorStorageKey(applicationId, caseId, commentId);
|
||||
|
||||
return Boolean(sessionStorage.getItem(draftStorageKey));
|
||||
const sessionValue = sessionStorage.getItem(draftStorageKey);
|
||||
|
||||
return Boolean(sessionValue && sessionValue !== comment);
|
||||
};
|
||||
|
||||
export const createUserAttachmentUserActionBuilder = ({
|
||||
|
@ -78,7 +85,8 @@ export const createUserAttachmentUserActionBuilder = ({
|
|||
className: classNames('userAction__comment', {
|
||||
outlined,
|
||||
isEdit,
|
||||
draftFooter: !isEdit && !isLoading && hasDraftComment(appId, caseId, comment.id),
|
||||
draftFooter:
|
||||
!isEdit && !isLoading && hasDraftComment(appId, caseId, comment.id, comment.comment),
|
||||
}),
|
||||
children: (
|
||||
<>
|
||||
|
@ -95,7 +103,7 @@ export const createUserAttachmentUserActionBuilder = ({
|
|||
version: comment.version,
|
||||
})}
|
||||
/>
|
||||
{!isEdit && !isLoading && hasDraftComment(appId, caseId, comment.id) ? (
|
||||
{!isEdit && !isLoading && hasDraftComment(appId, caseId, comment.id, comment.comment) ? (
|
||||
<MyEuiCommentFooter>
|
||||
<EuiText color="subdued" size="xs" data-test-subj="user-action-comment-unsaved-draft">
|
||||
{i18n.UNSAVED_DRAFT_COMMENT}
|
||||
|
|
|
@ -37,6 +37,13 @@ const isAddCommentRef = (
|
|||
return commentRef?.addQuote != null;
|
||||
};
|
||||
|
||||
const isSetCommentRef = (
|
||||
ref: AddCommentRefObject | UserActionMarkdownRefObject | null | undefined
|
||||
): ref is AddCommentRefObject => {
|
||||
const commentRef = ref as UserActionMarkdownRefObject;
|
||||
return commentRef?.setComment != null;
|
||||
};
|
||||
|
||||
export const useUserActionsHandler = (): UseUserActionsHandler => {
|
||||
const { detailName: caseId } = useCaseViewParams();
|
||||
const { clearDraftComment, draftComment, hasIncomingLensState, openLensModal } =
|
||||
|
@ -122,7 +129,7 @@ export const useUserActionsHandler = (): UseUserActionsHandler => {
|
|||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (draftComment?.commentId) {
|
||||
if (draftComment?.commentId && draftComment?.commentId !== 'description') {
|
||||
setManageMarkdownEditIds((prevManageMarkdownEditIds) => {
|
||||
if (
|
||||
NEW_COMMENT_ID !== draftComment?.commentId &&
|
||||
|
@ -135,7 +142,7 @@ export const useUserActionsHandler = (): UseUserActionsHandler => {
|
|||
|
||||
const ref = commentRefs?.current?.[draftComment.commentId];
|
||||
|
||||
if (isAddCommentRef(ref) && ref.editor?.textarea) {
|
||||
if (isSetCommentRef(ref) && ref.editor?.textarea) {
|
||||
ref.setComment(draftComment.comment);
|
||||
if (hasIncomingLensState) {
|
||||
openLensModal({ editorRef: ref.editor });
|
||||
|
|
|
@ -41,7 +41,7 @@ export function CasesSingleViewServiceProvider({ getService, getPageObject }: Ft
|
|||
},
|
||||
|
||||
async getCommentCount(): Promise<number> {
|
||||
const commentsContainer = await testSubjects.find('user-actions');
|
||||
const commentsContainer = await testSubjects.find('user-actions-list');
|
||||
const comments = await commentsContainer.findAllByClassName('euiComment');
|
||||
return comments.length - 1; // don't count the element for adding a new comment
|
||||
},
|
||||
|
@ -58,13 +58,22 @@ export function CasesSingleViewServiceProvider({ getService, getPageObject }: Ft
|
|||
});
|
||||
},
|
||||
|
||||
async addVisualization(visName: string) {
|
||||
async addVisualizationToNewComment(visName: string) {
|
||||
// open saved object finder
|
||||
const addCommentElement = await testSubjects.find('add-comment');
|
||||
const addVisualizationButton = await addCommentElement.findByCssSelector(
|
||||
'[data-test-subj="euiMarkdownEditorToolbarButton"][aria-label="Visualization"]'
|
||||
);
|
||||
await addVisualizationButton.click();
|
||||
|
||||
await this.findAndSaveVisualization(visName);
|
||||
|
||||
await testSubjects.existOrFail('cases-app', { timeout: 10 * 1000 });
|
||||
|
||||
await this.submitComment();
|
||||
},
|
||||
|
||||
async findAndSaveVisualization(visName: string) {
|
||||
await testSubjects.existOrFail('savedObjectsFinderTable', { timeout: 10 * 1000 });
|
||||
|
||||
// select visualization
|
||||
|
@ -78,8 +87,6 @@ export function CasesSingleViewServiceProvider({ getService, getPageObject }: Ft
|
|||
|
||||
// save and return to cases app, add comment
|
||||
await lensPage.saveAndReturn();
|
||||
await testSubjects.existOrFail('cases-app', { timeout: 10 * 1000 });
|
||||
await this.submitComment();
|
||||
},
|
||||
|
||||
async openVisualizationButtonTooltip() {
|
||||
|
|
|
@ -272,16 +272,6 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
|
|||
});
|
||||
|
||||
it('shows unsaved comment message when page is refreshed', async () => {
|
||||
const commentArea = await find.byCssSelector(
|
||||
'[data-test-subj="add-comment"] textarea.euiMarkdownEditorTextArea'
|
||||
);
|
||||
await commentArea.focus();
|
||||
await commentArea.type('Test comment from automation');
|
||||
|
||||
await testSubjects.click('submit-comment');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await testSubjects.click('property-actions-user-action-ellipses');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
@ -299,6 +289,8 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
|
|||
await editCommentTextArea.focus();
|
||||
await editCommentTextArea.type('Edited comment');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await browser.refresh();
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
@ -341,6 +333,104 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Lens visualization', () => {
|
||||
before(async () => {
|
||||
await cases.testResources.installKibanaSampleData('logs');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await cases.testResources.removeKibanaSampleData('logs');
|
||||
});
|
||||
|
||||
createOneCaseBeforeDeleteAllAfter(getPageObject, getService);
|
||||
|
||||
it('adds lens visualization in description', async () => {
|
||||
await testSubjects.click('description-edit-icon');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
const editCommentTextArea = await find.byCssSelector(
|
||||
'[data-test-subj*="editable-markdown-form"] textarea.euiMarkdownEditorTextArea'
|
||||
);
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await editCommentTextArea.focus();
|
||||
|
||||
const editableDescription = await testSubjects.find('editable-markdown-form');
|
||||
|
||||
const addVisualizationButton = await editableDescription.findByCssSelector(
|
||||
'[data-test-subj="euiMarkdownEditorToolbarButton"][aria-label="Visualization"]'
|
||||
);
|
||||
await addVisualizationButton.click();
|
||||
|
||||
await cases.singleCase.findAndSaveVisualization('[Logs] Bytes distribution');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await testSubjects.click('editable-save-markdown');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
const description = await find.byCssSelector('[data-test-subj="description"]');
|
||||
|
||||
await description.findByCssSelector('[data-test-subj="xyVisChart"]');
|
||||
});
|
||||
|
||||
it('adds lens visualization in existing comment', async () => {
|
||||
const commentArea = await find.byCssSelector(
|
||||
'[data-test-subj="add-comment"] textarea.euiMarkdownEditorTextArea'
|
||||
);
|
||||
await commentArea.focus();
|
||||
await commentArea.type('Test comment from automation');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await testSubjects.click('submit-comment');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await testSubjects.click('property-actions-user-action-ellipses');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await testSubjects.click('property-actions-user-action-pencil');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
const editComment = await find.byCssSelector('[data-test-subj*="editable-markdown-form"]');
|
||||
|
||||
const addVisualizationButton = await editComment.findByCssSelector(
|
||||
'[data-test-subj="euiMarkdownEditorToolbarButton"][aria-label="Visualization"]'
|
||||
);
|
||||
await addVisualizationButton.click();
|
||||
|
||||
await cases.singleCase.findAndSaveVisualization('[Logs] Bytes distribution');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await testSubjects.click('editable-save-markdown');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
const createdComment = await find.byCssSelector(
|
||||
'[data-test-subj*="comment-create-action"] [data-test-subj="scrollable-markdown"]'
|
||||
);
|
||||
|
||||
await createdComment.findByCssSelector('[data-test-subj="xyVisChart"]');
|
||||
});
|
||||
|
||||
it('adds lens visualization in new comment', async () => {
|
||||
await cases.singleCase.addVisualizationToNewComment('[Logs] Bytes distribution');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
const newComment = await find.byCssSelector('[data-test-subj*="comment-create-action"]');
|
||||
|
||||
await newComment.findByCssSelector('[data-test-subj="xyVisChart"]');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Severity field', () => {
|
||||
createOneCaseBeforeDeleteAllAfter(getPageObject, getService);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
it('cases visualization screenshot', async () => {
|
||||
await cases.navigation.navigateToApp();
|
||||
await cases.navigation.navigateToSingleCase('cases', CASE_ID);
|
||||
await cases.singleCase.addVisualization('[Logs] Bytes distribution');
|
||||
await cases.singleCase.addVisualizationToNewComment('[Logs] Bytes distribution');
|
||||
|
||||
await cases.singleCase.openVisualizationButtonTooltip();
|
||||
await commonScreenshots.takeScreenshot(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue