"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.GraphControls = void 0; var _react = _interopRequireWildcard(require("react")); var _styledComponents = _interopRequireDefault(require("styled-components")); var _i18n = require("@kbn/i18n"); var _eui = require("@elastic/eui"); var _reactRedux = require("react-redux"); var _side_effect_context = require("./side_effect_context"); var selectors = _interopRequireWildcard(require("../store/selectors")); var _use_colors = require("./use_colors"); var _styles = require("./panels/styles"); var _cube_for_process = require("./panels/cube_for_process"); var _generated_text = require("./generated_text"); var _action = require("../store/camera/action"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ // EuiRange is currently only horizontally positioned. This reorients the track to a vertical position const StyledEuiRange = (0, _styledComponents.default)(_eui.EuiRange)` & .euiRangeTrack:after { left: -65px; transform: rotate(90deg); } `; const StyledGraphControlsColumn = _styledComponents.default.div` display: flex; flex-direction: column; &:not(last-of-type) { margin-right: 5px; } `; const StyledEuiDescriptionListTitle = (0, _styledComponents.default)(_eui.EuiDescriptionListTitle)` text-transform: uppercase; max-width: 25%; `; const StyledEuiDescriptionListDescription = (0, _styledComponents.default)(_eui.EuiDescriptionListDescription)` min-width: 75%; width: 75%; `; const StyledEuiButtonIcon = (0, _styledComponents.default)(_eui.EuiButtonIcon)` background-color: ${props => props.$backgroundColor}; color: ${props => props.$iconColor}; border-color: ${props => props.$borderColor}; border-width: 1px; border-style: solid; border-radius: 4px; width: 40px; height: 40px; &:not(last-of-type) { margin-bottom: 7px; } `; const StyledGraphControls = _styledComponents.default.div` display: flex; flex-direction: row; position: absolute; top: 5px; right: 5px; background-color: transparent; color: ${props => props.$iconColor}; .zoom-controls { display: flex; flex-direction: column; align-items: center; padding: 5px 0px; .zoom-slider { width: 20px; height: 150px; margin: 5px 0px 2px 0px; input[type='range'] { width: 150px; height: 20px; transform-origin: 75px 75px; transform: rotate(-90deg); } } } .panning-controls { text-align: center; } `; /** * Controls for zooming, panning, and centering in Resolver */ // eslint-disable-next-line react/display-name const GraphControls = /*#__PURE__*/_react.default.memo(({ id, className }) => { const dispatch = (0, _reactRedux.useDispatch)(); const scalingFactor = (0, _reactRedux.useSelector)(state => selectors.scalingFactor(state.analyzer[id])); const { timestamp } = (0, _react.useContext)(_side_effect_context.SideEffectContext); const [activePopover, setPopover] = (0, _react.useState)(null); const colorMap = (0, _use_colors.useColors)(); const setActivePopover = (0, _react.useCallback)(value => { if (value === activePopover) { setPopover(null); } else { setPopover(value); } }, [setPopover, activePopover]); const closePopover = (0, _react.useCallback)(() => setPopover(null), []); const handleZoomAmountChange = (0, _react.useCallback)(event => { const valueAsNumber = parseFloat(event.target.value); if (isNaN(valueAsNumber) === false) { dispatch((0, _action.userSetZoomLevel)({ id, zoomLevel: valueAsNumber })); } }, [dispatch, id]); const handleCenterClick = (0, _react.useCallback)(() => { dispatch((0, _action.userSetPositionOfCamera)({ id, cameraView: [0, 0] })); }, [dispatch, id]); const handleZoomOutClick = (0, _react.useCallback)(() => { dispatch((0, _action.userClickedZoomOut)({ id })); }, [dispatch, id]); const handleZoomInClick = (0, _react.useCallback)(() => { dispatch((0, _action.userClickedZoomIn)({ id })); }, [dispatch, id]); const [handleNorth, handleEast, handleSouth, handleWest] = (0, _react.useMemo)(() => { const directionVectors = [[0, 1], [1, 0], [0, -1], [-1, 0]]; return directionVectors.map(direction => { return () => { dispatch((0, _action.userNudgedCamera)({ id, direction, time: timestamp() })); }; }); }, [dispatch, timestamp, id]); /* eslint-disable react/button-has-type */ return /*#__PURE__*/_react.default.createElement(StyledGraphControls, { className: className, $iconColor: colorMap.graphControls, "data-test-subj": "resolver:graph-controls" }, /*#__PURE__*/_react.default.createElement(StyledGraphControlsColumn, null, /*#__PURE__*/_react.default.createElement(SchemaInformation, { id: id, closePopover: closePopover, isOpen: activePopover === 'schemaInfo', setActivePopover: setActivePopover }), /*#__PURE__*/_react.default.createElement(NodeLegend, { id: id, closePopover: closePopover, isOpen: activePopover === 'nodeLegend', setActivePopover: setActivePopover })), /*#__PURE__*/_react.default.createElement(StyledGraphControlsColumn, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, { className: "panning-controls", paddingSize: "none", hasBorder: true }, /*#__PURE__*/_react.default.createElement("div", { className: "panning-controls-top" }, /*#__PURE__*/_react.default.createElement("button", { className: "north-button", "data-test-subj": "resolver:graph-controls:north-button", title: _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.north', { defaultMessage: 'North' }), onClick: handleNorth }, /*#__PURE__*/_react.default.createElement(_eui.EuiIcon, { type: "arrowUp" }))), /*#__PURE__*/_react.default.createElement("div", { className: "panning-controls-middle" }, /*#__PURE__*/_react.default.createElement("button", { className: "west-button", "data-test-subj": "resolver:graph-controls:west-button", title: _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.west', { defaultMessage: 'West' }), onClick: handleWest }, /*#__PURE__*/_react.default.createElement(_eui.EuiIcon, { type: "arrowLeft" })), /*#__PURE__*/_react.default.createElement("button", { className: "center-button", "data-test-subj": "resolver:graph-controls:center-button", title: _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.center', { defaultMessage: 'Center' }), onClick: handleCenterClick }, /*#__PURE__*/_react.default.createElement(_eui.EuiIcon, { type: "bullseye" })), /*#__PURE__*/_react.default.createElement("button", { className: "east-button", "data-test-subj": "resolver:graph-controls:east-button", title: _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.east', { defaultMessage: 'East' }), onClick: handleEast }, /*#__PURE__*/_react.default.createElement(_eui.EuiIcon, { type: "arrowRight" }))), /*#__PURE__*/_react.default.createElement("div", { className: "panning-controls-bottom" }, /*#__PURE__*/_react.default.createElement("button", { className: "south-button", "data-test-subj": "resolver:graph-controls:south-button", title: _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.south', { defaultMessage: 'South' }), onClick: handleSouth }, /*#__PURE__*/_react.default.createElement(_eui.EuiIcon, { type: "arrowDown" })))), /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, { className: "zoom-controls", paddingSize: "none", hasBorder: true }, /*#__PURE__*/_react.default.createElement("button", { title: _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.zoomIn', { defaultMessage: 'Zoom In' }), "data-test-subj": "resolver:graph-controls:zoom-in", onClick: handleZoomInClick }, /*#__PURE__*/_react.default.createElement(_eui.EuiIcon, { type: "plusInCircle" })), /*#__PURE__*/_react.default.createElement(StyledEuiRange, { className: "zoom-slider", "data-test-subj": "resolver:graph-controls:zoom-slider", min: 0, max: 1, step: 0.01, value: scalingFactor, onChange: handleZoomAmountChange }), /*#__PURE__*/_react.default.createElement("button", { title: _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.zoomOut', { defaultMessage: 'Zoom Out' }), "data-test-subj": "resolver:graph-controls:zoom-out", onClick: handleZoomOutClick }, /*#__PURE__*/_react.default.createElement(_eui.EuiIcon, { type: "minusInCircle" }))))); /* eslint-enable react/button-has-type */ }); exports.GraphControls = GraphControls; const SchemaInformation = ({ id, closePopover, setActivePopover, isOpen }) => { var _sourceAndSchema$data, _sourceAndSchema$sche, _sourceAndSchema$sche2; const colorMap = (0, _use_colors.useColors)(); const sourceAndSchema = (0, _reactRedux.useSelector)(state => selectors.resolverTreeSourceAndSchema(state.analyzer[id])); const setAsActivePopover = (0, _react.useCallback)(() => setActivePopover('schemaInfo'), [setActivePopover]); const schemaInfoButtonTitle = _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.schemaInfoButtonTitle', { defaultMessage: 'Schema Information' }); const unknownSchemaValue = _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.unknownSchemaValue', { defaultMessage: 'Unknown' }); return /*#__PURE__*/_react.default.createElement(_eui.EuiPopover, { button: /*#__PURE__*/_react.default.createElement(StyledEuiButtonIcon, { "data-test-subj": "resolver:graph-controls:schema-info-button", size: "m", title: schemaInfoButtonTitle, "aria-label": schemaInfoButtonTitle, onClick: setAsActivePopover, iconType: "iInCircle", $backgroundColor: colorMap.graphControlsBackground, $iconColor: colorMap.graphControls, $borderColor: colorMap.graphControlsBorderColor }), isOpen: isOpen, closePopover: closePopover, anchorPosition: "leftCenter" }, /*#__PURE__*/_react.default.createElement(_eui.EuiPopoverTitle, { style: { textTransform: 'uppercase' } }, _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.schemaInfoTitle', { defaultMessage: 'process tree' }), /*#__PURE__*/_react.default.createElement(_eui.EuiIconTip, { content: _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.schemaInfoTooltip', { defaultMessage: 'These are the fields used to create the process tree' }), position: "right" })), /*#__PURE__*/_react.default.createElement("div", { // Limit the width based on UX design style: { maxWidth: '268px' } }, /*#__PURE__*/_react.default.createElement(_styles.StyledDescriptionList, { "data-test-subj": "resolver:graph-controls:schema-info", type: "column", align: "left", compressed: true }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListTitle, { "data-test-subj": "resolver:graph-controls:schema-info:title", style: { width: '30%' } }, _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.schemaSource', { defaultMessage: 'source' })), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListDescription, { "data-test-subj": "resolver:graph-controls:schema-info:description", style: { width: '70%' } }, /*#__PURE__*/_react.default.createElement(_generated_text.GeneratedText, null, (_sourceAndSchema$data = sourceAndSchema === null || sourceAndSchema === void 0 ? void 0 : sourceAndSchema.dataSource) !== null && _sourceAndSchema$data !== void 0 ? _sourceAndSchema$data : unknownSchemaValue)), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListTitle, { "data-test-subj": "resolver:graph-controls:schema-info:title", style: { width: '30%' } }, _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.schemaID', { defaultMessage: 'id' })), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListDescription, { "data-test-subj": "resolver:graph-controls:schema-info:description", style: { width: '70%' } }, /*#__PURE__*/_react.default.createElement(_generated_text.GeneratedText, null, (_sourceAndSchema$sche = sourceAndSchema === null || sourceAndSchema === void 0 ? void 0 : sourceAndSchema.schema.id) !== null && _sourceAndSchema$sche !== void 0 ? _sourceAndSchema$sche : unknownSchemaValue)), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListTitle, { "data-test-subj": "resolver:graph-controls:schema-info:title", style: { width: '30%' } }, _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.schemaEdge', { defaultMessage: 'edge' })), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListDescription, { "data-test-subj": "resolver:graph-controls:schema-info:description", style: { width: '70%' } }, /*#__PURE__*/_react.default.createElement(_generated_text.GeneratedText, null, (_sourceAndSchema$sche2 = sourceAndSchema === null || sourceAndSchema === void 0 ? void 0 : sourceAndSchema.schema.parent) !== null && _sourceAndSchema$sche2 !== void 0 ? _sourceAndSchema$sche2 : unknownSchemaValue)))))); }; // This component defines the cube legend that allows users to identify the meaning of the cubes // Should be updated to be dynamic if and when non process based resolvers are possible const NodeLegend = ({ id, closePopover, setActivePopover, isOpen }) => { const setAsActivePopover = (0, _react.useCallback)(() => setActivePopover('nodeLegend'), [setActivePopover]); const colorMap = (0, _use_colors.useColors)(); const nodeLegendButtonTitle = _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.nodeLegendButtonTitle', { defaultMessage: 'Node Legend' }); return /*#__PURE__*/_react.default.createElement(_eui.EuiPopover, { button: /*#__PURE__*/_react.default.createElement(StyledEuiButtonIcon, { "data-test-subj": "resolver:graph-controls:node-legend-button", size: "m", title: nodeLegendButtonTitle, "aria-label": nodeLegendButtonTitle, onClick: setAsActivePopover, iconType: "node", $backgroundColor: colorMap.graphControlsBackground, $iconColor: colorMap.graphControls, $borderColor: colorMap.graphControlsBorderColor }), isOpen: isOpen, closePopover: closePopover, anchorPosition: "leftCenter" }, /*#__PURE__*/_react.default.createElement(_eui.EuiPopoverTitle, { style: { textTransform: 'uppercase' } }, _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.nodeLegend', { defaultMessage: 'legend' })), /*#__PURE__*/_react.default.createElement("div", { // Limit the width based on UX design style: { maxWidth: '212px' } }, /*#__PURE__*/_react.default.createElement(_styles.StyledDescriptionList, { "data-test-subj": "resolver:graph-controls:node-legend", type: "column", align: "left", compressed: true }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListTitle, { "data-test-subj": "resolver:graph-controls:node-legend:title", style: { width: '20% ' } }, /*#__PURE__*/_react.default.createElement(_cube_for_process.CubeForProcess, { id: id, size: "2.5em", "data-test-subj": "resolver:node-detail:title-icon", state: "running" })), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListDescription, { "data-test-subj": "resolver:graph-controls:node-legend:description", style: { width: '80%', lineHeight: '2.2em' } // lineHeight to align center vertically }, /*#__PURE__*/_react.default.createElement(_generated_text.GeneratedText, null, _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.runningProcessCube', { defaultMessage: 'Running Process' }))), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListTitle, { "data-test-subj": "resolver:graph-controls:node-legend:title", style: { width: '20% ' } }, /*#__PURE__*/_react.default.createElement(_cube_for_process.CubeForProcess, { id: id, size: "2.5em", "data-test-subj": "resolver:node-detail:title-icon", state: "terminated" })), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListDescription, { "data-test-subj": "resolver:graph-controls:node-legend:description", style: { width: '80%', lineHeight: '2.2em' } }, /*#__PURE__*/_react.default.createElement(_generated_text.GeneratedText, null, _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.terminatedProcessCube', { defaultMessage: 'Terminated Process' }))), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListTitle, { "data-test-subj": "resolver:graph-controls:node-legend:title", style: { width: '20% ' } }, /*#__PURE__*/_react.default.createElement(_cube_for_process.CubeForProcess, { id: id, size: "2.5em", "data-test-subj": "resolver:node-detail:title-icon", state: "loading" })), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListDescription, { "data-test-subj": "resolver:graph-controls:node-legend:description", style: { width: '80%', lineHeight: '2.2em' } }, /*#__PURE__*/_react.default.createElement(_generated_text.GeneratedText, null, _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.currentlyLoadingCube', { defaultMessage: 'Loading Process' }))), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListTitle, { "data-test-subj": "resolver:graph-controls:node-legend:title", style: { width: '20% ' } }, /*#__PURE__*/_react.default.createElement(_cube_for_process.CubeForProcess, { id: id, size: "2.5em", "data-test-subj": "resolver:node-detail:title-icon", state: "error" })), /*#__PURE__*/_react.default.createElement(StyledEuiDescriptionListDescription, { "data-test-subj": "resolver:graph-controls:node-legend:description", style: { width: '80%', lineHeight: '2.2em' } }, /*#__PURE__*/_react.default.createElement(_generated_text.GeneratedText, null, _i18n.i18n.translate('xpack.securitySolution.resolver.graphControls.errorCube', { defaultMessage: 'Error Process' }))))))); };