@dualbox/editor 1.0.86 → 1.0.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44010,6 +44010,14 @@ class GraphModel {
44010
44010
  this.ensure('ui');
44011
44011
  this.getCurrentMetanode().ui[id] = def;
44012
44012
  break;
44013
+ case "input":
44014
+ this.ensure('input');
44015
+ this.getCurrentMetanode().input[id] = def;
44016
+ break;
44017
+ case "output":
44018
+ this.ensure('output');
44019
+ this.getCurrentMetanode().output[id] = def;
44020
+ break;
44013
44021
  default:
44014
44022
  throw type + " is not module or ui, error";
44015
44023
  }
@@ -44375,7 +44383,12 @@ class GraphNode {
44375
44383
  var defType = this.getDefinitionInputType(inputName);
44376
44384
  var t;
44377
44385
  if (defType.includes("*")) {
44378
- t = assignedType ? assignedType : defType;
44386
+ if (assignedType) {
44387
+ return assignedType;
44388
+ } else {
44389
+ let linkedType = this.getInputLinkedType(inputName);
44390
+ return linkedType ? linkedType : defType;
44391
+ }
44379
44392
  } else {
44380
44393
  t = defType;
44381
44394
  }
@@ -44401,6 +44414,28 @@ class GraphNode {
44401
44414
  return lodash.get(this.def, ["assignedTypes", "output", outputName]);
44402
44415
  }
44403
44416
 
44417
+ getInputLinkedType(inputName) {
44418
+ let def = this.getInputDef(inputName);
44419
+ let linkedType = this.getLinkedType(def.typeLink);
44420
+ if (linkedType) {
44421
+ let definitionType = this.getDefinitionInputType(inputName);
44422
+ return definitionType.replaceAll('*', linkedType);
44423
+ } else {
44424
+ return null;
44425
+ }
44426
+ }
44427
+
44428
+ getOutputLinkedType(outputName) {
44429
+ let def = this.getOutputDef(outputName);
44430
+ let linkedType = this.getLinkedType(def.typeLink);
44431
+ if (linkedType) {
44432
+ let definitionType = this.getDefinitionOutputType(outputName);
44433
+ return definitionType.replaceAll('*', linkedType);
44434
+ } else {
44435
+ return null;
44436
+ }
44437
+ }
44438
+
44404
44439
  getAttributeAssignedType(attrName) {
44405
44440
  return lodash.get(this.def, ["assignedTypes", "attr", attrName]);
44406
44441
  }
@@ -44467,8 +44502,15 @@ class GraphNode {
44467
44502
  lodash.each(linkedInputs, (linkedInputDef, linkedInputName) => {
44468
44503
  var assignedType = this.getInputAssignedType(linkedInputName);
44469
44504
  if (assignedType !== undefined && assignedType !== null) {
44470
- linkedType = assignedType;
44471
- return false; // eol
44505
+ // build a regexp to fetch the type
44506
+ let re = new RegExp(linkedInputDef.type.replace('*', '(?<type>.*)'));
44507
+ let result = re.exec(assignedType);
44508
+ let type = lodash.get(result, ["groups", "type"]);
44509
+
44510
+ if (type) {
44511
+ linkedType = type;
44512
+ return false; // eol
44513
+ }
44472
44514
  }
44473
44515
  });
44474
44516
  }
@@ -44476,8 +44518,15 @@ class GraphNode {
44476
44518
  lodash.each(linkedOutputs, (linkedOutputDef, linkedOutputName) => {
44477
44519
  var assignedType = this.getOutputAssignedType(linkedOutputName);
44478
44520
  if (assignedType !== undefined && assignedType !== null) {
44479
- linkedType = assignedType;
44480
- return false; // eol
44521
+ // build a regexp to fetch the type
44522
+ let re = new RegExp(linkedOutputDef.type.replace('*', '(?<type>.*)'));
44523
+ let result = re.exec(assignedType);
44524
+ let type = lodash.get(result, ["groups", "type"]);
44525
+
44526
+ if (type) {
44527
+ linkedType = type;
44528
+ return false; // eol
44529
+ }
44481
44530
  }
44482
44531
  });
44483
44532
  }
@@ -44595,7 +44644,12 @@ class GraphNode {
44595
44644
  var defType = this.getDefinitionOutputType(outputName);
44596
44645
  var t;
44597
44646
  if (defType.includes("*")) {
44598
- t = assignedType ? assignedType : defType;
44647
+ if (assignedType) {
44648
+ return assignedType;
44649
+ } else {
44650
+ let linkedType = this.getOutputLinkedType(outputName);
44651
+ return linkedType ? linkedType : defType;
44652
+ }
44599
44653
  } else {
44600
44654
  t = defType;
44601
44655
  }
@@ -47241,7 +47295,7 @@ var script = {
47241
47295
  }
47242
47296
  }
47243
47297
  ];
47244
- if (this.n.isModule() || this.n.isUI()) {
47298
+ if (this.n.isModule() || this.n.isUI() || this.n.isInput() || this.n.isOutput()) {
47245
47299
  contextOptions.push({
47246
47300
  name: "Duplicate this box",
47247
47301
  fn: () => {
@@ -47855,7 +47909,7 @@ __vue_render__._withStripped = true;
47855
47909
  /* style */
47856
47910
  const __vue_inject_styles__ = function (inject) {
47857
47911
  if (!inject) return
47858
- inject("data-v-4f0778c6_0", { source: "\n.card-ui {\r\n background-color: #bff2ca !important;\n}\n.card-loop {\r\n /* background-color: #e5e8ea!important; */\r\n border: 5px double #dddddd;\r\n border-width: 4px;\n}\n.card-input {\r\n background-color: #f5d76e !important;\n}\n.card-output {\r\n background-color: #ffb3a7 !important;\n}\n.box-inputs {\r\n float: left;\r\n padding-left: 2px;\r\n padding-right: 5px;\r\n vertical-align: top;\r\n text-align: left;\n}\n.box-outputs {\r\n float: right;\r\n padding-left: 5px;\r\n padding-right: 2px;\r\n vertical-align: top;\r\n text-align: right;\n}\n.dualbox-graph-canvas .card,\r\n.card-node {\r\n /*border: 1px solid #dddddd;*/\r\n box-shadow: 1px 1px 5px #716f6f;\r\n opacity: 1;\r\n cursor: pointer;\r\n z-index: 20;\r\n position: absolute;\r\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\r\n -moz-transition: -moz-box-shadow 0.15s ease-in;\r\n -o-transition: -o-box-shadow 0.15s ease-in;\r\n transition: box-shadow 0.15s ease-in;\r\n color: #4d4d4d;\r\n user-select: none;\r\n padding: 0px 8px 0px 8px;\r\n overflow: hidden;\r\n background-color: #fff;\r\n -moz-border-radius: 3px;\r\n border-radius: 3px;\r\n font-size: 14px;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n}\n.card-node .card-top {\r\n padding-top: 2px;\n}\n.card-node .card-bottom {\r\n padding-bottom: 2px;\r\n text-align: center;\r\n line-height: 14px;\r\n white-space: nowrap;\n}\n.card-node hr {\r\n margin-top: 2px;\r\n margin-bottom: 2px;\r\n border-color: rgba(0, 0, 0, 0.1);\r\n margin-left: -8px;\r\n margin-right: -8px;\n}\n.card-node:hover {\r\n border-color: #80b2fc;\r\n box-shadow: 1px 1px 10px #80b2fc;\n}\n.card-node.selected,\r\n.card-node.selected:hover {\r\n border-color: #0066ff;\r\n box-shadow: 1px 1px 10px #0066ff;\n}\n.card-node-incomplete {\r\n box-shadow: 1px 1px 5px #dd6666 !important;\n}\n.input-not-resolvable {\r\n color: #dd6666 !important;\n}\n.card-node .title {\r\n vertical-align: top;\r\n font-weight: bold;\n}\n.card-node .subtitle {\r\n color: #929292;\r\n font-size: 11px;\r\n font-style: italic;\r\n vertical-align: center;\r\n font-family: tahoma, sans-serif;\n}\n.card-node .input {\r\n font-size: 13px;\r\n color: #8c8c8c;\n}\n.card-node .output {\r\n font-size: 13px;\r\n color: #8c8c8c;\r\n text-align: right;\n}\n.card-node .jtk-endpoint.active svg circle {\r\n /* fill: #99ff33 */\r\n stroke: #59b300;\n}\n.point {\r\n /* display: inline-block; */\r\n display: none;\r\n position: relative;\r\n top: 3px;\r\n margin-right: 5px;\r\n margin-left: 5px;\n}\n.dualbox-io {\r\n overflow: visible;\r\n margin-left: -8px;\r\n margin-right: -8px;\n}\n.box-inputs {\r\n display: flex;\r\n justify-content: space-between;\r\n position: relative;\r\n padding: 0;\r\n pointer-events: none;\n}\n.types {\r\n color: #6c757d !important;\r\n opacity: 0.7;\r\n pointer-events: none;\n}\n.box-inputs .types {\r\n display: inline-block;\n}\n.box-inputs .name {\r\n display: inline-block;\n}\n.box-inputs .type {\r\n display: block;\r\n text-align: right;\n}\n.box-inputs .point {\r\n display: block;\n}\n.box-inputs .name {\r\n display: block;\n}\n.box-outputs {\r\n display: flex;\r\n justify-content: center;\r\n position: relative;\r\n padding: 0;\r\n pointer-events: none;\n}\n.box-outputs .types {\r\n display: inline-block;\n}\n.box-outputs .point {\r\n display: inline-block;\n}\n.box-outputs .name {\r\n display: inline-block;\n}\n.box-outputs .type {\r\n display: block;\r\n text-align: left;\n}\n.box-outputs .point {\r\n display: block;\n}\n.box-outputs .name {\r\n display: block;\n}\nspan.feedback {\r\n font-weight: bold;\n}\n.event-dock {\r\n background-color: rgb(136, 137, 138);\r\n background-color: #a6a6a6;\r\n width: calc(100% + 18px);\r\n height: 12px;\r\n z-index: 3 !important;\n}\n.event-dock-top {\r\n margin-left: -9px;\r\n margin-right: -9px;\r\n margin-top: -3px;\r\n border-top-left-radius: 4px;\r\n border-top-right-radius: 4px;\r\n margin-bottom: 4px;\n}\n.event-dock-bottom {\r\n margin-left: -9px;\r\n margin-right: -9px;\r\n margin-bottom: -3px;\r\n border-bottom-left-radius: 4px;\r\n border-bottom-right-radius: 4px;\r\n margin-top: 4px;\r\n height: 11px;\r\n /* shorter because of box-shadow */\n}\n.event-label {\r\n z-index: 21;\r\n padding-left: 15px;\r\n transform: rotate(-90deg) translate(0%, -50%) !important;\r\n transform-origin: 0% 0%;\r\n color: #6c757d !important;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n font-size: 14px;\r\n opacity: 0.7;\r\n cursor: pointer;\n}\n.transparent {\r\n opacity: 0.3 !important;\n}\n.card-node {\r\n position: relative;\n}\n.card-comment {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n margin-top: -22px;\r\n color: #f4ad42 !important;\n}\n.card-problem {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n margin-top: -22px;\r\n color: red !important;\n}\n.card-snapshot {\n}\n.card-snapshot-idle {\r\n border: 2px solid gray !important;\r\n box-shadow: 1px 1px 5px gray !important;\r\n opacity: 0.7 !important;\n}\n.card-snapshot-computing {\r\n border: 2px solid darkgreen !important;\r\n box-shadow: 1px 1px 5px darkgreen !important;\r\n opacity: 1 !important;\n}\n.card-snapshot-awaiting-data {\r\n border: 2px solid blue !important;\r\n box-shadow: 1px 1px 5px blue !important;\r\n opacity: 0.7 !important;\n}\n.card-snapshot-ready {\r\n border: 2px solid lightgreen !important;\r\n box-shadow: 1px 1px 5px lightgreen !important;\r\n opacity: 1 !important;\n}\n.card-status {\r\n position: absolute;\r\n bottom: 0;\r\n right: 0;\r\n left: 0;\r\n margin-bottom: -26px;\r\n color: #f4ad42 !important;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n font-weight: bold;\r\n text-align: center;\n}\n.card-status-idle {\r\n color: gray !important;\r\n min-width: 85px;\n}\n.card-status-computing {\r\n color: darkgreen !important;\r\n min-width: 110px;\n}\n.card-status-awaiting-data {\r\n color: blue !important;\r\n min-width: 85px;\n}\n.card-status-ready {\r\n color: lightgreen !important;\r\n min-width: 85px;\n}\n.btn-snapshot-details {\r\n position: relative;\r\n margin-top: -2px;\r\n color: inherit;\n}\nspan.name {\r\n overflow-wrap: normal;\n}\r\n", map: {"version":3,"sources":["C:\\Users\\maxim\\Projects\\dualbox\\editor\\js\\src\\v\\templates\\graphNode.vue"],"names":[],"mappings":";AACA;IACA,oCAAA;AACA;AAEA;IACA,yCAAA;IACA,0BAAA;IACA,iBAAA;AACA;AAEA;IACA,oCAAA;AACA;AAEA;IACA,oCAAA;AACA;AAEA;IACA,WAAA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,gBAAA;AACA;AAEA;IACA,YAAA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,iBAAA;AACA;AAEA;;IAEA,6BAAA;IACA,+BAAA;IACA,UAAA;IACA,eAAA;IACA,WAAA;IACA,kBAAA;IACA,oDAAA;IACA,8CAAA;IACA,0CAAA;IACA,oCAAA;IACA,cAAA;IACA,iBAAA;IACA,wBAAA;IACA,gBAAA;IACA,sBAAA;IACA,uBAAA;IACA,kBAAA;IACA,eAAA;IACA,2DAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,mBAAA;IACA,kBAAA;IACA,iBAAA;IACA,mBAAA;AACA;AAEA;IACA,eAAA;IACA,kBAAA;IACA,gCAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;;IAEA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,0CAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,mBAAA;IACA,iBAAA;AACA;AAEA;IACA,cAAA;IACA,eAAA;IACA,kBAAA;IACA,sBAAA;IACA,+BAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;IACA,iBAAA;AACA;AAEA;IACA,kBAAA;IACA,eAAA;AACA;AAEA;IACA,2BAAA;IACA,aAAA;IACA,kBAAA;IACA,QAAA;IACA,iBAAA;IACA,gBAAA;AACA;AAEA;IACA,iBAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,aAAA;IACA,8BAAA;IACA,kBAAA;IACA,UAAA;IACA,oBAAA;AACA;AAEA;IACA,yBAAA;IACA,YAAA;IACA,oBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,cAAA;IACA,iBAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,aAAA;IACA,uBAAA;IACA,kBAAA;IACA,UAAA;IACA,oBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,cAAA;IACA,gBAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,oCAAA;IACA,yBAAA;IACA,wBAAA;IACA,YAAA;IACA,qBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,2BAAA;IACA,4BAAA;IACA,kBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,8BAAA;IACA,+BAAA;IACA,eAAA;IACA,YAAA;IACA,kCAAA;AACA;AAEA;IACA,WAAA;IACA,kBAAA;IACA,wDAAA;IACA,uBAAA;IACA,yBAAA;IACA,2DAAA;IACA,eAAA;IACA,YAAA;IACA,eAAA;AACA;AAEA;IACA,uBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,QAAA;IACA,iBAAA;IACA,yBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,OAAA;IACA,iBAAA;IACA,qBAAA;AACA;AAEA;AACA;AAEA;IACA,iCAAA;IACA,uCAAA;IACA,uBAAA;AACA;AAEA;IACA,sCAAA;IACA,4CAAA;IACA,qBAAA;AACA;AAEA;IACA,iCAAA;IACA,uCAAA;IACA,uBAAA;AACA;AAEA;IACA,uCAAA;IACA,6CAAA;IACA,qBAAA;AACA;AAEA;IACA,kBAAA;IACA,SAAA;IACA,QAAA;IACA,OAAA;IACA,oBAAA;IACA,yBAAA;IACA,2DAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,sBAAA;IACA,eAAA;AACA;AAEA;IACA,2BAAA;IACA,gBAAA;AACA;AAEA;IACA,sBAAA;IACA,eAAA;AACA;AAEA;IACA,4BAAA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,cAAA;AACA;AAEA;IACA,qBAAA;AACA","file":"graphNode.vue","sourcesContent":["<style>\r\n.card-ui {\r\n background-color: #bff2ca !important;\r\n}\r\n\r\n.card-loop {\r\n /* background-color: #e5e8ea!important; */\r\n border: 5px double #dddddd;\r\n border-width: 4px;\r\n}\r\n\r\n.card-input {\r\n background-color: #f5d76e !important;\r\n}\r\n\r\n.card-output {\r\n background-color: #ffb3a7 !important;\r\n}\r\n\r\n.box-inputs {\r\n float: left;\r\n padding-left: 2px;\r\n padding-right: 5px;\r\n vertical-align: top;\r\n text-align: left;\r\n}\r\n\r\n.box-outputs {\r\n float: right;\r\n padding-left: 5px;\r\n padding-right: 2px;\r\n vertical-align: top;\r\n text-align: right;\r\n}\r\n\r\n.dualbox-graph-canvas .card,\r\n.card-node {\r\n /*border: 1px solid #dddddd;*/\r\n box-shadow: 1px 1px 5px #716f6f;\r\n opacity: 1;\r\n cursor: pointer;\r\n z-index: 20;\r\n position: absolute;\r\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\r\n -moz-transition: -moz-box-shadow 0.15s ease-in;\r\n -o-transition: -o-box-shadow 0.15s ease-in;\r\n transition: box-shadow 0.15s ease-in;\r\n color: #4d4d4d;\r\n user-select: none;\r\n padding: 0px 8px 0px 8px;\r\n overflow: hidden;\r\n background-color: #fff;\r\n -moz-border-radius: 3px;\r\n border-radius: 3px;\r\n font-size: 14px;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n}\r\n\r\n.card-node .card-top {\r\n padding-top: 2px;\r\n}\r\n\r\n.card-node .card-bottom {\r\n padding-bottom: 2px;\r\n text-align: center;\r\n line-height: 14px;\r\n white-space: nowrap;\r\n}\r\n\r\n.card-node hr {\r\n margin-top: 2px;\r\n margin-bottom: 2px;\r\n border-color: rgba(0, 0, 0, 0.1);\r\n margin-left: -8px;\r\n margin-right: -8px;\r\n}\r\n\r\n.card-node:hover {\r\n border-color: #80b2fc;\r\n box-shadow: 1px 1px 10px #80b2fc;\r\n}\r\n\r\n.card-node.selected,\r\n.card-node.selected:hover {\r\n border-color: #0066ff;\r\n box-shadow: 1px 1px 10px #0066ff;\r\n}\r\n\r\n.card-node-incomplete {\r\n box-shadow: 1px 1px 5px #dd6666 !important;\r\n}\r\n\r\n.input-not-resolvable {\r\n color: #dd6666 !important;\r\n}\r\n\r\n.card-node .title {\r\n vertical-align: top;\r\n font-weight: bold;\r\n}\r\n\r\n.card-node .subtitle {\r\n color: #929292;\r\n font-size: 11px;\r\n font-style: italic;\r\n vertical-align: center;\r\n font-family: tahoma, sans-serif;\r\n}\r\n\r\n.card-node .input {\r\n font-size: 13px;\r\n color: #8c8c8c;\r\n}\r\n\r\n.card-node .output {\r\n font-size: 13px;\r\n color: #8c8c8c;\r\n text-align: right;\r\n}\r\n\r\n.card-node .jtk-endpoint.active svg circle {\r\n /* fill: #99ff33 */\r\n stroke: #59b300;\r\n}\r\n\r\n.point {\r\n /* display: inline-block; */\r\n display: none;\r\n position: relative;\r\n top: 3px;\r\n margin-right: 5px;\r\n margin-left: 5px;\r\n}\r\n\r\n.dualbox-io {\r\n overflow: visible;\r\n margin-left: -8px;\r\n margin-right: -8px;\r\n}\r\n\r\n.box-inputs {\r\n display: flex;\r\n justify-content: space-between;\r\n position: relative;\r\n padding: 0;\r\n pointer-events: none;\r\n}\r\n\r\n.types {\r\n color: #6c757d !important;\r\n opacity: 0.7;\r\n pointer-events: none;\r\n}\r\n\r\n.box-inputs .types {\r\n display: inline-block;\r\n}\r\n\r\n.box-inputs .name {\r\n display: inline-block;\r\n}\r\n\r\n.box-inputs .type {\r\n display: block;\r\n text-align: right;\r\n}\r\n\r\n.box-inputs .point {\r\n display: block;\r\n}\r\n\r\n.box-inputs .name {\r\n display: block;\r\n}\r\n\r\n.box-outputs {\r\n display: flex;\r\n justify-content: center;\r\n position: relative;\r\n padding: 0;\r\n pointer-events: none;\r\n}\r\n\r\n.box-outputs .types {\r\n display: inline-block;\r\n}\r\n\r\n.box-outputs .point {\r\n display: inline-block;\r\n}\r\n\r\n.box-outputs .name {\r\n display: inline-block;\r\n}\r\n\r\n.box-outputs .type {\r\n display: block;\r\n text-align: left;\r\n}\r\n\r\n.box-outputs .point {\r\n display: block;\r\n}\r\n\r\n.box-outputs .name {\r\n display: block;\r\n}\r\n\r\nspan.feedback {\r\n font-weight: bold;\r\n}\r\n\r\n.event-dock {\r\n background-color: rgb(136, 137, 138);\r\n background-color: #a6a6a6;\r\n width: calc(100% + 18px);\r\n height: 12px;\r\n z-index: 3 !important;\r\n}\r\n\r\n.event-dock-top {\r\n margin-left: -9px;\r\n margin-right: -9px;\r\n margin-top: -3px;\r\n border-top-left-radius: 4px;\r\n border-top-right-radius: 4px;\r\n margin-bottom: 4px;\r\n}\r\n\r\n.event-dock-bottom {\r\n margin-left: -9px;\r\n margin-right: -9px;\r\n margin-bottom: -3px;\r\n border-bottom-left-radius: 4px;\r\n border-bottom-right-radius: 4px;\r\n margin-top: 4px;\r\n height: 11px;\r\n /* shorter because of box-shadow */\r\n}\r\n\r\n.event-label {\r\n z-index: 21;\r\n padding-left: 15px;\r\n transform: rotate(-90deg) translate(0%, -50%) !important;\r\n transform-origin: 0% 0%;\r\n color: #6c757d !important;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n font-size: 14px;\r\n opacity: 0.7;\r\n cursor: pointer;\r\n}\r\n\r\n.transparent {\r\n opacity: 0.3 !important;\r\n}\r\n\r\n.card-node {\r\n position: relative;\r\n}\r\n\r\n.card-comment {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n margin-top: -22px;\r\n color: #f4ad42 !important;\r\n}\r\n\r\n.card-problem {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n margin-top: -22px;\r\n color: red !important;\r\n}\r\n\r\n.card-snapshot {\r\n}\r\n\r\n.card-snapshot-idle {\r\n border: 2px solid gray !important;\r\n box-shadow: 1px 1px 5px gray !important;\r\n opacity: 0.7 !important;\r\n}\r\n\r\n.card-snapshot-computing {\r\n border: 2px solid darkgreen !important;\r\n box-shadow: 1px 1px 5px darkgreen !important;\r\n opacity: 1 !important;\r\n}\r\n\r\n.card-snapshot-awaiting-data {\r\n border: 2px solid blue !important;\r\n box-shadow: 1px 1px 5px blue !important;\r\n opacity: 0.7 !important;\r\n}\r\n\r\n.card-snapshot-ready {\r\n border: 2px solid lightgreen !important;\r\n box-shadow: 1px 1px 5px lightgreen !important;\r\n opacity: 1 !important;\r\n}\r\n\r\n.card-status {\r\n position: absolute;\r\n bottom: 0;\r\n right: 0;\r\n left: 0;\r\n margin-bottom: -26px;\r\n color: #f4ad42 !important;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n font-weight: bold;\r\n text-align: center;\r\n}\r\n\r\n.card-status-idle {\r\n color: gray !important;\r\n min-width: 85px;\r\n}\r\n\r\n.card-status-computing {\r\n color: darkgreen !important;\r\n min-width: 110px;\r\n}\r\n\r\n.card-status-awaiting-data {\r\n color: blue !important;\r\n min-width: 85px;\r\n}\r\n\r\n.card-status-ready {\r\n color: lightgreen !important;\r\n min-width: 85px;\r\n}\r\n\r\n.btn-snapshot-details {\r\n position: relative;\r\n margin-top: -2px;\r\n color: inherit;\r\n}\r\n\r\nspan.name {\r\n overflow-wrap: normal;\r\n}\r\n</style>\r\n\r\n<template>\r\n <div class=\"jtk-node card card-node contextmenu\" v-bind:class=\"{ 'card-loop': n.hasLoop(), 'card-ui': n.isUI(), 'card-metanode': n.isMetanode(), 'card-input': n.isInput(), 'card-output': n.isOutput(), 'card-snapshot': n.hasSnapshot(), 'card-snapshot-idle': n.hasSnapshot() && n.isSnapshotStatus(0), 'card-snapshot-computing': n.hasSnapshot() && n.isSnapshotStatus(1), 'card-snapshot-awaiting-data': n.hasSnapshot() && n.isSnapshotStatus(2), 'card-snapshot-ready': n.hasSnapshot() && n.isSnapshotStatus(3) }\" v-bind:id=\"getId()\" v-bind:data-id=\"getId()\" v-bind:data-name=\"pkg.name\" style=\"overflow: visible;\">\r\n <div v-if=\"n.hasComment()\">\r\n <div class=\"card-comment\" data-toggle=\"tooltip\" data-placement=\"top\" :title=\"n.getComment()\">\r\n <i class=\"fas fa-comment-alt\" data-container=\"body\"></i>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"n.hasSnapshot()\">\r\n <div class=\"card-status\">\r\n <div v-if=\"n.isSnapshotStatus(0)\">\r\n <div class=\"card-status-idle\">\r\n <span>IDLE</span>\r\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"n.isSnapshotStatus(1)\">\r\n <div class=\"card-status-computing\">\r\n <span>COMPUTING</span>\r\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"n.isSnapshotStatus(2)\">\r\n <div class=\"card-status-awaiting-data\">\r\n <span>WAITING</span>\r\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"n.isSnapshotStatus(3)\">\r\n <div class=\"card-status-ready\">\r\n <span>READY</span>\r\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"!example && n.isUI() && !n.isOnAPanel()\">\r\n <div @click=\"registerToPanel\" class=\"card-problem\">\r\n <i class=\"fas fa-exclamation-circle\" data-container=\"body\" data-toggle=\"popover\" data-placement=\"top\" data-content=\"This UI is not set in a panel. It won't have any effect. Go to the Interface tab to add it to a panel.\"></i>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-top\">\r\n <div class=\"d-flex\">\r\n <span class=\"title\" style=\"white-space: nowrap; margin-right: 5px;\">\r\n <span v-if=\"n.isMetanode()\" class=\"badge badge-secondary\"><b>META</b></span> {{n.graphId}}\r\n <i v-if=\"n.isParallel()\" class=\"fas fa-server\" style=\"color: orange;\" title=\"this module is computed in a web worker\"></i>\r\n </span>\r\n\r\n <div class=\"ml-auto\">\r\n <button class=\"btn btn-outline-secondary btn-outline-discrete btn-editor-xs btn-settings\" v-on:click=\"openNodeSettings\"><i class=\"fas fa-cog\"></i></button>\r\n </div>\r\n </div>\r\n </div>\r\n <div v-if=\"!n.isInput() && !n.isOutput()\" class=\"card-center\">\r\n <hr style=\"margin-bottom: 5px;\" />\r\n <div class=\"dualbox-io\" style=\"overflow: visible;\">\r\n <div class=\"inputs\" style=\"display: inline-block; float: left;\">\r\n <div class=\"box-inputs\">\r\n <div class=\"types\">\r\n <span class=\"type\" v-for=\"key in getVisibleInputs()\" v-bind:data-key=\"key\">\r\n {{ n.getInputType(key) }}\r\n </span>\r\n </div>\r\n <div class=\"points\">\r\n <div class=\"point\" v-for=\"key in getVisibleInputs()\" v-bind:data-key=\"key\" v-bind:data-type=\"n.getInputDef(key).type\" v-html=\"point\"></div>\r\n </div>\r\n <div class=\"names\">\r\n <span class=\"name\" v-for=\"key in getVisibleInputs()\" :class=\"{'feedback': n.isFeedbackTarget(key), 'input-not-resolvable': !example && !n.isInputResolvable(key) }\" v-bind:data-input=\"key\">\r\n <span v-if=\"n.hasIterator(key)\">&lt;{{key}}&gt;</span>\r\n <span v-else>{{key}}</span>\r\n <small v-if=\"!n.isInputConst(key)\" data-toggle=\"tooltip\" data-trigger=\"hover\" title=\"this value will be cloned at execution time\"><i class=\"fas fa-clone transparent\"></i></small>\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"outputs\" style=\"display: inline-block; float: right\">\r\n <div class=\"box-outputs\">\r\n <div class=\"names\">\r\n <span class=\"name\" v-for=\"key in getVisibleOutputs()\" v-bind:class=\"{feedback: n.isFeedbackTarget(key)}\" v-bind:data-output=\"key\">\r\n <span v-if=\"n.hasLoop() && n.hasFeedback(key)\">{{key}}</span>\r\n <span v-else-if=\"n.hasLoop() && !n.hasFeedback(key)\">&lt;{{key}}&gt;</span>\r\n <span v-else>{{key}}</span>\r\n\r\n <span v-if=\"n.hasCacheActivated()\">\r\n &nbsp;<i class=\"fa fa-hdd\" title=\"This module has cache activated\"></i>\r\n </span>\r\n </span>\r\n </div>\r\n <div class=\"points\">\r\n <div class=\"point\" v-for=\"key in getVisibleOutputs()\" v-bind:data-key=\"key\" v-bind:data-type=\"n.getOutputDef(key).type\" v-html=\"point\"></div>\r\n </div>\r\n <div class=\"types\">\r\n <span class=\"type\" v-for=\"key in getVisibleOutputs()\" v-bind:data-key=\"key\">\r\n {{ n.getOutputType(key) }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <hr style=\"margin-top: 5px;\" />\r\n <div class=\"card-bottom\">\r\n <span class=\"subtitle\">{{ shortName }}</span>\r\n\r\n <div v-if=\"n.isMetanode()\" class=\"d-inline-block\">\r\n <button class=\"btn btn-outline-secondary btn-outline-discrete btn-editor-xs btn-enter-metanode\" v-on:click=\"enterMetanode\"><i class=\"fas fa-sign-in-alt\"></i></button>\r\n </div>\r\n\r\n <!--\r\n <div v-if=\"n.isUI()\" class=\"event-dock event-dock-bottom\"></div>\r\n -->\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport ContextMenu from \"../ContextMenu\";\r\nimport _ from \"lodash-es\";\r\nimport dbutils from \"../../m/DualboxUtils\";\r\n\r\n// fix inputs types and output types position relatively to the div\r\n$.fn.fixCardDisplay = function() {\r\n var offsetPoint = 12;\r\n var offsetBorder = parseInt($(this).css(\"border-top-width\"));\r\n\r\n // if we have width or height set to 0, we are not ready yet to\r\n // execute this function. Postpone it.\r\n if( $(this).width() === 0 || $(this).height() === 0 ) {\r\n setTimeout(() => {\r\n $(this).fixCardDisplay();\r\n }, 50);\r\n return;\r\n }\r\n\r\n if (\r\n $(this)\r\n .find(\".box-inputs\")\r\n .height() === 0 &&\r\n $(this)\r\n .find(\".box-outputs\")\r\n .height() === 0\r\n ) {\r\n // if this card has no input/output, remove the card center\r\n $(this)\r\n .find(\".card-center\")\r\n .remove();\r\n } else {\r\n // else, adjust the input/output display for endpoints\r\n // 1) translate inputs by the right amount of pixels to have the circle on the line\r\n var boxInputs = $(this).find(\".box-inputs\");\r\n\r\n // fix css names width\r\n var namesDiv = boxInputs.find(\".names\");\r\n namesDiv.css(\"width\", namesDiv.width() + 1 + \"px\");\r\n\r\n // translate inputs to the left\r\n var translateLeft =\r\n boxInputs.find(\".types\").width() + offsetPoint + offsetBorder / 2;\r\n $(this)\r\n .find(\".box-inputs\")\r\n .css(\"transform\", \"translateX(-\" + translateLeft + \"px)\");\r\n\r\n // adjust inputs main div width\r\n $(this)\r\n .find(\".inputs\")\r\n .width(\r\n $(this)\r\n .find(\".inputs\")\r\n .width() -\r\n translateLeft +\r\n 10 /* margin */\r\n );\r\n\r\n // 2) translate outputs by the right amount of pixels to have the circle on the line\r\n var boxOutputs = $(this).find(\".box-outputs\");\r\n\r\n // fix css names with\r\n var namesDiv = boxOutputs.find(\".names\");\r\n namesDiv.css(\"width\", namesDiv.width() + 1 + \"px\");\r\n\r\n // translate inputs to the right\r\n var translateRight =\r\n boxOutputs.find(\".types\").width() + offsetPoint + offsetBorder / 2;\r\n $(this)\r\n .find(\".box-outputs\")\r\n .css(\"transform\", \"translateX(\" + translateRight + \"px)\");\r\n\r\n // adjust output main div width\r\n $(this)\r\n .find(\".outputs\")\r\n .width(\r\n $(this)\r\n .find(\".outputs\")\r\n .width() -\r\n translateRight +\r\n 10 /* margin */\r\n );\r\n\r\n // fix io width\r\n //$('.dualbox-io').css('width', (($(this).find('.inputs').width() + $(this).find('.outputs').width()) + \"px\"));\r\n }\r\n\r\n $(this).ready(() => {\r\n // take the current width and add it as a css property\r\n var width = $(this).width();\r\n width += parseInt($(this).css(\"padding-right\"));\r\n width += parseInt($(this).css(\"padding-left\"));\r\n width += parseInt($(this).css(\"border-left-width\"));\r\n width += parseInt($(this).css(\"border-right-width\"));\r\n $(this).css(\"width\", Math.ceil(width) + \"px\");\r\n });\r\n};\r\n\r\n// find position of element relative to an ancestor matching selector\r\n$.fn.positionFrom = function(selector) {\r\n var ancestor = $(this).closest(selector);\r\n var offset = $(this).offset();\r\n var ancestorOffset = ancestor.offset();\r\n return {\r\n top: offset.top - ancestorOffset.top,\r\n left: offset.left - ancestorOffset.left\r\n };\r\n};\r\n\r\nexport default {\r\n props: [\r\n \"id\", // the module id\r\n \"pkg\", // the module package.json\r\n \"n\", // the GraphNode object (from model)\r\n \"example\", // true if this vue is used as an example display (no need to connect)\r\n \"displayEvents\" // true if events should be displayed\r\n ],\r\n data: function() {\r\n return {\r\n shortName: \"\",\r\n point:\r\n '<svg width=\"14\" height=\"14\" pointer-events=\"all\" position=\"absolute\" version=\"1.1\" xmlns=\"http://www.w3.org/1999/xhtml\"><circle cx=\"7\" cy=\"7\" r=\"5\" version=\"1.1\" xmlns=\"http://www.w3.org/1999/xhtml\" fill=\"#ffffff\" stroke=\"#727272\" style=\"\" stroke-width=\"2\"></circle></svg>'\r\n };\r\n },\r\n beforeUpdate: function() {\r\n //console.log('[UPDATING] ' + this.n.getUniqId());\r\n },\r\n destroyed: function() {\r\n this.deactivateTooltip();\r\n $(\".tooltip\").remove();\r\n },\r\n created: function() {\r\n this.initialized = false;\r\n this.view = window.dualboxEditor.v;\r\n\r\n //console.log('[CREATED] ' + this.n.getUniqId());\r\n // We compute the shortname of our box\r\n if (this.n.isInput() || this.n.isOutput()) {\r\n this.shortName = this.n.getType();\r\n } else {\r\n this.shortName = dbutils.shortName(this.pkg.name);\r\n }\r\n },\r\n mounted: async function() {\r\n //console.log('[MOUNTED] ' + this.n.getUniqId());\r\n var div = $(this.$el);\r\n div.fixCardDisplay();\r\n this.activateTooltip();\r\n return await this.initialize();\r\n },\r\n beforeUpdate: function() {\r\n this.deactivateTooltip();\r\n },\r\n updated: async function() {\r\n //console.log('[UPDATED] ' + this.n.getUniqId());\r\n\r\n // we reset jsPlumb before app update (in graph.vue)\r\n // so we need to initialize again\r\n this.assignContextMenu();\r\n\r\n $(this.$el).fixCardDisplay();\r\n $(this.$el).ready(() => {\r\n this.activateTooltip();\r\n });\r\n return await this.initialize();\r\n },\r\n activate: function() {\r\n this.activateTooltip();\r\n },\r\n deactivate: function() {\r\n this.deactivateTooltip();\r\n },\r\n methods: {\r\n getId: function() {\r\n // if this is an example graphNode, change our \"id\" to \"id-junk\"\r\n // to avoid connection jsplumb conflicts with the real node\r\n return this.example ? this.id + \"-junk\" : this.id;\r\n },\r\n\r\n activateTooltip: function() {\r\n $(this.$el)\r\n .find('[data-toggle=\"tooltip\"]')\r\n .tooltip();\r\n },\r\n\r\n deactivateTooltip: function() {\r\n $(this.$el)\r\n .find('[data-toggle=\"tooltip\"]')\r\n .tooltip(\"dispose\");\r\n },\r\n\r\n initialize: async function() {\r\n var self = this;\r\n var div = $(this.$el);\r\n var id = this.getId();\r\n var view = this.view;\r\n\r\n this.initialized = false;\r\n\r\n if (!this.example) {\r\n // if we have a position, set it\r\n var def = this.n.getDef();\r\n var position = _.get(def, [\"graph\", \"position\"]);\r\n if (position) {\r\n var jsPlumbElement = self.$parent.jsPlumbInstance.getElement(\r\n id\r\n );\r\n self.$parent.jsPlumbInstance.setPosition(\r\n jsPlumbElement,\r\n position\r\n );\r\n }\r\n\r\n // This needs to be registered before draggable\r\n div.on(\"mousedown\", function(e) {\r\n // if this div is not selected already, deselect the other divs\r\n if (!self.$parent.selector.isSelected(this)) {\r\n self.$parent.selector.deselect();\r\n }\r\n });\r\n\r\n await this.initializeJsPlumb();\r\n\r\n div.click(function(e) {\r\n if (e.ctrlKey) {\r\n view.selector.toggleSelection(this);\r\n }\r\n });\r\n\r\n this.assignContextMenu();\r\n }\r\n\r\n return new Promise(resolve => {\r\n div.ready(() => {\r\n //console.log('[INITIALIZED] ' + this.n.getUniqId());\r\n this.initialized = true;\r\n resolve();\r\n });\r\n });\r\n },\r\n\r\n initializeJsPlumb: function() {\r\n var self = this;\r\n var div = $(this.$el);\r\n var id = this.getId();\r\n var view = this.view;\r\n\r\n if (!this.example) {\r\n // If this node was never initialized in this jsplumb instance, do it\r\n if (\r\n !_.get(this.$parent.jsPlumbInstance, [\r\n \"initializedNodes\",\r\n id\r\n ])\r\n ) {\r\n _.set(\r\n this.$parent.jsPlumbInstance,\r\n [\"initializedNodes\", id],\r\n true\r\n ); // initialized\r\n\r\n if (this.n.isInput() || this.n.isOutput()) {\r\n var type = \"*\";\r\n var input = \"value\";\r\n var output = \"value\";\r\n var offsetTop =\r\n $(div)\r\n .find(\".card-top\")\r\n .height() +\r\n 12 /* hr size */ -\r\n 3;\r\n\r\n var uuid = [id, \"input\", input].join(\"#\");\r\n var ep = this.$parent.jsPlumbInstance.addEndpoint(\r\n id,\r\n {\r\n isSource: false,\r\n isTarget: true,\r\n uuid: uuid,\r\n anchor: [0, 0, -1, 0, 0, offsetTop],\r\n maxConnections: 1,\r\n parameters: {\r\n type: \"data\",\r\n target: {\r\n id: id,\r\n input: output\r\n }\r\n }\r\n },\r\n this.$parent.style.inputEndpoint\r\n );\r\n\r\n // add data to the endpoint div so we can identify it easier\r\n $(ep.canvas).attr(\"data-node\", id);\r\n $(ep.canvas).attr(\"data-type\", \"input\");\r\n $(ep.canvas).attr(\"data-input\", input);\r\n\r\n // bind tooltip\r\n $(ep.canvas).attr(\"data-toggle\", \"tooltip\");\r\n $(ep.canvas).attr(\"data-trigger\", \"hover\");\r\n $(ep.canvas).attr(\"data-placement\", \"left\");\r\n $(ep.canvas).attr(\"data-html\", \"true\");\r\n var inputType = view.m\r\n .getNode(id)\r\n .getInputType(\"value\");\r\n $(ep.canvas).attr(\r\n \"title\",\r\n \"Type: <b>\" + inputType + \"</b>\"\r\n );\r\n $(ep.canvas).tooltip();\r\n\r\n // bind context menu to the endpoint\r\n $(ep.canvas).addClass(\"capture-right-click\");\r\n $(ep.canvas).ready(function() {\r\n var menu = new ContextMenu(\r\n \".jtk-endpoint-anchor[data-node='\" +\r\n id.trim() +\r\n \"'][data-input='\" +\r\n input +\r\n \"']\",\r\n [\r\n {\r\n name: \"Create input for here\",\r\n fn: () => {\r\n view.c.createInputFromConnection(\r\n id,\r\n input\r\n );\r\n }\r\n }\r\n ]\r\n );\r\n });\r\n\r\n var uuid = [id, \"output\", output].join(\"#\");\r\n var ep = this.$parent.jsPlumbInstance.addEndpoint(\r\n id,\r\n {\r\n isSource: true,\r\n isTarget: false,\r\n uuid: uuid,\r\n anchor: [1, 0, 1, 0, 0, offsetTop],\r\n parameters: {\r\n type: \"data\",\r\n source: {\r\n id: id,\r\n output: output\r\n }\r\n }\r\n },\r\n this.$parent.style.outputEndpoint\r\n );\r\n\r\n // add data to the endpoint div so we can identify it easier\r\n $(ep.canvas).attr(\"data-node\", id);\r\n $(ep.canvas).attr(\"data-type\", \"output\");\r\n $(ep.canvas).attr(\"data-output\", output);\r\n\r\n // bind tooltip\r\n $(ep.canvas).attr(\"data-toggle\", \"tooltip\");\r\n $(ep.canvas).attr(\"data-trigger\", \"hover\");\r\n $(ep.canvas).attr(\"data-placement\", \"right\");\r\n $(ep.canvas).attr(\"data-html\", \"true\");\r\n var outputType = view.m\r\n .getNode(id)\r\n .getOutputType(\"value\");\r\n $(ep.canvas).attr(\r\n \"title\",\r\n \"Type: <b>\" + outputType + \"</b>\"\r\n );\r\n $(ep.canvas).tooltip();\r\n\r\n // bind context menu to the endpoint\r\n $(ep.canvas).addClass(\"capture-right-click\");\r\n $(ep.canvas).ready(function() {\r\n var menu = new ContextMenu(\r\n \".jtk-endpoint-anchor[data-node='\" +\r\n id.trim() +\r\n \"'][data-output='\" +\r\n output.trim() +\r\n \"']\",\r\n [\r\n {\r\n name: \"Create output for here\",\r\n fn: () => {\r\n view.c.createOutputFromConnection(\r\n id,\r\n output\r\n );\r\n }\r\n }\r\n ]\r\n );\r\n });\r\n } else {\r\n // add input endoints\r\n div.find(\".box-inputs\")\r\n .find(\".point\")\r\n .each(function(index) {\r\n $(this)\r\n .css(\"visibility\", \"hidden\")\r\n .css(\"opacity\", \"0\"); // replaced by jsPlumb point\r\n\r\n var input = div\r\n .find(\".box-inputs\")\r\n .find(\".name\")\r\n .eq(index)\r\n .attr(\"data-input\")\r\n .trim();\r\n var type = view.m\r\n .getNode(id)\r\n .getInputType(input);\r\n\r\n var offsetTop =\r\n $(this).positionFrom(\".card\").top +\r\n $(this).height() / 2 -\r\n 3;\r\n var uuid = [\r\n id,\r\n \"input\",\r\n $(this).data(\"key\")\r\n ].join(\"#\");\r\n var ep = self.$parent.jsPlumbInstance.addEndpoint(\r\n id,\r\n {\r\n isSource: false,\r\n isTarget: true,\r\n uuid: uuid,\r\n anchor: [0, 0, -1, 0, 0, offsetTop],\r\n maxConnections: 1,\r\n parameters: {\r\n type: \"data\",\r\n target: {\r\n id: id,\r\n input: $(this).data(\"key\")\r\n }\r\n }\r\n },\r\n self.$parent.style.inputEndpoint\r\n );\r\n\r\n // add data to the endpoint div so we can identify it easier\r\n $(ep.canvas).attr(\"data-node\", id);\r\n $(ep.canvas).attr(\"data-type\", \"input\");\r\n $(ep.canvas).attr(\"data-input\", input);\r\n\r\n // bind tooltip\r\n $(ep.canvas).attr(\"data-toggle\", \"tooltip\");\r\n $(ep.canvas).attr(\"data-trigger\", \"hover\");\r\n $(ep.canvas).attr(\"data-placement\", \"left\");\r\n $(ep.canvas).attr(\"data-html\", \"true\");\r\n $(ep.canvas).attr(\r\n \"title\",\r\n \"Type: <b>\" + type + \"</b>\"\r\n );\r\n $(ep.canvas).tooltip();\r\n\r\n // bind context menu to the endpoint\r\n $(ep.canvas).addClass(\"capture-right-click\");\r\n $(ep.canvas).ready(function() {\r\n var menu = new ContextMenu(\r\n \".jtk-endpoint-anchor[data-node='\" +\r\n id.trim() +\r\n \"'][data-input='\" +\r\n input.trim() +\r\n \"']\",\r\n [\r\n {\r\n name: \"Create input for here\",\r\n fn: () => {\r\n view.c.createInputFromConnection(\r\n id,\r\n input\r\n );\r\n }\r\n }\r\n ]\r\n );\r\n });\r\n });\r\n\r\n // add output endpoints\r\n div.find(\".box-outputs\")\r\n .find(\".point\")\r\n .each(function(index) {\r\n $(this)\r\n .css(\"visibility\", \"hidden\")\r\n .css(\"opacity\", \"0\"); // replaced by jsPlumb point\r\n\r\n var output = div\r\n .find(\".box-outputs\")\r\n .find(\".name\")\r\n .eq(index)\r\n .attr(\"data-output\")\r\n .trim();\r\n var type = view.m\r\n .getNode(id)\r\n .getOutputType(output);\r\n\r\n var offsetTop =\r\n $(this).positionFrom(\".card\").top +\r\n $(this).height() / 2 -\r\n 3;\r\n var uuid = [\r\n id,\r\n \"output\",\r\n $(this).data(\"key\")\r\n ].join(\"#\");\r\n var ep = self.$parent.jsPlumbInstance.addEndpoint(\r\n id,\r\n {\r\n isSource: true,\r\n isTarget: false,\r\n uuid: uuid,\r\n anchor: [1, 0, 1, 0, 0, offsetTop],\r\n parameters: {\r\n type: \"data\",\r\n source: {\r\n id: id,\r\n output: $(this).data(\"key\")\r\n }\r\n }\r\n },\r\n self.$parent.style.outputEndpoint\r\n );\r\n\r\n // add data to the endpoint div so we can identify it easier\r\n $(ep.canvas).attr(\"data-node\", id);\r\n $(ep.canvas).attr(\"data-type\", \"output\");\r\n $(ep.canvas).attr(\"data-output\", output);\r\n\r\n // bind tooltip\r\n $(ep.canvas).attr(\"data-toggle\", \"tooltip\");\r\n $(ep.canvas).attr(\"data-trigger\", \"hover\");\r\n $(ep.canvas).attr(\"data-placement\", \"right\");\r\n $(ep.canvas).attr(\"data-html\", \"true\");\r\n $(ep.canvas).attr(\r\n \"title\",\r\n \"Type: <b>\" + type + \"</b>\"\r\n );\r\n $(ep.canvas).tooltip();\r\n\r\n // bind context menu to the endpoint\r\n $(ep.canvas).addClass(\"capture-right-click\");\r\n $(ep.canvas).ready(function() {\r\n var menu = new ContextMenu(\r\n \".jtk-endpoint-anchor[data-node='\" +\r\n id.trim() +\r\n \"'][data-output='\" +\r\n output.trim() +\r\n \"']\",\r\n [\r\n {\r\n name: \"Create output for here\",\r\n fn: () => {\r\n view.c.createOutputFromConnection(\r\n id,\r\n output\r\n );\r\n }\r\n }\r\n ]\r\n );\r\n });\r\n });\r\n\r\n if (this.n.isUI() && this.displayEvents) {\r\n // Make this a target for events\r\n this.$parent.jsPlumbInstance.makeTarget(\r\n id,\r\n {\r\n isSource: false,\r\n isTarget: true,\r\n uniqueEndpoint: false,\r\n anchor: \"Continuous\",\r\n uuid: id + \"#event-in\",\r\n paintStyle: {\r\n fill: \"green\",\r\n radius: 3,\r\n stroke: \"#727272\",\r\n strokeWidth: 1\r\n },\r\n parameters: {\r\n type: \"event\",\r\n target: { id: id }\r\n }\r\n },\r\n self.$parent.style.eventEndpoint\r\n );\r\n\r\n // Create an enpoint to create a new event\r\n var ep = this.$parent.jsPlumbInstance.addEndpoint(\r\n id,\r\n {\r\n isSource: true,\r\n isTarget: false,\r\n uuid: id + \"#event-out\",\r\n anchor: [1, 1, 0, 1, 0, -10],\r\n parameters: {\r\n type: \"event\",\r\n source: { id: id }\r\n },\r\n paintStyle: {\r\n fill: \"green\",\r\n radius: 3,\r\n stroke: \"#727272\",\r\n strokeWidth: 1\r\n }\r\n },\r\n this.$parent.style.eventEndpoint\r\n );\r\n\r\n // Add overlay here so we don't mess with splitConnection\r\n ep.addOverlay([\r\n \"PlainArrow\",\r\n {\r\n width: 15,\r\n length: 15,\r\n location: 1,\r\n id: \"arrow\"\r\n }\r\n ]);\r\n\r\n $(ep.canvas).attr(\"data-toggle\", \"tooltip\");\r\n $(ep.canvas).attr(\"data-trigger\", \"hover\");\r\n $(ep.canvas).attr(\"data-placement\", \"bottom\");\r\n $(ep.canvas).attr(\"data-html\", \"true\");\r\n $(ep.canvas).attr(\r\n \"title\",\r\n \"Connect from here ito add an event that will be triggered when this box is done computing.\"\r\n );\r\n $(ep.canvas).tooltip();\r\n }\r\n }\r\n\r\n // Make the div draggable\r\n this.$parent.jsPlumbInstance.draggable(div, {\r\n //containment:true, // not allowed outside of container div\r\n drag: function(e) {\r\n // TODO: bug. After a repaint(), jsPlumb seems to be broken (connections dont follow on div drag)\r\n // It doesn't occur on jsPlumb.reset() instead of creating another instance on beforeUpdate(),\r\n // (as it should be), but we can't do that, because JsPlumb is broken on zoom otherwise...\r\n // One of thoses problem may be fixed later by updating jsPlumb...\r\n // Note: this \"fix\" may affect performances on drag, maybe a setTimeout will do\r\n //self.$parent.jsPlumbInstance.repaintEverything();\r\n self.$parent.jsPlumbInstance.repaint(id);\r\n },\r\n stop: function(e) {\r\n // resize the canvas if necessary\r\n self.$parent.canvasSizeHandler.debouncedResize();\r\n\r\n if (\r\n self.$parent.selector.isMultipleSelectionActive()\r\n ) {\r\n // We just dropped a bunch of divs, ajust all their positions\r\n self.view.m.batch(() => {\r\n self.$parent.selector.each(div => {\r\n var pos = self.$parent.jsPlumbInstance.getPosition(\r\n div\r\n );\r\n view.m\r\n .getNode($(div).attr(\"id\"))\r\n .setPosition(pos);\r\n });\r\n });\r\n } else {\r\n // We just dropped this one, set the new position in the graph model\r\n var el = self.$parent.jsPlumbInstance.getElement(\r\n id\r\n );\r\n $(el).ready(function() {\r\n var pos = self.$parent.jsPlumbInstance.getPosition(\r\n el\r\n );\r\n view.m.getNode(id).setPosition(pos);\r\n });\r\n }\r\n }\r\n });\r\n }\r\n }\r\n\r\n return new Promise(resolve =>\r\n this.$parent.jsPlumbInstance.ready(resolve)\r\n );\r\n },\r\n\r\n assignContextMenu: function() {\r\n var id = this.getId();\r\n\r\n // Create a contextmenu for the div\r\n var contextOptions = [\r\n {\r\n name: \"Remove this box\",\r\n fn: () => {\r\n this.view.c.removeBox(id);\r\n }\r\n }\r\n ];\r\n if (this.n.isModule() || this.n.isUI()) {\r\n contextOptions.push({\r\n name: \"Duplicate this box\",\r\n fn: () => {\r\n this.view.c.duplicateBox(id);\r\n }\r\n });\r\n }\r\n var nodeMenu = new ContextMenu(\"#\" + id, contextOptions);\r\n },\r\n\r\n htmlentities: function(s) {\r\n return this.view.utils.htmlentities(s);\r\n },\r\n\r\n getVisibleInputs: function() {\r\n return this.n.getInputsNames().filter(inputName => {\r\n return this.n.isInputVisible(inputName);\r\n });\r\n },\r\n\r\n getVisibleOutputs: function() {\r\n return this.n.getOutputsNames().filter(outputName => {\r\n return this.n.isOutputVisible(outputName);\r\n });\r\n },\r\n\r\n enterMetanode: function(e) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n this.view.c.enterMetanode(this.id);\r\n },\r\n\r\n openNodeSettings: function(e) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.view.openBoxSettings(this.id);\r\n },\r\n\r\n openSnapshotDetails: async function(e) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n await this.view.openDebug(this.id);\r\n },\r\n\r\n registerToPanel: async function(e) {\r\n await this.view.c.registerNodeToInterface(this.id);\r\n }\r\n },\r\n watch: {\r\n app: {\r\n handler: () => {\r\n console.log(\"graphVue.app changed\");\r\n },\r\n deep: true\r\n }\r\n }\r\n};\r\n</script>\r\n"]}, media: undefined });
47912
+ inject("data-v-08972d38_0", { source: "\n.card-ui {\r\n background-color: #bff2ca !important;\n}\n.card-loop {\r\n /* background-color: #e5e8ea!important; */\r\n border: 5px double #dddddd;\r\n border-width: 4px;\n}\n.card-input {\r\n background-color: #f5d76e !important;\n}\n.card-output {\r\n background-color: #ffb3a7 !important;\n}\n.box-inputs {\r\n float: left;\r\n padding-left: 2px;\r\n padding-right: 5px;\r\n vertical-align: top;\r\n text-align: left;\n}\n.box-outputs {\r\n float: right;\r\n padding-left: 5px;\r\n padding-right: 2px;\r\n vertical-align: top;\r\n text-align: right;\n}\n.dualbox-graph-canvas .card,\r\n.card-node {\r\n /*border: 1px solid #dddddd;*/\r\n box-shadow: 1px 1px 5px #716f6f;\r\n opacity: 1;\r\n cursor: pointer;\r\n z-index: 20;\r\n position: absolute;\r\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\r\n -moz-transition: -moz-box-shadow 0.15s ease-in;\r\n -o-transition: -o-box-shadow 0.15s ease-in;\r\n transition: box-shadow 0.15s ease-in;\r\n color: #4d4d4d;\r\n user-select: none;\r\n padding: 0px 8px 0px 8px;\r\n overflow: hidden;\r\n background-color: #fff;\r\n -moz-border-radius: 3px;\r\n border-radius: 3px;\r\n font-size: 14px;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n}\n.card-node .card-top {\r\n padding-top: 2px;\n}\n.card-node .card-bottom {\r\n padding-bottom: 2px;\r\n text-align: center;\r\n line-height: 14px;\r\n white-space: nowrap;\n}\n.card-node hr {\r\n margin-top: 2px;\r\n margin-bottom: 2px;\r\n border-color: rgba(0, 0, 0, 0.1);\r\n margin-left: -8px;\r\n margin-right: -8px;\n}\n.card-node:hover {\r\n border-color: #80b2fc;\r\n box-shadow: 1px 1px 10px #80b2fc;\n}\n.card-node.selected,\r\n.card-node.selected:hover {\r\n border-color: #0066ff;\r\n box-shadow: 1px 1px 10px #0066ff;\n}\n.card-node-incomplete {\r\n box-shadow: 1px 1px 5px #dd6666 !important;\n}\n.input-not-resolvable {\r\n color: #dd6666 !important;\n}\n.card-node .title {\r\n vertical-align: top;\r\n font-weight: bold;\n}\n.card-node .subtitle {\r\n color: #929292;\r\n font-size: 11px;\r\n font-style: italic;\r\n vertical-align: center;\r\n font-family: tahoma, sans-serif;\n}\n.card-node .input {\r\n font-size: 13px;\r\n color: #8c8c8c;\n}\n.card-node .output {\r\n font-size: 13px;\r\n color: #8c8c8c;\r\n text-align: right;\n}\n.card-node .jtk-endpoint.active svg circle {\r\n /* fill: #99ff33 */\r\n stroke: #59b300;\n}\n.point {\r\n /* display: inline-block; */\r\n display: none;\r\n position: relative;\r\n top: 3px;\r\n margin-right: 5px;\r\n margin-left: 5px;\n}\n.dualbox-io {\r\n overflow: visible;\r\n margin-left: -8px;\r\n margin-right: -8px;\n}\n.box-inputs {\r\n display: flex;\r\n justify-content: space-between;\r\n position: relative;\r\n padding: 0;\r\n pointer-events: none;\n}\n.types {\r\n color: #6c757d !important;\r\n opacity: 0.7;\r\n pointer-events: none;\n}\n.box-inputs .types {\r\n display: inline-block;\n}\n.box-inputs .name {\r\n display: inline-block;\n}\n.box-inputs .type {\r\n display: block;\r\n text-align: right;\n}\n.box-inputs .point {\r\n display: block;\n}\n.box-inputs .name {\r\n display: block;\n}\n.box-outputs {\r\n display: flex;\r\n justify-content: center;\r\n position: relative;\r\n padding: 0;\r\n pointer-events: none;\n}\n.box-outputs .types {\r\n display: inline-block;\n}\n.box-outputs .point {\r\n display: inline-block;\n}\n.box-outputs .name {\r\n display: inline-block;\n}\n.box-outputs .type {\r\n display: block;\r\n text-align: left;\n}\n.box-outputs .point {\r\n display: block;\n}\n.box-outputs .name {\r\n display: block;\n}\nspan.feedback {\r\n font-weight: bold;\n}\n.event-dock {\r\n background-color: rgb(136, 137, 138);\r\n background-color: #a6a6a6;\r\n width: calc(100% + 18px);\r\n height: 12px;\r\n z-index: 3 !important;\n}\n.event-dock-top {\r\n margin-left: -9px;\r\n margin-right: -9px;\r\n margin-top: -3px;\r\n border-top-left-radius: 4px;\r\n border-top-right-radius: 4px;\r\n margin-bottom: 4px;\n}\n.event-dock-bottom {\r\n margin-left: -9px;\r\n margin-right: -9px;\r\n margin-bottom: -3px;\r\n border-bottom-left-radius: 4px;\r\n border-bottom-right-radius: 4px;\r\n margin-top: 4px;\r\n height: 11px;\r\n /* shorter because of box-shadow */\n}\n.event-label {\r\n z-index: 21;\r\n padding-left: 15px;\r\n transform: rotate(-90deg) translate(0%, -50%) !important;\r\n transform-origin: 0% 0%;\r\n color: #6c757d !important;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n font-size: 14px;\r\n opacity: 0.7;\r\n cursor: pointer;\n}\n.transparent {\r\n opacity: 0.3 !important;\n}\n.card-node {\r\n position: relative;\n}\n.card-comment {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n margin-top: -22px;\r\n color: #f4ad42 !important;\n}\n.card-problem {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n margin-top: -22px;\r\n color: red !important;\n}\n.card-snapshot {\n}\n.card-snapshot-idle {\r\n border: 2px solid gray !important;\r\n box-shadow: 1px 1px 5px gray !important;\r\n opacity: 0.7 !important;\n}\n.card-snapshot-computing {\r\n border: 2px solid darkgreen !important;\r\n box-shadow: 1px 1px 5px darkgreen !important;\r\n opacity: 1 !important;\n}\n.card-snapshot-awaiting-data {\r\n border: 2px solid blue !important;\r\n box-shadow: 1px 1px 5px blue !important;\r\n opacity: 0.7 !important;\n}\n.card-snapshot-ready {\r\n border: 2px solid lightgreen !important;\r\n box-shadow: 1px 1px 5px lightgreen !important;\r\n opacity: 1 !important;\n}\n.card-status {\r\n position: absolute;\r\n bottom: 0;\r\n right: 0;\r\n left: 0;\r\n margin-bottom: -26px;\r\n color: #f4ad42 !important;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n font-weight: bold;\r\n text-align: center;\n}\n.card-status-idle {\r\n color: gray !important;\r\n min-width: 85px;\n}\n.card-status-computing {\r\n color: darkgreen !important;\r\n min-width: 110px;\n}\n.card-status-awaiting-data {\r\n color: blue !important;\r\n min-width: 85px;\n}\n.card-status-ready {\r\n color: lightgreen !important;\r\n min-width: 85px;\n}\n.btn-snapshot-details {\r\n position: relative;\r\n margin-top: -2px;\r\n color: inherit;\n}\nspan.name {\r\n overflow-wrap: normal;\n}\r\n", map: {"version":3,"sources":["C:\\Users\\maxim\\Projects\\dualbox\\editor\\js\\src\\v\\templates\\graphNode.vue"],"names":[],"mappings":";AACA;IACA,oCAAA;AACA;AAEA;IACA,yCAAA;IACA,0BAAA;IACA,iBAAA;AACA;AAEA;IACA,oCAAA;AACA;AAEA;IACA,oCAAA;AACA;AAEA;IACA,WAAA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,gBAAA;AACA;AAEA;IACA,YAAA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,iBAAA;AACA;AAEA;;IAEA,6BAAA;IACA,+BAAA;IACA,UAAA;IACA,eAAA;IACA,WAAA;IACA,kBAAA;IACA,oDAAA;IACA,8CAAA;IACA,0CAAA;IACA,oCAAA;IACA,cAAA;IACA,iBAAA;IACA,wBAAA;IACA,gBAAA;IACA,sBAAA;IACA,uBAAA;IACA,kBAAA;IACA,eAAA;IACA,2DAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,mBAAA;IACA,kBAAA;IACA,iBAAA;IACA,mBAAA;AACA;AAEA;IACA,eAAA;IACA,kBAAA;IACA,gCAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;;IAEA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,0CAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,mBAAA;IACA,iBAAA;AACA;AAEA;IACA,cAAA;IACA,eAAA;IACA,kBAAA;IACA,sBAAA;IACA,+BAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;IACA,iBAAA;AACA;AAEA;IACA,kBAAA;IACA,eAAA;AACA;AAEA;IACA,2BAAA;IACA,aAAA;IACA,kBAAA;IACA,QAAA;IACA,iBAAA;IACA,gBAAA;AACA;AAEA;IACA,iBAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,aAAA;IACA,8BAAA;IACA,kBAAA;IACA,UAAA;IACA,oBAAA;AACA;AAEA;IACA,yBAAA;IACA,YAAA;IACA,oBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,cAAA;IACA,iBAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,aAAA;IACA,uBAAA;IACA,kBAAA;IACA,UAAA;IACA,oBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,cAAA;IACA,gBAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,oCAAA;IACA,yBAAA;IACA,wBAAA;IACA,YAAA;IACA,qBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,2BAAA;IACA,4BAAA;IACA,kBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,8BAAA;IACA,+BAAA;IACA,eAAA;IACA,YAAA;IACA,kCAAA;AACA;AAEA;IACA,WAAA;IACA,kBAAA;IACA,wDAAA;IACA,uBAAA;IACA,yBAAA;IACA,2DAAA;IACA,eAAA;IACA,YAAA;IACA,eAAA;AACA;AAEA;IACA,uBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,QAAA;IACA,iBAAA;IACA,yBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,OAAA;IACA,iBAAA;IACA,qBAAA;AACA;AAEA;AACA;AAEA;IACA,iCAAA;IACA,uCAAA;IACA,uBAAA;AACA;AAEA;IACA,sCAAA;IACA,4CAAA;IACA,qBAAA;AACA;AAEA;IACA,iCAAA;IACA,uCAAA;IACA,uBAAA;AACA;AAEA;IACA,uCAAA;IACA,6CAAA;IACA,qBAAA;AACA;AAEA;IACA,kBAAA;IACA,SAAA;IACA,QAAA;IACA,OAAA;IACA,oBAAA;IACA,yBAAA;IACA,2DAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,sBAAA;IACA,eAAA;AACA;AAEA;IACA,2BAAA;IACA,gBAAA;AACA;AAEA;IACA,sBAAA;IACA,eAAA;AACA;AAEA;IACA,4BAAA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,cAAA;AACA;AAEA;IACA,qBAAA;AACA","file":"graphNode.vue","sourcesContent":["<style>\r\n.card-ui {\r\n background-color: #bff2ca !important;\r\n}\r\n\r\n.card-loop {\r\n /* background-color: #e5e8ea!important; */\r\n border: 5px double #dddddd;\r\n border-width: 4px;\r\n}\r\n\r\n.card-input {\r\n background-color: #f5d76e !important;\r\n}\r\n\r\n.card-output {\r\n background-color: #ffb3a7 !important;\r\n}\r\n\r\n.box-inputs {\r\n float: left;\r\n padding-left: 2px;\r\n padding-right: 5px;\r\n vertical-align: top;\r\n text-align: left;\r\n}\r\n\r\n.box-outputs {\r\n float: right;\r\n padding-left: 5px;\r\n padding-right: 2px;\r\n vertical-align: top;\r\n text-align: right;\r\n}\r\n\r\n.dualbox-graph-canvas .card,\r\n.card-node {\r\n /*border: 1px solid #dddddd;*/\r\n box-shadow: 1px 1px 5px #716f6f;\r\n opacity: 1;\r\n cursor: pointer;\r\n z-index: 20;\r\n position: absolute;\r\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\r\n -moz-transition: -moz-box-shadow 0.15s ease-in;\r\n -o-transition: -o-box-shadow 0.15s ease-in;\r\n transition: box-shadow 0.15s ease-in;\r\n color: #4d4d4d;\r\n user-select: none;\r\n padding: 0px 8px 0px 8px;\r\n overflow: hidden;\r\n background-color: #fff;\r\n -moz-border-radius: 3px;\r\n border-radius: 3px;\r\n font-size: 14px;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n}\r\n\r\n.card-node .card-top {\r\n padding-top: 2px;\r\n}\r\n\r\n.card-node .card-bottom {\r\n padding-bottom: 2px;\r\n text-align: center;\r\n line-height: 14px;\r\n white-space: nowrap;\r\n}\r\n\r\n.card-node hr {\r\n margin-top: 2px;\r\n margin-bottom: 2px;\r\n border-color: rgba(0, 0, 0, 0.1);\r\n margin-left: -8px;\r\n margin-right: -8px;\r\n}\r\n\r\n.card-node:hover {\r\n border-color: #80b2fc;\r\n box-shadow: 1px 1px 10px #80b2fc;\r\n}\r\n\r\n.card-node.selected,\r\n.card-node.selected:hover {\r\n border-color: #0066ff;\r\n box-shadow: 1px 1px 10px #0066ff;\r\n}\r\n\r\n.card-node-incomplete {\r\n box-shadow: 1px 1px 5px #dd6666 !important;\r\n}\r\n\r\n.input-not-resolvable {\r\n color: #dd6666 !important;\r\n}\r\n\r\n.card-node .title {\r\n vertical-align: top;\r\n font-weight: bold;\r\n}\r\n\r\n.card-node .subtitle {\r\n color: #929292;\r\n font-size: 11px;\r\n font-style: italic;\r\n vertical-align: center;\r\n font-family: tahoma, sans-serif;\r\n}\r\n\r\n.card-node .input {\r\n font-size: 13px;\r\n color: #8c8c8c;\r\n}\r\n\r\n.card-node .output {\r\n font-size: 13px;\r\n color: #8c8c8c;\r\n text-align: right;\r\n}\r\n\r\n.card-node .jtk-endpoint.active svg circle {\r\n /* fill: #99ff33 */\r\n stroke: #59b300;\r\n}\r\n\r\n.point {\r\n /* display: inline-block; */\r\n display: none;\r\n position: relative;\r\n top: 3px;\r\n margin-right: 5px;\r\n margin-left: 5px;\r\n}\r\n\r\n.dualbox-io {\r\n overflow: visible;\r\n margin-left: -8px;\r\n margin-right: -8px;\r\n}\r\n\r\n.box-inputs {\r\n display: flex;\r\n justify-content: space-between;\r\n position: relative;\r\n padding: 0;\r\n pointer-events: none;\r\n}\r\n\r\n.types {\r\n color: #6c757d !important;\r\n opacity: 0.7;\r\n pointer-events: none;\r\n}\r\n\r\n.box-inputs .types {\r\n display: inline-block;\r\n}\r\n\r\n.box-inputs .name {\r\n display: inline-block;\r\n}\r\n\r\n.box-inputs .type {\r\n display: block;\r\n text-align: right;\r\n}\r\n\r\n.box-inputs .point {\r\n display: block;\r\n}\r\n\r\n.box-inputs .name {\r\n display: block;\r\n}\r\n\r\n.box-outputs {\r\n display: flex;\r\n justify-content: center;\r\n position: relative;\r\n padding: 0;\r\n pointer-events: none;\r\n}\r\n\r\n.box-outputs .types {\r\n display: inline-block;\r\n}\r\n\r\n.box-outputs .point {\r\n display: inline-block;\r\n}\r\n\r\n.box-outputs .name {\r\n display: inline-block;\r\n}\r\n\r\n.box-outputs .type {\r\n display: block;\r\n text-align: left;\r\n}\r\n\r\n.box-outputs .point {\r\n display: block;\r\n}\r\n\r\n.box-outputs .name {\r\n display: block;\r\n}\r\n\r\nspan.feedback {\r\n font-weight: bold;\r\n}\r\n\r\n.event-dock {\r\n background-color: rgb(136, 137, 138);\r\n background-color: #a6a6a6;\r\n width: calc(100% + 18px);\r\n height: 12px;\r\n z-index: 3 !important;\r\n}\r\n\r\n.event-dock-top {\r\n margin-left: -9px;\r\n margin-right: -9px;\r\n margin-top: -3px;\r\n border-top-left-radius: 4px;\r\n border-top-right-radius: 4px;\r\n margin-bottom: 4px;\r\n}\r\n\r\n.event-dock-bottom {\r\n margin-left: -9px;\r\n margin-right: -9px;\r\n margin-bottom: -3px;\r\n border-bottom-left-radius: 4px;\r\n border-bottom-right-radius: 4px;\r\n margin-top: 4px;\r\n height: 11px;\r\n /* shorter because of box-shadow */\r\n}\r\n\r\n.event-label {\r\n z-index: 21;\r\n padding-left: 15px;\r\n transform: rotate(-90deg) translate(0%, -50%) !important;\r\n transform-origin: 0% 0%;\r\n color: #6c757d !important;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n font-size: 14px;\r\n opacity: 0.7;\r\n cursor: pointer;\r\n}\r\n\r\n.transparent {\r\n opacity: 0.3 !important;\r\n}\r\n\r\n.card-node {\r\n position: relative;\r\n}\r\n\r\n.card-comment {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n margin-top: -22px;\r\n color: #f4ad42 !important;\r\n}\r\n\r\n.card-problem {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n margin-top: -22px;\r\n color: red !important;\r\n}\r\n\r\n.card-snapshot {\r\n}\r\n\r\n.card-snapshot-idle {\r\n border: 2px solid gray !important;\r\n box-shadow: 1px 1px 5px gray !important;\r\n opacity: 0.7 !important;\r\n}\r\n\r\n.card-snapshot-computing {\r\n border: 2px solid darkgreen !important;\r\n box-shadow: 1px 1px 5px darkgreen !important;\r\n opacity: 1 !important;\r\n}\r\n\r\n.card-snapshot-awaiting-data {\r\n border: 2px solid blue !important;\r\n box-shadow: 1px 1px 5px blue !important;\r\n opacity: 0.7 !important;\r\n}\r\n\r\n.card-snapshot-ready {\r\n border: 2px solid lightgreen !important;\r\n box-shadow: 1px 1px 5px lightgreen !important;\r\n opacity: 1 !important;\r\n}\r\n\r\n.card-status {\r\n position: absolute;\r\n bottom: 0;\r\n right: 0;\r\n left: 0;\r\n margin-bottom: -26px;\r\n color: #f4ad42 !important;\r\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n font-weight: bold;\r\n text-align: center;\r\n}\r\n\r\n.card-status-idle {\r\n color: gray !important;\r\n min-width: 85px;\r\n}\r\n\r\n.card-status-computing {\r\n color: darkgreen !important;\r\n min-width: 110px;\r\n}\r\n\r\n.card-status-awaiting-data {\r\n color: blue !important;\r\n min-width: 85px;\r\n}\r\n\r\n.card-status-ready {\r\n color: lightgreen !important;\r\n min-width: 85px;\r\n}\r\n\r\n.btn-snapshot-details {\r\n position: relative;\r\n margin-top: -2px;\r\n color: inherit;\r\n}\r\n\r\nspan.name {\r\n overflow-wrap: normal;\r\n}\r\n</style>\r\n\r\n<template>\r\n <div class=\"jtk-node card card-node contextmenu\" v-bind:class=\"{ 'card-loop': n.hasLoop(), 'card-ui': n.isUI(), 'card-metanode': n.isMetanode(), 'card-input': n.isInput(), 'card-output': n.isOutput(), 'card-snapshot': n.hasSnapshot(), 'card-snapshot-idle': n.hasSnapshot() && n.isSnapshotStatus(0), 'card-snapshot-computing': n.hasSnapshot() && n.isSnapshotStatus(1), 'card-snapshot-awaiting-data': n.hasSnapshot() && n.isSnapshotStatus(2), 'card-snapshot-ready': n.hasSnapshot() && n.isSnapshotStatus(3) }\" v-bind:id=\"getId()\" v-bind:data-id=\"getId()\" v-bind:data-name=\"pkg.name\" style=\"overflow: visible;\">\r\n <div v-if=\"n.hasComment()\">\r\n <div class=\"card-comment\" data-toggle=\"tooltip\" data-placement=\"top\" :title=\"n.getComment()\">\r\n <i class=\"fas fa-comment-alt\" data-container=\"body\"></i>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"n.hasSnapshot()\">\r\n <div class=\"card-status\">\r\n <div v-if=\"n.isSnapshotStatus(0)\">\r\n <div class=\"card-status-idle\">\r\n <span>IDLE</span>\r\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"n.isSnapshotStatus(1)\">\r\n <div class=\"card-status-computing\">\r\n <span>COMPUTING</span>\r\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"n.isSnapshotStatus(2)\">\r\n <div class=\"card-status-awaiting-data\">\r\n <span>WAITING</span>\r\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"n.isSnapshotStatus(3)\">\r\n <div class=\"card-status-ready\">\r\n <span>READY</span>\r\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"!example && n.isUI() && !n.isOnAPanel()\">\r\n <div @click=\"registerToPanel\" class=\"card-problem\">\r\n <i class=\"fas fa-exclamation-circle\" data-container=\"body\" data-toggle=\"popover\" data-placement=\"top\" data-content=\"This UI is not set in a panel. It won't have any effect. Go to the Interface tab to add it to a panel.\"></i>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-top\">\r\n <div class=\"d-flex\">\r\n <span class=\"title\" style=\"white-space: nowrap; margin-right: 5px;\">\r\n <span v-if=\"n.isMetanode()\" class=\"badge badge-secondary\"><b>META</b></span> {{n.graphId}}\r\n <i v-if=\"n.isParallel()\" class=\"fas fa-server\" style=\"color: orange;\" title=\"this module is computed in a web worker\"></i>\r\n </span>\r\n\r\n <div class=\"ml-auto\">\r\n <button class=\"btn btn-outline-secondary btn-outline-discrete btn-editor-xs btn-settings\" v-on:click=\"openNodeSettings\"><i class=\"fas fa-cog\"></i></button>\r\n </div>\r\n </div>\r\n </div>\r\n <div v-if=\"!n.isInput() && !n.isOutput()\" class=\"card-center\">\r\n <hr style=\"margin-bottom: 5px;\" />\r\n <div class=\"dualbox-io\" style=\"overflow: visible;\">\r\n <div class=\"inputs\" style=\"display: inline-block; float: left;\">\r\n <div class=\"box-inputs\">\r\n <div class=\"types\">\r\n <span class=\"type\" v-for=\"key in getVisibleInputs()\" v-bind:data-key=\"key\">\r\n {{ n.getInputType(key) }}\r\n </span>\r\n </div>\r\n <div class=\"points\">\r\n <div class=\"point\" v-for=\"key in getVisibleInputs()\" v-bind:data-key=\"key\" v-bind:data-type=\"n.getInputDef(key).type\" v-html=\"point\"></div>\r\n </div>\r\n <div class=\"names\">\r\n <span class=\"name\" v-for=\"key in getVisibleInputs()\" :class=\"{'feedback': n.isFeedbackTarget(key), 'input-not-resolvable': !example && !n.isInputResolvable(key) }\" v-bind:data-input=\"key\">\r\n <span v-if=\"n.hasIterator(key)\">&lt;{{key}}&gt;</span>\r\n <span v-else>{{key}}</span>\r\n <small v-if=\"!n.isInputConst(key)\" data-toggle=\"tooltip\" data-trigger=\"hover\" title=\"this value will be cloned at execution time\"><i class=\"fas fa-clone transparent\"></i></small>\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"outputs\" style=\"display: inline-block; float: right\">\r\n <div class=\"box-outputs\">\r\n <div class=\"names\">\r\n <span class=\"name\" v-for=\"key in getVisibleOutputs()\" v-bind:class=\"{feedback: n.isFeedbackTarget(key)}\" v-bind:data-output=\"key\">\r\n <span v-if=\"n.hasLoop() && n.hasFeedback(key)\">{{key}}</span>\r\n <span v-else-if=\"n.hasLoop() && !n.hasFeedback(key)\">&lt;{{key}}&gt;</span>\r\n <span v-else>{{key}}</span>\r\n\r\n <span v-if=\"n.hasCacheActivated()\">\r\n &nbsp;<i class=\"fa fa-hdd\" title=\"This module has cache activated\"></i>\r\n </span>\r\n </span>\r\n </div>\r\n <div class=\"points\">\r\n <div class=\"point\" v-for=\"key in getVisibleOutputs()\" v-bind:data-key=\"key\" v-bind:data-type=\"n.getOutputDef(key).type\" v-html=\"point\"></div>\r\n </div>\r\n <div class=\"types\">\r\n <span class=\"type\" v-for=\"key in getVisibleOutputs()\" v-bind:data-key=\"key\">\r\n {{ n.getOutputType(key) }}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <hr style=\"margin-top: 5px;\" />\r\n <div class=\"card-bottom\">\r\n <span class=\"subtitle\">{{ shortName }}</span>\r\n\r\n <div v-if=\"n.isMetanode()\" class=\"d-inline-block\">\r\n <button class=\"btn btn-outline-secondary btn-outline-discrete btn-editor-xs btn-enter-metanode\" v-on:click=\"enterMetanode\"><i class=\"fas fa-sign-in-alt\"></i></button>\r\n </div>\r\n\r\n <!--\r\n <div v-if=\"n.isUI()\" class=\"event-dock event-dock-bottom\"></div>\r\n -->\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport ContextMenu from \"../ContextMenu\";\r\nimport _ from \"lodash-es\";\r\nimport dbutils from \"../../m/DualboxUtils\";\r\n\r\n// fix inputs types and output types position relatively to the div\r\n$.fn.fixCardDisplay = function() {\r\n var offsetPoint = 12;\r\n var offsetBorder = parseInt($(this).css(\"border-top-width\"));\r\n\r\n // if we have width or height set to 0, we are not ready yet to\r\n // execute this function. Postpone it.\r\n if( $(this).width() === 0 || $(this).height() === 0 ) {\r\n setTimeout(() => {\r\n $(this).fixCardDisplay();\r\n }, 50);\r\n return;\r\n }\r\n\r\n if (\r\n $(this)\r\n .find(\".box-inputs\")\r\n .height() === 0 &&\r\n $(this)\r\n .find(\".box-outputs\")\r\n .height() === 0\r\n ) {\r\n // if this card has no input/output, remove the card center\r\n $(this)\r\n .find(\".card-center\")\r\n .remove();\r\n } else {\r\n // else, adjust the input/output display for endpoints\r\n // 1) translate inputs by the right amount of pixels to have the circle on the line\r\n var boxInputs = $(this).find(\".box-inputs\");\r\n\r\n // fix css names width\r\n var namesDiv = boxInputs.find(\".names\");\r\n namesDiv.css(\"width\", namesDiv.width() + 1 + \"px\");\r\n\r\n // translate inputs to the left\r\n var translateLeft =\r\n boxInputs.find(\".types\").width() + offsetPoint + offsetBorder / 2;\r\n $(this)\r\n .find(\".box-inputs\")\r\n .css(\"transform\", \"translateX(-\" + translateLeft + \"px)\");\r\n\r\n // adjust inputs main div width\r\n $(this)\r\n .find(\".inputs\")\r\n .width(\r\n $(this)\r\n .find(\".inputs\")\r\n .width() -\r\n translateLeft +\r\n 10 /* margin */\r\n );\r\n\r\n // 2) translate outputs by the right amount of pixels to have the circle on the line\r\n var boxOutputs = $(this).find(\".box-outputs\");\r\n\r\n // fix css names with\r\n var namesDiv = boxOutputs.find(\".names\");\r\n namesDiv.css(\"width\", namesDiv.width() + 1 + \"px\");\r\n\r\n // translate inputs to the right\r\n var translateRight =\r\n boxOutputs.find(\".types\").width() + offsetPoint + offsetBorder / 2;\r\n $(this)\r\n .find(\".box-outputs\")\r\n .css(\"transform\", \"translateX(\" + translateRight + \"px)\");\r\n\r\n // adjust output main div width\r\n $(this)\r\n .find(\".outputs\")\r\n .width(\r\n $(this)\r\n .find(\".outputs\")\r\n .width() -\r\n translateRight +\r\n 10 /* margin */\r\n );\r\n\r\n // fix io width\r\n //$('.dualbox-io').css('width', (($(this).find('.inputs').width() + $(this).find('.outputs').width()) + \"px\"));\r\n }\r\n\r\n $(this).ready(() => {\r\n // take the current width and add it as a css property\r\n var width = $(this).width();\r\n width += parseInt($(this).css(\"padding-right\"));\r\n width += parseInt($(this).css(\"padding-left\"));\r\n width += parseInt($(this).css(\"border-left-width\"));\r\n width += parseInt($(this).css(\"border-right-width\"));\r\n $(this).css(\"width\", Math.ceil(width) + \"px\");\r\n });\r\n};\r\n\r\n// find position of element relative to an ancestor matching selector\r\n$.fn.positionFrom = function(selector) {\r\n var ancestor = $(this).closest(selector);\r\n var offset = $(this).offset();\r\n var ancestorOffset = ancestor.offset();\r\n return {\r\n top: offset.top - ancestorOffset.top,\r\n left: offset.left - ancestorOffset.left\r\n };\r\n};\r\n\r\nexport default {\r\n props: [\r\n \"id\", // the module id\r\n \"pkg\", // the module package.json\r\n \"n\", // the GraphNode object (from model)\r\n \"example\", // true if this vue is used as an example display (no need to connect)\r\n \"displayEvents\" // true if events should be displayed\r\n ],\r\n data: function() {\r\n return {\r\n shortName: \"\",\r\n point:\r\n '<svg width=\"14\" height=\"14\" pointer-events=\"all\" position=\"absolute\" version=\"1.1\" xmlns=\"http://www.w3.org/1999/xhtml\"><circle cx=\"7\" cy=\"7\" r=\"5\" version=\"1.1\" xmlns=\"http://www.w3.org/1999/xhtml\" fill=\"#ffffff\" stroke=\"#727272\" style=\"\" stroke-width=\"2\"></circle></svg>'\r\n };\r\n },\r\n beforeUpdate: function() {\r\n //console.log('[UPDATING] ' + this.n.getUniqId());\r\n },\r\n destroyed: function() {\r\n this.deactivateTooltip();\r\n $(\".tooltip\").remove();\r\n },\r\n created: function() {\r\n this.initialized = false;\r\n this.view = window.dualboxEditor.v;\r\n\r\n //console.log('[CREATED] ' + this.n.getUniqId());\r\n // We compute the shortname of our box\r\n if (this.n.isInput() || this.n.isOutput()) {\r\n this.shortName = this.n.getType();\r\n } else {\r\n this.shortName = dbutils.shortName(this.pkg.name);\r\n }\r\n },\r\n mounted: async function() {\r\n //console.log('[MOUNTED] ' + this.n.getUniqId());\r\n var div = $(this.$el);\r\n div.fixCardDisplay();\r\n this.activateTooltip();\r\n return await this.initialize();\r\n },\r\n beforeUpdate: function() {\r\n this.deactivateTooltip();\r\n },\r\n updated: async function() {\r\n //console.log('[UPDATED] ' + this.n.getUniqId());\r\n\r\n // we reset jsPlumb before app update (in graph.vue)\r\n // so we need to initialize again\r\n this.assignContextMenu();\r\n\r\n $(this.$el).fixCardDisplay();\r\n $(this.$el).ready(() => {\r\n this.activateTooltip();\r\n });\r\n return await this.initialize();\r\n },\r\n activate: function() {\r\n this.activateTooltip();\r\n },\r\n deactivate: function() {\r\n this.deactivateTooltip();\r\n },\r\n methods: {\r\n getId: function() {\r\n // if this is an example graphNode, change our \"id\" to \"id-junk\"\r\n // to avoid connection jsplumb conflicts with the real node\r\n return this.example ? this.id + \"-junk\" : this.id;\r\n },\r\n\r\n activateTooltip: function() {\r\n $(this.$el)\r\n .find('[data-toggle=\"tooltip\"]')\r\n .tooltip();\r\n },\r\n\r\n deactivateTooltip: function() {\r\n $(this.$el)\r\n .find('[data-toggle=\"tooltip\"]')\r\n .tooltip(\"dispose\");\r\n },\r\n\r\n initialize: async function() {\r\n var self = this;\r\n var div = $(this.$el);\r\n var id = this.getId();\r\n var view = this.view;\r\n\r\n this.initialized = false;\r\n\r\n if (!this.example) {\r\n // if we have a position, set it\r\n var def = this.n.getDef();\r\n var position = _.get(def, [\"graph\", \"position\"]);\r\n if (position) {\r\n var jsPlumbElement = self.$parent.jsPlumbInstance.getElement(\r\n id\r\n );\r\n self.$parent.jsPlumbInstance.setPosition(\r\n jsPlumbElement,\r\n position\r\n );\r\n }\r\n\r\n // This needs to be registered before draggable\r\n div.on(\"mousedown\", function(e) {\r\n // if this div is not selected already, deselect the other divs\r\n if (!self.$parent.selector.isSelected(this)) {\r\n self.$parent.selector.deselect();\r\n }\r\n });\r\n\r\n await this.initializeJsPlumb();\r\n\r\n div.click(function(e) {\r\n if (e.ctrlKey) {\r\n view.selector.toggleSelection(this);\r\n }\r\n });\r\n\r\n this.assignContextMenu();\r\n }\r\n\r\n return new Promise(resolve => {\r\n div.ready(() => {\r\n //console.log('[INITIALIZED] ' + this.n.getUniqId());\r\n this.initialized = true;\r\n resolve();\r\n });\r\n });\r\n },\r\n\r\n initializeJsPlumb: function() {\r\n var self = this;\r\n var div = $(this.$el);\r\n var id = this.getId();\r\n var view = this.view;\r\n\r\n if (!this.example) {\r\n // If this node was never initialized in this jsplumb instance, do it\r\n if (\r\n !_.get(this.$parent.jsPlumbInstance, [\r\n \"initializedNodes\",\r\n id\r\n ])\r\n ) {\r\n _.set(\r\n this.$parent.jsPlumbInstance,\r\n [\"initializedNodes\", id],\r\n true\r\n ); // initialized\r\n\r\n if (this.n.isInput() || this.n.isOutput()) {\r\n var type = \"*\";\r\n var input = \"value\";\r\n var output = \"value\";\r\n var offsetTop =\r\n $(div)\r\n .find(\".card-top\")\r\n .height() +\r\n 12 /* hr size */ -\r\n 3;\r\n\r\n var uuid = [id, \"input\", input].join(\"#\");\r\n var ep = this.$parent.jsPlumbInstance.addEndpoint(\r\n id,\r\n {\r\n isSource: false,\r\n isTarget: true,\r\n uuid: uuid,\r\n anchor: [0, 0, -1, 0, 0, offsetTop],\r\n maxConnections: 1,\r\n parameters: {\r\n type: \"data\",\r\n target: {\r\n id: id,\r\n input: output\r\n }\r\n }\r\n },\r\n this.$parent.style.inputEndpoint\r\n );\r\n\r\n // add data to the endpoint div so we can identify it easier\r\n $(ep.canvas).attr(\"data-node\", id);\r\n $(ep.canvas).attr(\"data-type\", \"input\");\r\n $(ep.canvas).attr(\"data-input\", input);\r\n\r\n // bind tooltip\r\n $(ep.canvas).attr(\"data-toggle\", \"tooltip\");\r\n $(ep.canvas).attr(\"data-trigger\", \"hover\");\r\n $(ep.canvas).attr(\"data-placement\", \"left\");\r\n $(ep.canvas).attr(\"data-html\", \"true\");\r\n var inputType = view.m\r\n .getNode(id)\r\n .getInputType(\"value\");\r\n $(ep.canvas).attr(\r\n \"title\",\r\n \"Type: <b>\" + inputType + \"</b>\"\r\n );\r\n $(ep.canvas).tooltip();\r\n\r\n // bind context menu to the endpoint\r\n $(ep.canvas).addClass(\"capture-right-click\");\r\n $(ep.canvas).ready(function() {\r\n var menu = new ContextMenu(\r\n \".jtk-endpoint-anchor[data-node='\" +\r\n id.trim() +\r\n \"'][data-input='\" +\r\n input +\r\n \"']\",\r\n [\r\n {\r\n name: \"Create input for here\",\r\n fn: () => {\r\n view.c.createInputFromConnection(\r\n id,\r\n input\r\n );\r\n }\r\n }\r\n ]\r\n );\r\n });\r\n\r\n var uuid = [id, \"output\", output].join(\"#\");\r\n var ep = this.$parent.jsPlumbInstance.addEndpoint(\r\n id,\r\n {\r\n isSource: true,\r\n isTarget: false,\r\n uuid: uuid,\r\n anchor: [1, 0, 1, 0, 0, offsetTop],\r\n parameters: {\r\n type: \"data\",\r\n source: {\r\n id: id,\r\n output: output\r\n }\r\n }\r\n },\r\n this.$parent.style.outputEndpoint\r\n );\r\n\r\n // add data to the endpoint div so we can identify it easier\r\n $(ep.canvas).attr(\"data-node\", id);\r\n $(ep.canvas).attr(\"data-type\", \"output\");\r\n $(ep.canvas).attr(\"data-output\", output);\r\n\r\n // bind tooltip\r\n $(ep.canvas).attr(\"data-toggle\", \"tooltip\");\r\n $(ep.canvas).attr(\"data-trigger\", \"hover\");\r\n $(ep.canvas).attr(\"data-placement\", \"right\");\r\n $(ep.canvas).attr(\"data-html\", \"true\");\r\n var outputType = view.m\r\n .getNode(id)\r\n .getOutputType(\"value\");\r\n $(ep.canvas).attr(\r\n \"title\",\r\n \"Type: <b>\" + outputType + \"</b>\"\r\n );\r\n $(ep.canvas).tooltip();\r\n\r\n // bind context menu to the endpoint\r\n $(ep.canvas).addClass(\"capture-right-click\");\r\n $(ep.canvas).ready(function() {\r\n var menu = new ContextMenu(\r\n \".jtk-endpoint-anchor[data-node='\" +\r\n id.trim() +\r\n \"'][data-output='\" +\r\n output.trim() +\r\n \"']\",\r\n [\r\n {\r\n name: \"Create output for here\",\r\n fn: () => {\r\n view.c.createOutputFromConnection(\r\n id,\r\n output\r\n );\r\n }\r\n }\r\n ]\r\n );\r\n });\r\n } else {\r\n // add input endoints\r\n div.find(\".box-inputs\")\r\n .find(\".point\")\r\n .each(function(index) {\r\n $(this)\r\n .css(\"visibility\", \"hidden\")\r\n .css(\"opacity\", \"0\"); // replaced by jsPlumb point\r\n\r\n var input = div\r\n .find(\".box-inputs\")\r\n .find(\".name\")\r\n .eq(index)\r\n .attr(\"data-input\")\r\n .trim();\r\n var type = view.m\r\n .getNode(id)\r\n .getInputType(input);\r\n\r\n var offsetTop =\r\n $(this).positionFrom(\".card\").top +\r\n $(this).height() / 2 -\r\n 3;\r\n var uuid = [\r\n id,\r\n \"input\",\r\n $(this).data(\"key\")\r\n ].join(\"#\");\r\n var ep = self.$parent.jsPlumbInstance.addEndpoint(\r\n id,\r\n {\r\n isSource: false,\r\n isTarget: true,\r\n uuid: uuid,\r\n anchor: [0, 0, -1, 0, 0, offsetTop],\r\n maxConnections: 1,\r\n parameters: {\r\n type: \"data\",\r\n target: {\r\n id: id,\r\n input: $(this).data(\"key\")\r\n }\r\n }\r\n },\r\n self.$parent.style.inputEndpoint\r\n );\r\n\r\n // add data to the endpoint div so we can identify it easier\r\n $(ep.canvas).attr(\"data-node\", id);\r\n $(ep.canvas).attr(\"data-type\", \"input\");\r\n $(ep.canvas).attr(\"data-input\", input);\r\n\r\n // bind tooltip\r\n $(ep.canvas).attr(\"data-toggle\", \"tooltip\");\r\n $(ep.canvas).attr(\"data-trigger\", \"hover\");\r\n $(ep.canvas).attr(\"data-placement\", \"left\");\r\n $(ep.canvas).attr(\"data-html\", \"true\");\r\n $(ep.canvas).attr(\r\n \"title\",\r\n \"Type: <b>\" + type + \"</b>\"\r\n );\r\n $(ep.canvas).tooltip();\r\n\r\n // bind context menu to the endpoint\r\n $(ep.canvas).addClass(\"capture-right-click\");\r\n $(ep.canvas).ready(function() {\r\n var menu = new ContextMenu(\r\n \".jtk-endpoint-anchor[data-node='\" +\r\n id.trim() +\r\n \"'][data-input='\" +\r\n input.trim() +\r\n \"']\",\r\n [\r\n {\r\n name: \"Create input for here\",\r\n fn: () => {\r\n view.c.createInputFromConnection(\r\n id,\r\n input\r\n );\r\n }\r\n }\r\n ]\r\n );\r\n });\r\n });\r\n\r\n // add output endpoints\r\n div.find(\".box-outputs\")\r\n .find(\".point\")\r\n .each(function(index) {\r\n $(this)\r\n .css(\"visibility\", \"hidden\")\r\n .css(\"opacity\", \"0\"); // replaced by jsPlumb point\r\n\r\n var output = div\r\n .find(\".box-outputs\")\r\n .find(\".name\")\r\n .eq(index)\r\n .attr(\"data-output\")\r\n .trim();\r\n var type = view.m\r\n .getNode(id)\r\n .getOutputType(output);\r\n\r\n var offsetTop =\r\n $(this).positionFrom(\".card\").top +\r\n $(this).height() / 2 -\r\n 3;\r\n var uuid = [\r\n id,\r\n \"output\",\r\n $(this).data(\"key\")\r\n ].join(\"#\");\r\n var ep = self.$parent.jsPlumbInstance.addEndpoint(\r\n id,\r\n {\r\n isSource: true,\r\n isTarget: false,\r\n uuid: uuid,\r\n anchor: [1, 0, 1, 0, 0, offsetTop],\r\n parameters: {\r\n type: \"data\",\r\n source: {\r\n id: id,\r\n output: $(this).data(\"key\")\r\n }\r\n }\r\n },\r\n self.$parent.style.outputEndpoint\r\n );\r\n\r\n // add data to the endpoint div so we can identify it easier\r\n $(ep.canvas).attr(\"data-node\", id);\r\n $(ep.canvas).attr(\"data-type\", \"output\");\r\n $(ep.canvas).attr(\"data-output\", output);\r\n\r\n // bind tooltip\r\n $(ep.canvas).attr(\"data-toggle\", \"tooltip\");\r\n $(ep.canvas).attr(\"data-trigger\", \"hover\");\r\n $(ep.canvas).attr(\"data-placement\", \"right\");\r\n $(ep.canvas).attr(\"data-html\", \"true\");\r\n $(ep.canvas).attr(\r\n \"title\",\r\n \"Type: <b>\" + type + \"</b>\"\r\n );\r\n $(ep.canvas).tooltip();\r\n\r\n // bind context menu to the endpoint\r\n $(ep.canvas).addClass(\"capture-right-click\");\r\n $(ep.canvas).ready(function() {\r\n var menu = new ContextMenu(\r\n \".jtk-endpoint-anchor[data-node='\" +\r\n id.trim() +\r\n \"'][data-output='\" +\r\n output.trim() +\r\n \"']\",\r\n [\r\n {\r\n name: \"Create output for here\",\r\n fn: () => {\r\n view.c.createOutputFromConnection(\r\n id,\r\n output\r\n );\r\n }\r\n }\r\n ]\r\n );\r\n });\r\n });\r\n\r\n if (this.n.isUI() && this.displayEvents) {\r\n // Make this a target for events\r\n this.$parent.jsPlumbInstance.makeTarget(\r\n id,\r\n {\r\n isSource: false,\r\n isTarget: true,\r\n uniqueEndpoint: false,\r\n anchor: \"Continuous\",\r\n uuid: id + \"#event-in\",\r\n paintStyle: {\r\n fill: \"green\",\r\n radius: 3,\r\n stroke: \"#727272\",\r\n strokeWidth: 1\r\n },\r\n parameters: {\r\n type: \"event\",\r\n target: { id: id }\r\n }\r\n },\r\n self.$parent.style.eventEndpoint\r\n );\r\n\r\n // Create an enpoint to create a new event\r\n var ep = this.$parent.jsPlumbInstance.addEndpoint(\r\n id,\r\n {\r\n isSource: true,\r\n isTarget: false,\r\n uuid: id + \"#event-out\",\r\n anchor: [1, 1, 0, 1, 0, -10],\r\n parameters: {\r\n type: \"event\",\r\n source: { id: id }\r\n },\r\n paintStyle: {\r\n fill: \"green\",\r\n radius: 3,\r\n stroke: \"#727272\",\r\n strokeWidth: 1\r\n }\r\n },\r\n this.$parent.style.eventEndpoint\r\n );\r\n\r\n // Add overlay here so we don't mess with splitConnection\r\n ep.addOverlay([\r\n \"PlainArrow\",\r\n {\r\n width: 15,\r\n length: 15,\r\n location: 1,\r\n id: \"arrow\"\r\n }\r\n ]);\r\n\r\n $(ep.canvas).attr(\"data-toggle\", \"tooltip\");\r\n $(ep.canvas).attr(\"data-trigger\", \"hover\");\r\n $(ep.canvas).attr(\"data-placement\", \"bottom\");\r\n $(ep.canvas).attr(\"data-html\", \"true\");\r\n $(ep.canvas).attr(\r\n \"title\",\r\n \"Connect from here ito add an event that will be triggered when this box is done computing.\"\r\n );\r\n $(ep.canvas).tooltip();\r\n }\r\n }\r\n\r\n // Make the div draggable\r\n this.$parent.jsPlumbInstance.draggable(div, {\r\n //containment:true, // not allowed outside of container div\r\n drag: function(e) {\r\n // TODO: bug. After a repaint(), jsPlumb seems to be broken (connections dont follow on div drag)\r\n // It doesn't occur on jsPlumb.reset() instead of creating another instance on beforeUpdate(),\r\n // (as it should be), but we can't do that, because JsPlumb is broken on zoom otherwise...\r\n // One of thoses problem may be fixed later by updating jsPlumb...\r\n // Note: this \"fix\" may affect performances on drag, maybe a setTimeout will do\r\n //self.$parent.jsPlumbInstance.repaintEverything();\r\n self.$parent.jsPlumbInstance.repaint(id);\r\n },\r\n stop: function(e) {\r\n // resize the canvas if necessary\r\n self.$parent.canvasSizeHandler.debouncedResize();\r\n\r\n if (\r\n self.$parent.selector.isMultipleSelectionActive()\r\n ) {\r\n // We just dropped a bunch of divs, ajust all their positions\r\n self.view.m.batch(() => {\r\n self.$parent.selector.each(div => {\r\n var pos = self.$parent.jsPlumbInstance.getPosition(\r\n div\r\n );\r\n view.m\r\n .getNode($(div).attr(\"id\"))\r\n .setPosition(pos);\r\n });\r\n });\r\n } else {\r\n // We just dropped this one, set the new position in the graph model\r\n var el = self.$parent.jsPlumbInstance.getElement(\r\n id\r\n );\r\n $(el).ready(function() {\r\n var pos = self.$parent.jsPlumbInstance.getPosition(\r\n el\r\n );\r\n view.m.getNode(id).setPosition(pos);\r\n });\r\n }\r\n }\r\n });\r\n }\r\n }\r\n\r\n return new Promise(resolve =>\r\n this.$parent.jsPlumbInstance.ready(resolve)\r\n );\r\n },\r\n\r\n assignContextMenu: function() {\r\n var id = this.getId();\r\n\r\n // Create a contextmenu for the div\r\n var contextOptions = [\r\n {\r\n name: \"Remove this box\",\r\n fn: () => {\r\n this.view.c.removeBox(id);\r\n }\r\n }\r\n ];\r\n if (this.n.isModule() || this.n.isUI() || this.n.isInput() || this.n.isOutput()) {\r\n contextOptions.push({\r\n name: \"Duplicate this box\",\r\n fn: () => {\r\n this.view.c.duplicateBox(id);\r\n }\r\n });\r\n }\r\n var nodeMenu = new ContextMenu(\"#\" + id, contextOptions);\r\n },\r\n\r\n htmlentities: function(s) {\r\n return this.view.utils.htmlentities(s);\r\n },\r\n\r\n getVisibleInputs: function() {\r\n return this.n.getInputsNames().filter(inputName => {\r\n return this.n.isInputVisible(inputName);\r\n });\r\n },\r\n\r\n getVisibleOutputs: function() {\r\n return this.n.getOutputsNames().filter(outputName => {\r\n return this.n.isOutputVisible(outputName);\r\n });\r\n },\r\n\r\n enterMetanode: function(e) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n this.view.c.enterMetanode(this.id);\r\n },\r\n\r\n openNodeSettings: function(e) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.view.openBoxSettings(this.id);\r\n },\r\n\r\n openSnapshotDetails: async function(e) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n await this.view.openDebug(this.id);\r\n },\r\n\r\n registerToPanel: async function(e) {\r\n await this.view.c.registerNodeToInterface(this.id);\r\n }\r\n },\r\n watch: {\r\n app: {\r\n handler: () => {\r\n console.log(\"graphVue.app changed\");\r\n },\r\n deep: true\r\n }\r\n }\r\n};\r\n</script>\r\n"]}, media: undefined });
47859
47913
 
47860
47914
  };
47861
47915
  /* scoped */
@@ -47903,10 +47957,12 @@ class Zoomer {
47903
47957
  }
47904
47958
 
47905
47959
  initialize() {
47906
- this.container.off('mousewheel');
47907
- this.container.on('mousewheel', (e) => {
47908
- // normalize wheel to +1 or -1
47909
- if (e.originalEvent.wheelDelta / 120 > 0) {
47960
+ this.container.off('mousewheel DOMMouseScroll');
47961
+ this.container.on('mousewheel DOMMouseScroll', (e) => {
47962
+ let evt = e.originalEvent;
47963
+ let direction = (evt.detail < 0 || evt.wheelDelta > 0) ? 1 : -1; // normalize wheel to +1 or -1
47964
+
47965
+ if (direction > 0) {
47910
47966
  this.zoomIn(e);
47911
47967
  } else {
47912
47968
  this.zoomOut(e);
@@ -63594,35 +63650,35 @@ var script$5 = {
63594
63650
  "mousePosition" // mouse position when this panel was opened
63595
63651
  ],
63596
63652
  components: {
63597
- 'search-results' : SearchResultsVue,
63598
- 'display-result' : DisplayResultVue,
63599
- 'edit-type' : EditTypeVue
63653
+ "search-results": SearchResultsVue,
63654
+ "display-result": DisplayResultVue,
63655
+ "edit-type": EditTypeVue
63600
63656
  },
63601
- data: function () {
63657
+ data: function() {
63602
63658
  return {
63603
63659
  error: null,
63604
63660
 
63605
63661
  searchText: {}, // the search text, indexed by selectedType
63606
63662
  results: {}, // dictionary of arrays, indexed by selectedType
63607
- selectedResult : {}, // dictionary of string, indexed by selectedType
63663
+ selectedResult: {}, // dictionary of string, indexed by selectedType
63608
63664
  selectedType: "module",
63609
63665
  inputType: "*",
63610
63666
  outputType: "*"
63611
- }
63667
+ };
63612
63668
  },
63613
63669
  created: function() {
63614
63670
  this.view = window.dualboxEditor.v;
63615
63671
  },
63616
63672
  updated: function() {
63617
- console.log('AddNode updated !');
63673
+ console.log("AddNode updated !");
63618
63674
  this.updateVisibility();
63619
63675
  this.setSearchFocus();
63620
63676
 
63621
- if( !this.display ) {
63677
+ if (!this.display) {
63622
63678
  // make sure the modal disappeared
63623
- $(this.$el).modal('hide');
63624
- $('body').removeClass('modal-open');
63625
- $('.modal-backdrop').remove();
63679
+ $(this.$el).modal("hide");
63680
+ $("body").removeClass("modal-open");
63681
+ $(".modal-backdrop").remove();
63626
63682
  }
63627
63683
  },
63628
63684
  mounted: function() {
@@ -63633,23 +63689,24 @@ var script$5 = {
63633
63689
  this.setSearchFocus();
63634
63690
  });
63635
63691
  $(this.$el).on("hide.bs.modal", () => {
63636
- self.$emit('closed');
63692
+ self.$emit("closed");
63637
63693
  });
63638
63694
 
63639
- $(this.$el).find('[data-toggle="pill"]').on('shown.bs.tab', (e) => {
63640
- this.setSearchFocus();
63641
- var selectedResult = this.getSelectedResult();
63642
- if( selectedResult ) {
63643
- this.$refs.searchResults.selected = selectedResult.name;
63644
- }
63645
- });
63695
+ $(this.$el)
63696
+ .find('[data-toggle="pill"]')
63697
+ .on("shown.bs.tab", e => {
63698
+ this.setSearchFocus();
63699
+ var selectedResult = this.getSelectedResult();
63700
+ if (selectedResult) {
63701
+ this.$refs.searchResults.selected = selectedResult.name;
63702
+ }
63703
+ });
63646
63704
  },
63647
63705
  methods: {
63648
- updateVisibility : function() {
63649
- if( this.display ) {
63706
+ updateVisibility: function() {
63707
+ if (this.display) {
63650
63708
  $(this.$el).modal("show");
63651
- }
63652
- else {
63709
+ } else {
63653
63710
  $(this.$el).modal("hide");
63654
63711
  }
63655
63712
  },
@@ -63657,11 +63714,28 @@ var script$5 = {
63657
63714
  closeModal: function() {
63658
63715
  // don't mutate prop directly, mute the parent
63659
63716
  // this.display = false;
63660
- this.$emit('closed');
63717
+
63718
+ return new Promise((resolve, reject) => {
63719
+ this.$emit("closed");
63720
+
63721
+ let forceCloseModal = () => {
63722
+ if (!this.display) {
63723
+ resolve();
63724
+ } else {
63725
+ this.$emit("closed");
63726
+ setTimeout(forceCloseModal, 100);
63727
+ }
63728
+ };
63729
+
63730
+ this.$nextTick(forceCloseModal);
63731
+ });
63661
63732
  },
63662
63733
 
63663
- setSearchFocus : function() {
63664
- $(this.$el).find('.nav-link.active').find('input').focus();
63734
+ setSearchFocus: function() {
63735
+ $(this.$el)
63736
+ .find(".nav-link.active")
63737
+ .find("input")
63738
+ .focus();
63665
63739
  },
63666
63740
 
63667
63741
  selectType(t) {
@@ -63670,81 +63744,100 @@ var script$5 = {
63670
63744
  this.searchText[t] = searchText;
63671
63745
  },
63672
63746
 
63673
- addSelectedNode: function(e) {
63674
- switch( this.selectedType ) {
63675
- case "module":
63676
- case "ui":
63677
- var selectedNode = $('.node-result.selected')[0];
63678
- if( selectedNode ) {
63679
- this.closeModal();
63680
- this.$nextTick(() => {
63747
+ addSelectedNode: async function(e) {
63748
+ switch (this.selectedType) {
63749
+ case "module":
63750
+ case "ui":
63751
+ var selectedNode = $(".node-result.selected")[0];
63752
+ if (selectedNode) {
63753
+ await this.closeModal();
63681
63754
  // add node to the controller
63682
- var packageName = $(selectedNode).data('package');
63755
+ var packageName = $(selectedNode).data("package");
63683
63756
  this.view.c.addNewBox(packageName, this.mousePosition);
63684
- });
63685
- }
63686
- else {
63687
- sweetalert2_all('Please select a node', '', 'error');
63688
- return;
63689
- }
63690
- break;
63757
+ } else {
63758
+ sweetalert2_all("Please select a node", "", "error");
63759
+ return;
63760
+ }
63761
+ break;
63691
63762
 
63692
- case "input":
63693
- var type = this.$refs.inputType.get();
63694
- var name = $(this.$el).find('.input-name').val();
63695
- var desc = $(this.$el).find('.input-description').val();
63696
- if( type !== undefined && name ) {
63697
- this.closeModal();
63698
- this.$nextTick(() => {
63699
- this.view.c.addInput(name, type, desc, this.mousePosition);
63763
+ case "input":
63764
+ var type = this.$refs.inputType.get();
63765
+ var name = $(this.$el)
63766
+ .find(".input-name")
63767
+ .val();
63768
+ var desc = $(this.$el)
63769
+ .find(".input-description")
63770
+ .val();
63771
+ if (type !== undefined && name) {
63772
+ await this.closeModal();
63773
+ this.view.c.addInput(
63774
+ name,
63775
+ type,
63776
+ desc,
63777
+ this.mousePosition
63778
+ );
63700
63779
  // reset fields
63701
63780
  this.$refs.inputType.resetChanges();
63702
- $(this.$el).find('.input-name').val("");
63703
- $(this.$el).find('.input-description').val("");
63704
- });
63705
- }
63706
- else {
63707
- sweetalert2_all('Please complete all fields', '', 'error');
63708
- return;
63709
- }
63710
- break;
63781
+ $(this.$el)
63782
+ .find(".input-name")
63783
+ .val("");
63784
+ $(this.$el)
63785
+ .find(".input-description")
63786
+ .val("");
63787
+ } else {
63788
+ sweetalert2_all("Please complete all fields", "", "error");
63789
+ return;
63790
+ }
63791
+ break;
63711
63792
 
63712
- case "output":
63713
- var name = $(this.$el).find('.output-name').val();
63714
- var type = this.$refs.outputType.get();
63715
- var desc = $(this.$el).find('.output-description').val();
63716
- if( type !== undefined && name ) {
63717
- this.closeModal();
63718
- this.$nextTick(() => {
63719
- this.view.c.addOutput(name, type, desc, this.mousePosition);
63793
+ case "output":
63794
+ var name = $(this.$el)
63795
+ .find(".output-name")
63796
+ .val();
63797
+ var type = this.$refs.outputType.get();
63798
+ var desc = $(this.$el)
63799
+ .find(".output-description")
63800
+ .val();
63801
+ if (type !== undefined && name) {
63802
+ await this.closeModal();
63803
+ this.view.c.addOutput(
63804
+ name,
63805
+ type,
63806
+ desc,
63807
+ this.mousePosition
63808
+ );
63720
63809
  // reset fields
63721
63810
  this.$refs.outputType.resetChanges();
63722
- $(this.$el).find('.output-name').val("");
63723
- $(this.$el).find('.output-description').val("");
63724
- });
63725
- }
63726
- else {
63727
- sweetalert2_all('Please complete all fields', '', 'error');
63728
- return;
63729
- }
63730
- break;
63811
+ $(this.$el)
63812
+ .find(".output-name")
63813
+ .val("");
63814
+ $(this.$el)
63815
+ .find(".output-description")
63816
+ .val("");
63817
+ } else {
63818
+ sweetalert2_all("Please complete all fields", "", "error");
63819
+ return;
63820
+ }
63821
+ break;
63731
63822
 
63732
- case "metanode":
63733
- var name = $(this.$el).find('.metanode-name').val();
63734
- var desc = $(this.$el).find('.metanode-description').val();
63735
- if( !name ) {
63736
- sweetalert2_all('Please complete name field', '', 'error');
63737
- return;
63738
- }
63823
+ case "metanode":
63824
+ var name = $(this.$el)
63825
+ .find(".metanode-name")
63826
+ .val();
63827
+ var desc = $(this.$el)
63828
+ .find(".metanode-description")
63829
+ .val();
63830
+ if (!name) {
63831
+ sweetalert2_all("Please complete name field", "", "error");
63832
+ return;
63833
+ }
63739
63834
 
63740
- var json = this.metanodeJSON || {};
63741
- json.description = desc;
63835
+ var json = this.metanodeJSON || {};
63836
+ json.description = desc;
63742
63837
 
63743
- this.closeModal();
63744
- this.$nextTick(() => {
63838
+ await this.closeModal();
63745
63839
  this.view.c.addNewMetabox(name, json, this.mousePosition);
63746
- });
63747
- default:
63840
+ default:
63748
63841
  }
63749
63842
  },
63750
63843
 
@@ -63753,12 +63846,14 @@ var script$5 = {
63753
63846
  var text = this.searchText[this.selectedType];
63754
63847
  try {
63755
63848
  this.error = null;
63756
- this.results[this.selectedType] = await this.view.e.search(text, this.selectedType);
63849
+ this.results[this.selectedType] = await this.view.e.search(
63850
+ text,
63851
+ this.selectedType
63852
+ );
63757
63853
  this.$forceUpdate();
63758
- }
63759
- catch(e) {
63854
+ } catch (e) {
63760
63855
  this.error = e;
63761
- sweetalert2_all('error searching packages', e.reason, "error");
63856
+ sweetalert2_all("error searching packages", e.reason, "error");
63762
63857
  }
63763
63858
  },
63764
63859
 
@@ -63769,14 +63864,14 @@ var script$5 = {
63769
63864
  setSelectedResult: function(packageName) {
63770
63865
  // first, find the selected result in the list
63771
63866
  var selectedPackage = null;
63772
- lodash.each(this.getResults(), (r) => {
63773
- if( r.name == packageName ) {
63867
+ lodash.each(this.getResults(), r => {
63868
+ if (r.name == packageName) {
63774
63869
  selectedPackage = r;
63775
63870
  return false;
63776
63871
  }
63777
63872
  });
63778
63873
 
63779
- if( !selectedPackage ) {
63874
+ if (!selectedPackage) {
63780
63875
  throw "Could not find package named " + packageName;
63781
63876
  }
63782
63877
 
@@ -63794,16 +63889,18 @@ var script$5 = {
63794
63889
 
63795
63890
  getNbResults: function() {
63796
63891
  var results = this.getResults();
63797
- return results && results.length ? results.length: 0;
63892
+ return results && results.length ? results.length : 0;
63798
63893
  },
63799
63894
 
63800
63895
  onMetaboxFileSelect: function(e) {
63801
63896
  var file = e.target.files[0];
63802
63897
  const reader = new FileReader();
63803
- reader.onload = (e) => {
63898
+ reader.onload = e => {
63804
63899
  this.metanodeJSON = JSON.parse(e.target.result);
63805
- if( this.metanodeJSON.description ) {
63806
- $(this.$el).find('.metanode-description').val(this.metanodeJSON.description);
63900
+ if (this.metanodeJSON.description) {
63901
+ $(this.$el)
63902
+ .find(".metanode-description")
63903
+ .val(this.metanodeJSON.description);
63807
63904
  }
63808
63905
  };
63809
63906
  reader.readAsText(file);
@@ -64205,7 +64302,9 @@ var __vue_render__$5 = function() {
64205
64302
  },
64206
64303
  [
64207
64304
  _c("h2", { staticClass: "mt-2" }, [
64208
- _vm._v("Add a new Metabox ")
64305
+ _vm._v(
64306
+ "Add a new Metabox\n "
64307
+ )
64209
64308
  ]),
64210
64309
  _vm._v(" "),
64211
64310
  _vm._m(10),
@@ -64453,11 +64552,11 @@ __vue_render__$5._withStripped = true;
64453
64552
  /* style */
64454
64553
  const __vue_inject_styles__$5 = function (inject) {
64455
64554
  if (!inject) return
64456
- inject("data-v-1749da54_0", { source: "\n.add-node-modal .modal-body[data-v-1749da54] {\r\n height: 70vh;\n}\n.h100[data-v-1749da54] {\r\n height: 100%!important;\r\n min-height: 100%!important;\n}\n.table-desc th[data-v-1749da54], .table-desc td[data-v-1749da54] {\r\n margin-right: 10px;\n}\n#add-node-modal .modal-dialog[data-v-1749da54] {\r\n min-width: calc(100% - 40px)!important;\r\n height: calc(100% - 40px);\r\n margin: 20px;\r\n padding: 0;\n}\n#add-node-modal .modal-content[data-v-1749da54] {\r\n height: auto;\r\n min-height: 100%;\r\n border-radius: 0;\n}\n.nav-item[data-v-1749da54] {\r\n margin-left: 15px;\r\n margin-right: 15px;\n}\n.nav-link[data-v-1749da54] {\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-bottom: 4px;\r\n padding-top: 4px;\r\n vertical-align: middle;\r\n position: relative;\r\n user-select: none;\n}\n.nav-link.active[data-v-1749da54] {\r\n top: 0px;\r\n border-top-left-radius: 5px;\r\n border-bottom-left-radius: 5px;\n}\n.nav-link > span[data-v-1749da54] {\r\n padding-left: 10px;\r\n padding-right: 10px;\n}\n.nav-link.active > span[data-v-1749da54] {\r\n color: black;\n}\n.input-search[data-v-1749da54] {\r\n display: none;\r\n width: 1px;\r\n height: 24px;\r\n box-shadow: none!important;\r\n border-color: rgba(0,0,0,0.3)!important;\n}\n.nav-link.active .input-search[data-v-1749da54] {\r\n display: inline-block;\r\n border-top-left-radius: 0px;\r\n border-bottom-left-radius: 0px;\r\n transition: width 1s;\r\n width: 200px;\n}\n.nav-compute > a.active > input[data-v-1749da54] {\r\n background-color: rgba(0,0,0,0.3)!important;\n}\n.nav-compute > a.active[data-v-1749da54], .nav-compute > a.active > input[data-v-1749da54] {\r\n background-color: rgba(0,0,0,0.3)!important;\r\n color: rgba(255,255,255,0.5);\n}\n.nav-compute> a.active > .input-search[data-v-1749da54]::placeholder {\r\n color: rgba(255,255,255,0.5);\n}\n.nav-uis > a.active[data-v-1749da54], .nav-uis > a.active > input[data-v-1749da54] {\r\n background-color: #bff2ca!important;\n}\n.nav-inputs > a.active[data-v-1749da54] {\r\n background-color: #f5d76e!important;\n}\n.nav-compute > a.active > input[data-v-1749da54] {\r\n background-color: rgba(0,0,0,0.8);\n}\n.nav-outputs > a.active[data-v-1749da54], .nav-outputs > a.active > input[data-v-1749da54] {\r\n background-color: #ffb3a7!important;\n}\n.message-container[data-v-1749da54] {\r\n position: relative;\r\n width: 100%;\r\n height: 100%;\n}\n.message[data-v-1749da54] {\r\n position: absolute;\r\n top: 50%;\r\n transform: translateY(-80%);\r\n left: 0;\r\n right: 0;\r\n opacity: 0.6;\r\n text-align: center;\n}\n.tab-content[data-v-1749da54], .tab-pane[data-v-1749da54] {\r\n width: 100%;\r\n height: 100%;\n}\nlabel[data-v-1749da54] {\r\n font-size: 20px;\r\n margin-top: 20px;\n}\nfieldset[data-v-1749da54] {\r\n border: 1px solid rgba(0,0,0,0.1);\r\n margin: 10px;\r\n padding: 20px;\r\n min-width: 600px;\n}\r\n", map: {"version":3,"sources":["C:\\Users\\maxim\\Projects\\dualbox\\editor\\js\\src\\v\\templates\\addNode.vue"],"names":[],"mappings":";AACA;IACA,YAAA;AACA;AAEA;IACA,sBAAA;IACA,0BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;EACA,sCAAA;EACA,yBAAA;EACA,YAAA;EACA,UAAA;AACA;AAEA;EACA,YAAA;EACA,gBAAA;EACA,gBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,gBAAA;IACA,sBAAA;IACA,kBAAA;IACA,iBAAA;AACA;AAEA;IACA,QAAA;IACA,2BAAA;IACA,8BAAA;AACA;AAEA;IACA,kBAAA;IACA,mBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,aAAA;IACA,UAAA;IACA,YAAA;IACA,0BAAA;IACA,uCAAA;AACA;AAEA;IACA,qBAAA;IACA,2BAAA;IACA,8BAAA;IACA,oBAAA;IACA,YAAA;AACA;AACA;IACA,2CAAA;AACA;AAEA;IACA,2CAAA;IACA,4BAAA;AACA;AAEA;IACA,4BAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,iCAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,kBAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,2BAAA;IACA,OAAA;IACA,QAAA;IACA,YAAA;IACA,kBAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,eAAA;IACA,gBAAA;AACA;AAEA;IACA,iCAAA;IACA,YAAA;IACA,aAAA;IACA,gBAAA;AACA","file":"addNode.vue","sourcesContent":["<style scoped>\r\n.add-node-modal .modal-body {\r\n height: 70vh;\r\n}\r\n\r\n.h100 {\r\n height: 100%!important;\r\n min-height: 100%!important;\r\n}\r\n\r\n.table-desc th, .table-desc td {\r\n margin-right: 10px;\r\n}\r\n\r\n#add-node-modal .modal-dialog {\r\n min-width: calc(100% - 40px)!important;\r\n height: calc(100% - 40px);\r\n margin: 20px;\r\n padding: 0;\r\n}\r\n\r\n#add-node-modal .modal-content {\r\n height: auto;\r\n min-height: 100%;\r\n border-radius: 0;\r\n}\r\n\r\n.nav-item {\r\n margin-left: 15px;\r\n margin-right: 15px;\r\n}\r\n\r\n.nav-link {\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-bottom: 4px;\r\n padding-top: 4px;\r\n vertical-align: middle;\r\n position: relative;\r\n user-select: none;\r\n}\r\n\r\n.nav-link.active {\r\n top: 0px;\r\n border-top-left-radius: 5px;\r\n border-bottom-left-radius: 5px;\r\n}\r\n\r\n.nav-link > span {\r\n padding-left: 10px;\r\n padding-right: 10px;\r\n}\r\n\r\n.nav-link.active > span {\r\n color: black;\r\n}\r\n\r\n.input-search {\r\n display: none;\r\n width: 1px;\r\n height: 24px;\r\n box-shadow: none!important;\r\n border-color: rgba(0,0,0,0.3)!important;\r\n}\r\n\r\n.nav-link.active .input-search {\r\n display: inline-block;\r\n border-top-left-radius: 0px;\r\n border-bottom-left-radius: 0px;\r\n transition: width 1s;\r\n width: 200px;\r\n}\r\n.nav-compute > a.active > input {\r\n background-color: rgba(0,0,0,0.3)!important;\r\n}\r\n\r\n.nav-compute > a.active, .nav-compute > a.active > input {\r\n background-color: rgba(0,0,0,0.3)!important;\r\n color: rgba(255,255,255,0.5);\r\n}\r\n\r\n.nav-compute> a.active > .input-search::placeholder {\r\n color: rgba(255,255,255,0.5);\r\n}\r\n\r\n.nav-uis > a.active, .nav-uis > a.active > input {\r\n background-color: #bff2ca!important;\r\n}\r\n\r\n.nav-inputs > a.active {\r\n background-color: #f5d76e!important;\r\n}\r\n\r\n.nav-compute > a.active > input {\r\n background-color: rgba(0,0,0,0.8);\r\n}\r\n\r\n.nav-outputs > a.active, .nav-outputs > a.active > input {\r\n background-color: #ffb3a7!important;\r\n}\r\n\r\n.message-container {\r\n position: relative;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.message {\r\n position: absolute;\r\n top: 50%;\r\n transform: translateY(-80%);\r\n left: 0;\r\n right: 0;\r\n opacity: 0.6;\r\n text-align: center;\r\n}\r\n\r\n.tab-content, .tab-pane {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\nlabel {\r\n font-size: 20px;\r\n margin-top: 20px;\r\n}\r\n\r\nfieldset {\r\n border: 1px solid rgba(0,0,0,0.1);\r\n margin: 10px;\r\n padding: 20px;\r\n min-width: 600px;\r\n}\r\n</style>\r\n\r\n<template>\r\n <div class=\"modal fade add-node-modal\" :class=\"{ 'hide' : !display }\" id=\"add-node-modal\" tabindex=\"-1\" role=\"dialog\">\r\n <div class=\"modal-dialog\" role=\"document\">\r\n <div class=\"modal-content h100\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title\">Add Box</h5>\r\n <ul class=\"nav nav-pills mr-auto ml-2\">\r\n <li class=\"nav-item nav-compute\">\r\n <a class=\"nav-link active\" href=\"#add-module-or-ui\" data-toggle=\"pill\" @click=\"selectType('module')\" draggable=\"false\">\r\n <span>Compute</span>\r\n <input class=\"form-control input-sm input-search search-modules\" type=\"text\" placeholder=\"Search modules...\" id=\"search-modules\" v-model=\"searchText['module']\" @input=\"searchModules\" autofocus/>\r\n </a>\r\n </li>\r\n <li class=\"nav-item nav-uis\">\r\n <a class=\"nav-link\" href=\"#add-module-or-ui\" data-toggle=\"pill\" @click=\"selectType('ui')\" draggable=\"false\">\r\n <span>UI</span>\r\n <input class=\"form-control input-sm input-search search-ui\" type=\"text\" placeholder=\"Search UIs...\" id=\"search-uis\" @input=\"searchModules\" v-model=\"searchText['ui']\" autofocus/>\r\n </a>\r\n </li>\r\n <li class=\"nav-item nav-inputs\" @click=\"selectType('input')\">\r\n <a class=\"nav-link\" href=\"#add-input\" data-toggle=\"pill\" draggable=\"false\"><span>Input</span></a>\r\n </li>\r\n <li class=\"nav-item nav-outputs\" @click=\"selectType('output')\">\r\n <a class=\"nav-link\" href=\"#add-output\"data-toggle=\"pill\" draggable=\"false\"><span>Output</span></a>\r\n </li>\r\n <li class=\"nav-item nav-outputs\" @click=\"selectType('metanode')\">\r\n <a class=\"nav-link\" href=\"#add-metanode\"data-toggle=\"pill\" draggable=\"false\"><span>Metabox</span></a>\r\n </li>\r\n </ul>\r\n\r\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div class=\"container-fluid h100\">\r\n\r\n <div class=\"tab-content\">\r\n <div class=\"tab-pane active\" id=\"add-module-or-ui\" role=\"tabpanel\" aria-labelledby=\"add-module-or-ui-tab\">\r\n <div class=\"row h100\">\r\n <div v-if=\"getSearchText().length == 0\" class=\"message-container\">\r\n <p class=\"message\"><i class=\"fas fa-search\"></i> Type something to search through the Dualbox library.</p>\r\n </div>\r\n <div v-else-if=\"getNbResults() == 0\">\r\n <p class=\"message\"><i class=\"fas fa-search\"></i> No results.</p>\r\n </div>\r\n <template v-else>\r\n <div class=\"col-md-4 h100\" style=\"padding-left: 0; padding-right: 0; overflow-y: auto; overflow-x: hidden;\">\r\n <search-results ref=\"searchResults\" :results=\"getResults()\" :err=\"error\" @resultSelected=\"setSelectedResult\"></search-results>\r\n </div>\r\n <div class=\"col-md-8 h100\" style=\"padding-left: 15px; padding-right: 0;\">\r\n <display-result ref=\"displayResults\" v-if=\"getSelectedResult()\" :result=\"getSelectedResult()\"></display-result>\r\n <div v-else class=\"message-container\">\r\n <p class=\"message\">Select a result to display</p>\r\n </div>\r\n </div>\r\n </template>\r\n </div>\r\n </div>\r\n <div class=\"tab-pane\" id=\"add-input\" role=\"tabpanel\" aria-labelledby=\"add-input-tab\">\r\n <div class=\"row\">\r\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\r\n <h2 class=\"mt-2\">Add a new input</h2>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"input-name\">Input name:</label>\r\n <input type=\"text\" class=\"form-control input-name\" id=\"input-name\" placeholder=\"Enter name...\" autofocus required>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"input-name\">Input type:</label>\r\n <input style=\"display: none;\" required/>\r\n <edit-type ref=\"inputType\" :type=\"inputType\" :displayOKButton=\"false\"></edit-type>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"input-description\">Input description:</label>\r\n <textarea class=\"input-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\r\n </textarea>\r\n </div>\r\n </fieldset>\r\n </div>\r\n </div>\r\n <div class=\"tab-pane\" id=\"add-output\" role=\"tabpanel\" aria-labelledby=\"add-output-tab\">\r\n <div class=\"row\">\r\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\r\n <h2 class=\"mt-2\">Add a new output</h2>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"output-name\">Output name:</label>\r\n <input type=\"text\" class=\"form-control output-name\" id=\"output-name\" placeholder=\"Enter name...\" autofocus required>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"output-name\">Output type:</label>\r\n <input style=\"display: none;\" required/>\r\n <edit-type ref=\"outputType\" :type=\"outputType\" :displayOKButton=\"false\"></edit-type>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"output-description\">Output description:</label>\r\n <textarea class=\"output-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\r\n </textarea>\r\n </div>\r\n </fieldset>\r\n </div>\r\n </div>\r\n <div class=\"tab-pane\" id=\"add-metanode\" role=\"tabpanel\" aria-labelledby=\"add-metanode-tab\">\r\n <div class=\"row\">\r\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\r\n <h2 class=\"mt-2\">Add a new Metabox <!--<button class=\"btn btn-outline-secondary float-right\" @click=\"importMetabox\"><i class=\"fas fa-upload\"></i></button>--></h2>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"metanode-name\">Metabox name:</label>\r\n <input type=\"text\" class=\"form-control metanode-name\" id=\"metanode-name\" placeholder=\"Enter name...\" autofocus required>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"metanode-def\">Metabox definition (optional):</label>\r\n <input type=\"file\" class=\"form-control-file\" id=\"metanode-def\" @change=\"onMetaboxFileSelect\">\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"metanode-description\">Metabox description:</label>\r\n <textarea class=\"metanode-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\r\n </textarea>\r\n </div>\r\n </fieldset>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\r\n <button type=\"button\" class=\"btn btn-primary add-node-btn\" @click=\"addSelectedNode\">Add node</button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport _ from 'lodash-es';\r\nimport swal from 'sweetalert2';\r\nimport SearchResultsVue from './searchResults.vue';\r\nimport DisplayResultVue from './displayResult.vue';\r\nimport EditTypeVue from './editType.vue'\r\n\r\nexport default {\r\n props: [\r\n \"display\", // original state (true = show, false=hide) of the modal\r\n \"mousePosition\" // mouse position when this panel was opened\r\n ],\r\n components: {\r\n 'search-results' : SearchResultsVue,\r\n 'display-result' : DisplayResultVue,\r\n 'edit-type' : EditTypeVue\r\n },\r\n data: function () {\r\n return {\r\n error: null,\r\n\r\n searchText: {}, // the search text, indexed by selectedType\r\n results: {}, // dictionary of arrays, indexed by selectedType\r\n selectedResult : {}, // dictionary of string, indexed by selectedType\r\n selectedType: \"module\",\r\n inputType: \"*\",\r\n outputType: \"*\"\r\n }\r\n },\r\n created: function() {\r\n this.view = window.dualboxEditor.v;\r\n },\r\n updated: function() {\r\n console.log('AddNode updated !');\r\n this.updateVisibility();\r\n this.setSearchFocus();\r\n\r\n if( !this.display ) {\r\n // make sure the modal disappeared\r\n $(this.$el).modal('hide');\r\n $('body').removeClass('modal-open');\r\n $('.modal-backdrop').remove();\r\n }\r\n },\r\n mounted: function() {\r\n var self = this;\r\n this.updateVisibility(); // to init our modal\r\n\r\n $(this.$el).on(\"shown.bs.modal\", () => {\r\n this.setSearchFocus();\r\n });\r\n $(this.$el).on(\"hide.bs.modal\", () => {\r\n self.$emit('closed');\r\n });\r\n\r\n $(this.$el).find('[data-toggle=\"pill\"]').on('shown.bs.tab', (e) => {\r\n this.setSearchFocus();\r\n var selectedResult = this.getSelectedResult();\r\n if( selectedResult ) {\r\n this.$refs.searchResults.selected = selectedResult.name;\r\n }\r\n });\r\n },\r\n methods: {\r\n updateVisibility : function() {\r\n if( this.display ) {\r\n $(this.$el).modal(\"show\");\r\n }\r\n else {\r\n $(this.$el).modal(\"hide\");\r\n }\r\n },\r\n\r\n closeModal: function() {\r\n // don't mutate prop directly, mute the parent\r\n // this.display = false;\r\n this.$emit('closed');\r\n },\r\n\r\n setSearchFocus : function() {\r\n $(this.$el).find('.nav-link.active').find('input').focus();\r\n },\r\n\r\n selectType(t) {\r\n let searchText = this.searchText[this.selectedType];\r\n this.selectedType = t;\r\n this.searchText[t] = searchText;\r\n },\r\n\r\n addSelectedNode: function(e) {\r\n switch( this.selectedType ) {\r\n case \"module\":\r\n case \"ui\":\r\n var selectedNode = $('.node-result.selected')[0];\r\n if( selectedNode ) {\r\n this.closeModal();\r\n this.$nextTick(() => {\r\n // add node to the controller\r\n var packageName = $(selectedNode).data('package');\r\n this.view.c.addNewBox(packageName, this.mousePosition);\r\n });\r\n }\r\n else {\r\n swal('Please select a node', '', 'error');\r\n return;\r\n }\r\n break;\r\n\r\n case \"input\":\r\n var type = this.$refs.inputType.get();\r\n var name = $(this.$el).find('.input-name').val();\r\n var desc = $(this.$el).find('.input-description').val();\r\n if( type !== undefined && name ) {\r\n this.closeModal();\r\n this.$nextTick(() => {\r\n this.view.c.addInput(name, type, desc, this.mousePosition);\r\n // reset fields\r\n this.$refs.inputType.resetChanges();\r\n $(this.$el).find('.input-name').val(\"\");\r\n $(this.$el).find('.input-description').val(\"\");\r\n });\r\n }\r\n else {\r\n swal('Please complete all fields', '', 'error');\r\n return;\r\n }\r\n break;\r\n\r\n case \"output\":\r\n var name = $(this.$el).find('.output-name').val();\r\n var type = this.$refs.outputType.get();\r\n var desc = $(this.$el).find('.output-description').val();\r\n if( type !== undefined && name ) {\r\n this.closeModal();\r\n this.$nextTick(() => {\r\n this.view.c.addOutput(name, type, desc, this.mousePosition);\r\n // reset fields\r\n this.$refs.outputType.resetChanges();\r\n $(this.$el).find('.output-name').val(\"\");\r\n $(this.$el).find('.output-description').val(\"\");\r\n });\r\n }\r\n else {\r\n swal('Please complete all fields', '', 'error');\r\n return;\r\n }\r\n break;\r\n\r\n case \"metanode\":\r\n var name = $(this.$el).find('.metanode-name').val();\r\n var desc = $(this.$el).find('.metanode-description').val();\r\n if( !name ) {\r\n swal('Please complete name field', '', 'error');\r\n return;\r\n }\r\n\r\n var json = this.metanodeJSON || {};\r\n json.description = desc;\r\n\r\n this.closeModal();\r\n this.$nextTick(() => {\r\n this.view.c.addNewMetabox(name, json, this.mousePosition);\r\n });\r\n default:\r\n }\r\n },\r\n\r\n searchModules: async function(e) {\r\n //var text = $(e.target).val();\r\n var text = this.searchText[this.selectedType];\r\n try {\r\n this.error = null;\r\n this.results[this.selectedType] = await this.view.e.search(text, this.selectedType);\r\n this.$forceUpdate();\r\n }\r\n catch(e) {\r\n this.error = e;\r\n swal('error searching packages', e.reason, \"error\");\r\n }\r\n },\r\n\r\n getSearchText: function() {\r\n return this.searchText[this.selectedType] || \"\";\r\n },\r\n\r\n setSelectedResult: function(packageName) {\r\n // first, find the selected result in the list\r\n var selectedPackage = null;\r\n _.each(this.getResults(), (r) => {\r\n if( r.name == packageName ) {\r\n selectedPackage = r;\r\n return false;\r\n }\r\n });\r\n\r\n if( !selectedPackage ) {\r\n throw \"Could not find package named \" + packageName;\r\n }\r\n\r\n this.selectedResult[this.selectedType] = selectedPackage;\r\n this.$forceUpdate();\r\n },\r\n\r\n getSelectedResult: function() {\r\n return this.selectedResult[this.selectedType];\r\n },\r\n\r\n getResults: function() {\r\n return this.results[this.selectedType] || null;\r\n },\r\n\r\n getNbResults: function() {\r\n var results = this.getResults();\r\n return results && results.length ? results.length: 0;\r\n },\r\n\r\n onMetaboxFileSelect: function(e) {\r\n var file = e.target.files[0];\r\n const reader = new FileReader()\r\n reader.onload = (e) => {\r\n this.metanodeJSON = JSON.parse(e.target.result);\r\n if( this.metanodeJSON.description ) {\r\n $(this.$el).find('.metanode-description').val(this.metanodeJSON.description);\r\n }\r\n }\r\n reader.readAsText(file)\r\n }\r\n }\r\n}\r\n\r\n</script>\r\n\r\n"]}, media: undefined });
64555
+ inject("data-v-2cca907e_0", { source: "\n.add-node-modal .modal-body[data-v-2cca907e] {\r\n height: 70vh;\n}\n.h100[data-v-2cca907e] {\r\n height: 100% !important;\r\n min-height: 100% !important;\n}\n.table-desc th[data-v-2cca907e],\r\n.table-desc td[data-v-2cca907e] {\r\n margin-right: 10px;\n}\n#add-node-modal .modal-dialog[data-v-2cca907e] {\r\n min-width: calc(100% - 40px) !important;\r\n height: calc(100% - 40px);\r\n margin: 20px;\r\n padding: 0;\n}\n#add-node-modal .modal-content[data-v-2cca907e] {\r\n height: auto;\r\n min-height: 100%;\r\n border-radius: 0;\n}\n.nav-item[data-v-2cca907e] {\r\n margin-left: 15px;\r\n margin-right: 15px;\n}\n.nav-link[data-v-2cca907e] {\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-bottom: 4px;\r\n padding-top: 4px;\r\n vertical-align: middle;\r\n position: relative;\r\n user-select: none;\n}\n.nav-link.active[data-v-2cca907e] {\r\n top: 0px;\r\n border-top-left-radius: 5px;\r\n border-bottom-left-radius: 5px;\n}\n.nav-link > span[data-v-2cca907e] {\r\n padding-left: 10px;\r\n padding-right: 10px;\n}\n.nav-link.active > span[data-v-2cca907e] {\r\n color: black;\n}\n.input-search[data-v-2cca907e] {\r\n display: none;\r\n width: 1px;\r\n height: 24px;\r\n box-shadow: none !important;\r\n border-color: rgba(0, 0, 0, 0.3) !important;\n}\n.nav-link.active .input-search[data-v-2cca907e] {\r\n display: inline-block;\r\n border-top-left-radius: 0px;\r\n border-bottom-left-radius: 0px;\r\n transition: width 1s;\r\n width: 200px;\n}\n.nav-compute > a.active > input[data-v-2cca907e] {\r\n background-color: rgba(0, 0, 0, 0.3) !important;\n}\n.nav-compute > a.active[data-v-2cca907e],\r\n.nav-compute > a.active > input[data-v-2cca907e] {\r\n background-color: rgba(0, 0, 0, 0.3) !important;\r\n color: rgba(255, 255, 255, 0.5);\n}\n.nav-compute > a.active > .input-search[data-v-2cca907e]::placeholder {\r\n color: rgba(255, 255, 255, 0.5);\n}\n.nav-uis > a.active[data-v-2cca907e],\r\n.nav-uis > a.active > input[data-v-2cca907e] {\r\n background-color: #bff2ca !important;\n}\n.nav-inputs > a.active[data-v-2cca907e] {\r\n background-color: #f5d76e !important;\n}\n.nav-compute > a.active > input[data-v-2cca907e] {\r\n background-color: rgba(0, 0, 0, 0.8);\n}\n.nav-outputs > a.active[data-v-2cca907e],\r\n.nav-outputs > a.active > input[data-v-2cca907e] {\r\n background-color: #ffb3a7 !important;\n}\n.message-container[data-v-2cca907e] {\r\n position: relative;\r\n width: 100%;\r\n height: 100%;\n}\n.message[data-v-2cca907e] {\r\n position: absolute;\r\n top: 50%;\r\n transform: translateY(-80%);\r\n left: 0;\r\n right: 0;\r\n opacity: 0.6;\r\n text-align: center;\n}\n.tab-content[data-v-2cca907e],\r\n.tab-pane[data-v-2cca907e] {\r\n width: 100%;\r\n height: 100%;\n}\nlabel[data-v-2cca907e] {\r\n font-size: 20px;\r\n margin-top: 20px;\n}\nfieldset[data-v-2cca907e] {\r\n border: 1px solid rgba(0, 0, 0, 0.1);\r\n margin: 10px;\r\n padding: 20px;\r\n min-width: 600px;\n}\r\n", map: {"version":3,"sources":["C:\\Users\\maxim\\Projects\\dualbox\\editor\\js\\src\\v\\templates\\addNode.vue"],"names":[],"mappings":";AACA;IACA,YAAA;AACA;AAEA;IACA,uBAAA;IACA,2BAAA;AACA;AAEA;;IAEA,kBAAA;AACA;AAEA;IACA,uCAAA;IACA,yBAAA;IACA,YAAA;IACA,UAAA;AACA;AAEA;IACA,YAAA;IACA,gBAAA;IACA,gBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,gBAAA;IACA,sBAAA;IACA,kBAAA;IACA,iBAAA;AACA;AAEA;IACA,QAAA;IACA,2BAAA;IACA,8BAAA;AACA;AAEA;IACA,kBAAA;IACA,mBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,aAAA;IACA,UAAA;IACA,YAAA;IACA,2BAAA;IACA,2CAAA;AACA;AAEA;IACA,qBAAA;IACA,2BAAA;IACA,8BAAA;IACA,oBAAA;IACA,YAAA;AACA;AACA;IACA,+CAAA;AACA;AAEA;;IAEA,+CAAA;IACA,+BAAA;AACA;AAEA;IACA,+BAAA;AACA;AAEA;;IAEA,oCAAA;AACA;AAEA;IACA,oCAAA;AACA;AAEA;IACA,oCAAA;AACA;AAEA;;IAEA,oCAAA;AACA;AAEA;IACA,kBAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,2BAAA;IACA,OAAA;IACA,QAAA;IACA,YAAA;IACA,kBAAA;AACA;AAEA;;IAEA,WAAA;IACA,YAAA;AACA;AAEA;IACA,eAAA;IACA,gBAAA;AACA;AAEA;IACA,oCAAA;IACA,YAAA;IACA,aAAA;IACA,gBAAA;AACA","file":"addNode.vue","sourcesContent":["<style scoped>\r\n.add-node-modal .modal-body {\r\n height: 70vh;\r\n}\r\n\r\n.h100 {\r\n height: 100% !important;\r\n min-height: 100% !important;\r\n}\r\n\r\n.table-desc th,\r\n.table-desc td {\r\n margin-right: 10px;\r\n}\r\n\r\n#add-node-modal .modal-dialog {\r\n min-width: calc(100% - 40px) !important;\r\n height: calc(100% - 40px);\r\n margin: 20px;\r\n padding: 0;\r\n}\r\n\r\n#add-node-modal .modal-content {\r\n height: auto;\r\n min-height: 100%;\r\n border-radius: 0;\r\n}\r\n\r\n.nav-item {\r\n margin-left: 15px;\r\n margin-right: 15px;\r\n}\r\n\r\n.nav-link {\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-bottom: 4px;\r\n padding-top: 4px;\r\n vertical-align: middle;\r\n position: relative;\r\n user-select: none;\r\n}\r\n\r\n.nav-link.active {\r\n top: 0px;\r\n border-top-left-radius: 5px;\r\n border-bottom-left-radius: 5px;\r\n}\r\n\r\n.nav-link > span {\r\n padding-left: 10px;\r\n padding-right: 10px;\r\n}\r\n\r\n.nav-link.active > span {\r\n color: black;\r\n}\r\n\r\n.input-search {\r\n display: none;\r\n width: 1px;\r\n height: 24px;\r\n box-shadow: none !important;\r\n border-color: rgba(0, 0, 0, 0.3) !important;\r\n}\r\n\r\n.nav-link.active .input-search {\r\n display: inline-block;\r\n border-top-left-radius: 0px;\r\n border-bottom-left-radius: 0px;\r\n transition: width 1s;\r\n width: 200px;\r\n}\r\n.nav-compute > a.active > input {\r\n background-color: rgba(0, 0, 0, 0.3) !important;\r\n}\r\n\r\n.nav-compute > a.active,\r\n.nav-compute > a.active > input {\r\n background-color: rgba(0, 0, 0, 0.3) !important;\r\n color: rgba(255, 255, 255, 0.5);\r\n}\r\n\r\n.nav-compute > a.active > .input-search::placeholder {\r\n color: rgba(255, 255, 255, 0.5);\r\n}\r\n\r\n.nav-uis > a.active,\r\n.nav-uis > a.active > input {\r\n background-color: #bff2ca !important;\r\n}\r\n\r\n.nav-inputs > a.active {\r\n background-color: #f5d76e !important;\r\n}\r\n\r\n.nav-compute > a.active > input {\r\n background-color: rgba(0, 0, 0, 0.8);\r\n}\r\n\r\n.nav-outputs > a.active,\r\n.nav-outputs > a.active > input {\r\n background-color: #ffb3a7 !important;\r\n}\r\n\r\n.message-container {\r\n position: relative;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.message {\r\n position: absolute;\r\n top: 50%;\r\n transform: translateY(-80%);\r\n left: 0;\r\n right: 0;\r\n opacity: 0.6;\r\n text-align: center;\r\n}\r\n\r\n.tab-content,\r\n.tab-pane {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\nlabel {\r\n font-size: 20px;\r\n margin-top: 20px;\r\n}\r\n\r\nfieldset {\r\n border: 1px solid rgba(0, 0, 0, 0.1);\r\n margin: 10px;\r\n padding: 20px;\r\n min-width: 600px;\r\n}\r\n</style>\r\n\r\n<template>\r\n <div class=\"modal fade add-node-modal\" :class=\"{ 'hide' : !display }\" id=\"add-node-modal\" tabindex=\"-1\" role=\"dialog\">\r\n <div class=\"modal-dialog\" role=\"document\">\r\n <div class=\"modal-content h100\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title\">Add Box</h5>\r\n <ul class=\"nav nav-pills mr-auto ml-2\">\r\n <li class=\"nav-item nav-compute\">\r\n <a class=\"nav-link active\" href=\"#add-module-or-ui\" data-toggle=\"pill\" @click=\"selectType('module')\" draggable=\"false\">\r\n <span>Compute</span>\r\n <input class=\"form-control input-sm input-search search-modules\" type=\"text\" placeholder=\"Search modules...\" id=\"search-modules\" v-model=\"searchText['module']\" @input=\"searchModules\" autofocus />\r\n </a>\r\n </li>\r\n <li class=\"nav-item nav-uis\">\r\n <a class=\"nav-link\" href=\"#add-module-or-ui\" data-toggle=\"pill\" @click=\"selectType('ui')\" draggable=\"false\">\r\n <span>UI</span>\r\n <input class=\"form-control input-sm input-search search-ui\" type=\"text\" placeholder=\"Search UIs...\" id=\"search-uis\" @input=\"searchModules\" v-model=\"searchText['ui']\" autofocus />\r\n </a>\r\n </li>\r\n <li class=\"nav-item nav-inputs\" @click=\"selectType('input')\">\r\n <a class=\"nav-link\" href=\"#add-input\" data-toggle=\"pill\" draggable=\"false\"><span>Input</span></a>\r\n </li>\r\n <li class=\"nav-item nav-outputs\" @click=\"selectType('output')\">\r\n <a class=\"nav-link\" href=\"#add-output\" data-toggle=\"pill\" draggable=\"false\"><span>Output</span></a>\r\n </li>\r\n <li class=\"nav-item nav-outputs\" @click=\"selectType('metanode')\">\r\n <a class=\"nav-link\" href=\"#add-metanode\" data-toggle=\"pill\" draggable=\"false\"><span>Metabox</span></a>\r\n </li>\r\n </ul>\r\n\r\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div class=\"container-fluid h100\">\r\n\r\n <div class=\"tab-content\">\r\n <div class=\"tab-pane active\" id=\"add-module-or-ui\" role=\"tabpanel\" aria-labelledby=\"add-module-or-ui-tab\">\r\n <div class=\"row h100\">\r\n <div v-if=\"getSearchText().length == 0\" class=\"message-container\">\r\n <p class=\"message\"><i class=\"fas fa-search\"></i> Type something to search through the Dualbox library.</p>\r\n </div>\r\n <div v-else-if=\"getNbResults() == 0\">\r\n <p class=\"message\"><i class=\"fas fa-search\"></i> No results.</p>\r\n </div>\r\n <template v-else>\r\n <div class=\"col-md-4 h100\" style=\"padding-left: 0; padding-right: 0; overflow-y: auto; overflow-x: hidden;\">\r\n <search-results ref=\"searchResults\" :results=\"getResults()\" :err=\"error\" @resultSelected=\"setSelectedResult\"></search-results>\r\n </div>\r\n <div class=\"col-md-8 h100\" style=\"padding-left: 15px; padding-right: 0;\">\r\n <display-result ref=\"displayResults\" v-if=\"getSelectedResult()\" :result=\"getSelectedResult()\"></display-result>\r\n <div v-else class=\"message-container\">\r\n <p class=\"message\">Select a result to display</p>\r\n </div>\r\n </div>\r\n </template>\r\n </div>\r\n </div>\r\n <div class=\"tab-pane\" id=\"add-input\" role=\"tabpanel\" aria-labelledby=\"add-input-tab\">\r\n <div class=\"row\">\r\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\r\n <h2 class=\"mt-2\">Add a new input</h2>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"input-name\">Input name:</label>\r\n <input type=\"text\" class=\"form-control input-name\" id=\"input-name\" placeholder=\"Enter name...\" autofocus required>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"input-name\">Input type:</label>\r\n <input style=\"display: none;\" required />\r\n <edit-type ref=\"inputType\" :type=\"inputType\" :displayOKButton=\"false\"></edit-type>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"input-description\">Input description:</label>\r\n <textarea class=\"input-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\r\n </textarea>\r\n </div>\r\n </fieldset>\r\n </div>\r\n </div>\r\n <div class=\"tab-pane\" id=\"add-output\" role=\"tabpanel\" aria-labelledby=\"add-output-tab\">\r\n <div class=\"row\">\r\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\r\n <h2 class=\"mt-2\">Add a new output</h2>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"output-name\">Output name:</label>\r\n <input type=\"text\" class=\"form-control output-name\" id=\"output-name\" placeholder=\"Enter name...\" autofocus required>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"output-name\">Output type:</label>\r\n <input style=\"display: none;\" required />\r\n <edit-type ref=\"outputType\" :type=\"outputType\" :displayOKButton=\"false\"></edit-type>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"output-description\">Output description:</label>\r\n <textarea class=\"output-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\r\n </textarea>\r\n </div>\r\n </fieldset>\r\n </div>\r\n </div>\r\n <div class=\"tab-pane\" id=\"add-metanode\" role=\"tabpanel\" aria-labelledby=\"add-metanode-tab\">\r\n <div class=\"row\">\r\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\r\n <h2 class=\"mt-2\">Add a new Metabox\r\n <!--<button class=\"btn btn-outline-secondary float-right\" @click=\"importMetabox\"><i class=\"fas fa-upload\"></i></button>-->\r\n </h2>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"metanode-name\">Metabox name:</label>\r\n <input type=\"text\" class=\"form-control metanode-name\" id=\"metanode-name\" placeholder=\"Enter name...\" autofocus required>\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"metanode-def\">Metabox definition (optional):</label>\r\n <input type=\"file\" class=\"form-control-file\" id=\"metanode-def\" @change=\"onMetaboxFileSelect\">\r\n </div>\r\n\r\n <div class=\"form-group\">\r\n <label for=\"metanode-description\">Metabox description:</label>\r\n <textarea class=\"metanode-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\r\n </textarea>\r\n </div>\r\n </fieldset>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\r\n <button type=\"button\" class=\"btn btn-primary add-node-btn\" @click=\"addSelectedNode\">Add node</button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport _ from \"lodash-es\";\r\nimport swal from \"sweetalert2\";\r\nimport SearchResultsVue from \"./searchResults.vue\";\r\nimport DisplayResultVue from \"./displayResult.vue\";\r\nimport EditTypeVue from \"./editType.vue\";\r\n\r\nexport default {\r\n props: [\r\n \"display\", // original state (true = show, false=hide) of the modal\r\n \"mousePosition\" // mouse position when this panel was opened\r\n ],\r\n components: {\r\n \"search-results\": SearchResultsVue,\r\n \"display-result\": DisplayResultVue,\r\n \"edit-type\": EditTypeVue\r\n },\r\n data: function() {\r\n return {\r\n error: null,\r\n\r\n searchText: {}, // the search text, indexed by selectedType\r\n results: {}, // dictionary of arrays, indexed by selectedType\r\n selectedResult: {}, // dictionary of string, indexed by selectedType\r\n selectedType: \"module\",\r\n inputType: \"*\",\r\n outputType: \"*\"\r\n };\r\n },\r\n created: function() {\r\n this.view = window.dualboxEditor.v;\r\n },\r\n updated: function() {\r\n console.log(\"AddNode updated !\");\r\n this.updateVisibility();\r\n this.setSearchFocus();\r\n\r\n if (!this.display) {\r\n // make sure the modal disappeared\r\n $(this.$el).modal(\"hide\");\r\n $(\"body\").removeClass(\"modal-open\");\r\n $(\".modal-backdrop\").remove();\r\n }\r\n },\r\n mounted: function() {\r\n var self = this;\r\n this.updateVisibility(); // to init our modal\r\n\r\n $(this.$el).on(\"shown.bs.modal\", () => {\r\n this.setSearchFocus();\r\n });\r\n $(this.$el).on(\"hide.bs.modal\", () => {\r\n self.$emit(\"closed\");\r\n });\r\n\r\n $(this.$el)\r\n .find('[data-toggle=\"pill\"]')\r\n .on(\"shown.bs.tab\", e => {\r\n this.setSearchFocus();\r\n var selectedResult = this.getSelectedResult();\r\n if (selectedResult) {\r\n this.$refs.searchResults.selected = selectedResult.name;\r\n }\r\n });\r\n },\r\n methods: {\r\n updateVisibility: function() {\r\n if (this.display) {\r\n $(this.$el).modal(\"show\");\r\n } else {\r\n $(this.$el).modal(\"hide\");\r\n }\r\n },\r\n\r\n closeModal: function() {\r\n // don't mutate prop directly, mute the parent\r\n // this.display = false;\r\n\r\n return new Promise((resolve, reject) => {\r\n this.$emit(\"closed\");\r\n\r\n let forceCloseModal = () => {\r\n if (!this.display) {\r\n resolve();\r\n } else {\r\n this.$emit(\"closed\");\r\n setTimeout(forceCloseModal, 100);\r\n }\r\n };\r\n\r\n this.$nextTick(forceCloseModal);\r\n });\r\n },\r\n\r\n setSearchFocus: function() {\r\n $(this.$el)\r\n .find(\".nav-link.active\")\r\n .find(\"input\")\r\n .focus();\r\n },\r\n\r\n selectType(t) {\r\n let searchText = this.searchText[this.selectedType];\r\n this.selectedType = t;\r\n this.searchText[t] = searchText;\r\n },\r\n\r\n addSelectedNode: async function(e) {\r\n switch (this.selectedType) {\r\n case \"module\":\r\n case \"ui\":\r\n var selectedNode = $(\".node-result.selected\")[0];\r\n if (selectedNode) {\r\n await this.closeModal();\r\n // add node to the controller\r\n var packageName = $(selectedNode).data(\"package\");\r\n this.view.c.addNewBox(packageName, this.mousePosition);\r\n } else {\r\n swal(\"Please select a node\", \"\", \"error\");\r\n return;\r\n }\r\n break;\r\n\r\n case \"input\":\r\n var type = this.$refs.inputType.get();\r\n var name = $(this.$el)\r\n .find(\".input-name\")\r\n .val();\r\n var desc = $(this.$el)\r\n .find(\".input-description\")\r\n .val();\r\n if (type !== undefined && name) {\r\n await this.closeModal();\r\n this.view.c.addInput(\r\n name,\r\n type,\r\n desc,\r\n this.mousePosition\r\n );\r\n // reset fields\r\n this.$refs.inputType.resetChanges();\r\n $(this.$el)\r\n .find(\".input-name\")\r\n .val(\"\");\r\n $(this.$el)\r\n .find(\".input-description\")\r\n .val(\"\");\r\n } else {\r\n swal(\"Please complete all fields\", \"\", \"error\");\r\n return;\r\n }\r\n break;\r\n\r\n case \"output\":\r\n var name = $(this.$el)\r\n .find(\".output-name\")\r\n .val();\r\n var type = this.$refs.outputType.get();\r\n var desc = $(this.$el)\r\n .find(\".output-description\")\r\n .val();\r\n if (type !== undefined && name) {\r\n await this.closeModal();\r\n this.view.c.addOutput(\r\n name,\r\n type,\r\n desc,\r\n this.mousePosition\r\n );\r\n // reset fields\r\n this.$refs.outputType.resetChanges();\r\n $(this.$el)\r\n .find(\".output-name\")\r\n .val(\"\");\r\n $(this.$el)\r\n .find(\".output-description\")\r\n .val(\"\");\r\n } else {\r\n swal(\"Please complete all fields\", \"\", \"error\");\r\n return;\r\n }\r\n break;\r\n\r\n case \"metanode\":\r\n var name = $(this.$el)\r\n .find(\".metanode-name\")\r\n .val();\r\n var desc = $(this.$el)\r\n .find(\".metanode-description\")\r\n .val();\r\n if (!name) {\r\n swal(\"Please complete name field\", \"\", \"error\");\r\n return;\r\n }\r\n\r\n var json = this.metanodeJSON || {};\r\n json.description = desc;\r\n\r\n await this.closeModal();\r\n this.view.c.addNewMetabox(name, json, this.mousePosition);\r\n default:\r\n }\r\n },\r\n\r\n searchModules: async function(e) {\r\n //var text = $(e.target).val();\r\n var text = this.searchText[this.selectedType];\r\n try {\r\n this.error = null;\r\n this.results[this.selectedType] = await this.view.e.search(\r\n text,\r\n this.selectedType\r\n );\r\n this.$forceUpdate();\r\n } catch (e) {\r\n this.error = e;\r\n swal(\"error searching packages\", e.reason, \"error\");\r\n }\r\n },\r\n\r\n getSearchText: function() {\r\n return this.searchText[this.selectedType] || \"\";\r\n },\r\n\r\n setSelectedResult: function(packageName) {\r\n // first, find the selected result in the list\r\n var selectedPackage = null;\r\n _.each(this.getResults(), r => {\r\n if (r.name == packageName) {\r\n selectedPackage = r;\r\n return false;\r\n }\r\n });\r\n\r\n if (!selectedPackage) {\r\n throw \"Could not find package named \" + packageName;\r\n }\r\n\r\n this.selectedResult[this.selectedType] = selectedPackage;\r\n this.$forceUpdate();\r\n },\r\n\r\n getSelectedResult: function() {\r\n return this.selectedResult[this.selectedType];\r\n },\r\n\r\n getResults: function() {\r\n return this.results[this.selectedType] || null;\r\n },\r\n\r\n getNbResults: function() {\r\n var results = this.getResults();\r\n return results && results.length ? results.length : 0;\r\n },\r\n\r\n onMetaboxFileSelect: function(e) {\r\n var file = e.target.files[0];\r\n const reader = new FileReader();\r\n reader.onload = e => {\r\n this.metanodeJSON = JSON.parse(e.target.result);\r\n if (this.metanodeJSON.description) {\r\n $(this.$el)\r\n .find(\".metanode-description\")\r\n .val(this.metanodeJSON.description);\r\n }\r\n };\r\n reader.readAsText(file);\r\n }\r\n }\r\n};\r\n</script>\r\n\r\n"]}, media: undefined });
64457
64556
 
64458
64557
  };
64459
64558
  /* scoped */
64460
- const __vue_scope_id__$5 = "data-v-1749da54";
64559
+ const __vue_scope_id__$5 = "data-v-2cca907e";
64461
64560
  /* module identifier */
64462
64561
  const __vue_module_identifier__$5 = undefined;
64463
64562
  /* functional template */
@@ -64905,6 +65004,8 @@ catch(e) {
64905
65004
 
64906
65005
  //
64907
65006
 
65007
+ var JSONEditorMode = "tree";
65008
+
64908
65009
  String.prototype.hashCode = function() {
64909
65010
  var hash = 0,
64910
65011
  i,
@@ -65016,8 +65117,12 @@ var script$8 = {
65016
65117
  this.editor = new _import$1(
65017
65118
  $(this.$el).find(".field-editor")[0],
65018
65119
  {
65120
+ mode: JSONEditorMode,
65019
65121
  modes: ["tree", "code", "text"],
65020
- onChange: this.debouncedJsonEmit
65122
+ onChange: this.debouncedJsonEmit,
65123
+ onModeChange: (newMode) => {
65124
+ JSONEditorMode = newMode;
65125
+ }
65021
65126
  }
65022
65127
  );
65023
65128
  }
@@ -65388,9 +65493,9 @@ var __vue_render__$8 = function() {
65388
65493
  ? [
65389
65494
  _vm.dataType === "string"
65390
65495
  ? [
65391
- _c("input", {
65496
+ _c("textarea", {
65392
65497
  staticClass: "edit-value-input",
65393
- attrs: { type: "text" },
65498
+ attrs: { rows: "3", type: "text" },
65394
65499
  domProps: { value: _vm.v },
65395
65500
  on: {
65396
65501
  keyup: [
@@ -65537,7 +65642,8 @@ var __vue_render__$8 = function() {
65537
65642
  padding: "0",
65538
65643
  "background-color": "white",
65539
65644
  "overflow-y": "auto",
65540
- "border-right": "1px solid rgba(0, 0, 0, 0.125)"
65645
+ "border-right": "1px solid rgba(0, 0, 0, 0.125)",
65646
+ "max-height": "500px"
65541
65647
  }
65542
65648
  },
65543
65649
  [
@@ -65551,7 +65657,10 @@ var __vue_render__$8 = function() {
65551
65657
  staticClass:
65552
65658
  "list-group-item list-group-item-action",
65553
65659
  class: { active: _vm.isSelectedIndex(index) },
65554
- staticStyle: { "text-align": "center" },
65660
+ staticStyle: {
65661
+ "text-align": "center",
65662
+ padding: "12px"
65663
+ },
65555
65664
  attrs: {
65556
65665
  draggable: _vm.isArrayType(),
65557
65666
  "data-key": index,
@@ -65686,11 +65795,11 @@ __vue_render__$8._withStripped = true;
65686
65795
  /* style */
65687
65796
  const __vue_inject_styles__$8 = function (inject) {
65688
65797
  if (!inject) return
65689
- inject("data-v-bcbe186e_0", { source: "\n.template-value-container[data-v-bcbe186e],\r\n.field-editor[data-v-bcbe186e] {\r\n margin-bottom: 10px;\n}\n.template-value-message[data-v-bcbe186e] {\r\n text-align: center;\r\n margin-top: 30px;\r\n margin-bottom: 30px;\r\n width: 100%;\r\n opacity: 0.5;\n}\n.dragOver[data-v-bcbe186e] {\r\n border-bottom: 2px solid blue;\n}\r\n", map: {"version":3,"sources":["C:\\Users\\maxim\\Projects\\dualbox\\editor\\js\\src\\v\\templates\\editValue.vue"],"names":[],"mappings":";AACA;;IAEA,mBAAA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,6BAAA;AACA","file":"editValue.vue","sourcesContent":["<style scoped>\r\n.template-value-container,\r\n.field-editor {\r\n margin-bottom: 10px;\r\n}\r\n\r\n.template-value-message {\r\n text-align: center;\r\n margin-top: 30px;\r\n margin-bottom: 30px;\r\n width: 100%;\r\n opacity: 0.5;\r\n}\r\n\r\n.dragOver {\r\n border-bottom: 2px solid blue;\r\n}\r\n</style>\r\n\r\n<template>\r\n <div class=\"w-100\">\r\n <p style=\"display: none;\">{{cIndex}}</p>\r\n <template v-if=\"isBasicDataType()\">\r\n <template v-if=\"dataType === 'string'\">\r\n <input class=\"edit-value-input\" type=\"text\" @keyup.enter=\"setStringValue\" @keyup.esc=\"setStringValue\" @blur=\"setStringValueFromBlur\" :value=\"v\" @focus=\"$event.target.select()\" />\r\n </template>\r\n\r\n <template v-else-if=\"dataType === 'boolean'\">\r\n <select class=\"edit-value-input\" @change=\"setBoolValue\">\r\n <option value=\"true\" :selected=\"v == true\">True</option>\r\n <option value=\"false\" :selected=\"v == false\">False</option>\r\n </select>\r\n </template>\r\n\r\n <template v-else-if=\"dataType === 'number'\">\r\n <input class=\"edit-value-input\" type=\"number\" @keyup.enter=\"setNumberValue\" @blur=\"setNumberValueFromBlur\" :value=\"v\" @focus=\"$event.target.select()\" style=\"width: 40px;\" />\r\n </template>\r\n </template>\r\n\r\n <template v-else>\r\n <!-- we already are in a modal, don't instanciate another one -->\r\n <template v-if=\"isTemplateType()\">\r\n <div class=\"container template-value-container\" style=\"border: 1px solid rgba(0, 0, 0, 0.125);\">\r\n <div v-if=\"isArrayType()\" class=\"row\" style=\"background-color: rgba(0,0,0,.125);\">Array Editor</div>\r\n <div v-else-if=\"isMapType()\" class=\"row\" style=\"background-color: rgba(0,0,0,.125);\">Map Editor</div>\r\n <div class=\"row\" style=\"1px solid rgba(0,0,0,.125);\">\r\n <div class=\"col list-group-flush\" :class=\"{ 'col-1' : isArrayType(), 'col-2' : isMapType()}\" style=\"padding: 0; background-color: white; overflow-y: auto; border-right: 1px solid rgba(0, 0, 0, 0.125);\">\r\n <button v-for=\"index in deserializedValue.keys()\" :draggable=\"isArrayType()\" @dragstart=\"arrayIndexDragStart(index, $event)\" @dragover.prevent @dragenter=\"arrayIndexDragEnter\" @dragleave=\"arrayIndexDragLeave\" @drop=\"arrayIndexDrop(index, $event)\" :key=\"index\" :data-key=\"index\" type=\"button\" class=\"list-group-item list-group-item-action\" :class=\"{ active: isSelectedIndex(index) }\" style=\"text-align: center;\" @click=\"selectIndex(index)\">{{index}}</button>\r\n <button type=\"button\" @click=\"addItem\" class=\"list-group-item list-group-item-action add-item\" style=\"text-align: center;\"><i class=\"fas fa-plus-circle\"></i></button>\r\n </div>\r\n <div class=\"col\" style=\"padding: 10px\">\r\n <edit-value v-if=\"selectedIndex !== undefined && selectedIndex !== null\" :key=\"selectedIndex\" ref=\"subValueEditor\" :cIndex=\"selectedIndex\" :type=\"embeddedType\" :v=\"getElement(selectedIndex)\" @edited=\"onSubValueEdited\"></edit-value>\r\n <p v-else class=\"template-value-message\">Select an element to edit.</p>\r\n </div>\r\n </div>\r\n </div>\r\n </template>\r\n <template v-else>\r\n <span v-if=\"isNull()\" @click=\"setEmptyJsonValue\" class=\"d-inline-block data-display data-value\" style=\"word-break: break-all;\" title=\"set value here\" data-toggle=\"tooltip\" data-trigger=\"hover\" data-placement=\"top\">\r\n <i class=\"fas fa-pen\"></i> null\r\n </span>\r\n <div v-else class=\"field-editor\" :data-value=\"hash()\"></div>\r\n </template>\r\n </template>\r\n\r\n <!-- set null and delete buttons -->\r\n <div class=\"d-inline-block float-right\">\r\n <button class=\"btn btn-secondary btn-sm btn-xs\" title=\"set null\" @click=\"setNullValue\">null</button>\r\n <button class=\"btn btn-danger btn-sm btn-xs\" title=\"delete value\" @click=\"deleteValue\" style=\"margin-left: 0px;\"><i class=\"fas fa-trash\"></i></button>\r\n </div>\r\n </div>\r\n\r\n</template>\r\n\r\n<script>\r\nimport _ from \"lodash-es\";\r\nimport swal from \"sweetalert2\";\r\nimport JSONEditor from \"@dualbox/dualbox-lib-jsoneditor\";\r\n\r\nString.prototype.hashCode = function() {\r\n var hash = 0,\r\n i,\r\n chr;\r\n if (this.length === 0) return hash;\r\n for (i = 0; i < this.length; i++) {\r\n chr = this.charCodeAt(i);\r\n hash = (hash << 5) - hash + chr;\r\n hash |= 0; // Convert to 32bit integer\r\n }\r\n return hash;\r\n};\r\n\r\nexport default {\r\n name: \"edit-value\",\r\n props: [\r\n // required\r\n \"v\", // the value\r\n \"type\", // the dualbox type of the value\r\n\r\n // specific properties (for recursivity)\r\n \"cIndex\" // index for reference when in an array\r\n ],\r\n data: function() {\r\n return {\r\n dataType: null, // the real javascript dataType of this.v\r\n deserializedValue: null,\r\n\r\n // if type is a collection (dataType==\"map\" or dataType==\"array\")\r\n embeddedType: null, // the embedded type of this templated collection\r\n selectedIndex: null // the current index of the element we are editing\r\n };\r\n },\r\n created: function() {\r\n this.view = window.dualboxEditor.v;\r\n this.editor = null;\r\n this.edited = false;\r\n this.initData();\r\n this.saveOnDestroy = true;\r\n\r\n // create a debounced json emit\r\n this.jsonEmit = () => {\r\n try {\r\n var json = this.editor.get();\r\n this.autochange = true;\r\n this.emit(json);\r\n } catch (e) {}\r\n };\r\n this.debouncedJsonEmit = _.debounce(this.jsonEmit, 5000); // 5 second save debounce\r\n this.debouncedSetStringValue = _.debounce(this.setStringValue, 250); // thoses are to be used with the blur event, so it's cancellable if\r\n this.debouncedSetNumberValue = _.debounce(this.setNumberValue, 250); // the user clicked on \"null\" or \"remove\" instead or changing the string/num value\r\n },\r\n mounted: function() {\r\n var self = this;\r\n\r\n this.updateEditor();\r\n\r\n $(this.$el)\r\n .find(\".edit-value-input\")\r\n .focus(); // focus on the edit element\r\n },\r\n beforeUpdate: function() {\r\n this.updateData();\r\n },\r\n updated: function() {\r\n if (this.autochange) {\r\n // change triggered by ourself, skip\r\n this.autochange = false;\r\n } else {\r\n this.updateEditor();\r\n }\r\n },\r\n beforeDestroy: function() {\r\n if (this.saveOnDestroy) {\r\n // if some debounced json edition was going on, do it now\r\n this.debouncedJsonEmit.flush();\r\n\r\n // make sure the value was set\r\n if (!this.emitted) {\r\n if (this.isBasicDataType()) {\r\n var elt = $(this.$el).find(\".edit-value-input\");\r\n var val = elt.val();\r\n this.$emit(\"edited\", val);\r\n } else {\r\n this.saveChanges();\r\n }\r\n }\r\n }\r\n },\r\n methods: {\r\n hash: function() {\r\n var str = new String(this.v).toString();\r\n return str\r\n .split(\"\")\r\n .reduce(\r\n (prevHash, currVal) =>\r\n ((prevHash << 5) - prevHash + currVal.charCodeAt(0)) |\r\n 0,\r\n 0\r\n );\r\n },\r\n\r\n updateEditor: function() {\r\n if (this.dataType === \"object\" && !this.isNull()) {\r\n if (\r\n !this.editor &&\r\n $(this.$el).find(\".field-editor\")[0] !== undefined\r\n ) {\r\n // bind the json editor\r\n this.editor = new JSONEditor(\r\n $(this.$el).find(\".field-editor\")[0],\r\n {\r\n modes: [\"tree\", \"code\", \"text\"],\r\n onChange: this.debouncedJsonEmit\r\n }\r\n );\r\n }\r\n\r\n if (this.editor) {\r\n this.editor.set(this.v || {});\r\n }\r\n }\r\n },\r\n resolveDatatype() {\r\n // determine datatype of the value\r\n var resolvedType = this.type\r\n ? this.type.toLowerCase()\r\n : typeof this.v;\r\n\r\n // If \"*\", resolve the type by detecting it dynamically from value\r\n if (resolvedType.indexOf(\"*\") !== -1) {\r\n resolvedType = window.DualBox.Type.detectType(\r\n this.v\r\n ).toLowerCase();\r\n }\r\n\r\n // Check if we have a template type. If so, determine current index and embedded type\r\n var templateType = null;\r\n if (resolvedType.startsWith(\"array\")) {\r\n templateType = \"array\";\r\n this.deserializedValue = _.clone(this.v || []);\r\n } else if (resolvedType.startsWith(\"map\")) {\r\n templateType = \"map\";\r\n this.deserializedValue = _.clone(\r\n window.DualBox.Type.deserialize(\r\n this.v || {\r\n metadata: {\r\n type:\r\n \"Map<String,\" +\r\n this.firstLetterUppercase(\r\n this.getEmbeddedType(resolvedType)\r\n ) +\r\n \">\"\r\n },\r\n data: {}\r\n }\r\n )\r\n );\r\n }\r\n\r\n if (templateType) {\r\n this.dataType = templateType;\r\n this.embeddedType = this.getEmbeddedType(resolvedType);\r\n if (this.selectedIndex == null) {\r\n var firstKey = this.deserializedValue.keys().next();\r\n if (firstKey && firstKey.value) {\r\n this.selectedIndex = firstKey.value;\r\n }\r\n }\r\n } else {\r\n this.dataType = resolvedType;\r\n }\r\n\r\n // Finally, transform to object if not a basic value\r\n if (\r\n [\"string\", \"number\", \"boolean\", \"array\", \"map\"].indexOf(\r\n this.dataType\r\n ) == -1\r\n ) {\r\n this.dataType = \"object\";\r\n }\r\n //console.log(`Type: ${this.type}, Datatype: ${this.dataType}, embeddedType: ${this.embeddedType}`);\r\n },\r\n\r\n initData: function() {\r\n this.v = this.v;\r\n this.resolveDatatype();\r\n this.selectNextIndex();\r\n },\r\n\r\n updateData: function() {\r\n this.resolveDatatype();\r\n },\r\n\r\n isBasicDataType() {\r\n return (\r\n this.dataType == \"string\" ||\r\n this.dataType == \"number\" ||\r\n this.dataType == \"boolean\"\r\n );\r\n },\r\n\r\n serialize(value) {\r\n if (this.isTemplateType()) {\r\n if (this.isArrayType()) {\r\n return value; // we store arrays as is\r\n } else if (this.isMapType()) {\r\n return window.DualBox.Type.serialize(value);\r\n }\r\n } else {\r\n return value;\r\n }\r\n },\r\n\r\n emit(val) {\r\n this.$emit(\"edited\", val, this.cIndex);\r\n this.emitted = true;\r\n },\r\n\r\n saveChanges: function() {\r\n this.$forceUpdate();\r\n\r\n if (this.isTemplateType()) {\r\n let value = _.clone(this.deserializedValue);\r\n this.emit(this.serialize(value));\r\n this.emitted = true;\r\n } else if (this.isObjectType()) {\r\n // emit the result to the parent Vue\r\n this.emit(this.editor.get());\r\n this.emitted = true;\r\n }\r\n },\r\n\r\n setStringValue: function(e) {\r\n var val = $(e.target).val();\r\n this.emit(val);\r\n this.emitted = true;\r\n },\r\n\r\n // debounce the function to allow user to click on null or remove\r\n setStringValueFromBlur: function(e) {\r\n this.debouncedSetStringValue(e);\r\n },\r\n\r\n setBoolValue: function(e) {\r\n var val = $(e.target).val() == \"true\";\r\n this.emit(val);\r\n this.emitted = true;\r\n },\r\n\r\n setNumberValue: function(e) {\r\n var val = parseFloat($(e.target).val());\r\n if (isNaN(val)) {\r\n this.deleteValue(e);\r\n } else {\r\n this.emit(val);\r\n this.emitted = true;\r\n }\r\n },\r\n\r\n // debounce the function to allow user to click on null or remove\r\n setNumberValueFromBlur: function(e) {\r\n this.debouncedSetNumberValue(e);\r\n },\r\n\r\n cancelBlurDebounced: function() {\r\n this.debouncedSetStringValue.cancel();\r\n this.debouncedSetNumberValue.cancel();\r\n },\r\n\r\n setNullValue: function() {\r\n this.cancelBlurDebounced(); // kill incoming debounced setStringFromBlur or setNumberFromBlur\r\n\r\n this.$forceUpdate();\r\n\r\n // emit the result to the parent Vue\r\n this.emit(null);\r\n },\r\n\r\n setEmptyJsonValue: function() {\r\n // TODO: check this.type and create an empty object of this type\r\n this.emit({});\r\n },\r\n\r\n selectNextIndex: function() {\r\n if (this.isArrayType()) {\r\n this.selectedIndex =\r\n this.deserializedValue.length > 0 ? 0 : null;\r\n } else if (this.isMapType()) {\r\n var keys = this.deserializedValue.keys();\r\n var next = keys.next();\r\n this.selectedIndex = next ? next.value : null;\r\n }\r\n },\r\n\r\n deleteValue: function(e) {\r\n this.cancelBlurDebounced(); // kill incoming debounced setStringFromBlur or setNumberFromBlur\r\n this.selectNextIndex();\r\n this.$forceUpdate();\r\n\r\n // emit the result to the parent Vue\r\n this.emit(undefined);\r\n this.emitted = true;\r\n },\r\n\r\n isArrayType: function() {\r\n return this.dataType == \"array\";\r\n },\r\n\r\n isMapType: function() {\r\n return this.dataType == \"map\";\r\n },\r\n\r\n isObjectType: function() {\r\n return this.dataType == \"object\";\r\n },\r\n\r\n isTemplateType: function() {\r\n return this.isArrayType() || this.isMapType();\r\n },\r\n\r\n isNull: function() {\r\n return this.v === null;\r\n },\r\n\r\n getEmbeddedType: function(type) {\r\n var start = type.indexOf(\"<\") + 1;\r\n var end = type.lastIndexOf(\">\");\r\n if (type.toLowerCase().startsWith(\"array\")) {\r\n return type\r\n .substr(start, end - start)\r\n .trim()\r\n .toLowerCase();\r\n } else if (type.toLowerCase().startsWith(\"map\")) {\r\n var sub = type.substr(start, end - start);\r\n return sub\r\n .substr(sub.indexOf(\",\") + 1)\r\n .trim()\r\n .toLowerCase();\r\n }\r\n },\r\n\r\n firstLetterUppercase: function(s) {\r\n return s.charAt(0).toUpperCase() + s.slice(1);\r\n },\r\n\r\n selectIndex: function(index) {\r\n if (this.selectedIndex !== index) {\r\n this.selectedIndex = index;\r\n this.$forceUpdate();\r\n }\r\n },\r\n\r\n isSelectedIndex: function(index) {\r\n return index == this.selectedIndex;\r\n },\r\n\r\n getElement: function(i) {\r\n if (Array.isArray(this.v)) {\r\n return this.deserializedValue[i];\r\n } else {\r\n return this.deserializedValue.get(i);\r\n }\r\n },\r\n\r\n onSubValueEdited: function(newValue, index) {\r\n console.log(\r\n `Edited at index ${index}: ${JSON.stringify(newValue)}`\r\n );\r\n if (this.isArrayType()) {\r\n if (newValue === undefined) {\r\n // we just remove this value\r\n this.deserializedValue.splice(index, 1);\r\n } else {\r\n this.deserializedValue[index] = newValue;\r\n }\r\n } else if (this.isMapType()) {\r\n if (newValue === undefined) {\r\n this.deserializedValue.delete(index);\r\n } else {\r\n this.deserializedValue.set(index, newValue);\r\n }\r\n }\r\n this.saveChanges();\r\n this.$forceUpdate();\r\n },\r\n\r\n addItem: function() {\r\n if (this.isArrayType()) {\r\n this.deserializedValue[this.deserializedValue.length] = null;\r\n this.selectedIndex = this.deserializedValue.length - 1;\r\n this.saveChanges();\r\n this.$forceUpdate();\r\n } else if (this.isMapType()) {\r\n this.swalFixBootstrapModal();\r\n swal({\r\n input: \"text\",\r\n title: \"Enter map key\"\r\n }).then(result => {\r\n this.swalRestoreBootstrapModal();\r\n if (result && result.value) {\r\n this.selectedIndex = result.value;\r\n this.deserializedValue.set(result.value, null);\r\n this.saveChanges();\r\n this.$forceUpdate();\r\n }\r\n });\r\n }\r\n },\r\n\r\n // call this before showing SweetAlert:\r\n swalFixBootstrapModal() {\r\n var modal = $(\"body\").find('.modal[tabindex=\"-1\"]');\r\n if (!modal) return;\r\n modal.removeAttr(\"tabindex\");\r\n modal.addClass(\"js-swal-fixed\");\r\n },\r\n\r\n // call this before hiding SweetAlert (inside done callback):\r\n swalRestoreBootstrapModal() {\r\n var modal = $(\"body\").find(\".modal.js-swal-fixed\");\r\n if (!modal) return;\r\n modal.attr(\"tabindex\", \"-1\");\r\n modal.removeClass(\"js-swal-fixed\");\r\n },\r\n\r\n arrayIndexDragStart(which, e) {\r\n if (this.isArrayType()) {\r\n this.dragging = which;\r\n }\r\n this.selectedIndex = to;\r\n this.$forceUpdate();\r\n },\r\n\r\n arrayIndexDrop(to, e) {\r\n if (this.isArrayType()) {\r\n $(e.target).removeClass(\"dragOver\");\r\n let from = this.dragging;\r\n\r\n if (from === this.selectedIndex) {\r\n // we will have to ignore next destroy\r\n this.$refs.subValueEditor.saveOnDestroy = false;\r\n }\r\n\r\n // remove from for our indices and insert it after \"to\"\r\n var elem = this.deserializedValue.splice(from, 1)[0];\r\n this.deserializedValue.splice(to, 0, elem);\r\n\r\n this.selectedIndex = to;\r\n this.saveChanges();\r\n this.$forceUpdate();\r\n }\r\n },\r\n\r\n arrayIndexDragEnter(e) {\r\n $(e.target).addClass(\"dragOver\");\r\n },\r\n\r\n arrayIndexDragLeave(e) {\r\n $(e.target).removeClass(\"dragOver\");\r\n }\r\n }\r\n};\r\n</script>\r\n"]}, media: undefined });
65798
+ inject("data-v-d7e27fa2_0", { source: "\n.template-value-container[data-v-d7e27fa2],\r\n.field-editor[data-v-d7e27fa2] {\r\n margin-bottom: 10px;\n}\n.template-value-message[data-v-d7e27fa2] {\r\n text-align: center;\r\n margin-top: 30px;\r\n margin-bottom: 30px;\r\n width: 100%;\r\n opacity: 0.5;\n}\n.dragOver[data-v-d7e27fa2] {\r\n border-bottom: 2px solid blue;\n}\n.edit-input-value[type=\"text\"][data-v-d7e27fa2] {\r\n font-size: 75px;\n}\r\n\r\n", map: {"version":3,"sources":["C:\\Users\\maxim\\Projects\\dualbox\\editor\\js\\src\\v\\templates\\editValue.vue"],"names":[],"mappings":";AACA;;IAEA,mBAAA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,eAAA;AACA","file":"editValue.vue","sourcesContent":["<style scoped>\r\n.template-value-container,\r\n.field-editor {\r\n margin-bottom: 10px;\r\n}\r\n\r\n.template-value-message {\r\n text-align: center;\r\n margin-top: 30px;\r\n margin-bottom: 30px;\r\n width: 100%;\r\n opacity: 0.5;\r\n}\r\n\r\n.dragOver {\r\n border-bottom: 2px solid blue;\r\n}\r\n\r\n.edit-input-value[type=\"text\"] {\r\n font-size: 75px;\r\n}\r\n\r\n</style>\r\n\r\n<template>\r\n <div class=\"w-100\">\r\n <p style=\"display: none;\">{{cIndex}}</p>\r\n <template v-if=\"isBasicDataType()\">\r\n <template v-if=\"dataType === 'string'\">\r\n <textarea rows=3 class=\"edit-value-input\" type=\"text\" @keyup.enter=\"setStringValue\" @keyup.esc=\"setStringValue\" @blur=\"setStringValueFromBlur\" :value=\"v\" @focus=\"$event.target.select()\" />\r\n </template>\r\n\r\n <template v-else-if=\"dataType === 'boolean'\">\r\n <select class=\"edit-value-input\" @change=\"setBoolValue\">\r\n <option value=\"true\" :selected=\"v == true\">True</option>\r\n <option value=\"false\" :selected=\"v == false\">False</option>\r\n </select>\r\n </template>\r\n\r\n <template v-else-if=\"dataType === 'number'\">\r\n <input class=\"edit-value-input\" type=\"number\" @keyup.enter=\"setNumberValue\" @blur=\"setNumberValueFromBlur\" :value=\"v\" @focus=\"$event.target.select()\" style=\"width: 40px;\" />\r\n </template>\r\n </template>\r\n\r\n <template v-else>\r\n <!-- we already are in a modal, don't instanciate another one -->\r\n <template v-if=\"isTemplateType()\">\r\n <div class=\"container template-value-container\" style=\"border: 1px solid rgba(0, 0, 0, 0.125);\">\r\n <div v-if=\"isArrayType()\" class=\"row\" style=\"background-color: rgba(0,0,0,.125);\">Array Editor</div>\r\n <div v-else-if=\"isMapType()\" class=\"row\" style=\"background-color: rgba(0,0,0,.125);\">Map Editor</div>\r\n <div class=\"row\" style=\"1px solid rgba(0,0,0,.125);\">\r\n <div class=\"col list-group-flush\" :class=\"{ 'col-1' : isArrayType(), 'col-2' : isMapType()}\" style=\"padding: 0; background-color: white; overflow-y: auto; border-right: 1px solid rgba(0, 0, 0, 0.125); max-height: 500px;\">\r\n <button v-for=\"index in deserializedValue.keys()\" :draggable=\"isArrayType()\" @dragstart=\"arrayIndexDragStart(index, $event)\" @dragover.prevent @dragenter=\"arrayIndexDragEnter\" @dragleave=\"arrayIndexDragLeave\" @drop=\"arrayIndexDrop(index, $event)\" :key=\"index\" :data-key=\"index\" type=\"button\" class=\"list-group-item list-group-item-action\" :class=\"{ active: isSelectedIndex(index) }\" style=\"text-align: center; padding: 12px;\" @click=\"selectIndex(index)\">{{index}}</button>\r\n <button type=\"button\" @click=\"addItem\" class=\"list-group-item list-group-item-action add-item\" style=\"text-align: center;\"><i class=\"fas fa-plus-circle\"></i></button>\r\n </div>\r\n <div class=\"col\" style=\"padding: 10px\">\r\n <edit-value v-if=\"selectedIndex !== undefined && selectedIndex !== null\" :key=\"selectedIndex\" ref=\"subValueEditor\" :cIndex=\"selectedIndex\" :type=\"embeddedType\" :v=\"getElement(selectedIndex)\" @edited=\"onSubValueEdited\"></edit-value>\r\n <p v-else class=\"template-value-message\">Select an element to edit.</p>\r\n </div>\r\n </div>\r\n </div>\r\n </template>\r\n <template v-else>\r\n <span v-if=\"isNull()\" @click=\"setEmptyJsonValue\" class=\"d-inline-block data-display data-value\" style=\"word-break: break-all;\" title=\"set value here\" data-toggle=\"tooltip\" data-trigger=\"hover\" data-placement=\"top\">\r\n <i class=\"fas fa-pen\"></i> null\r\n </span>\r\n <div v-else class=\"field-editor\" :data-value=\"hash()\"></div>\r\n </template>\r\n </template>\r\n\r\n <!-- set null and delete buttons -->\r\n <div class=\"d-inline-block float-right\">\r\n <button class=\"btn btn-secondary btn-sm btn-xs\" title=\"set null\" @click=\"setNullValue\">null</button>\r\n <button class=\"btn btn-danger btn-sm btn-xs\" title=\"delete value\" @click=\"deleteValue\" style=\"margin-left: 0px;\"><i class=\"fas fa-trash\"></i></button>\r\n </div>\r\n </div>\r\n\r\n</template>\r\n\r\n<script>\r\nimport _ from \"lodash-es\";\r\nimport swal from \"sweetalert2\";\r\nimport JSONEditor from \"@dualbox/dualbox-lib-jsoneditor\";\r\n\r\nvar JSONEditorMode = \"tree\";\r\n\r\nString.prototype.hashCode = function() {\r\n var hash = 0,\r\n i,\r\n chr;\r\n if (this.length === 0) return hash;\r\n for (i = 0; i < this.length; i++) {\r\n chr = this.charCodeAt(i);\r\n hash = (hash << 5) - hash + chr;\r\n hash |= 0; // Convert to 32bit integer\r\n }\r\n return hash;\r\n};\r\n\r\nexport default {\r\n name: \"edit-value\",\r\n props: [\r\n // required\r\n \"v\", // the value\r\n \"type\", // the dualbox type of the value\r\n\r\n // specific properties (for recursivity)\r\n \"cIndex\" // index for reference when in an array\r\n ],\r\n data: function() {\r\n return {\r\n dataType: null, // the real javascript dataType of this.v\r\n deserializedValue: null,\r\n\r\n // if type is a collection (dataType==\"map\" or dataType==\"array\")\r\n embeddedType: null, // the embedded type of this templated collection\r\n selectedIndex: null // the current index of the element we are editing\r\n };\r\n },\r\n created: function() {\r\n this.view = window.dualboxEditor.v;\r\n this.editor = null;\r\n this.edited = false;\r\n this.initData();\r\n this.saveOnDestroy = true;\r\n\r\n // create a debounced json emit\r\n this.jsonEmit = () => {\r\n try {\r\n var json = this.editor.get();\r\n this.autochange = true;\r\n this.emit(json);\r\n } catch (e) {}\r\n };\r\n this.debouncedJsonEmit = _.debounce(this.jsonEmit, 5000); // 5 second save debounce\r\n this.debouncedSetStringValue = _.debounce(this.setStringValue, 250); // thoses are to be used with the blur event, so it's cancellable if\r\n this.debouncedSetNumberValue = _.debounce(this.setNumberValue, 250); // the user clicked on \"null\" or \"remove\" instead or changing the string/num value\r\n },\r\n mounted: function() {\r\n var self = this;\r\n\r\n this.updateEditor();\r\n\r\n $(this.$el)\r\n .find(\".edit-value-input\")\r\n .focus(); // focus on the edit element\r\n },\r\n beforeUpdate: function() {\r\n this.updateData();\r\n },\r\n updated: function() {\r\n if (this.autochange) {\r\n // change triggered by ourself, skip\r\n this.autochange = false;\r\n } else {\r\n this.updateEditor();\r\n }\r\n },\r\n beforeDestroy: function() {\r\n if (this.saveOnDestroy) {\r\n // if some debounced json edition was going on, do it now\r\n this.debouncedJsonEmit.flush();\r\n\r\n // make sure the value was set\r\n if (!this.emitted) {\r\n if (this.isBasicDataType()) {\r\n var elt = $(this.$el).find(\".edit-value-input\");\r\n var val = elt.val();\r\n this.$emit(\"edited\", val);\r\n } else {\r\n this.saveChanges();\r\n }\r\n }\r\n }\r\n },\r\n methods: {\r\n hash: function() {\r\n var str = new String(this.v).toString();\r\n return str\r\n .split(\"\")\r\n .reduce(\r\n (prevHash, currVal) =>\r\n ((prevHash << 5) - prevHash + currVal.charCodeAt(0)) |\r\n 0,\r\n 0\r\n );\r\n },\r\n\r\n updateEditor: function() {\r\n if (this.dataType === \"object\" && !this.isNull()) {\r\n if (\r\n !this.editor &&\r\n $(this.$el).find(\".field-editor\")[0] !== undefined\r\n ) {\r\n // bind the json editor\r\n this.editor = new JSONEditor(\r\n $(this.$el).find(\".field-editor\")[0],\r\n {\r\n mode: JSONEditorMode,\r\n modes: [\"tree\", \"code\", \"text\"],\r\n onChange: this.debouncedJsonEmit,\r\n onModeChange: (newMode) => {\r\n JSONEditorMode = newMode;\r\n }\r\n }\r\n );\r\n }\r\n\r\n if (this.editor) {\r\n this.editor.set(this.v || {});\r\n }\r\n }\r\n },\r\n resolveDatatype() {\r\n // determine datatype of the value\r\n var resolvedType = this.type\r\n ? this.type.toLowerCase()\r\n : typeof this.v;\r\n\r\n // If \"*\", resolve the type by detecting it dynamically from value\r\n if (resolvedType.indexOf(\"*\") !== -1) {\r\n resolvedType = window.DualBox.Type.detectType(\r\n this.v\r\n ).toLowerCase();\r\n }\r\n\r\n // Check if we have a template type. If so, determine current index and embedded type\r\n var templateType = null;\r\n if (resolvedType.startsWith(\"array\")) {\r\n templateType = \"array\";\r\n this.deserializedValue = _.clone(this.v || []);\r\n } else if (resolvedType.startsWith(\"map\")) {\r\n templateType = \"map\";\r\n this.deserializedValue = _.clone(\r\n window.DualBox.Type.deserialize(\r\n this.v || {\r\n metadata: {\r\n type:\r\n \"Map<String,\" +\r\n this.firstLetterUppercase(\r\n this.getEmbeddedType(resolvedType)\r\n ) +\r\n \">\"\r\n },\r\n data: {}\r\n }\r\n )\r\n );\r\n }\r\n\r\n if (templateType) {\r\n this.dataType = templateType;\r\n this.embeddedType = this.getEmbeddedType(resolvedType);\r\n if (this.selectedIndex == null) {\r\n var firstKey = this.deserializedValue.keys().next();\r\n if (firstKey && firstKey.value) {\r\n this.selectedIndex = firstKey.value;\r\n }\r\n }\r\n } else {\r\n this.dataType = resolvedType;\r\n }\r\n\r\n // Finally, transform to object if not a basic value\r\n if (\r\n [\"string\", \"number\", \"boolean\", \"array\", \"map\"].indexOf(\r\n this.dataType\r\n ) == -1\r\n ) {\r\n this.dataType = \"object\";\r\n }\r\n //console.log(`Type: ${this.type}, Datatype: ${this.dataType}, embeddedType: ${this.embeddedType}`);\r\n },\r\n\r\n initData: function() {\r\n this.v = this.v;\r\n this.resolveDatatype();\r\n this.selectNextIndex();\r\n },\r\n\r\n updateData: function() {\r\n this.resolveDatatype();\r\n },\r\n\r\n isBasicDataType() {\r\n return (\r\n this.dataType == \"string\" ||\r\n this.dataType == \"number\" ||\r\n this.dataType == \"boolean\"\r\n );\r\n },\r\n\r\n serialize(value) {\r\n if (this.isTemplateType()) {\r\n if (this.isArrayType()) {\r\n return value; // we store arrays as is\r\n } else if (this.isMapType()) {\r\n return window.DualBox.Type.serialize(value);\r\n }\r\n } else {\r\n return value;\r\n }\r\n },\r\n\r\n emit(val) {\r\n this.$emit(\"edited\", val, this.cIndex);\r\n this.emitted = true;\r\n },\r\n\r\n saveChanges: function() {\r\n this.$forceUpdate();\r\n\r\n if (this.isTemplateType()) {\r\n let value = _.clone(this.deserializedValue);\r\n this.emit(this.serialize(value));\r\n this.emitted = true;\r\n } else if (this.isObjectType()) {\r\n // emit the result to the parent Vue\r\n this.emit(this.editor.get());\r\n this.emitted = true;\r\n }\r\n },\r\n\r\n setStringValue: function(e) {\r\n var val = $(e.target).val();\r\n this.emit(val);\r\n this.emitted = true;\r\n },\r\n\r\n // debounce the function to allow user to click on null or remove\r\n setStringValueFromBlur: function(e) {\r\n this.debouncedSetStringValue(e);\r\n },\r\n\r\n setBoolValue: function(e) {\r\n var val = $(e.target).val() == \"true\";\r\n this.emit(val);\r\n this.emitted = true;\r\n },\r\n\r\n setNumberValue: function(e) {\r\n var val = parseFloat($(e.target).val());\r\n if (isNaN(val)) {\r\n this.deleteValue(e);\r\n } else {\r\n this.emit(val);\r\n this.emitted = true;\r\n }\r\n },\r\n\r\n // debounce the function to allow user to click on null or remove\r\n setNumberValueFromBlur: function(e) {\r\n this.debouncedSetNumberValue(e);\r\n },\r\n\r\n cancelBlurDebounced: function() {\r\n this.debouncedSetStringValue.cancel();\r\n this.debouncedSetNumberValue.cancel();\r\n },\r\n\r\n setNullValue: function() {\r\n this.cancelBlurDebounced(); // kill incoming debounced setStringFromBlur or setNumberFromBlur\r\n\r\n this.$forceUpdate();\r\n\r\n // emit the result to the parent Vue\r\n this.emit(null);\r\n },\r\n\r\n setEmptyJsonValue: function() {\r\n // TODO: check this.type and create an empty object of this type\r\n this.emit({});\r\n },\r\n\r\n selectNextIndex: function() {\r\n if (this.isArrayType()) {\r\n this.selectedIndex =\r\n this.deserializedValue.length > 0 ? 0 : null;\r\n } else if (this.isMapType()) {\r\n var keys = this.deserializedValue.keys();\r\n var next = keys.next();\r\n this.selectedIndex = next ? next.value : null;\r\n }\r\n },\r\n\r\n deleteValue: function(e) {\r\n this.cancelBlurDebounced(); // kill incoming debounced setStringFromBlur or setNumberFromBlur\r\n this.selectNextIndex();\r\n this.$forceUpdate();\r\n\r\n // emit the result to the parent Vue\r\n this.emit(undefined);\r\n this.emitted = true;\r\n },\r\n\r\n isArrayType: function() {\r\n return this.dataType == \"array\";\r\n },\r\n\r\n isMapType: function() {\r\n return this.dataType == \"map\";\r\n },\r\n\r\n isObjectType: function() {\r\n return this.dataType == \"object\";\r\n },\r\n\r\n isTemplateType: function() {\r\n return this.isArrayType() || this.isMapType();\r\n },\r\n\r\n isNull: function() {\r\n return this.v === null;\r\n },\r\n\r\n getEmbeddedType: function(type) {\r\n var start = type.indexOf(\"<\") + 1;\r\n var end = type.lastIndexOf(\">\");\r\n if (type.toLowerCase().startsWith(\"array\")) {\r\n return type\r\n .substr(start, end - start)\r\n .trim()\r\n .toLowerCase();\r\n } else if (type.toLowerCase().startsWith(\"map\")) {\r\n var sub = type.substr(start, end - start);\r\n return sub\r\n .substr(sub.indexOf(\",\") + 1)\r\n .trim()\r\n .toLowerCase();\r\n }\r\n },\r\n\r\n firstLetterUppercase: function(s) {\r\n return s.charAt(0).toUpperCase() + s.slice(1);\r\n },\r\n\r\n selectIndex: function(index) {\r\n if (this.selectedIndex !== index) {\r\n this.selectedIndex = index;\r\n this.$forceUpdate();\r\n }\r\n },\r\n\r\n isSelectedIndex: function(index) {\r\n return index == this.selectedIndex;\r\n },\r\n\r\n getElement: function(i) {\r\n if (Array.isArray(this.v)) {\r\n return this.deserializedValue[i];\r\n } else {\r\n return this.deserializedValue.get(i);\r\n }\r\n },\r\n\r\n onSubValueEdited: function(newValue, index) {\r\n console.log(\r\n `Edited at index ${index}: ${JSON.stringify(newValue)}`\r\n );\r\n if (this.isArrayType()) {\r\n if (newValue === undefined) {\r\n // we just remove this value\r\n this.deserializedValue.splice(index, 1);\r\n } else {\r\n this.deserializedValue[index] = newValue;\r\n }\r\n } else if (this.isMapType()) {\r\n if (newValue === undefined) {\r\n this.deserializedValue.delete(index);\r\n } else {\r\n this.deserializedValue.set(index, newValue);\r\n }\r\n }\r\n this.saveChanges();\r\n this.$forceUpdate();\r\n },\r\n\r\n addItem: function() {\r\n if (this.isArrayType()) {\r\n this.deserializedValue[this.deserializedValue.length] = null;\r\n this.selectedIndex = this.deserializedValue.length - 1;\r\n this.saveChanges();\r\n this.$forceUpdate();\r\n } else if (this.isMapType()) {\r\n this.swalFixBootstrapModal();\r\n swal({\r\n input: \"text\",\r\n title: \"Enter map key\"\r\n }).then(result => {\r\n this.swalRestoreBootstrapModal();\r\n if (result && result.value) {\r\n this.selectedIndex = result.value;\r\n this.deserializedValue.set(result.value, null);\r\n this.saveChanges();\r\n this.$forceUpdate();\r\n }\r\n });\r\n }\r\n },\r\n\r\n // call this before showing SweetAlert:\r\n swalFixBootstrapModal() {\r\n var modal = $(\"body\").find('.modal[tabindex=\"-1\"]');\r\n if (!modal) return;\r\n modal.removeAttr(\"tabindex\");\r\n modal.addClass(\"js-swal-fixed\");\r\n },\r\n\r\n // call this before hiding SweetAlert (inside done callback):\r\n swalRestoreBootstrapModal() {\r\n var modal = $(\"body\").find(\".modal.js-swal-fixed\");\r\n if (!modal) return;\r\n modal.attr(\"tabindex\", \"-1\");\r\n modal.removeClass(\"js-swal-fixed\");\r\n },\r\n\r\n arrayIndexDragStart(which, e) {\r\n if (this.isArrayType()) {\r\n this.dragging = which;\r\n }\r\n this.selectedIndex = to;\r\n this.$forceUpdate();\r\n },\r\n\r\n arrayIndexDrop(to, e) {\r\n if (this.isArrayType()) {\r\n $(e.target).removeClass(\"dragOver\");\r\n let from = this.dragging;\r\n\r\n if (from === this.selectedIndex) {\r\n // we will have to ignore next destroy\r\n this.$refs.subValueEditor.saveOnDestroy = false;\r\n }\r\n\r\n // remove from for our indices and insert it after \"to\"\r\n var elem = this.deserializedValue.splice(from, 1)[0];\r\n this.deserializedValue.splice(to, 0, elem);\r\n\r\n this.selectedIndex = to;\r\n this.saveChanges();\r\n this.$forceUpdate();\r\n }\r\n },\r\n\r\n arrayIndexDragEnter(e) {\r\n $(e.target).addClass(\"dragOver\");\r\n },\r\n\r\n arrayIndexDragLeave(e) {\r\n $(e.target).removeClass(\"dragOver\");\r\n }\r\n }\r\n};\r\n</script>\r\n"]}, media: undefined });
65690
65799
 
65691
65800
  };
65692
65801
  /* scoped */
65693
- const __vue_scope_id__$8 = "data-v-bcbe186e";
65802
+ const __vue_scope_id__$8 = "data-v-d7e27fa2";
65694
65803
  /* module identifier */
65695
65804
  const __vue_module_identifier__$8 = undefined;
65696
65805
  /* functional template */
@@ -67365,7 +67474,7 @@ __vue_render__$a._withStripped = true;
67365
67474
  /* style */
67366
67475
  const __vue_inject_styles__$a = function (inject) {
67367
67476
  if (!inject) return
67368
- inject("data-v-3d749219_0", { source: "\n.card-settings .card-body {\r\n font-size: 12px;\r\n padding-left: 5px;\r\n padding-right: 5px;\n}\n.fa {\r\n pointer-events: none;\n}\n.table-desc {\r\n width: 100%;\n}\n.table-desc > thead > th > td {\r\n margin-right: 6px;\n}\n.table-desc > tbody > tr > td {\r\n margin-right: 6px;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n height: 40px;\n}\n.application-description {\r\n margin-top: 20px;\r\n text-align: left;\r\n font-size: 12px;\n}\n.card-header[data-toggle=\"collapse\"] {\r\n cursor: pointer;\n}\n.card-header[data-toggle=\"collapse\"] h5 {\r\n user-select: none;\n}\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\r\n text-decoration: none;\n}\n.text-value, .number-value, .boolean-value {\r\n max-width: 140px;\n}\n.select-event-target, .select-event-name, .event-if, .event-data {\r\n font-size: 12px;\n}\n.edit-body {\r\n overflow-y: hidden;\r\n overflow-x: hidden;\r\n max-height: calc(100% - 90px);\n}\r\n\r\n/* remove bs4 transition on collapsing */\n.edit-main-panel .collapsing {\r\n -webkit-transition: none!important;\r\n transition: none!important;\r\n display: none!important;\n}\n.table-events .event-rooting {\r\n margin-top: 10px;\n}\n.table-events thead {\r\n border-bottom: 1px solid #ddd;\n}\n.table-events .tr-event-condition td {\r\n padding-left: 10px;\n}\n.table-events .tr-event-data td {\r\n padding-left: 10px;\n}\n.tr-event-condition td, .tr-event-data td {\r\n height: 20px!important;\n}\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\r\n padding-top: 1px!important;\r\n padding-bottom: 1px!important;\n}\n.table-events tr + .event-rooting {\r\n /* border-top: 1px solid #ddd; */\n}\n.event-rooting td {\r\n padding-top: 8px!important;\r\n padding-bottom: 4px!important;\n}\n.event-data-type {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\n}\n.event-data-display {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\n}\n.event-if {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\n}\ni.fa, i.fas, i.far {\r\n pointer-events: none;\n}\n.h100 {\r\n height: 100%;\n}\n.card-app-event > .card-header {\r\n padding: 6px 12px;\n}\n.card-main-settings {\r\n border: 1px solid rgba(0,0,0,.125);\n}\n.card-main-settings > .card-header {\r\n padding-top: 6px;\r\n padding-bottom: 6px;\r\n padding-left: 12px;\r\n padding-right: 12px;\n}\n.card-main-settings > .card-header > h5 {\r\n font-size: 20px;\n}\r\n", map: {"version":3,"sources":["C:\\Users\\maxim\\Projects\\dualbox\\editor\\js\\src\\v\\templates\\editMainSettings.vue"],"names":[],"mappings":";AACA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,oBAAA;AACA;AAEA;IACA,WAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;IACA,YAAA;AACA;AAEA;IACA,gBAAA;IACA,gBAAA;IACA,eAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,kBAAA;IACA,6BAAA;AACA;;AAEA,wCAAA;AACA;IACA,kCAAA;IACA,0BAAA;IACA,uBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,gCAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,oBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,kCAAA;AACA;AAEA;IACA,gBAAA;IACA,mBAAA;IACA,kBAAA;IACA,mBAAA;AACA;AAEA;IACA,eAAA;AACA","file":"editMainSettings.vue","sourcesContent":["<style>\r\n.card-settings .card-body {\r\n font-size: 12px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n}\r\n\r\n.fa {\r\n pointer-events: none;\r\n}\r\n\r\n.table-desc {\r\n width: 100%;\r\n}\r\n\r\n.table-desc > thead > th > td {\r\n margin-right: 6px;\r\n}\r\n\r\n.table-desc > tbody > tr > td {\r\n margin-right: 6px;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n height: 40px;\r\n}\r\n\r\n.application-description {\r\n margin-top: 20px;\r\n text-align: left;\r\n font-size: 12px;\r\n}\r\n\r\n.card-header[data-toggle=\"collapse\"] {\r\n cursor: pointer;\r\n}\r\n\r\n.card-header[data-toggle=\"collapse\"] h5 {\r\n user-select: none;\r\n}\r\n\r\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\r\n text-decoration: none;\r\n}\r\n\r\n.text-value, .number-value, .boolean-value {\r\n max-width: 140px;\r\n}\r\n\r\n.select-event-target, .select-event-name, .event-if, .event-data {\r\n font-size: 12px;\r\n}\r\n\r\n.edit-body {\r\n overflow-y: hidden;\r\n overflow-x: hidden;\r\n max-height: calc(100% - 90px);\r\n}\r\n\r\n/* remove bs4 transition on collapsing */\r\n.edit-main-panel .collapsing {\r\n -webkit-transition: none!important;\r\n transition: none!important;\r\n display: none!important;\r\n}\r\n\r\n.table-events .event-rooting {\r\n margin-top: 10px;\r\n}\r\n\r\n.table-events thead {\r\n border-bottom: 1px solid #ddd;\r\n}\r\n\r\n.table-events .tr-event-condition td {\r\n padding-left: 10px;\r\n}\r\n\r\n.table-events .tr-event-data td {\r\n padding-left: 10px;\r\n}\r\n\r\n.tr-event-condition td, .tr-event-data td {\r\n height: 20px!important;\r\n}\r\n\r\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\r\n padding-top: 1px!important;\r\n padding-bottom: 1px!important;\r\n}\r\n\r\n.table-events tr + .event-rooting {\r\n /* border-top: 1px solid #ddd; */\r\n}\r\n\r\n.event-rooting td {\r\n padding-top: 8px!important;\r\n padding-bottom: 4px!important;\r\n}\r\n\r\n.event-data-type {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n}\r\n\r\n.event-data-display {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n}\r\n\r\n.event-if {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n}\r\n\r\ni.fa, i.fas, i.far {\r\n pointer-events: none;\r\n}\r\n\r\n.h100 {\r\n height: 100%;\r\n}\r\n\r\n.card-app-event > .card-header {\r\n padding: 6px 12px;\r\n}\r\n\r\n.card-main-settings {\r\n border: 1px solid rgba(0,0,0,.125);\r\n}\r\n\r\n.card-main-settings > .card-header {\r\n padding-top: 6px;\r\n padding-bottom: 6px;\r\n padding-left: 12px;\r\n padding-right: 12px;\r\n}\r\n\r\n.card-main-settings > .card-header > h5 {\r\n font-size: 20px;\r\n}\r\n</style>\r\n\r\n<template>\r\n\r\n<div class=\"edit-main-panel h100\" id=\"edit-main-panel\">\r\n <div class=\"edit-main-presentation\" style=\"padding-left: 10px; padding-top: 10px; padding-right: 10px; padding-bottom 10px;\">\r\n <h2 class=\"edit-dualbox-app\" style=\"margin-bottom: none;\">\r\n <div class=\"dualbox-node-name\">\r\n <span class=\"text-truncate d-inline-block\" style=\"width: 290px\">Application</span>\r\n </div>\r\n </h2>\r\n </div>\r\n\r\n <div class=\"edit-body h100\">\r\n <!--\r\n <div class=\"card-main-settings\">\r\n <div class=\"card-header\" id=\"dualbox-main-desc\" data-toggle=\"collapse\" data-target=\"#dualbox-main-desc-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-main-desc-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Description</h5>\r\n </div>\r\n\r\n\r\n <div id=\"dualbox-main-desc-collapse\" class=\"collapse show\" aria-labelledby=\"dualbox-main-desc\" data-parent=\"#edit-main-panel\">\r\n <div class=\"card-body\">\r\n <p class=\"application-description\">{{ app.getDescription() || \"[No description available]\" }} <button class=\"btn btn-editor-xs btn-light btn-edit-app-description\" @click=\"editAppDescription\"><i class=\"fa fa-edit\"></i></button></p>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n -->\r\n <div class=\"card-main-settings\">\r\n <div class=\"card-header\" id=\"dualbox-main-events\" data-toggle=\"collapse\" data-target=\"#dualbox-main-events-collapse\" aria-expanded=\"true\" aria-controls=\"dualbox-main-events-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Events</h5>\r\n </div>\r\n\r\n <div id=\"dualbox-main-events-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-main-events\" data-parent=\"#edit-main-panel\">\r\n <div class=\"card-body\" style=\"padding-left: 4px; padding-right: 4px;\">\r\n <button class=\"btn btn-success btn-sm btn-add-app-event mb-3\" @click=\"addAppEvent\">Add application event</button>\r\n <div v-for=\"key in app.getEventsNames()\" class=\"card card-app-event\" :key=\"'app-event-' + key\">\r\n <div class=\"card-header\" :id=\"'dualbox-event-' + key\" data-toggle=\"collapse\" :data-target=\"'#dualbox-event-' + key + '-collapse'\" aria-expanded=\"false\" aria-controls=\"'dualbox-event-' + key + '-collapse'\">\r\n <h5 class=\"mb-0 btn-link\" style=\"font-size: 16px; font-weight: normal;\">\r\n {{key}}\r\n <div class=\"float-right d-inline-block\">\r\n <button class=\"btn btn-light btn-editor-xs btn-rename-app-event\" :data-event=\"key\" @click=\"renameAppEvent\">\r\n <i class=\"fa fa-edit\"></i>\r\n </button>\r\n <button class=\"btn btn-danger btn-editor-xs btn-remove-app-event\" :data-event=\"key\" @click=\"removeAppEvent\">\r\n <i class=\"fa fa-minus\"></i>\r\n </button>\r\n </div>\r\n </h5>\r\n </div>\r\n\r\n <div :id=\"'dualbox-event-'+ key + '-collapse'\" class=\"collapse\" :aria-labelledby=\"'dualbox-event-' + key\" data-parent=\"#dualbox-main-events\">\r\n <div class=\"card-body\" style=\"padding-left: 4px; padding-right: 4px;\">\r\n <h5 style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Description</h5>\r\n <p>{{ app.getEventDescription(key) || \"[no description available]\" }} <button class=\"btn btn-editor-xs btn-light btn-edit-event-description\" :data-event=\"key\" @click=\"editEventDescription\"><i class=\"fa fa-edit\"></i></button></p>\r\n <h5 class=\"mt-3\" style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Triggers</h5>\r\n\r\n <table class=\"table-events table-desc\" style=\"font-size: 12px!important;\">\r\n <thead class=\"thead-dark\">\r\n <th>Target</th>\r\n <th>Event</th>\r\n <!--<th>If</th>-->\r\n <!--<th>Data</th>-->\r\n <th>Action</th>\r\n </thead>\r\n <tbody>\r\n <template v-for=\"(evt,index) in app.getEventIn(key)\" :data-index=\"index\">\r\n <tr class=\"event-rooting\">\r\n <td>\r\n <select v-if=\"evt.node !== undefined\" class=\"form-control form-control-sm select-event-target\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" @change=\"selectEventTarget\">\r\n <option v-for=\"node in getNodesWithInEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()==evt.node\" :key=\"'event-in-target-' + node.getGraphId()\">{{node.getGraphId()}}</option>\r\n </select>\r\n <span v-else>{{evt.selector}}</span>\r\n </td>\r\n <td>\r\n <select class=\"form-control form-control-sm select-event-name\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" @change=\"selectEventName\" >\r\n <template v-if=\"evt.node\">\r\n <option v-for=\"te in getNodeInEvents(evt.node)\" :value=\"te\" :selected=\"te == evt.event\" :key=\"'app-event-in-target-' + evt.node + '-' + te\">{{te}}</option>\r\n </template>\r\n <template v-else>\r\n <option value=\"hide\">hide</option>\r\n <option value=\"show\">show</option>\r\n </template>\r\n </select>\r\n </td>\r\n <td style=\"min-width: 58px;\">\r\n <button class=\"btn btn-secondary btn-editor-xs\" :data-event=\"key\" :data-index=\"index\" @click=\"toggleAdvancedAppEventSettings\" style=\"margin-left: 10px;\" title=\"Toggle advanced event settings\" >\r\n <i class=\"fas fa-cog\"></i>\r\n </button>\r\n <button class=\"btn btn-danger btn-editor-xs\" :data-event=\"key\" :data-index=\"index\" @click=\"removeInEvent\" >\r\n <i class=\"fas fa-minus\"></i>\r\n </button>\r\n </td>\r\n </tr>\r\n <tr v-if=\"evt.if || expanded[key+'##'+index]\" class=\"tr-event-condition\">\r\n <td colspan=\"3\">\r\n <span style=\"width: 60px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Occur if:</span>\r\n\r\n <input style=\"max-width: 340px; width: 340px;\" class=\"form-control form-control-sm event-if d-inline-block\" type=\"text\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" :value=\"evt.if\" @change=\"setEventIf\" />\r\n </td>\r\n </tr>\r\n <tr v-if=\"evt.data || evt.datatype || expanded[key+'##'+index]\" class=\"tr-event-data\" colspan=\"3\">\r\n <td colspan=\"3\">\r\n <span style=\"width: 53px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Data:</span>\r\n <span style=\"width: 350px;\">\r\n <display-type :type=\"getDataType(evt)\" @edited=\"onEditEventInDataType(key, index, $event)\"></display-type>\r\n <display-value :v=\"evt.data\" :type=\"getDataType(evt)\" cssWidth=\"auto\" @edited=\"onEditEventInData(key, index, $event)\"></display-value>\r\n </span>\r\n </td>\r\n </tr>\r\n </template>\r\n <tr>\r\n <td colspan=\"5\" style=\"padding-top: 0px; padding-bottom: 0px;\">\r\n <button class=\"btn btn-secondary btn-sm btn-add-subevent\" style=\"width: 100%;\" @click=\"addSubEvent(key)\">Add a subevent</button>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n <h5 class=\"mt-3\" style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Callback</h5>\r\n\r\n <table class=\"table-desc table-striped\" style=\"font-size: 12px!important;\">\r\n <thead class=\"thead-dark\">\r\n <th>Target</th>\r\n <th>Event</th>\r\n <th>Action</th>\r\n </thead>\r\n <tbody>\r\n <tr v-if=\"app.getEventOut(key) !== undefined\">\r\n <td>\r\n <select class=\"form-control form-control-sm select-event-target select-callback-target\" dualbox-target=\"events-out\" @change=\"setCallback(key)\">\r\n <option v-for=\"node in getNodesWithOutEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()===app.getEventOut(key).node\" :key=\"'app-event-out-target-' + node.getGraphId()\">{{ node.getGraphId() }}</option>\r\n </select>\r\n </td>\r\n <td>\r\n <select class=\"form-control form-control-sm select-event-name select-callback-event\" dualbox-target=\"events-out\">\r\n <template v-if=\"app.getEventOut(key).node\" @change=\"setCallback(key)\">\r\n <option v-for=\"(te, index) in getNodeOutEvents(app.getEventOut(key).node)\" :value=\"te\" :selected=\"te == app.getEventOut(key).event\" :key=\"'app-event-out-' + index\">{{te}}</option>\r\n </template>\r\n </select>\r\n </td>\r\n <td>\r\n <button class=\"btn btn-danger btn-editor-xs btn-remove-out-event\" :data-event=\"key\" @click=\"removeOutEvent\">\r\n <i class=\"fa fa-minus\"></i>\r\n </button>\r\n </td>\r\n </tr>\r\n <tr v-else>\r\n <td colspan=\"3\" style=\"padding-top: 0px; padding-bottom: 0px;\">\r\n <button class=\"btn btn-sm btn-add-callback\" style=\"width: 100%;\" @click=\"addCallback(key)\">Add a callback</button>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"modal edit-value-modal\" tabindex=\"-1\" role=\"dialog\">\r\n <div class=\"modal-dialog\" role=\"document\">\r\n <div class=\"modal-content\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title\">Edit value</h5>\r\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div>\r\n <div class=\"form-check\">\r\n <input type=\"radio\" class=\"form-check-input set-value unset-value\" id=\"unset-value\" name=\"set-value\" value=\"unset-value\" checked>\r\n <label class=\"form-check-label\" for=\"unset-value\">\r\n don't set a value\r\n </label>\r\n </div>\r\n <div class=\"form-check\">\r\n <input type=\"radio\" class=\"form-check-input set-value set-value-null\" id=\"set-value-null\" name=\"set-value\" value=\"set-value-null\">\r\n <label class=\"form-check-label\" for=\"set-value-null\">\r\n set null\r\n </label>\r\n </div>\r\n <div class=\"form-check\">\r\n <input type=\"radio\" class=\"form-check-input set-value set-value-type\" id=\"set-value-type\" name=\"set-value\" value=\"set-value-type\" aria-label=\"Set a value of type\">\r\n <div class=\"form-inline form-check-label\" style=\"height: 24px;\">\r\n <label for=\"set-value-type\">\r\n set a value of type:\r\n <select class=\"form-control choose-value-type d-inline-block form-control-sm ml-2\">\r\n <option value=\"string\">String</option>\r\n <option value=\"number\">Number</option>\r\n <option value=\"boolean\">Boolean</option>\r\n <option value=\"object\">Object</option>\r\n </select>\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"has-value\" style=\"display: none;\">\r\n <hr/>\r\n <div class=\"define-value define-boolean\" style=\"display: none;\">\r\n <div class=\"form-inline\">\r\n <label>Value: </label>\r\n <select class=\"form-control form-control-sm bool-value d-inline-block ml-2\">\r\n <option value=true>True</option>\r\n <option value=false>False</option>\r\n </select>\r\n </div>\r\n </div>\r\n <div class=\"define-value define-number\" style=\"display: none;\">\r\n <div class=\"form-inline\">\r\n <label>Value: </label>\r\n <input type=\"number\" class=\"form-control form-control-sm number-value ml-2\"/>\r\n </div>\r\n </div>\r\n <div class=\"define-value define-string\" style=\"display: none;\">\r\n <div class=\"form-inline\">\r\n <label>Value: </label>\r\n <input type=\"text\" class=\"form-control form-control-sm text-value ml-2\"/>\r\n </div>\r\n </div>\r\n <div class=\"define-value define-object\" style=\"display: none;\">\r\n <label>Value: </label>\r\n <div class=\"json-editor\" style=\"height: 400px;\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-primary btn-save\">Save changes</button>\r\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n</template>\r\n\r\n<script>\r\nimport _ from 'lodash-es';\r\nimport swal from 'sweetalert2';\r\nimport DisplayTypeVue from './displayType.vue';\r\nimport DisplayValueVue from './displayValue.vue';\r\n\r\nexport default {\r\n props: [\r\n \"app\"\r\n ],\r\n components: {\r\n \"display-type\" : DisplayTypeVue,\r\n \"display-value\" : DisplayValueVue,\r\n },\r\n data: function () {\r\n return {\r\n expanded: {} // expanded app events (advanced settings)\r\n };\r\n },\r\n created: function() {\r\n this.view = window.dualboxEditor.v;\r\n },\r\n mounted: function() {\r\n // bind tooltips\r\n $(this.$el).find('button[data-toggle=\"tooltip\"]').tooltip();\r\n this.fixMaxHeightForCategories();\r\n },\r\n updated: function() {\r\n this.fixMaxHeightForCategories();\r\n },\r\n methods: {\r\n // setup a max height for each menu, so a scroll appears if there's too much item in it\r\n fixMaxHeightForCategories : function() {\r\n let nbActiveCategories = $(this.$el).find('.edit-body > .card').length;\r\n let headerHeight = $(this.$el).find('.edit-body > .card > .card-header').outerHeight();\r\n let panelHeight = $(this.$el).height() - $(this.$el).find('.edit-main-presentation').outerHeight();\r\n let maxCategoryHeight = panelHeight - nbActiveCategories * headerHeight;\r\n $(this.$el).find('.edit-body').css('height', panelHeight);\r\n $(this.$el).find('.edit-body > .card > .collapse > .card-body').css('max-height', maxCategoryHeight + \"px\");\r\n },\r\n\r\n onEdited: function() {\r\n this.view.repaint();\r\n },\r\n\r\n getNodesWithInEvents: function() {\r\n var l = [];\r\n var nodes = this.view.m.getNodes(\"ui\");\r\n _.each(nodes, (n) => {\r\n if( n.getInEventsNames().length > 0 ) {\r\n l.push(n);\r\n }\r\n });\r\n return l;\r\n },\r\n\r\n getNodesWithOutEvents: function() {\r\n var l = [];\r\n var nodes = this.view.m.getNodes(\"ui\");\r\n _.each(nodes, (n) => {\r\n if( n.getOutEventsNames().length > 0 ) {\r\n l.push(n);\r\n }\r\n });\r\n return l;\r\n },\r\n\r\n getNodeEvents: function( nodeId ) {\r\n var node = this.view.m.getNode(nodeId);\r\n return node.getEventsNames();\r\n },\r\n\r\n getNodeInEvents: function( nodeId ) {\r\n var node = this.view.m.getNode(nodeId);\r\n return node.getInEventsNames();\r\n },\r\n\r\n getNodeOutEvents: function( nodeId ) {\r\n var node = this.view.m.getNode(nodeId);\r\n return node.getOutEventsNames();\r\n },\r\n\r\n editAppDescription: function() {\r\n swal({\r\n input: 'text',\r\n title: 'Enter the description',\r\n }).then((result) => {\r\n this.view.c.setAppDescription(result.value);\r\n });\r\n },\r\n\r\n editEventDescription: function(e) {\r\n var eventName = $(e.target).attr('data-event');\r\n\r\n swal({\r\n input: 'text',\r\n title: 'Enter the description',\r\n }).then((result) => {\r\n this.view.c.setAppEventDescription(eventName, result.value);\r\n });\r\n },\r\n\r\n removeAppEvent: function(e) {\r\n var name = $(e.target).attr('data-event');\r\n this.view.c.removeAppEvent(name);\r\n this.onEdited();\r\n },\r\n\r\n renameAppEvent: function(e) {\r\n var name = $(e.target).attr('data-event');\r\n swal({\r\n input: 'text',\r\n title: 'Enter the new event name',\r\n }).then((result) => {\r\n if( result.value ) {\r\n this.view.c.renameAppEvent(name, result.value);\r\n this.onEdited();\r\n }\r\n });\r\n },\r\n\r\n setEventIf: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventIf( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val);\r\n this.onEdited();\r\n },\r\n\r\n setEventData: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventData( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val);\r\n this.onEdited();\r\n },\r\n\r\n selectEventTarget: function(e) {\r\n var target = $(e.target).val();\r\n\r\n // change options of closest .select-event-name according to this new target\r\n var targetNode = this.view.m.getNode(target);\r\n var targetEvents = targetNode.getEventsNames();\r\n var select = $(e.target).closest('tr').find('.select-event-name');\r\n select.html('');\r\n _.each(targetEvents, (eventName) => {\r\n select.append( $('<option/>', {\r\n value: eventName\r\n }).append(eventName));\r\n });\r\n\r\n var index = parseInt($(e.target).attr('data-index'));\r\n\r\n // set event target\r\n this.view.c.setEventTarget( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, target);\r\n\r\n // also set event name, to ensure we don't have a set event that doesn't exist on this node\r\n this.view.c.setEventName( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, targetEvents[0]);\r\n this.onEdited();\r\n },\r\n\r\n selectEventName: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventName( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val );\r\n this.onEdited();\r\n },\r\n\r\n addCallback: function(appEventName) {\r\n var nodesWithOutEvents = this.getNodesWithOutEvents();\r\n if( nodesWithOutEvents.length > 0 ) {\r\n var firstNode = nodesWithOutEvents[0];\r\n var firstEvent = firstNode.getOutEventsNames()[0];\r\n this.setCallback(appEventName, firstNode, firstEvent);\r\n }\r\n else {\r\n swal({\r\n title: \"You can not add an API callback here\",\r\n text: \"None of the UIs of the application does have an OUT event, usable for API callbacks\",\r\n type: \"error\"\r\n })\r\n }\r\n },\r\n\r\n setCallback: function(appEventName, e) {\r\n var targetNodeId = $(this.$el).find('.select-callback-target').val();\r\n var targetNodeEvent = $(this.$el).find('.select-callback-event').val();\r\n this.view.c.setCallback(appEventName, targetNodeId, targetNodeEvent);\r\n this.onEdited();\r\n },\r\n\r\n addAppEvent: function(e) {\r\n swal({\r\n input: 'text',\r\n title: 'Enter the event name',\r\n }).then(async (result) => {\r\n await this.view.c.addAppEvent(result.value);\r\n this.onEdited();\r\n });\r\n },\r\n\r\n removeInEvent: function(e) {\r\n var eventName = $(e.target).attr('data-event');\r\n var index = parseInt($(e.target).attr('data-index'));\r\n this.view.c.removeAppInEvent(eventName, index);\r\n this.onEdited();\r\n },\r\n\r\n removeOutEvent: function(e) {\r\n var eventName = $(e.target).attr('data-event');\r\n this.view.c.removeAppOutEvent(eventName);\r\n this.onEdited();\r\n },\r\n\r\n addSubEvent: function(eventName) {\r\n this.view.c.addSubEvent(eventName);\r\n this.onEdited();\r\n },\r\n\r\n getDataType: function(evt) {\r\n if( evt.datatype ) {\r\n return evt.datatype;\r\n }\r\n else if( evt.data ) {\r\n return window.DualBox.Type.detectType(evt.data);\r\n }\r\n else {\r\n return undefined;\r\n }\r\n },\r\n\r\n toggleAdvancedAppEventSettings: function(e) {\r\n var key = $(e.target).data('event');\r\n var index = $(e.target).data('index');\r\n var k=key+'##'+index;\r\n this.expanded[k] = this.expanded[k] ? false : true;\r\n this.$forceUpdate();\r\n },\r\n\r\n onEditEventInData(key, index, val) {\r\n this.view.c.setEventData( \"#application-events-in-\" + key, index, val);\r\n this.$emit('edited');\r\n },\r\n\r\n onEditEventInDataType(key, index, type) {\r\n this.view.c.setEventDataType( \"#application-events-in-\" + key, index, type);\r\n\r\n // check that the set value still match the new type\r\n // delete it otherwise\r\n var val = this.app.getEventIn(key)[index].data;\r\n try {\r\n // TODO: ensure type is already loaded (after dualbox) and remove the try/catch\r\n if( !window.DualBox.Type.check(type, val) ) {\r\n // delete data (== set undefined)\r\n this.view.c.setEventData( \"#application-events-in-\" + key, index, undefined);\r\n }\r\n }\r\n catch(e) {\r\n this.view.c.setEventData( \"#application-events-in-\" + key, index, undefined);\r\n }\r\n\r\n this.$emit('edited');\r\n },\r\n }\r\n}\r\n</script>\r\n"]}, media: undefined });
67477
+ inject("data-v-0f5578f2_0", { source: "\n.card-settings .card-body {\r\n font-size: 12px;\r\n padding-left: 5px;\r\n padding-right: 5px;\n}\n.fa {\r\n pointer-events: none;\n}\n.table-desc {\r\n width: 100%;\n}\n.table-desc > thead > th > td {\r\n margin-right: 6px;\n}\n.table-desc > tbody > tr > td {\r\n margin-right: 6px;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n height: 40px;\n}\n.application-description {\r\n margin-top: 20px;\r\n text-align: left;\r\n font-size: 12px;\n}\n.card-header[data-toggle=\"collapse\"] {\r\n cursor: pointer;\n}\n.card-header[data-toggle=\"collapse\"] h5 {\r\n user-select: none;\n}\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\r\n text-decoration: none;\n}\n.text-value, .number-value, .boolean-value {\r\n max-width: 140px;\n}\n.select-event-target, .select-event-name, .event-if, .event-data {\r\n font-size: 12px;\n}\n.edit-body {\r\n overflow-y: hidden;\r\n overflow-x: hidden;\r\n max-height: calc(100% - 90px);\n}\r\n\r\n/* remove bs4 transition on collapsing */\n.edit-main-panel .collapsing {\r\n -webkit-transition: none!important;\r\n transition: none!important;\r\n display: none!important;\n}\n.table-events .event-rooting {\r\n margin-top: 10px;\n}\n.table-events thead {\r\n border-bottom: 1px solid #ddd;\n}\n.table-events .tr-event-condition td {\r\n padding-left: 10px;\n}\n.table-events .tr-event-data td {\r\n padding-left: 10px;\n}\n.tr-event-condition td, .tr-event-data td {\r\n height: 20px!important;\n}\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\r\n padding-top: 1px!important;\r\n padding-bottom: 1px!important;\n}\n.table-events tr + .event-rooting {\r\n /* border-top: 1px solid #ddd; */\n}\n.event-rooting td {\r\n padding-top: 8px!important;\r\n padding-bottom: 4px!important;\n}\n.event-data-type {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\n}\n.event-data-display {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\n}\n.event-if {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\n}\ni.fa, i.fas, i.far {\r\n pointer-events: none;\n}\n.h100 {\r\n height: 100%;\n}\n.card-app-event > .card-header {\r\n padding: 6px 12px;\n}\n.card-main-settings {\r\n border: 1px solid rgba(0,0,0,.125);\r\n max-height: calc(100vh - 120px);\r\n overflow: auto;\n}\n.card-main-settings > .card-header {\r\n padding-top: 6px;\r\n padding-bottom: 6px;\r\n padding-left: 12px;\r\n padding-right: 12px;\n}\n.card-main-settings > .card-header > h5 {\r\n font-size: 20px;\n}\r\n", map: {"version":3,"sources":["C:\\Users\\maxim\\Projects\\dualbox\\editor\\js\\src\\v\\templates\\editMainSettings.vue"],"names":[],"mappings":";AACA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,oBAAA;AACA;AAEA;IACA,WAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;IACA,YAAA;AACA;AAEA;IACA,gBAAA;IACA,gBAAA;IACA,eAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,kBAAA;IACA,6BAAA;AACA;;AAEA,wCAAA;AACA;IACA,kCAAA;IACA,0BAAA;IACA,uBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,gCAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,oBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,kCAAA;IACA,+BAAA;IACA,cAAA;AACA;AAEA;IACA,gBAAA;IACA,mBAAA;IACA,kBAAA;IACA,mBAAA;AACA;AAEA;IACA,eAAA;AACA","file":"editMainSettings.vue","sourcesContent":["<style>\r\n.card-settings .card-body {\r\n font-size: 12px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n}\r\n\r\n.fa {\r\n pointer-events: none;\r\n}\r\n\r\n.table-desc {\r\n width: 100%;\r\n}\r\n\r\n.table-desc > thead > th > td {\r\n margin-right: 6px;\r\n}\r\n\r\n.table-desc > tbody > tr > td {\r\n margin-right: 6px;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n height: 40px;\r\n}\r\n\r\n.application-description {\r\n margin-top: 20px;\r\n text-align: left;\r\n font-size: 12px;\r\n}\r\n\r\n.card-header[data-toggle=\"collapse\"] {\r\n cursor: pointer;\r\n}\r\n\r\n.card-header[data-toggle=\"collapse\"] h5 {\r\n user-select: none;\r\n}\r\n\r\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\r\n text-decoration: none;\r\n}\r\n\r\n.text-value, .number-value, .boolean-value {\r\n max-width: 140px;\r\n}\r\n\r\n.select-event-target, .select-event-name, .event-if, .event-data {\r\n font-size: 12px;\r\n}\r\n\r\n.edit-body {\r\n overflow-y: hidden;\r\n overflow-x: hidden;\r\n max-height: calc(100% - 90px);\r\n}\r\n\r\n/* remove bs4 transition on collapsing */\r\n.edit-main-panel .collapsing {\r\n -webkit-transition: none!important;\r\n transition: none!important;\r\n display: none!important;\r\n}\r\n\r\n.table-events .event-rooting {\r\n margin-top: 10px;\r\n}\r\n\r\n.table-events thead {\r\n border-bottom: 1px solid #ddd;\r\n}\r\n\r\n.table-events .tr-event-condition td {\r\n padding-left: 10px;\r\n}\r\n\r\n.table-events .tr-event-data td {\r\n padding-left: 10px;\r\n}\r\n\r\n.tr-event-condition td, .tr-event-data td {\r\n height: 20px!important;\r\n}\r\n\r\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\r\n padding-top: 1px!important;\r\n padding-bottom: 1px!important;\r\n}\r\n\r\n.table-events tr + .event-rooting {\r\n /* border-top: 1px solid #ddd; */\r\n}\r\n\r\n.event-rooting td {\r\n padding-top: 8px!important;\r\n padding-bottom: 4px!important;\r\n}\r\n\r\n.event-data-type {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n}\r\n\r\n.event-data-display {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n}\r\n\r\n.event-if {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n}\r\n\r\ni.fa, i.fas, i.far {\r\n pointer-events: none;\r\n}\r\n\r\n.h100 {\r\n height: 100%;\r\n}\r\n\r\n.card-app-event > .card-header {\r\n padding: 6px 12px;\r\n}\r\n\r\n.card-main-settings {\r\n border: 1px solid rgba(0,0,0,.125);\r\n max-height: calc(100vh - 120px);\r\n overflow: auto;\r\n}\r\n\r\n.card-main-settings > .card-header {\r\n padding-top: 6px;\r\n padding-bottom: 6px;\r\n padding-left: 12px;\r\n padding-right: 12px;\r\n}\r\n\r\n.card-main-settings > .card-header > h5 {\r\n font-size: 20px;\r\n}\r\n</style>\r\n\r\n<template>\r\n\r\n<div class=\"edit-main-panel h100\" id=\"edit-main-panel\">\r\n <div class=\"edit-main-presentation\" style=\"padding-left: 10px; padding-top: 10px; padding-right: 10px; padding-bottom 10px;\">\r\n <h2 class=\"edit-dualbox-app\" style=\"margin-bottom: none;\">\r\n <div class=\"dualbox-node-name\">\r\n <span class=\"text-truncate d-inline-block\" style=\"width: 290px\">Application</span>\r\n </div>\r\n </h2>\r\n </div>\r\n\r\n <div class=\"edit-body h100\">\r\n <!--\r\n <div class=\"card-main-settings\">\r\n <div class=\"card-header\" id=\"dualbox-main-desc\" data-toggle=\"collapse\" data-target=\"#dualbox-main-desc-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-main-desc-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Description</h5>\r\n </div>\r\n\r\n\r\n <div id=\"dualbox-main-desc-collapse\" class=\"collapse show\" aria-labelledby=\"dualbox-main-desc\" data-parent=\"#edit-main-panel\">\r\n <div class=\"card-body\">\r\n <p class=\"application-description\">{{ app.getDescription() || \"[No description available]\" }} <button class=\"btn btn-editor-xs btn-light btn-edit-app-description\" @click=\"editAppDescription\"><i class=\"fa fa-edit\"></i></button></p>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n -->\r\n <div class=\"card-main-settings\">\r\n <div class=\"card-header\" id=\"dualbox-main-events\" data-toggle=\"collapse\" data-target=\"#dualbox-main-events-collapse\" aria-expanded=\"true\" aria-controls=\"dualbox-main-events-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Events</h5>\r\n </div>\r\n\r\n <div id=\"dualbox-main-events-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-main-events\" data-parent=\"#edit-main-panel\">\r\n <div class=\"card-body\" style=\"padding-left: 4px; padding-right: 4px;\">\r\n <button class=\"btn btn-success btn-sm btn-add-app-event mb-3\" @click=\"addAppEvent\">Add application event</button>\r\n <div v-for=\"key in app.getEventsNames()\" class=\"card card-app-event\" :key=\"'app-event-' + key\">\r\n <div class=\"card-header\" :id=\"'dualbox-event-' + key\" data-toggle=\"collapse\" :data-target=\"'#dualbox-event-' + key + '-collapse'\" aria-expanded=\"false\" aria-controls=\"'dualbox-event-' + key + '-collapse'\">\r\n <h5 class=\"mb-0 btn-link\" style=\"font-size: 16px; font-weight: normal;\">\r\n {{key}}\r\n <div class=\"float-right d-inline-block\">\r\n <button class=\"btn btn-light btn-editor-xs btn-rename-app-event\" :data-event=\"key\" @click=\"renameAppEvent\">\r\n <i class=\"fa fa-edit\"></i>\r\n </button>\r\n <button class=\"btn btn-danger btn-editor-xs btn-remove-app-event\" :data-event=\"key\" @click=\"removeAppEvent\">\r\n <i class=\"fa fa-minus\"></i>\r\n </button>\r\n </div>\r\n </h5>\r\n </div>\r\n\r\n <div :id=\"'dualbox-event-'+ key + '-collapse'\" class=\"collapse\" :aria-labelledby=\"'dualbox-event-' + key\" data-parent=\"#dualbox-main-events\">\r\n <div class=\"card-body\" style=\"padding-left: 4px; padding-right: 4px;\">\r\n <h5 style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Description</h5>\r\n <p>{{ app.getEventDescription(key) || \"[no description available]\" }} <button class=\"btn btn-editor-xs btn-light btn-edit-event-description\" :data-event=\"key\" @click=\"editEventDescription\"><i class=\"fa fa-edit\"></i></button></p>\r\n <h5 class=\"mt-3\" style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Triggers</h5>\r\n\r\n <table class=\"table-events table-desc\" style=\"font-size: 12px!important;\">\r\n <thead class=\"thead-dark\">\r\n <th>Target</th>\r\n <th>Event</th>\r\n <!--<th>If</th>-->\r\n <!--<th>Data</th>-->\r\n <th>Action</th>\r\n </thead>\r\n <tbody>\r\n <template v-for=\"(evt,index) in app.getEventIn(key)\" :data-index=\"index\">\r\n <tr class=\"event-rooting\">\r\n <td>\r\n <select v-if=\"evt.node !== undefined\" class=\"form-control form-control-sm select-event-target\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" @change=\"selectEventTarget\">\r\n <option v-for=\"node in getNodesWithInEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()==evt.node\" :key=\"'event-in-target-' + node.getGraphId()\">{{node.getGraphId()}}</option>\r\n </select>\r\n <span v-else>{{evt.selector}}</span>\r\n </td>\r\n <td>\r\n <select class=\"form-control form-control-sm select-event-name\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" @change=\"selectEventName\" >\r\n <template v-if=\"evt.node\">\r\n <option v-for=\"te in getNodeInEvents(evt.node)\" :value=\"te\" :selected=\"te == evt.event\" :key=\"'app-event-in-target-' + evt.node + '-' + te\">{{te}}</option>\r\n </template>\r\n <template v-else>\r\n <option value=\"hide\">hide</option>\r\n <option value=\"show\">show</option>\r\n </template>\r\n </select>\r\n </td>\r\n <td style=\"min-width: 58px;\">\r\n <button class=\"btn btn-secondary btn-editor-xs\" :data-event=\"key\" :data-index=\"index\" @click=\"toggleAdvancedAppEventSettings\" style=\"margin-left: 10px;\" title=\"Toggle advanced event settings\" >\r\n <i class=\"fas fa-cog\"></i>\r\n </button>\r\n <button class=\"btn btn-danger btn-editor-xs\" :data-event=\"key\" :data-index=\"index\" @click=\"removeInEvent\" >\r\n <i class=\"fas fa-minus\"></i>\r\n </button>\r\n </td>\r\n </tr>\r\n <tr v-if=\"evt.if || expanded[key+'##'+index]\" class=\"tr-event-condition\">\r\n <td colspan=\"3\">\r\n <span style=\"width: 60px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Occur if:</span>\r\n\r\n <input style=\"max-width: 340px; width: 340px;\" class=\"form-control form-control-sm event-if d-inline-block\" type=\"text\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" :value=\"evt.if\" @change=\"setEventIf\" />\r\n </td>\r\n </tr>\r\n <tr v-if=\"evt.data || evt.datatype || expanded[key+'##'+index]\" class=\"tr-event-data\" colspan=\"3\">\r\n <td colspan=\"3\">\r\n <span style=\"width: 53px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Data:</span>\r\n <span style=\"width: 350px;\">\r\n <display-type :type=\"getDataType(evt)\" @edited=\"onEditEventInDataType(key, index, $event)\"></display-type>\r\n <display-value :v=\"evt.data\" :type=\"getDataType(evt)\" cssWidth=\"auto\" @edited=\"onEditEventInData(key, index, $event)\"></display-value>\r\n </span>\r\n </td>\r\n </tr>\r\n </template>\r\n <tr>\r\n <td colspan=\"5\" style=\"padding-top: 0px; padding-bottom: 0px;\">\r\n <button class=\"btn btn-secondary btn-sm btn-add-subevent\" style=\"width: 100%;\" @click=\"addSubEvent(key)\">Add a subevent</button>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n <h5 class=\"mt-3\" style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Callback</h5>\r\n\r\n <table class=\"table-desc table-striped\" style=\"font-size: 12px!important;\">\r\n <thead class=\"thead-dark\">\r\n <th>Target</th>\r\n <th>Event</th>\r\n <th>Action</th>\r\n </thead>\r\n <tbody>\r\n <tr v-if=\"app.getEventOut(key) !== undefined\">\r\n <td>\r\n <select class=\"form-control form-control-sm select-event-target select-callback-target\" dualbox-target=\"events-out\" @change=\"setCallback(key)\">\r\n <option v-for=\"node in getNodesWithOutEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()===app.getEventOut(key).node\" :key=\"'app-event-out-target-' + node.getGraphId()\">{{ node.getGraphId() }}</option>\r\n </select>\r\n </td>\r\n <td>\r\n <select class=\"form-control form-control-sm select-event-name select-callback-event\" dualbox-target=\"events-out\">\r\n <template v-if=\"app.getEventOut(key).node\" @change=\"setCallback(key)\">\r\n <option v-for=\"(te, index) in getNodeOutEvents(app.getEventOut(key).node)\" :value=\"te\" :selected=\"te == app.getEventOut(key).event\" :key=\"'app-event-out-' + index\">{{te}}</option>\r\n </template>\r\n </select>\r\n </td>\r\n <td>\r\n <button class=\"btn btn-danger btn-editor-xs btn-remove-out-event\" :data-event=\"key\" @click=\"removeOutEvent\">\r\n <i class=\"fa fa-minus\"></i>\r\n </button>\r\n </td>\r\n </tr>\r\n <tr v-else>\r\n <td colspan=\"3\" style=\"padding-top: 0px; padding-bottom: 0px;\">\r\n <button class=\"btn btn-sm btn-add-callback\" style=\"width: 100%;\" @click=\"addCallback(key)\">Add a callback</button>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"modal edit-value-modal\" tabindex=\"-1\" role=\"dialog\">\r\n <div class=\"modal-dialog\" role=\"document\">\r\n <div class=\"modal-content\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title\">Edit value</h5>\r\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div>\r\n <div class=\"form-check\">\r\n <input type=\"radio\" class=\"form-check-input set-value unset-value\" id=\"unset-value\" name=\"set-value\" value=\"unset-value\" checked>\r\n <label class=\"form-check-label\" for=\"unset-value\">\r\n don't set a value\r\n </label>\r\n </div>\r\n <div class=\"form-check\">\r\n <input type=\"radio\" class=\"form-check-input set-value set-value-null\" id=\"set-value-null\" name=\"set-value\" value=\"set-value-null\">\r\n <label class=\"form-check-label\" for=\"set-value-null\">\r\n set null\r\n </label>\r\n </div>\r\n <div class=\"form-check\">\r\n <input type=\"radio\" class=\"form-check-input set-value set-value-type\" id=\"set-value-type\" name=\"set-value\" value=\"set-value-type\" aria-label=\"Set a value of type\">\r\n <div class=\"form-inline form-check-label\" style=\"height: 24px;\">\r\n <label for=\"set-value-type\">\r\n set a value of type:\r\n <select class=\"form-control choose-value-type d-inline-block form-control-sm ml-2\">\r\n <option value=\"string\">String</option>\r\n <option value=\"number\">Number</option>\r\n <option value=\"boolean\">Boolean</option>\r\n <option value=\"object\">Object</option>\r\n </select>\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"has-value\" style=\"display: none;\">\r\n <hr/>\r\n <div class=\"define-value define-boolean\" style=\"display: none;\">\r\n <div class=\"form-inline\">\r\n <label>Value: </label>\r\n <select class=\"form-control form-control-sm bool-value d-inline-block ml-2\">\r\n <option value=true>True</option>\r\n <option value=false>False</option>\r\n </select>\r\n </div>\r\n </div>\r\n <div class=\"define-value define-number\" style=\"display: none;\">\r\n <div class=\"form-inline\">\r\n <label>Value: </label>\r\n <input type=\"number\" class=\"form-control form-control-sm number-value ml-2\"/>\r\n </div>\r\n </div>\r\n <div class=\"define-value define-string\" style=\"display: none;\">\r\n <div class=\"form-inline\">\r\n <label>Value: </label>\r\n <input type=\"text\" class=\"form-control form-control-sm text-value ml-2\"/>\r\n </div>\r\n </div>\r\n <div class=\"define-value define-object\" style=\"display: none;\">\r\n <label>Value: </label>\r\n <div class=\"json-editor\" style=\"height: 400px;\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-primary btn-save\">Save changes</button>\r\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n</template>\r\n\r\n<script>\r\nimport _ from 'lodash-es';\r\nimport swal from 'sweetalert2';\r\nimport DisplayTypeVue from './displayType.vue';\r\nimport DisplayValueVue from './displayValue.vue';\r\n\r\nexport default {\r\n props: [\r\n \"app\"\r\n ],\r\n components: {\r\n \"display-type\" : DisplayTypeVue,\r\n \"display-value\" : DisplayValueVue,\r\n },\r\n data: function () {\r\n return {\r\n expanded: {} // expanded app events (advanced settings)\r\n };\r\n },\r\n created: function() {\r\n this.view = window.dualboxEditor.v;\r\n },\r\n mounted: function() {\r\n // bind tooltips\r\n $(this.$el).find('button[data-toggle=\"tooltip\"]').tooltip();\r\n this.fixMaxHeightForCategories();\r\n },\r\n updated: function() {\r\n this.fixMaxHeightForCategories();\r\n },\r\n methods: {\r\n // setup a max height for each menu, so a scroll appears if there's too much item in it\r\n fixMaxHeightForCategories : function() {\r\n let nbActiveCategories = $(this.$el).find('.edit-body > .card').length;\r\n let headerHeight = $(this.$el).find('.edit-body > .card > .card-header').outerHeight();\r\n let panelHeight = $(this.$el).height() - $(this.$el).find('.edit-main-presentation').outerHeight();\r\n let maxCategoryHeight = panelHeight - nbActiveCategories * headerHeight;\r\n $(this.$el).find('.edit-body').css('height', panelHeight);\r\n $(this.$el).find('.edit-body > .card > .collapse > .card-body').css('max-height', maxCategoryHeight + \"px\");\r\n },\r\n\r\n onEdited: function() {\r\n this.view.repaint();\r\n },\r\n\r\n getNodesWithInEvents: function() {\r\n var l = [];\r\n var nodes = this.view.m.getNodes(\"ui\");\r\n _.each(nodes, (n) => {\r\n if( n.getInEventsNames().length > 0 ) {\r\n l.push(n);\r\n }\r\n });\r\n return l;\r\n },\r\n\r\n getNodesWithOutEvents: function() {\r\n var l = [];\r\n var nodes = this.view.m.getNodes(\"ui\");\r\n _.each(nodes, (n) => {\r\n if( n.getOutEventsNames().length > 0 ) {\r\n l.push(n);\r\n }\r\n });\r\n return l;\r\n },\r\n\r\n getNodeEvents: function( nodeId ) {\r\n var node = this.view.m.getNode(nodeId);\r\n return node.getEventsNames();\r\n },\r\n\r\n getNodeInEvents: function( nodeId ) {\r\n var node = this.view.m.getNode(nodeId);\r\n return node.getInEventsNames();\r\n },\r\n\r\n getNodeOutEvents: function( nodeId ) {\r\n var node = this.view.m.getNode(nodeId);\r\n return node.getOutEventsNames();\r\n },\r\n\r\n editAppDescription: function() {\r\n swal({\r\n input: 'text',\r\n title: 'Enter the description',\r\n }).then((result) => {\r\n this.view.c.setAppDescription(result.value);\r\n });\r\n },\r\n\r\n editEventDescription: function(e) {\r\n var eventName = $(e.target).attr('data-event');\r\n\r\n swal({\r\n input: 'text',\r\n title: 'Enter the description',\r\n }).then((result) => {\r\n this.view.c.setAppEventDescription(eventName, result.value);\r\n });\r\n },\r\n\r\n removeAppEvent: function(e) {\r\n var name = $(e.target).attr('data-event');\r\n this.view.c.removeAppEvent(name);\r\n this.onEdited();\r\n },\r\n\r\n renameAppEvent: function(e) {\r\n var name = $(e.target).attr('data-event');\r\n swal({\r\n input: 'text',\r\n title: 'Enter the new event name',\r\n }).then((result) => {\r\n if( result.value ) {\r\n this.view.c.renameAppEvent(name, result.value);\r\n this.onEdited();\r\n }\r\n });\r\n },\r\n\r\n setEventIf: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventIf( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val);\r\n this.onEdited();\r\n },\r\n\r\n setEventData: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventData( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val);\r\n this.onEdited();\r\n },\r\n\r\n selectEventTarget: function(e) {\r\n var target = $(e.target).val();\r\n\r\n // change options of closest .select-event-name according to this new target\r\n var targetNode = this.view.m.getNode(target);\r\n var targetEvents = targetNode.getEventsNames();\r\n var select = $(e.target).closest('tr').find('.select-event-name');\r\n select.html('');\r\n _.each(targetEvents, (eventName) => {\r\n select.append( $('<option/>', {\r\n value: eventName\r\n }).append(eventName));\r\n });\r\n\r\n var index = parseInt($(e.target).attr('data-index'));\r\n\r\n // set event target\r\n this.view.c.setEventTarget( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, target);\r\n\r\n // also set event name, to ensure we don't have a set event that doesn't exist on this node\r\n this.view.c.setEventName( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, targetEvents[0]);\r\n this.onEdited();\r\n },\r\n\r\n selectEventName: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventName( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val );\r\n this.onEdited();\r\n },\r\n\r\n addCallback: function(appEventName) {\r\n var nodesWithOutEvents = this.getNodesWithOutEvents();\r\n if( nodesWithOutEvents.length > 0 ) {\r\n var firstNode = nodesWithOutEvents[0];\r\n var firstEvent = firstNode.getOutEventsNames()[0];\r\n this.setCallback(appEventName, firstNode, firstEvent);\r\n }\r\n else {\r\n swal({\r\n title: \"You can not add an API callback here\",\r\n text: \"None of the UIs of the application does have an OUT event, usable for API callbacks\",\r\n type: \"error\"\r\n })\r\n }\r\n },\r\n\r\n setCallback: function(appEventName, e) {\r\n var targetNodeId = $(this.$el).find('.select-callback-target').val();\r\n var targetNodeEvent = $(this.$el).find('.select-callback-event').val();\r\n this.view.c.setCallback(appEventName, targetNodeId, targetNodeEvent);\r\n this.onEdited();\r\n },\r\n\r\n addAppEvent: function(e) {\r\n swal({\r\n input: 'text',\r\n title: 'Enter the event name',\r\n }).then(async (result) => {\r\n await this.view.c.addAppEvent(result.value);\r\n this.onEdited();\r\n });\r\n },\r\n\r\n removeInEvent: function(e) {\r\n var eventName = $(e.target).attr('data-event');\r\n var index = parseInt($(e.target).attr('data-index'));\r\n this.view.c.removeAppInEvent(eventName, index);\r\n this.onEdited();\r\n },\r\n\r\n removeOutEvent: function(e) {\r\n var eventName = $(e.target).attr('data-event');\r\n this.view.c.removeAppOutEvent(eventName);\r\n this.onEdited();\r\n },\r\n\r\n addSubEvent: function(eventName) {\r\n this.view.c.addSubEvent(eventName);\r\n this.onEdited();\r\n },\r\n\r\n getDataType: function(evt) {\r\n if( evt.datatype ) {\r\n return evt.datatype;\r\n }\r\n else if( evt.data ) {\r\n return window.DualBox.Type.detectType(evt.data);\r\n }\r\n else {\r\n return undefined;\r\n }\r\n },\r\n\r\n toggleAdvancedAppEventSettings: function(e) {\r\n var key = $(e.target).data('event');\r\n var index = $(e.target).data('index');\r\n var k=key+'##'+index;\r\n this.expanded[k] = this.expanded[k] ? false : true;\r\n this.$forceUpdate();\r\n },\r\n\r\n onEditEventInData(key, index, val) {\r\n this.view.c.setEventData( \"#application-events-in-\" + key, index, val);\r\n this.$emit('edited');\r\n },\r\n\r\n onEditEventInDataType(key, index, type) {\r\n this.view.c.setEventDataType( \"#application-events-in-\" + key, index, type);\r\n\r\n // check that the set value still match the new type\r\n // delete it otherwise\r\n var val = this.app.getEventIn(key)[index].data;\r\n try {\r\n // TODO: ensure type is already loaded (after dualbox) and remove the try/catch\r\n if( !window.DualBox.Type.check(type, val) ) {\r\n // delete data (== set undefined)\r\n this.view.c.setEventData( \"#application-events-in-\" + key, index, undefined);\r\n }\r\n }\r\n catch(e) {\r\n this.view.c.setEventData( \"#application-events-in-\" + key, index, undefined);\r\n }\r\n\r\n this.$emit('edited');\r\n },\r\n }\r\n}\r\n</script>\r\n"]}, media: undefined });
67369
67478
 
67370
67479
  };
67371
67480
  /* scoped */
@@ -67432,10 +67541,6 @@ var script$b = {
67432
67541
 
67433
67542
  // allow tooltips
67434
67543
  this.activateTooltip();
67435
-
67436
- // bind the json editor
67437
- this.editor = new _import$1($(this.$el).find('.json-editor')[0], { modes: ['tree', 'code', 'text' ]});
67438
- this.editor.set({});
67439
67544
  },
67440
67545
  beforeUpdate: function() {
67441
67546
  //console.log('[Updating] node-settings');
@@ -67457,11 +67562,6 @@ var script$b = {
67457
67562
  deactivate: function() {
67458
67563
  this.deactivateTooltip();
67459
67564
  },
67460
- destroyed: function() {
67461
- if( this.editor ) {
67462
- this.editor.destroy();
67463
- }
67464
- },
67465
67565
  methods: {
67466
67566
  fixCardStyle: function() {
67467
67567
  var card = $(this.$el).find('.module-left-signature .card');
@@ -69125,9 +69225,7 @@ var __vue_render__$b = function() {
69125
69225
  )
69126
69226
  ])
69127
69227
  : _vm._e()
69128
- ]),
69129
- _vm._v(" "),
69130
- _vm._m(15)
69228
+ ])
69131
69229
  ]
69132
69230
  )
69133
69231
  };
@@ -69388,295 +69486,6 @@ var __vue_staticRenderFns__$b = [
69388
69486
  { staticStyle: { width: "53px", display: "inline-block" } },
69389
69487
  [_c("i", { staticClass: "fas fa-caret-right" }), _vm._v(" Data:")]
69390
69488
  )
69391
- },
69392
- function() {
69393
- var _vm = this;
69394
- var _h = _vm.$createElement;
69395
- var _c = _vm._self._c || _h;
69396
- return _c(
69397
- "div",
69398
- {
69399
- staticClass: "modal edit-value-modal",
69400
- attrs: { tabindex: "-1", role: "dialog" }
69401
- },
69402
- [
69403
- _c(
69404
- "div",
69405
- { staticClass: "modal-dialog", attrs: { role: "document" } },
69406
- [
69407
- _c("div", { staticClass: "modal-content" }, [
69408
- _c("div", { staticClass: "modal-header" }, [
69409
- _c("h5", { staticClass: "modal-title" }, [
69410
- _vm._v("Edit value")
69411
- ]),
69412
- _vm._v(" "),
69413
- _c(
69414
- "button",
69415
- {
69416
- staticClass: "close",
69417
- attrs: {
69418
- type: "button",
69419
- "data-dismiss": "modal",
69420
- "aria-label": "Close"
69421
- }
69422
- },
69423
- [
69424
- _c("span", { attrs: { "aria-hidden": "true" } }, [
69425
- _vm._v("×")
69426
- ])
69427
- ]
69428
- )
69429
- ]),
69430
- _vm._v(" "),
69431
- _c("div", { staticClass: "modal-body" }, [
69432
- _c("div", { staticClass: "set-type" }, [
69433
- _c("div", { staticClass: "form-check" }, [
69434
- _c("input", {
69435
- staticClass: "form-check-input set-value unset-value",
69436
- attrs: {
69437
- type: "radio",
69438
- id: "unset-value",
69439
- name: "set-value",
69440
- value: "unset-value",
69441
- checked: ""
69442
- }
69443
- }),
69444
- _vm._v(" "),
69445
- _c(
69446
- "label",
69447
- {
69448
- staticClass: "form-check-label",
69449
- attrs: { for: "unset-value" }
69450
- },
69451
- [
69452
- _vm._v(
69453
- "\n don't set a value\n "
69454
- )
69455
- ]
69456
- )
69457
- ]),
69458
- _vm._v(" "),
69459
- _c("div", { staticClass: "form-check" }, [
69460
- _c("input", {
69461
- staticClass: "form-check-input set-value set-value-null",
69462
- attrs: {
69463
- type: "radio",
69464
- id: "set-value-null",
69465
- name: "set-value",
69466
- value: "set-value-null"
69467
- }
69468
- }),
69469
- _vm._v(" "),
69470
- _c(
69471
- "label",
69472
- {
69473
- staticClass: "form-check-label",
69474
- attrs: { for: "set-value-null" }
69475
- },
69476
- [
69477
- _vm._v(
69478
- "\n set null\n "
69479
- )
69480
- ]
69481
- )
69482
- ]),
69483
- _vm._v(" "),
69484
- _c("div", { staticClass: "form-check" }, [
69485
- _c("input", {
69486
- staticClass: "form-check-input set-value set-value-type",
69487
- attrs: {
69488
- type: "radio",
69489
- id: "set-value-type",
69490
- name: "set-value",
69491
- value: "set-value-type",
69492
- "aria-label": "Set a value of type"
69493
- }
69494
- }),
69495
- _vm._v(" "),
69496
- _c(
69497
- "div",
69498
- {
69499
- staticClass: "form-inline form-check-label",
69500
- staticStyle: { height: "24px" }
69501
- },
69502
- [
69503
- _c("label", { attrs: { for: "set-value-type" } }, [
69504
- _vm._v(
69505
- "\n set a value of type:\n "
69506
- ),
69507
- _c(
69508
- "select",
69509
- {
69510
- staticClass:
69511
- "form-control choose-value-type d-inline-block form-control-sm ml-2"
69512
- },
69513
- [
69514
- _c("option", { attrs: { value: "string" } }, [
69515
- _vm._v("String")
69516
- ]),
69517
- _vm._v(" "),
69518
- _c("option", { attrs: { value: "number" } }, [
69519
- _vm._v("Number")
69520
- ]),
69521
- _vm._v(" "),
69522
- _c("option", { attrs: { value: "boolean" } }, [
69523
- _vm._v("Boolean")
69524
- ]),
69525
- _vm._v(" "),
69526
- _c("option", { attrs: { value: "object" } }, [
69527
- _vm._v("Object")
69528
- ]),
69529
- _vm._v(" "),
69530
- _c("option", { attrs: { value: "file" } }, [
69531
- _vm._v("File")
69532
- ])
69533
- ]
69534
- )
69535
- ])
69536
- ]
69537
- )
69538
- ])
69539
- ]),
69540
- _vm._v(" "),
69541
- _c("hr", { staticClass: "separator" }),
69542
- _vm._v(" "),
69543
- _c(
69544
- "div",
69545
- {
69546
- staticClass: "has-value",
69547
- staticStyle: { display: "none" }
69548
- },
69549
- [
69550
- _c(
69551
- "div",
69552
- {
69553
- staticClass: "define-value define-boolean",
69554
- staticStyle: { display: "none" }
69555
- },
69556
- [
69557
- _c("div", { staticClass: "form-inline" }, [
69558
- _c("label", [_vm._v("Value: ")]),
69559
- _vm._v(" "),
69560
- _c(
69561
- "select",
69562
- {
69563
- staticClass:
69564
- "form-control form-control-sm bool-value d-inline-block ml-2"
69565
- },
69566
- [
69567
- _c("option", { attrs: { value: "true" } }, [
69568
- _vm._v("True")
69569
- ]),
69570
- _vm._v(" "),
69571
- _c("option", { attrs: { value: "false" } }, [
69572
- _vm._v("False")
69573
- ])
69574
- ]
69575
- )
69576
- ])
69577
- ]
69578
- ),
69579
- _vm._v(" "),
69580
- _c(
69581
- "div",
69582
- {
69583
- staticClass: "define-value define-file",
69584
- staticStyle: { display: "none" }
69585
- },
69586
- [
69587
- _c("div", { staticClass: "form-inline" }, [
69588
- _c("label", [_vm._v("File input")]),
69589
- _vm._v(" "),
69590
- _c("input", {
69591
- staticClass:
69592
- "form-control-file form-control-sm file-value",
69593
- attrs: { type: "file" }
69594
- })
69595
- ])
69596
- ]
69597
- ),
69598
- _vm._v(" "),
69599
- _c(
69600
- "div",
69601
- {
69602
- staticClass: "define-value define-number",
69603
- staticStyle: { display: "none" }
69604
- },
69605
- [
69606
- _c("div", { staticClass: "form-inline" }, [
69607
- _c("label", [_vm._v("Value: ")]),
69608
- _vm._v(" "),
69609
- _c("input", {
69610
- staticClass:
69611
- "form-control form-control-sm number-value ml-2",
69612
- attrs: { type: "number" }
69613
- })
69614
- ])
69615
- ]
69616
- ),
69617
- _vm._v(" "),
69618
- _c(
69619
- "div",
69620
- {
69621
- staticClass: "define-value define-string",
69622
- staticStyle: { display: "none" }
69623
- },
69624
- [
69625
- _c("div", { staticClass: "form-inline" }, [
69626
- _c("label", [_vm._v("Value: ")]),
69627
- _vm._v(" "),
69628
- _c("input", {
69629
- staticClass:
69630
- "form-control form-control-sm text-value ml-2",
69631
- attrs: { type: "text" }
69632
- })
69633
- ])
69634
- ]
69635
- ),
69636
- _vm._v(" "),
69637
- _c(
69638
- "div",
69639
- {
69640
- staticClass: "define-value define-object",
69641
- staticStyle: { display: "none" }
69642
- },
69643
- [
69644
- _c("label", [_vm._v("Value: ")]),
69645
- _vm._v(" "),
69646
- _c("div", {
69647
- staticClass: "json-editor",
69648
- staticStyle: { height: "400px" }
69649
- })
69650
- ]
69651
- )
69652
- ]
69653
- )
69654
- ]),
69655
- _vm._v(" "),
69656
- _c("div", { staticClass: "modal-footer" }, [
69657
- _c(
69658
- "button",
69659
- {
69660
- staticClass: "btn btn-primary btn-save",
69661
- attrs: { type: "button" }
69662
- },
69663
- [_vm._v("Save changes")]
69664
- ),
69665
- _vm._v(" "),
69666
- _c(
69667
- "button",
69668
- {
69669
- staticClass: "btn btn-secondary",
69670
- attrs: { type: "button", "data-dismiss": "modal" }
69671
- },
69672
- [_vm._v("Close")]
69673
- )
69674
- ])
69675
- ])
69676
- ]
69677
- )
69678
- ]
69679
- )
69680
69489
  }
69681
69490
  ];
69682
69491
  __vue_render__$b._withStripped = true;
@@ -69684,7 +69493,7 @@ __vue_render__$b._withStripped = true;
69684
69493
  /* style */
69685
69494
  const __vue_inject_styles__$b = function (inject) {
69686
69495
  if (!inject) return
69687
- inject("data-v-135e50fe_0", { source: "\n.edit-dualbox-node-id {\n margin-bottom: 0px;\n display: inline-block;\n width: 100%;\n}\n.edit-dualbox-node-package-name {\n font-style: italic;\n}\n.btn-edit-dualbox-node-name {\n display: inline-block;\n margin-left: 5px;\n margin-top: -10px;\n position: relative;\n top: -10px;\n vertical-align: bottom;\n}\n.module-left-description {\n padding-top: 30px;\n font-size: 12px;\n text-align: center;\n}\n.card-settings .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n overflow-y: auto;\n}\n.table-desc {\n width: 100%;\n}\n.table-desc > thead > th > td {\n margin-right: 6px;\n}\n.table-desc > tbody > tr > td {\n margin-right: 6px;\n padding-top: 8px;\n padding-bottom: 8px;\n height: 40px;\n}\n.card-header[data-toggle=\"collapse\"] {\n cursor: pointer;\n}\n.card-header[data-toggle=\"collapse\"] h5 {\n user-select: none;\n}\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\n text-decoration: none;\n}\n.dualbox-node-name, .dualbox-node-name-input {\n max-width: 400px;\n}\n.dualbox-node-name-span {\n max-width: 350px;\n}\n.dualbox-node-name-input {\n display: inline-block;\n border-radius: 4px;\n padding: 4px 8px 4px 8px;\n font-size: 20px;\n max-width: 280px;\n}\n.text-value, .number-value, .boolean-value {\n max-width: 140px;\n}\n.event-if, .event-data {\n max-width: 80px;\n}\n.select-event-target, .select-event-name, .event-if, .event-data {\n font-size: 12px;\n}\n.edit-body {\n overflow-y: hidden;\n overflow-x: hidden;\n max-height: calc(100% - 90px);\n}\n.table-events .event-rooting {\n margin-top: 10px;\n}\n.table-events thead {\n border-bottom: 1px solid #ddd;\n}\n.table-events .tr-event-condition td {\n padding-left: 10px;\n}\n.table-events .tr-event-data td {\n padding-left: 10px;\n}\n.tr-event-condition td, .tr-event-data td {\n height: 20px!important;\n}\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\n padding-top: 1px!important;\n padding-bottom: 1px!important;\n}\n.table-events tr + .event-rooting {\n /* border-top: 1px solid #ddd; */\n}\n.event-rooting td {\n padding-top: 8px!important;\n padding-bottom: 4px!important;\n}\n.event-data-type {\n font-size: 75%;\n border-radius: 5px;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-data-display {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-if {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\ni.fa, i.fas, i.far {\n pointer-events: none;\n}\n.h100 {\n height: 100%;\n}\n.card-settings > .card-header {\n padding-top: 6px;\n padding-bottom: 6px;\n padding-left: 12px;\n padding-right: 12px;\n}\n.card-settings > .card-header > h5 {\n font-size: 20px;\n}\n\n", map: {"version":3,"sources":["C:\\Users\\maxim\\Projects\\dualbox\\editor\\js\\src\\v\\templates\\editNodeSettings.vue"],"names":[],"mappings":";AACA;IACA,kBAAA;IACA,qBAAA;IACA,WAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,gBAAA;IACA,iBAAA;IACA,kBAAA;IACA,UAAA;IACA,sBAAA;AACA;AAEA;IACA,iBAAA;IACA,eAAA;IACA,kBAAA;AACA;AAEA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;AACA;AAEA;IACA,WAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;IACA,YAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,qBAAA;IACA,kBAAA;IACA,wBAAA;IACA,eAAA;IACA,gBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,kBAAA;IACA,6BAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,gCAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,oBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,gBAAA;IACA,mBAAA;IACA,kBAAA;IACA,mBAAA;AACA;AAEA;IACA,eAAA;AACA","file":"editNodeSettings.vue","sourcesContent":["<style>\r\n .edit-dualbox-node-id {\r\n margin-bottom: 0px;\r\n display: inline-block;\r\n width: 100%;\r\n }\r\n\r\n .edit-dualbox-node-package-name {\r\n font-style: italic;\r\n }\r\n\r\n .btn-edit-dualbox-node-name {\r\n display: inline-block;\r\n margin-left: 5px;\r\n margin-top: -10px;\r\n position: relative;\r\n top: -10px;\r\n vertical-align: bottom;\r\n }\r\n\r\n .module-left-description {\r\n padding-top: 30px;\r\n font-size: 12px;\r\n text-align: center;\r\n }\r\n\r\n .card-settings .card-body {\r\n font-size: 12px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n overflow-y: auto;\r\n }\r\n\r\n .table-desc {\r\n width: 100%;\r\n }\r\n\r\n .table-desc > thead > th > td {\r\n margin-right: 6px;\r\n }\r\n\r\n .table-desc > tbody > tr > td {\r\n margin-right: 6px;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n height: 40px;\r\n }\r\n\r\n .card-header[data-toggle=\"collapse\"] {\r\n cursor: pointer;\r\n }\r\n\r\n .card-header[data-toggle=\"collapse\"] h5 {\r\n user-select: none;\r\n }\r\n\r\n .card-header[data-toggle=\"collapse\"]:hover .btn-link {\r\n text-decoration: none;\r\n }\r\n\r\n .dualbox-node-name, .dualbox-node-name-input {\r\n max-width: 400px;\r\n }\r\n\r\n .dualbox-node-name-span {\r\n max-width: 350px;\r\n }\r\n\r\n .dualbox-node-name-input {\r\n display: inline-block;\r\n border-radius: 4px;\r\n padding: 4px 8px 4px 8px;\r\n font-size: 20px;\r\n max-width: 280px;\r\n }\r\n\r\n .text-value, .number-value, .boolean-value {\r\n max-width: 140px;\r\n }\r\n\r\n .event-if, .event-data {\r\n max-width: 80px;\r\n }\r\n\r\n .select-event-target, .select-event-name, .event-if, .event-data {\r\n font-size: 12px;\r\n }\r\n\r\n .edit-body {\r\n overflow-y: hidden;\r\n overflow-x: hidden;\r\n max-height: calc(100% - 90px);\r\n }\r\n\r\n .table-events .event-rooting {\r\n margin-top: 10px;\r\n }\r\n\r\n .table-events thead {\r\n border-bottom: 1px solid #ddd;\r\n }\r\n\r\n .table-events .tr-event-condition td {\r\n padding-left: 10px;\r\n }\r\n\r\n .table-events .tr-event-data td {\r\n padding-left: 10px;\r\n }\r\n\r\n .tr-event-condition td, .tr-event-data td {\r\n height: 20px!important;\r\n }\r\n\r\n .tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\r\n padding-top: 1px!important;\r\n padding-bottom: 1px!important;\r\n }\r\n\r\n .table-events tr + .event-rooting {\r\n /* border-top: 1px solid #ddd; */\r\n }\r\n\r\n .event-rooting td {\r\n padding-top: 8px!important;\r\n padding-bottom: 4px!important;\r\n }\r\n\r\n .event-data-type {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n }\r\n\r\n .event-data-display {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n }\r\n\r\n .event-if {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n }\r\n\r\n i.fa, i.fas, i.far {\r\n pointer-events: none;\r\n }\r\n\r\n .h100 {\r\n height: 100%;\r\n }\r\n\r\n .card-settings > .card-header {\r\n padding-top: 6px;\r\n padding-bottom: 6px;\r\n padding-left: 12px;\r\n padding-right: 12px;\r\n }\r\n\r\n .card-settings > .card-header > h5 {\r\n font-size: 20px;\r\n }\r\n\r\n</style>\r\n\r\n<template>\r\n <div class=\"edit-node-panel h100\" id=\"edit-node-panel\" :key=\"n.id\">\r\n <div class=\"edit-node-presentation\" style=\"padding-left: 10px; padding-top: 10px; padding-right: 10px; padding-bottom: 10px;\">\r\n <h2 class=\"edit-dualbox-node-id\">\r\n <div v-if=\"nowEditingNodeName\" class=\"dualbox-node-name-edit\">\r\n <input type=\"text\" class=\"form-control dualbox-node-name-input\" style=\"display: inline-block;\" :value=\"n.graphId\" @keypress=\"changeNodeName\" autofocus/>\r\n <button class=\"btn btn-primary btn-save-node-name-change\" :data-id=\"n.graphId\" style=\"display: inline-block;\" @click=\"saveNodeName\">Save</button>\r\n </div>\r\n <div v-else class=\"dualbox-node-name\">\r\n <span class=\"dualbox-node-name-span text-truncate d-inline-block\" @click=\"editNodeName\">{{n.graphId}}</span>\r\n </div>\r\n </h2>\r\n <p style=\"margin-bottom: 0\"><small class=\"edit-dualbox-node-package-name\">{{n.getPackageName()}}</small></p>\r\n </div>\r\n\r\n <div class=\"edit-body\">\r\n <div class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-desc\" data-toggle=\"collapse\" data-target=\"#dualbox-node-desc-collapse\" aria-expanded=\"true\" aria-controls=\"dualbox-node-desc-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Description</h5>\r\n </div>\r\n\r\n <div id=\"dualbox-node-desc-collapse\" class=\"collapse show\" aria-labelledby=\"dualbox-node-desc\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\" style=\"padding-left: 15px;\">\r\n <div class=\"module-left-signature\">\r\n <graph-node :id=\"n.id\" :example=\"true\" :pkg=\"n.getPackage()\" :n=\"createExampleNode(n)\"></graph-node>\r\n </div>\r\n <p class=\"module-left-description\">\r\n <template v-if=\"n.isInput() || n.isOutput() || n.isMetanode()\">\r\n <template v-if=\"nowEditingDescription\">\r\n <textarea class=\"edit-node-description\" rows=4 style=\"width: 100%;\" :value=\"n.getDescription()\" autofocus>\r\n </textarea>\r\n <button class=\"btn btn-success\" @click=\"setDescription\">Save</button>\r\n </template>\r\n <template v-else>\r\n <button class=\"btn btn-transparent btn-xs\" @click=\"editDescription\"><i class=\"fa fa-edit\" ></i></button>\r\n <span> {{ getDescription() }}</span>\r\n </template>\r\n </template>\r\n <span v-else>\r\n {{ n.getPackage().description || \"[No description available]\" }}\r\n </span>\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-comments\" data-toggle=\"collapse\" data-target=\"#dualbox-node-comments-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-comments-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Comments</h5>\r\n </div>\r\n <div id=\"dualbox-node-comments-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-comments\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <div style=\"padding-left: 15px; padding-right: 15px;\">\r\n <div v-if=\"nowEditingComment\" class=\"node-comment-edit\">\r\n <textarea class=\"node-comment\" rows=4 style=\"width: 100%;\" :data-id=\"n.id\" v-model=\"comment\" autofocus>\r\n </textarea>\r\n <div style=\"text-align: right; margin-top: 10px;\">\r\n <button class=\"btn btn-sm btn-secundary\" @click=\"deleteComment\">Delete</button>\r\n <button class=\"btn btn-sm btn-primary btn-save-comment\" @click=\"saveComment\">Save</button>\r\n </div>\r\n </div>\r\n <p v-else class=\"node-comment-text\">\r\n <span>{{ n.hasComment() ? n.getComment() : \"[Add a comment]\" }} </span>\r\n <button class=\"btn btn-xs btn-transparent\" @click=\"editComment\"><i class=\"fa fa-edit\"></i></button>\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Compute options -->\r\n <div v-if=\"n.isModule()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-compute-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-compute-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Compute options</h5>\r\n </div>\r\n <div id=\"dualbox-node-compute-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <div class=\"form-group\" style=\"padding-left: 20px;\">\r\n <div>\r\n <label>\r\n <input class=\"input-cache-toggle\" type=\"checkbox\" v-bind:checked=\"n.hasCacheActivated()\" @change=\"toggleCache\">\r\n <span>Cache result <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Keep the result in memory (the cache) to avoid computing this box every-time its result is required. The cache will be invalidated if an input prior to this box is changed.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button></span>\r\n </label>\r\n </div>\r\n\r\n <div v-if=\"!n.isMetanode()\">\r\n <label>\r\n <input class=\"input-worker-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:checked=\"n.isParallel()\" @change=\"toggleWorker\" />\r\n <span>Execute in a worker <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Workers are separate contexts of executions that can execute long-running tasks without blocking the browser execution. Use this for heavy computations.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button></span>\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Widget options -->\r\n <div v-if=\"n.isWidget()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-widget\" data-toggle=\"collapse\" data-target=\"#dualbox-node-widget-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-widget-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Widget Options</h5>\r\n </div>\r\n <div id=\"dualbox-node-widget-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-widget\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <span>Widget registered to: </span>\r\n <select class=\"form-control form-control-sm select-widget-registerTo\" style=\"max-width: 250px;\" @change=\"registerToWidget\">\r\n <option value=\"\">none</option>\r\n <option v-for=\"target in getSpecialUINodes()\" :key=\"'target-'+target.id\" :value=\"target.graphId\" :selected=\"n.getWidgetRegistration() == target.graphId\">{{target.id}}</option>\r\n\r\n </select>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Inputs -->\r\n <div v-if=\"n.isInput()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-default\" data-toggle=\"collapse\" data-target=\"#dualbox-node-default-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-default-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Default value</h5>\r\n </div>\r\n <div id=\"dualbox-node-default-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-default\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <span>Default value:</span>\r\n <span><display-value :v=\"n.getDefaultValue()\" :type=\"n.getType()\" @edited=\"onEditDefaultValue\"></display-value></span>\r\n </div>\r\n </div>\r\n </div>\r\n <div v-else-if=\"n.hasInputs()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-inputs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-inputs-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Inputs <small><span class=\"badge badge-secondary\">{{n.getInputsNames().length}}</span></small></h5>\r\n </div>\r\n <div id=\"dualbox-node-inputs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <table class=\"table-desc table-striped\">\r\n <thead class=\"thead-dark\">\r\n <th>Input</th>\r\n <th>Visible</th>\r\n <th>Type</th>\r\n <th>Default</th>\r\n </thead>\r\n <tbody>\r\n <tr v-for=\"key in n.getInputsNames()\" :key=\"'input-'+key\">\r\n <td>\r\n {{key}}\r\n <button v-if=\"n.hasInputDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" v-bind:title=\"n.getInputDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\r\n </td>\r\n <td>\r\n <input v-if=\"n.isInputHideable(key)\" class=\"input-visibility-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:data-input=\"key\" v-bind:checked=\"n.isInputVisible(key)\" @change=\"toggleInputVisibility\">\r\n <span v-else class=\"d-inline-block\" tabindex=\"0\" data-toggle=\"tooltip\" data-trigger=\"hover\" data-placement=\"right\" data-original-title=\"Input is not connected, and has no default value. Cannot hide it yet.\">\r\n <input class=\"input-visibility-toggle\" style=\"pointer-events: none;\" type=\"checkbox\" v-bind:checked=\"n.isInputVisible(key)\" disabled>\r\n </span>\r\n </td>\r\n <td>\r\n <!-- If there's a start, then we must edit the type -->\r\n <display-type :type=\"n.getInputType(key)\" :readonly=\"!n.isInputTemplateType(key)\" @edited=\"onEditInputType(key, $event)\"></display-type>\r\n </td>\r\n <td>\r\n <display-value :v=\"n.getInputDefaultValue(key)\" :type=\"n.getInputType(key)\" @edited=\"onEditInputDefaultValue(key, $event)\" :readonly=\"!n.isFullyDefinedInputType(key)\" :readonlyReason=\"!n.isFullyDefinedInputType(key) ? 'You must first define a full type (without *) before you can edit this value' : ''\"></display-value>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Outputs -->\r\n <div v-if=\"n.hasOutputs()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-outputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-outputs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-outputs-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Outputs <small><span class=\"badge badge-secondary\">{{n.getOutputsNames().length}}</span></small></h5>\r\n </div>\r\n <div id=\"dualbox-node-outputs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-outputs\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <table class=\"table-desc table-striped\">\r\n <thead class=\"thead-dark\">\r\n <th>Output</th>\r\n <th>Type</th>\r\n <th>Visible</th>\r\n </thead>\r\n <tbody>\r\n <tr v-for=\"key in n.getOutputsNames()\" :key=\"'output-'+key\">\r\n <td>{{key}}\r\n <button v-if=\"n.hasOutputDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" v-bind:title=\"n.getOutputDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\r\n </td>\r\n <td><display-type :type=\"n.getOutputType(key)\" @edited=\"onEditOutputType(key, $event)\"></display-type></td>\r\n <td>\r\n <input class=\"output-visibility-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:data-output=\"key\" v-bind:checked=\"n.isOutputVisible(key)\" @change=\"toggleOutputVisibility\">\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Attributes -->\r\n <div v-if=\"n.hasAttributes()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-attrs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-attrs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-attrs-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Attributes <small><span class=\"badge badge-secondary\">{{n.getAttributesNames().length}}</span></small></h5>\r\n </div>\r\n <div id=\"dualbox-node-attrs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-attrs\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <table class=\"table-desc table-striped\">\r\n <thead class=\"thead-dark\">\r\n <th>Output</th>\r\n <th>Type</th>\r\n <th>Value</th>\r\n </thead>\r\n <tbody>\r\n <tr v-for=\"key in n.getAttributesNames()\" :key=\"'attr-'+key\">\r\n <td>{{key}}\r\n <button v-if=\"n.hasAttributeDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" :title=\"n.getAttributeDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\r\n </td>\r\n <td>\r\n <!-- If there's a start, then we must edit the type -->\r\n <display-type :type=\"n.getAttributeType(key)\" :readonly=\"!n.isAttributeTemplateType(key)\" @edited=\"onEditAttributeType(key, $event)\"></display-type>\r\n </td>\r\n <td>\r\n <display-value :v=\"n.getAttributeValue(key)\" :type=\"n.getAttributeType(key)\" @edited=\"onEditAttribute(key, $event)\" :readonly=\"!n.isFullyDefinedAttributeType(key)\" :readonlyReason=\"!n.isFullyDefinedInputType(key) ? 'You must first define a full type (without *) before you can edit this value' : ''\"></display-value>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n <!-- Loops -->\r\n <div v-if=\"n.hasInputs()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-loops-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-loops-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Loops <small><span class=\"badge badge-secondary\">{{ n.hasLoop() ? \"on\" : \"off\" }}</span></small></h5>\r\n </div>\r\n <div id=\"dualbox-node-loops-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <h4>Iterators\r\n <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Iterators will break an array in input into a list of their components. The module will be computed several times, each time with one different component from every iterator input. Inputs that don't define iterators will use their current value as-is for the different computations.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\r\n </h4>\r\n <table class=\"table-desc table-striped\">\r\n <tbody>\r\n <tr v-for=\"key in n.getInputsNames()\" :key=\"'loop-iterator-'+key\">\r\n <td>{{key}}</td>\r\n <td>\r\n <input class=\"input-iterator-toggle\" type=\"checkbox\" :data-input=\"key\" :checked=\"n.hasIterator(key)\" @change=\"toggleIterator\" />\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n <h4 class=\"mt-2\">Feedback\r\n <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Feedback (during a loop) is a reinjection of an output result of one iteration into an input of the next iteration.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\r\n </h4>\r\n <table class=\"table-desc table-striped\">\r\n <tbody>\r\n <tr v-for=\"key in n.getOutputsNames()\" :key=\"'loop-feedback-'+key\">\r\n <td>{{key}}</td>\r\n <td>\r\n <select class=\"form-control form-control-sm select-output-feedback\" :data-output=\"key\" @change=\"selectOutputFeedback\">\r\n <option value=\"none\">No feedback</option>\r\n <option v-for=\"i in n.getInputsNames()\" :value=\"i\" :selected=\"n.getFeedback(key) == i\" :key=\"'loop-feedback-input-'+i\">{{i}}</option>\r\n </select>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Events -->\r\n <div v-if=\"n.isUI()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-events\" data-toggle=\"collapse\" data-target=\"#dualbox-node-events-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-events-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Events <small><span class=\"badge badge-secondary\">{{n.getOutboundEvents().length}}</span></small></h5>\r\n </div>\r\n <div id=\"dualbox-node-events-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-events\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <table class=\"table-events table-desc\" style=\"font-size: 12px!important;\">\r\n <thead class=\"thead-dark\">\r\n <th>Target</th>\r\n <th>Event</th>\r\n <th>Action</th>\r\n </thead>\r\n <tbody>\r\n <template v-if=\"n.hasOutEvents()\" v-for=\"(evt, index) in n.getOutboundEvents()\" :data-index=\"index\">\r\n <tr class=\"event-rooting\">\r\n <td>\r\n <select v-if=\"evt.node\" class=\"form-control form-control-sm select-event-target\" :data-index=\"index\"@change=\"selectEventTarget\" >\r\n <option v-for=\"node in getUINodesWithEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()==evt.node\" :key=\"node.id\">{{node.getGraphId()}}</option>\r\n </select>\r\n <span v-else>{{evt.selector}}</span>\r\n </td>\r\n <td>\r\n <select class=\"form-control form-control-sm select-event-name\" :data-index=\"index\" @change=\"selectEventName\">\r\n <template v-if=\"evt.node\">\r\n <option v-for=\"targetEvent in getTargetNodeEvents(evt.node)\" :value=\"targetEvent\" :selected=\"evt.event===targetEvent\" :key=\"targetEvent\">{{targetEvent}}</option>\r\n </template>\r\n <template v-else>\r\n <option value=\"hide\">hide</option>\r\n <option value=\"show\">show</option>\r\n </template>\r\n </select>\r\n </td>\r\n <td>\r\n <button class=\"btn btn-secondary btn-editor-xs\" :data-index=\"index\" @click=\"toggleAdvancedAppEventSettings\" style=\"margin-left: 10px;\" title=\"Toggle advanced event settings\" >\r\n <i class=\"fas fa-cog\"></i>\r\n </button>\r\n <button class=\"btn btn-danger btn-editor-xs btn-remove-event\" :data-index=\"index\" @click=\"removeEvent\">\r\n <i class=\"fa fa-minus\"></i>\r\n </button>\r\n </td>\r\n </tr>\r\n <tr v-if=\"evt.if || expanded[index]\" class=\"tr-event-condition\">\r\n <td colspan=\"3\">\r\n <span style=\"width: 60px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Occur if:</span>\r\n\r\n <input style=\"max-width: 340px; width: 340px;\" class=\"form-control form-control-sm event-if d-inline-block\" type=\"text\" dualbox-target=\"events-in\" :data-index=\"index\" :value=\"evt.if\" @change=\"setEventIf\" />\r\n </td>\r\n </tr>\r\n <tr v-if=\"evt.data || evt.datatype || expanded[index]\" class=\"tr-event-data\" colspan=\"3\">\r\n <td colspan=\"3\">\r\n <span style=\"width: 53px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Data:</span>\r\n <span style=\"width: 350px;\">\r\n <display-type :type=\"getDataType(evt)\" @edited=\"onEditEventInDataType(key, index, $event)\"></display-type>\r\n <display-value :v=\"evt.data\" :type=\"getDataType(evt)\" @edited=\"onEditEventData(key, index, $event)\"></display-value>\r\n </span>\r\n </td>\r\n </tr>\r\n </template>\r\n <tr>\r\n <td colspan=\"5\" style=\"padding-top: 0px; padding-bottom: 0px;\">\r\n <button class=\"btn btn-secondary btn-sm\" :data-id=\"n.id\" style=\"width: 100%;\" @click=\"addEvent\">Add event</button>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"modal edit-value-modal\" tabindex=\"-1\" role=\"dialog\">\r\n <div class=\"modal-dialog\" role=\"document\">\r\n <div class=\"modal-content\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title\">Edit value</h5>\r\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div class=\"set-type\">\r\n <div class=\"form-check\">\r\n <input type=\"radio\" class=\"form-check-input set-value unset-value\" id=\"unset-value\" name=\"set-value\" value=\"unset-value\" checked>\r\n <label class=\"form-check-label\" for=\"unset-value\">\r\n don't set a value\r\n </label>\r\n </div>\r\n <div class=\"form-check\">\r\n <input type=\"radio\" class=\"form-check-input set-value set-value-null\" id=\"set-value-null\" name=\"set-value\" value=\"set-value-null\">\r\n <label class=\"form-check-label\" for=\"set-value-null\">\r\n set null\r\n </label>\r\n </div>\r\n <div class=\"form-check\">\r\n <input type=\"radio\" class=\"form-check-input set-value set-value-type\" id=\"set-value-type\" name=\"set-value\" value=\"set-value-type\" aria-label=\"Set a value of type\">\r\n <div class=\"form-inline form-check-label\" style=\"height: 24px;\">\r\n <label for=\"set-value-type\">\r\n set a value of type:\r\n <select class=\"form-control choose-value-type d-inline-block form-control-sm ml-2\">\r\n <option value=\"string\">String</option>\r\n <option value=\"number\">Number</option>\r\n <option value=\"boolean\">Boolean</option>\r\n <option value=\"object\">Object</option>\r\n <option value=\"file\">File</option>\r\n </select>\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n <hr class=\"separator\"/>\r\n <div class=\"has-value\" style=\"display: none;\">\r\n <div class=\"define-value define-boolean\" style=\"display: none;\">\r\n <div class=\"form-inline\">\r\n <label>Value: </label>\r\n <select class=\"form-control form-control-sm bool-value d-inline-block ml-2\">\r\n <option value=true>True</option>\r\n <option value=false>False</option>\r\n </select>\r\n </div>\r\n </div>\r\n <div class=\"define-value define-file\" style=\"display: none;\">\r\n <div class=\"form-inline\">\r\n <label>File input</label>\r\n <input type=\"file\" class=\"form-control-file form-control-sm file-value\">\r\n </div>\r\n </div>\r\n <div class=\"define-value define-number\" style=\"display: none;\">\r\n <div class=\"form-inline\">\r\n <label>Value: </label>\r\n <input type=\"number\" class=\"form-control form-control-sm number-value ml-2\"/>\r\n </div>\r\n </div>\r\n <div class=\"define-value define-string\" style=\"display: none;\">\r\n <div class=\"form-inline\">\r\n <label>Value: </label>\r\n <input type=\"text\" class=\"form-control form-control-sm text-value ml-2\"/>\r\n </div>\r\n </div>\r\n <div class=\"define-value define-object\" style=\"display: none;\">\r\n <label>Value: </label>\r\n <div class=\"json-editor\" style=\"height: 400px;\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-primary btn-save\">Save changes</button>\r\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport _ from 'lodash-es';\r\nimport DisplayTypeVue from './displayType.vue';\r\nimport DisplayValueVue from './displayValue.vue';\r\nimport GraphNodeVue from './graphNode.vue';\r\nimport JSONEditor from '@dualbox/dualbox-lib-jsoneditor';\r\nimport swal from 'sweetalert2';\r\n\r\nexport default {\r\n props: [\r\n \"id\", // the GraphNode object\r\n ],\r\n components: {\r\n \"display-type\" : DisplayTypeVue,\r\n \"display-value\" : DisplayValueVue,\r\n \"graph-node\" : GraphNodeVue\r\n },\r\n data: function () {\r\n return {\r\n comment: null,\r\n expanded: {}, // expanded app events (advanced settings)\r\n\r\n // states\r\n isParallel: false,\r\n nowEditingComment: false,\r\n nowEditingNodeName: false,\r\n nowEditingDescription: false,\r\n };\r\n },\r\n created: function() {\r\n this.view = window.dualboxEditor.v;\r\n this.n = this.view.m.getNode(this.id);\r\n\r\n // fetch the comment for this node\r\n this.comment = this.n.hasComment() ? this.n.getComment() : \"\";\r\n this.isParallel = this.n.isParallel();\r\n },\r\n mounted: function() {\r\n // adapt the style of the example graph node\r\n // remove the \"position: absolute;\" that messes up the display\r\n this.fixCardStyle();\r\n this.fixMaxHeightForCategories();\r\n\r\n // allow tooltips\r\n this.activateTooltip();\r\n\r\n // bind the json editor\r\n this.editor = new JSONEditor($(this.$el).find('.json-editor')[0], { modes: ['tree', 'code', 'text' ]});\r\n this.editor.set({});\r\n },\r\n beforeUpdate: function() {\r\n //console.log('[Updating] node-settings');\r\n // we need to refresh our node object\r\n this.n = this.view.m.getNode(this.id); // it breaks updating node name\r\n this.deactivateTooltip();\r\n },\r\n updated: function() {\r\n //console.log('[Updated] node-settings');\r\n this.fixCardStyle();\r\n this.fixMaxHeightForCategories();\r\n this.activateTooltip();\r\n this.focus();\r\n },\r\n activate: function() {\r\n this.activateTooltip();\r\n this.focus();\r\n },\r\n deactivate: function() {\r\n this.deactivateTooltip();\r\n },\r\n destroyed: function() {\r\n if( this.editor ) {\r\n this.editor.destroy();\r\n }\r\n },\r\n methods: {\r\n fixCardStyle: function() {\r\n var card = $(this.$el).find('.module-left-signature .card');\r\n card.css('position', 'static').css('point-events', 'none');\r\n card.find('.point').css(\"visibibility\", \"visible\").find('svg').css(\"visibibility\", \"visible\");\r\n card.ready(() => {\r\n var width = Math.max(\r\n card.find('.inputs').width() + card.find('.outputs').width() + 20,\r\n card.find('.title').width() + 60,\r\n card.find('.subtitle').width() + 40\r\n );\r\n card.css('width', width + 'px');\r\n card.addClass('mx-auto');\r\n });\r\n },\r\n\r\n // setup a max height for each menu, so a scroll appears if there's too much item in it\r\n fixMaxHeightForCategories : function() {\r\n let nbActiveCategories = $(this.$el).find('.edit-body > .card-settings').length;\r\n let headerHeight = $(this.$el).find('.edit-body > .card-settings > .card-header').outerHeight();\r\n let panelHeight = $(this.$el).height() - $(this.$el).find('.edit-node-presentation').outerHeight();\r\n let maxCategoryHeight = panelHeight - nbActiveCategories * headerHeight;\r\n $(this.$el).find('.edit-body').css('height', panelHeight);\r\n $(this.$el).find('.edit-body > .card-settings > .collapse > .card-body').css('max-height', maxCategoryHeight + \"px\");\r\n },\r\n\r\n activateTooltip: function() {\r\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip();\r\n },\r\n\r\n deactivateTooltip: function() {\r\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip(\"dispose\");\r\n },\r\n\r\n focus: function() {\r\n $(this.$el).find('[autofocus]').focus();\r\n },\r\n\r\n // for widget registration\r\n getSpecialUINodes: function() {\r\n var targets = this.n.m.getSpecialUINodes( this.n.getRegisterType() );\r\n return targets;\r\n },\r\n\r\n getUINodesWithEvents : function() {\r\n var nodes = this.n.m.getNodes(\"ui\");\r\n var eventNodes = nodes.filter( function(n) {\r\n return n.getEventsNames().length > 0;\r\n });\r\n return eventNodes;\r\n },\r\n\r\n getTargetNodeEvents: function(nodeId) {\r\n var targetNode = this.n.m.getNode(nodeId);\r\n return targetNode.getEventsNames();\r\n },\r\n\r\n editComment: function(e) {\r\n this.nowEditingComment = true;\r\n },\r\n\r\n saveComment: function(e) {\r\n var val = $(this.$el).find('.node-comment').val();\r\n this.view.c.setComment(this.n.id, val);\r\n this.nowEditingComment = false;\r\n this.onEdited();\r\n },\r\n\r\n deleteComment: function(e) {\r\n this.view.c.deleteComment(this.n.id);\r\n this.nowEditingComment = false;\r\n this.onEdited();\r\n },\r\n\r\n addEvent: function(e) {\r\n this.view.c.addEvent(this.n.id);\r\n this.onEdited();\r\n },\r\n\r\n toggleInputVisibility: function(e) {\r\n var inputName = $(e.target).data('input');\r\n var visible = $(e.target).is(\":checked\");\r\n if( !this.view.c.setInputVisibility(this.n.id, inputName, visible) ) {\r\n // failed, reset this to old value\r\n $(e.target).prop('checked', !visible);\r\n }\r\n },\r\n\r\n toggleOutputVisibility: function(e) {\r\n var outputName = $(e.target).data('output');\r\n var visible = $(e.target).is(\":checked\");\r\n if( !this.view.c.setOutputVisibility(this.n.id, outputName, visible) ) {\r\n // failed, reset this to old value\r\n $(e.target).prop('checked', !visible);\r\n }\r\n },\r\n\r\n editNodeName: function(e) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.nowEditingNodeName = true;\r\n },\r\n\r\n changeNodeName: function(e) {\r\n // user pressed enter\r\n if(e.which == 13 || e.keyCode == 13) {\r\n this.saveNodeName(e);\r\n }\r\n },\r\n\r\n saveNodeName: function(e) {\r\n var newId = $(e.target).parent().find('.dualbox-node-name-input').val();\r\n this.view.c.renameBox(this.n.graphId, newId, this.n.type);\r\n\r\n // get the new node\r\n switch( this.n.type ) {\r\n case \"input\": this.n = this.view.m.getNode(\"in-\"+newId); break;\r\n case \"output\": this.n = this.view.m.getNode(\"in-\"+newId); break;\r\n default: this.n = this.view.m.getNode(newId);\r\n }\r\n\r\n this.nowEditingNodeName = false;\r\n },\r\n\r\n toggleIterator: function(e) {\r\n var destInput = $(e.target).attr('data-input');\r\n if( $(e.target).is(\":checked\") ) {\r\n this.view.c.setIterator( this.n.id, destInput );\r\n }\r\n else {\r\n this.view.c.unsetIterator( this.n.id, destInput );\r\n }\r\n this.onEdited();\r\n },\r\n\r\n registerToWidget: function(e) {\r\n var targetId = $(e.target).val();\r\n this.view.c.registerWidget(this.n.id, targetId);\r\n },\r\n\r\n selectOutputFeedback: function(e) {\r\n var val = $(e.target).val();\r\n var destOutput = $(e.target).attr('data-output');\r\n if( val !== \"none\" ) {\r\n this.view.c.setFeedback( this.n.id, destOutput, val );\r\n }\r\n else {\r\n this.view.c.unsetFeedback( this.n.id, destOutput );\r\n }\r\n },\r\n\r\n removeEvent: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n this.view.c.removeEvent( this.n.id, index );\r\n this.$forceUpdate();\r\n },\r\n\r\n setEventIf: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventIf( this.n.id, index, val );\r\n },\r\n\r\n setEventData: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventData( this.n.id, index, val );\r\n },\r\n\r\n // TODO: remake this into it's own vue\r\n selectEventTarget: function(e) {\r\n var target = $(e.target).val();\r\n\r\n // change options of closest .select-event-name according to this new target\r\n var targetNode = this.view.m.getNode(target);\r\n var targetEvents = targetNode.getEventsNames();\r\n\r\n var index = parseInt($(e.target).attr('data-index'));\r\n this.view.c.setEventTarget( this.n.id, index, target );\r\n this.onEdited();\r\n },\r\n\r\n selectEventName: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventName( this.n.id, index, val );\r\n this.onEdited();\r\n },\r\n\r\n toggleCache: function(e) {\r\n var val = $(e.target).is(':checked');\r\n this.view.c.setBoxCache( this.n.id, val );\r\n },\r\n\r\n toggleWorker: function(e) {\r\n var val = $(e.target).is(':checked');\r\n this.view.c.setBoxParallel( this.n.id, val );\r\n this.isParallel = val;\r\n this.onEdited();\r\n },\r\n\r\n editModuleDescription: function(e) {\r\n var desc = $(e.target).attr('data-desc');\r\n\r\n swal({\r\n title: \"Describe what this metabox does\",\r\n input: \"textarea\",\r\n inputValue: desc || \"\",\r\n showCancelButton: true,\r\n closeOnConfirm: false,\r\n showLoaderOnConfirm: true,\r\n animation: \"slide-from-top\",\r\n inputPlaceholder: \"This metabox...\"\r\n }).then( (result) => {\r\n if (result.value === \"\") {\r\n swal.showInputError(\"You need to write something!\");\r\n return false;\r\n }\r\n else {\r\n this.view.c.setMetanodeDescription(this.n.id, result.value);\r\n }\r\n });\r\n },\r\n\r\n createExampleNode(n) {\r\n return this.view.m.createCloneNode(n.getPackage().name, n.id)\r\n },\r\n\r\n onEditInputType(inputName, typeStr) {\r\n this.n.assignInputType(inputName, typeStr);\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEditOutputType(outputName, typeStr) {\r\n this.n.assignOutputType(outputName, typeStr);\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEditAttributeType(attributeName, typeStr) {\r\n this.n.assignAttributeType(attributeName, typeStr);\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEditDefaultValue(val) {\r\n this.n.setDefaultValue(val);\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEditInputDefaultValue(inputName, val) {\r\n if( val === undefined ) {\r\n this.n.deleteVal(\"input\", inputName);\r\n this.n.setInputVisibility(inputName, true); // show the input then (connection needed)\r\n }\r\n else {\r\n this.n.val(\"input\", inputName, val );\r\n this.n.setInputVisibility(inputName, false); // hide inputs with values (no connection needed)\r\n }\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEditAttribute(attrName, val) {\r\n if( val === undefined ) {\r\n this.n.deleteVal(\"attr\", attrName);\r\n }\r\n else {\r\n this.n.val(\"attr\", attrName, val);\r\n }\r\n this.onEdited();\r\n },\r\n\r\n onEditDefaultInput(inputName, val) {\r\n if( val === undefined ) {\r\n this.n.deleteVal(\"input\", inputName);\r\n }\r\n else {\r\n this.n.val(\"input\", inputName, val);\r\n }\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEdited() {\r\n // we need to refresh our node object\r\n this.n = this.view.m.getNode(this.id); // it breaks updating node name\r\n this.$forceUpdate();\r\n },\r\n\r\n getDataType: function(evt) {\r\n if( evt.datatype ) {\r\n return evt.datatype;\r\n }\r\n else if( evt.data ) {\r\n return window.DualBox.Type.detectType(evt.data);\r\n }\r\n else {\r\n return undefined;\r\n }\r\n },\r\n\r\n toggleAdvancedAppEventSettings: function(e) {\r\n var index = $(e.target).data('index');\r\n this.expanded[index] = this.expanded[index] ? false : true;\r\n this.$forceUpdate();\r\n },\r\n\r\n onEditEventData(key, index, val) {\r\n this.view.c.setEventData( this.n.id, index, val );\r\n this.$forceUpdate();\r\n },\r\n\r\n onEditEventInDataType(key, index, type) {\r\n this.view.c.setEventDataType( this.n.id, index, type);\r\n\r\n // check that the set value still match the new type\r\n // delete it otherwise\r\n var val = this.n.getOutboundEvents()[index].data;\r\n try {\r\n // TODO: ensure type is already loaded (after dualbox) and remove the try/catch\r\n if( !window.DualBox.Type.check(type, val) ) {\r\n // delete data (== set undefined)\r\n this.view.c.setEventData( this.n.id, index, undefined);\r\n }\r\n }\r\n catch(e) {\r\n this.view.c.setEventData( this.n.id, index, undefined);\r\n }\r\n\r\n this.$forceUpdate();\r\n },\r\n\r\n getDescription() {\r\n return this.n.getDescription() || \"[Add a description]\"\r\n },\r\n\r\n editDescription() {\r\n this.nowEditingDescription = true;\r\n },\r\n\r\n setDescription() {\r\n var val = $(this.$el).find('.edit-node-description').val();\r\n if( this.n.isInput() ) {\r\n this.view.c.setInputDescription(this.n.graphId, val);\r\n }\r\n else if( this.n.isOutput() ) {\r\n this.view.c.setOutputDescription(this.n.graphId, val);\r\n }\r\n else if( this.n.isMetanode() ) {\r\n this.view.c.setMetanodeDescription(this.n.graphId, val);\r\n }\r\n this.nowEditingDescription = false;\r\n\r\n this.$forceUpdate();\r\n },\r\n }\r\n}\r\n\r\n\r\n</script>\r\n"]}, media: undefined });
69496
+ inject("data-v-560c5170_0", { source: "\n.edit-dualbox-node-id {\n margin-bottom: 0px;\n display: inline-block;\n width: 100%;\n}\n.edit-dualbox-node-package-name {\n font-style: italic;\n}\n.btn-edit-dualbox-node-name {\n display: inline-block;\n margin-left: 5px;\n margin-top: -10px;\n position: relative;\n top: -10px;\n vertical-align: bottom;\n}\n.module-left-description {\n padding-top: 30px;\n font-size: 12px;\n text-align: center;\n}\n.card-settings .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n overflow-y: auto;\n}\n.table-desc {\n width: 100%;\n}\n.table-desc > thead > th > td {\n margin-right: 6px;\n}\n.table-desc > tbody > tr > td {\n margin-right: 6px;\n padding-top: 8px;\n padding-bottom: 8px;\n height: 40px;\n}\n.card-header[data-toggle=\"collapse\"] {\n cursor: pointer;\n}\n.card-header[data-toggle=\"collapse\"] h5 {\n user-select: none;\n}\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\n text-decoration: none;\n}\n.dualbox-node-name, .dualbox-node-name-input {\n max-width: 400px;\n}\n.dualbox-node-name-span {\n max-width: 350px;\n}\n.dualbox-node-name-input {\n display: inline-block;\n border-radius: 4px;\n padding: 4px 8px 4px 8px;\n font-size: 20px;\n max-width: 280px;\n}\n.text-value, .number-value, .boolean-value {\n max-width: 140px;\n}\n.event-if, .event-data {\n max-width: 80px;\n}\n.select-event-target, .select-event-name, .event-if, .event-data {\n font-size: 12px;\n}\n.edit-body {\n overflow-y: hidden;\n overflow-x: hidden;\n max-height: calc(100% - 90px);\n}\n.table-events .event-rooting {\n margin-top: 10px;\n}\n.table-events thead {\n border-bottom: 1px solid #ddd;\n}\n.table-events .tr-event-condition td {\n padding-left: 10px;\n}\n.table-events .tr-event-data td {\n padding-left: 10px;\n}\n.tr-event-condition td, .tr-event-data td {\n height: 20px!important;\n}\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\n padding-top: 1px!important;\n padding-bottom: 1px!important;\n}\n.table-events tr + .event-rooting {\n /* border-top: 1px solid #ddd; */\n}\n.event-rooting td {\n padding-top: 8px!important;\n padding-bottom: 4px!important;\n}\n.event-data-type {\n font-size: 75%;\n border-radius: 5px;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-data-display {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-if {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\ni.fa, i.fas, i.far {\n pointer-events: none;\n}\n.h100 {\n height: 100%;\n}\n.card-settings > .card-header {\n padding-top: 6px;\n padding-bottom: 6px;\n padding-left: 12px;\n padding-right: 12px;\n}\n.card-settings > .card-header > h5 {\n font-size: 20px;\n}\n\n", map: {"version":3,"sources":["C:\\Users\\maxim\\Projects\\dualbox\\editor\\js\\src\\v\\templates\\editNodeSettings.vue"],"names":[],"mappings":";AACA;IACA,kBAAA;IACA,qBAAA;IACA,WAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,gBAAA;IACA,iBAAA;IACA,kBAAA;IACA,UAAA;IACA,sBAAA;AACA;AAEA;IACA,iBAAA;IACA,eAAA;IACA,kBAAA;AACA;AAEA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;AACA;AAEA;IACA,WAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;IACA,YAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,qBAAA;IACA,kBAAA;IACA,wBAAA;IACA,eAAA;IACA,gBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,kBAAA;IACA,6BAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,gCAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,oBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,gBAAA;IACA,mBAAA;IACA,kBAAA;IACA,mBAAA;AACA;AAEA;IACA,eAAA;AACA","file":"editNodeSettings.vue","sourcesContent":["<style>\r\n .edit-dualbox-node-id {\r\n margin-bottom: 0px;\r\n display: inline-block;\r\n width: 100%;\r\n }\r\n\r\n .edit-dualbox-node-package-name {\r\n font-style: italic;\r\n }\r\n\r\n .btn-edit-dualbox-node-name {\r\n display: inline-block;\r\n margin-left: 5px;\r\n margin-top: -10px;\r\n position: relative;\r\n top: -10px;\r\n vertical-align: bottom;\r\n }\r\n\r\n .module-left-description {\r\n padding-top: 30px;\r\n font-size: 12px;\r\n text-align: center;\r\n }\r\n\r\n .card-settings .card-body {\r\n font-size: 12px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n overflow-y: auto;\r\n }\r\n\r\n .table-desc {\r\n width: 100%;\r\n }\r\n\r\n .table-desc > thead > th > td {\r\n margin-right: 6px;\r\n }\r\n\r\n .table-desc > tbody > tr > td {\r\n margin-right: 6px;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n height: 40px;\r\n }\r\n\r\n .card-header[data-toggle=\"collapse\"] {\r\n cursor: pointer;\r\n }\r\n\r\n .card-header[data-toggle=\"collapse\"] h5 {\r\n user-select: none;\r\n }\r\n\r\n .card-header[data-toggle=\"collapse\"]:hover .btn-link {\r\n text-decoration: none;\r\n }\r\n\r\n .dualbox-node-name, .dualbox-node-name-input {\r\n max-width: 400px;\r\n }\r\n\r\n .dualbox-node-name-span {\r\n max-width: 350px;\r\n }\r\n\r\n .dualbox-node-name-input {\r\n display: inline-block;\r\n border-radius: 4px;\r\n padding: 4px 8px 4px 8px;\r\n font-size: 20px;\r\n max-width: 280px;\r\n }\r\n\r\n .text-value, .number-value, .boolean-value {\r\n max-width: 140px;\r\n }\r\n\r\n .event-if, .event-data {\r\n max-width: 80px;\r\n }\r\n\r\n .select-event-target, .select-event-name, .event-if, .event-data {\r\n font-size: 12px;\r\n }\r\n\r\n .edit-body {\r\n overflow-y: hidden;\r\n overflow-x: hidden;\r\n max-height: calc(100% - 90px);\r\n }\r\n\r\n .table-events .event-rooting {\r\n margin-top: 10px;\r\n }\r\n\r\n .table-events thead {\r\n border-bottom: 1px solid #ddd;\r\n }\r\n\r\n .table-events .tr-event-condition td {\r\n padding-left: 10px;\r\n }\r\n\r\n .table-events .tr-event-data td {\r\n padding-left: 10px;\r\n }\r\n\r\n .tr-event-condition td, .tr-event-data td {\r\n height: 20px!important;\r\n }\r\n\r\n .tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\r\n padding-top: 1px!important;\r\n padding-bottom: 1px!important;\r\n }\r\n\r\n .table-events tr + .event-rooting {\r\n /* border-top: 1px solid #ddd; */\r\n }\r\n\r\n .event-rooting td {\r\n padding-top: 8px!important;\r\n padding-bottom: 4px!important;\r\n }\r\n\r\n .event-data-type {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n }\r\n\r\n .event-data-display {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n }\r\n\r\n .event-if {\r\n font-size: 75%;\r\n border-radius: 5px;\r\n border: 1px solid #ddd;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n padding-top: 2px;\r\n padding-bottom: 2px;\r\n }\r\n\r\n i.fa, i.fas, i.far {\r\n pointer-events: none;\r\n }\r\n\r\n .h100 {\r\n height: 100%;\r\n }\r\n\r\n .card-settings > .card-header {\r\n padding-top: 6px;\r\n padding-bottom: 6px;\r\n padding-left: 12px;\r\n padding-right: 12px;\r\n }\r\n\r\n .card-settings > .card-header > h5 {\r\n font-size: 20px;\r\n }\r\n\r\n</style>\r\n\r\n<template>\r\n <div class=\"edit-node-panel h100\" id=\"edit-node-panel\" :key=\"n.id\">\r\n <div class=\"edit-node-presentation\" style=\"padding-left: 10px; padding-top: 10px; padding-right: 10px; padding-bottom: 10px;\">\r\n <h2 class=\"edit-dualbox-node-id\">\r\n <div v-if=\"nowEditingNodeName\" class=\"dualbox-node-name-edit\">\r\n <input type=\"text\" class=\"form-control dualbox-node-name-input\" style=\"display: inline-block;\" :value=\"n.graphId\" @keypress=\"changeNodeName\" autofocus/>\r\n <button class=\"btn btn-primary btn-save-node-name-change\" :data-id=\"n.graphId\" style=\"display: inline-block;\" @click=\"saveNodeName\">Save</button>\r\n </div>\r\n <div v-else class=\"dualbox-node-name\">\r\n <span class=\"dualbox-node-name-span text-truncate d-inline-block\" @click=\"editNodeName\">{{n.graphId}}</span>\r\n </div>\r\n </h2>\r\n <p style=\"margin-bottom: 0\"><small class=\"edit-dualbox-node-package-name\">{{n.getPackageName()}}</small></p>\r\n </div>\r\n\r\n <div class=\"edit-body\">\r\n <div class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-desc\" data-toggle=\"collapse\" data-target=\"#dualbox-node-desc-collapse\" aria-expanded=\"true\" aria-controls=\"dualbox-node-desc-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Description</h5>\r\n </div>\r\n\r\n <div id=\"dualbox-node-desc-collapse\" class=\"collapse show\" aria-labelledby=\"dualbox-node-desc\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\" style=\"padding-left: 15px;\">\r\n <div class=\"module-left-signature\">\r\n <graph-node :id=\"n.id\" :example=\"true\" :pkg=\"n.getPackage()\" :n=\"createExampleNode(n)\"></graph-node>\r\n </div>\r\n <p class=\"module-left-description\">\r\n <template v-if=\"n.isInput() || n.isOutput() || n.isMetanode()\">\r\n <template v-if=\"nowEditingDescription\">\r\n <textarea class=\"edit-node-description\" rows=4 style=\"width: 100%;\" :value=\"n.getDescription()\" autofocus>\r\n </textarea>\r\n <button class=\"btn btn-success\" @click=\"setDescription\">Save</button>\r\n </template>\r\n <template v-else>\r\n <button class=\"btn btn-transparent btn-xs\" @click=\"editDescription\"><i class=\"fa fa-edit\" ></i></button>\r\n <span> {{ getDescription() }}</span>\r\n </template>\r\n </template>\r\n <span v-else>\r\n {{ n.getPackage().description || \"[No description available]\" }}\r\n </span>\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-comments\" data-toggle=\"collapse\" data-target=\"#dualbox-node-comments-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-comments-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Comments</h5>\r\n </div>\r\n <div id=\"dualbox-node-comments-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-comments\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <div style=\"padding-left: 15px; padding-right: 15px;\">\r\n <div v-if=\"nowEditingComment\" class=\"node-comment-edit\">\r\n <textarea class=\"node-comment\" rows=4 style=\"width: 100%;\" :data-id=\"n.id\" v-model=\"comment\" autofocus>\r\n </textarea>\r\n <div style=\"text-align: right; margin-top: 10px;\">\r\n <button class=\"btn btn-sm btn-secundary\" @click=\"deleteComment\">Delete</button>\r\n <button class=\"btn btn-sm btn-primary btn-save-comment\" @click=\"saveComment\">Save</button>\r\n </div>\r\n </div>\r\n <p v-else class=\"node-comment-text\">\r\n <span>{{ n.hasComment() ? n.getComment() : \"[Add a comment]\" }} </span>\r\n <button class=\"btn btn-xs btn-transparent\" @click=\"editComment\"><i class=\"fa fa-edit\"></i></button>\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Compute options -->\r\n <div v-if=\"n.isModule()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-compute-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-compute-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Compute options</h5>\r\n </div>\r\n <div id=\"dualbox-node-compute-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <div class=\"form-group\" style=\"padding-left: 20px;\">\r\n <div>\r\n <label>\r\n <input class=\"input-cache-toggle\" type=\"checkbox\" v-bind:checked=\"n.hasCacheActivated()\" @change=\"toggleCache\">\r\n <span>Cache result <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Keep the result in memory (the cache) to avoid computing this box every-time its result is required. The cache will be invalidated if an input prior to this box is changed.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button></span>\r\n </label>\r\n </div>\r\n\r\n <div v-if=\"!n.isMetanode()\">\r\n <label>\r\n <input class=\"input-worker-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:checked=\"n.isParallel()\" @change=\"toggleWorker\" />\r\n <span>Execute in a worker <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Workers are separate contexts of executions that can execute long-running tasks without blocking the browser execution. Use this for heavy computations.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button></span>\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Widget options -->\r\n <div v-if=\"n.isWidget()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-widget\" data-toggle=\"collapse\" data-target=\"#dualbox-node-widget-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-widget-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Widget Options</h5>\r\n </div>\r\n <div id=\"dualbox-node-widget-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-widget\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <span>Widget registered to: </span>\r\n <select class=\"form-control form-control-sm select-widget-registerTo\" style=\"max-width: 250px;\" @change=\"registerToWidget\">\r\n <option value=\"\">none</option>\r\n <option v-for=\"target in getSpecialUINodes()\" :key=\"'target-'+target.id\" :value=\"target.graphId\" :selected=\"n.getWidgetRegistration() == target.graphId\">{{target.id}}</option>\r\n\r\n </select>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Inputs -->\r\n <div v-if=\"n.isInput()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-default\" data-toggle=\"collapse\" data-target=\"#dualbox-node-default-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-default-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Default value</h5>\r\n </div>\r\n <div id=\"dualbox-node-default-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-default\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <span>Default value:</span>\r\n <span><display-value :v=\"n.getDefaultValue()\" :type=\"n.getType()\" @edited=\"onEditDefaultValue\"></display-value></span>\r\n </div>\r\n </div>\r\n </div>\r\n <div v-else-if=\"n.hasInputs()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-inputs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-inputs-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Inputs <small><span class=\"badge badge-secondary\">{{n.getInputsNames().length}}</span></small></h5>\r\n </div>\r\n <div id=\"dualbox-node-inputs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <table class=\"table-desc table-striped\">\r\n <thead class=\"thead-dark\">\r\n <th>Input</th>\r\n <th>Visible</th>\r\n <th>Type</th>\r\n <th>Default</th>\r\n </thead>\r\n <tbody>\r\n <tr v-for=\"key in n.getInputsNames()\" :key=\"'input-'+key\">\r\n <td>\r\n {{key}}\r\n <button v-if=\"n.hasInputDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" v-bind:title=\"n.getInputDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\r\n </td>\r\n <td>\r\n <input v-if=\"n.isInputHideable(key)\" class=\"input-visibility-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:data-input=\"key\" v-bind:checked=\"n.isInputVisible(key)\" @change=\"toggleInputVisibility\">\r\n <span v-else class=\"d-inline-block\" tabindex=\"0\" data-toggle=\"tooltip\" data-trigger=\"hover\" data-placement=\"right\" data-original-title=\"Input is not connected, and has no default value. Cannot hide it yet.\">\r\n <input class=\"input-visibility-toggle\" style=\"pointer-events: none;\" type=\"checkbox\" v-bind:checked=\"n.isInputVisible(key)\" disabled>\r\n </span>\r\n </td>\r\n <td>\r\n <!-- If there's a start, then we must edit the type -->\r\n <display-type :type=\"n.getInputType(key)\" :readonly=\"!n.isInputTemplateType(key)\" @edited=\"onEditInputType(key, $event)\"></display-type>\r\n </td>\r\n <td>\r\n <display-value :v=\"n.getInputDefaultValue(key)\" :type=\"n.getInputType(key)\" @edited=\"onEditInputDefaultValue(key, $event)\" :readonly=\"!n.isFullyDefinedInputType(key)\" :readonlyReason=\"!n.isFullyDefinedInputType(key) ? 'You must first define a full type (without *) before you can edit this value' : ''\"></display-value>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Outputs -->\r\n <div v-if=\"n.hasOutputs()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-outputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-outputs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-outputs-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Outputs <small><span class=\"badge badge-secondary\">{{n.getOutputsNames().length}}</span></small></h5>\r\n </div>\r\n <div id=\"dualbox-node-outputs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-outputs\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <table class=\"table-desc table-striped\">\r\n <thead class=\"thead-dark\">\r\n <th>Output</th>\r\n <th>Type</th>\r\n <th>Visible</th>\r\n </thead>\r\n <tbody>\r\n <tr v-for=\"key in n.getOutputsNames()\" :key=\"'output-'+key\">\r\n <td>{{key}}\r\n <button v-if=\"n.hasOutputDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" v-bind:title=\"n.getOutputDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\r\n </td>\r\n <td><display-type :type=\"n.getOutputType(key)\" @edited=\"onEditOutputType(key, $event)\"></display-type></td>\r\n <td>\r\n <input class=\"output-visibility-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:data-output=\"key\" v-bind:checked=\"n.isOutputVisible(key)\" @change=\"toggleOutputVisibility\">\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Attributes -->\r\n <div v-if=\"n.hasAttributes()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-attrs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-attrs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-attrs-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Attributes <small><span class=\"badge badge-secondary\">{{n.getAttributesNames().length}}</span></small></h5>\r\n </div>\r\n <div id=\"dualbox-node-attrs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-attrs\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <table class=\"table-desc table-striped\">\r\n <thead class=\"thead-dark\">\r\n <th>Output</th>\r\n <th>Type</th>\r\n <th>Value</th>\r\n </thead>\r\n <tbody>\r\n <tr v-for=\"key in n.getAttributesNames()\" :key=\"'attr-'+key\">\r\n <td>{{key}}\r\n <button v-if=\"n.hasAttributeDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" :title=\"n.getAttributeDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\r\n </td>\r\n <td>\r\n <!-- If there's a start, then we must edit the type -->\r\n <display-type :type=\"n.getAttributeType(key)\" :readonly=\"!n.isAttributeTemplateType(key)\" @edited=\"onEditAttributeType(key, $event)\"></display-type>\r\n </td>\r\n <td>\r\n <display-value :v=\"n.getAttributeValue(key)\" :type=\"n.getAttributeType(key)\" @edited=\"onEditAttribute(key, $event)\" :readonly=\"!n.isFullyDefinedAttributeType(key)\" :readonlyReason=\"!n.isFullyDefinedInputType(key) ? 'You must first define a full type (without *) before you can edit this value' : ''\"></display-value>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n <!-- Loops -->\r\n <div v-if=\"n.hasInputs()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-loops-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-loops-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Loops <small><span class=\"badge badge-secondary\">{{ n.hasLoop() ? \"on\" : \"off\" }}</span></small></h5>\r\n </div>\r\n <div id=\"dualbox-node-loops-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <h4>Iterators\r\n <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Iterators will break an array in input into a list of their components. The module will be computed several times, each time with one different component from every iterator input. Inputs that don't define iterators will use their current value as-is for the different computations.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\r\n </h4>\r\n <table class=\"table-desc table-striped\">\r\n <tbody>\r\n <tr v-for=\"key in n.getInputsNames()\" :key=\"'loop-iterator-'+key\">\r\n <td>{{key}}</td>\r\n <td>\r\n <input class=\"input-iterator-toggle\" type=\"checkbox\" :data-input=\"key\" :checked=\"n.hasIterator(key)\" @change=\"toggleIterator\" />\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n <h4 class=\"mt-2\">Feedback\r\n <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Feedback (during a loop) is a reinjection of an output result of one iteration into an input of the next iteration.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\r\n </h4>\r\n <table class=\"table-desc table-striped\">\r\n <tbody>\r\n <tr v-for=\"key in n.getOutputsNames()\" :key=\"'loop-feedback-'+key\">\r\n <td>{{key}}</td>\r\n <td>\r\n <select class=\"form-control form-control-sm select-output-feedback\" :data-output=\"key\" @change=\"selectOutputFeedback\">\r\n <option value=\"none\">No feedback</option>\r\n <option v-for=\"i in n.getInputsNames()\" :value=\"i\" :selected=\"n.getFeedback(key) == i\" :key=\"'loop-feedback-input-'+i\">{{i}}</option>\r\n </select>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Events -->\r\n <div v-if=\"n.isUI()\" class=\"card card-settings\">\r\n <div class=\"card-header\" id=\"dualbox-node-events\" data-toggle=\"collapse\" data-target=\"#dualbox-node-events-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-events-collapse\">\r\n <h5 class=\"mb-0 btn-link\">Events <small><span class=\"badge badge-secondary\">{{n.getOutboundEvents().length}}</span></small></h5>\r\n </div>\r\n <div id=\"dualbox-node-events-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-events\" data-parent=\"#edit-node-panel\">\r\n <div class=\"card-body\">\r\n <table class=\"table-events table-desc\" style=\"font-size: 12px!important;\">\r\n <thead class=\"thead-dark\">\r\n <th>Target</th>\r\n <th>Event</th>\r\n <th>Action</th>\r\n </thead>\r\n <tbody>\r\n <template v-if=\"n.hasOutEvents()\" v-for=\"(evt, index) in n.getOutboundEvents()\" :data-index=\"index\">\r\n <tr class=\"event-rooting\">\r\n <td>\r\n <select v-if=\"evt.node\" class=\"form-control form-control-sm select-event-target\" :data-index=\"index\"@change=\"selectEventTarget\" >\r\n <option v-for=\"node in getUINodesWithEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()==evt.node\" :key=\"node.id\">{{node.getGraphId()}}</option>\r\n </select>\r\n <span v-else>{{evt.selector}}</span>\r\n </td>\r\n <td>\r\n <select class=\"form-control form-control-sm select-event-name\" :data-index=\"index\" @change=\"selectEventName\">\r\n <template v-if=\"evt.node\">\r\n <option v-for=\"targetEvent in getTargetNodeEvents(evt.node)\" :value=\"targetEvent\" :selected=\"evt.event===targetEvent\" :key=\"targetEvent\">{{targetEvent}}</option>\r\n </template>\r\n <template v-else>\r\n <option value=\"hide\">hide</option>\r\n <option value=\"show\">show</option>\r\n </template>\r\n </select>\r\n </td>\r\n <td>\r\n <button class=\"btn btn-secondary btn-editor-xs\" :data-index=\"index\" @click=\"toggleAdvancedAppEventSettings\" style=\"margin-left: 10px;\" title=\"Toggle advanced event settings\" >\r\n <i class=\"fas fa-cog\"></i>\r\n </button>\r\n <button class=\"btn btn-danger btn-editor-xs btn-remove-event\" :data-index=\"index\" @click=\"removeEvent\">\r\n <i class=\"fa fa-minus\"></i>\r\n </button>\r\n </td>\r\n </tr>\r\n <tr v-if=\"evt.if || expanded[index]\" class=\"tr-event-condition\">\r\n <td colspan=\"3\">\r\n <span style=\"width: 60px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Occur if:</span>\r\n\r\n <input style=\"max-width: 340px; width: 340px;\" class=\"form-control form-control-sm event-if d-inline-block\" type=\"text\" dualbox-target=\"events-in\" :data-index=\"index\" :value=\"evt.if\" @change=\"setEventIf\" />\r\n </td>\r\n </tr>\r\n <tr v-if=\"evt.data || evt.datatype || expanded[index]\" class=\"tr-event-data\" colspan=\"3\">\r\n <td colspan=\"3\">\r\n <span style=\"width: 53px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Data:</span>\r\n <span style=\"width: 350px;\">\r\n <display-type :type=\"getDataType(evt)\" @edited=\"onEditEventInDataType(key, index, $event)\"></display-type>\r\n <display-value :v=\"evt.data\" :type=\"getDataType(evt)\" @edited=\"onEditEventData(key, index, $event)\"></display-value>\r\n </span>\r\n </td>\r\n </tr>\r\n </template>\r\n <tr>\r\n <td colspan=\"5\" style=\"padding-top: 0px; padding-bottom: 0px;\">\r\n <button class=\"btn btn-secondary btn-sm\" :data-id=\"n.id\" style=\"width: 100%;\" @click=\"addEvent\">Add event</button>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport _ from 'lodash-es';\r\nimport DisplayTypeVue from './displayType.vue';\r\nimport DisplayValueVue from './displayValue.vue';\r\nimport GraphNodeVue from './graphNode.vue';\r\nimport swal from 'sweetalert2';\r\n\r\nexport default {\r\n props: [\r\n \"id\", // the GraphNode object\r\n ],\r\n components: {\r\n \"display-type\" : DisplayTypeVue,\r\n \"display-value\" : DisplayValueVue,\r\n \"graph-node\" : GraphNodeVue\r\n },\r\n data: function () {\r\n return {\r\n comment: null,\r\n expanded: {}, // expanded app events (advanced settings)\r\n\r\n // states\r\n isParallel: false,\r\n nowEditingComment: false,\r\n nowEditingNodeName: false,\r\n nowEditingDescription: false,\r\n };\r\n },\r\n created: function() {\r\n this.view = window.dualboxEditor.v;\r\n this.n = this.view.m.getNode(this.id);\r\n\r\n // fetch the comment for this node\r\n this.comment = this.n.hasComment() ? this.n.getComment() : \"\";\r\n this.isParallel = this.n.isParallel();\r\n },\r\n mounted: function() {\r\n // adapt the style of the example graph node\r\n // remove the \"position: absolute;\" that messes up the display\r\n this.fixCardStyle();\r\n this.fixMaxHeightForCategories();\r\n\r\n // allow tooltips\r\n this.activateTooltip();\r\n },\r\n beforeUpdate: function() {\r\n //console.log('[Updating] node-settings');\r\n // we need to refresh our node object\r\n this.n = this.view.m.getNode(this.id); // it breaks updating node name\r\n this.deactivateTooltip();\r\n },\r\n updated: function() {\r\n //console.log('[Updated] node-settings');\r\n this.fixCardStyle();\r\n this.fixMaxHeightForCategories();\r\n this.activateTooltip();\r\n this.focus();\r\n },\r\n activate: function() {\r\n this.activateTooltip();\r\n this.focus();\r\n },\r\n deactivate: function() {\r\n this.deactivateTooltip();\r\n },\r\n methods: {\r\n fixCardStyle: function() {\r\n var card = $(this.$el).find('.module-left-signature .card');\r\n card.css('position', 'static').css('point-events', 'none');\r\n card.find('.point').css(\"visibibility\", \"visible\").find('svg').css(\"visibibility\", \"visible\");\r\n card.ready(() => {\r\n var width = Math.max(\r\n card.find('.inputs').width() + card.find('.outputs').width() + 20,\r\n card.find('.title').width() + 60,\r\n card.find('.subtitle').width() + 40\r\n );\r\n card.css('width', width + 'px');\r\n card.addClass('mx-auto');\r\n });\r\n },\r\n\r\n // setup a max height for each menu, so a scroll appears if there's too much item in it\r\n fixMaxHeightForCategories : function() {\r\n let nbActiveCategories = $(this.$el).find('.edit-body > .card-settings').length;\r\n let headerHeight = $(this.$el).find('.edit-body > .card-settings > .card-header').outerHeight();\r\n let panelHeight = $(this.$el).height() - $(this.$el).find('.edit-node-presentation').outerHeight();\r\n let maxCategoryHeight = panelHeight - nbActiveCategories * headerHeight;\r\n $(this.$el).find('.edit-body').css('height', panelHeight);\r\n $(this.$el).find('.edit-body > .card-settings > .collapse > .card-body').css('max-height', maxCategoryHeight + \"px\");\r\n },\r\n\r\n activateTooltip: function() {\r\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip();\r\n },\r\n\r\n deactivateTooltip: function() {\r\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip(\"dispose\");\r\n },\r\n\r\n focus: function() {\r\n $(this.$el).find('[autofocus]').focus();\r\n },\r\n\r\n // for widget registration\r\n getSpecialUINodes: function() {\r\n var targets = this.n.m.getSpecialUINodes( this.n.getRegisterType() );\r\n return targets;\r\n },\r\n\r\n getUINodesWithEvents : function() {\r\n var nodes = this.n.m.getNodes(\"ui\");\r\n var eventNodes = nodes.filter( function(n) {\r\n return n.getEventsNames().length > 0;\r\n });\r\n return eventNodes;\r\n },\r\n\r\n getTargetNodeEvents: function(nodeId) {\r\n var targetNode = this.n.m.getNode(nodeId);\r\n return targetNode.getEventsNames();\r\n },\r\n\r\n editComment: function(e) {\r\n this.nowEditingComment = true;\r\n },\r\n\r\n saveComment: function(e) {\r\n var val = $(this.$el).find('.node-comment').val();\r\n this.view.c.setComment(this.n.id, val);\r\n this.nowEditingComment = false;\r\n this.onEdited();\r\n },\r\n\r\n deleteComment: function(e) {\r\n this.view.c.deleteComment(this.n.id);\r\n this.nowEditingComment = false;\r\n this.onEdited();\r\n },\r\n\r\n addEvent: function(e) {\r\n this.view.c.addEvent(this.n.id);\r\n this.onEdited();\r\n },\r\n\r\n toggleInputVisibility: function(e) {\r\n var inputName = $(e.target).data('input');\r\n var visible = $(e.target).is(\":checked\");\r\n if( !this.view.c.setInputVisibility(this.n.id, inputName, visible) ) {\r\n // failed, reset this to old value\r\n $(e.target).prop('checked', !visible);\r\n }\r\n },\r\n\r\n toggleOutputVisibility: function(e) {\r\n var outputName = $(e.target).data('output');\r\n var visible = $(e.target).is(\":checked\");\r\n if( !this.view.c.setOutputVisibility(this.n.id, outputName, visible) ) {\r\n // failed, reset this to old value\r\n $(e.target).prop('checked', !visible);\r\n }\r\n },\r\n\r\n editNodeName: function(e) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.nowEditingNodeName = true;\r\n },\r\n\r\n changeNodeName: function(e) {\r\n // user pressed enter\r\n if(e.which == 13 || e.keyCode == 13) {\r\n this.saveNodeName(e);\r\n }\r\n },\r\n\r\n saveNodeName: function(e) {\r\n var newId = $(e.target).parent().find('.dualbox-node-name-input').val();\r\n this.view.c.renameBox(this.n.graphId, newId, this.n.type);\r\n\r\n // get the new node\r\n switch( this.n.type ) {\r\n case \"input\": this.n = this.view.m.getNode(\"in-\"+newId); break;\r\n case \"output\": this.n = this.view.m.getNode(\"in-\"+newId); break;\r\n default: this.n = this.view.m.getNode(newId);\r\n }\r\n\r\n this.nowEditingNodeName = false;\r\n },\r\n\r\n toggleIterator: function(e) {\r\n var destInput = $(e.target).attr('data-input');\r\n if( $(e.target).is(\":checked\") ) {\r\n this.view.c.setIterator( this.n.id, destInput );\r\n }\r\n else {\r\n this.view.c.unsetIterator( this.n.id, destInput );\r\n }\r\n this.onEdited();\r\n },\r\n\r\n registerToWidget: function(e) {\r\n var targetId = $(e.target).val();\r\n this.view.c.registerWidget(this.n.id, targetId);\r\n },\r\n\r\n selectOutputFeedback: function(e) {\r\n var val = $(e.target).val();\r\n var destOutput = $(e.target).attr('data-output');\r\n if( val !== \"none\" ) {\r\n this.view.c.setFeedback( this.n.id, destOutput, val );\r\n }\r\n else {\r\n this.view.c.unsetFeedback( this.n.id, destOutput );\r\n }\r\n },\r\n\r\n removeEvent: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n this.view.c.removeEvent( this.n.id, index );\r\n this.$forceUpdate();\r\n },\r\n\r\n setEventIf: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventIf( this.n.id, index, val );\r\n },\r\n\r\n setEventData: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventData( this.n.id, index, val );\r\n },\r\n\r\n // TODO: remake this into it's own vue\r\n selectEventTarget: function(e) {\r\n var target = $(e.target).val();\r\n\r\n // change options of closest .select-event-name according to this new target\r\n var targetNode = this.view.m.getNode(target);\r\n var targetEvents = targetNode.getEventsNames();\r\n\r\n var index = parseInt($(e.target).attr('data-index'));\r\n this.view.c.setEventTarget( this.n.id, index, target );\r\n this.onEdited();\r\n },\r\n\r\n selectEventName: function(e) {\r\n var index = parseInt($(e.target).attr('data-index'));\r\n var val = $(e.target).val();\r\n this.view.c.setEventName( this.n.id, index, val );\r\n this.onEdited();\r\n },\r\n\r\n toggleCache: function(e) {\r\n var val = $(e.target).is(':checked');\r\n this.view.c.setBoxCache( this.n.id, val );\r\n },\r\n\r\n toggleWorker: function(e) {\r\n var val = $(e.target).is(':checked');\r\n this.view.c.setBoxParallel( this.n.id, val );\r\n this.isParallel = val;\r\n this.onEdited();\r\n },\r\n\r\n editModuleDescription: function(e) {\r\n var desc = $(e.target).attr('data-desc');\r\n\r\n swal({\r\n title: \"Describe what this metabox does\",\r\n input: \"textarea\",\r\n inputValue: desc || \"\",\r\n showCancelButton: true,\r\n closeOnConfirm: false,\r\n showLoaderOnConfirm: true,\r\n animation: \"slide-from-top\",\r\n inputPlaceholder: \"This metabox...\"\r\n }).then( (result) => {\r\n if (result.value === \"\") {\r\n swal.showInputError(\"You need to write something!\");\r\n return false;\r\n }\r\n else {\r\n this.view.c.setMetanodeDescription(this.n.id, result.value);\r\n }\r\n });\r\n },\r\n\r\n createExampleNode(n) {\r\n return this.view.m.createCloneNode(n.getPackage().name, n.id)\r\n },\r\n\r\n onEditInputType(inputName, typeStr) {\r\n this.n.assignInputType(inputName, typeStr);\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEditOutputType(outputName, typeStr) {\r\n this.n.assignOutputType(outputName, typeStr);\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEditAttributeType(attributeName, typeStr) {\r\n this.n.assignAttributeType(attributeName, typeStr);\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEditDefaultValue(val) {\r\n this.n.setDefaultValue(val);\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEditInputDefaultValue(inputName, val) {\r\n if( val === undefined ) {\r\n this.n.deleteVal(\"input\", inputName);\r\n this.n.setInputVisibility(inputName, true); // show the input then (connection needed)\r\n }\r\n else {\r\n this.n.val(\"input\", inputName, val );\r\n this.n.setInputVisibility(inputName, false); // hide inputs with values (no connection needed)\r\n }\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEditAttribute(attrName, val) {\r\n if( val === undefined ) {\r\n this.n.deleteVal(\"attr\", attrName);\r\n }\r\n else {\r\n this.n.val(\"attr\", attrName, val);\r\n }\r\n this.onEdited();\r\n },\r\n\r\n onEditDefaultInput(inputName, val) {\r\n if( val === undefined ) {\r\n this.n.deleteVal(\"input\", inputName);\r\n }\r\n else {\r\n this.n.val(\"input\", inputName, val);\r\n }\r\n this.onEdited();\r\n this.view.repaint();\r\n },\r\n\r\n onEdited() {\r\n // we need to refresh our node object\r\n this.n = this.view.m.getNode(this.id); // it breaks updating node name\r\n this.$forceUpdate();\r\n },\r\n\r\n getDataType: function(evt) {\r\n if( evt.datatype ) {\r\n return evt.datatype;\r\n }\r\n else if( evt.data ) {\r\n return window.DualBox.Type.detectType(evt.data);\r\n }\r\n else {\r\n return undefined;\r\n }\r\n },\r\n\r\n toggleAdvancedAppEventSettings: function(e) {\r\n var index = $(e.target).data('index');\r\n this.expanded[index] = this.expanded[index] ? false : true;\r\n this.$forceUpdate();\r\n },\r\n\r\n onEditEventData(key, index, val) {\r\n this.view.c.setEventData( this.n.id, index, val );\r\n this.$forceUpdate();\r\n },\r\n\r\n onEditEventInDataType(key, index, type) {\r\n this.view.c.setEventDataType( this.n.id, index, type);\r\n\r\n // check that the set value still match the new type\r\n // delete it otherwise\r\n var val = this.n.getOutboundEvents()[index].data;\r\n try {\r\n // TODO: ensure type is already loaded (after dualbox) and remove the try/catch\r\n if( !window.DualBox.Type.check(type, val) ) {\r\n // delete data (== set undefined)\r\n this.view.c.setEventData( this.n.id, index, undefined);\r\n }\r\n }\r\n catch(e) {\r\n this.view.c.setEventData( this.n.id, index, undefined);\r\n }\r\n\r\n this.$forceUpdate();\r\n },\r\n\r\n getDescription() {\r\n return this.n.getDescription() || \"[Add a description]\"\r\n },\r\n\r\n editDescription() {\r\n this.nowEditingDescription = true;\r\n },\r\n\r\n setDescription() {\r\n var val = $(this.$el).find('.edit-node-description').val();\r\n if( this.n.isInput() ) {\r\n this.view.c.setInputDescription(this.n.graphId, val);\r\n }\r\n else if( this.n.isOutput() ) {\r\n this.view.c.setOutputDescription(this.n.graphId, val);\r\n }\r\n else if( this.n.isMetanode() ) {\r\n this.view.c.setMetanodeDescription(this.n.graphId, val);\r\n }\r\n this.nowEditingDescription = false;\r\n\r\n this.$forceUpdate();\r\n },\r\n }\r\n}\r\n\r\n\r\n</script>\r\n"]}, media: undefined });
69688
69497
 
69689
69498
  };
69690
69499
  /* scoped */
@@ -89723,8 +89532,12 @@ class GraphController {
89723
89532
  }
89724
89533
 
89725
89534
  createId(name) {
89726
- var shortName = utils.shortName(name);
89727
- return shortName + '-' + utils.randomString(8);
89535
+ if (name) {
89536
+ var shortName = utils.shortName(name);
89537
+ return shortName + '-' + utils.randomString(8);
89538
+ } else {
89539
+ return utils.randomString(8);
89540
+ }
89728
89541
  }
89729
89542
 
89730
89543
  registerNodeToInterface(id) {
@@ -89854,10 +89667,11 @@ class GraphController {
89854
89667
  var node = this.m.getNode(id);
89855
89668
  var type = node.type;
89856
89669
  var def = lodash.cloneDeep(node.getDef());
89857
- var newId = this.createId(def.module);
89670
+ var newId = this.createId(def.module || def.type);
89858
89671
 
89859
89672
  // remove links, change position a little bit
89860
89673
  delete def.links;
89674
+ delete def.link;
89861
89675
  var leftPosition = idx_1(def, o => o.graph.position.left);
89862
89676
  if (leftPosition) {
89863
89677
  def.graph.position.left = (parseInt(leftPosition) + 200).toString();