Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RAC][Analyzer] Make analyzer full screen mode compatible with EuiDataGrid's #110723

Closed
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,9 @@ const EventsViewerComponent: React.FC<Props> = ({
refetch={refetch}
/>

{graphEventId && <GraphOverlay isEventViewer={true} timelineId={id} />}
{graphEventId && (
<GraphOverlay isEventViewer={true} timelineId={id} isDataGridExpanded={false} />
)}
<FullWidthFlexGroup $visible={!graphEventId} gutterSize="none">
<ScrollableFlexItem grow={1}>
<StatefulBody
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* 2.0.
*/

import React, { useCallback, useMemo, useEffect } from 'react';
import React, { useMemo, useEffect, useCallback } from 'react';
import { EuiMutationObserver } from '@elastic/eui';
import { connect, ConnectedProps, useDispatch } from 'react-redux';
import deepEqual from 'fast-deep-equal';
import styled from 'styled-components';
Expand All @@ -19,11 +20,12 @@ import type { SubsetTimelineModel, TimelineModel } from '../../../timelines/stor
import { Status } from '../../../../common/detection_engine/schemas/common/schemas';
import { Filter } from '../../../../../../../src/plugins/data/public';
import { InspectButtonContainer } from '../inspect';
import { useGlobalFullScreen } from '../../containers/use_full_screen';
import { useGlobalFullScreen, useIsDataGridExpanded } from '../../containers/use_full_screen';
import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features';
import { SourcererScopeName } from '../../store/sourcerer/model';
import { useSourcererScope } from '../../containers/sourcerer';
import type { EntityType } from '../../../../../timelines/common';
import type { TGridType } from '../../../../../timelines/public';
import { TGridCellAction } from '../../../../../timelines/common/types';
import { DetailsPanel } from '../../../timelines/components/side_panel';
import { CellValueElementProps } from '../../../timelines/components/timeline/cell_rendering';
Expand Down Expand Up @@ -145,100 +147,151 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({

const globalFilters = useMemo(() => [...filters, ...(pageFilters ?? [])], [filters, pageFilters]);
const trailingControlColumns: ControlColumnProps[] = EMPTY_CONTROL_COLUMNS;
const graphOverlay = useMemo(
() =>
graphEventId != null && graphEventId.length > 0 ? (
<GraphOverlay isEventViewer={true} timelineId={id} />
) : null,
[graphEventId, id]
);
const { isDataGridExpanded, onMutation } = useIsDataGridExpanded();
const setQuery = useCallback(
(inspect, loading, refetch) => {
dispatch(inputsActions.setQuery({ id, inputId: 'global', inspect, loading, refetch }));
},
[dispatch, id]
);
const graphOverlay = useMemo(
() =>
graphEventId != null && graphEventId.length > 0 ? (
<GraphOverlay
isEventViewer={true}
timelineId={id}
isDataGridExpanded={isDataGridExpanded}
/>
) : null,
[graphEventId, id, isDataGridExpanded]
);

const tGridProps = useMemo(() => {
const type: TGridType = 'embedded';
return {
id,
type,
browserFields,
columns,
dataProviders: dataProviders!,
defaultCellActions,
deletedEventIds,
docValueFields,
end,
entityType,
filters: globalFilters,
globalFullScreen,
graphOverlay,
hasAlertsCrud,
indexNames: selectedPatterns,
indexPattern,
isLive,
isLoadingIndexPattern,
itemsPerPage,
itemsPerPageOptions: itemsPerPageOptions!,
kqlMode,
query,
onRuleChange,
renderCellValue,
rowRenderers,
setQuery,
start,
sort,
additionalFilters,
graphEventId,
filterStatus: currentFilter,
leadingControlColumns,
trailingControlColumns,
tGridEventRenderedViewEnabled,
unit,
};
}, [
additionalFilters,
browserFields,
columns,
currentFilter,
dataProviders,
defaultCellActions,
deletedEventIds,
docValueFields,
end,
entityType,
globalFilters,
globalFullScreen,
graphEventId,
graphOverlay,
hasAlertsCrud,
id,
indexPattern,
isLive,
isLoadingIndexPattern,
itemsPerPage,
itemsPerPageOptions,
kqlMode,
onRuleChange,
query,
renderCellValue,
rowRenderers,
selectedPatterns,
setQuery,
sort,
start,
tGridEventRenderedViewEnabled,
trailingControlColumns,
unit,
]);

return (
<>
<FullScreenContainer $isFullScreen={globalFullScreen}>
<InspectButtonContainer>
{tGridEnabled ? (
timelinesUi.getTGrid<'embedded'>({
id,
type: 'embedded',
browserFields,
columns,
dataProviders: dataProviders!,
defaultCellActions,
deletedEventIds,
docValueFields,
end,
entityType,
filters: globalFilters,
globalFullScreen,
graphOverlay,
hasAlertsCrud,
indexNames: selectedPatterns,
indexPattern,
isLive,
isLoadingIndexPattern,
itemsPerPage,
itemsPerPageOptions: itemsPerPageOptions!,
kqlMode,
query,
onRuleChange,
renderCellValue,
rowRenderers,
setQuery,
start,
sort,
additionalFilters,
graphEventId,
filterStatus: currentFilter,
leadingControlColumns,
trailingControlColumns,
tGridEventRenderedViewEnabled,
unit,
})
) : (
<EventsViewer
browserFields={browserFields}
columns={columns}
docValueFields={docValueFields}
id={id}
dataProviders={dataProviders!}
deletedEventIds={deletedEventIds}
end={end}
isLoadingIndexPattern={isLoadingIndexPattern}
filters={globalFilters}
indexNames={selectedPatterns}
indexPattern={indexPattern}
isLive={isLive}
itemsPerPage={itemsPerPage!}
itemsPerPageOptions={itemsPerPageOptions!}
kqlMode={kqlMode}
query={query}
onRuleChange={onRuleChange}
renderCellValue={renderCellValue}
rowRenderers={rowRenderers}
start={start}
sort={sort}
showTotalCount={isEmpty(graphEventId) ? true : false}
utilityBar={utilityBar}
graphEventId={graphEventId}
/>
)}
</InspectButtonContainer>
</FullScreenContainer>
<DetailsPanel
browserFields={browserFields}
entityType={entityType}
docValueFields={docValueFields}
isFlyoutView
timelineId={id}
/>
</>
<EuiMutationObserver
observerOptions={{ subtree: true, attributeFilter: ['class'] }}
onMutation={onMutation}
>
{(mutationRef) => (
<>
<FullScreenContainer $isFullScreen={globalFullScreen} ref={mutationRef}>
<InspectButtonContainer>
{tGridEnabled ? (
timelinesUi.getTGrid<'embedded'>(tGridProps)
) : (
<EventsViewer
browserFields={browserFields}
columns={columns}
docValueFields={docValueFields}
id={id}
dataProviders={dataProviders!}
deletedEventIds={deletedEventIds}
end={end}
isLoadingIndexPattern={isLoadingIndexPattern}
filters={globalFilters}
indexNames={selectedPatterns}
indexPattern={indexPattern}
isLive={isLive}
itemsPerPage={itemsPerPage!}
itemsPerPageOptions={itemsPerPageOptions!}
kqlMode={kqlMode}
query={query}
onRuleChange={onRuleChange}
renderCellValue={renderCellValue}
rowRenderers={rowRenderers}
start={start}
sort={sort}
showTotalCount={isEmpty(graphEventId) ? true : false}
utilityBar={utilityBar}
graphEventId={graphEventId}
/>
)}
</InspectButtonContainer>
</FullScreenContainer>
<DetailsPanel
browserFields={browserFields}
entityType={entityType}
docValueFields={docValueFields}
isFlyoutView
timelineId={id}
/>
</>
)}
</EuiMutationObserver>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { useCallback, useMemo } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { useDispatch } from 'react-redux';

import { SCROLLING_DISABLED_CLASS_NAME } from '../../../../common/constants';
Expand All @@ -29,6 +29,25 @@ export const resetScroll = () => {
}, 0);
};

export const setDataGridFullScreen = (isExpanded: boolean) => {
const clickEvent = new KeyboardEvent('click', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oof

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please put a // TODO with a link to the Eui issue so we remember to come back and refactor once a method is available. @chandlerprall could you please help us find an eui issue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

view: window,
bubbles: true,
cancelable: true,
});
const dataGridIsFullScreen = document.querySelector('.euiDataGrid--fullScreen') !== null;
const dataGridFullScreenButtonNew = document.querySelector(
Copy link
Contributor

@XavierM XavierM Sep 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my hacky sense love it, however my gray hair are telling me to not go for it and just ask EUI to create a callback on the full screen action. I really appreciate the ingenuity here.

I am sorry if I disappoint you but a safer bet it is to go with @stephmilovic 's PR to just disable the full screen on the analyzer for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@paulewing are you ok with that?

'[data-test-subj="dataGridFullScrenButton"]'
);
const dataGridFullScreenButtonOld = document.querySelector(
'[data-test-subj="dataGridFullScreenButton"]'
);
const dataGridFullScreenButton = dataGridFullScreenButtonNew || dataGridFullScreenButtonOld;
if (dataGridIsFullScreen !== isExpanded && dataGridFullScreenButton) {
dataGridFullScreenButton.dispatchEvent(clickEvent);
}
};

interface GlobalFullScreen {
globalFullScreen: boolean;
setGlobalFullScreen: (fullScreen: boolean) => void;
Expand All @@ -46,9 +65,11 @@ export const useGlobalFullScreen = (): GlobalFullScreen => {
const setGlobalFullScreen = useCallback(
(fullScreen: boolean) => {
if (fullScreen) {
setDataGridFullScreen(true);
document.body.classList.add(SCROLLING_DISABLED_CLASS_NAME);
resetScroll();
} else {
setDataGridFullScreen(false);
document.body.classList.remove(SCROLLING_DISABLED_CLASS_NAME);
resetScroll();
}
Expand All @@ -71,9 +92,10 @@ export const useTimelineFullScreen = (): TimelineFullScreen => {
const dispatch = useDispatch();
const timelineFullScreen =
useShallowEqualSelector(inputsSelectors.timelineFullScreenSelector) ?? false;

const setTimelineFullScreen = useCallback(
(fullScreen: boolean) => dispatch(inputsActions.setFullScreen({ id: 'timeline', fullScreen })),
(fullScreen: boolean) => {
dispatch(inputsActions.setFullScreen({ id: 'timeline', fullScreen }));
},
[dispatch]
);
const memoizedReturn = useMemo(
Expand All @@ -85,3 +107,14 @@ export const useTimelineFullScreen = (): TimelineFullScreen => {
);
return memoizedReturn;
};

export const useIsDataGridExpanded = () => {
const [isDataGridExpanded, setDataGridExpanded] = useState(false);
const onMutation = useCallback(() => {
const isExpanded = document.querySelector('.euiDataGrid--fullScreen') !== null;
setDataGridExpanded(isExpanded);
}, [setDataGridExpanded]);
Copy link
Contributor

@XavierM XavierM Sep 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think you should be able to remove this setter as a dependency because it is coming from useState

return useMemo(() => {
return { onMutation, isDataGridExpanded };
}, [onMutation, isDataGridExpanded]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import {
setActiveTabTimeline,
updateTimelineGraphEventId,
} from '../../../../timelines/store/timeline/actions';
import {
useGlobalFullScreen,
useTimelineFullScreen,
} from '../../../../common/containers/use_full_screen';
import { TimelineId, TimelineTabs } from '../../../../../common';
import { ACTION_INVESTIGATE_IN_RESOLVER } from '../../../../timelines/components/timeline/body/translations';
import { Ecs } from '../../../../../common/ecs';
Expand All @@ -35,13 +39,23 @@ export const useInvestigateInResolverContextItem = ({
}: InvestigateInResolverProps) => {
const dispatch = useDispatch();
const isDisabled = useMemo(() => !isInvestigateInResolverActionEnabled(ecsData), [ecsData]);
const { setGlobalFullScreen } = useGlobalFullScreen();
const { setTimelineFullScreen } = useTimelineFullScreen();
const handleClick = useCallback(() => {
const dataGridIsFullScreen = document.querySelector('.euiDataGrid--fullScreen');
dispatch(updateTimelineGraphEventId({ id: timelineId, graphEventId: ecsData._id }));
if (timelineId === TimelineId.active) {
if (dataGridIsFullScreen) {
setTimelineFullScreen(true);
}
dispatch(setActiveTabTimeline({ id: timelineId, activeTab: TimelineTabs.graph }));
} else {
if (dataGridIsFullScreen) {
setGlobalFullScreen(true);
}
}
onClose();
}, [dispatch, ecsData._id, onClose, timelineId]);
}, [dispatch, ecsData._id, onClose, timelineId, setGlobalFullScreen, setTimelineFullScreen]);
return isDisabled
? []
: [
Expand Down
Loading