From 7806d114b5fb7271eb74eeda7cfadee171b6fe34 Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Tue, 31 Mar 2020 11:38:53 -0400 Subject: [PATCH 01/14] base changes for selected node styling --- .../embeddables/resolver/store/selectors.ts | 11 ++++++++++ .../embeddables/resolver/view/index.tsx | 21 +++++++++++-------- .../resolver/view/process_event_dot.tsx | 9 ++++++++ 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts index 37482916496e7..f37a895c0da45 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts @@ -59,6 +59,10 @@ export const processAdjacencies = composeSelectors( dataSelectors.processAdjacencies ); +export const uiActiveDescendantId = composeSelectors(uiStateSelector, uiState => { + return uiState.activeDescendentId; +}); + /** * Returns the camera state from within ResolverState */ @@ -73,6 +77,13 @@ function dataStateSelector(state: ResolverState) { return state.data; } +/** + * Returns the ui state from within ResolverState + */ +function uiStateSelector(state: ResolverState) { + return state.ui; +} + /** * Whether or not the resolver is pending fetching data */ diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx index 22e9d05ad98ff..101c4060b7c22 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx @@ -66,6 +66,7 @@ export const Resolver = styled( payload: { selectedEvent }, }); }, [dispatch, selectedEvent]); + return (
{isLoading ? ( @@ -88,15 +89,17 @@ export const Resolver = styled( projectionMatrix={projectionMatrix} /> ))} - {Array.from(processNodePositions).map(([processEvent, position], index) => ( - - ))} + {Array.from(processNodePositions).map(([processEvent, position], index) => { + return ( + + ); + })} )} diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index 603521e2d9bb3..75f1df2791e86 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -8,6 +8,7 @@ import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; import { htmlIdGenerator, EuiKeyboardAccessible } from '@elastic/eui'; +import { useSelector } from 'react-redux'; import { applyMatrix3 } from '../lib/vector2'; import { Vector2, Matrix3, AdjacentProcessMap, ResolverProcessType } from '../types'; import { SymbolIds, NamedColors, PaintServerIds } from './defs'; @@ -15,6 +16,7 @@ import { ResolverEvent } from '../../../../common/types'; import { useResolverDispatch } from './use_resolver_dispatch'; import * as eventModel from '../../../../common/models/event'; import * as processModel from '../models/process_event'; +import * as selectors from '../store/selectors'; const nodeAssets = { runningProcessCube: { @@ -93,6 +95,8 @@ export const ProcessEventDot = styled( const selfId = adjacentNodeMap?.self; + const activeDescendantId = useSelector(selectors.uiActiveDescendantId); + const nodeViewportStyle = useMemo( () => ({ left: `${left}px`, @@ -139,6 +143,10 @@ export const ProcessEventDot = styled( resolverNodeIdGenerator(), ] as string[]; + const isActiveDescendant = useMemo(() => { + return nodeId === activeDescendantId; + }, [activeDescendantId, nodeId]); + const dispatch = useResolverDispatch(); const handleFocus = useCallback( @@ -176,6 +184,7 @@ export const ProcessEventDot = styled( aria-labelledby={labelId} aria-describedby={descriptionId} aria-haspopup={'true'} + aria-selected={isActiveDescendant ? 'true' : undefined} style={nodeViewportStyle} id={nodeId} onClick={handleClick} From 0055a47e135a764aa61e85b3ab74d630e7034db1 Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Tue, 31 Mar 2020 15:21:51 -0400 Subject: [PATCH 02/14] run style off of selected/current state --- .../embeddables/resolver/store/actions.ts | 16 +++++++++- .../embeddables/resolver/store/reducer.ts | 8 ++++- .../embeddables/resolver/store/selectors.ts | 19 ++++++++++-- .../resolver/store/ui/selectors.ts | 29 +++++++++++++++++++ .../public/embeddables/resolver/types.ts | 4 +++ .../resolver/view/process_event_dot.tsx | 24 +++++++++++++-- 6 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 x-pack/plugins/endpoint/public/embeddables/resolver/store/ui/selectors.ts diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts index ceb5da2ca9098..210da01cbb8db 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts @@ -56,10 +56,24 @@ interface UserFocusedOnResolverNode { }; } +/** + * When the user "selects" a node in the Resolver + */ +interface UserSelectedResolverNode { + readonly type: 'userSelectedResolverNode'; + readonly payload: { + /** + * Used to identify the process node that the user selected + */ + readonly nodeId: string; + }; +} + export type ResolverAction = | CameraAction | DataAction | UserBroughtProcessIntoView | UserChangedSelectedEvent | AppRequestedResolverData - | UserFocusedOnResolverNode; + | UserFocusedOnResolverNode + | UserSelectedResolverNode; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts index 1c66a998a4c22..39433cae461bd 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts @@ -10,13 +10,19 @@ import { dataReducer } from './data/reducer'; import { ResolverState, ResolverAction, ResolverUIState } from '../types'; const uiReducer: Reducer = ( - uiState = { activeDescendentId: null }, + uiState = { activeDescendentId: null, selectedDescendantId: null }, action ) => { if (action.type === 'userFocusedOnResolverNode') { return { + ...uiState, activeDescendentId: action.payload.nodeId, }; + } else if (action.type === 'userSelectedResolverNode') { + return { + ...uiState, + selectedDescendantId: action.payload.nodeId, + }; } else { return uiState; } diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts index f37a895c0da45..e03b7836fdf11 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts @@ -6,6 +6,7 @@ import * as cameraSelectors from './camera/selectors'; import * as dataSelectors from './data/selectors'; +import * as uiSelectors from './ui/selectors'; import { ResolverState } from '../types'; /** @@ -59,9 +60,21 @@ export const processAdjacencies = composeSelectors( dataSelectors.processAdjacencies ); -export const uiActiveDescendantId = composeSelectors(uiStateSelector, uiState => { - return uiState.activeDescendentId; -}); +/** + * Returns the id of the "current" tree node (fake-focused) + */ +export const uiActiveDescendantId = composeSelectors( + uiStateSelector, + uiSelectors.activeDescendantId +); + +/** + * Returns the id of the "selected" tree node (fake-focused) + */ +export const uiSelectedDescendantId = composeSelectors( + uiStateSelector, + uiSelectors.selectedDescendantId +); /** * Returns the camera state from within ResolverState diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/ui/selectors.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/ui/selectors.ts new file mode 100644 index 0000000000000..5bcb0c0356300 --- /dev/null +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/ui/selectors.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import { createSelector } from 'reselect'; +import { ResolverUIState } from '../../types'; + +/** + * id of the "current" tree node (fake-focused) + */ +export const activeDescendantId = createSelector( + (uiState: ResolverUIState) => uiState, + ({ activeDescendentId }) => { + return activeDescendentId; + } +); + +/** + * id of the currently "selected" tree node + */ +export const selectedDescendantId = createSelector( + (uiState: ResolverUIState) => uiState, + /* eslint-disable no-shadow */ + ({ selectedDescendantId }) => { + return selectedDescendantId; + } +); diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts index 674553aba0937..3bda820a64684 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts @@ -38,6 +38,10 @@ export interface ResolverUIState { * The ID attribute of the resolver's aria-activedescendent. */ readonly activeDescendentId: string | null; + /** + * The ID attribute of the resolver's currently selected descendant. + */ + readonly selectedDescendantId: string | null; } /** diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index 75f1df2791e86..f998068ea99b9 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -96,6 +96,7 @@ export const ProcessEventDot = styled( const selfId = adjacentNodeMap?.self; const activeDescendantId = useSelector(selectors.uiActiveDescendantId); + const selectedDescendantId = useSelector(selectors.uiSelectedDescendantId); const nodeViewportStyle = useMemo( () => ({ @@ -147,6 +148,10 @@ export const ProcessEventDot = styled( return nodeId === activeDescendantId; }, [activeDescendantId, nodeId]); + const isSelectedDescendant = useMemo(() => { + return nodeId === selectedDescendantId; + }, [selectedDescendantId, nodeId]); + const dispatch = useResolverDispatch(); const handleFocus = useCallback( @@ -157,7 +162,6 @@ export const ProcessEventDot = styled( nodeId, }, }); - focusEvent.currentTarget.setAttribute('aria-current', 'true'); }, [dispatch, nodeId] ); @@ -167,8 +171,14 @@ export const ProcessEventDot = styled( if (clickTargetRef.current !== null) { (clickTargetRef.current as any).beginElement(); } + dispatch({ + type: 'userSelectedResolverNode', + payload: { + nodeId, + }, + }); }, - [clickTargetRef] + [clickTargetRef, dispatch, nodeId] ); return ( @@ -184,7 +194,8 @@ export const ProcessEventDot = styled( aria-labelledby={labelId} aria-describedby={descriptionId} aria-haspopup={'true'} - aria-selected={isActiveDescendant ? 'true' : undefined} + aria-current={isActiveDescendant ? 'true' : undefined} + aria-selected={isSelectedDescendant ? 'true' : undefined} style={nodeViewportStyle} id={nodeId} onClick={handleClick} @@ -271,6 +282,13 @@ export const ProcessEventDot = styled( white-space: nowrap; will-change: left, top, width, height; contain: strict; + + &[aria-current] { + outline: 1px solid red; + } + &[aria-selected] { + background: gray; + } `; const processTypeToCube: Record = { From 9e182b64fe7e33bb342a27a4ab87c4e4df066f6a Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Tue, 31 Mar 2020 16:24:50 -0400 Subject: [PATCH 03/14] fix spelling mistake --- .../endpoint/public/embeddables/resolver/store/reducer.ts | 2 +- .../public/embeddables/resolver/store/ui/selectors.ts | 5 +++-- x-pack/plugins/endpoint/public/embeddables/resolver/types.ts | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts index 39433cae461bd..c12762a560edf 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts @@ -10,7 +10,7 @@ import { dataReducer } from './data/reducer'; import { ResolverState, ResolverAction, ResolverUIState } from '../types'; const uiReducer: Reducer = ( - uiState = { activeDescendentId: null, selectedDescendantId: null }, + uiState = { activeDescendantId: null, selectedDescendantId: null }, action ) => { if (action.type === 'userFocusedOnResolverNode') { diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/ui/selectors.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/ui/selectors.ts index 5bcb0c0356300..196e834c406b3 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/ui/selectors.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/ui/selectors.ts @@ -12,8 +12,9 @@ import { ResolverUIState } from '../../types'; */ export const activeDescendantId = createSelector( (uiState: ResolverUIState) => uiState, - ({ activeDescendentId }) => { - return activeDescendentId; + /* eslint-disable no-shadow */ + ({ activeDescendantId }) => { + return activeDescendantId; } ); diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts index 3bda820a64684..d370bda0d1842 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts @@ -37,7 +37,7 @@ export interface ResolverUIState { /** * The ID attribute of the resolver's aria-activedescendent. */ - readonly activeDescendentId: string | null; + readonly activeDescendantId: string | null; /** * The ID attribute of the resolver's currently selected descendant. */ From b687ea1c5008377beee790f387c0de133988b339 Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Wed, 1 Apr 2020 10:40:35 -0400 Subject: [PATCH 04/14] placeholder to see active state --- .../public/embeddables/resolver/view/process_event_dot.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index 14942a0ba426b..e2aeb75e78bc9 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -209,6 +209,11 @@ export const ProcessEventDot = styled( tabIndex={-1} > + {/** + * placheholer until we get the real asset + */} + Date: Wed, 1 Apr 2020 14:26:17 -0400 Subject: [PATCH 05/14] w/placeholder hex to demonstrate focus animation --- .../embeddables/resolver/store/reducer.ts | 2 +- .../resolver/view/process_event_dot.tsx | 34 ++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts index c12762a560edf..649bb40bbe9bb 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts @@ -16,7 +16,7 @@ const uiReducer: Reducer = ( if (action.type === 'userFocusedOnResolverNode') { return { ...uiState, - activeDescendentId: action.payload.nodeId, + activeDescendantId: action.payload.nodeId, }; } else if (action.type === 'userSelectedResolverNode') { return { diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index e2aeb75e78bc9..85ae9f23b8520 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -209,11 +209,24 @@ export const ProcessEventDot = styled( tabIndex={-1} > - {/** - * placheholer until we get the real asset - */} - + + + + + Date: Wed, 1 Apr 2020 17:12:43 -0400 Subject: [PATCH 06/14] active style w/ path animation --- .../resolver/view/process_event_dot.tsx | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index 85ae9f23b8520..4e0e984355306 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -210,23 +210,16 @@ export const ProcessEventDot = styled( > - - - + resolver backing + + Date: Wed, 1 Apr 2020 17:29:18 -0400 Subject: [PATCH 07/14] position adjustment --- .../public/embeddables/resolver/store/selectors.ts | 2 +- .../resolver/view/process_event_dot.tsx | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts index e03b7836fdf11..e8ae3d08e5cb6 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/selectors.ts @@ -69,7 +69,7 @@ export const uiActiveDescendantId = composeSelectors( ); /** - * Returns the id of the "selected" tree node (fake-focused) + * Returns the id of the "selected" tree node (the node that is currently "pressed" and possibly controlling other popups / components) */ export const uiSelectedDescendantId = composeSelectors( uiStateSelector, diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index 4e0e984355306..c8702c36a1e45 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -210,14 +210,20 @@ export const ProcessEventDot = styled( > resolver backing - + = { From dd90b83915cb509e3ccb0a75054bf5c6bda6e123 Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Wed, 1 Apr 2020 17:35:18 -0400 Subject: [PATCH 08/14] active descendant to parent --- .../plugins/endpoint/public/embeddables/resolver/view/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx index b1d77be669cbf..36155ece57a9c 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/index.tsx @@ -59,6 +59,7 @@ export const Resolver = styled( const { projectionMatrix, ref, onMouseDown } = useCamera(); const isLoading = useSelector(selectors.isLoading); + const activeDescendantId = useSelector(selectors.uiActiveDescendantId); useLayoutEffect(() => { dispatch({ @@ -80,6 +81,7 @@ export const Resolver = styled( ref={ref} role="tree" tabIndex={0} + aria-activedescendant={activeDescendantId || undefined} > {edgeLineSegments.map(([startPosition, endPosition], index) => ( Date: Thu, 2 Apr 2020 11:03:42 -0400 Subject: [PATCH 09/14] add backing to match comp & transfer outline shape to defs --- .../public/embeddables/resolver/view/defs.tsx | 10 ++++++++ .../resolver/view/process_event_dot.tsx | 24 +++++++++---------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx index 911cda1be6517..8ee9bfafc630e 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx @@ -193,6 +193,7 @@ export const SymbolIds = { runningTriggerCube: idGenerator('runningTriggerCube'), terminatedProcessCube: idGenerator('terminatedCube'), terminatedTriggerCube: idGenerator('terminatedTriggerCube'), + processCubeActiveBacking: idGenerator('activeBacking'), }; /** @@ -393,6 +394,15 @@ const SymbolsAndShapes = memo(() => ( /> + + resolver active backing + + )); diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index c8702c36a1e45..bb5085ab6b407 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -209,23 +209,21 @@ export const ProcessEventDot = styled( tabIndex={-1} > - - resolver backing - - - + className="backing" + /> + Date: Thu, 2 Apr 2020 11:28:29 -0400 Subject: [PATCH 10/14] switch to fixed positioning --- .../embeddables/resolver/view/process_event_dot.tsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index bb5085ab6b407..1c5737405981a 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -217,13 +217,7 @@ export const ProcessEventDot = styled( height={markerSize * 1.5} className="backing" /> - + Date: Thu, 2 Apr 2020 13:58:06 -0400 Subject: [PATCH 11/14] better documentation to differentiate UI actions --- .../public/embeddables/resolver/store/actions.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts index a83064474cc2c..a26f43e1f8cc0 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts @@ -45,7 +45,11 @@ interface AppRequestedResolverData { } /** - * When the user switches the active descendent of the Resolver. + * When the user switches the "active descendant" of the Resolver. + * The "active descendant" (from the point of view of the parent element) + * corresponds to the "current" child element. "active" or "current" here meaning + * the element that is focused on by the user's interactions with the UI, but + * not necessarily "selected" (see UserSelectedResolverNode below) */ interface UserFocusedOnResolverNode { readonly type: 'userFocusedOnResolverNode'; @@ -59,6 +63,9 @@ interface UserFocusedOnResolverNode { /** * When the user "selects" a node in the Resolver + * "Selected" refers to the state of being the element that the + * user most recently "picked" (by e.g. pressing a button corresponding + * to the element in a list) as opposed to "active" or "current" (see UserFocusedOnResolverNode above). */ interface UserSelectedResolverNode { readonly type: 'userSelectedResolverNode'; From bd73015fd9f8ecbe4e0eeb85eb4f7c3b3509e15f Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Thu, 2 Apr 2020 15:06:32 -0400 Subject: [PATCH 12/14] late change: sync panel icon click --- .../public/embeddables/resolver/store/reducer.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts index 649bb40bbe9bb..60f79da4aa9da 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts @@ -4,10 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ import { Reducer, combineReducers } from 'redux'; +import { htmlIdGenerator } from '@elastic/eui'; import { animateProcessIntoView } from './methods'; import { cameraReducer } from './camera/reducer'; import { dataReducer } from './data/reducer'; import { ResolverState, ResolverAction, ResolverUIState } from '../types'; +import { uniquePidForProcess } from '../models/process_event'; + +const resolverNodeIdGenerator = htmlIdGenerator('resolverNode'); const uiReducer: Reducer = ( uiState = { activeDescendantId: null, selectedDescendantId: null }, @@ -23,6 +27,12 @@ const uiReducer: Reducer = ( ...uiState, selectedDescendantId: action.payload.nodeId, }; + } else if (action.type === 'userBroughtProcessIntoView') { + const processNodeId = resolverNodeIdGenerator(uniquePidForProcess(action.payload.process)); + return { + ...uiState, + activeDescendantId: processNodeId, + }; } else { return uiState; } From c6d457fac97f4e98eadabc301003a59924d693cf Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Fri, 3 Apr 2020 15:33:10 -0400 Subject: [PATCH 13/14] Robert Austin review: add comments, remove useMemo --- .../public/embeddables/resolver/store/reducer.ts | 10 ++++++++++ .../embeddables/resolver/view/process_event_dot.tsx | 13 ++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts index 60f79da4aa9da..61a46c9d98ea1 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts @@ -11,6 +11,11 @@ import { dataReducer } from './data/reducer'; import { ResolverState, ResolverAction, ResolverUIState } from '../types'; import { uniquePidForProcess } from '../models/process_event'; +/** + * Despite the name "generator", this function is entirely determinant + * (i.e. it will return the same html id given the same prefix 'resolverNode' + * and nodeId) +*/ const resolverNodeIdGenerator = htmlIdGenerator('resolverNode'); const uiReducer: Reducer = ( @@ -28,6 +33,11 @@ const uiReducer: Reducer = ( selectedDescendantId: action.payload.nodeId, }; } else if (action.type === 'userBroughtProcessIntoView') { + /** + * This action has a process payload (instead of a processId), so we use + * `uniquePidForProcess` and `resolverNodeIdGenerator` to resolve the determinant + * html id of the node being brought into view. + */ const processNodeId = resolverNodeIdGenerator(uniquePidForProcess(action.payload.process)); return { ...uiState, diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index 1c5737405981a..2e3981de74d34 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -148,13 +148,8 @@ export const ProcessEventDot = styled( const labelId = useMemo(() => resolverNodeIdGenerator(), [resolverNodeIdGenerator]); const descriptionId = useMemo(() => resolverNodeIdGenerator(), [resolverNodeIdGenerator]); - const isActiveDescendant = useMemo(() => { - return nodeId === activeDescendantId; - }, [activeDescendantId, nodeId]); - - const isSelectedDescendant = useMemo(() => { - return nodeId === selectedDescendantId; - }, [selectedDescendantId, nodeId]); + const isActiveDescendant = nodeId === activeDescendantId; + const isSelectedDescendant = nodeId === selectedDescendantId; const dispatch = useResolverDispatch(); @@ -298,6 +293,10 @@ export const ProcessEventDot = styled( will-change: left, top, width, height; contain: strict; + //dasharray & dashoffset should be equal to "pull" the stroke back + //when it is transitioned. + //The value is tuned to look good when animated, but to preserve + //the effect, it should always be _at least_ the length of the stroke & .backing { stroke-dasharray: 500; stroke-dashoffset: 500; From 96394a8c7a69b01c0c98fa781fd960e00ed8bacd Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Fri, 3 Apr 2020 15:37:35 -0400 Subject: [PATCH 14/14] Robert Austin review: add comments to reducer --- .../endpoint/public/embeddables/resolver/store/reducer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts index 61a46c9d98ea1..82206d77f8349 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/reducer.ts @@ -15,7 +15,7 @@ import { uniquePidForProcess } from '../models/process_event'; * Despite the name "generator", this function is entirely determinant * (i.e. it will return the same html id given the same prefix 'resolverNode' * and nodeId) -*/ + */ const resolverNodeIdGenerator = htmlIdGenerator('resolverNode'); const uiReducer: Reducer = ( @@ -37,7 +37,7 @@ const uiReducer: Reducer = ( * This action has a process payload (instead of a processId), so we use * `uniquePidForProcess` and `resolverNodeIdGenerator` to resolve the determinant * html id of the node being brought into view. - */ + */ const processNodeId = resolverNodeIdGenerator(uniquePidForProcess(action.payload.process)); return { ...uiState,