= ({ theCase }) => {
+ const { hasDataToPush, isLoading } = useGetCaseUserActions(theCase.id);
+ const handleRenderDataToPush = useCallback(
+ () =>
+ isLoading ? (
+
+ ) : (
+
+
+ {theCase.externalService?.externalTitle}
+
+ {hasDataToPush ? i18n.REQUIRES_UPDATE : i18n.UP_TO_DATE}
+
+ ),
+ [hasDataToPush, isLoading, theCase.externalService]
+ );
+ if (theCase.externalService !== null) {
+ return handleRenderDataToPush();
+ }
+ return renderStringField(i18n.NOT_PUSHED, `case-table-column-external-notPushed`);
+};
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx
index cbb9ddae22d04..27316ab8427cb 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx
@@ -109,19 +109,21 @@ export const AllCases = React.memo(() => {
const { dispatchResetIsUpdated, isUpdated, updateBulkStatus } = useUpdateCases();
+ const refreshCases = useCallback(() => {
+ refetchCases(filterOptions, queryParams);
+ fetchCasesStatus();
+ }, [filterOptions, queryParams]);
+
useEffect(() => {
if (isDeleted) {
- refetchCases(filterOptions, queryParams);
- fetchCasesStatus();
+ refreshCases();
dispatchResetIsDeleted();
}
if (isUpdated) {
- refetchCases(filterOptions, queryParams);
- fetchCasesStatus();
+ refreshCases();
dispatchResetIsUpdated();
}
- }, [isDeleted, isUpdated, filterOptions, queryParams]);
-
+ }, [isDeleted, isUpdated]);
const [deleteThisCase, setDeleteThisCase] = useState({
title: '',
id: '',
@@ -327,6 +329,10 @@ export const AllCases = React.memo(() => {
>
{i18n.BULK_ACTIONS}
+
+
+ {i18n.REFRESH}
+
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts
index b18134f6d093e..e8459454576e3 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts
@@ -62,3 +62,17 @@ export const CLOSED = i18n.translate('xpack.siem.case.caseTable.closed', {
export const DELETE = i18n.translate('xpack.siem.case.caseTable.delete', {
defaultMessage: 'Delete',
});
+export const REQUIRES_UPDATE = i18n.translate('xpack.siem.case.caseTable.requiresUpdate', {
+ defaultMessage: ' requires update',
+});
+
+export const UP_TO_DATE = i18n.translate('xpack.siem.case.caseTable.upToDate', {
+ defaultMessage: ' is up to date',
+});
+export const NOT_PUSHED = i18n.translate('xpack.siem.case.caseTable.notPushed', {
+ defaultMessage: 'Not pushed',
+});
+
+export const REFRESH = i18n.translate('xpack.siem.case.caseTable.refreshTitle', {
+ defaultMessage: 'Refresh',
+});
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts
index beba80ccd934c..c081567e3be72 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts
@@ -59,6 +59,10 @@ export const EDIT_DESCRIPTION = i18n.translate('xpack.siem.case.caseView.edit.de
defaultMessage: 'Edit description',
});
+export const QUOTE = i18n.translate('xpack.siem.case.caseView.edit.quote', {
+ defaultMessage: 'Quote',
+});
+
export const EDIT_COMMENT = i18n.translate('xpack.siem.case.caseView.edit.comment', {
defaultMessage: 'Edit comment',
});
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/property_actions/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/property_actions/index.tsx
index 01ccf3c510b60..25332982dca1a 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/property_actions/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/property_actions/index.tsx
@@ -45,7 +45,7 @@ export const PropertyActions = React.memo(({ propertyActio
const onClosePopover = useCallback((cb?: () => void) => {
setShowActions(false);
- if (cb) {
+ if (cb != null) {
cb();
}
}, []);
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx
index 8b77186f76f77..d8b9ac115426a 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx
@@ -57,6 +57,7 @@ export const UserActionTree = React.memo(
);
const currentUser = useCurrentUser();
const [manageMarkdownEditIds, setManangeMardownEditIds] = useState([]);
+ const [insertQuote, setInsertQuote] = useState(null);
const handleManageMarkdownEditId = useCallback(
(id: string) => {
@@ -92,6 +93,9 @@ export const UserActionTree = React.memo(
top: y,
behavior: 'smooth',
});
+ if (id === 'add-comment') {
+ moveToTarget.getElementsByTagName('textarea')[0].focus();
+ }
}
window.clearTimeout(handlerTimeoutId.current);
setSelectedOutlineCommentId(id);
@@ -103,6 +107,15 @@ export const UserActionTree = React.memo(
[handlerTimeoutId.current]
);
+ const handleManageQuote = useCallback(
+ (quote: string) => {
+ const addCarrots = quote.replace(new RegExp('\r?\n', 'g'), ' \n> ');
+ setInsertQuote(`> ${addCarrots} \n`);
+ handleOutlineComment('add-comment');
+ },
+ [handleOutlineComment]
+ );
+
const handleUpdate = useCallback(
(comment: Comment) => {
addPostedComment(comment);
@@ -131,12 +144,13 @@ export const UserActionTree = React.memo(
() => (
),
- [caseData.id, handleUpdate]
+ [caseData.id, handleUpdate, insertQuote]
);
useEffect(() => {
@@ -156,10 +170,12 @@ export const UserActionTree = React.memo(
isEditable={manageMarkdownEditIds.includes(DESCRIPTION_ID)}
isLoading={isLoadingDescription}
labelEditAction={i18n.EDIT_DESCRIPTION}
+ labelQuoteAction={i18n.QUOTE}
labelTitle={<>{i18n.ADDED_DESCRIPTION}>}
fullName={caseData.createdBy.fullName ?? caseData.createdBy.username}
markdown={MarkdownDescription}
onEdit={handleManageMarkdownEditId.bind(null, DESCRIPTION_ID)}
+ onQuote={handleManageQuote.bind(null, caseData.description)}
userName={caseData.createdBy.username}
/>
@@ -176,6 +192,7 @@ export const UserActionTree = React.memo(
isEditable={manageMarkdownEditIds.includes(comment.id)}
isLoading={isLoadingIds.includes(comment.id)}
labelEditAction={i18n.EDIT_COMMENT}
+ labelQuoteAction={i18n.QUOTE}
labelTitle={<>{i18n.ADDED_COMMENT}>}
fullName={comment.createdBy.fullName ?? comment.createdBy.username}
markdown={
@@ -188,6 +205,7 @@ export const UserActionTree = React.memo(
/>
}
onEdit={handleManageMarkdownEditId.bind(null, comment.id)}
+ onQuote={handleManageQuote.bind(null, comment.comment)}
outlineComment={handleOutlineComment}
userName={comment.createdBy.username}
updatedAt={comment.updatedAt}
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx
index 10a7c56e2eb2d..c1dbe3b5fdbfa 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx
@@ -25,11 +25,13 @@ interface UserActionItemProps {
isEditable: boolean;
isLoading: boolean;
labelEditAction?: string;
+ labelQuoteAction?: string;
labelTitle?: JSX.Element;
linkId?: string | null;
fullName: string;
markdown?: React.ReactNode;
onEdit?: (id: string) => void;
+ onQuote?: (id: string) => void;
userName: string;
updatedAt?: string | null;
outlineComment?: (id: string) => void;
@@ -113,11 +115,13 @@ export const UserActionItem = ({
isEditable,
isLoading,
labelEditAction,
+ labelQuoteAction,
labelTitle,
linkId,
fullName,
markdown,
onEdit,
+ onQuote,
outlineComment,
showBottomFooter,
showTopFooter,
@@ -147,11 +151,13 @@ export const UserActionItem = ({
id={id}
isLoading={isLoading}
labelEditAction={labelEditAction}
+ labelQuoteAction={labelQuoteAction}
labelTitle={labelTitle ?? <>>}
linkId={linkId}
userName={userName}
updatedAt={updatedAt}
onEdit={onEdit}
+ onQuote={onQuote}
outlineComment={outlineComment}
/>
{markdown}
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx
index 6ca81667d9712..391f54da7e972 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx
@@ -30,11 +30,13 @@ interface UserActionTitleProps {
id: string;
isLoading: boolean;
labelEditAction?: string;
+ labelQuoteAction?: string;
labelTitle: JSX.Element;
linkId?: string | null;
updatedAt?: string | null;
userName: string;
onEdit?: (id: string) => void;
+ onQuote?: (id: string) => void;
outlineComment?: (id: string) => void;
}
@@ -43,27 +45,39 @@ export const UserActionTitle = ({
id,
isLoading,
labelEditAction,
+ labelQuoteAction,
labelTitle,
linkId,
userName,
updatedAt,
onEdit,
+ onQuote,
outlineComment,
}: UserActionTitleProps) => {
const { detailName: caseId } = useParams();
const urlSearch = useGetUrlSearch(navTabs.case);
const propertyActions = useMemo(() => {
- if (labelEditAction != null && onEdit != null) {
- return [
- {
- iconType: 'pencil',
- label: labelEditAction,
- onClick: () => onEdit(id),
- },
- ];
- }
- return [];
- }, [id, labelEditAction, onEdit]);
+ return [
+ ...(labelEditAction != null && onEdit != null
+ ? [
+ {
+ iconType: 'pencil',
+ label: labelEditAction,
+ onClick: () => onEdit(id),
+ },
+ ]
+ : []),
+ ...(labelQuoteAction != null && onQuote != null
+ ? [
+ {
+ iconType: 'quote',
+ label: labelQuoteAction,
+ onClick: () => onQuote(id),
+ },
+ ]
+ : []),
+ ];
+ }, [id, labelEditAction, onEdit, labelQuoteAction, onQuote]);
const handleAnchorLink = useCallback(() => {
copy(