Skip to content

Commit

Permalink
chore(matchExpr): clean up and save graph positions
Browse files Browse the repository at this point in the history
Signed-off-by: Thuan Vo <[email protected]>
  • Loading branch information
Thuan Vo committed Mar 22, 2023
1 parent 3ed4d7c commit ff12a36
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 13 deletions.
5 changes: 2 additions & 3 deletions src/app/Rules/CreateRule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ const CreateRuleForm: React.FC<CreateRuleFormProps> = ({ ...props }) => {
}
setMatchExpressionValid(validation);
matchedTargets.next(matches);
console.log(matchExpression);
}, [matchExpression, targets, matchedTargets, setMatchExpressionValid, setTemplateName]);

const createButtonLoadingProps = React.useMemo(
Expand Down Expand Up @@ -634,14 +633,14 @@ const Comp: React.FC = () => {
<Grid hasGutter style={gridStyles}>
<GridItem xl={5} order={{ xl: '0', default: '1' }}>
<Card isFullHeight>
<CardBody style={{ overflow: 'auto' }}>
<CardBody className="overflow-auto">
<CreateRuleForm />
</CardBody>
</Card>
</GridItem>
<GridItem xl={7} order={{ xl: '1', default: '0' }}>
<Card isFullHeight>
<CardBody style={{ overflow: 'auto' }}>
<CardBody className="overflow-auto">
<MatchExpressionVisualizer />
</CardBody>
</Card>
Expand Down
4 changes: 2 additions & 2 deletions src/app/SecurityPanel/Credentials/CreateCredentialModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export const CreateCredentialModal: React.FunctionComponent<CreateCredentialModa
<Grid hasGutter style={{ height: '100%' }}>
<GridItem xl={4}>
<Card isFullHeight isFlat>
<CardBody style={{ overflow: 'auto' }}>
<CardBody className="overflow-auto">
<AuthForm
visible={visible}
onDismiss={onDismiss}
Expand All @@ -105,7 +105,7 @@ export const CreateCredentialModal: React.FunctionComponent<CreateCredentialModa
</GridItem>
<GridItem xl={8}>
<Card isFullHeight isFlat>
<CardBody style={{ overflow: 'auto' }}>
<CardBody className="overflow-auto">
<MatchExpressionVisualizer alertOptions={alertOptions} />
</CardBody>
</Card>
Expand Down
73 changes: 66 additions & 7 deletions src/app/Shared/MatchExpression/MatchExpressionVisualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,17 @@
* SOFTWARE.
*/
import { TopologyControlBar } from '@app/Topology/GraphView/TopologyControlBar';
import { SavedGraphPosition, SavedNodePosition } from '@app/Topology/GraphView/TopologyGraphView';
import { getNodeById } from '@app/Topology/GraphView/UtilsFactory';
import EntityDetails, { AlertOptions } from '@app/Topology/Shared/Entity/EntityDetails';
import { useSearchExpression } from '@app/Topology/Shared/utils';
import { TopologySideBar } from '@app/Topology/SideBar/TopologySideBar';
import { NodeType } from '@app/Topology/typings';
import { getFromLocalStorage, saveToLocalStorage } from '@app/utils/LocalStorage';
import { useSubscriptions } from '@app/utils/useSubscriptions';
import { evaluateTargetWithExpr, hashCode } from '@app/utils/utils';
import {
Bullseye,
Button,
DataList,
DataListCell,
DataListContent,
Expand All @@ -69,19 +70,18 @@ import { ContainerNodeIcon, SearchIcon } from '@patternfly/react-icons';
import { css } from '@patternfly/react-styles';
import {
action,
BOTTOM_LAYER,
DEFAULT_LAYER,
GraphElement,
GROUPS_LAYER,
GRAPH_POSITION_CHANGE_EVENT,
Model,
NODE_POSITIONED_EVENT,
SelectionEventListener,
SELECTION_EVENT,
TopologyView,
TOP_LAYER,
Visualization,
VisualizationProvider,
VisualizationSurface,
} from '@patternfly/react-topology';
import _ from 'lodash';
import * as React from 'react';
import { ServiceContext } from '../Services/Services';
import { Target } from '../Services/Target.service';
Expand Down Expand Up @@ -170,6 +170,40 @@ const GraphView: React.FC<{ alertOptions?: AlertOptions }> = ({ alertOptions, ..
setSelectedEntity(ids[0] ? _newVisualization.getElementById(ids[0]) : undefined);
});

_newVisualization.addEventListener(
GRAPH_POSITION_CHANGE_EVENT,
_.debounce(() => {
const { graph } = _newVisualization.toModel();
if (graph) {
const saved: SavedGraphPosition = {
id: graph.id,
type: graph.type,
x: graph.x,
y: graph.y,
scale: graph.scale,
scaleExtent: graph.scaleExtent,
};
saveToLocalStorage('MATCH_EXPRES_VIS_GRAPH_POSITIONS', saved);
}
}, 200)
);

_newVisualization.addEventListener(
NODE_POSITIONED_EVENT,
_.debounce(() => {
const { nodes } = _newVisualization.toModel();
if (nodes) {
const savedPos: SavedNodePosition[] = nodes.map((n) => ({
id: n.id,
x: n.x,
y: n.y,
collapsed: n.collapsed,
}));
saveToLocalStorage('MATCH_EXPRES_VIS_NODE_POSITIONS', savedPos);
}
}, 200)
);

return _newVisualization;
}, [setSelectedIds, setSelectedEntity]);

Expand All @@ -184,8 +218,22 @@ const GraphView: React.FC<{ alertOptions?: AlertOptions }> = ({ alertOptions, ..
}, [addSubscription, context.targets, setTargets]);

React.useEffect(() => {
const graphData: SavedGraphPosition = getFromLocalStorage('MATCH_EXPRES_VIS_GRAPH_POSITIONS', {});
const nodePositions: SavedNodePosition[] = getFromLocalStorage('MATCH_EXPRES_VIS_NODE_POSITIONS', []);

const model: Model = {
nodes: _transformedData.nodes,
nodes: _transformedData.nodes.map((n) => {
const savedData = nodePositions.find((ps) => ps.id === n.id);
if (savedData) {
n = {
...n,
x: savedData.x,
y: savedData.y,
collapsed: savedData.collapsed,
};
}
return n;
}),
edges: _transformedData.edges,
graph: {
id: 'cryostat-match-expression-visualizer',
Expand All @@ -198,12 +246,23 @@ const GraphView: React.FC<{ alertOptions?: AlertOptions }> = ({ alertOptions, ..
labels: {},
children: targetNodes,
},
x: graphData.x,
y: graphData.y,
scale: graphData.scale,
scaleExtent: graphData.scaleExtent,
},
};

// Initialize the controller with model to create nodes
visualization.fromModel(model, false);
const _id = setTimeout(action(() => visualization.getGraph().fit()));

const _id = setTimeout(
action(() => {
if (!graphData.id || !graphData.x || !graphData.y) {
visualization.getGraph().fit();
}
})
);
return () => clearTimeout(_id);
}, [_transformedData, targetNodes, visualization]);

Expand Down
4 changes: 4 additions & 0 deletions src/app/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -519,3 +519,7 @@ input[type=number].datetime-picker__number-input {
width: 80% !important;
height: 80%;
}

.overflow-auto {
overflow: auto;
}
2 changes: 2 additions & 0 deletions src/app/utils/LocalStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export enum LocalStorageKey {
NOTIFICATIONS_ENABLED,
WEBSOCKET_DEBOUNCE_MS,
DATETIME_FORMAT,
MATCH_EXPRES_VIS_GRAPH_POSITIONS,
MATCH_EXPRES_VIS_NODE_POSITIONS,
}

export type LocalStorageKeyStrings = keyof typeof LocalStorageKey;
Expand Down
2 changes: 1 addition & 1 deletion src/test/Rules/CreateRule.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { Rule } from '@app/Rules/Rules';
import { defaultServices } from '@app/Shared/Services/Services';
import { Target } from '@app/Shared/Services/Target.service';
import '@testing-library/jest-dom';
import { act, cleanup, screen, waitFor } from '@testing-library/react';
import { cleanup, screen, waitFor } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import * as React from 'react';
import { of } from 'rxjs';
Expand Down

0 comments on commit ff12a36

Please sign in to comment.