@dualbox/editor 1.0.55 → 1.0.56
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.
- package/js/dist/GraphEditor.js +100 -94
- package/js/dist/GraphEditor.min.js +99 -93
- package/js/src/m/GraphModel.js +8 -1
- package/js/src/m/History.js +1 -1
- package/js/src/m/Merger.js +60 -64
- package/js/src/v/CanvasSizeHandler.js +30 -30
- package/js/src/v/templates/graphNode.vue +1 -1
- package/package.json +1 -1
|
@@ -17225,7 +17225,7 @@ class History {
|
|
|
17225
17225
|
// execute the callback and save the history as 1 change
|
|
17226
17226
|
batch(cb) {
|
|
17227
17227
|
this.ignore(cb);
|
|
17228
|
-
this.save();
|
|
17228
|
+
return this.save();
|
|
17229
17229
|
}
|
|
17230
17230
|
|
|
17231
17231
|
ignore(cb) {
|
|
@@ -42811,6 +42811,13 @@ class GraphModel {
|
|
|
42811
42811
|
}
|
|
42812
42812
|
}
|
|
42813
42813
|
|
|
42814
|
+
batch(cb) {
|
|
42815
|
+
var diff = this.history.batch(cb);
|
|
42816
|
+
if (this.onChangeCb) {
|
|
42817
|
+
this.onChangeCb(diff);
|
|
42818
|
+
}
|
|
42819
|
+
}
|
|
42820
|
+
|
|
42814
42821
|
setWindow(name) {
|
|
42815
42822
|
var newWindows = [];
|
|
42816
42823
|
lodash.each(this.data.windows, (w) => {
|
|
@@ -44370,7 +44377,7 @@ class GraphNode {
|
|
|
44370
44377
|
}
|
|
44371
44378
|
|
|
44372
44379
|
rename(newId) {
|
|
44373
|
-
this.m.
|
|
44380
|
+
this.m.batch(() => {
|
|
44374
44381
|
// change the target name according to type (ex: if input: "size" -> "in-size")
|
|
44375
44382
|
var newGraphId;
|
|
44376
44383
|
if (this.isInput()) {
|
|
@@ -45796,7 +45803,7 @@ var script = {
|
|
|
45796
45803
|
|
|
45797
45804
|
if( self.$parent.selector.isMultipleSelectionActive() ) {
|
|
45798
45805
|
// We just dropped a bunch of divs, ajust all their positions
|
|
45799
|
-
self.view.m.
|
|
45806
|
+
self.view.m.batch(() => {
|
|
45800
45807
|
self.$parent.selector.each(div => {
|
|
45801
45808
|
var pos = self.$parent.jsPlumbInstance.getPosition(div);
|
|
45802
45809
|
view.m.getNode($(div).attr('id')).setPosition(pos);
|
|
@@ -46447,7 +46454,7 @@ __vue_render__._withStripped = true;
|
|
|
46447
46454
|
/* style */
|
|
46448
46455
|
const __vue_inject_styles__ = function (inject) {
|
|
46449
46456
|
if (!inject) return
|
|
46450
|
-
inject("data-v-4e3d5666_0", { source: "\n.card-ui {\n background-color: #bff2ca!important;\n}\n.card-loop {\n /* background-color: #e5e8ea!important; */\n border: 5px double #dddddd;\n border-width: 4px;\n}\n.card-input {\n background-color: #f5d76e!important;\n}\n.card-output {\n background-color: #ffb3a7!important;\n}\n.box-inputs {\n float: left;\n padding-left: 2px;\n padding-right: 5px;\n vertical-align: top;\n text-align: left;\n}\n.box-outputs {\n float: right;\n padding-left: 5px;\n padding-right: 2px;\n vertical-align: top;\n text-align: right;\n}\n.dualbox-graph-canvas .card, .card-node {\n /*border: 1px solid #dddddd;*/\n box-shadow: 1px 1px 5px #716f6f;\n opacity: 1;\n cursor: pointer;\n z-index: 20;\n position: absolute;\n\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\n -moz-transition: -moz-box-shadow 0.15s ease-in;\n -o-transition: -o-box-shadow 0.15s ease-in;\n transition: box-shadow 0.15s ease-in;\n\n color: #4d4d4d;\n user-select: none;\n padding: 0px 8px 0px 8px;\n overflow:hidden;\n background-color: #fff;\n -moz-border-radius: 3px;\n border-radius:3px;\n font-size: 14px;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n}\n.card-node .card-top {\n padding-top: 2px;\n}\n.card-node .card-bottom {\n padding-bottom: 2px;\n text-align: center;\n line-height: 14px;\n white-space: nowrap;\n}\n.card-node hr {\n margin-top: 2px;\n margin-bottom: 2px;\n border-color: rgba(0,0,0,0.1);\n margin-left: -8px;\n margin-right: -8px;\n}\n.card-node:hover {\n border-color: #80b2fc;\n box-shadow: 1px 1px 10px #80b2fc;\n}\n.card-node.selected, .card-node.selected:hover {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n}\n.card-node-incomplete {\n box-shadow: 1px 1px 5px #dd6666 !important;\n}\n.input-not-resolvable {\n color: #dd6666!important;\n}\n.card-node .title {\n vertical-align:top;\n font-weight: bold;\n}\n.card-node .subtitle {\n color:#929292;\n font-size: 11px;\n font-style: italic;\n vertical-align:center;\n font-family: tahoma, sans-serif;\n}\n.card-node .input {\n font-size: 13px;\n color: #8c8c8c;\n}\n.card-node .output {\n font-size: 13px;\n color: #8c8c8c;\n text-align:right;\n}\n.card-node .jtk-endpoint.active svg circle {\n /* fill: #99ff33 */\n stroke: #59b300;\n}\n.point {\n /* display: inline-block; */\n display: none;\n position: relative;\n top: 3px;\n margin-right: 5px;\n margin-left: 5px;\n}\n.dualbox-io {\n overflow: visible;\n margin-left: -8px;\n margin-right: -8px;\n}\n.box-inputs {\n display: flex;\n justify-content: space-between;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n.types {\n color: #6c757d!important;\n opacity: 0.7;\n pointer-events: none;\n}\n.box-inputs .types {\n display: inline-block;\n}\n.box-inputs .name {\n display: inline-block;\n}\n.box-inputs .type {\n display: block;\n text-align: right;\n}\n.box-inputs .point {\n display: block;\n}\n.box-inputs .name {\n display: block;\n}\n.box-outputs {\n display: flex;\n justify-content: center;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n.box-outputs .types {\n display: inline-block;\n}\n.box-outputs .point {\n display: inline-block;\n}\n.box-outputs .name {\n display: inline-block;\n}\n.box-outputs .type {\n display: block;\n text-align: left;\n}\n.box-outputs .point {\n display: block;\n}\n.box-outputs .name {\n display: block;\n}\nspan.feedback {\n font-weight: bold;\n}\n.event-dock {\n background-color: rgb(136, 137, 138);\n background-color: #a6a6a6;\n width: calc(100% + 18px);\n height: 12px;\n z-index: 3!important;\n}\n.event-dock-top {\n margin-left: -9px;\n margin-right: -9px;\n margin-top: -3px;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n margin-bottom: 4px;\n}\n.event-dock-bottom {\n margin-left: -9px;\n margin-right: -9px;\n margin-bottom: -3px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n margin-top: 4px;\n height: 11px; /* shorter because of box-shadow */\n}\n.event-label {\n z-index: 21;\n padding-left: 15px;\n transform: rotate(-90deg) translate(0%, -50%)!important;\n transform-origin: 0% 0%;\n color: #6c757d!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-size: 14px;\n opacity: 0.7;\n cursor: pointer;\n}\n.transparent {\n opacity: 0.3!important;\n}\n.card-node {\n position: relative;\n}\n.card-comment {\n position: absolute;\n top: 0;\n right: 0;\n margin-top: -22px;\n color: #f4ad42!important;\n}\n.card-problem {\n position: absolute;\n top: 0;\n left: 0;\n margin-top: -22px;\n color: red!important;\n}\n.card-snapshot {\n}\n.card-snapshot-idle {\n border: 2px solid gray!important;\n box-shadow: 1px 1px 5px gray!important;\n opacity: 0.7!important;\n}\n.card-snapshot-computing {\n border: 2px solid darkgreen!important;\n box-shadow: 1px 1px 5px darkgreen!important;\n opacity: 1!important;\n}\n.card-snapshot-awaiting-data {\n border: 2px solid blue!important;\n box-shadow: 1px 1px 5px blue!important;\n opacity: 0.7!important;\n}\n.card-snapshot-ready {\n border: 2px solid lightgreen!important;\n box-shadow: 1px 1px 5px lightgreen!important;\n opacity: 1!important;\n}\n.card-status {\n position: absolute;\n bottom: 0;\n right: 0;\n left: 0;\n margin-bottom: -26px;\n color: #f4ad42!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-weight: bold;\n text-align: center;\n}\n.card-status-idle {\n color: gray!important;\n min-width: 85px;\n}\n.card-status-computing {\n color: darkgreen!important;\n min-width: 110px;\n}\n.card-status-awaiting-data {\n color: blue!important;\n min-width: 85px;\n}\n.card-status-ready {\n color: lightgreen!important;\n min-width: 85px;\n}\n.btn-snapshot-details {\n position: relative;\n margin-top: -2px;\n color: inherit;\n}\nspan.name {\n overflow-wrap: normal;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/graphNode.vue"],"names":[],"mappings":";AACA;IACA,mCAAA;AACA;AAEA;IACA,yCAAA;IACA,0BAAA;IACA,iBAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,mCAAA;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;IACA,6BAAA;IACA,+BAAA;IACA,UAAA;IACA,eAAA;IACA,WAAA;IACA,kBAAA;;IAEA,oDAAA;IACA,8CAAA;IACA,0CAAA;IACA,oCAAA;;IAEA,cAAA;IACA,iBAAA;IACA,wBAAA;IACA,eAAA;IACA,sBAAA;IACA,uBAAA;IACA,iBAAA;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,6BAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,0CAAA;AACA;AAEA;IACA,wBAAA;AACA;AAEA;IACA,kBAAA;IACA,iBAAA;AACA;AAEA;IACA,aAAA;IACA,eAAA;IACA,kBAAA;IACA,qBAAA;IACA,+BAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;IACA,gBAAA;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,wBAAA;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,2BAAA;IACA,wBAAA;IACA,YAAA;IACA,oBAAA;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,EAAA,kCAAA;AACA;AAEA;IACA,WAAA;IACA,kBAAA;IACA,uDAAA;IACA,uBAAA;IACA,wBAAA;IACA,2DAAA;IACA,eAAA;IACA,YAAA;IACA,eAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,QAAA;IACA,iBAAA;IACA,wBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,OAAA;IACA,iBAAA;IACA,oBAAA;AACA;AAEA;AAEA;AAEA;IACA,gCAAA;IACA,sCAAA;IACA,sBAAA;AACA;AAEA;IACA,qCAAA;IACA,2CAAA;IACA,oBAAA;AACA;AAEA;IACA,gCAAA;IACA,sCAAA;IACA,sBAAA;AACA;AAEA;IACA,sCAAA;IACA,4CAAA;IACA,oBAAA;AACA;AAEA;IACA,kBAAA;IACA,SAAA;IACA,QAAA;IACA,OAAA;IACA,oBAAA;IACA,wBAAA;IACA,2DAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,eAAA;AACA;AAEA;IACA,0BAAA;IACA,gBAAA;AACA;AAEA;IACA,qBAAA;IACA,eAAA;AACA;AAEA;IACA,2BAAA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,cAAA;AACA;AAEA;IACA,qBAAA;AACA","file":"graphNode.vue","sourcesContent":["<style>\n.card-ui {\n background-color: #bff2ca!important;\n}\n\n.card-loop {\n /* background-color: #e5e8ea!important; */\n border: 5px double #dddddd;\n border-width: 4px;\n}\n\n.card-input {\n background-color: #f5d76e!important;\n}\n\n.card-output {\n background-color: #ffb3a7!important;\n}\n\n.box-inputs {\n float: left;\n padding-left: 2px;\n padding-right: 5px;\n vertical-align: top;\n text-align: left;\n}\n\n.box-outputs {\n float: right;\n padding-left: 5px;\n padding-right: 2px;\n vertical-align: top;\n text-align: right;\n}\n\n.dualbox-graph-canvas .card, .card-node {\n /*border: 1px solid #dddddd;*/\n box-shadow: 1px 1px 5px #716f6f;\n opacity: 1;\n cursor: pointer;\n z-index: 20;\n position: absolute;\n\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\n -moz-transition: -moz-box-shadow 0.15s ease-in;\n -o-transition: -o-box-shadow 0.15s ease-in;\n transition: box-shadow 0.15s ease-in;\n\n color: #4d4d4d;\n user-select: none;\n padding: 0px 8px 0px 8px;\n overflow:hidden;\n background-color: #fff;\n -moz-border-radius: 3px;\n border-radius:3px;\n font-size: 14px;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n}\n\n.card-node .card-top {\n padding-top: 2px;\n}\n\n.card-node .card-bottom {\n padding-bottom: 2px;\n text-align: center;\n line-height: 14px;\n white-space: nowrap;\n}\n\n.card-node hr {\n margin-top: 2px;\n margin-bottom: 2px;\n border-color: rgba(0,0,0,0.1);\n margin-left: -8px;\n margin-right: -8px;\n}\n\n.card-node:hover {\n border-color: #80b2fc;\n box-shadow: 1px 1px 10px #80b2fc;\n}\n\n.card-node.selected, .card-node.selected:hover {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n}\n\n.card-node-incomplete {\n box-shadow: 1px 1px 5px #dd6666 !important;\n}\n\n.input-not-resolvable {\n color: #dd6666!important;\n}\n\n.card-node .title {\n vertical-align:top;\n font-weight: bold;\n}\n\n.card-node .subtitle {\n color:#929292;\n font-size: 11px;\n font-style: italic;\n vertical-align:center;\n font-family: tahoma, sans-serif;\n}\n\n.card-node .input {\n font-size: 13px;\n color: #8c8c8c;\n}\n\n.card-node .output {\n font-size: 13px;\n color: #8c8c8c;\n text-align:right;\n}\n\n.card-node .jtk-endpoint.active svg circle {\n /* fill: #99ff33 */\n stroke: #59b300;\n}\n\n.point {\n /* display: inline-block; */\n display: none;\n position: relative;\n top: 3px;\n margin-right: 5px;\n margin-left: 5px;\n}\n\n.dualbox-io {\n overflow: visible;\n margin-left: -8px;\n margin-right: -8px;\n}\n\n.box-inputs {\n display: flex;\n justify-content: space-between;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n\n.types {\n color: #6c757d!important;\n opacity: 0.7;\n pointer-events: none;\n}\n\n.box-inputs .types {\n display: inline-block;\n}\n\n.box-inputs .name {\n display: inline-block;\n}\n\n.box-inputs .type {\n display: block;\n text-align: right;\n}\n\n.box-inputs .point {\n display: block;\n}\n\n.box-inputs .name {\n display: block;\n}\n\n.box-outputs {\n display: flex;\n justify-content: center;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n\n.box-outputs .types {\n display: inline-block;\n}\n\n.box-outputs .point {\n display: inline-block;\n}\n\n.box-outputs .name {\n display: inline-block;\n}\n\n.box-outputs .type {\n display: block;\n text-align: left;\n}\n\n.box-outputs .point {\n display: block;\n}\n\n.box-outputs .name {\n display: block;\n}\n\nspan.feedback {\n font-weight: bold;\n}\n\n.event-dock {\n background-color: rgb(136, 137, 138);\n background-color: #a6a6a6;\n width: calc(100% + 18px);\n height: 12px;\n z-index: 3!important;\n}\n\n.event-dock-top {\n margin-left: -9px;\n margin-right: -9px;\n margin-top: -3px;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n margin-bottom: 4px;\n}\n\n.event-dock-bottom {\n margin-left: -9px;\n margin-right: -9px;\n margin-bottom: -3px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n margin-top: 4px;\n height: 11px; /* shorter because of box-shadow */\n}\n\n.event-label {\n z-index: 21;\n padding-left: 15px;\n transform: rotate(-90deg) translate(0%, -50%)!important;\n transform-origin: 0% 0%;\n color: #6c757d!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-size: 14px;\n opacity: 0.7;\n cursor: pointer;\n}\n\n.transparent {\n opacity: 0.3!important;\n}\n\n.card-node {\n position: relative;\n}\n\n.card-comment {\n position: absolute;\n top: 0;\n right: 0;\n margin-top: -22px;\n color: #f4ad42!important;\n}\n\n.card-problem {\n position: absolute;\n top: 0;\n left: 0;\n margin-top: -22px;\n color: red!important;\n}\n\n.card-snapshot {\n\n}\n\n.card-snapshot-idle {\n border: 2px solid gray!important;\n box-shadow: 1px 1px 5px gray!important;\n opacity: 0.7!important;\n}\n\n.card-snapshot-computing {\n border: 2px solid darkgreen!important;\n box-shadow: 1px 1px 5px darkgreen!important;\n opacity: 1!important;\n}\n\n.card-snapshot-awaiting-data {\n border: 2px solid blue!important;\n box-shadow: 1px 1px 5px blue!important;\n opacity: 0.7!important;\n}\n\n.card-snapshot-ready {\n border: 2px solid lightgreen!important;\n box-shadow: 1px 1px 5px lightgreen!important;\n opacity: 1!important;\n}\n\n.card-status {\n position: absolute;\n bottom: 0;\n right: 0;\n left: 0;\n margin-bottom: -26px;\n color: #f4ad42!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-weight: bold;\n text-align: center;\n}\n\n.card-status-idle {\n color: gray!important;\n min-width: 85px;\n}\n\n.card-status-computing {\n color: darkgreen!important;\n min-width: 110px;\n}\n\n.card-status-awaiting-data {\n color: blue!important;\n min-width: 85px;\n}\n\n.card-status-ready {\n color: lightgreen!important;\n min-width: 85px;\n}\n\n.btn-snapshot-details {\n position: relative;\n margin-top: -2px;\n color: inherit;\n}\n\nspan.name {\n overflow-wrap: normal;\n}\n</style>\n\n<template>\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;\">\n <div v-if=\"n.hasComment()\">\n <div class=\"card-comment\" data-toggle=\"tooltip\" data-placement=\"top\" :title=\"n.getComment()\">\n <i class=\"fas fa-comment-alt\" data-container=\"body\"></i>\n </div>\n </div>\n\n <div v-if=\"n.hasSnapshot()\">\n <div class=\"card-status\">\n <div v-if=\"n.isSnapshotStatus(0)\">\n <div class=\"card-status-idle\">\n <span>IDLE</span>\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>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(1)\">\n <div class=\"card-status-computing\">\n <span>COMPUTING</span>\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>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(2)\">\n <div class=\"card-status-awaiting-data\">\n <span>WAITING</span>\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>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(3)\">\n <div class=\"card-status-ready\">\n <span>READY</span>\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>\n </div>\n </div>\n </div>\n </div>\n\n <div v-if=\"!example && n.isUI() && !n.isOnAPanel()\">\n <div class=\"card-problem\">\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>\n </div>\n </div>\n\n <div class=\"card-top\">\n <div class=\"d-flex\">\n <span class=\"title\" style=\"white-space: nowrap; margin-right: 5px;\">\n <span v-if=\"n.isMetanode()\" class=\"badge badge-secondary\"><b>META</b></span>\n {{n.graphId}}\n <i v-if=\"n.isParallel()\" class=\"fas fa-server\" style=\"color: orange;\" title=\"this module is computed in a web worker\"></i>\n </span>\n\n <div class=\"ml-auto\">\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>\n </div>\n </div>\n </div>\n <div v-if=\"!n.isInput() && !n.isOutput()\" class=\"card-center\">\n <hr style=\"margin-bottom: 5px;\"/>\n <div class=\"dualbox-io\" style=\"overflow: visible;\">\n <div class=\"inputs\" style=\"display: inline-block; float: left;\">\n <div class=\"box-inputs\">\n <div class=\"types\">\n <span class=\"type\" v-for=\"key in getVisibleInputs()\" v-bind:data-key=\"key\">\n {{ n.getInputType(key) }}\n </span>\n </div>\n <div class=\"points\">\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>\n </div>\n <div class=\"names\">\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\">\n <span v-if=\"n.hasIterator(key)\"><{{key}}></span>\n <span v-else>{{key}}</span>\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>\n </span>\n </div>\n </div>\n </div>\n <div class=\"outputs\" style=\"display: inline-block; float: right\">\n <div class=\"box-outputs\">\n <div class=\"names\">\n <span class=\"name\" v-for=\"key in getVisibleOutputs()\" v-bind:class=\"{feedback: n.isFeedbackTarget(key)}\" v-bind:data-output=\"key\">\n <span v-if=\"n.hasLoop() && n.hasFeedback(key)\">{{key}}</span>\n <span v-else-if=\"n.hasLoop() && !n.hasFeedback(key)\" v-html='\"<\"+key+\">\"'></span>\n <span v-else>{{key}}</span>\n\n <span v-if=\"n.hasCacheActivated()\">\n <i class=\"fa fa-hdd\" title=\"This module has cache activated\"></i>\n </span>\n </span>\n </div>\n <div class=\"points\">\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>\n </div>\n <div class=\"types\">\n <span class=\"type\" v-for=\"key in getVisibleOutputs()\" v-bind:data-key=\"key\">\n {{ n.getOutputType(key) }}\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <hr style=\"margin-top: 5px;\"/>\n <div class=\"card-bottom\">\n <span class=\"subtitle\">{{ shortName }}</span>\n\n <div v-if=\"n.isMetanode()\" class=\"d-inline-block\">\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>\n </div>\n\n <!--\n <div v-if=\"n.isUI()\" class=\"event-dock event-dock-bottom\"></div>\n -->\n </div>\n </div>\n</template>\n\n<script>\nimport ContextMenu from '../ContextMenu';\nimport _ from 'lodash';\nimport dbutils from '../../m/DualboxUtils';\n\n// fix inputs types and output types position relatively to the div\n$.fn.fixCardDisplay = function() {\n var offsetPoint = 12;\n var offsetBorder = parseInt($(this).css(\"border-top-width\"));\n\n if( $(this).find('.box-inputs').height() === 0 && $(this).find('.box-outputs').height() === 0 ) {\n // if this card has no input/output, remove the card center\n $(this).find('.card-center').remove();\n }\n else {\n // else, adjust the input/output display for endpoints\n // 1) translate inputs by the right amount of pixels to have the circle on the line\n var boxInputs = $(this).find('.box-inputs');\n\n // fix css names width\n var namesDiv = boxInputs.find('.names');\n namesDiv.css('width', (namesDiv.width()+1) + 'px');\n\n // translate inputs to the left\n var translateLeft = boxInputs.find('.types').width() + offsetPoint + offsetBorder/2;\n $(this).find('.box-inputs').css('transform', 'translateX(-' + translateLeft + 'px)');\n\n // adjust inputs main div width\n $(this).find('.inputs').width( $(this).find('.inputs').width() - translateLeft + 10 /* margin */ );\n\n\n // 2) translate outputs by the right amount of pixels to have the circle on the line\n var boxOutputs = $(this).find('.box-outputs');\n\n // fix css names with\n var namesDiv = boxOutputs.find('.names');\n namesDiv.css('width', (namesDiv.width() + 1) + 'px');\n\n // translate inputs to the right\n var translateRight = boxOutputs.find('.types').width() + offsetPoint + offsetBorder/2;\n $(this).find('.box-outputs').css('transform', 'translateX(' + translateRight + 'px)');\n\n // adjust output main div width\n $(this).find('.outputs').width( $(this).find('.outputs').width() - translateRight + 10 /* margin */ );\n\n // fix io width\n //$('.dualbox-io').css('width', (($(this).find('.inputs').width() + $(this).find('.outputs').width()) + \"px\"));\n }\n}\n\n// take the current width and add it as a css property\n$.fn.fixWidth = function() {\n var width = $(this).width();\n width += parseInt($(this).css('padding-right'));\n width += parseInt($(this).css('padding-left'));\n width += parseInt($(this).css('border-left-width'));\n width += parseInt($(this).css('border-right-width'));\n $(this).css('width', width + 'px');\n}\n\n// find position of element relative to an ancestor matching selector\n$.fn.positionFrom = function( selector ) {\n var ancestor = $(this).closest(selector);\n var offset = $(this).offset();\n var ancestorOffset = ancestor.offset();\n return {\n top: offset.top - ancestorOffset.top,\n left: offset.left - ancestorOffset.left,\n }\n}\n\nexport default {\n props: [\n \"id\", // the module id\n \"pkg\", // the module package.json\n \"n\", // the GraphNode object (from model)\n \"example\", // true if this vue is used as an example display (no need to connect)\n \"displayEvents\", // true if events should be displayed\n ],\n data: function () {\n return {\n shortName: \"\",\n point: '<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>',\n }\n },\n beforeUpdate: function() {\n //console.log('[UPDATING] ' + this.n.getUniqId());\n },\n destroyed: function() {\n //console.log('[DESTROYED] ' + this.n.getUniqId());\n },\n created: function() {\n this.initialized = false;\n this.view = window.dualboxEditor.v;\n\n //console.log('[CREATED] ' + this.n.getUniqId());\n // We compute the shortname of our box\n if( this.n.isInput() || this.n.isOutput() ) {\n this.shortName = this.n.getType();\n }\n else {\n this.shortName = dbutils.shortName(this.pkg.name);\n }\n },\n mounted: async function() {\n //console.log('[MOUNTED] ' + this.n.getUniqId());\n var div = $(this.$el);\n div.fixCardDisplay();\n div.ready(() => {\n //if( !this.example ) {\n div.fixWidth();\n //}\n });\n this.activateTooltip();\n return await this.initialize();\n },\n beforeUpdate: function() {\n this.deactivateTooltip();\n },\n updated: async function() {\n //console.log('[UPDATED] ' + this.n.getUniqId());\n\n // we reset jsPlumb before app update (in graph.vue)\n // so we need to initialize again\n this.assignContextMenu();\n\n $(this.$el).fixCardDisplay();\n $(this.$el).ready(()=>{\n $(this.$el).fixWidth();\n this.activateTooltip();\n });\n return await this.initialize();\n },\n activate: function() {\n this.activateTooltip();\n },\n deactivate: function() {\n this.deactivateTooltip();\n },\n methods: {\n getId: function() {\n // if this is an example graphNode, change our \"id\" to \"id-junk\"\n // to avoid connection jsplumb conflicts with the real node\n return this.example ? this.id + '-junk' : this.id;\n },\n\n activateTooltip: function() {\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip();\n },\n\n deactivateTooltip: function() {\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip(\"dispose\");\n },\n\n initialize: async function() {\n var self = this;\n var div = $(this.$el);\n var id = this.getId();\n var view = this.view;\n\n this.initialized = false;\n\n if( !this.example ) {\n // if we have a position, set it\n var def = this.n.getDef();\n var position = _.get(def, [\"graph\", \"position\"]);\n if( position ) {\n var jsPlumbElement = self.$parent.jsPlumbInstance.getElement(id);\n self.$parent.jsPlumbInstance.setPosition(jsPlumbElement, position);\n }\n\n // This needs to be registered before draggable\n div.on('mousedown', function(e) {\n // if this div is not selected already, deselect the other divs\n if( !self.$parent.selector.isSelected(this) ) {\n self.$parent.selector.deselect();\n }\n });\n\n await this.initializeJsPlumb();\n\n div.click(function(e) {\n if( e.ctrlKey ) {\n view.selector.toggleSelection(this);\n }\n });\n\n this.assignContextMenu();\n }\n\n return new Promise(resolve => {\n div.ready(() => {\n //console.log('[INITIALIZED] ' + this.n.getUniqId());\n this.initialized = true;\n resolve();\n });\n });\n },\n\n initializeJsPlumb: function() {\n var self = this;\n var div = $(this.$el);\n var id = this.getId();\n var view = this.view;\n\n if( !this.example ) {\n // If this node was never initialized in this jsplumb instance, do it\n if( !_.get(this.$parent.jsPlumbInstance, [\"initializedNodes\", id]) ) {\n _.set(this.$parent.jsPlumbInstance, [\"initializedNodes\", id], true); // initialized\n\n if( this.n.isInput() || this.n.isOutput() ) {\n var type = \"*\";\n var input = \"value\";\n var output = \"value\";\n var offsetTop = $(div).find('.card-top').height() + 12 /* hr size */ - 3;\n\n var uuid = [ id, \"input\", input].join('#');\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : false,\n isTarget : true,\n uuid : uuid,\n anchor : [0,0,-1,0,0,offsetTop],\n maxConnections : 1,\n parameters : {\n type: \"data\",\n target : {\n id : id,\n input : output\n }\n }\n }, this.$parent.style.inputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', 'input');\n $(ep.canvas).attr('data-input', input);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"left\");\n $(ep.canvas).attr('data-html', \"true\");\n var inputType = view.m.getNode(id).getInputType(\"value\");\n $(ep.canvas).attr('title', \"Type: <b>\" + inputType + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-input='\" + input + \"']\", [\n {\n name: 'Create input for here',\n fn: () => {\n view.c.createInputFromConnection(id, input);\n }\n },\n ]);\n });\n\n var uuid = [ id, \"output\", output].join('#');\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : uuid,\n anchor : [1,0,1,0,0,offsetTop],\n parameters : {\n type: \"data\",\n source : {\n id : id,\n output : output\n }\n }\n }, this.$parent.style.outputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', \"output\");\n $(ep.canvas).attr('data-output', output);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"right\");\n $(ep.canvas).attr('data-html', \"true\");\n var outputType = view.m.getNode(id).getOutputType(\"value\");\n $(ep.canvas).attr('title', \"Type: <b>\" + outputType + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-output='\" + output.trim() + \"']\", [\n {\n name: 'Create output for here',\n fn: () => {\n view.c.createOutputFromConnection(id, output);\n }\n },\n ]);\n });\n }\n else {\n // add input endoints\n div.find('.box-inputs').find('.point').each( function(index) {\n $(this).css('visibility', 'hidden').css('opacity', '0'); // replaced by jsPlumb point\n\n var input = div.find('.box-inputs').find('.name').eq(index).attr('data-input').trim();\n var type = view.m.getNode(id).getInputType(input);\n\n var offsetTop = $(this).positionFrom('.card').top + $(this).height()/2 - 3;\n var uuid = [ id, \"input\", $(this).data('key')].join('#');\n var ep = self.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : false,\n isTarget : true,\n uuid : uuid,\n anchor : [0,0,-1,0,0,offsetTop],\n maxConnections : 1,\n parameters : {\n type: \"data\",\n target : {\n id : id,\n input : $(this).data('key')\n }\n }\n }, self.$parent.style.inputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', 'input');\n $(ep.canvas).attr('data-input', input);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"left\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Type: <b>\" + type + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-input='\" + input.trim() + \"']\", [\n {\n name: 'Create input for here',\n fn: () => {\n view.c.createInputFromConnection(id, input);\n }\n },\n ]);\n });\n });\n\n // add output endpoints\n div.find('.box-outputs').find('.point').each( function(index) {\n $(this).css('visibility', 'hidden').css('opacity', '0'); // replaced by jsPlumb point\n\n var output = div.find('.box-outputs').find('.name').eq(index).attr('data-output').trim();\n var type = view.m.getNode(id).getOutputType(output);\n\n var offsetTop = $(this).positionFrom('.card').top + $(this).height()/2 - 3;\n var uuid = [ id, \"output\", $(this).data('key')].join('#');\n var ep = self.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : uuid,\n anchor : [1,0,1,0,0,offsetTop],\n parameters : {\n type: \"data\",\n source : {\n id : id,\n output : $(this).data('key')\n }\n }\n }, self.$parent.style.outputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', \"output\");\n $(ep.canvas).attr('data-output', output);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"right\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Type: <b>\" + type + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-output='\" + output.trim() + \"']\", [\n {\n name: 'Create output for here',\n fn: () => {\n view.c.createOutputFromConnection(id, output);\n }\n },\n ]);\n });\n });\n\n if( this.n.isUI() && this.displayEvents ) {\n // Make this a target for events\n this.$parent.jsPlumbInstance.makeTarget(id, {\n isSource:false,\n isTarget:true,\n uniqueEndpoint: false,\n anchor:\"Continuous\",\n uuid: id + \"#event-in\",\n paintStyle:{ fill:\"green\", radius: 3, stroke: \"#727272\", strokeWidth: 1 },\n parameters: {\n type: \"event\",\n target: { \"id\" : id }\n },\n }, self.$parent.style.eventEndpoint);\n\n // Create an enpoint to create a new event\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : id + \"#event-out\",\n anchor : [1, 1, 0, 1, 0, -10],\n parameters : {\n type: \"event\",\n source: { \"id\" : id }\n },\n paintStyle:{ fill:\"green\", radius: 3, stroke: \"#727272\", strokeWidth: 1 },\n }, this.$parent.style.eventEndpoint);\n\n // Add overlay here so we don't mess with splitConnection\n ep.addOverlay([\"PlainArrow\", { width:15, length:15, location:1, id:\"arrow\" }]);\n\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"bottom\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Connect from here ito add an event that will be triggered when this box is done computing.\");\n $(ep.canvas).tooltip();\n }\n }\n\n // Make the div draggable\n this.$parent.jsPlumbInstance.draggable(div, {\n //containment:true, // not allowed outside of container div\n drag: function(e) {\n // TODO: bug. After a repaint(), jsPlumb seems to be broken (connections dont follow on div drag)\n // It doesn't occur on jsPlumb.reset() instead of creating another instance on beforeUpdate(),\n // (as it should be), but we can't do that, because JsPlumb is broken on zoom otherwise...\n // One of thoses problem may be fixed later by updating jsPlumb...\n // Note: this \"fix\" may affect performances on drag, maybe a setTimeout will do\n //self.$parent.jsPlumbInstance.repaintEverything();\n self.$parent.jsPlumbInstance.repaint(id);\n },\n stop: function(e) {\n // resize the canvas if necessary\n self.$parent.canvasSizeHandler.debouncedResize();\n\n if( self.$parent.selector.isMultipleSelectionActive() ) {\n // We just dropped a bunch of divs, ajust all their positions\n self.view.m.history.batch(() => {\n self.$parent.selector.each(div => {\n var pos = self.$parent.jsPlumbInstance.getPosition(div);\n view.m.getNode($(div).attr('id')).setPosition(pos);\n });\n });\n }\n else {\n // We just dropped this one, set the new position in the graph model\n var el = self.$parent.jsPlumbInstance.getElement(id);\n $(el).ready(function() {\n var pos = self.$parent.jsPlumbInstance.getPosition(el);\n view.m.getNode(id).setPosition(pos);\n });\n }\n }\n });\n }\n }\n\n return new Promise((resolve) => this.$parent.jsPlumbInstance.ready(resolve));\n },\n\n assignContextMenu: function() {\n var id = this.getId();\n\n // Create a contextmenu for the div\n var contextOptions = [\n {\n name: 'Remove this box',\n fn: () => {\n this.view.c.removeBox(id);\n }\n }\n ];\n if( this.n.isModule() || this.n.isUI() ) {\n contextOptions.push({\n name: 'Duplicate this box',\n fn: () => {\n this.view.c.duplicateBox(id);\n }\n });\n }\n var nodeMenu = new ContextMenu(\"#\" + id, contextOptions);\n },\n\n htmlentities: function( s ) {\n return this.view.utils.htmlentities(s);\n },\n\n getVisibleInputs: function() {\n return this.n.getInputsNames().filter((inputName) => {\n return this.n.isInputVisible(inputName);\n })\n },\n\n getVisibleOutputs: function() {\n return this.n.getOutputsNames().filter((outputName) => {\n return this.n.isOutputVisible(outputName);\n })\n },\n\n enterMetanode: function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n this.view.c.enterMetanode(this.id);\n },\n\n openNodeSettings: function(e) {\n e.preventDefault();\n e.stopPropagation();\n this.view.openBoxSettings(this.id);\n },\n\n openSnapshotDetails: function(e) {\n e.preventDefault();\n e.stopPropagation();\n this.view.openDebug(this.id);\n }\n },\n watch: {\n 'app': {\n handler: () => {\n console.log('graphVue.app changed');\n },\n deep: true\n }\n }\n}\n\n</script>\n"]}, media: undefined });
|
|
46457
|
+
inject("data-v-1aee1868_0", { source: "\n.card-ui {\n background-color: #bff2ca!important;\n}\n.card-loop {\n /* background-color: #e5e8ea!important; */\n border: 5px double #dddddd;\n border-width: 4px;\n}\n.card-input {\n background-color: #f5d76e!important;\n}\n.card-output {\n background-color: #ffb3a7!important;\n}\n.box-inputs {\n float: left;\n padding-left: 2px;\n padding-right: 5px;\n vertical-align: top;\n text-align: left;\n}\n.box-outputs {\n float: right;\n padding-left: 5px;\n padding-right: 2px;\n vertical-align: top;\n text-align: right;\n}\n.dualbox-graph-canvas .card, .card-node {\n /*border: 1px solid #dddddd;*/\n box-shadow: 1px 1px 5px #716f6f;\n opacity: 1;\n cursor: pointer;\n z-index: 20;\n position: absolute;\n\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\n -moz-transition: -moz-box-shadow 0.15s ease-in;\n -o-transition: -o-box-shadow 0.15s ease-in;\n transition: box-shadow 0.15s ease-in;\n\n color: #4d4d4d;\n user-select: none;\n padding: 0px 8px 0px 8px;\n overflow:hidden;\n background-color: #fff;\n -moz-border-radius: 3px;\n border-radius:3px;\n font-size: 14px;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n}\n.card-node .card-top {\n padding-top: 2px;\n}\n.card-node .card-bottom {\n padding-bottom: 2px;\n text-align: center;\n line-height: 14px;\n white-space: nowrap;\n}\n.card-node hr {\n margin-top: 2px;\n margin-bottom: 2px;\n border-color: rgba(0,0,0,0.1);\n margin-left: -8px;\n margin-right: -8px;\n}\n.card-node:hover {\n border-color: #80b2fc;\n box-shadow: 1px 1px 10px #80b2fc;\n}\n.card-node.selected, .card-node.selected:hover {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n}\n.card-node-incomplete {\n box-shadow: 1px 1px 5px #dd6666 !important;\n}\n.input-not-resolvable {\n color: #dd6666!important;\n}\n.card-node .title {\n vertical-align:top;\n font-weight: bold;\n}\n.card-node .subtitle {\n color:#929292;\n font-size: 11px;\n font-style: italic;\n vertical-align:center;\n font-family: tahoma, sans-serif;\n}\n.card-node .input {\n font-size: 13px;\n color: #8c8c8c;\n}\n.card-node .output {\n font-size: 13px;\n color: #8c8c8c;\n text-align:right;\n}\n.card-node .jtk-endpoint.active svg circle {\n /* fill: #99ff33 */\n stroke: #59b300;\n}\n.point {\n /* display: inline-block; */\n display: none;\n position: relative;\n top: 3px;\n margin-right: 5px;\n margin-left: 5px;\n}\n.dualbox-io {\n overflow: visible;\n margin-left: -8px;\n margin-right: -8px;\n}\n.box-inputs {\n display: flex;\n justify-content: space-between;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n.types {\n color: #6c757d!important;\n opacity: 0.7;\n pointer-events: none;\n}\n.box-inputs .types {\n display: inline-block;\n}\n.box-inputs .name {\n display: inline-block;\n}\n.box-inputs .type {\n display: block;\n text-align: right;\n}\n.box-inputs .point {\n display: block;\n}\n.box-inputs .name {\n display: block;\n}\n.box-outputs {\n display: flex;\n justify-content: center;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n.box-outputs .types {\n display: inline-block;\n}\n.box-outputs .point {\n display: inline-block;\n}\n.box-outputs .name {\n display: inline-block;\n}\n.box-outputs .type {\n display: block;\n text-align: left;\n}\n.box-outputs .point {\n display: block;\n}\n.box-outputs .name {\n display: block;\n}\nspan.feedback {\n font-weight: bold;\n}\n.event-dock {\n background-color: rgb(136, 137, 138);\n background-color: #a6a6a6;\n width: calc(100% + 18px);\n height: 12px;\n z-index: 3!important;\n}\n.event-dock-top {\n margin-left: -9px;\n margin-right: -9px;\n margin-top: -3px;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n margin-bottom: 4px;\n}\n.event-dock-bottom {\n margin-left: -9px;\n margin-right: -9px;\n margin-bottom: -3px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n margin-top: 4px;\n height: 11px; /* shorter because of box-shadow */\n}\n.event-label {\n z-index: 21;\n padding-left: 15px;\n transform: rotate(-90deg) translate(0%, -50%)!important;\n transform-origin: 0% 0%;\n color: #6c757d!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-size: 14px;\n opacity: 0.7;\n cursor: pointer;\n}\n.transparent {\n opacity: 0.3!important;\n}\n.card-node {\n position: relative;\n}\n.card-comment {\n position: absolute;\n top: 0;\n right: 0;\n margin-top: -22px;\n color: #f4ad42!important;\n}\n.card-problem {\n position: absolute;\n top: 0;\n left: 0;\n margin-top: -22px;\n color: red!important;\n}\n.card-snapshot {\n}\n.card-snapshot-idle {\n border: 2px solid gray!important;\n box-shadow: 1px 1px 5px gray!important;\n opacity: 0.7!important;\n}\n.card-snapshot-computing {\n border: 2px solid darkgreen!important;\n box-shadow: 1px 1px 5px darkgreen!important;\n opacity: 1!important;\n}\n.card-snapshot-awaiting-data {\n border: 2px solid blue!important;\n box-shadow: 1px 1px 5px blue!important;\n opacity: 0.7!important;\n}\n.card-snapshot-ready {\n border: 2px solid lightgreen!important;\n box-shadow: 1px 1px 5px lightgreen!important;\n opacity: 1!important;\n}\n.card-status {\n position: absolute;\n bottom: 0;\n right: 0;\n left: 0;\n margin-bottom: -26px;\n color: #f4ad42!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-weight: bold;\n text-align: center;\n}\n.card-status-idle {\n color: gray!important;\n min-width: 85px;\n}\n.card-status-computing {\n color: darkgreen!important;\n min-width: 110px;\n}\n.card-status-awaiting-data {\n color: blue!important;\n min-width: 85px;\n}\n.card-status-ready {\n color: lightgreen!important;\n min-width: 85px;\n}\n.btn-snapshot-details {\n position: relative;\n margin-top: -2px;\n color: inherit;\n}\nspan.name {\n overflow-wrap: normal;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/graphNode.vue"],"names":[],"mappings":";AACA;IACA,mCAAA;AACA;AAEA;IACA,yCAAA;IACA,0BAAA;IACA,iBAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,mCAAA;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;IACA,6BAAA;IACA,+BAAA;IACA,UAAA;IACA,eAAA;IACA,WAAA;IACA,kBAAA;;IAEA,oDAAA;IACA,8CAAA;IACA,0CAAA;IACA,oCAAA;;IAEA,cAAA;IACA,iBAAA;IACA,wBAAA;IACA,eAAA;IACA,sBAAA;IACA,uBAAA;IACA,iBAAA;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,6BAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,0CAAA;AACA;AAEA;IACA,wBAAA;AACA;AAEA;IACA,kBAAA;IACA,iBAAA;AACA;AAEA;IACA,aAAA;IACA,eAAA;IACA,kBAAA;IACA,qBAAA;IACA,+BAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;IACA,gBAAA;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,wBAAA;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,2BAAA;IACA,wBAAA;IACA,YAAA;IACA,oBAAA;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,EAAA,kCAAA;AACA;AAEA;IACA,WAAA;IACA,kBAAA;IACA,uDAAA;IACA,uBAAA;IACA,wBAAA;IACA,2DAAA;IACA,eAAA;IACA,YAAA;IACA,eAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,QAAA;IACA,iBAAA;IACA,wBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,OAAA;IACA,iBAAA;IACA,oBAAA;AACA;AAEA;AAEA;AAEA;IACA,gCAAA;IACA,sCAAA;IACA,sBAAA;AACA;AAEA;IACA,qCAAA;IACA,2CAAA;IACA,oBAAA;AACA;AAEA;IACA,gCAAA;IACA,sCAAA;IACA,sBAAA;AACA;AAEA;IACA,sCAAA;IACA,4CAAA;IACA,oBAAA;AACA;AAEA;IACA,kBAAA;IACA,SAAA;IACA,QAAA;IACA,OAAA;IACA,oBAAA;IACA,wBAAA;IACA,2DAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,eAAA;AACA;AAEA;IACA,0BAAA;IACA,gBAAA;AACA;AAEA;IACA,qBAAA;IACA,eAAA;AACA;AAEA;IACA,2BAAA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,cAAA;AACA;AAEA;IACA,qBAAA;AACA","file":"graphNode.vue","sourcesContent":["<style>\n.card-ui {\n background-color: #bff2ca!important;\n}\n\n.card-loop {\n /* background-color: #e5e8ea!important; */\n border: 5px double #dddddd;\n border-width: 4px;\n}\n\n.card-input {\n background-color: #f5d76e!important;\n}\n\n.card-output {\n background-color: #ffb3a7!important;\n}\n\n.box-inputs {\n float: left;\n padding-left: 2px;\n padding-right: 5px;\n vertical-align: top;\n text-align: left;\n}\n\n.box-outputs {\n float: right;\n padding-left: 5px;\n padding-right: 2px;\n vertical-align: top;\n text-align: right;\n}\n\n.dualbox-graph-canvas .card, .card-node {\n /*border: 1px solid #dddddd;*/\n box-shadow: 1px 1px 5px #716f6f;\n opacity: 1;\n cursor: pointer;\n z-index: 20;\n position: absolute;\n\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\n -moz-transition: -moz-box-shadow 0.15s ease-in;\n -o-transition: -o-box-shadow 0.15s ease-in;\n transition: box-shadow 0.15s ease-in;\n\n color: #4d4d4d;\n user-select: none;\n padding: 0px 8px 0px 8px;\n overflow:hidden;\n background-color: #fff;\n -moz-border-radius: 3px;\n border-radius:3px;\n font-size: 14px;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n}\n\n.card-node .card-top {\n padding-top: 2px;\n}\n\n.card-node .card-bottom {\n padding-bottom: 2px;\n text-align: center;\n line-height: 14px;\n white-space: nowrap;\n}\n\n.card-node hr {\n margin-top: 2px;\n margin-bottom: 2px;\n border-color: rgba(0,0,0,0.1);\n margin-left: -8px;\n margin-right: -8px;\n}\n\n.card-node:hover {\n border-color: #80b2fc;\n box-shadow: 1px 1px 10px #80b2fc;\n}\n\n.card-node.selected, .card-node.selected:hover {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n}\n\n.card-node-incomplete {\n box-shadow: 1px 1px 5px #dd6666 !important;\n}\n\n.input-not-resolvable {\n color: #dd6666!important;\n}\n\n.card-node .title {\n vertical-align:top;\n font-weight: bold;\n}\n\n.card-node .subtitle {\n color:#929292;\n font-size: 11px;\n font-style: italic;\n vertical-align:center;\n font-family: tahoma, sans-serif;\n}\n\n.card-node .input {\n font-size: 13px;\n color: #8c8c8c;\n}\n\n.card-node .output {\n font-size: 13px;\n color: #8c8c8c;\n text-align:right;\n}\n\n.card-node .jtk-endpoint.active svg circle {\n /* fill: #99ff33 */\n stroke: #59b300;\n}\n\n.point {\n /* display: inline-block; */\n display: none;\n position: relative;\n top: 3px;\n margin-right: 5px;\n margin-left: 5px;\n}\n\n.dualbox-io {\n overflow: visible;\n margin-left: -8px;\n margin-right: -8px;\n}\n\n.box-inputs {\n display: flex;\n justify-content: space-between;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n\n.types {\n color: #6c757d!important;\n opacity: 0.7;\n pointer-events: none;\n}\n\n.box-inputs .types {\n display: inline-block;\n}\n\n.box-inputs .name {\n display: inline-block;\n}\n\n.box-inputs .type {\n display: block;\n text-align: right;\n}\n\n.box-inputs .point {\n display: block;\n}\n\n.box-inputs .name {\n display: block;\n}\n\n.box-outputs {\n display: flex;\n justify-content: center;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n\n.box-outputs .types {\n display: inline-block;\n}\n\n.box-outputs .point {\n display: inline-block;\n}\n\n.box-outputs .name {\n display: inline-block;\n}\n\n.box-outputs .type {\n display: block;\n text-align: left;\n}\n\n.box-outputs .point {\n display: block;\n}\n\n.box-outputs .name {\n display: block;\n}\n\nspan.feedback {\n font-weight: bold;\n}\n\n.event-dock {\n background-color: rgb(136, 137, 138);\n background-color: #a6a6a6;\n width: calc(100% + 18px);\n height: 12px;\n z-index: 3!important;\n}\n\n.event-dock-top {\n margin-left: -9px;\n margin-right: -9px;\n margin-top: -3px;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n margin-bottom: 4px;\n}\n\n.event-dock-bottom {\n margin-left: -9px;\n margin-right: -9px;\n margin-bottom: -3px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n margin-top: 4px;\n height: 11px; /* shorter because of box-shadow */\n}\n\n.event-label {\n z-index: 21;\n padding-left: 15px;\n transform: rotate(-90deg) translate(0%, -50%)!important;\n transform-origin: 0% 0%;\n color: #6c757d!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-size: 14px;\n opacity: 0.7;\n cursor: pointer;\n}\n\n.transparent {\n opacity: 0.3!important;\n}\n\n.card-node {\n position: relative;\n}\n\n.card-comment {\n position: absolute;\n top: 0;\n right: 0;\n margin-top: -22px;\n color: #f4ad42!important;\n}\n\n.card-problem {\n position: absolute;\n top: 0;\n left: 0;\n margin-top: -22px;\n color: red!important;\n}\n\n.card-snapshot {\n\n}\n\n.card-snapshot-idle {\n border: 2px solid gray!important;\n box-shadow: 1px 1px 5px gray!important;\n opacity: 0.7!important;\n}\n\n.card-snapshot-computing {\n border: 2px solid darkgreen!important;\n box-shadow: 1px 1px 5px darkgreen!important;\n opacity: 1!important;\n}\n\n.card-snapshot-awaiting-data {\n border: 2px solid blue!important;\n box-shadow: 1px 1px 5px blue!important;\n opacity: 0.7!important;\n}\n\n.card-snapshot-ready {\n border: 2px solid lightgreen!important;\n box-shadow: 1px 1px 5px lightgreen!important;\n opacity: 1!important;\n}\n\n.card-status {\n position: absolute;\n bottom: 0;\n right: 0;\n left: 0;\n margin-bottom: -26px;\n color: #f4ad42!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-weight: bold;\n text-align: center;\n}\n\n.card-status-idle {\n color: gray!important;\n min-width: 85px;\n}\n\n.card-status-computing {\n color: darkgreen!important;\n min-width: 110px;\n}\n\n.card-status-awaiting-data {\n color: blue!important;\n min-width: 85px;\n}\n\n.card-status-ready {\n color: lightgreen!important;\n min-width: 85px;\n}\n\n.btn-snapshot-details {\n position: relative;\n margin-top: -2px;\n color: inherit;\n}\n\nspan.name {\n overflow-wrap: normal;\n}\n</style>\n\n<template>\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;\">\n <div v-if=\"n.hasComment()\">\n <div class=\"card-comment\" data-toggle=\"tooltip\" data-placement=\"top\" :title=\"n.getComment()\">\n <i class=\"fas fa-comment-alt\" data-container=\"body\"></i>\n </div>\n </div>\n\n <div v-if=\"n.hasSnapshot()\">\n <div class=\"card-status\">\n <div v-if=\"n.isSnapshotStatus(0)\">\n <div class=\"card-status-idle\">\n <span>IDLE</span>\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>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(1)\">\n <div class=\"card-status-computing\">\n <span>COMPUTING</span>\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>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(2)\">\n <div class=\"card-status-awaiting-data\">\n <span>WAITING</span>\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>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(3)\">\n <div class=\"card-status-ready\">\n <span>READY</span>\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>\n </div>\n </div>\n </div>\n </div>\n\n <div v-if=\"!example && n.isUI() && !n.isOnAPanel()\">\n <div class=\"card-problem\">\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>\n </div>\n </div>\n\n <div class=\"card-top\">\n <div class=\"d-flex\">\n <span class=\"title\" style=\"white-space: nowrap; margin-right: 5px;\">\n <span v-if=\"n.isMetanode()\" class=\"badge badge-secondary\"><b>META</b></span>\n {{n.graphId}}\n <i v-if=\"n.isParallel()\" class=\"fas fa-server\" style=\"color: orange;\" title=\"this module is computed in a web worker\"></i>\n </span>\n\n <div class=\"ml-auto\">\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>\n </div>\n </div>\n </div>\n <div v-if=\"!n.isInput() && !n.isOutput()\" class=\"card-center\">\n <hr style=\"margin-bottom: 5px;\"/>\n <div class=\"dualbox-io\" style=\"overflow: visible;\">\n <div class=\"inputs\" style=\"display: inline-block; float: left;\">\n <div class=\"box-inputs\">\n <div class=\"types\">\n <span class=\"type\" v-for=\"key in getVisibleInputs()\" v-bind:data-key=\"key\">\n {{ n.getInputType(key) }}\n </span>\n </div>\n <div class=\"points\">\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>\n </div>\n <div class=\"names\">\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\">\n <span v-if=\"n.hasIterator(key)\"><{{key}}></span>\n <span v-else>{{key}}</span>\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>\n </span>\n </div>\n </div>\n </div>\n <div class=\"outputs\" style=\"display: inline-block; float: right\">\n <div class=\"box-outputs\">\n <div class=\"names\">\n <span class=\"name\" v-for=\"key in getVisibleOutputs()\" v-bind:class=\"{feedback: n.isFeedbackTarget(key)}\" v-bind:data-output=\"key\">\n <span v-if=\"n.hasLoop() && n.hasFeedback(key)\">{{key}}</span>\n <span v-else-if=\"n.hasLoop() && !n.hasFeedback(key)\" v-html='\"<\"+key+\">\"'></span>\n <span v-else>{{key}}</span>\n\n <span v-if=\"n.hasCacheActivated()\">\n <i class=\"fa fa-hdd\" title=\"This module has cache activated\"></i>\n </span>\n </span>\n </div>\n <div class=\"points\">\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>\n </div>\n <div class=\"types\">\n <span class=\"type\" v-for=\"key in getVisibleOutputs()\" v-bind:data-key=\"key\">\n {{ n.getOutputType(key) }}\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <hr style=\"margin-top: 5px;\"/>\n <div class=\"card-bottom\">\n <span class=\"subtitle\">{{ shortName }}</span>\n\n <div v-if=\"n.isMetanode()\" class=\"d-inline-block\">\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>\n </div>\n\n <!--\n <div v-if=\"n.isUI()\" class=\"event-dock event-dock-bottom\"></div>\n -->\n </div>\n </div>\n</template>\n\n<script>\nimport ContextMenu from '../ContextMenu';\nimport _ from 'lodash';\nimport dbutils from '../../m/DualboxUtils';\n\n// fix inputs types and output types position relatively to the div\n$.fn.fixCardDisplay = function() {\n var offsetPoint = 12;\n var offsetBorder = parseInt($(this).css(\"border-top-width\"));\n\n if( $(this).find('.box-inputs').height() === 0 && $(this).find('.box-outputs').height() === 0 ) {\n // if this card has no input/output, remove the card center\n $(this).find('.card-center').remove();\n }\n else {\n // else, adjust the input/output display for endpoints\n // 1) translate inputs by the right amount of pixels to have the circle on the line\n var boxInputs = $(this).find('.box-inputs');\n\n // fix css names width\n var namesDiv = boxInputs.find('.names');\n namesDiv.css('width', (namesDiv.width()+1) + 'px');\n\n // translate inputs to the left\n var translateLeft = boxInputs.find('.types').width() + offsetPoint + offsetBorder/2;\n $(this).find('.box-inputs').css('transform', 'translateX(-' + translateLeft + 'px)');\n\n // adjust inputs main div width\n $(this).find('.inputs').width( $(this).find('.inputs').width() - translateLeft + 10 /* margin */ );\n\n\n // 2) translate outputs by the right amount of pixels to have the circle on the line\n var boxOutputs = $(this).find('.box-outputs');\n\n // fix css names with\n var namesDiv = boxOutputs.find('.names');\n namesDiv.css('width', (namesDiv.width() + 1) + 'px');\n\n // translate inputs to the right\n var translateRight = boxOutputs.find('.types').width() + offsetPoint + offsetBorder/2;\n $(this).find('.box-outputs').css('transform', 'translateX(' + translateRight + 'px)');\n\n // adjust output main div width\n $(this).find('.outputs').width( $(this).find('.outputs').width() - translateRight + 10 /* margin */ );\n\n // fix io width\n //$('.dualbox-io').css('width', (($(this).find('.inputs').width() + $(this).find('.outputs').width()) + \"px\"));\n }\n}\n\n// take the current width and add it as a css property\n$.fn.fixWidth = function() {\n var width = $(this).width();\n width += parseInt($(this).css('padding-right'));\n width += parseInt($(this).css('padding-left'));\n width += parseInt($(this).css('border-left-width'));\n width += parseInt($(this).css('border-right-width'));\n $(this).css('width', width + 'px');\n}\n\n// find position of element relative to an ancestor matching selector\n$.fn.positionFrom = function( selector ) {\n var ancestor = $(this).closest(selector);\n var offset = $(this).offset();\n var ancestorOffset = ancestor.offset();\n return {\n top: offset.top - ancestorOffset.top,\n left: offset.left - ancestorOffset.left,\n }\n}\n\nexport default {\n props: [\n \"id\", // the module id\n \"pkg\", // the module package.json\n \"n\", // the GraphNode object (from model)\n \"example\", // true if this vue is used as an example display (no need to connect)\n \"displayEvents\", // true if events should be displayed\n ],\n data: function () {\n return {\n shortName: \"\",\n point: '<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>',\n }\n },\n beforeUpdate: function() {\n //console.log('[UPDATING] ' + this.n.getUniqId());\n },\n destroyed: function() {\n //console.log('[DESTROYED] ' + this.n.getUniqId());\n },\n created: function() {\n this.initialized = false;\n this.view = window.dualboxEditor.v;\n\n //console.log('[CREATED] ' + this.n.getUniqId());\n // We compute the shortname of our box\n if( this.n.isInput() || this.n.isOutput() ) {\n this.shortName = this.n.getType();\n }\n else {\n this.shortName = dbutils.shortName(this.pkg.name);\n }\n },\n mounted: async function() {\n //console.log('[MOUNTED] ' + this.n.getUniqId());\n var div = $(this.$el);\n div.fixCardDisplay();\n div.ready(() => {\n //if( !this.example ) {\n div.fixWidth();\n //}\n });\n this.activateTooltip();\n return await this.initialize();\n },\n beforeUpdate: function() {\n this.deactivateTooltip();\n },\n updated: async function() {\n //console.log('[UPDATED] ' + this.n.getUniqId());\n\n // we reset jsPlumb before app update (in graph.vue)\n // so we need to initialize again\n this.assignContextMenu();\n\n $(this.$el).fixCardDisplay();\n $(this.$el).ready(()=>{\n $(this.$el).fixWidth();\n this.activateTooltip();\n });\n return await this.initialize();\n },\n activate: function() {\n this.activateTooltip();\n },\n deactivate: function() {\n this.deactivateTooltip();\n },\n methods: {\n getId: function() {\n // if this is an example graphNode, change our \"id\" to \"id-junk\"\n // to avoid connection jsplumb conflicts with the real node\n return this.example ? this.id + '-junk' : this.id;\n },\n\n activateTooltip: function() {\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip();\n },\n\n deactivateTooltip: function() {\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip(\"dispose\");\n },\n\n initialize: async function() {\n var self = this;\n var div = $(this.$el);\n var id = this.getId();\n var view = this.view;\n\n this.initialized = false;\n\n if( !this.example ) {\n // if we have a position, set it\n var def = this.n.getDef();\n var position = _.get(def, [\"graph\", \"position\"]);\n if( position ) {\n var jsPlumbElement = self.$parent.jsPlumbInstance.getElement(id);\n self.$parent.jsPlumbInstance.setPosition(jsPlumbElement, position);\n }\n\n // This needs to be registered before draggable\n div.on('mousedown', function(e) {\n // if this div is not selected already, deselect the other divs\n if( !self.$parent.selector.isSelected(this) ) {\n self.$parent.selector.deselect();\n }\n });\n\n await this.initializeJsPlumb();\n\n div.click(function(e) {\n if( e.ctrlKey ) {\n view.selector.toggleSelection(this);\n }\n });\n\n this.assignContextMenu();\n }\n\n return new Promise(resolve => {\n div.ready(() => {\n //console.log('[INITIALIZED] ' + this.n.getUniqId());\n this.initialized = true;\n resolve();\n });\n });\n },\n\n initializeJsPlumb: function() {\n var self = this;\n var div = $(this.$el);\n var id = this.getId();\n var view = this.view;\n\n if( !this.example ) {\n // If this node was never initialized in this jsplumb instance, do it\n if( !_.get(this.$parent.jsPlumbInstance, [\"initializedNodes\", id]) ) {\n _.set(this.$parent.jsPlumbInstance, [\"initializedNodes\", id], true); // initialized\n\n if( this.n.isInput() || this.n.isOutput() ) {\n var type = \"*\";\n var input = \"value\";\n var output = \"value\";\n var offsetTop = $(div).find('.card-top').height() + 12 /* hr size */ - 3;\n\n var uuid = [ id, \"input\", input].join('#');\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : false,\n isTarget : true,\n uuid : uuid,\n anchor : [0,0,-1,0,0,offsetTop],\n maxConnections : 1,\n parameters : {\n type: \"data\",\n target : {\n id : id,\n input : output\n }\n }\n }, this.$parent.style.inputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', 'input');\n $(ep.canvas).attr('data-input', input);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"left\");\n $(ep.canvas).attr('data-html', \"true\");\n var inputType = view.m.getNode(id).getInputType(\"value\");\n $(ep.canvas).attr('title', \"Type: <b>\" + inputType + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-input='\" + input + \"']\", [\n {\n name: 'Create input for here',\n fn: () => {\n view.c.createInputFromConnection(id, input);\n }\n },\n ]);\n });\n\n var uuid = [ id, \"output\", output].join('#');\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : uuid,\n anchor : [1,0,1,0,0,offsetTop],\n parameters : {\n type: \"data\",\n source : {\n id : id,\n output : output\n }\n }\n }, this.$parent.style.outputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', \"output\");\n $(ep.canvas).attr('data-output', output);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"right\");\n $(ep.canvas).attr('data-html', \"true\");\n var outputType = view.m.getNode(id).getOutputType(\"value\");\n $(ep.canvas).attr('title', \"Type: <b>\" + outputType + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-output='\" + output.trim() + \"']\", [\n {\n name: 'Create output for here',\n fn: () => {\n view.c.createOutputFromConnection(id, output);\n }\n },\n ]);\n });\n }\n else {\n // add input endoints\n div.find('.box-inputs').find('.point').each( function(index) {\n $(this).css('visibility', 'hidden').css('opacity', '0'); // replaced by jsPlumb point\n\n var input = div.find('.box-inputs').find('.name').eq(index).attr('data-input').trim();\n var type = view.m.getNode(id).getInputType(input);\n\n var offsetTop = $(this).positionFrom('.card').top + $(this).height()/2 - 3;\n var uuid = [ id, \"input\", $(this).data('key')].join('#');\n var ep = self.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : false,\n isTarget : true,\n uuid : uuid,\n anchor : [0,0,-1,0,0,offsetTop],\n maxConnections : 1,\n parameters : {\n type: \"data\",\n target : {\n id : id,\n input : $(this).data('key')\n }\n }\n }, self.$parent.style.inputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', 'input');\n $(ep.canvas).attr('data-input', input);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"left\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Type: <b>\" + type + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-input='\" + input.trim() + \"']\", [\n {\n name: 'Create input for here',\n fn: () => {\n view.c.createInputFromConnection(id, input);\n }\n },\n ]);\n });\n });\n\n // add output endpoints\n div.find('.box-outputs').find('.point').each( function(index) {\n $(this).css('visibility', 'hidden').css('opacity', '0'); // replaced by jsPlumb point\n\n var output = div.find('.box-outputs').find('.name').eq(index).attr('data-output').trim();\n var type = view.m.getNode(id).getOutputType(output);\n\n var offsetTop = $(this).positionFrom('.card').top + $(this).height()/2 - 3;\n var uuid = [ id, \"output\", $(this).data('key')].join('#');\n var ep = self.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : uuid,\n anchor : [1,0,1,0,0,offsetTop],\n parameters : {\n type: \"data\",\n source : {\n id : id,\n output : $(this).data('key')\n }\n }\n }, self.$parent.style.outputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', \"output\");\n $(ep.canvas).attr('data-output', output);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"right\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Type: <b>\" + type + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-output='\" + output.trim() + \"']\", [\n {\n name: 'Create output for here',\n fn: () => {\n view.c.createOutputFromConnection(id, output);\n }\n },\n ]);\n });\n });\n\n if( this.n.isUI() && this.displayEvents ) {\n // Make this a target for events\n this.$parent.jsPlumbInstance.makeTarget(id, {\n isSource:false,\n isTarget:true,\n uniqueEndpoint: false,\n anchor:\"Continuous\",\n uuid: id + \"#event-in\",\n paintStyle:{ fill:\"green\", radius: 3, stroke: \"#727272\", strokeWidth: 1 },\n parameters: {\n type: \"event\",\n target: { \"id\" : id }\n },\n }, self.$parent.style.eventEndpoint);\n\n // Create an enpoint to create a new event\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : id + \"#event-out\",\n anchor : [1, 1, 0, 1, 0, -10],\n parameters : {\n type: \"event\",\n source: { \"id\" : id }\n },\n paintStyle:{ fill:\"green\", radius: 3, stroke: \"#727272\", strokeWidth: 1 },\n }, this.$parent.style.eventEndpoint);\n\n // Add overlay here so we don't mess with splitConnection\n ep.addOverlay([\"PlainArrow\", { width:15, length:15, location:1, id:\"arrow\" }]);\n\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"bottom\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Connect from here ito add an event that will be triggered when this box is done computing.\");\n $(ep.canvas).tooltip();\n }\n }\n\n // Make the div draggable\n this.$parent.jsPlumbInstance.draggable(div, {\n //containment:true, // not allowed outside of container div\n drag: function(e) {\n // TODO: bug. After a repaint(), jsPlumb seems to be broken (connections dont follow on div drag)\n // It doesn't occur on jsPlumb.reset() instead of creating another instance on beforeUpdate(),\n // (as it should be), but we can't do that, because JsPlumb is broken on zoom otherwise...\n // One of thoses problem may be fixed later by updating jsPlumb...\n // Note: this \"fix\" may affect performances on drag, maybe a setTimeout will do\n //self.$parent.jsPlumbInstance.repaintEverything();\n self.$parent.jsPlumbInstance.repaint(id);\n },\n stop: function(e) {\n // resize the canvas if necessary\n self.$parent.canvasSizeHandler.debouncedResize();\n\n if( self.$parent.selector.isMultipleSelectionActive() ) {\n // We just dropped a bunch of divs, ajust all their positions\n self.view.m.batch(() => {\n self.$parent.selector.each(div => {\n var pos = self.$parent.jsPlumbInstance.getPosition(div);\n view.m.getNode($(div).attr('id')).setPosition(pos);\n });\n });\n }\n else {\n // We just dropped this one, set the new position in the graph model\n var el = self.$parent.jsPlumbInstance.getElement(id);\n $(el).ready(function() {\n var pos = self.$parent.jsPlumbInstance.getPosition(el);\n view.m.getNode(id).setPosition(pos);\n });\n }\n }\n });\n }\n }\n\n return new Promise((resolve) => this.$parent.jsPlumbInstance.ready(resolve));\n },\n\n assignContextMenu: function() {\n var id = this.getId();\n\n // Create a contextmenu for the div\n var contextOptions = [\n {\n name: 'Remove this box',\n fn: () => {\n this.view.c.removeBox(id);\n }\n }\n ];\n if( this.n.isModule() || this.n.isUI() ) {\n contextOptions.push({\n name: 'Duplicate this box',\n fn: () => {\n this.view.c.duplicateBox(id);\n }\n });\n }\n var nodeMenu = new ContextMenu(\"#\" + id, contextOptions);\n },\n\n htmlentities: function( s ) {\n return this.view.utils.htmlentities(s);\n },\n\n getVisibleInputs: function() {\n return this.n.getInputsNames().filter((inputName) => {\n return this.n.isInputVisible(inputName);\n })\n },\n\n getVisibleOutputs: function() {\n return this.n.getOutputsNames().filter((outputName) => {\n return this.n.isOutputVisible(outputName);\n })\n },\n\n enterMetanode: function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n this.view.c.enterMetanode(this.id);\n },\n\n openNodeSettings: function(e) {\n e.preventDefault();\n e.stopPropagation();\n this.view.openBoxSettings(this.id);\n },\n\n openSnapshotDetails: function(e) {\n e.preventDefault();\n e.stopPropagation();\n this.view.openDebug(this.id);\n }\n },\n watch: {\n 'app': {\n handler: () => {\n console.log('graphVue.app changed');\n },\n deep: true\n }\n }\n}\n\n</script>\n"]}, media: undefined });
|
|
46451
46458
|
|
|
46452
46459
|
};
|
|
46453
46460
|
/* scoped */
|
|
@@ -47099,11 +47106,11 @@ class Translater {
|
|
|
47099
47106
|
*/
|
|
47100
47107
|
|
|
47101
47108
|
var editorView = null;
|
|
47102
|
-
$.fn.savePosition = function(
|
|
47109
|
+
$.fn.savePosition = function(selector) {
|
|
47103
47110
|
var id = $(this).attr('id');
|
|
47104
|
-
if(
|
|
47111
|
+
if (id) {
|
|
47105
47112
|
var jsPlumbElement = editorView.jsPlumbInstance.getElement(id);
|
|
47106
|
-
if(
|
|
47113
|
+
if (jsPlumbElement) {
|
|
47107
47114
|
var pos = editorView.jsPlumbInstance.getPosition(jsPlumbElement);
|
|
47108
47115
|
editorView.view.m.getNode(id).setPosition(pos);
|
|
47109
47116
|
}
|
|
@@ -47114,7 +47121,7 @@ class CanvasSizeHandler {
|
|
|
47114
47121
|
constructor(parent, canvas) {
|
|
47115
47122
|
this.parent = editorView = parent;
|
|
47116
47123
|
this.canvas = canvas;
|
|
47117
|
-
this.minWidth
|
|
47124
|
+
this.minWidth = this.width = this.canvas.width();
|
|
47118
47125
|
this.minHeight = this.height = this.canvas.height();
|
|
47119
47126
|
|
|
47120
47127
|
// arbitrary: number of pixels to expand/shrink the canvas for 1 step
|
|
@@ -47128,41 +47135,41 @@ class CanvasSizeHandler {
|
|
|
47128
47135
|
this.z = 0; // current zoom
|
|
47129
47136
|
}
|
|
47130
47137
|
|
|
47131
|
-
refreshZoom(
|
|
47138
|
+
refreshZoom(z) {
|
|
47132
47139
|
this.z = z;
|
|
47133
47140
|
}
|
|
47134
47141
|
|
|
47135
47142
|
// set the current width and height to the new canvas
|
|
47136
47143
|
apply() {
|
|
47137
47144
|
var offset = this.canvas.offset();
|
|
47138
|
-
var oldWidth
|
|
47145
|
+
var oldWidth = this.canvas.width();
|
|
47139
47146
|
var oldHeight = this.canvas.height();
|
|
47140
47147
|
|
|
47141
|
-
if(
|
|
47148
|
+
if (oldWidth !== this.width) {
|
|
47142
47149
|
console.log('setting canvas width: %s -> %s', this.canvas.width(), this.width);
|
|
47143
47150
|
this.canvas.width(this.width);
|
|
47144
47151
|
}
|
|
47145
|
-
if(
|
|
47152
|
+
if (oldHeight !== this.height) {
|
|
47146
47153
|
console.log('setting canvas height: %s -> %s', this.canvas.height(), this.height);
|
|
47147
47154
|
this.canvas.height(this.height);
|
|
47148
47155
|
}
|
|
47149
47156
|
|
|
47150
47157
|
// If we are in a zoomed state, we need to update the transform-origin so we stay at the same position
|
|
47151
|
-
if(
|
|
47152
|
-
// transform-origin is defined in % in the debugger, but for some reason, jquery seems to give us offset when
|
|
47158
|
+
if (this.z !== 1) {
|
|
47159
|
+
// transform-origin is defined in % in the debugger, but for some reason, jquery seems to give us offset when
|
|
47153
47160
|
// we integrate it
|
|
47154
47161
|
var oldTO = this.canvas.css('transform-origin');
|
|
47155
47162
|
var oldTOX = parseFloat(oldTO);
|
|
47156
47163
|
var oldTOY = parseFloat(oldTO.split(' ')[1]);
|
|
47157
47164
|
var newTOX = oldTOX; // init thoses at the old value
|
|
47158
|
-
var newTOY = oldTOY;
|
|
47165
|
+
var newTOY = oldTOY;
|
|
47159
47166
|
|
|
47160
|
-
if(
|
|
47167
|
+
if (oldWidth !== this.width) {
|
|
47161
47168
|
var xRatioChange = this.width / oldWidth;
|
|
47162
47169
|
var newTOX = oldTOX * xRatioChange;
|
|
47163
47170
|
}
|
|
47164
47171
|
|
|
47165
|
-
if(
|
|
47172
|
+
if (oldHeight !== this.height) {
|
|
47166
47173
|
var yRatioChange = this.height / oldHeight;
|
|
47167
47174
|
var newTOY = oldTOY * yRatioChange;
|
|
47168
47175
|
}
|
|
@@ -47178,21 +47185,21 @@ class CanvasSizeHandler {
|
|
|
47178
47185
|
// dont trigger save
|
|
47179
47186
|
this.parent.view.m.history.ignore(() => {
|
|
47180
47187
|
// refresh zoom value, zoom affects width, height and offset calculations
|
|
47181
|
-
this.refreshZoom(
|
|
47188
|
+
this.refreshZoom(this.parent.zoomer.getZoom());
|
|
47182
47189
|
|
|
47183
47190
|
// find the coord of the 2d box bounding all divs
|
|
47184
47191
|
var most = {
|
|
47185
|
-
top:
|
|
47192
|
+
top: +Infinity,
|
|
47186
47193
|
bottom: -Infinity,
|
|
47187
|
-
left:
|
|
47188
|
-
right:
|
|
47194
|
+
left: +Infinity,
|
|
47195
|
+
right: -Infinity
|
|
47189
47196
|
};
|
|
47190
47197
|
this.canvas.find('.card').each(function() {
|
|
47191
47198
|
var rect = this.getBoundingClientRect();
|
|
47192
|
-
if(
|
|
47193
|
-
if(
|
|
47194
|
-
if(
|
|
47195
|
-
if(
|
|
47199
|
+
if (rect.top < most.top) most.top = Math.floor(rect.top);
|
|
47200
|
+
if (rect.bottom > most.bottom) most.bottom = Math.ceil(rect.bottom);
|
|
47201
|
+
if (rect.left < most.left) most.left = Math.floor(rect.left);
|
|
47202
|
+
if (rect.right > most.right) most.right = Math.ceil(rect.right);
|
|
47196
47203
|
});
|
|
47197
47204
|
|
|
47198
47205
|
// compare to the canvas coord
|
|
@@ -47200,24 +47207,24 @@ class CanvasSizeHandler {
|
|
|
47200
47207
|
var tresholdAdapted = this.treshold * this.z;
|
|
47201
47208
|
|
|
47202
47209
|
var r = {
|
|
47203
|
-
top:
|
|
47210
|
+
top: ((canvasRect.top + tresholdAdapted) - most.top) / this.z,
|
|
47204
47211
|
bottom: (most.bottom - (canvasRect.bottom - tresholdAdapted)) / this.z,
|
|
47205
|
-
left:
|
|
47206
|
-
right:
|
|
47212
|
+
left: ((canvasRect.left + tresholdAdapted) - most.left) / this.z,
|
|
47213
|
+
right: (most.right - (canvasRect.right - tresholdAdapted)) / this.z
|
|
47207
47214
|
};
|
|
47208
47215
|
|
|
47209
47216
|
// avoid to resize for some pixel roundup
|
|
47210
|
-
if(
|
|
47217
|
+
if (Math.abs(r.top) > 2 || Math.abs(r.left) > 2 || Math.abs(r.bottom) > 2 || Math.abs(r.right) > 2) {
|
|
47211
47218
|
// resize width and height
|
|
47212
47219
|
this.width += r.left + r.right;
|
|
47213
47220
|
this.height += r.top + r.bottom;
|
|
47214
|
-
if(
|
|
47215
|
-
if(
|
|
47221
|
+
if (this.width < this.minWidth) this.width = this.minWidth;
|
|
47222
|
+
if (this.height < this.minHeight) this.height = this.minHeight;
|
|
47216
47223
|
this.apply();
|
|
47217
47224
|
|
|
47218
47225
|
// if we're expanding to the top or shrinking back, move the non-selected divs
|
|
47219
47226
|
// in the opposite direction
|
|
47220
|
-
if(
|
|
47227
|
+
if (r.top > 0 || (r.top < 0 && this.height > this.minHeight)) {
|
|
47221
47228
|
// move the non-selected divs to the bottom
|
|
47222
47229
|
this.canvas.find('.card:not(.selected)').each(function() {
|
|
47223
47230
|
var offset = $(this).offset();
|
|
@@ -47233,7 +47240,7 @@ class CanvasSizeHandler {
|
|
|
47233
47240
|
}
|
|
47234
47241
|
|
|
47235
47242
|
// same for left
|
|
47236
|
-
if(
|
|
47243
|
+
if (r.left > 0 || (r.left < 0 && this.width > this.minWidth)) {
|
|
47237
47244
|
// move the non-selected divs to the right
|
|
47238
47245
|
this.canvas.find('.card:not(.selected)').each(function() {
|
|
47239
47246
|
var offset = $(this).offset();
|
|
@@ -87787,24 +87794,24 @@ class Merger {
|
|
|
87787
87794
|
|
|
87788
87795
|
this.nodes = [];
|
|
87789
87796
|
lodash.each(ids, (id) => {
|
|
87790
|
-
this.nodes.push(
|
|
87797
|
+
this.nodes.push(this.m.getNode(id));
|
|
87791
87798
|
});
|
|
87792
87799
|
|
|
87793
87800
|
this.id = null;
|
|
87794
87801
|
|
|
87795
87802
|
// links from and to outside
|
|
87796
87803
|
this.inboundLinksFromOutside = [];
|
|
87797
|
-
this.outboundLinksToOutside
|
|
87804
|
+
this.outboundLinksToOutside = [];
|
|
87798
87805
|
}
|
|
87799
87806
|
|
|
87800
87807
|
// merge all divs into a metabox
|
|
87801
87808
|
// ids: array of ids from the boxes to be merged
|
|
87802
87809
|
// metaboxName: name of the new metabox
|
|
87803
87810
|
// metaboxDesc: description of the new metabox
|
|
87804
|
-
merge(
|
|
87811
|
+
merge(metaboxName, metaboxDesc) {
|
|
87805
87812
|
this.def.desc = metaboxDesc;
|
|
87806
87813
|
|
|
87807
|
-
this.m.
|
|
87814
|
+
this.m.batch(() => {
|
|
87808
87815
|
// 0. create a new ID for our metanode
|
|
87809
87816
|
this.id = metaboxName + '-' + utils.randomString(8);
|
|
87810
87817
|
|
|
@@ -87828,16 +87835,16 @@ class Merger {
|
|
|
87828
87835
|
|
|
87829
87836
|
// 5. Our metanode definition is ready, add it to the app
|
|
87830
87837
|
this.m.data.app.metanodes = this.m.data.app.metanodes || {};
|
|
87831
|
-
this.m.data.app.metanodes[
|
|
87838
|
+
this.m.data.app.metanodes[metaboxName] = this.def;
|
|
87832
87839
|
|
|
87833
87840
|
// 6. Create a new node from this def
|
|
87834
87841
|
this.m.data.app.modules[this.id] = {
|
|
87835
|
-
"module"
|
|
87842
|
+
"module": metaboxName,
|
|
87836
87843
|
"version": "*",
|
|
87837
|
-
"graph"
|
|
87838
|
-
"position"
|
|
87839
|
-
top
|
|
87840
|
-
left
|
|
87844
|
+
"graph": {
|
|
87845
|
+
"position": {
|
|
87846
|
+
top: (bbox.top + bbox.bottom) / 2,
|
|
87847
|
+
left: (bbox.left + bbox.right) / 2
|
|
87841
87848
|
}
|
|
87842
87849
|
}
|
|
87843
87850
|
};
|
|
@@ -87849,13 +87856,13 @@ class Merger {
|
|
|
87849
87856
|
}
|
|
87850
87857
|
|
|
87851
87858
|
_debug() {
|
|
87852
|
-
console.log(
|
|
87859
|
+
console.log(this.def);
|
|
87853
87860
|
}
|
|
87854
87861
|
|
|
87855
|
-
_isInMetanode(
|
|
87862
|
+
_isInMetanode(id) {
|
|
87856
87863
|
var inGroup = false;
|
|
87857
|
-
lodash.each(
|
|
87858
|
-
if(
|
|
87864
|
+
lodash.each(this.nodes, (node) => {
|
|
87865
|
+
if (node.id === id) {
|
|
87859
87866
|
inGroup = true;
|
|
87860
87867
|
return false; // eol
|
|
87861
87868
|
}
|
|
@@ -87865,36 +87872,35 @@ class Merger {
|
|
|
87865
87872
|
|
|
87866
87873
|
// find the links from and to outside the metanode
|
|
87867
87874
|
_collectAndDetachExternalLinks() {
|
|
87868
|
-
lodash.each(
|
|
87875
|
+
lodash.each(this.nodes, (node) => {
|
|
87869
87876
|
var links = node.getInboundLinks();
|
|
87870
|
-
lodash.each(
|
|
87871
|
-
if(
|
|
87877
|
+
lodash.each(links, (link) => {
|
|
87878
|
+
if (!this._isInMetanode(link.sourceId)) {
|
|
87872
87879
|
link.detach(); // we don't need this link anymore
|
|
87873
|
-
this.inboundLinksFromOutside.push(
|
|
87880
|
+
this.inboundLinksFromOutside.push(link);
|
|
87874
87881
|
}
|
|
87875
87882
|
});
|
|
87876
87883
|
|
|
87877
87884
|
var links = node.getOutboundLinks();
|
|
87878
|
-
lodash.each(
|
|
87879
|
-
if(
|
|
87885
|
+
lodash.each(links, (link) => {
|
|
87886
|
+
if (!this._isInMetanode(link.targetId)) {
|
|
87880
87887
|
link.detach();
|
|
87881
|
-
this.outboundLinksToOutside.push(
|
|
87888
|
+
this.outboundLinksToOutside.push(link);
|
|
87882
87889
|
}
|
|
87883
87890
|
});
|
|
87884
87891
|
});
|
|
87885
87892
|
}
|
|
87886
87893
|
|
|
87887
87894
|
// transform "cond" into "cond2", or "cond3" if cond2 is taken, etc.
|
|
87888
|
-
_nextName(
|
|
87895
|
+
_nextName(type, name) {
|
|
87889
87896
|
// find the appropriate number end (that is not taken already)
|
|
87890
87897
|
var ending = 2;
|
|
87891
|
-
if(
|
|
87892
|
-
while(
|
|
87893
|
-
}
|
|
87894
|
-
|
|
87895
|
-
while( this.def.output[ name + "-" + ending ] ) ending++;
|
|
87898
|
+
if (type == "input") {
|
|
87899
|
+
while (this.def.input[name + "-" + ending]) ending++;
|
|
87900
|
+
} else {
|
|
87901
|
+
while (this.def.output[name + "-" + ending]) ending++;
|
|
87896
87902
|
}
|
|
87897
|
-
return name+"-"+ending;
|
|
87903
|
+
return name + "-" + ending;
|
|
87898
87904
|
}
|
|
87899
87905
|
|
|
87900
87906
|
// find and create the metabox inputs
|
|
@@ -87907,7 +87913,7 @@ class Merger {
|
|
|
87907
87913
|
var getInputNameForThisLink = function(l) {
|
|
87908
87914
|
var r = null;
|
|
87909
87915
|
lodash.each(inputToLinks, (link, inputName) => {
|
|
87910
|
-
if(
|
|
87916
|
+
if (link.sourceId == l.sourceId && link.sourceOutput == l.sourceOutput) {
|
|
87911
87917
|
r = inputName;
|
|
87912
87918
|
return false;
|
|
87913
87919
|
}
|
|
@@ -87921,7 +87927,7 @@ class Merger {
|
|
|
87921
87927
|
|
|
87922
87928
|
// get the original input name, rename if necessary
|
|
87923
87929
|
var inputName = link.targetInput;
|
|
87924
|
-
if(
|
|
87930
|
+
if (this.def.input[inputName]) {
|
|
87925
87931
|
|
|
87926
87932
|
// check if an input for this source has already been created
|
|
87927
87933
|
// otherwise, create a new one
|
|
@@ -87929,8 +87935,8 @@ class Merger {
|
|
|
87929
87935
|
inputName = lookupInputName ? lookupInputName : this._nextName("input", inputName);
|
|
87930
87936
|
}
|
|
87931
87937
|
|
|
87932
|
-
this.def.input[
|
|
87933
|
-
type: targetNode.getInputType(
|
|
87938
|
+
this.def.input[inputName] = {
|
|
87939
|
+
type: targetNode.getInputType(link.targetInput),
|
|
87934
87940
|
graph: {
|
|
87935
87941
|
position: this._computeInputSmartPosition(index)
|
|
87936
87942
|
}
|
|
@@ -87942,7 +87948,7 @@ class Merger {
|
|
|
87942
87948
|
link.nextTargetInput = inputName;
|
|
87943
87949
|
|
|
87944
87950
|
// save our link in the dictionary
|
|
87945
|
-
inputToLinks[
|
|
87951
|
+
inputToLinks[inputName] = link;
|
|
87946
87952
|
});
|
|
87947
87953
|
}
|
|
87948
87954
|
|
|
@@ -87953,13 +87959,13 @@ class Merger {
|
|
|
87953
87959
|
var sourceNode = link.getSourceNode();
|
|
87954
87960
|
|
|
87955
87961
|
var outputName = link.sourceOutput;
|
|
87956
|
-
if(
|
|
87962
|
+
if (this.def.output[outputName]) {
|
|
87957
87963
|
// check if the source of the output is the same as this link
|
|
87958
87964
|
var outputLink = this.def.output[outputName].link;
|
|
87959
87965
|
var sourceId = lodash.keys(outputLink)[0];
|
|
87960
87966
|
var sourceOutput = outputLink[sourceId];
|
|
87961
87967
|
|
|
87962
|
-
if(
|
|
87968
|
+
if (!(link.sourceId == sourceId && link.sourceOutput == sourceOutput)) {
|
|
87963
87969
|
// the output already exists. we need to create another one.
|
|
87964
87970
|
outputName = this._nextName("output", outputName);
|
|
87965
87971
|
}
|
|
@@ -87967,8 +87973,8 @@ class Merger {
|
|
|
87967
87973
|
|
|
87968
87974
|
var l = {};
|
|
87969
87975
|
l[link.sourceId] = link.sourceOutput;
|
|
87970
|
-
this.def.output[
|
|
87971
|
-
type: sourceNode.getOutputType(
|
|
87976
|
+
this.def.output[outputName] = {
|
|
87977
|
+
type: sourceNode.getOutputType(link.sourceOutput),
|
|
87972
87978
|
graph: {
|
|
87973
87979
|
position: this._computeOutputSmartPosition(index)
|
|
87974
87980
|
},
|
|
@@ -87988,15 +87994,15 @@ class Merger {
|
|
|
87988
87994
|
var left = Number.MAX_SAFE_INTEGER;
|
|
87989
87995
|
lodash.each(this.nodes, (node) => {
|
|
87990
87996
|
var pos = node.getPosition();
|
|
87991
|
-
if(
|
|
87992
|
-
if(
|
|
87997
|
+
if (pos.top < top) top = pos.top;
|
|
87998
|
+
if (pos.left < left) left = pos.left;
|
|
87993
87999
|
});
|
|
87994
88000
|
|
|
87995
88001
|
// we want to put theses node to 50px top and 50px left, so compute the diff
|
|
87996
88002
|
var topdiff = top - 50;
|
|
87997
88003
|
var leftdiff = left - 250;
|
|
87998
|
-
if(
|
|
87999
|
-
if(
|
|
88004
|
+
if (topdiff < 0) topdiff = 0;
|
|
88005
|
+
if (leftdiff < 0) leftdiff = 0;
|
|
88000
88006
|
|
|
88001
88007
|
// reposition all nodes
|
|
88002
88008
|
lodash.each(this.nodes, (node) => {
|
|
@@ -88010,18 +88016,18 @@ class Merger {
|
|
|
88010
88016
|
_moveNodes() {
|
|
88011
88017
|
// move the nodes into the Metamodule def
|
|
88012
88018
|
lodash.each(this.nodes, (node) => {
|
|
88013
|
-
if(
|
|
88019
|
+
if (node.isMetanode()) {
|
|
88014
88020
|
// move the metanode definition too
|
|
88015
|
-
this.def.metanodes[
|
|
88021
|
+
this.def.metanodes[node.def.module] = node.getMetanodeDefinition();
|
|
88016
88022
|
}
|
|
88017
88023
|
|
|
88018
88024
|
// move the node module definition (preserving the links between metabox's node)
|
|
88019
|
-
this.def.modules[node.id] = this.m.data.app.modules[
|
|
88025
|
+
this.def.modules[node.id] = this.m.data.app.modules[node.id];
|
|
88020
88026
|
delete this.m.data.app.modules[node.id];
|
|
88021
88027
|
|
|
88022
|
-
if(
|
|
88028
|
+
if (node.isMetanode()) {
|
|
88023
88029
|
// if the metanode isn't still in use in the main app, remove def from here
|
|
88024
|
-
if(
|
|
88030
|
+
if (!this.m.isMetanodeUsed(node.def.module)) {
|
|
88025
88031
|
delete this.m.data.app.metanodes[node.def.module];
|
|
88026
88032
|
}
|
|
88027
88033
|
}
|
|
@@ -88031,7 +88037,7 @@ class Merger {
|
|
|
88031
88037
|
_bindInputs() {
|
|
88032
88038
|
lodash.each(this.inboundLinksFromOutside, (link) => {
|
|
88033
88039
|
// we created an input with the same name, bind it to it
|
|
88034
|
-
this.def.modules[link.targetId].links[link.targetInput] = { "input"
|
|
88040
|
+
this.def.modules[link.targetId].links[link.targetInput] = { "input": link.nextTargetInput };
|
|
88035
88041
|
});
|
|
88036
88042
|
}
|
|
88037
88043
|
|
|
@@ -88063,18 +88069,18 @@ class Merger {
|
|
|
88063
88069
|
// compute the bbox of all divs beeing merged, position the new div in the middle
|
|
88064
88070
|
_computeBbox() {
|
|
88065
88071
|
var most = {
|
|
88066
|
-
top:
|
|
88072
|
+
top: +Infinity,
|
|
88067
88073
|
bottom: -Infinity,
|
|
88068
|
-
left:
|
|
88069
|
-
right:
|
|
88074
|
+
left: +Infinity,
|
|
88075
|
+
right: -Infinity
|
|
88070
88076
|
};
|
|
88071
88077
|
|
|
88072
|
-
lodash.each(
|
|
88078
|
+
lodash.each(this.nodes, (node) => {
|
|
88073
88079
|
var pos = node.getPosition();
|
|
88074
|
-
if(
|
|
88075
|
-
if(
|
|
88076
|
-
if(
|
|
88077
|
-
if(
|
|
88080
|
+
if (pos.top < most.top) most.top = pos.top;
|
|
88081
|
+
if (pos.top > most.bottom) most.bottom = pos.top;
|
|
88082
|
+
if (pos.left < most.left) most.left = pos.left;
|
|
88083
|
+
if (pos.left > most.right) most.right = pos.left;
|
|
88078
88084
|
});
|
|
88079
88085
|
|
|
88080
88086
|
return most;
|
|
@@ -88083,11 +88089,11 @@ class Merger {
|
|
|
88083
88089
|
_getPositioningValues() {
|
|
88084
88090
|
// todo: get a better system with the real bbox
|
|
88085
88091
|
return {
|
|
88086
|
-
width
|
|
88087
|
-
height
|
|
88088
|
-
hMargin
|
|
88089
|
-
vMargin
|
|
88090
|
-
divAvgWidth
|
|
88092
|
+
width: 100,
|
|
88093
|
+
height: 80,
|
|
88094
|
+
hMargin: 80,
|
|
88095
|
+
vMargin: 20,
|
|
88096
|
+
divAvgWidth: 150
|
|
88091
88097
|
}
|
|
88092
88098
|
}
|
|
88093
88099
|
|