Skip to content

Commit

Permalink
fix it
Browse files Browse the repository at this point in the history
  • Loading branch information
stephmilovic committed Oct 20, 2022
1 parent c7a3a16 commit e76c1ea
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface CreateCaseFlyoutProps {
onClose?: () => void;
onSuccess?: (theCase: Case) => Promise<void>;
attachments?: CaseAttachmentsWithoutOwner;
optionalContent?: React.ReactNode;
}

const StyledFlyout = styled(EuiFlyout)`
Expand Down Expand Up @@ -71,9 +72,10 @@ const FormWrapper = styled.div`
`;

export const CreateCaseFlyout = React.memo<CreateCaseFlyoutProps>(
({ afterCaseCreated, onClose, onSuccess, attachments }) => {
({ afterCaseCreated, onClose, onSuccess, attachments, optionalContent }) => {
const handleCancel = onClose || function () {};
const handleOnSuccess = onSuccess || async function () {};
console.log('optional content??', optionalContent);
return (
<QueryClientProvider client={casesQueryClient}>
<GlobalStyle />
Expand All @@ -87,6 +89,7 @@ export const CreateCaseFlyout = React.memo<CreateCaseFlyoutProps>(
<EuiTitle size="m">
<h2>{i18n.CREATE_CASE_TITLE}</h2>
</EuiTitle>
{optionalContent && optionalContent}
</EuiFlyoutHeader>
<StyledEuiFlyoutBody>
<FormWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import type React from 'react';
import { useCallback } from 'react';
import type { CaseAttachmentsWithoutOwner } from '../../../types';
import { useCasesToast } from '../../../common/use_cases_toast';
Expand All @@ -29,12 +30,16 @@ export const useCasesAddToNewCaseFlyout = (props: AddToNewCaseFlyoutProps = {})
}, [dispatch]);

const openFlyout = useCallback(
({ attachments }: { attachments?: CaseAttachmentsWithoutOwner } = {}) => {
({
attachments,
optionalContent,
}: { attachments?: CaseAttachmentsWithoutOwner; optionalContent?: React.ReactNode } = {}) => {
dispatch({
type: CasesContextStoreActionsList.OPEN_CREATE_CASE_FLYOUT,
payload: {
...props,
attachments,
optionalContent,
onClose: () => {
closeFlyout();
if (props.onClose) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,18 @@ const EventDetailsComponent: React.FC<Props> = ({
const hasRiskInfoWithLicense = isLicenseValid && (hostRisk || userRisk);
return hasEnrichments || hasRiskInfoWithLicense;
}, [enrichmentCount, hostRisk, isLicenseValid, userRisk]);
const TourStep = () => (
<GuidedOnboardingTourStep
altAnchor
isTourAnchor={isTourAnchor}
step={3}
stepId={SecurityStepId.alertsCases}
>
<></>
</GuidedOnboardingTourStep>
const TourStep = useCallback(
() => (
<GuidedOnboardingTourStep
altAnchor
isTourAnchor={isTourAnchor}
step={3}
stepId={SecurityStepId.alertsCases}
>
<></>
</GuidedOnboardingTourStep>
),
[isTourAnchor]
);
const summaryTab: EventViewTab | undefined = useMemo(
() =>
Expand Down Expand Up @@ -290,23 +293,25 @@ const EventDetailsComponent: React.FC<Props> = ({
}
: undefined,
[
allEnrichments,
isAlert,
isTourAnchor,
TourStep,
browserFields,
scopeId,
data,
detailsEcsData,
goToTableTab,
handleOnEventClosed,
hostRisk,
id,
indexName,
isAlert,
isDraggable,
scopeId,
isEnrichmentsLoading,
showThreatSummary,
handleOnEventClosed,
isReadOnly,
renderer,
detailsEcsData,
isDraggable,
goToTableTab,
showThreatSummary,
hostRisk,
userRisk,
allEnrichments,
isEnrichmentsLoading,
]
);

Expand Down Expand Up @@ -411,11 +416,19 @@ const EventDetailsComponent: React.FC<Props> = ({
rawEventData: rawEventData as AlertRawEventData,
});

const tabs = useMemo(() => {
return [summaryTab, threatIntelTab, tableTab, jsonTab, osqueryTab].filter(
(tab: EventViewTab | undefined): tab is EventViewTab => !!tab
);
}, [summaryTab, threatIntelTab, tableTab, jsonTab, osqueryTab]);
// intervention for not being able to put the actual tour step tag in ourselves
const possibleTourStepTag = useMemo(
() => (isTourAnchor ? { 'tour-step': getTourAnchor(3, SecurityStepId.alertsCases) } : {}),
[isTourAnchor]
);

const tabs = useMemo(
() =>
[summaryTab, threatIntelTab, tableTab, jsonTab, osqueryTab]
.filter((tab: EventViewTab | undefined): tab is EventViewTab => !!tab)
.map((tab) => ({ ...tab, ...possibleTourStepTag })),
[summaryTab, threatIntelTab, tableTab, jsonTab, osqueryTab, possibleTourStepTag]
);

const selectedTab = useMemo(
() => tabs.find((tab) => tab.id === selectedTabId) ?? tabs[0],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,19 @@ interface SecurityTourStep {
}

export const SecurityTourStep = ({ step, stepId }: SecurityTourStep) => {
const { activeStep, incrementStep } = useTourContext();
const { activeStep, incrementStep, isTourShown } = useTourContext();
const tourStep = useMemo(
() => securityTourConfig[stepId].find((config) => config.step === step),
[step, stepId]
);
if (step !== activeStep || tourStep == null) {
// step === 5 && stepId === SecurityStepId.alertsCases is in Cases app and out of context.
// If we mount this step, we know we need to render it
// we are also managing the context on the siem end in the background
const overrideContext = step === 5 && stepId === SecurityStepId.alertsCases;
if (tourStep == null || ((step !== activeStep || !isTourShown(stepId)) && !overrideContext)) {
return null;
}

const { content, imageConfig, dataTestSubj, hideNextButton = false, ...rest } = tourStep;

const footerAction: EuiTourStepProps['footerAction'] = !hideNextButton ? (
Expand Down Expand Up @@ -75,7 +80,8 @@ export const SecurityTourStep = ({ step, stepId }: SecurityTourStep) => {
</>
}
footerAction={footerAction}
isStepOpen={step === activeStep}
// we wouldn't even mount if it was not open
isStepOpen
// guided onboarding does not allow skipping tour through the steps
onFinish={() => null}
stepsTotal={securityTourConfig[stepId].length}
Expand Down Expand Up @@ -128,7 +134,7 @@ export interface TourContextValue {
}

const initialState: TourContextValue = {
activeStep: 1,
activeStep: 0,
isTourShown: () => false,
endTourStep: () => {},
incrementStep: () => {},
Expand Down Expand Up @@ -165,7 +171,6 @@ export const TourContextProvider = ({ children }: { children: ReactChild }) => {
(stepId: SecurityStepId) => tourStatus[stepId] && !isSmallScreen,
[isSmallScreen, tourStatus]
);

const [activeStep, _setActiveStep] = useState<number>(1);

const incrementStep = useCallback((stepId: SecurityStepId, step?: number) => {
Expand All @@ -178,16 +183,18 @@ export const TourContextProvider = ({ children }: { children: ReactChild }) => {
_setActiveStep(1);
}, []);

const resetTour = useCallback(() => {
resetStep();
}, [resetStep]);
// const onSkipTour = useCallback((stepId: SecurityStepId) => {
// // active state means the user is on this step but has not yet begun. so when the user hits skip,
// // the tour will go back to this step until they "re-start it"
// // guidedOnboardingApi.idkSetStepTo(stepId, 'active')
// }, []);

const endTourStep = useCallback(
async (stepId: SecurityStepId) => {
resetTour();
await guidedOnboardingApi?.completeGuideStep('security', stepId);
resetStep();
},
[resetTour, guidedOnboardingApi]
[resetStep, guidedOnboardingApi]
);

const context = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ interface SecurityTourConfig {
}

export const securityTourConfig: SecurityTourConfig = {
/**
* OLM team implement your tour config here
*/
[SecurityStepId.addData]: [],
[SecurityStepId.rules]: [],
[SecurityStepId.alertsCases]: alertsCasesConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import React, { useCallback, useMemo } from 'react';
import { EuiContextMenuItem } from '@elastic/eui';
import { CommentType } from '@kbn/cases-plugin/common';
import type { CaseAttachmentsWithoutOwner } from '@kbn/cases-plugin/public';
import { GuidedOnboardingTourStep } from '../../../../common/components/guided_onboarding/tour';
import { SecurityStepId } from '../../../../common/components/guided_onboarding/tour_config';
import { useTourContext } from '../../../../common/components/guided_onboarding';
import { useGetUserCasesPermissions, useKibana } from '../../../../common/lib/kibana';
import type { TimelineNonEcsData } from '../../../../../common/search_strategy';
Expand Down Expand Up @@ -54,21 +56,18 @@ export const useAddToCaseActions = ({
: [];
}, [casesUi.helpers, ecsData, nonEcsData]);

const { activeStep, endTour, incrementStep, isTourShown } = useTourContext();
const { activeStep, endTourStep, incrementStep, isTourShown } = useTourContext();

const onCreateCaseSuccess = useCallback(async () => {
if (onSuccess) {
await onSuccess();
// onSuccess only passed on alert take action dropdown, which is a trigger for tour steps
if (isTourShown) {
endTour();
}
const afterCaseCreated = useCallback(async () => {
if (isTourShown(SecurityStepId.alertsCases)) {
endTourStep(SecurityStepId.alertsCases);
}
}, [endTour, isTourShown, onSuccess]);
}, [endTourStep, isTourShown]);

const createCaseFlyout = casesUi.hooks.getUseCasesAddToNewCaseFlyout({
onClose: onMenuItemClick,
onSuccess: onCreateCaseSuccess,
onSuccess,
afterCaseCreated,
});

const selectCaseModal = casesUi.hooks.getUseCasesAddToExistingCaseModal({
Expand All @@ -78,12 +77,20 @@ export const useAddToCaseActions = ({
const handleAddToNewCaseClick = useCallback(() => {
// TODO rename this, this is really `closePopover()`
onMenuItemClick();
createCaseFlyout.open({ attachments: caseAttachments });
// This alleviates a race condition where the active step attempts to mount before the tour anchor is mounted
if (isTourShown && activeStep === 4) {
setTimeout(() => {
incrementStep(5);
}, 500);
createCaseFlyout.open({
attachments: caseAttachments,
...(isTourShown(SecurityStepId.alertsCases) && activeStep === 4
? {
optionalContent: (
<GuidedOnboardingTourStep isTourAnchor step={5} stepId={SecurityStepId.alertsCases}>
<p />
</GuidedOnboardingTourStep>
),
}
: {}),
});
if (isTourShown(SecurityStepId.alertsCases) && activeStep === 4) {
incrementStep(SecurityStepId.alertsCases);
}
}, [onMenuItemClick, createCaseFlyout, caseAttachments, isTourShown, activeStep, incrementStep]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import React, { useCallback, useMemo, useState } from 'react';
import { EuiButton, EuiContextMenuPanel, EuiPopover } from '@elastic/eui';
import type { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { getTourAnchor } from '../../../common/components/guided_onboarding/tour_config';
import { GuidedOnboardingTourStep } from '../../../common/components/guided_onboarding/tour';
import { SecurityStepId } from '../../../common/components/guided_onboarding/tour_config';
import { isActiveTimeline } from '../../../helpers';
import { TableId } from '../../../../common/types';
import { useResponderActionItem } from '../endpoint_responder';
Expand Down Expand Up @@ -255,16 +256,17 @@ export const TakeActionDropdown = React.memo(

const takeActionButton = useMemo(() => {
return (
<EuiButton
tour-step={getTourAnchor(4)}
data-test-subj="take-action-dropdown-btn"
fill
iconSide="right"
iconType="arrowDown"
onClick={togglePopoverHandler}
>
{TAKE_ACTION}
</EuiButton>
<GuidedOnboardingTourStep isTourAnchor step={4} stepId={SecurityStepId.alertsCases}>
<EuiButton
data-test-subj="take-action-dropdown-btn"
fill
iconSide="right"
iconType="arrowDown"
onClick={togglePopoverHandler}
>
{TAKE_ACTION}
</EuiButton>
</GuidedOnboardingTourStep>
);
}, [togglePopoverHandler]);
return items.length && !loadingEventDetails && ecsData ? (
Expand Down

0 comments on commit e76c1ea

Please sign in to comment.