Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions e2e/creatingASimpleGraph.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ test('Creating a Simple Graph', async ({ page }) => {

//click on the input port of the file to open the parameter table modal and highlight the port
await page.locator('#hello .inputPort').click();

// set 'changeable' on the port to true
await page.locator('.highlighted .column_Flags button.changeableFlag').click();

//rename the port
await page.locator('.highlighted .tableFieldDisplayName').fill('testInput');

Expand Down
9 changes: 5 additions & 4 deletions src/Daliuge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export namespace Daliuge {
EXECUTION_TIME = "execution_time",
GROUP_START = "group_start",
GROUP_END = "group_end",
FILE_PATH = "filepath",

INPUT_ERROR_RATE = "input_error_threshold",
NUM_OF_COPIES = "num_of_copies",
Expand Down Expand Up @@ -171,8 +172,8 @@ export namespace Daliuge {
export const groupStartField = new Field(null, FieldName.GROUP_START, "true", "true", "Is this node the start of a group?", false, DataType.Boolean, false, [], false, FieldType.Component, FieldUsage.NoPort);
export const groupEndField = new Field(null, FieldName.GROUP_END, "true", "true", "Is this node the end of a group?", false, DataType.Boolean, false, [], false, FieldType.Component, FieldUsage.NoPort);

export const branchYesField = new Field(null, FieldName.TRUE, "", "", "The affirmative output from a branch node", false, DataType.Object, false, [], false, FieldType.Component, FieldUsage.OutputPort);
export const branchNoField = new Field(null, FieldName.FALSE, "", "", "he negative output from a branch node", false, DataType.Object, false, [], false, FieldType.Component, FieldUsage.OutputPort);
export const branchTrueField = new Field(null, FieldName.TRUE, "", "", "The affirmative output from a branch node", false, DataType.Object, false, [], false, FieldType.Component, FieldUsage.OutputPort);
export const branchFalseField = new Field(null, FieldName.FALSE, "", "", "he negative output from a branch node", false, DataType.Object, false, [], false, FieldType.Component, FieldUsage.OutputPort);

export const dropClassField = new Field(null, FieldName.DROP_CLASS, "", "", "", false, DataType.String, false, [], false, FieldType.Component, FieldUsage.NoPort);

Expand Down Expand Up @@ -264,8 +265,8 @@ export namespace Daliuge {
Category.Branch
],
fields: [
Daliuge.branchYesField,
Daliuge.branchNoField,
Daliuge.branchTrueField,
Daliuge.branchFalseField,
Daliuge.dropClassField
]
},
Expand Down
50 changes: 35 additions & 15 deletions src/Eagle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3824,7 +3824,9 @@ export class Eagle {
const realSourceNode: Node = RightClick.edgeDropSrcNode;
const realSourcePort: Field = RightClick.edgeDropSrcPort;
const realDestNode: Node = nodes[0];
let realDestPort = realDestNode.findPortByMatchingType(realSourcePort.getType(), !RightClick.edgeDropSrcIsInput);

const usages: Daliuge.FieldUsage[] = [RightClick.edgeDropSrcIsInput ? Daliuge.FieldUsage.OutputPort : Daliuge.FieldUsage.InputPort, Daliuge.FieldUsage.InputOutput];
let realDestPort = realDestNode.findPortByMatchingType(realSourcePort.getType(), usages);

// if no dest port was found, just use first input port on dest node
if (realDestPort === null){
Expand Down Expand Up @@ -4571,7 +4573,8 @@ export class Eagle {
if (typeof intermediaryComponent === 'undefined'){
intermediaryComponent = new Node("Data", "Data Component", "", Category.Data);
} else {
intermediaryComponent = Utils.duplicateNode(intermediaryComponent);
//intermediaryComponent = Utils.duplicateNode(intermediaryComponent);
intermediaryComponent = intermediaryComponent.clone().setId(Utils.generateNodeId());
}

// if edge DOES NOT connect two applications, process normally
Expand All @@ -4588,14 +4591,20 @@ export class Eagle {
const newName = srcPort.getDisplayText();
const newDescription = srcPort.getDescription();
destNode.setName(newName);
destPort.setDisplayText(newName);
destPort.setDescription(newDescription);

if (destPort.isChangeable()){
destPort.setDisplayText(newName);
destPort.setDescription(newDescription);
}
} else {
const newName = destPort.getDisplayText();
const newDescription = destPort.getDescription();
srcNode.setName(newName);
srcPort.setDisplayText(newName);
srcPort.setDescription(newDescription);

if (srcPort.isChangeable()){
srcPort.setDisplayText(newName);
srcPort.setDescription(newDescription);
}
}
}

Expand Down Expand Up @@ -4629,18 +4638,29 @@ export class Eagle {
};

// Add the intermediary component to the graph
const newNode : Node = this.logicalGraph().addDataComponentToGraph(intermediaryComponent, dataComponentPosition);
//const newNode : Node = this.logicalGraph().addDataComponentToGraph(intermediaryComponent, dataComponentPosition); // DOESN't WORK!! io port is not rendered
const newNode = (await this.addNodeToLogicalGraph(intermediaryComponent, Utils.generateNodeId(), Eagle.AddNodeMode.Default))[0]; // WORKS!! (just location is not used)

newNode.setPosition(dataComponentPosition.x, dataComponentPosition.y);

// set name of new node (use user-facing name)
newNode.setName(srcPort.getDisplayText());

// remove existing ports from the memory node
newNode.removeAllInputPorts();
newNode.removeAllOutputPorts();

// add InputOutput port for dataType
const newInputOutputPort = new Field(Utils.generateFieldId(), srcPort.getDisplayText(), "", "", srcPort.getDescription(), false, srcPort.getType(), false, [], false, Daliuge.FieldType.Application, Daliuge.FieldUsage.InputOutput);
newNode.addField(newInputOutputPort);

// find InputOutput port on node, which matches the source port dataType
const inputOutputPort = newNode.findPortByMatchingType(srcPort.getType(), [Daliuge.FieldUsage.InputOutput]);
if (inputOutputPort === null){
Utils.showNotification("Add Edge Error", "Unable to find suitable port on intermediary component", "danger");
reject("Unable to find suitable port on intermediary component");
return;
}

// if the port is changeable, set its display text and description to match the source port
if (inputOutputPort.isChangeable()){
inputOutputPort.setDisplayText(srcPort.getDisplayText());
inputOutputPort.setDescription(srcPort.getDescription());
}

// set the parent of the new node
// by default, set parent to parent of dest node,
Expand All @@ -4657,8 +4677,8 @@ export class Eagle {
}

// create TWO edges, one from src to data component, one from data component to dest
const firstEdge : Edge = new Edge('', srcNode, srcPort, newNode, newInputOutputPort, loopAware, closesLoop, false);
const secondEdge : Edge = new Edge('', newNode, newInputOutputPort, destNode, destPort, loopAware, closesLoop, false);
const firstEdge : Edge = new Edge('', srcNode, srcPort, newNode, inputOutputPort, loopAware, closesLoop, false);
const secondEdge : Edge = new Edge('', newNode, inputOutputPort, destNode, destPort, loopAware, closesLoop, false);

this.logicalGraph().addEdgeComplete(firstEdge);
this.logicalGraph().addEdgeComplete(secondEdge);
Expand Down
28 changes: 25 additions & 3 deletions src/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export class Field {
private node : ko.Observable<Node>;
private edges: ko.Observable<Map<EdgeId, Edge>>;

// run-time only attributes
private changeable : ko.Observable<boolean>;

// graph related attributes
private inputX : ko.Observable<number>;
private inputY : ko.Observable<number>;
Expand Down Expand Up @@ -65,6 +68,9 @@ export class Field {
this.node = ko.observable(null);
this.edges = ko.observable(new Map<EdgeId, Edge>());

// run-time only attributes
this.changeable = ko.observable(true); // whether the field can be renamed or not

//graph related things
this.inputX = ko.observable(0);
this.inputY = ko.observable(0);
Expand Down Expand Up @@ -240,6 +246,15 @@ export class Field {
return this.precious();
}

isChangeable = () : boolean => {
return this.changeable();
}

toggleChangeable = () : Field => {
this.changeable(!this.changeable());
return this;
}

updateEdgeId(oldId: EdgeId, newId: EdgeId): void {
const edge = this.edges().get(oldId);

Expand Down Expand Up @@ -465,6 +480,7 @@ export class Field {
this.isEvent(false);
this.node(null);
this.edges().clear();
this.changeable(true);

return this;
}
Expand All @@ -478,6 +494,7 @@ export class Field {
const f = new Field(this.id(), this.displayText(), this.value(), this.defaultValue(), this.description(), this.readonly(), this.type(), this.precious(), options, this.positional(), this.parameterType(), this.usage());
f.encoding(this.encoding());
f.isEvent(this.isEvent());
f.changeable(this.changeable());
f.node(this.node());
f.edges(new Map<EdgeId, Edge>());
for (const edge of this.edges().values()) {
Expand Down Expand Up @@ -506,6 +523,7 @@ export class Field {
f.isEvent = this.isEvent;
f.node = this.node;
f.edges = this.edges;
f.changeable = this.changeable;

return f;
}
Expand Down Expand Up @@ -544,6 +562,7 @@ export class Field {
this.usage(src.usage());
this.encoding(src.encoding());
this.isEvent(src.isEvent());
this.changeable(src.changeable());

// NOTE: these two are not copied from the src, but come from the function's parameters
this.id(id);
Expand Down Expand Up @@ -791,7 +810,7 @@ export class Field {
};
}

static fromOJSJson(data : any) : Field {
static fromOJSJson(data : any, changeable: boolean) : Field {
let id: FieldId = Utils.generateFieldId();
let name: string = "";
let description: string = "";
Expand Down Expand Up @@ -879,10 +898,11 @@ export class Field {
const result = new Field(id, name, value, defaultValue, description, readonly, type, precious, options, positional, parameterType, usage);
result.isEvent(isEvent);
result.encoding(encoding);
result.changeable(changeable);
return result;
}

static fromOJSJsonPort(data : any) : Field {
static fromOJSJsonPort(data : any, changeable: boolean) : Field {
let name: string = "";
let event: boolean = false;
let type: Daliuge.DataType = Daliuge.DataType.Unknown;
Expand All @@ -908,10 +928,11 @@ export class Field {
const f = new Field(data.Id, name, "", "", description, false, type, false, [], false, Daliuge.FieldType.Unknown, Daliuge.FieldUsage.NoPort);
f.isEvent(event);
f.encoding(encoding);
f.changeable(changeable);
return f;
}

static fromV4Json(data: any): Field {
static fromV4Json(data: any, changeable: boolean): Field {
let id: FieldId;
let name: string;
let value: string;
Expand Down Expand Up @@ -961,6 +982,7 @@ export class Field {
const f = new Field(id, name, value, defaultValue, description, readonly, type, precious, options, positional, parameterType, usage);
f.isEvent(event);
f.encoding(encoding);
f.changeable(changeable);
return f;
}

Expand Down
37 changes: 13 additions & 24 deletions src/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -933,21 +933,10 @@ export class Node {
return null;
}


findPortByMatchingType = (type: string, input: boolean) : Field | null => {
if (input){
// check input ports
for (const inputPort of this.getInputPorts()){
if (Utils.typesMatch(inputPort.getType(), type)){
return inputPort;
}
}
} else {
// check output ports
for (const outputPort of this.getOutputPorts()){
if (Utils.typesMatch(outputPort.getType(), type)){
return outputPort;
}
findPortByMatchingType = (type: string, usages: Daliuge.FieldUsage[]) : Field | null => {
for (const port of this.getFields()){
if (usages.includes(port.getUsage()) && Utils.typesMatch(port.getType(), type)){
return port;
}
}
return null;
Expand Down Expand Up @@ -1596,7 +1585,7 @@ export class Node {
// add fields
if (typeof nodeData.fields !== 'undefined'){
for (const fieldData of nodeData.fields){
const field = Field.fromOJSJson(fieldData);
const field = Field.fromOJSJson(fieldData, !isPaletteNode);

// if the parameter type is not specified, assume it is a ComponentParameter
if (field.getParameterType() === Daliuge.FieldType.Unknown){
Expand All @@ -1610,7 +1599,7 @@ export class Node {
// add application params
if (typeof nodeData.applicationArgs !== 'undefined'){
for (const paramData of nodeData.applicationArgs){
const field = Field.fromOJSJson(paramData);
const field = Field.fromOJSJson(paramData, !isPaletteNode);
field.setParameterType(Daliuge.FieldType.Application);
node.addField(field);
}
Expand All @@ -1620,7 +1609,7 @@ export class Node {
if (typeof nodeData.inputAppFields !== 'undefined'){
for (const fieldData of nodeData.inputAppFields){
if (node.hasInputApplication()){
const field = Field.fromOJSJson(fieldData);
const field = Field.fromOJSJson(fieldData, !isPaletteNode);
node.inputApplication().addField(field);
} else {
errorsWarnings.errors.push(Errors.Message("Can't add input app field " + fieldData.text + " to node " + node.getName() + ". No input application."));
Expand All @@ -1632,7 +1621,7 @@ export class Node {
if (typeof nodeData.outputAppFields !== 'undefined'){
for (const fieldData of nodeData.outputAppFields){
if (node.hasOutputApplication()){
const field = Field.fromOJSJson(fieldData);
const field = Field.fromOJSJson(fieldData, !isPaletteNode);
node.outputApplication().addField(field);
} else {
errorsWarnings.errors.push(Errors.Message("Can't add output app field " + fieldData.text + " to node " + node.getName() + ". No output application."));
Expand All @@ -1643,7 +1632,7 @@ export class Node {
// add input ports
if (typeof nodeData.inputPorts !== 'undefined'){
for (const inputPort of nodeData.inputPorts){
const port = Field.fromOJSJsonPort(inputPort);
const port = Field.fromOJSJsonPort(inputPort, !isPaletteNode);
port.setParameterType(Daliuge.FieldType.Application);
port.setUsage(Daliuge.FieldUsage.InputPort);

Expand All @@ -1662,7 +1651,7 @@ export class Node {
// add output ports
if (typeof nodeData.outputPorts !== 'undefined'){
for (const outputPort of nodeData.outputPorts){
const port = Field.fromOJSJsonPort(outputPort);
const port = Field.fromOJSJsonPort(outputPort, !isPaletteNode);
port.setParameterType(Daliuge.FieldType.Application);
port.setUsage(Daliuge.FieldUsage.OutputPort);

Expand All @@ -1682,7 +1671,7 @@ export class Node {
if (typeof nodeData.inputLocalPorts !== 'undefined'){
for (const inputLocalPort of nodeData.inputLocalPorts){
if (node.hasInputApplication()){
const port = Field.fromOJSJsonPort(inputLocalPort);
const port = Field.fromOJSJsonPort(inputLocalPort, !isPaletteNode);
port.setParameterType(Daliuge.FieldType.Application);
port.setUsage(Daliuge.FieldUsage.OutputPort);

Expand All @@ -1696,7 +1685,7 @@ export class Node {
// add output local ports
if (typeof nodeData.outputLocalPorts !== 'undefined'){
for (const outputLocalPort of nodeData.outputLocalPorts){
const port = Field.fromOJSJsonPort(outputLocalPort);
const port = Field.fromOJSJsonPort(outputLocalPort, !isPaletteNode);
port.setParameterType(Daliuge.FieldType.Application);
port.setUsage(Daliuge.FieldUsage.InputPort);

Expand Down Expand Up @@ -1750,7 +1739,7 @@ export class Node {

// add fields
for (const [id, fieldData] of Object.entries(nodeData.fields)){
const field = Field.fromV4Json(fieldData);
const field = Field.fromV4Json(fieldData, !isPaletteNode);
node.addField(field);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export class Palette {

// add nodes
for (const [nodeId, nodeData] of Object.entries(dataObject.nodes)){
const node = Node.fromV4Json(nodeData, errorsWarnings, false);
const node = Node.fromV4Json(nodeData, errorsWarnings, true);

result.nodes().set(nodeId as NodeId, node);
result.nodes.valueHasMutated();
Expand Down
2 changes: 1 addition & 1 deletion static/tables.css
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
}

.parameter_table_flags{
width: 101px;
width: 121px;
}

.parameter_table_actions{
Expand Down
Loading