Skip to content

Commit

Permalink
[Resolver] Refactor resolver assets (#77795)
Browse files Browse the repository at this point in the history
This PR splits the `assets` module into several other modules/hooks:
* `calculateResolverFontSize` is now `fontSize`
* `colorMap` is now `useColors`
* `cubeAssetsForNow` is now `useCubeAssets`
* `nodeAssets` is gone (inlined into `useCubeAssets`)

The PaintServer and Symbol IDs no longer use random IDs. They are now based on the `resolverComponentInstanceID`. This sets us up to use a provider that can allow multiple resolver instances to share these assets.
  • Loading branch information
Robert Austin authored Sep 18, 2020
1 parent 3e5ae01 commit cdb3c30
Show file tree
Hide file tree
Showing 16 changed files with 634 additions and 565 deletions.
521 changes: 0 additions & 521 deletions x-pack/plugins/security_solution/public/resolver/view/assets.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import styled from 'styled-components';
import { FormattedMessage } from '@kbn/i18n/react';
import { applyMatrix3, distance, angle } from '../models/vector2';
import { Vector2, Matrix3, EdgeLineMetadata } from '../types';
import { useResolverTheme, calculateResolverFontSize } from './assets';
import { fontSize } from './font_size';
import { useColors } from './use_colors';

interface StyledEdgeLine {
readonly resolverEdgeColor: string;
Expand All @@ -19,7 +20,7 @@ interface StyledEdgeLine {
const StyledEdgeLine = styled.div<StyledEdgeLine>`
position: absolute;
height: ${(props) => {
return `${calculateResolverFontSize(props.magFactorX, 12, 8.5)}px`;
return `${fontSize(props.magFactorX, 12, 8.5)}px`;
}};
background-color: ${(props) => props.resolverEdgeColor};
`;
Expand Down Expand Up @@ -87,16 +88,16 @@ const EdgeLineComponent = React.memo(
*/
const screenStart = applyMatrix3(startPosition, projectionMatrix);
const screenEnd = applyMatrix3(endPosition, projectionMatrix);
const [magFactorX] = projectionMatrix;
const { colorMap } = useResolverTheme();
const [xScale] = projectionMatrix;
const colorMap = useColors();
const elapsedTime = edgeLineMetadata?.elapsedTime;

/**
* We render the line using a short, long, `div` element. The length of this `div`
* should be the same as the distance between the start and end points.
*/
const length = distance(screenStart, screenEnd);
const scaledTypeSize = calculateResolverFontSize(magFactorX, 10, 7.5);
const scaledTypeSize = fontSize(xScale, 10, 7.5);

const style = {
left: `${screenStart[0]}px`,
Expand All @@ -120,8 +121,8 @@ const EdgeLineComponent = React.memo(
/**
* Calculates a fractional offset from 0 -> 5% as magFactorX decreases from 1 to a min of .5
*/
if (magFactorX < 1) {
const fractionalOffset = (1 / magFactorX) * ((1 - magFactorX) * 10);
if (xScale < 1) {
const fractionalOffset = (1 / xScale) * ((1 - xScale) * 10);
elapsedTimeLeftPosPct += fractionalOffset;
}

Expand All @@ -130,7 +131,7 @@ const EdgeLineComponent = React.memo(
className={className}
style={style}
resolverEdgeColor={colorMap.resolverEdge}
magFactorX={magFactorX}
magFactorX={xScale}
data-test-subj="resolver:graph:edgeline"
>
{elapsedTime && (
Expand Down
12 changes: 12 additions & 0 deletions x-pack/plugins/security_solution/public/resolver/view/font_size.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

/**
* Return a font-size based on a scale, minimum size, and a coefficient.
*/
export function fontSize(scale: number, minimum: number, slope: number): number {
return minimum + (scale > 1 ? slope * (scale - 1) : 0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { useSelector, useDispatch } from 'react-redux';
import { SideEffectContext } from './side_effect_context';
import { Vector2 } from '../types';
import * as selectors from '../store/selectors';
import { useResolverTheme } from './assets';
import { ResolverAction } from '../store/actions';
import { useColors } from './use_colors';

interface StyledGraphControls {
graphControlsBackground: string;
Expand Down Expand Up @@ -66,7 +66,7 @@ const GraphControlsComponent = React.memo(
const dispatch: (action: ResolverAction) => unknown = useDispatch();
const scalingFactor = useSelector(selectors.scalingFactor);
const { timestamp } = useContext(SideEffectContext);
const { colorMap } = useResolverTheme();
const colorMap = useColors();

const handleZoomAmountChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement> | React.MouseEvent<HTMLButtonElement>) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import { i18n } from '@kbn/i18n';
/* eslint-disable react/display-name */

import React, { memo } from 'react';
import { useResolverTheme, SymbolIds } from '../assets';

interface StyledSVGCube {
readonly isOrigin?: boolean;
}
import { useCubeAssets } from '../use_cube_assets';
import { useSymbolIDs } from '../use_symbol_ids';

/**
* Icon representing a process node.
Expand All @@ -34,8 +35,8 @@ export const CubeForProcess = memo(function ({
isOrigin?: boolean;
className?: string;
}) {
const { cubeAssetsForNode } = useResolverTheme();
const { cubeSymbol, strokeColor } = cubeAssetsForNode(!running, false);
const { cubeSymbol, strokeColor } = useCubeAssets(!running, false);
const { processCubeActiveBacking } = useSymbolIDs();

return (
<StyledSVG
Expand All @@ -54,7 +55,7 @@ export const CubeForProcess = memo(function ({
</desc>
{isOrigin && (
<use
xlinkHref={`#${SymbolIds.processCubeActiveBacking}`}
xlinkHref={`#${processCubeActiveBacking}`}
fill="transparent"
x={0}
y={-1}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
} from '../../models/process_event';
import { CubeForProcess } from './cube_for_process';
import { ResolverEvent } from '../../../../common/endpoint/types';
import { useResolverTheme } from '../assets';
import { useCubeAssets } from '../use_cube_assets';
import { ResolverState } from '../../types';
import { PanelLoading } from './panel_loading';
import { StyledPanel } from '../styles';
Expand Down Expand Up @@ -166,13 +166,7 @@ const NodeDetailView = memo(function NodeDetailView({
},
];
}, [processName, nodesLinkNavProps]);
const { cubeAssetsForNode } = useResolverTheme();
const { descriptionText } = useMemo(() => {
if (!processEvent) {
return { descriptionText: '' };
}
return cubeAssetsForNode(isProcessTerminated, false);
}, [processEvent, cubeAssetsForNode, isProcessTerminated]);
const { descriptionText } = useCubeAssets(isProcessTerminated, false);

const nodeDetailHref = useSelector((state: ResolverState) =>
selectors.relativeHref(state)({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { SafeResolverEvent } from '../../../../common/endpoint/types';
import { LimitWarning } from '../limit_warnings';
import { ResolverState } from '../../types';
import { useNavigateOrReplace } from '../use_navigate_or_replace';
import { useResolverTheme } from '../assets';
import { useColors } from '../use_colors';

const StyledLimitWarning = styled(LimitWarning)`
flex-flow: row wrap;
Expand Down Expand Up @@ -208,9 +208,7 @@ function NodeDetailLink({ name, item }: { name: string; item: ProcessTableView }
const isTerminated = useSelector((state: ResolverState) =>
entityID === undefined ? false : selectors.isProcessTerminated(state)(entityID)
);
const {
colorMap: { descriptionText },
} = useResolverTheme();
const { descriptionText } = useColors();
return (
<EuiButtonEmpty {...useNavigateOrReplace({ search: item.href })}>
{name === '' ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/

/* eslint-disable react/display-name */

import { i18n } from '@kbn/i18n';
import { EuiBreadcrumbs, EuiCode, EuiBetaBadge } from '@elastic/eui';
import styled from 'styled-components';
import React, { memo } from 'react';
import { useResolverTheme } from '../assets';
import { useColors } from '../use_colors';

/**
* A bold version of EuiCode to display certain titles with
Expand Down Expand Up @@ -63,7 +65,7 @@ export const GeneratedText = React.memo(function ({ children }) {
valueSplitByWordBoundaries[0],
...valueSplitByWordBoundaries
.splice(1)
.reduce(function (generatedTextMemo: Array<string | JSX.Element>, value, index) {
.reduce(function (generatedTextMemo: Array<string | JSX.Element>, value) {
return [...generatedTextMemo, value, <wbr />];
}, []),
];
Expand All @@ -73,7 +75,6 @@ export const GeneratedText = React.memo(function ({ children }) {
});
}
});
GeneratedText.displayName = 'GeneratedText';

/**
* A component to keep time representations in blocks so they don't wrap
Expand All @@ -93,9 +94,7 @@ export const StyledBreadcrumbs = memo(function StyledBreadcrumbs({
}: {
breadcrumbs: Breadcrumbs;
}) {
const {
colorMap: { resolverBreadcrumbBackground, resolverEdgeText },
} = useResolverTheme();
const { resolverBreadcrumbBackground, resolverEdgeText } = useColors();
return (
<>
<BetaHeader>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { NodeSubMenu } from './submenu';
import { applyMatrix3 } from '../models/vector2';
import { Vector2, Matrix3, ResolverState } from '../types';
import { SymbolIds, useResolverTheme, calculateResolverFontSize } from './assets';
import { ResolverEvent, SafeResolverEvent } from '../../../common/endpoint/types';
import { useResolverDispatch } from './use_resolver_dispatch';
import * as eventModel from '../../../common/endpoint/models/event';
import * as selectors from '../store/selectors';
import { useNavigateOrReplace } from './use_navigate_or_replace';
import { fontSize } from './font_size';
import { useCubeAssets } from './use_cube_assets';
import { useSymbolIDs } from './use_symbol_ids';
import { useColors } from './use_colors';

interface StyledActionsContainer {
readonly color: string;
Expand Down Expand Up @@ -108,6 +111,8 @@ const UnstyledProcessEventDot = React.memo(
// This should be unique to each instance of Resolver
const htmlIDPrefix = `resolver:${resolverComponentInstanceID}`;

const symbolIDs = useSymbolIDs();

/**
* Convert the position, which is in 'world' coordinates, to screen coordinates.
*/
Expand Down Expand Up @@ -191,7 +196,7 @@ const UnstyledProcessEventDot = React.memo(
* 18.75 : The smallest readable font size at which labels/descriptions can be read. Font size will not scale below this.
* 12.5 : A 'slope' at which the font size will scale w.r.t. to zoom level otherwise
*/
const scaledTypeSize = calculateResolverFontSize(xScale, 18.75, 12.5);
const scaledTypeSize = fontSize(xScale, 18.75, 12.5);

const markerBaseSize = 15;
const markerSize = markerBaseSize;
Expand All @@ -212,15 +217,15 @@ const UnstyledProcessEventDot = React.memo(
})
| null;
} = React.createRef();
const { colorMap, cubeAssetsForNode } = useResolverTheme();
const colorMap = useColors();
const {
backingFill,
cubeSymbol,
descriptionText,
isLabelFilled,
labelButtonFill,
strokeColor,
} = cubeAssetsForNode(
} = useCubeAssets(
isProcessTerminated,
/**
* There is no definition for 'trigger process' yet. return false.
Expand Down Expand Up @@ -323,7 +328,7 @@ const UnstyledProcessEventDot = React.memo(
>
<StyledOuterGroup>
<use
xlinkHref={`#${SymbolIds.processCubeActiveBacking}`}
xlinkHref={`#${symbolIDs.processCubeActiveBacking}`}
fill={backingFill} // Only visible on hover
x={-15.35}
y={-15.35}
Expand All @@ -334,7 +339,7 @@ const UnstyledProcessEventDot = React.memo(
/>
{isOrigin && (
<use
xlinkHref={`#${SymbolIds.processCubeActiveBacking}`}
xlinkHref={`#${symbolIDs.processCubeActiveBacking}`}
fill="transparent" // Transparent so we don't double up on the default hover
x={-15.35}
y={-15.35}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ import { EdgeLine } from './edge_line';
import { GraphControls } from './graph_controls';
import { ProcessEventDot } from './process_event_dot';
import { useCamera } from './use_camera';
import { SymbolDefinitions, useResolverTheme } from './assets';
import { SymbolDefinitions } from './symbol_definitions';
import { useStateSyncingActions } from './use_state_syncing_actions';
import { StyledMapContainer, GraphContainer } from './styles';
import { entityIDSafeVersion } from '../../../common/endpoint/models/event';
import { SideEffectContext } from './side_effect_context';
import { ResolverProps, ResolverState } from '../types';
import { PanelRouter } from './panels';
import { useColors } from './use_colors';

/**
* The highest level connected Resolver component. Needs a `Provider` in its ancestry to work.
Expand Down Expand Up @@ -73,7 +74,7 @@ export const ResolverWithoutProviders = React.memo(
const isLoading = useSelector(selectors.isTreeLoading);
const hasError = useSelector(selectors.hadErrorLoadingTree);
const activeDescendantId = useSelector(selectors.ariaActiveDescendant);
const { colorMap } = useResolverTheme();
const colorMap = useColors();

return (
<StyledMapContainer className={className} backgroundColor={colorMap.resolverBackground}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import styled from 'styled-components';
import { ResolverNodeStats } from '../../../common/endpoint/types';
import { useRelatedEventByCategoryNavigation } from './use_related_event_by_category_navigation';
import { Matrix3 } from '../types';
import { useResolverTheme } from './assets';
import { useColors } from './use_colors';

/**
* i18n-translated titles for submenus and identifiers for display of states:
Expand Down Expand Up @@ -182,9 +182,7 @@ const NodeSubMenuComponents = React.memo(
// no matter what, keep track of the last project matrix that was used to size the popover
projectionMatrixAtLastRender.current = projectionMatrix;
}, [projectionMatrixAtLastRender, projectionMatrix]);
const {
colorMap: { pillStroke: pillBorderStroke, resolverBackground: pillFill },
} = useResolverTheme();
const { pillStroke: pillBorderStroke, resolverBackground: pillFill } = useColors();
const listStylesFromTheme = useMemo(() => {
return {
border: `1.5px solid ${pillBorderStroke}`,
Expand Down Expand Up @@ -239,6 +237,7 @@ const NodeSubMenuComponents = React.memo(
className="item"
data-test-subj="resolver:map:node-submenu-item"
style={listStylesFromTheme}
key={opt.optionTitle}
>
<button type="button" className="kbn-resetFocusState" onClick={opt.action}>
{opt.prefix} {opt.optionTitle}
Expand Down
Loading

0 comments on commit cdb3c30

Please sign in to comment.