diff --git a/redisinsight/ui/src/packages/redisgraph/src/Graph.tsx b/redisinsight/ui/src/packages/redisgraph/src/Graph.tsx index 4dd68eb185..a9612afc86 100644 --- a/redisinsight/ui/src/packages/redisgraph/src/Graph.tsx +++ b/redisinsight/ui/src/packages/redisgraph/src/Graph.tsx @@ -1,9 +1,10 @@ -import { useEffect, useRef, useState, useMemo } from 'react' +import React, { useEffect, useRef, useState, useMemo } from 'react' import * as d3 from 'd3' import { executeRedisCommand } from 'redisinsight-plugin-sdk' import { EuiButtonIcon, EuiToolTip, + EuiSwitch, } from '@elastic/eui' import Graphd3, { IGraphD3 } from './graphd3' import { responseParser } from './parser' @@ -49,6 +50,7 @@ export default function Graph(props: { graphKey: string, data: any[] }) { const [container, setContainer] = useState(null) const [selectedEntity, setSelectedEntity] = useState(null) const [start, setStart] = useState(false) + const [showAutomaticEdges, setShowAutomaticEdges] = useState(true); const parsedResponse = responseParser(props.data) let nodeIds = new Set(parsedResponse.nodes.map(n => n.id)) @@ -135,7 +137,7 @@ export default function Graph(props: { graphKey: string, data: any[] }) { .filter(e => nodeIds.has(e.source) && nodeIds.has(e.target) && !edgeIds.has(e.id)) .map(e => { newEdgeTypes[e.type] = (newEdgeTypes[e.type] + 1 || 1) - return ({ ...e, startNode: e.source, endNode: e.target }) + return ({ ...e, startNode: e.source, endNode: e.target, fetchedAutomatically: true }) }) setGraphData({ @@ -250,6 +252,18 @@ export default function Graph(props: { graphKey: string, data: any[] }) { return (
+
+ + { + container.toggleShowAutomaticEdges() + setShowAutomaticEdges(!showAutomaticEdges) + }} + /> + +
{ @@ -259,14 +273,14 @@ export default function Graph(props: { graphKey: string, data: any[] }) { Object.keys(nodeLabels).map((item, i) => (
{item}
)) } -
+
) } { @@ -295,7 +309,7 @@ export default function Graph(props: { graphKey: string, data: any[] }) { selectedEntity.type === EntityType.Node ?
{selectedEntity.property}
: -
{selectedEntity.property}
+
{selectedEntity.property}
} setSelectedEntity(null)} display="empty" iconType="cross" aria-label="Close" />
@@ -303,9 +317,7 @@ export default function Graph(props: { graphKey: string, data: any[] }) { { Object.keys(selectedEntity.props).map(k => [k, selectedEntity.props[k]]).reduce( (a, b) => a.concat(b), [] - ).map(k => -
{k}
- ) + ).map(k =>
{k}
) } diff --git a/redisinsight/ui/src/packages/redisgraph/src/graphd3.ts b/redisinsight/ui/src/packages/redisgraph/src/graphd3.ts index b0f31920c8..f37fb2e40f 100644 --- a/redisinsight/ui/src/packages/redisgraph/src/graphd3.ts +++ b/redisinsight/ui/src/packages/redisgraph/src/graphd3.ts @@ -571,6 +571,10 @@ interface INode extends d3.SimulationNodeDatum { properties: { [key: string]: string | number | object } labels: string[] color: string + angleX: number + angleY: number + links: string[] + targetLabels: {[label: string]: number} } interface IRelationship extends d3.SimulationLinkDatum{ @@ -592,6 +596,7 @@ interface IRelationship extends d3.SimulationLinkDatum{ shaftLength: number midShaftPoint: Point } + fetchedAutomatically?: boolean } interface IGraph { @@ -615,11 +620,13 @@ export interface IGraphD3 { updateWithD3Data: (d3Data: any) => void updateWithGraphData: (graphData: any) => void zoomFuncs: IZoomFuncs + toggleShowAutomaticEdges: () => void } function GraphD3(_selector: HTMLDivElement, _options: any): IGraphD3 { let info: any let nodes: INode[] + let shouldShowAutomaticEdges = true; let relationship: d3.Selection let labelCounter = 0; let labels: { [key: string]: number } = { } @@ -983,7 +990,7 @@ function GraphD3(_selector: HTMLDivElement, _options: any): IGraphD3 { function appendRelationship() { return relationship.enter() .append('g') - .attr('class', 'relationship') + .attr('class', r => `relationship relationship-${r.id}`) .on('dblclick', function onRelationshipDoubleClick(event, d) { if (typeof options.onRelationshipDoubleClick === 'function') { options.onRelationshipDoubleClick(this, d, event) @@ -1046,7 +1053,6 @@ function GraphD3(_selector: HTMLDivElement, _options: any): IGraphD3 { function updateRelationships(r: IRelationship) { Array.prototype.push.apply(relationships, r) - let a = svgRelationships.selectAll('.relationship') relationship = svgRelationships .selectAll('.relationship') @@ -1071,14 +1077,31 @@ function GraphD3(_selector: HTMLDivElement, _options: any): IGraphD3 { n = n.filter(k => !nodeIds.includes(k.id)) let edgeIds = relationships.map(e => e.id) + const previousEdges = [...r] r = r.filter(k => !edgeIds.includes(k.id)) + if (relationship !== undefined) { + relationship.each(r => { + // If an edge is being fetchedAutomatically and is now added + // in new data, mark fetchedAutomatically to false. + if (r.fetchedAutomatically && previousEdges.map(k => k.id).includes(r.id)) { + r.fetchedAutomatically = false; + } + }) + } + updateRelationships(r) updateNodes(n) simulation.nodes(nodes) simulation.force('link', d3.forceLink(relationships).id((d: IRelationship) => d.id)) + // Every time the function is run, do check whether automatically fetched edges must be rendered. + d3.selectAll('.relationship').each((r: IRelationship) => { + if (!shouldShowAutomaticEdges && r.fetchedAutomatically) { + d3.selectAll(`.relationship-${r.id}`).remove() + } + }) } function graphDataToD3Data(data) { @@ -1643,12 +1666,20 @@ function GraphD3(_selector: HTMLDivElement, _options: any): IGraphD3 { resize() + function toggleShowAutomaticEdges() { + // Simply re-run the function. `updateNodesAndRelationships` internally checks for `shouldShowAutomaticEdges` prop to render edges that were fetched automatically. + shouldShowAutomaticEdges = !shouldShowAutomaticEdges; + updateNodesAndRelationships([], []) + simulation.restart() + } + return { graphDataToD3Data, size, updateWithD3Data, updateWithGraphData, zoomFuncs, + toggleShowAutomaticEdges, } } diff --git a/redisinsight/ui/src/packages/redisgraph/src/styles/styles.less b/redisinsight/ui/src/packages/redisgraph/src/styles/styles.less index 20d7895a03..1a3c1168e5 100644 --- a/redisinsight/ui/src/packages/redisgraph/src/styles/styles.less +++ b/redisinsight/ui/src/packages/redisgraph/src/styles/styles.less @@ -263,3 +263,17 @@ .euiToolTip__arrow { background-color: var(--tooltip-background) !important; } + + +.automatic-edges-switch { + border-radius: 4px; + right: 4px; + position: absolute; + display: flex; + flex-direction: row; + color: var(--info-color); + margin-top: 12px !important; + margin-left: 24px !important; + font-size: 12px; + line-height: 18px; +}