Skip to content

Commit

Permalink
#1598 Prototype the mapping transformer application
Browse files Browse the repository at this point in the history
  • Loading branch information
tomlyn committed Oct 27, 2023
1 parent 2025e70 commit b952a17
Show file tree
Hide file tree
Showing 13 changed files with 1,487 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2304,7 +2304,6 @@ export default class SVGCanvasRenderer {
this.removeContextToolbar();
}


// Note: Comment and Node resizing is started by the comment/node highlight rectangle.
if (this.commentSizing) {
this.initializeResizeVariables(d);
Expand Down Expand Up @@ -2819,7 +2818,14 @@ export default class SVGCanvasRenderer {
.attr("height", (d) => d.height)
.attr("x", 0)
.attr("y", 0)
.each(addNodeExternalObject.bind(this));
.each(addNodeExternalObject.bind(
this,
this.canvasController,
this.activePipeline.nodes,
this.setPortPositions.bind(this),
this.setNodesProperties.bind(this),
this.raiseNodeToTopById.bind(this)
));

// Node Image
nonBindingNodeGrps
Expand Down Expand Up @@ -2918,6 +2924,54 @@ export default class SVGCanvasRenderer {
removeSel.remove();
}

setPortPositions(info) {
const node = this.activePipeline.getNode(info.nodeId);

if (info.inputPositions) {
info.inputPositions.forEach((inputPos) => {
const inp = node.inputs.find((input) => input.id === inputPos.id);

// TODO - Decide if zoomTransform should be passed to react object or not.
inp.cx = inputPos.cx / this.zoomTransform.k;
inp.cy = inputPos.cy / this.zoomTransform.k;
});
}
if (info.outputPositions) {
info.outputPositions.forEach((outputPos) => {
const out = node.outputs.find((output) => output.id === outputPos.id);
out.cx = outputPos.cx / this.zoomTransform.k;
out.cy = outputPos.cy / this.zoomTransform.k;
});
}
this.displayLinks();
}

setNodesProperties(newProps) {
if (newProps) {
newProps.forEach((np) => {
const node = this.activePipeline.getNode(np.id);
if (np.height) {
node.height = np.height;
}
if (np.width) {
node.width = np.width;
}
if (np.x_pos) {
node.x_pos = np.x_pos;
}
if (np.y_pos) {
node.y_pos = np.y_pos;
}
});

this.displayNodes();
}
}

raiseNodeToTopById(nodeId) {
this.getNodeGroupSelectionById(nodeId).raise();
}

// Handles the display of a supernode sub-flow contents or hides the contents
// as necessary.
displaySupernodeContents(d, supernodeD3Object) {
Expand Down Expand Up @@ -6238,6 +6292,7 @@ export default class SVGCanvasRenderer {

// Creates all newly created links specified in the enter selection.
createLinks(enter) {
this.logger.logStartTimer("createLinks");
// Add groups for links
const newLinkGrps = enter.append("g")
.attr("data-id", (d) => this.getId("link_grp", d.id))
Expand Down Expand Up @@ -6281,13 +6336,16 @@ export default class SVGCanvasRenderer {
});
}

this.logger.logEndTimer("createLinks");

return newLinkGrps;
}

// Updates all the link groups (and descendant objects) in the joinedLinkGrps
// selection object. The selection object will contain newly created links
// as well as existing links.
updateLinks(joinedLinkGrps, lineArray) {
this.logger.logStartTimer("updateLinks");
// Update link selection area
joinedLinkGrps
.selectAll(".d3-link-selection-area")
Expand Down Expand Up @@ -6336,6 +6394,8 @@ export default class SVGCanvasRenderer {
if (!this.dragging) {
this.setDisplayOrder(joinedLinkGrps);
}

this.logger.logEndTimer("updateLinks");
}

attachLinkGroupListeners(linkGrps) {
Expand Down Expand Up @@ -6672,6 +6732,8 @@ export default class SVGCanvasRenderer {
}

buildLinksArray() {
this.logger.logStartTimer("buildLinksArray");

let linksArray = [];

if (this.canvasLayout.linkType === LINK_TYPE_STRAIGHT) {
Expand Down Expand Up @@ -6703,6 +6765,8 @@ export default class SVGCanvasRenderer {
// Add connection path info to the links.
linksArray = this.linkUtils.addConnectionPaths(linksArray);

this.logger.logEndTimer("buildLinksArray");

return linksArray;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@
import React from "react";
import ReactDOM from "react-dom";

export const addNodeExternalObject = (node, i, foreignObjects) => {
export const addNodeExternalObject = (canvasController, nodes, setPortPositions, setNodesProperties, raiseNodeToTopById, node, i, foreignObjects) => {
ReactDOM.render(
<node.layout.nodeExternalObject
nodeData={node}
nodes={nodes}
canvasController={canvasController}
setPortPositions={setPortPositions}
setNodesProperties={setNodesProperties}
raiseNodeToTopById={raiseNodeToTopById}
/>,
foreignObjects[i]
);
Expand Down
3 changes: 3 additions & 0 deletions canvas_modules/harness/assets/images/vector.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion canvas_modules/harness/src/client/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import ExplainCanvas from "./components/custom-canvases/explain/explain-canvas";
import Explain2Canvas from "./components/custom-canvases/explain2/explain2-canvas";
import StreamsCanvas from "./components/custom-canvases/streams/streams-canvas";
import ReactNodesCarbonCanvas from "./components/custom-canvases/react-nodes-carbon/react-nodes-carbon";
import ReactNodesMappingCanvas from "./components/custom-canvases/react-nodes-mapping/react-nodes-mapping";

import Breadcrumbs from "./components/breadcrumbs.jsx";
import Console from "./components/console/console.jsx";
Expand Down Expand Up @@ -109,6 +110,7 @@ import {
EXAMPLE_APP_READ_ONLY,
EXAMPLE_APP_PROGRESS,
EXAMPLE_APP_REACT_NODES_CARBON,
EXAMPLE_APP_REACT_NODES_MAPPING,
CUSTOM,
PALETTE_FLYOUT,
PROPERTIES_FLYOUT,
Expand Down Expand Up @@ -224,7 +226,7 @@ class App extends React.Component {
selectedExternalPipelineFlows: true,
selectedEditingActions: true,
selectedMoveNodesOnSupernodeResize: true,
selectedRaiseNodesToTopOnHover: false,
selectedRaiseNodesToTopOnHover: true,
selectedResizableNodes: false,
selectedDisplayFullLabelOnHover: false,
selectedPositionNodeOnRightFlyoutOpen: false,
Expand Down Expand Up @@ -2577,6 +2579,13 @@ class App extends React.Component {
config={commonCanvasConfig}
/>
);
} else if (this.state.selectedExampleApp === EXAMPLE_APP_REACT_NODES_MAPPING) {
firstCanvas = (
<ReactNodesMappingCanvas
ref={this.canvasRef}
config={commonCanvasConfig}
/>
);
}

let commonCanvas;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright 2023 Elyra Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// import Action from "../command-stack/action.js";
import { v4 as uuid4 } from "uuid";
import { get } from "lodash";

export default class LinkInputToOutputAction {
constructor(srcNodeId, srcFields, trgNodeId, canvasController) {
// super(data);
this.srcNodeId = srcNodeId;
this.srcFields = srcFields;
this.trgNodeId = trgNodeId;
this.canvasController = canvasController;
this.oldTrgNode = canvasController.getNode(trgNodeId);

this.oldTrgInputs = [...this.oldTrgNode.inputs];
this.oldLinks = [...this.canvasController.getLinks()];
this.oldTrgAppData = this.oldTrgNode.app_data;
this.oldTrgFields = get(this, "oldTrgNode.app_data.table_data.fields", []);

this.newTrgFields = [...this.oldTrgFields];
this.newTrgInputs = [...this.oldTrgInputs];
const startingLinks = this.oldLinks.filter((l) => l.srcNodeId === srcNodeId && l.trgNodeId === trgNodeId);
this.newLinks = [...startingLinks];

srcFields.forEach((sf) => {
let trgField = this.getMatchingTrgField(sf);
if (!trgField) {
const trgId = uuid4();
trgField = { id: trgId, label: sf.label, type: sf.type };
this.newTrgFields.push(trgField);
this.newTrgInputs.push({ id: trgId });
}

// Create what would be the link to the new, or existing, target field
const link = {
id: uuid4(),
srcNodeId: srcNodeId,
srcNodePortId: sf.id,
trgNodeId: trgNodeId,
trgNodePortId: trgField.id,
type: "nodeLink"
};

// If the link doesn't exist, add it to those to be added to the camvas.
if (!this.linkExists(link)) {
this.newLinks.push(link);
}
});

this.newTrgAppData = {
table_data: {
fields: this.newTrgFields
}
};
}

getMatchingTrgField(sourceField) {
return this.oldTrgFields.find((tf) => tf.label === sourceField.label);
}

linkExists(link) {
const result = this.oldLinks.find((l) =>
l.srcNodeId === link.srcNodeId &&
l.srcNodePortId === link.srcNodePortId &&
l.trgNodeId === link.trgNodeId &&
l.trgNodePortId === link.trgNodePortId);
return result;
}

// Returns true if there is something to execute. No need to check the
// inputs array because it should be in-sync with the fields array.
isDoable() {
return this.newTrgFields.length > this.oldTrgFields.length || this.newLinks.length > this.oldLinks.length;
}

// Standard methods
do() {
this.canvasController.setNodeProperties(this.trgNodeId, { inputs: this.newTrgInputs, app_data: this.newTrgAppData });
this.canvasController.addLinks(this.newLinks);
}

undo() {
this.canvasController.setNodeProperties(this.trgNodeId, { inputs: this.oldTrgInputs, app_data: this.oldTrgAppData });
this.canvasController.setLinks(this.oldLinks);
}

redo() {
this.do();
}

getLabel() {
return "Create " + this.newLinks.length + " mappings";
}
}
Loading

0 comments on commit b952a17

Please sign in to comment.