@dualbox/editor 1.0.39 → 1.0.41
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/html/editor.html +114 -109
- package/js/dist/GraphEditor.js +301 -269
- package/js/dist/GraphEditor.min.js +300 -268
- package/js/src/GraphEditor.js +3 -3
- package/js/src/m/GraphModel.js +160 -157
- package/js/src/v/Selector.js +56 -44
- package/js/src/v/templates/addNode.vue +1 -1
- package/js/src/v/templates/editMainSettings.vue +23 -5
- package/js/src/v/templates/editNodeSettings.vue +29 -16
- package/js/src/v/templates/graphNode.vue +17 -6
- package/js/src/v/templates/main.vue +1 -2
- package/lib/draco/1.3.5/draco_decoder.js +31 -0
- package/lib/draco/1.3.5/draco_decoder.wasm +0 -0
- package/lib/draco/1.3.5/draco_decoder_gltf.js +31 -0
- package/lib/draco/1.3.5/draco_decoder_gltf.wasm +0 -0
- package/lib/draco/1.3.5/draco_encoder.js +33 -0
- package/lib/draco/1.3.5/draco_wasm_wrapper.js +117 -0
- package/lib/draco/1.3.5/draco_wasm_wrapper_gltf.js +117 -0
- package/package.json +1 -1
|
@@ -42610,7 +42610,9 @@ class GraphModel {
|
|
|
42610
42610
|
windows: null
|
|
42611
42611
|
};
|
|
42612
42612
|
this.data.app = this.data.root;
|
|
42613
|
-
this.data.windows = [
|
|
42613
|
+
this.data.windows = [
|
|
42614
|
+
[this.e.rootAppName, this.data.app]
|
|
42615
|
+
];
|
|
42614
42616
|
|
|
42615
42617
|
// An object to save/restore different states of this.data (ctrl-z/ctrl-y)
|
|
42616
42618
|
this.history = new History(this);
|
|
@@ -42629,7 +42631,9 @@ class GraphModel {
|
|
|
42629
42631
|
|
|
42630
42632
|
this.data.root = json;
|
|
42631
42633
|
this.data.app = this.data.root; // reset ptr
|
|
42632
|
-
this.data.windows = [
|
|
42634
|
+
this.data.windows = [
|
|
42635
|
+
[this.e.rootAppName, this.data.app]
|
|
42636
|
+
];
|
|
42633
42637
|
|
|
42634
42638
|
await this.addNativeTypes();
|
|
42635
42639
|
|
|
@@ -42905,24 +42909,21 @@ class GraphModel {
|
|
|
42905
42909
|
return false;
|
|
42906
42910
|
}
|
|
42907
42911
|
var node = this.data.app.modules[id] = desc;
|
|
42908
|
-
}
|
|
42909
|
-
else if (utils.isUI(pkg.name)) {
|
|
42912
|
+
} else if (utils.isUI(pkg.name)) {
|
|
42910
42913
|
this.ensure('ui');
|
|
42911
42914
|
if (this.data.app.ui[id]) {
|
|
42912
42915
|
console.error('Could not add ui ' + id + ': already exists');
|
|
42913
42916
|
return false;
|
|
42914
42917
|
}
|
|
42915
42918
|
var node = this.data.app.ui[id] = desc;
|
|
42916
|
-
}
|
|
42917
|
-
else {
|
|
42919
|
+
} else {
|
|
42918
42920
|
// may be a metanode
|
|
42919
42921
|
var nodeDef = idx_1(this.data.app, o => o.metanodes[pkg.name]);
|
|
42920
42922
|
if (nodeDef) {
|
|
42921
42923
|
this.ensure('modules');
|
|
42922
42924
|
var node = this.data.app.modules[id] = desc;
|
|
42923
42925
|
return node;
|
|
42924
|
-
}
|
|
42925
|
-
else {
|
|
42926
|
+
} else {
|
|
42926
42927
|
throw pkg.name + " is not module or ui, can't add node !";
|
|
42927
42928
|
}
|
|
42928
42929
|
}
|
|
@@ -43037,8 +43038,7 @@ class GraphModel {
|
|
|
43037
43038
|
try {
|
|
43038
43039
|
var n = this.getNode(id);
|
|
43039
43040
|
return true;
|
|
43040
|
-
}
|
|
43041
|
-
catch (e) {
|
|
43041
|
+
} catch (e) {
|
|
43042
43042
|
return false;
|
|
43043
43043
|
}
|
|
43044
43044
|
}
|
|
@@ -43070,8 +43070,7 @@ class GraphModel {
|
|
|
43070
43070
|
.concat(lodash.map(lodash.keys(this.data.app.output), k => this.outputPrefix + k))
|
|
43071
43071
|
.concat(lodash.keys(this.data.app.modules))
|
|
43072
43072
|
.concat(lodash.keys(this.data.app.ui));
|
|
43073
|
-
}
|
|
43074
|
-
else {
|
|
43073
|
+
} else {
|
|
43075
43074
|
throw new Error('unknown node type: ' + type);
|
|
43076
43075
|
}
|
|
43077
43076
|
}
|
|
@@ -43118,11 +43117,9 @@ class GraphModel {
|
|
|
43118
43117
|
node.graphId = id; // for UIs and modules
|
|
43119
43118
|
if (pkgName.startsWith('@dualbox/dualbox-module-') || pkgName.startsWith('dualbox-core')) {
|
|
43120
43119
|
node.type = "module";
|
|
43121
|
-
}
|
|
43122
|
-
else if (pkgName.startsWith('@dualbox/dualbox-ui-')) {
|
|
43120
|
+
} else if (pkgName.startsWith('@dualbox/dualbox-ui-')) {
|
|
43123
43121
|
node.type = "ui";
|
|
43124
|
-
}
|
|
43125
|
-
else {
|
|
43122
|
+
} else {
|
|
43126
43123
|
throw "pkg " + pkgName + " does not appear to be a module or ui";
|
|
43127
43124
|
}
|
|
43128
43125
|
|
|
@@ -43154,11 +43151,9 @@ class GraphModel {
|
|
|
43154
43151
|
prefixId(id, type) {
|
|
43155
43152
|
if (type == "input" && !id.startsWith('in-')) {
|
|
43156
43153
|
return this.inputPrefix + id;
|
|
43157
|
-
}
|
|
43158
|
-
else if (type == "output" && !id.startsWith('out-')) {
|
|
43154
|
+
} else if (type == "output" && !id.startsWith('out-')) {
|
|
43159
43155
|
return this.outputPrefix + id;
|
|
43160
|
-
}
|
|
43161
|
-
else {
|
|
43156
|
+
} else {
|
|
43162
43157
|
return id;
|
|
43163
43158
|
}
|
|
43164
43159
|
}
|
|
@@ -43167,8 +43162,7 @@ class GraphModel {
|
|
|
43167
43162
|
if (typeof v == "string" && v.startsWith('____dualbox_storage')) {
|
|
43168
43163
|
var id = v.replace("____dualbox_storage(", "").slice(0, -1);
|
|
43169
43164
|
return this.data.root.snapshotObjects[id];
|
|
43170
|
-
}
|
|
43171
|
-
else {
|
|
43165
|
+
} else {
|
|
43172
43166
|
return v;
|
|
43173
43167
|
}
|
|
43174
43168
|
}
|
|
@@ -43190,27 +43184,22 @@ class GraphNode {
|
|
|
43190
43184
|
this.type = "input";
|
|
43191
43185
|
this.graphId = id.substring(3); // the id to identify it in the dualbox graph
|
|
43192
43186
|
this.def = this.app.input[this.graphId];
|
|
43193
|
-
}
|
|
43194
|
-
else if (id.startsWith(this.m.outputPrefix)) {
|
|
43187
|
+
} else if (id.startsWith(this.m.outputPrefix)) {
|
|
43195
43188
|
this.type = "output";
|
|
43196
43189
|
this.graphId = id.substring(4);
|
|
43197
43190
|
this.def = this.app.output[this.graphId];
|
|
43198
|
-
}
|
|
43199
|
-
else if (this.app.modules && this.app.modules[id]) {
|
|
43191
|
+
} else if (this.app.modules && this.app.modules[id]) {
|
|
43200
43192
|
this.graphId = id;
|
|
43201
43193
|
this.type = "module";
|
|
43202
43194
|
this.def = this.app.modules[this.graphId];
|
|
43203
|
-
}
|
|
43204
|
-
else if (this.app.ui && this.app.ui[id]) {
|
|
43195
|
+
} else if (this.app.ui && this.app.ui[id]) {
|
|
43205
43196
|
this.graphId = id;
|
|
43206
43197
|
this.type = "ui";
|
|
43207
43198
|
this.def = this.app.ui[this.graphId];
|
|
43208
|
-
}
|
|
43209
|
-
else {
|
|
43199
|
+
} else {
|
|
43210
43200
|
throw "Cant find node " + id;
|
|
43211
43201
|
}
|
|
43212
|
-
}
|
|
43213
|
-
else {
|
|
43202
|
+
} else {
|
|
43214
43203
|
this.def = null;
|
|
43215
43204
|
this.graphId = null;
|
|
43216
43205
|
}
|
|
@@ -43256,8 +43245,9 @@ class GraphNode {
|
|
|
43256
43245
|
|
|
43257
43246
|
// return the input links for a node
|
|
43258
43247
|
getNormalizeLinksDef() {
|
|
43259
|
-
return this.type == "input" || this.type == "output" ?
|
|
43260
|
-
|
|
43248
|
+
return this.type == "input" || this.type == "output" ? {
|
|
43249
|
+
"value": this.def.link
|
|
43250
|
+
} :
|
|
43261
43251
|
this.def.links;
|
|
43262
43252
|
}
|
|
43263
43253
|
|
|
@@ -43299,8 +43289,7 @@ class GraphNode {
|
|
|
43299
43289
|
}
|
|
43300
43290
|
};
|
|
43301
43291
|
return r;
|
|
43302
|
-
}
|
|
43303
|
-
else {
|
|
43292
|
+
} else {
|
|
43304
43293
|
switch (this.type) {
|
|
43305
43294
|
case "input":
|
|
43306
43295
|
case "output":
|
|
@@ -43322,25 +43311,59 @@ class GraphNode {
|
|
|
43322
43311
|
// return the assigned input type if there is one. Else, return the module's definition type for this input
|
|
43323
43312
|
// Also, take loops into account
|
|
43324
43313
|
getInputType(inputName) {
|
|
43325
|
-
var assignedType =
|
|
43314
|
+
var assignedType = this.getInputAssignedType(inputName);
|
|
43326
43315
|
var t = assignedType ? assignedType : this.getDefinitionInputType(inputName);
|
|
43327
43316
|
return this.hasIterator(inputName) ? "Array<" + t + ">" : t;
|
|
43328
43317
|
}
|
|
43329
43318
|
|
|
43330
43319
|
// return the assigned input type if there is one. Else, return the module's definition type for this input
|
|
43331
|
-
getAttributeType(
|
|
43332
|
-
var assignedType =
|
|
43320
|
+
getAttributeType(attrName) {
|
|
43321
|
+
var assignedType = this.getAttributeAssignedType(attrName);
|
|
43333
43322
|
return assignedType ? assignedType : this.getDefinitionAttributeType(inputName);
|
|
43334
43323
|
}
|
|
43335
43324
|
|
|
43325
|
+
getInputAssignedType(inputName) {
|
|
43326
|
+
return lodash.get(this.def, ["assignedTypes", "input", inputName]);
|
|
43327
|
+
}
|
|
43328
|
+
|
|
43329
|
+
getAttributeAssignedType(attrName) {
|
|
43330
|
+
return lodash.get(this.def, ["assignedTypes", "attr", attrName]);
|
|
43331
|
+
}
|
|
43332
|
+
|
|
43336
43333
|
getDefinitionInputType(inputName) {
|
|
43337
43334
|
if ((this.isInput() || this.isOutput()) && inputName == "value") {
|
|
43338
43335
|
return this.getType();
|
|
43339
|
-
}
|
|
43340
|
-
else {
|
|
43336
|
+
} else {
|
|
43341
43337
|
var pkg = this.getPackage();
|
|
43342
|
-
var type = pkg
|
|
43343
|
-
|
|
43338
|
+
var type = lodash.get(pkg, ["dualbox", "input", inputName, "type"]) || "*";
|
|
43339
|
+
|
|
43340
|
+
if (type === "*") {
|
|
43341
|
+
return this.getLinkedType(inputName);
|
|
43342
|
+
} else {
|
|
43343
|
+
return type;
|
|
43344
|
+
}
|
|
43345
|
+
}
|
|
43346
|
+
}
|
|
43347
|
+
|
|
43348
|
+
// resolve typelinks, if some other linked input has user-assigned type already
|
|
43349
|
+
getLinkedType(inputName) {
|
|
43350
|
+
var linkedType = "*";
|
|
43351
|
+
var inputsDescription = lodash.get(this.getPackage(), ["dualbox", "input"]);
|
|
43352
|
+
var inputDef = inputsDescription[inputName];
|
|
43353
|
+
if (inputDef.typeLink) {
|
|
43354
|
+
var typeLink = inputDef.typeLink;
|
|
43355
|
+
var linkedInputs = lodash.pickBy(inputsDescription, v => v.typeLink === typeLink); // linked inputs
|
|
43356
|
+
lodash.each(linkedInputs, (linkedInputDef, linkedInputName) => {
|
|
43357
|
+
var assignedType = this.getInputAssignedType(linkedInputName);
|
|
43358
|
+
if (assignedType !== undefined && assignedType !== null) {
|
|
43359
|
+
linkedType = assignedType;
|
|
43360
|
+
return false; // eol
|
|
43361
|
+
}
|
|
43362
|
+
});
|
|
43363
|
+
|
|
43364
|
+
return linkedType;
|
|
43365
|
+
} else {
|
|
43366
|
+
return inputDef.type; // should be "*"
|
|
43344
43367
|
}
|
|
43345
43368
|
}
|
|
43346
43369
|
|
|
@@ -43384,8 +43407,7 @@ class GraphNode {
|
|
|
43384
43407
|
getDescription() {
|
|
43385
43408
|
if (this.def.desc) {
|
|
43386
43409
|
return this.def.desc;
|
|
43387
|
-
}
|
|
43388
|
-
else {
|
|
43410
|
+
} else {
|
|
43389
43411
|
var pkg = this.getPackage();
|
|
43390
43412
|
return pkg && pkg.description;
|
|
43391
43413
|
}
|
|
@@ -43396,9 +43418,11 @@ class GraphNode {
|
|
|
43396
43418
|
var pkgDefault = pkg && pkg.dualbox && pkg.dualbox.input && pkg.dualbox.input[inputName] && pkg.dualbox.input[inputName].value;
|
|
43397
43419
|
var appDefault = this.def.defaultInputs && this.def.defaultInputs[inputName];
|
|
43398
43420
|
|
|
43399
|
-
if (appDefault !== undefined) {
|
|
43400
|
-
|
|
43401
|
-
else
|
|
43421
|
+
if (appDefault !== undefined) {
|
|
43422
|
+
return appDefault;
|
|
43423
|
+
} else if (pkgDefault !== undefined) {
|
|
43424
|
+
return pkgDefault;
|
|
43425
|
+
} else return undefined;
|
|
43402
43426
|
}
|
|
43403
43427
|
|
|
43404
43428
|
setInputDefaultValue(inputName, val) {
|
|
@@ -43422,15 +43446,13 @@ class GraphNode {
|
|
|
43422
43446
|
getOutputType(outputName) {
|
|
43423
43447
|
if ((this.isInput() || this.isOutput()) && outputName == "value") {
|
|
43424
43448
|
return this.getType();
|
|
43425
|
-
}
|
|
43426
|
-
else {
|
|
43449
|
+
} else {
|
|
43427
43450
|
var pkg = this.getPackage();
|
|
43428
43451
|
var type = idx_1(pkg, o => o.dualbox.output[outputName].type) || "*";
|
|
43429
43452
|
if (this.hasLoop()) {
|
|
43430
43453
|
// if this output is not a feedback, "arrayize" it
|
|
43431
43454
|
return this.hasFeedback(outputName) ? type : "Array<" + type + ">";
|
|
43432
|
-
}
|
|
43433
|
-
else {
|
|
43455
|
+
} else {
|
|
43434
43456
|
return type;
|
|
43435
43457
|
}
|
|
43436
43458
|
}
|
|
@@ -43470,9 +43492,11 @@ class GraphNode {
|
|
|
43470
43492
|
var pkg = this.getPackage();
|
|
43471
43493
|
var pkgDefault = pkg && pkg.dualbox && pkg.dualbox.attr && pkg.dualbox.attr[attrName].value;
|
|
43472
43494
|
var appDefault = this.def.attr && this.def.attr[attrName];
|
|
43473
|
-
if (appDefault !== undefined) {
|
|
43474
|
-
|
|
43475
|
-
else
|
|
43495
|
+
if (appDefault !== undefined) {
|
|
43496
|
+
return appDefault;
|
|
43497
|
+
} else if (pkgDefault !== undefined) {
|
|
43498
|
+
return pkgDefault;
|
|
43499
|
+
} else return undefined;
|
|
43476
43500
|
}
|
|
43477
43501
|
|
|
43478
43502
|
setAttributeValue(attrName, val) {
|
|
@@ -43499,17 +43523,14 @@ class GraphNode {
|
|
|
43499
43523
|
// it's a get
|
|
43500
43524
|
if (srcType === "input") {
|
|
43501
43525
|
return this.getInputDefaultValue(name);
|
|
43502
|
-
}
|
|
43503
|
-
else if (srcType === "attr") {
|
|
43526
|
+
} else if (srcType === "attr") {
|
|
43504
43527
|
return this.getAttributeValue(name);
|
|
43505
43528
|
}
|
|
43506
|
-
}
|
|
43507
|
-
else {
|
|
43529
|
+
} else {
|
|
43508
43530
|
// it's a set
|
|
43509
43531
|
if (srcType === "input") {
|
|
43510
43532
|
return this.setInputDefaultValue(name, val);
|
|
43511
|
-
}
|
|
43512
|
-
else if (srcType === "attr") {
|
|
43533
|
+
} else if (srcType === "attr") {
|
|
43513
43534
|
return this.setAttributeValue(name, val);
|
|
43514
43535
|
}
|
|
43515
43536
|
}
|
|
@@ -43526,8 +43547,7 @@ class GraphNode {
|
|
|
43526
43547
|
getValueType(srcType, name) {
|
|
43527
43548
|
if (srcType === "input") {
|
|
43528
43549
|
return this.getInputType(name);
|
|
43529
|
-
}
|
|
43530
|
-
else if (srcType === "attr") {
|
|
43550
|
+
} else if (srcType === "attr") {
|
|
43531
43551
|
return this.getAttributeType(name);
|
|
43532
43552
|
}
|
|
43533
43553
|
}
|
|
@@ -43790,17 +43810,14 @@ class GraphNode {
|
|
|
43790
43810
|
isInputVisible(inputName) {
|
|
43791
43811
|
if (this.isInput() || this.isOutput()) {
|
|
43792
43812
|
return true;
|
|
43793
|
-
}
|
|
43794
|
-
else {
|
|
43813
|
+
} else {
|
|
43795
43814
|
if (this.isInputConnected(inputName)) {
|
|
43796
43815
|
return true;
|
|
43797
|
-
}
|
|
43798
|
-
else {
|
|
43816
|
+
} else {
|
|
43799
43817
|
var val = idx_1(this.def, o => o.graph.in.visible[inputName]);
|
|
43800
43818
|
if (val !== undefined) {
|
|
43801
43819
|
return val !== false;
|
|
43802
|
-
}
|
|
43803
|
-
else {
|
|
43820
|
+
} else {
|
|
43804
43821
|
// check if the app did set a default value for this input
|
|
43805
43822
|
var defaultVal = idx_1(this.def, o => o.defaultInputs[inputName]);
|
|
43806
43823
|
if (defaultVal !== undefined) {
|
|
@@ -43813,15 +43830,12 @@ class GraphNode {
|
|
|
43813
43830
|
if (pkgDef) {
|
|
43814
43831
|
if (pkgDef.visible === false) {
|
|
43815
43832
|
return false;
|
|
43816
|
-
}
|
|
43817
|
-
else if (pkgDef.value !== undefined) {
|
|
43833
|
+
} else if (pkgDef.value !== undefined) {
|
|
43818
43834
|
return false;
|
|
43819
|
-
}
|
|
43820
|
-
else {
|
|
43835
|
+
} else {
|
|
43821
43836
|
return true;
|
|
43822
43837
|
}
|
|
43823
|
-
}
|
|
43824
|
-
else {
|
|
43838
|
+
} else {
|
|
43825
43839
|
return true;
|
|
43826
43840
|
}
|
|
43827
43841
|
}
|
|
@@ -43832,17 +43846,14 @@ class GraphNode {
|
|
|
43832
43846
|
isOutputVisible(outputName) {
|
|
43833
43847
|
if (this.isInput() || this.isOutput()) {
|
|
43834
43848
|
return true;
|
|
43835
|
-
}
|
|
43836
|
-
else {
|
|
43849
|
+
} else {
|
|
43837
43850
|
if (this.isOutputConnected(outputName)) {
|
|
43838
43851
|
return true;
|
|
43839
|
-
}
|
|
43840
|
-
else {
|
|
43852
|
+
} else {
|
|
43841
43853
|
var val = idx_1(this.def, o => o.graph.out.visible[outputName]);
|
|
43842
43854
|
if (val === false) {
|
|
43843
43855
|
return false;
|
|
43844
|
-
}
|
|
43845
|
-
else {
|
|
43856
|
+
} else {
|
|
43846
43857
|
var pkg = this.getPackage();
|
|
43847
43858
|
var pkgDef = idx_1(pkg, o => o.dualbox.output[outputName]);
|
|
43848
43859
|
return pkgDef.visible !== false;
|
|
@@ -43917,11 +43928,9 @@ class GraphNode {
|
|
|
43917
43928
|
isInputResolvable(input) {
|
|
43918
43929
|
if (this.hasDefaultValue(input)) {
|
|
43919
43930
|
return true;
|
|
43920
|
-
}
|
|
43921
|
-
else if (this.isInputConnected(input)) {
|
|
43931
|
+
} else if (this.isInputConnected(input)) {
|
|
43922
43932
|
return true;
|
|
43923
|
-
}
|
|
43924
|
-
else {
|
|
43933
|
+
} else {
|
|
43925
43934
|
return false;
|
|
43926
43935
|
}
|
|
43927
43936
|
}
|
|
@@ -44005,8 +44014,7 @@ class GraphNode {
|
|
|
44005
44014
|
if ((this.isInput() || this.isOutput()) && inputName === "value") {
|
|
44006
44015
|
var targetId = this.isInput() ? "input" : "output";
|
|
44007
44016
|
var targetInput = this.graphId;
|
|
44008
|
-
}
|
|
44009
|
-
else {
|
|
44017
|
+
} else {
|
|
44010
44018
|
var targetId = this.graphId;
|
|
44011
44019
|
var targetInput = inputName;
|
|
44012
44020
|
}
|
|
@@ -44026,8 +44034,7 @@ class GraphNode {
|
|
|
44026
44034
|
if ((this.isInput() || this.isOutput()) && outputName === "value") {
|
|
44027
44035
|
var sourceId = this.isInput() ? "input" : "output";
|
|
44028
44036
|
var sourceOutput = this.graphId;
|
|
44029
|
-
}
|
|
44030
|
-
else {
|
|
44037
|
+
} else {
|
|
44031
44038
|
var sourceId = this.graphId;
|
|
44032
44039
|
var sourceOutput = outputName;
|
|
44033
44040
|
}
|
|
@@ -44117,7 +44124,10 @@ class GraphNode {
|
|
|
44117
44124
|
}
|
|
44118
44125
|
|
|
44119
44126
|
getPosition() {
|
|
44120
|
-
var pos = this.def.graph && this.def.graph.position || {
|
|
44127
|
+
var pos = this.def.graph && this.def.graph.position || {
|
|
44128
|
+
left: 0,
|
|
44129
|
+
top: 0
|
|
44130
|
+
};
|
|
44121
44131
|
pos.top = parseInt(pos.top);
|
|
44122
44132
|
pos.left = parseInt(pos.left);
|
|
44123
44133
|
return pos;
|
|
@@ -44138,8 +44148,7 @@ class GraphNode {
|
|
|
44138
44148
|
if (nodeId == id) {
|
|
44139
44149
|
if (this.isInput() || this.isOutput()) {
|
|
44140
44150
|
delete this.def.link;
|
|
44141
|
-
}
|
|
44142
|
-
else {
|
|
44151
|
+
} else {
|
|
44143
44152
|
delete this.def.links[inputName];
|
|
44144
44153
|
}
|
|
44145
44154
|
}
|
|
@@ -44184,10 +44193,18 @@ class GraphNode {
|
|
|
44184
44193
|
|
|
44185
44194
|
addTo(app) {
|
|
44186
44195
|
switch (this.type) {
|
|
44187
|
-
case "module":
|
|
44188
|
-
|
|
44189
|
-
|
|
44190
|
-
case "
|
|
44196
|
+
case "module":
|
|
44197
|
+
app.modules[this.graphId] = this.def;
|
|
44198
|
+
break;
|
|
44199
|
+
case "ui":
|
|
44200
|
+
app.ui[this.graphId] = this.def;
|
|
44201
|
+
break;
|
|
44202
|
+
case "input":
|
|
44203
|
+
app.input[this.graphId] = this.def;
|
|
44204
|
+
break;
|
|
44205
|
+
case "output":
|
|
44206
|
+
app.output[this.graphId] = this.def;
|
|
44207
|
+
break;
|
|
44191
44208
|
default:
|
|
44192
44209
|
throw "wtf";
|
|
44193
44210
|
}
|
|
@@ -44198,8 +44215,12 @@ class GraphNode {
|
|
|
44198
44215
|
this.detachEvents();
|
|
44199
44216
|
|
|
44200
44217
|
switch (this.type) {
|
|
44201
|
-
case "module":
|
|
44202
|
-
|
|
44218
|
+
case "module":
|
|
44219
|
+
delete app.modules[this.graphId];
|
|
44220
|
+
break;
|
|
44221
|
+
case "ui":
|
|
44222
|
+
delete app.ui[this.graphId];
|
|
44223
|
+
break;
|
|
44203
44224
|
case "input":
|
|
44204
44225
|
delete app.input[this.graphId];
|
|
44205
44226
|
if (!this.m.isRootApp(app)) {
|
|
@@ -44301,22 +44322,18 @@ class GraphNode {
|
|
|
44301
44322
|
if (this.isInput()) {
|
|
44302
44323
|
if (newId.startsWith(this.m.inputPrefix)) {
|
|
44303
44324
|
newGraphId = newId.substring(3);
|
|
44304
|
-
}
|
|
44305
|
-
else {
|
|
44325
|
+
} else {
|
|
44306
44326
|
newGraphId = newId;
|
|
44307
44327
|
newId = this.m.inputPrefix + newId;
|
|
44308
44328
|
}
|
|
44309
|
-
}
|
|
44310
|
-
else if (this.isOutput()) {
|
|
44329
|
+
} else if (this.isOutput()) {
|
|
44311
44330
|
if (newId.startsWith(this.m.outputPrefix)) {
|
|
44312
44331
|
newGraphId = newId.substring(4);
|
|
44313
|
-
}
|
|
44314
|
-
else {
|
|
44332
|
+
} else {
|
|
44315
44333
|
newGraphId = newId;
|
|
44316
44334
|
newId = this.m.outputPrefix + newId;
|
|
44317
44335
|
}
|
|
44318
|
-
}
|
|
44319
|
-
else {
|
|
44336
|
+
} else {
|
|
44320
44337
|
newGraphId = newId;
|
|
44321
44338
|
}
|
|
44322
44339
|
|
|
@@ -44372,8 +44389,7 @@ class GraphNode {
|
|
|
44372
44389
|
}
|
|
44373
44390
|
});
|
|
44374
44391
|
});
|
|
44375
|
-
}
|
|
44376
|
-
else if (this.isOutput()) {
|
|
44392
|
+
} else if (this.isOutput()) {
|
|
44377
44393
|
// get inboundLinks of this node that target this input, and detach them
|
|
44378
44394
|
lodash.each(parentNodes, (n) => {
|
|
44379
44395
|
lodash.each(n.getOutboundLinks(), (l) => {
|
|
@@ -44416,8 +44432,7 @@ class GraphNode {
|
|
|
44416
44432
|
lodash.each(links2node, (link) => {
|
|
44417
44433
|
if (link.sourceId == "input" || link.sourceId == "output") {
|
|
44418
44434
|
link.sourceOutput = newId;
|
|
44419
|
-
}
|
|
44420
|
-
else {
|
|
44435
|
+
} else {
|
|
44421
44436
|
link.sourceId = newId;
|
|
44422
44437
|
}
|
|
44423
44438
|
link.attach();
|
|
@@ -44480,8 +44495,7 @@ class DataLink {
|
|
|
44480
44495
|
if (sourceNode.isInput()) {
|
|
44481
44496
|
this.sourceId = "input";
|
|
44482
44497
|
this.sourceOutput = this.m.inputPrefix + sourceNode.graphId;
|
|
44483
|
-
}
|
|
44484
|
-
else if (sourceNode.isOutput()) {
|
|
44498
|
+
} else if (sourceNode.isOutput()) {
|
|
44485
44499
|
this.sourceId = "output";
|
|
44486
44500
|
this.sourceOutput = this.m.outputPrefix + sourceNode.graphId;
|
|
44487
44501
|
}
|
|
@@ -44490,8 +44504,7 @@ class DataLink {
|
|
|
44490
44504
|
if (targetNode.isInput()) {
|
|
44491
44505
|
this.targetId = "input";
|
|
44492
44506
|
this.targetInput = this.m.inputPrefix + targetNode.graphId;
|
|
44493
|
-
}
|
|
44494
|
-
else if (targetNode.isOutput()) {
|
|
44507
|
+
} else if (targetNode.isOutput()) {
|
|
44495
44508
|
this.targetId = "output";
|
|
44496
44509
|
this.targetInput = this.m.outputPrefix + targetNode.graphId;
|
|
44497
44510
|
}
|
|
@@ -44501,20 +44514,16 @@ class DataLink {
|
|
|
44501
44514
|
if (this.sourceId === "input") {
|
|
44502
44515
|
if (this.sourceOutput.startsWith(this.m.inputPrefix)) {
|
|
44503
44516
|
return this.m.getNode(this.sourceOutput);
|
|
44504
|
-
}
|
|
44505
|
-
else {
|
|
44517
|
+
} else {
|
|
44506
44518
|
return this.m.getNode(this.m.inputPrefix + this.sourceOutput);
|
|
44507
44519
|
}
|
|
44508
|
-
}
|
|
44509
|
-
else if (this.sourceId === "output") {
|
|
44520
|
+
} else if (this.sourceId === "output") {
|
|
44510
44521
|
if (this.sourceOutput.startsWith(this.m.outputPrefix)) {
|
|
44511
44522
|
return this.m.getNode(this.sourceOutput);
|
|
44512
|
-
}
|
|
44513
|
-
else {
|
|
44523
|
+
} else {
|
|
44514
44524
|
return this.m.getNode(this.m.outputPrefix + this.sourceOutput);
|
|
44515
44525
|
}
|
|
44516
|
-
}
|
|
44517
|
-
else {
|
|
44526
|
+
} else {
|
|
44518
44527
|
return this.m.getNode(this.sourceId);
|
|
44519
44528
|
}
|
|
44520
44529
|
}
|
|
@@ -44523,20 +44532,16 @@ class DataLink {
|
|
|
44523
44532
|
if (this.targetId === "input") {
|
|
44524
44533
|
if (this.targetInput.startsWith(this.m.inputPrefix)) {
|
|
44525
44534
|
return this.m.getNode(this.targetInput);
|
|
44526
|
-
}
|
|
44527
|
-
else {
|
|
44535
|
+
} else {
|
|
44528
44536
|
return this.m.getNode(this.m.inputPrefix + this.targetInput);
|
|
44529
44537
|
}
|
|
44530
|
-
}
|
|
44531
|
-
else if (this.targetId == "output") {
|
|
44538
|
+
} else if (this.targetId == "output") {
|
|
44532
44539
|
if (this.targetInput.startsWith(this.m.outputPrefix)) {
|
|
44533
44540
|
return this.m.getNode(this.targetInput);
|
|
44534
|
-
}
|
|
44535
|
-
else {
|
|
44541
|
+
} else {
|
|
44536
44542
|
return this.m.getNode(this.m.outputPrefix + this.targetInput);
|
|
44537
44543
|
}
|
|
44538
|
-
}
|
|
44539
|
-
else {
|
|
44544
|
+
} else {
|
|
44540
44545
|
return this.m.getNode(this.targetId);
|
|
44541
44546
|
}
|
|
44542
44547
|
}
|
|
@@ -44558,8 +44563,7 @@ class DataLink {
|
|
|
44558
44563
|
def.graph = def.graph || {};
|
|
44559
44564
|
def.graph.path = def.graph.path || [];
|
|
44560
44565
|
def.graph.path.unshift(pos);
|
|
44561
|
-
}
|
|
44562
|
-
else {
|
|
44566
|
+
} else {
|
|
44563
44567
|
// we need to find pos1 in the array to add pos at the right location
|
|
44564
44568
|
var index;
|
|
44565
44569
|
lodash.each(def.graph.path, (p, i) => {
|
|
@@ -44607,11 +44611,9 @@ class DataLink {
|
|
|
44607
44611
|
var targetNode = this.getTargetNode();
|
|
44608
44612
|
if (targetNode.isInput()) {
|
|
44609
44613
|
return targetNode.def.link;
|
|
44610
|
-
}
|
|
44611
|
-
else if (targetNode.isOutput()) {
|
|
44614
|
+
} else if (targetNode.isOutput()) {
|
|
44612
44615
|
return targetNode.def.link;
|
|
44613
|
-
}
|
|
44614
|
-
else {
|
|
44616
|
+
} else {
|
|
44615
44617
|
return targetNode.def.links && targetNode.def.links[this.targetInput] || {};
|
|
44616
44618
|
}
|
|
44617
44619
|
}
|
|
@@ -44624,11 +44626,9 @@ class DataLink {
|
|
|
44624
44626
|
var targetNode = this.getTargetNode();
|
|
44625
44627
|
if (targetNode.isInput()) {
|
|
44626
44628
|
targetNode.def.link = def;
|
|
44627
|
-
}
|
|
44628
|
-
else if (targetNode.isOutput()) {
|
|
44629
|
+
} else if (targetNode.isOutput()) {
|
|
44629
44630
|
targetNode.def.link = def;
|
|
44630
|
-
}
|
|
44631
|
-
else {
|
|
44631
|
+
} else {
|
|
44632
44632
|
targetNode.def.links = targetNode.def.links || {};
|
|
44633
44633
|
targetNode.def.links[this.targetInput] = def;
|
|
44634
44634
|
}
|
|
@@ -44646,12 +44646,14 @@ class DataLink {
|
|
|
44646
44646
|
// build the connection object
|
|
44647
44647
|
var sourceNode = this.getSourceNode();
|
|
44648
44648
|
if (sourceNode.isInput()) {
|
|
44649
|
-
var connection = {
|
|
44650
|
-
|
|
44651
|
-
|
|
44652
|
-
|
|
44653
|
-
|
|
44654
|
-
|
|
44649
|
+
var connection = {
|
|
44650
|
+
"input": sourceNode.graphId
|
|
44651
|
+
};
|
|
44652
|
+
} else if (sourceNode.isOutput()) {
|
|
44653
|
+
var connection = {
|
|
44654
|
+
"output": sourceNode.graphId
|
|
44655
|
+
};
|
|
44656
|
+
} else {
|
|
44655
44657
|
var connection = {};
|
|
44656
44658
|
connection[sourceNode.graphId] = this.sourceOutput;
|
|
44657
44659
|
}
|
|
@@ -44666,7 +44668,7 @@ class DataLink {
|
|
|
44666
44668
|
var l = new DataLink(this.m, key, val, this.targetId, this.targetInput);
|
|
44667
44669
|
if (!this.equals(l)) {
|
|
44668
44670
|
throw "Can not add link " + this.sourceId + ":" + this.sourceOutput + " -> " +
|
|
44669
|
-
|
|
44671
|
+
this.targetId + ":" + this.targetInput + " : a link already exist to target input";
|
|
44670
44672
|
}
|
|
44671
44673
|
}
|
|
44672
44674
|
|
|
@@ -44678,8 +44680,7 @@ class DataLink {
|
|
|
44678
44680
|
var targetNode = this.getTargetNode();
|
|
44679
44681
|
if (targetNode.isInput() || targetNode.isOutput()) {
|
|
44680
44682
|
delete targetNode.def.link;
|
|
44681
|
-
}
|
|
44682
|
-
else {
|
|
44683
|
+
} else {
|
|
44683
44684
|
delete targetNode.def.links[this.targetInput];
|
|
44684
44685
|
}
|
|
44685
44686
|
}
|
|
@@ -44731,8 +44732,7 @@ class EventLink {
|
|
|
44731
44732
|
|
|
44732
44733
|
if (index) {
|
|
44733
44734
|
n.def.events[index] = def;
|
|
44734
|
-
}
|
|
44735
|
-
else {
|
|
44735
|
+
} else {
|
|
44736
44736
|
n.def.events.push(def);
|
|
44737
44737
|
}
|
|
44738
44738
|
}
|
|
@@ -44767,8 +44767,7 @@ class EventLink {
|
|
|
44767
44767
|
def.graph = def.graph || {};
|
|
44768
44768
|
def.graph.path = def.graph.path || [];
|
|
44769
44769
|
def.graph.path.unshift(pos);
|
|
44770
|
-
}
|
|
44771
|
-
else {
|
|
44770
|
+
} else {
|
|
44772
44771
|
// we need to find pos1 in the array to add pos at the right location
|
|
44773
44772
|
var index;
|
|
44774
44773
|
lodash.each(def.graph.path, (p, i) => {
|
|
@@ -44901,7 +44900,10 @@ class Application {
|
|
|
44901
44900
|
addSubEvent(name, nodeName, evtName) {
|
|
44902
44901
|
var inputEvents = lodash.get(this.json.events, [name, "in"]);
|
|
44903
44902
|
if (!inputEvents) inputEvents = [];
|
|
44904
|
-
inputEvents.push({
|
|
44903
|
+
inputEvents.push({
|
|
44904
|
+
"node": nodeName,
|
|
44905
|
+
"event": evtName
|
|
44906
|
+
});
|
|
44905
44907
|
}
|
|
44906
44908
|
|
|
44907
44909
|
addCallback(name) {
|
|
@@ -44917,7 +44919,9 @@ class Application {
|
|
|
44917
44919
|
}
|
|
44918
44920
|
|
|
44919
44921
|
addAppEvent(name) {
|
|
44920
|
-
this.json.events[name] = {
|
|
44922
|
+
this.json.events[name] = {
|
|
44923
|
+
"in": []
|
|
44924
|
+
};
|
|
44921
44925
|
}
|
|
44922
44926
|
}
|
|
44923
44927
|
|
|
@@ -45706,12 +45710,23 @@ var script = {
|
|
|
45706
45710
|
// resize the canvas if necessary
|
|
45707
45711
|
self.$parent.canvasSizeHandler.debouncedResize();
|
|
45708
45712
|
|
|
45709
|
-
|
|
45710
|
-
|
|
45711
|
-
|
|
45712
|
-
|
|
45713
|
-
|
|
45714
|
-
|
|
45713
|
+
if( self.$parent.selector.isMultipleSelectionActive() ) {
|
|
45714
|
+
// We just dropped a bunch of divs, ajust all their positions
|
|
45715
|
+
self.view.m.history.batch(() => {
|
|
45716
|
+
self.$parent.selector.each(div => {
|
|
45717
|
+
var pos = self.$parent.jsPlumbInstance.getPosition(div);
|
|
45718
|
+
view.m.getNode($(div).attr('id')).setPosition(pos);
|
|
45719
|
+
});
|
|
45720
|
+
});
|
|
45721
|
+
}
|
|
45722
|
+
else {
|
|
45723
|
+
// We just dropped this one, set the new position in the graph model
|
|
45724
|
+
var el = self.$parent.jsPlumbInstance.getElement(id);
|
|
45725
|
+
$(el).ready(function() {
|
|
45726
|
+
var pos = self.$parent.jsPlumbInstance.getPosition(el);
|
|
45727
|
+
view.m.getNode(id).setPosition(pos);
|
|
45728
|
+
});
|
|
45729
|
+
}
|
|
45715
45730
|
}
|
|
45716
45731
|
});
|
|
45717
45732
|
}
|
|
@@ -46348,7 +46363,7 @@ __vue_render__._withStripped = true;
|
|
|
46348
46363
|
/* style */
|
|
46349
46364
|
const __vue_inject_styles__ = function (inject) {
|
|
46350
46365
|
if (!inject) return
|
|
46351
|
-
inject("data-v-0f18803e_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 ],\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() && view.showEvents ) {\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\" },\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 }, 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 // 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 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 });
|
|
46366
|
+
inject("data-v-51e7220d_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 ],\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() && view.showEvents ) {\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\" },\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 }, 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 });
|
|
46352
46367
|
|
|
46353
46368
|
};
|
|
46354
46369
|
/* scoped */
|
|
@@ -46578,15 +46593,19 @@ class Selector {
|
|
|
46578
46593
|
this.parent = parent;
|
|
46579
46594
|
this.container = container;
|
|
46580
46595
|
// translateZ(0) avoid paint glitches in chrome as it forces a repaint every time
|
|
46581
|
-
this.div = $('<div/>', {
|
|
46596
|
+
this.div = $('<div/>', {
|
|
46597
|
+
id: 'selector',
|
|
46598
|
+
hidden: true,
|
|
46599
|
+
style: "border: 1px dotted #000; position: absolute; z-index: 100; transform: translateZ(0);"
|
|
46600
|
+
});
|
|
46582
46601
|
this.x1 = 0;
|
|
46583
46602
|
this.x2 = 0;
|
|
46584
46603
|
this.y1 = 0;
|
|
46585
46604
|
this.y2 = 0;
|
|
46586
46605
|
|
|
46587
46606
|
this.startEventHandler = this.onSelectionStart.bind(this);
|
|
46588
|
-
this.moveEventHandler
|
|
46589
|
-
this.stopEventHandler
|
|
46607
|
+
this.moveEventHandler = this.onSelectionMove.bind(this);
|
|
46608
|
+
this.stopEventHandler = this.onSelectionStop.bind(this);
|
|
46590
46609
|
|
|
46591
46610
|
// offset difference relative to pageX/Y
|
|
46592
46611
|
// we can't use offsetX and offsetY directly cause their value will be 0
|
|
@@ -46607,10 +46626,20 @@ class Selector {
|
|
|
46607
46626
|
this.container.append(this.div);
|
|
46608
46627
|
this.container.off('mousedown', this.startEventHandler);
|
|
46609
46628
|
this.container.off('mousemove', this.moveEventHandler);
|
|
46610
|
-
this.container.off('mouseup',
|
|
46629
|
+
this.container.off('mouseup', this.stopEventHandler);
|
|
46611
46630
|
this.container.on('mousedown', this.startEventHandler);
|
|
46612
46631
|
this.container.on('mousemove', this.moveEventHandler);
|
|
46613
|
-
this.container.on('mouseup',
|
|
46632
|
+
this.container.on('mouseup', this.stopEventHandler);
|
|
46633
|
+
}
|
|
46634
|
+
|
|
46635
|
+
each(cb) {
|
|
46636
|
+
_.each(this.selection, selected => {
|
|
46637
|
+
cb(selected);
|
|
46638
|
+
});
|
|
46639
|
+
}
|
|
46640
|
+
|
|
46641
|
+
isMultipleSelectionActive() {
|
|
46642
|
+
return this.selection.length > 1;
|
|
46614
46643
|
}
|
|
46615
46644
|
|
|
46616
46645
|
getSelection() {
|
|
@@ -46625,7 +46654,7 @@ class Selector {
|
|
|
46625
46654
|
isSelected(div) {
|
|
46626
46655
|
var selected = false;
|
|
46627
46656
|
_.each(this.selection, (selectedDiv) => {
|
|
46628
|
-
if(
|
|
46657
|
+
if ($(div).is($(selectedDiv))) {
|
|
46629
46658
|
selected = true;
|
|
46630
46659
|
return false; // end of loop
|
|
46631
46660
|
}
|
|
@@ -46643,7 +46672,7 @@ class Selector {
|
|
|
46643
46672
|
|
|
46644
46673
|
// find the index
|
|
46645
46674
|
_.each(this.selection, (selectedDiv, index) => {
|
|
46646
|
-
if(
|
|
46675
|
+
if ($(div).is($(selectedDiv))) {
|
|
46647
46676
|
i = index;
|
|
46648
46677
|
return false; // end of loop
|
|
46649
46678
|
}
|
|
@@ -46654,32 +46683,31 @@ class Selector {
|
|
|
46654
46683
|
}
|
|
46655
46684
|
|
|
46656
46685
|
toggleSelection(div) {
|
|
46657
|
-
if(
|
|
46686
|
+
if (this.isSelected(div)) {
|
|
46658
46687
|
this.removeFromSelection(div);
|
|
46659
|
-
}
|
|
46660
|
-
else {
|
|
46688
|
+
} else {
|
|
46661
46689
|
this.addToSelection(div);
|
|
46662
46690
|
}
|
|
46663
46691
|
this.handleSelectionMenu();
|
|
46664
46692
|
}
|
|
46665
46693
|
|
|
46666
|
-
onSelect(
|
|
46694
|
+
onSelect(cb) {
|
|
46667
46695
|
this.onSelectCb = cb;
|
|
46668
46696
|
}
|
|
46669
46697
|
|
|
46670
|
-
onSelecting(
|
|
46698
|
+
onSelecting(cb) {
|
|
46671
46699
|
this.onSelectingCb = cb;
|
|
46672
46700
|
}
|
|
46673
46701
|
|
|
46674
|
-
onDeselect(
|
|
46702
|
+
onDeselect(cb) {
|
|
46675
46703
|
this.onDeselectCb = cb;
|
|
46676
46704
|
}
|
|
46677
46705
|
|
|
46678
46706
|
reCalc() {
|
|
46679
|
-
var x3 = Math.min(this.x1,this.x2);
|
|
46680
|
-
var x4 = Math.max(this.x1,this.x2);
|
|
46681
|
-
var y3 = Math.min(this.y1,this.y2);
|
|
46682
|
-
var y4 = Math.max(this.y1,this.y2);
|
|
46707
|
+
var x3 = Math.min(this.x1, this.x2);
|
|
46708
|
+
var x4 = Math.max(this.x1, this.x2);
|
|
46709
|
+
var y3 = Math.min(this.y1, this.y2);
|
|
46710
|
+
var y4 = Math.max(this.y1, this.y2);
|
|
46683
46711
|
|
|
46684
46712
|
this.div[0].style.left = (x3 - this.diffX) + 'px';
|
|
46685
46713
|
this.div[0].style.top = (y3 - this.diffY) + 'px';
|
|
@@ -46693,19 +46721,19 @@ class Selector {
|
|
|
46693
46721
|
// - it's over the container
|
|
46694
46722
|
// - it's not over a container's button
|
|
46695
46723
|
// - it's not over a "capture-left-click" item
|
|
46696
|
-
if(
|
|
46724
|
+
if (e.which === 1 &&
|
|
46697
46725
|
this.container.find('.btn:hover').length == 0 &&
|
|
46698
46726
|
this.container.find('.nodrag:hover').length == 0 &&
|
|
46699
46727
|
this.container.find('.jtk-connector:hover').length == 0 &&
|
|
46700
46728
|
this.container.find('.capture-left-click:hover').length == 0
|
|
46701
46729
|
) {
|
|
46702
|
-
if(
|
|
46730
|
+
if (this.container.is(':hover')) {
|
|
46703
46731
|
// we're starting a selection
|
|
46704
46732
|
e.preventDefault();
|
|
46705
46733
|
e.stopPropagation();
|
|
46706
46734
|
|
|
46707
46735
|
// remove previous selection
|
|
46708
|
-
if(
|
|
46736
|
+
if (this.onDeselectCb) {
|
|
46709
46737
|
this.onDeselectCb(this.selection);
|
|
46710
46738
|
this.selection = [];
|
|
46711
46739
|
}
|
|
@@ -46725,7 +46753,7 @@ class Selector {
|
|
|
46725
46753
|
}
|
|
46726
46754
|
|
|
46727
46755
|
onSelectionMove(e) {
|
|
46728
|
-
if(
|
|
46756
|
+
if (this.selecting) {
|
|
46729
46757
|
e.preventDefault();
|
|
46730
46758
|
e.stopPropagation();
|
|
46731
46759
|
|
|
@@ -46734,14 +46762,14 @@ class Selector {
|
|
|
46734
46762
|
this.y2 = e.pageY;
|
|
46735
46763
|
this.reCalc();
|
|
46736
46764
|
|
|
46737
|
-
if(
|
|
46765
|
+
if (this.onSelectingCb) {
|
|
46738
46766
|
// now we have our area, find all divs in it and return
|
|
46739
46767
|
// result to the onSelectCb
|
|
46740
46768
|
this.findCardDivs({
|
|
46741
|
-
left
|
|
46742
|
-
right
|
|
46743
|
-
top
|
|
46744
|
-
bottom
|
|
46769
|
+
left: Math.min(this.x1, this.x2),
|
|
46770
|
+
right: Math.max(this.x1, this.x2),
|
|
46771
|
+
top: Math.min(this.y1, this.y2),
|
|
46772
|
+
bottom: Math.max(this.y1, this.y2)
|
|
46745
46773
|
}, (divs) => {
|
|
46746
46774
|
this.selection = divs;
|
|
46747
46775
|
this.handleSelectionMenu();
|
|
@@ -46752,7 +46780,7 @@ class Selector {
|
|
|
46752
46780
|
}
|
|
46753
46781
|
|
|
46754
46782
|
onSelectionStop(e) {
|
|
46755
|
-
if(
|
|
46783
|
+
if (this.selecting && e.which === 1) {
|
|
46756
46784
|
e.preventDefault();
|
|
46757
46785
|
e.stopPropagation();
|
|
46758
46786
|
|
|
@@ -46760,14 +46788,14 @@ class Selector {
|
|
|
46760
46788
|
this.selecting = false;
|
|
46761
46789
|
this.div[0].hidden = 1;
|
|
46762
46790
|
|
|
46763
|
-
if(
|
|
46791
|
+
if (this.onSelectCb) {
|
|
46764
46792
|
// now we have our area, find all divs in it and return
|
|
46765
46793
|
// result to the onSelectCb
|
|
46766
46794
|
this.findCardDivs({
|
|
46767
|
-
left
|
|
46768
|
-
right
|
|
46769
|
-
top
|
|
46770
|
-
bottom
|
|
46795
|
+
left: Math.min(this.x1, this.x2),
|
|
46796
|
+
right: Math.max(this.x1, this.x2),
|
|
46797
|
+
top: Math.min(this.y1, this.y2),
|
|
46798
|
+
bottom: Math.max(this.y1, this.y2)
|
|
46771
46799
|
}, (divs) => {
|
|
46772
46800
|
this.selection = divs;
|
|
46773
46801
|
this.handleSelectionMenu();
|
|
@@ -46777,12 +46805,12 @@ class Selector {
|
|
|
46777
46805
|
}
|
|
46778
46806
|
}
|
|
46779
46807
|
|
|
46780
|
-
findCardDivs(
|
|
46808
|
+
findCardDivs(area, cb) {
|
|
46781
46809
|
var self = this;
|
|
46782
46810
|
var selectedCards = [];
|
|
46783
|
-
this.container.find('.card, .connection-control').each(function() {
|
|
46784
|
-
if(
|
|
46785
|
-
selectedCards.push($(this));
|
|
46811
|
+
this.container.find('.card, .connection-control').each(function () {
|
|
46812
|
+
if (self._intersects($(this), area)) {
|
|
46813
|
+
selectedCards.push($(this)[0]);
|
|
46786
46814
|
}
|
|
46787
46815
|
});
|
|
46788
46816
|
|
|
@@ -46790,22 +46818,21 @@ class Selector {
|
|
|
46790
46818
|
}
|
|
46791
46819
|
|
|
46792
46820
|
// utilities
|
|
46793
|
-
_intersects(
|
|
46821
|
+
_intersects(div, area) {
|
|
46794
46822
|
var r1 = $(div)[0].getBoundingClientRect();
|
|
46795
46823
|
var r2 = area;
|
|
46796
46824
|
var res = !(r2.left > r1.right ||
|
|
46797
|
-
|
|
46798
|
-
|
|
46799
|
-
|
|
46825
|
+
r2.right < r1.left ||
|
|
46826
|
+
r2.top > r1.bottom ||
|
|
46827
|
+
r2.bottom < r1.top);
|
|
46800
46828
|
return res;
|
|
46801
46829
|
}
|
|
46802
46830
|
|
|
46803
46831
|
// show/hide the selection menu if we have more than 2 divs selected
|
|
46804
46832
|
handleSelectionMenu() {
|
|
46805
|
-
if(
|
|
46833
|
+
if (this.selection.length > 1) {
|
|
46806
46834
|
this.parent.view.div.find('.selection-menu').show();
|
|
46807
|
-
}
|
|
46808
|
-
else {
|
|
46835
|
+
} else {
|
|
46809
46836
|
this.parent.view.div.find('.selection-menu').hide();
|
|
46810
46837
|
}
|
|
46811
46838
|
}
|
|
@@ -62150,7 +62177,7 @@ var script$5 = {
|
|
|
62150
62177
|
closeModal: function() {
|
|
62151
62178
|
// don't mutate prop directly, mute the parent
|
|
62152
62179
|
// this.display = false;
|
|
62153
|
-
this.$emit('
|
|
62180
|
+
this.$emit('closed');
|
|
62154
62181
|
},
|
|
62155
62182
|
|
|
62156
62183
|
setSearchFocus : function() {
|
|
@@ -62936,11 +62963,11 @@ __vue_render__$5._withStripped = true;
|
|
|
62936
62963
|
/* style */
|
|
62937
62964
|
const __vue_inject_styles__$5 = function (inject) {
|
|
62938
62965
|
if (!inject) return
|
|
62939
|
-
inject("data-v-11457554_0", { source: "\n.add-node-modal .modal-body[data-v-11457554] {\n height: 70vh;\n}\n.h100[data-v-11457554] {\n height: 100%!important;\n min-height: 100%!important;\n}\n.table-desc th[data-v-11457554], .table-desc td[data-v-11457554] {\n margin-right: 10px;\n}\n#add-node-modal .modal-dialog[data-v-11457554] {\n min-width: calc(100% - 40px)!important;\n height: calc(100% - 40px);\n margin: 20px;\n padding: 0;\n}\n#add-node-modal .modal-content[data-v-11457554] {\n height: auto;\n min-height: 100%;\n border-radius: 0;\n}\n.nav-item[data-v-11457554] {\n margin-left: 15px;\n margin-right: 15px;\n}\n.nav-link[data-v-11457554] {\n padding-left: 4px;\n padding-right: 4px;\n padding-bottom: 4px;\n padding-top: 4px;\n vertical-align: middle;\n position: relative;\n user-select: none;\n}\n.nav-link.active[data-v-11457554] {\n top: 0px;\n border-top-left-radius: 5px;\n border-bottom-left-radius: 5px;\n}\n.nav-link > span[data-v-11457554] {\n padding-left: 10px;\n padding-right: 10px;\n}\n.nav-link.active > span[data-v-11457554] {\n color: black;\n}\n.input-search[data-v-11457554] {\n display: none;\n width: 1px;\n height: 24px;\n box-shadow: none!important;\n border-color: rgba(0,0,0,0.3)!important;\n}\n.nav-link.active .input-search[data-v-11457554] {\n display: inline-block;\n border-top-left-radius: 0px;\n border-bottom-left-radius: 0px;\n transition: width 1s;\n width: 200px;\n}\n.nav-compute > a.active > input[data-v-11457554] {\n background-color: rgba(0,0,0,0.3)!important;\n}\n.nav-compute > a.active[data-v-11457554], .nav-compute > a.active > input[data-v-11457554] {\n background-color: rgba(0,0,0,0.3)!important;\n color: rgba(255,255,255,0.5);\n}\n.nav-compute> a.active > .input-search[data-v-11457554]::placeholder {\n color: rgba(255,255,255,0.5);\n}\n.nav-uis > a.active[data-v-11457554], .nav-uis > a.active > input[data-v-11457554] {\n background-color: #bff2ca!important;\n}\n.nav-inputs > a.active[data-v-11457554] {\n background-color: #f5d76e!important;\n}\n.nav-compute > a.active > input[data-v-11457554] {\n background-color: rgba(0,0,0,0.8);\n}\n.nav-outputs > a.active[data-v-11457554], .nav-outputs > a.active > input[data-v-11457554] {\n background-color: #ffb3a7!important;\n}\n.message-container[data-v-11457554] {\n position: relative;\n width: 100%;\n height: 100%;\n}\n.message[data-v-11457554] {\n position: absolute;\n top: 50%;\n transform: translateY(-80%);\n left: 0;\n right: 0;\n opacity: 0.6;\n text-align: center;\n}\n.tab-content[data-v-11457554], .tab-pane[data-v-11457554] {\n width: 100%;\n height: 100%;\n}\nlabel[data-v-11457554] {\n font-size: 20px;\n margin-top: 20px;\n}\nfieldset[data-v-11457554] {\n border: 1px solid rgba(0,0,0,0.1);\n margin: 10px;\n padding: 20px;\n min-width: 600px;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/addNode.vue"],"names":[],"mappings":";AACA;IACA,YAAA;AACA;AAEA;IACA,sBAAA;IACA,0BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;EACA,sCAAA;EACA,yBAAA;EACA,YAAA;EACA,UAAA;AACA;AAEA;EACA,YAAA;EACA,gBAAA;EACA,gBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,gBAAA;IACA,sBAAA;IACA,kBAAA;IACA,iBAAA;AACA;AAEA;IACA,QAAA;IACA,2BAAA;IACA,8BAAA;AACA;AAEA;IACA,kBAAA;IACA,mBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,aAAA;IACA,UAAA;IACA,YAAA;IACA,0BAAA;IACA,uCAAA;AACA;AAEA;IACA,qBAAA;IACA,2BAAA;IACA,8BAAA;IACA,oBAAA;IACA,YAAA;AACA;AACA;IACA,2CAAA;AACA;AAEA;IACA,2CAAA;IACA,4BAAA;AACA;AAEA;IACA,4BAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,iCAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,kBAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,2BAAA;IACA,OAAA;IACA,QAAA;IACA,YAAA;IACA,kBAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,eAAA;IACA,gBAAA;AACA;AAEA;IACA,iCAAA;IACA,YAAA;IACA,aAAA;IACA,gBAAA;AACA","file":"addNode.vue","sourcesContent":["<style scoped>\n.add-node-modal .modal-body {\n height: 70vh;\n}\n\n.h100 {\n height: 100%!important;\n min-height: 100%!important;\n}\n\n.table-desc th, .table-desc td {\n margin-right: 10px;\n}\n\n#add-node-modal .modal-dialog {\n min-width: calc(100% - 40px)!important;\n height: calc(100% - 40px);\n margin: 20px;\n padding: 0;\n}\n\n#add-node-modal .modal-content {\n height: auto;\n min-height: 100%;\n border-radius: 0;\n}\n\n.nav-item {\n margin-left: 15px;\n margin-right: 15px;\n}\n\n.nav-link {\n padding-left: 4px;\n padding-right: 4px;\n padding-bottom: 4px;\n padding-top: 4px;\n vertical-align: middle;\n position: relative;\n user-select: none;\n}\n\n.nav-link.active {\n top: 0px;\n border-top-left-radius: 5px;\n border-bottom-left-radius: 5px;\n}\n\n.nav-link > span {\n padding-left: 10px;\n padding-right: 10px;\n}\n\n.nav-link.active > span {\n color: black;\n}\n\n.input-search {\n display: none;\n width: 1px;\n height: 24px;\n box-shadow: none!important;\n border-color: rgba(0,0,0,0.3)!important;\n}\n\n.nav-link.active .input-search {\n display: inline-block;\n border-top-left-radius: 0px;\n border-bottom-left-radius: 0px;\n transition: width 1s;\n width: 200px;\n}\n.nav-compute > a.active > input {\n background-color: rgba(0,0,0,0.3)!important;\n}\n\n.nav-compute > a.active, .nav-compute > a.active > input {\n background-color: rgba(0,0,0,0.3)!important;\n color: rgba(255,255,255,0.5);\n}\n\n.nav-compute> a.active > .input-search::placeholder {\n color: rgba(255,255,255,0.5);\n}\n\n.nav-uis > a.active, .nav-uis > a.active > input {\n background-color: #bff2ca!important;\n}\n\n.nav-inputs > a.active {\n background-color: #f5d76e!important;\n}\n\n.nav-compute > a.active > input {\n background-color: rgba(0,0,0,0.8);\n}\n\n.nav-outputs > a.active, .nav-outputs > a.active > input {\n background-color: #ffb3a7!important;\n}\n\n.message-container {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.message {\n position: absolute;\n top: 50%;\n transform: translateY(-80%);\n left: 0;\n right: 0;\n opacity: 0.6;\n text-align: center;\n}\n\n.tab-content, .tab-pane {\n width: 100%;\n height: 100%;\n}\n\nlabel {\n font-size: 20px;\n margin-top: 20px;\n}\n\nfieldset {\n border: 1px solid rgba(0,0,0,0.1);\n margin: 10px;\n padding: 20px;\n min-width: 600px;\n}\n</style>\n\n<template>\n <div class=\"modal fade add-node-modal\" :class=\"{ 'hide' : !display }\" id=\"add-node-modal\" tabindex=\"-1\" role=\"dialog\">\n <div class=\"modal-dialog\" role=\"document\">\n <div class=\"modal-content h100\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">Add Box</h5>\n <ul class=\"nav nav-pills mr-auto ml-2\">\n <li class=\"nav-item nav-compute\">\n <a class=\"nav-link active\" href=\"#add-module-or-ui\" data-toggle=\"pill\" @click=\"selectType('module')\" draggable=\"false\">\n <span>Compute</span>\n <input class=\"form-control input-sm input-search search-modules\" type=\"text\" placeholder=\"Search modules...\" id=\"search-modules\" v-model=\"searchText['module']\" @input=\"searchModules\" autofocus/>\n </a>\n </li>\n <li class=\"nav-item nav-uis\">\n <a class=\"nav-link\" href=\"#add-module-or-ui\" data-toggle=\"pill\" @click=\"selectType('ui')\" draggable=\"false\">\n <span>UI</span>\n <input class=\"form-control input-sm input-search search-ui\" type=\"text\" placeholder=\"Search UIs...\" id=\"search-uis\" @input=\"searchModules\" v-model=\"searchText['ui']\" autofocus/>\n </a>\n </li>\n <li class=\"nav-item nav-inputs\" @click=\"selectType('input')\">\n <a class=\"nav-link\" href=\"#add-input\" data-toggle=\"pill\" draggable=\"false\"><span>Input</span></a>\n </li>\n <li class=\"nav-item nav-outputs\" @click=\"selectType('output')\">\n <a class=\"nav-link\" href=\"#add-output\"data-toggle=\"pill\" draggable=\"false\"><span>Output</span></a>\n </li>\n <li class=\"nav-item nav-outputs\" @click=\"selectType('metanode')\">\n <a class=\"nav-link\" href=\"#add-metanode\"data-toggle=\"pill\" draggable=\"false\"><span>Metabox</span></a>\n </li>\n </ul>\n\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n <div class=\"modal-body\">\n <div class=\"container-fluid h100\">\n\n <div class=\"tab-content\">\n <div class=\"tab-pane active\" id=\"add-module-or-ui\" role=\"tabpanel\" aria-labelledby=\"add-module-or-ui-tab\">\n <div class=\"row h100\">\n <div v-if=\"getSearchText().length == 0\" class=\"message-container\">\n <p class=\"message\"><i class=\"fas fa-search\"></i> Type something to search through the Dualbox library.</p>\n </div>\n <div v-else-if=\"getNbResults() == 0\">\n <p class=\"message\"><i class=\"fas fa-search\"></i> No results.</p>\n </div>\n <template v-else>\n <div class=\"col-md-4 h100\" style=\"padding-left: 0; padding-right: 0; overflow-y: auto; overflow-x: hidden;\">\n <search-results ref=\"searchResults\" :results=\"getResults()\" :err=\"error\" @resultSelected=\"setSelectedResult\"></search-results>\n </div>\n <div class=\"col-md-8 h100\" style=\"padding-left: 15px; padding-right: 0;\">\n <display-result ref=\"displayResults\" v-if=\"getSelectedResult()\" :result=\"getSelectedResult()\"></display-result>\n <div v-else class=\"message-container\">\n <p class=\"message\">Select a result to display</p>\n </div>\n </div>\n </template>\n </div>\n </div>\n <div class=\"tab-pane\" id=\"add-input\" role=\"tabpanel\" aria-labelledby=\"add-input-tab\">\n <div class=\"row\">\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\n <h2 class=\"mt-2\">Add a new input</h2>\n\n <div class=\"form-group\">\n <label for=\"input-name\">Input name:</label>\n <input type=\"text\" class=\"form-control input-name\" id=\"input-name\" placeholder=\"Enter name...\" autofocus required>\n </div>\n\n <div class=\"form-group\">\n <label for=\"input-name\">Input type:</label>\n <input style=\"display: none;\" required/>\n <edit-type ref=\"inputType\" :type=\"inputType\" :displayOKButton=\"false\"></edit-type>\n </div>\n\n <div class=\"form-group\">\n <label for=\"input-description\">Input description:</label>\n <textarea class=\"input-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\n </textarea>\n </div>\n </fieldset>\n </div>\n </div>\n <div class=\"tab-pane\" id=\"add-output\" role=\"tabpanel\" aria-labelledby=\"add-output-tab\">\n <div class=\"row\">\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\n <h2 class=\"mt-2\">Add a new output</h2>\n\n <div class=\"form-group\">\n <label for=\"output-name\">Output name:</label>\n <input type=\"text\" class=\"form-control output-name\" id=\"output-name\" placeholder=\"Enter name...\" autofocus required>\n </div>\n\n <div class=\"form-group\">\n <label for=\"output-name\">Output type:</label>\n <input style=\"display: none;\" required/>\n <edit-type ref=\"outputType\" :type=\"outputType\" :displayOKButton=\"false\"></edit-type>\n </div>\n\n <div class=\"form-group\">\n <label for=\"output-description\">Output description:</label>\n <textarea class=\"output-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\n </textarea>\n </div>\n </fieldset>\n </div>\n </div>\n <div class=\"tab-pane\" id=\"add-metanode\" role=\"tabpanel\" aria-labelledby=\"add-metanode-tab\">\n <div class=\"row\">\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\n <h2 class=\"mt-2\">Add a new Metabox <!--<button class=\"btn btn-outline-secondary float-right\" @click=\"importMetabox\"><i class=\"fas fa-upload\"></i></button>--></h2>\n\n <div class=\"form-group\">\n <label for=\"metanode-name\">Metabox name:</label>\n <input type=\"text\" class=\"form-control metanode-name\" id=\"metanode-name\" placeholder=\"Enter name...\" autofocus required>\n </div>\n\n <div class=\"form-group\">\n <label for=\"metanode-def\">Metabox definition (optional):</label>\n <input type=\"file\" class=\"form-control-file\" id=\"metanode-def\" @change=\"onMetaboxFileSelect\">\n </div>\n\n <div class=\"form-group\">\n <label for=\"metanode-description\">Metabox description:</label>\n <textarea class=\"metanode-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\n </textarea>\n </div>\n </fieldset>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\n <button type=\"button\" class=\"btn btn-primary add-node-btn\" @click=\"addSelectedNode\">Add node</button>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script>\nimport _ from 'lodash';\nimport swal from 'sweetalert2';\nimport SearchResultsVue from './searchResults.vue';\nimport DisplayResultVue from './displayResult.vue';\nimport EditTypeVue from './editType.vue'\n\nexport default {\n props: [\n \"display\", // original state (true = show, false=hide) of the modal\n \"mousePosition\" // mouse position when this panel was opened\n ],\n components: {\n 'search-results' : SearchResultsVue,\n 'display-result' : DisplayResultVue,\n 'edit-type' : EditTypeVue\n },\n data: function () {\n return {\n error: null,\n\n searchText: {}, // the search text, indexed by selectedType\n results: {}, // dictionary of arrays, indexed by selectedType\n selectedResult : {}, // dictionary of string, indexed by selectedType\n selectedType: \"module\",\n inputType: \"*\",\n outputType: \"*\"\n }\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n },\n updated: function() {\n console.log('AddNode updated !');\n this.updateVisibility();\n this.setSearchFocus();\n },\n mounted: function() {\n var self = this;\n this.updateVisibility(); // to init our modal\n\n $(this.$el).on(\"shown.bs.modal\", () => {\n this.setSearchFocus();\n });\n $(this.$el).on(\"hide.bs.modal\", () => {\n self.$emit('closed');\n });\n\n $(this.$el).find('[data-toggle=\"pill\"]').on('shown.bs.tab', (e) => {\n this.setSearchFocus();\n var selectedResult = this.getSelectedResult();\n if( selectedResult ) {\n this.$refs.searchResults.selected = selectedResult.name;\n }\n });\n },\n methods: {\n updateVisibility : function() {\n if( this.display ) {\n $(this.$el).modal(\"show\");\n }\n else {\n $(this.$el).modal(\"hide\");\n }\n },\n\n closeModal: function() {\n // don't mutate prop directly, mute the parent\n // this.display = false;\n this.$emit('close');\n },\n\n setSearchFocus : function() {\n $(this.$el).find('.nav-link.active').find('input').focus();\n },\n\n selectType(t) {\n this.selectedType = t;\n },\n\n addSelectedNode: function(e) {\n switch( this.selectedType ) {\n case \"module\":\n case \"ui\":\n var selectedNode = $('.node-result.selected')[0];\n if( selectedNode ) {\n // add node to the controller\n var packageName = $(selectedNode).data('package');\n this.view.c.addNewBox(packageName, this.mousePosition);\n this.closeModal();\n }\n else {\n swal('Please select a node', '', 'error');\n return;\n }\n break;\n\n case \"input\":\n var type = this.$refs.inputType.get();\n var name = $(this.$el).find('.input-name').val();\n var desc = $(this.$el).find('.input-description').val();\n if( type !== undefined && name ) {\n this.view.c.addInput(name, type, desc, this.mousePosition);\n // reset fields\n this.$refs.inputType.resetChanges();\n $(this.$el).find('.input-name').val(\"\");\n $(this.$el).find('.input-description').val(\"\");\n this.closeModal();\n }\n else {\n swal('Please complete all fields', '', 'error');\n return;\n }\n break;\n\n case \"output\":\n var name = $(this.$el).find('.output-name').val();\n var type = this.$refs.outputType.get();\n var desc = $(this.$el).find('.output-description').val();\n if( type !== undefined && name ) {\n this.view.c.addOutput(name, type, desc, this.mousePosition);\n // reset fields\n this.$refs.outputType.resetChanges();\n $(this.$el).find('.output-name').val(\"\");\n $(this.$el).find('.output-description').val(\"\");\n this.closeModal();\n }\n else {\n swal('Please complete all fields', '', 'error');\n return;\n }\n break;\n\n case \"metanode\":\n var name = $(this.$el).find('.metanode-name').val();\n var desc = $(this.$el).find('.metanode-description').val();\n if( !name ) {\n swal('Please complete name field', '', 'error');\n return;\n }\n\n var json = this.metanodeJSON || {};\n json.description = desc;\n\n this.view.c.addNewMetabox(name, json, this.mousePosition);\n this.closeModal();\n default:\n }\n },\n\n searchModules: async function(e) {\n //var text = $(e.target).val();\n var text = this.searchText[this.selectedType];\n try {\n this.error = null;\n this.results[this.selectedType] = await this.view.e.search(text, this.selectedType);\n this.$forceUpdate();\n }\n catch(e) {\n this.error = e;\n swal('error searching packages', e.reason, \"error\");\n }\n },\n\n getSearchText: function() {\n return this.searchText[this.selectedType] || \"\";\n },\n\n setSelectedResult: function(packageName) {\n // first, find the selected result in the list\n var selectedPackage = null;\n _.each(this.getResults(), (r) => {\n if( r.name == packageName ) {\n selectedPackage = r;\n return false;\n }\n });\n\n if( !selectedPackage ) {\n throw \"Could not find package named \" + packageName;\n }\n\n this.selectedResult[this.selectedType] = selectedPackage;\n this.$forceUpdate();\n },\n\n getSelectedResult: function() {\n return this.selectedResult[this.selectedType];\n },\n\n getResults: function() {\n return this.results[this.selectedType] || null;\n },\n\n getNbResults: function() {\n var results = this.getResults();\n return results && results.length ? results.length: 0;\n },\n\n onMetaboxFileSelect: function(e) {\n var file = e.target.files[0];\n const reader = new FileReader()\n reader.onload = (e) => {\n this.metanodeJSON = JSON.parse(e.target.result);\n if( this.metanodeJSON.description ) {\n $(this.$el).find('.metanode-description').val(this.metanodeJSON.description);\n }\n }\n reader.readAsText(file)\n }\n }\n}\n\n</script>\n\n"]}, media: undefined });
|
|
62966
|
+
inject("data-v-b85f4cf4_0", { source: "\n.add-node-modal .modal-body[data-v-b85f4cf4] {\n height: 70vh;\n}\n.h100[data-v-b85f4cf4] {\n height: 100%!important;\n min-height: 100%!important;\n}\n.table-desc th[data-v-b85f4cf4], .table-desc td[data-v-b85f4cf4] {\n margin-right: 10px;\n}\n#add-node-modal .modal-dialog[data-v-b85f4cf4] {\n min-width: calc(100% - 40px)!important;\n height: calc(100% - 40px);\n margin: 20px;\n padding: 0;\n}\n#add-node-modal .modal-content[data-v-b85f4cf4] {\n height: auto;\n min-height: 100%;\n border-radius: 0;\n}\n.nav-item[data-v-b85f4cf4] {\n margin-left: 15px;\n margin-right: 15px;\n}\n.nav-link[data-v-b85f4cf4] {\n padding-left: 4px;\n padding-right: 4px;\n padding-bottom: 4px;\n padding-top: 4px;\n vertical-align: middle;\n position: relative;\n user-select: none;\n}\n.nav-link.active[data-v-b85f4cf4] {\n top: 0px;\n border-top-left-radius: 5px;\n border-bottom-left-radius: 5px;\n}\n.nav-link > span[data-v-b85f4cf4] {\n padding-left: 10px;\n padding-right: 10px;\n}\n.nav-link.active > span[data-v-b85f4cf4] {\n color: black;\n}\n.input-search[data-v-b85f4cf4] {\n display: none;\n width: 1px;\n height: 24px;\n box-shadow: none!important;\n border-color: rgba(0,0,0,0.3)!important;\n}\n.nav-link.active .input-search[data-v-b85f4cf4] {\n display: inline-block;\n border-top-left-radius: 0px;\n border-bottom-left-radius: 0px;\n transition: width 1s;\n width: 200px;\n}\n.nav-compute > a.active > input[data-v-b85f4cf4] {\n background-color: rgba(0,0,0,0.3)!important;\n}\n.nav-compute > a.active[data-v-b85f4cf4], .nav-compute > a.active > input[data-v-b85f4cf4] {\n background-color: rgba(0,0,0,0.3)!important;\n color: rgba(255,255,255,0.5);\n}\n.nav-compute> a.active > .input-search[data-v-b85f4cf4]::placeholder {\n color: rgba(255,255,255,0.5);\n}\n.nav-uis > a.active[data-v-b85f4cf4], .nav-uis > a.active > input[data-v-b85f4cf4] {\n background-color: #bff2ca!important;\n}\n.nav-inputs > a.active[data-v-b85f4cf4] {\n background-color: #f5d76e!important;\n}\n.nav-compute > a.active > input[data-v-b85f4cf4] {\n background-color: rgba(0,0,0,0.8);\n}\n.nav-outputs > a.active[data-v-b85f4cf4], .nav-outputs > a.active > input[data-v-b85f4cf4] {\n background-color: #ffb3a7!important;\n}\n.message-container[data-v-b85f4cf4] {\n position: relative;\n width: 100%;\n height: 100%;\n}\n.message[data-v-b85f4cf4] {\n position: absolute;\n top: 50%;\n transform: translateY(-80%);\n left: 0;\n right: 0;\n opacity: 0.6;\n text-align: center;\n}\n.tab-content[data-v-b85f4cf4], .tab-pane[data-v-b85f4cf4] {\n width: 100%;\n height: 100%;\n}\nlabel[data-v-b85f4cf4] {\n font-size: 20px;\n margin-top: 20px;\n}\nfieldset[data-v-b85f4cf4] {\n border: 1px solid rgba(0,0,0,0.1);\n margin: 10px;\n padding: 20px;\n min-width: 600px;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/addNode.vue"],"names":[],"mappings":";AACA;IACA,YAAA;AACA;AAEA;IACA,sBAAA;IACA,0BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;EACA,sCAAA;EACA,yBAAA;EACA,YAAA;EACA,UAAA;AACA;AAEA;EACA,YAAA;EACA,gBAAA;EACA,gBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,gBAAA;IACA,sBAAA;IACA,kBAAA;IACA,iBAAA;AACA;AAEA;IACA,QAAA;IACA,2BAAA;IACA,8BAAA;AACA;AAEA;IACA,kBAAA;IACA,mBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,aAAA;IACA,UAAA;IACA,YAAA;IACA,0BAAA;IACA,uCAAA;AACA;AAEA;IACA,qBAAA;IACA,2BAAA;IACA,8BAAA;IACA,oBAAA;IACA,YAAA;AACA;AACA;IACA,2CAAA;AACA;AAEA;IACA,2CAAA;IACA,4BAAA;AACA;AAEA;IACA,4BAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,iCAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,kBAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,2BAAA;IACA,OAAA;IACA,QAAA;IACA,YAAA;IACA,kBAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,eAAA;IACA,gBAAA;AACA;AAEA;IACA,iCAAA;IACA,YAAA;IACA,aAAA;IACA,gBAAA;AACA","file":"addNode.vue","sourcesContent":["<style scoped>\n.add-node-modal .modal-body {\n height: 70vh;\n}\n\n.h100 {\n height: 100%!important;\n min-height: 100%!important;\n}\n\n.table-desc th, .table-desc td {\n margin-right: 10px;\n}\n\n#add-node-modal .modal-dialog {\n min-width: calc(100% - 40px)!important;\n height: calc(100% - 40px);\n margin: 20px;\n padding: 0;\n}\n\n#add-node-modal .modal-content {\n height: auto;\n min-height: 100%;\n border-radius: 0;\n}\n\n.nav-item {\n margin-left: 15px;\n margin-right: 15px;\n}\n\n.nav-link {\n padding-left: 4px;\n padding-right: 4px;\n padding-bottom: 4px;\n padding-top: 4px;\n vertical-align: middle;\n position: relative;\n user-select: none;\n}\n\n.nav-link.active {\n top: 0px;\n border-top-left-radius: 5px;\n border-bottom-left-radius: 5px;\n}\n\n.nav-link > span {\n padding-left: 10px;\n padding-right: 10px;\n}\n\n.nav-link.active > span {\n color: black;\n}\n\n.input-search {\n display: none;\n width: 1px;\n height: 24px;\n box-shadow: none!important;\n border-color: rgba(0,0,0,0.3)!important;\n}\n\n.nav-link.active .input-search {\n display: inline-block;\n border-top-left-radius: 0px;\n border-bottom-left-radius: 0px;\n transition: width 1s;\n width: 200px;\n}\n.nav-compute > a.active > input {\n background-color: rgba(0,0,0,0.3)!important;\n}\n\n.nav-compute > a.active, .nav-compute > a.active > input {\n background-color: rgba(0,0,0,0.3)!important;\n color: rgba(255,255,255,0.5);\n}\n\n.nav-compute> a.active > .input-search::placeholder {\n color: rgba(255,255,255,0.5);\n}\n\n.nav-uis > a.active, .nav-uis > a.active > input {\n background-color: #bff2ca!important;\n}\n\n.nav-inputs > a.active {\n background-color: #f5d76e!important;\n}\n\n.nav-compute > a.active > input {\n background-color: rgba(0,0,0,0.8);\n}\n\n.nav-outputs > a.active, .nav-outputs > a.active > input {\n background-color: #ffb3a7!important;\n}\n\n.message-container {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.message {\n position: absolute;\n top: 50%;\n transform: translateY(-80%);\n left: 0;\n right: 0;\n opacity: 0.6;\n text-align: center;\n}\n\n.tab-content, .tab-pane {\n width: 100%;\n height: 100%;\n}\n\nlabel {\n font-size: 20px;\n margin-top: 20px;\n}\n\nfieldset {\n border: 1px solid rgba(0,0,0,0.1);\n margin: 10px;\n padding: 20px;\n min-width: 600px;\n}\n</style>\n\n<template>\n <div class=\"modal fade add-node-modal\" :class=\"{ 'hide' : !display }\" id=\"add-node-modal\" tabindex=\"-1\" role=\"dialog\">\n <div class=\"modal-dialog\" role=\"document\">\n <div class=\"modal-content h100\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">Add Box</h5>\n <ul class=\"nav nav-pills mr-auto ml-2\">\n <li class=\"nav-item nav-compute\">\n <a class=\"nav-link active\" href=\"#add-module-or-ui\" data-toggle=\"pill\" @click=\"selectType('module')\" draggable=\"false\">\n <span>Compute</span>\n <input class=\"form-control input-sm input-search search-modules\" type=\"text\" placeholder=\"Search modules...\" id=\"search-modules\" v-model=\"searchText['module']\" @input=\"searchModules\" autofocus/>\n </a>\n </li>\n <li class=\"nav-item nav-uis\">\n <a class=\"nav-link\" href=\"#add-module-or-ui\" data-toggle=\"pill\" @click=\"selectType('ui')\" draggable=\"false\">\n <span>UI</span>\n <input class=\"form-control input-sm input-search search-ui\" type=\"text\" placeholder=\"Search UIs...\" id=\"search-uis\" @input=\"searchModules\" v-model=\"searchText['ui']\" autofocus/>\n </a>\n </li>\n <li class=\"nav-item nav-inputs\" @click=\"selectType('input')\">\n <a class=\"nav-link\" href=\"#add-input\" data-toggle=\"pill\" draggable=\"false\"><span>Input</span></a>\n </li>\n <li class=\"nav-item nav-outputs\" @click=\"selectType('output')\">\n <a class=\"nav-link\" href=\"#add-output\"data-toggle=\"pill\" draggable=\"false\"><span>Output</span></a>\n </li>\n <li class=\"nav-item nav-outputs\" @click=\"selectType('metanode')\">\n <a class=\"nav-link\" href=\"#add-metanode\"data-toggle=\"pill\" draggable=\"false\"><span>Metabox</span></a>\n </li>\n </ul>\n\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n <div class=\"modal-body\">\n <div class=\"container-fluid h100\">\n\n <div class=\"tab-content\">\n <div class=\"tab-pane active\" id=\"add-module-or-ui\" role=\"tabpanel\" aria-labelledby=\"add-module-or-ui-tab\">\n <div class=\"row h100\">\n <div v-if=\"getSearchText().length == 0\" class=\"message-container\">\n <p class=\"message\"><i class=\"fas fa-search\"></i> Type something to search through the Dualbox library.</p>\n </div>\n <div v-else-if=\"getNbResults() == 0\">\n <p class=\"message\"><i class=\"fas fa-search\"></i> No results.</p>\n </div>\n <template v-else>\n <div class=\"col-md-4 h100\" style=\"padding-left: 0; padding-right: 0; overflow-y: auto; overflow-x: hidden;\">\n <search-results ref=\"searchResults\" :results=\"getResults()\" :err=\"error\" @resultSelected=\"setSelectedResult\"></search-results>\n </div>\n <div class=\"col-md-8 h100\" style=\"padding-left: 15px; padding-right: 0;\">\n <display-result ref=\"displayResults\" v-if=\"getSelectedResult()\" :result=\"getSelectedResult()\"></display-result>\n <div v-else class=\"message-container\">\n <p class=\"message\">Select a result to display</p>\n </div>\n </div>\n </template>\n </div>\n </div>\n <div class=\"tab-pane\" id=\"add-input\" role=\"tabpanel\" aria-labelledby=\"add-input-tab\">\n <div class=\"row\">\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\n <h2 class=\"mt-2\">Add a new input</h2>\n\n <div class=\"form-group\">\n <label for=\"input-name\">Input name:</label>\n <input type=\"text\" class=\"form-control input-name\" id=\"input-name\" placeholder=\"Enter name...\" autofocus required>\n </div>\n\n <div class=\"form-group\">\n <label for=\"input-name\">Input type:</label>\n <input style=\"display: none;\" required/>\n <edit-type ref=\"inputType\" :type=\"inputType\" :displayOKButton=\"false\"></edit-type>\n </div>\n\n <div class=\"form-group\">\n <label for=\"input-description\">Input description:</label>\n <textarea class=\"input-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\n </textarea>\n </div>\n </fieldset>\n </div>\n </div>\n <div class=\"tab-pane\" id=\"add-output\" role=\"tabpanel\" aria-labelledby=\"add-output-tab\">\n <div class=\"row\">\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\n <h2 class=\"mt-2\">Add a new output</h2>\n\n <div class=\"form-group\">\n <label for=\"output-name\">Output name:</label>\n <input type=\"text\" class=\"form-control output-name\" id=\"output-name\" placeholder=\"Enter name...\" autofocus required>\n </div>\n\n <div class=\"form-group\">\n <label for=\"output-name\">Output type:</label>\n <input style=\"display: none;\" required/>\n <edit-type ref=\"outputType\" :type=\"outputType\" :displayOKButton=\"false\"></edit-type>\n </div>\n\n <div class=\"form-group\">\n <label for=\"output-description\">Output description:</label>\n <textarea class=\"output-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\n </textarea>\n </div>\n </fieldset>\n </div>\n </div>\n <div class=\"tab-pane\" id=\"add-metanode\" role=\"tabpanel\" aria-labelledby=\"add-metanode-tab\">\n <div class=\"row\">\n <fieldset class=\"mx-auto\" style=\"margin-top: 50px;\">\n <h2 class=\"mt-2\">Add a new Metabox <!--<button class=\"btn btn-outline-secondary float-right\" @click=\"importMetabox\"><i class=\"fas fa-upload\"></i></button>--></h2>\n\n <div class=\"form-group\">\n <label for=\"metanode-name\">Metabox name:</label>\n <input type=\"text\" class=\"form-control metanode-name\" id=\"metanode-name\" placeholder=\"Enter name...\" autofocus required>\n </div>\n\n <div class=\"form-group\">\n <label for=\"metanode-def\">Metabox definition (optional):</label>\n <input type=\"file\" class=\"form-control-file\" id=\"metanode-def\" @change=\"onMetaboxFileSelect\">\n </div>\n\n <div class=\"form-group\">\n <label for=\"metanode-description\">Metabox description:</label>\n <textarea class=\"metanode-description\" rows=4 style=\"width: 100%;\" placeholder=\"Enter description\" autofocus>\n </textarea>\n </div>\n </fieldset>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\n <button type=\"button\" class=\"btn btn-primary add-node-btn\" @click=\"addSelectedNode\">Add node</button>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script>\nimport _ from 'lodash';\nimport swal from 'sweetalert2';\nimport SearchResultsVue from './searchResults.vue';\nimport DisplayResultVue from './displayResult.vue';\nimport EditTypeVue from './editType.vue'\n\nexport default {\n props: [\n \"display\", // original state (true = show, false=hide) of the modal\n \"mousePosition\" // mouse position when this panel was opened\n ],\n components: {\n 'search-results' : SearchResultsVue,\n 'display-result' : DisplayResultVue,\n 'edit-type' : EditTypeVue\n },\n data: function () {\n return {\n error: null,\n\n searchText: {}, // the search text, indexed by selectedType\n results: {}, // dictionary of arrays, indexed by selectedType\n selectedResult : {}, // dictionary of string, indexed by selectedType\n selectedType: \"module\",\n inputType: \"*\",\n outputType: \"*\"\n }\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n },\n updated: function() {\n console.log('AddNode updated !');\n this.updateVisibility();\n this.setSearchFocus();\n },\n mounted: function() {\n var self = this;\n this.updateVisibility(); // to init our modal\n\n $(this.$el).on(\"shown.bs.modal\", () => {\n this.setSearchFocus();\n });\n $(this.$el).on(\"hide.bs.modal\", () => {\n self.$emit('closed');\n });\n\n $(this.$el).find('[data-toggle=\"pill\"]').on('shown.bs.tab', (e) => {\n this.setSearchFocus();\n var selectedResult = this.getSelectedResult();\n if( selectedResult ) {\n this.$refs.searchResults.selected = selectedResult.name;\n }\n });\n },\n methods: {\n updateVisibility : function() {\n if( this.display ) {\n $(this.$el).modal(\"show\");\n }\n else {\n $(this.$el).modal(\"hide\");\n }\n },\n\n closeModal: function() {\n // don't mutate prop directly, mute the parent\n // this.display = false;\n this.$emit('closed');\n },\n\n setSearchFocus : function() {\n $(this.$el).find('.nav-link.active').find('input').focus();\n },\n\n selectType(t) {\n this.selectedType = t;\n },\n\n addSelectedNode: function(e) {\n switch( this.selectedType ) {\n case \"module\":\n case \"ui\":\n var selectedNode = $('.node-result.selected')[0];\n if( selectedNode ) {\n // add node to the controller\n var packageName = $(selectedNode).data('package');\n this.view.c.addNewBox(packageName, this.mousePosition);\n this.closeModal();\n }\n else {\n swal('Please select a node', '', 'error');\n return;\n }\n break;\n\n case \"input\":\n var type = this.$refs.inputType.get();\n var name = $(this.$el).find('.input-name').val();\n var desc = $(this.$el).find('.input-description').val();\n if( type !== undefined && name ) {\n this.view.c.addInput(name, type, desc, this.mousePosition);\n // reset fields\n this.$refs.inputType.resetChanges();\n $(this.$el).find('.input-name').val(\"\");\n $(this.$el).find('.input-description').val(\"\");\n this.closeModal();\n }\n else {\n swal('Please complete all fields', '', 'error');\n return;\n }\n break;\n\n case \"output\":\n var name = $(this.$el).find('.output-name').val();\n var type = this.$refs.outputType.get();\n var desc = $(this.$el).find('.output-description').val();\n if( type !== undefined && name ) {\n this.view.c.addOutput(name, type, desc, this.mousePosition);\n // reset fields\n this.$refs.outputType.resetChanges();\n $(this.$el).find('.output-name').val(\"\");\n $(this.$el).find('.output-description').val(\"\");\n this.closeModal();\n }\n else {\n swal('Please complete all fields', '', 'error');\n return;\n }\n break;\n\n case \"metanode\":\n var name = $(this.$el).find('.metanode-name').val();\n var desc = $(this.$el).find('.metanode-description').val();\n if( !name ) {\n swal('Please complete name field', '', 'error');\n return;\n }\n\n var json = this.metanodeJSON || {};\n json.description = desc;\n\n this.view.c.addNewMetabox(name, json, this.mousePosition);\n this.closeModal();\n default:\n }\n },\n\n searchModules: async function(e) {\n //var text = $(e.target).val();\n var text = this.searchText[this.selectedType];\n try {\n this.error = null;\n this.results[this.selectedType] = await this.view.e.search(text, this.selectedType);\n this.$forceUpdate();\n }\n catch(e) {\n this.error = e;\n swal('error searching packages', e.reason, \"error\");\n }\n },\n\n getSearchText: function() {\n return this.searchText[this.selectedType] || \"\";\n },\n\n setSelectedResult: function(packageName) {\n // first, find the selected result in the list\n var selectedPackage = null;\n _.each(this.getResults(), (r) => {\n if( r.name == packageName ) {\n selectedPackage = r;\n return false;\n }\n });\n\n if( !selectedPackage ) {\n throw \"Could not find package named \" + packageName;\n }\n\n this.selectedResult[this.selectedType] = selectedPackage;\n this.$forceUpdate();\n },\n\n getSelectedResult: function() {\n return this.selectedResult[this.selectedType];\n },\n\n getResults: function() {\n return this.results[this.selectedType] || null;\n },\n\n getNbResults: function() {\n var results = this.getResults();\n return results && results.length ? results.length: 0;\n },\n\n onMetaboxFileSelect: function(e) {\n var file = e.target.files[0];\n const reader = new FileReader()\n reader.onload = (e) => {\n this.metanodeJSON = JSON.parse(e.target.result);\n if( this.metanodeJSON.description ) {\n $(this.$el).find('.metanode-description').val(this.metanodeJSON.description);\n }\n }\n reader.readAsText(file)\n }\n }\n}\n\n</script>\n\n"]}, media: undefined });
|
|
62940
62967
|
|
|
62941
62968
|
};
|
|
62942
62969
|
/* scoped */
|
|
62943
|
-
const __vue_scope_id__$5 = "data-v-
|
|
62970
|
+
const __vue_scope_id__$5 = "data-v-b85f4cf4";
|
|
62944
62971
|
/* module identifier */
|
|
62945
62972
|
const __vue_module_identifier__$5 = undefined;
|
|
62946
62973
|
/* functional template */
|
|
@@ -64283,8 +64310,22 @@ var script$a = {
|
|
|
64283
64310
|
mounted: function() {
|
|
64284
64311
|
// bind tooltips
|
|
64285
64312
|
$(this.$el).find('button[data-toggle="tooltip"]').tooltip();
|
|
64313
|
+
this.fixMaxHeightForCategories();
|
|
64314
|
+
},
|
|
64315
|
+
updated: function() {
|
|
64316
|
+
this.fixMaxHeightForCategories();
|
|
64286
64317
|
},
|
|
64287
64318
|
methods: {
|
|
64319
|
+
// setup a max height for each menu, so a scroll appears if there's too much item in it
|
|
64320
|
+
fixMaxHeightForCategories : function() {
|
|
64321
|
+
let nbActiveCategories = $(this.$el).find('.edit-body > .card').length;
|
|
64322
|
+
let headerHeight = $(this.$el).find('.edit-body > .card > .card-header').outerHeight();
|
|
64323
|
+
let panelHeight = $(this.$el).height() - $(this.$el).find('.edit-main-presentation').outerHeight();
|
|
64324
|
+
let maxCategoryHeight = panelHeight - nbActiveCategories * headerHeight;
|
|
64325
|
+
$(this.$el).find('.edit-body').css('height', panelHeight);
|
|
64326
|
+
$(this.$el).find('.edit-body > .card > .collapse > .card-body').css('max-height', maxCategoryHeight + "px");
|
|
64327
|
+
},
|
|
64328
|
+
|
|
64288
64329
|
onEdited: function() {
|
|
64289
64330
|
this.view.repaint();
|
|
64290
64331
|
},
|
|
@@ -64517,7 +64558,7 @@ var __vue_render__$a = function() {
|
|
|
64517
64558
|
[
|
|
64518
64559
|
_vm._m(0),
|
|
64519
64560
|
_vm._v(" "),
|
|
64520
|
-
_c("div", { staticClass: "edit-body" }, [
|
|
64561
|
+
_c("div", { staticClass: "edit-body h100" }, [
|
|
64521
64562
|
_c("div", { staticClass: "card" }, [
|
|
64522
64563
|
_vm._m(1),
|
|
64523
64564
|
_vm._v(" "),
|
|
@@ -65304,6 +65345,7 @@ var __vue_staticRenderFns__$a = [
|
|
|
65304
65345
|
return _c(
|
|
65305
65346
|
"div",
|
|
65306
65347
|
{
|
|
65348
|
+
staticClass: "edit-main-presentation",
|
|
65307
65349
|
staticStyle: {
|
|
65308
65350
|
"padding-left": "10px",
|
|
65309
65351
|
"padding-top": "10px",
|
|
@@ -65311,18 +65353,25 @@ var __vue_staticRenderFns__$a = [
|
|
|
65311
65353
|
}
|
|
65312
65354
|
},
|
|
65313
65355
|
[
|
|
65314
|
-
_c(
|
|
65315
|
-
|
|
65316
|
-
|
|
65317
|
-
|
|
65318
|
-
|
|
65319
|
-
|
|
65320
|
-
|
|
65321
|
-
|
|
65322
|
-
|
|
65323
|
-
|
|
65324
|
-
|
|
65325
|
-
|
|
65356
|
+
_c(
|
|
65357
|
+
"h2",
|
|
65358
|
+
{
|
|
65359
|
+
staticClass: "edit-dualbox-app",
|
|
65360
|
+
staticStyle: { "margin-bottom": "none" }
|
|
65361
|
+
},
|
|
65362
|
+
[
|
|
65363
|
+
_c("div", { staticClass: "dualbox-node-name" }, [
|
|
65364
|
+
_c(
|
|
65365
|
+
"span",
|
|
65366
|
+
{
|
|
65367
|
+
staticClass: "text-truncate d-inline-block",
|
|
65368
|
+
staticStyle: { width: "290px" }
|
|
65369
|
+
},
|
|
65370
|
+
[_vm._v("Application")]
|
|
65371
|
+
)
|
|
65372
|
+
])
|
|
65373
|
+
]
|
|
65374
|
+
)
|
|
65326
65375
|
]
|
|
65327
65376
|
)
|
|
65328
65377
|
},
|
|
@@ -65680,7 +65729,7 @@ __vue_render__$a._withStripped = true;
|
|
|
65680
65729
|
/* style */
|
|
65681
65730
|
const __vue_inject_styles__$a = function (inject) {
|
|
65682
65731
|
if (!inject) return
|
|
65683
|
-
inject("data-v-78348dd6_0", { source: "\n.card-settings .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n}\n.fa {\n pointer-events: none;\n}\n.table-desc {\n width: 100%;\n}\n.table-desc > thead > th > td {\n margin-right: 6px;\n}\n.table-desc > tbody > tr > td {\n margin-right: 6px;\n padding-top: 8px;\n padding-bottom: 8px;\n height: 40px;\n}\n.application-description {\n margin-top: 20px;\n text-align: left;\n font-size: 12px;\n}\n.card-header[data-toggle=\"collapse\"] {\n cursor: pointer;\n}\n.card-header[data-toggle=\"collapse\"] h5 {\n user-select: none;\n}\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\n text-decoration: none;\n}\n.text-value, .number-value, .boolean-value {\n max-width: 140px;\n}\n.select-event-target, .select-event-name, .event-if, .event-data {\n font-size: 12px;\n}\n.edit-body {\n overflow-y: auto;\n overflow-x: hidden;\n max-height: calc(100% - 80px);\n}\n\n/* remove bs4 transition on collapsing */\n.edit-main-panel .collapsing {\n -webkit-transition: none!important;\n transition: none!important;\n display: none!important;\n}\n.table-events .event-rooting {\n margin-top: 10px;\n}\n.table-events thead {\n border-bottom: 1px solid #ddd;\n}\n.table-events .tr-event-condition td {\n padding-left: 10px;\n}\n.table-events .tr-event-data td {\n padding-left: 10px;\n}\n.tr-event-condition td, .tr-event-data td {\n height: 20px!important;\n}\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\n padding-top: 1px!important;\n padding-bottom: 1px!important;\n}\n.table-events tr + .event-rooting {\n /* border-top: 1px solid #ddd; */\n}\n.event-rooting td {\n padding-top: 8px!important;\n padding-bottom: 4px!important;\n}\n.event-data-type {\n font-size: 75%;\n border-radius: 5px;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-data-display {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-if {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\ni.fa, i.fas, i.far {\n pointer-events: none;\n}\n\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/editMainSettings.vue"],"names":[],"mappings":";AACA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,oBAAA;AACA;AAEA;IACA,WAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;IACA,YAAA;AACA;AAEA;IACA,gBAAA;IACA,gBAAA;IACA,eAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,gBAAA;IACA,kBAAA;IACA,6BAAA;AACA;;AAEA,wCAAA;AACA;IACA,kCAAA;IACA,0BAAA;IACA,uBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,gCAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,oBAAA;AACA","file":"editMainSettings.vue","sourcesContent":["<style>\n.card-settings .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n}\n\n.fa {\n pointer-events: none;\n}\n\n.table-desc {\n width: 100%;\n}\n\n.table-desc > thead > th > td {\n margin-right: 6px;\n}\n\n.table-desc > tbody > tr > td {\n margin-right: 6px;\n padding-top: 8px;\n padding-bottom: 8px;\n height: 40px;\n}\n\n.application-description {\n margin-top: 20px;\n text-align: left;\n font-size: 12px;\n}\n\n.card-header[data-toggle=\"collapse\"] {\n cursor: pointer;\n}\n\n.card-header[data-toggle=\"collapse\"] h5 {\n user-select: none;\n}\n\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\n text-decoration: none;\n}\n\n.text-value, .number-value, .boolean-value {\n max-width: 140px;\n}\n\n.select-event-target, .select-event-name, .event-if, .event-data {\n font-size: 12px;\n}\n\n.edit-body {\n overflow-y: auto;\n overflow-x: hidden;\n max-height: calc(100% - 80px);\n}\n\n/* remove bs4 transition on collapsing */\n.edit-main-panel .collapsing {\n -webkit-transition: none!important;\n transition: none!important;\n display: none!important;\n}\n\n.table-events .event-rooting {\n margin-top: 10px;\n}\n\n.table-events thead {\n border-bottom: 1px solid #ddd;\n}\n\n.table-events .tr-event-condition td {\n padding-left: 10px;\n}\n\n.table-events .tr-event-data td {\n padding-left: 10px;\n}\n\n.tr-event-condition td, .tr-event-data td {\n height: 20px!important;\n}\n\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\n padding-top: 1px!important;\n padding-bottom: 1px!important;\n}\n\n.table-events tr + .event-rooting {\n /* border-top: 1px solid #ddd; */\n}\n\n.event-rooting td {\n padding-top: 8px!important;\n padding-bottom: 4px!important;\n}\n\n.event-data-type {\n font-size: 75%;\n border-radius: 5px;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n\n.event-data-display {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n\n.event-if {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n\ni.fa, i.fas, i.far {\n pointer-events: none;\n}\n\n</style>\n\n<template>\n\n<div class=\"edit-main-panel h100\" id=\"edit-main-panel\">\n <div style=\"padding-left: 10px; padding-top: 10px; padding-right: 10px;\">\n <h2 class=\"edit-dualbox-app\">\n <div class=\"dualbox-node-name\">\n <span class=\"text-truncate d-inline-block\" style=\"width: 290px\">Application</span>\n </div>\n </h2>\n </div>\n\n <div class=\"edit-body\">\n <div class=\"card\">\n <div class=\"card-header\" id=\"dualbox-main-desc\" data-toggle=\"collapse\" data-target=\"#dualbox-main-desc-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-main-desc-collapse\">\n <h5 class=\"mb-0 btn-link\">Description</h5>\n </div>\n\n <div id=\"dualbox-main-desc-collapse\" class=\"collapse show\" aria-labelledby=\"dualbox-main-desc\" data-parent=\"#edit-main-panel\">\n <div class=\"card-body\">\n <p class=\"application-description\">{{ app.getDescription() || \"[No description available]\" }} <button class=\"btn btn-editor-xs btn-light btn-edit-app-description\" @click=\"editAppDescription\"><i class=\"fa fa-edit\"></i></button></p>\n </div>\n </div>\n </div>\n <div class=\"card\">\n <div class=\"card-header\" id=\"dualbox-main-events\" data-toggle=\"collapse\" data-target=\"#dualbox-main-events-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-main-events-collapse\">\n <h5 class=\"mb-0 btn-link\">Events</h5>\n </div>\n\n <div id=\"dualbox-main-events-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-main-events\" data-parent=\"#edit-main-panel\">\n <div class=\"card-body\" style=\"padding-left: 4px; padding-right: 4px;\">\n <button class=\"btn btn-success btn-add-app-event mb-3\" @click=\"addAppEvent\">Add application event</button>\n <div v-for=\"key in app.getEventsNames()\" class=\"card\" :key=\"'app-event-' + key\">\n <div class=\"card-header\" :id=\"'dualbox-event-' + key\" data-toggle=\"collapse\" :data-target=\"'#dualbox-event-' + key + '-collapse'\" aria-expanded=\"false\" aria-controls=\"'dualbox-event-' + key + '-collapse'\">\n <h5 class=\"mb-0 btn-link\" style=\"font-size: 16px; font-weight: normal;\">\n {{key}}\n <div class=\"float-right d-inline-block\">\n <button class=\"btn btn-light btn-editor-xs btn-rename-app-event\" :data-event=\"key\" @click=\"renameAppEvent\">\n <i class=\"fa fa-edit\"></i>\n </button>\n <button class=\"btn btn-danger btn-editor-xs btn-remove-app-event\" :data-event=\"key\" @click=\"removeAppEvent\">\n <i class=\"fa fa-minus\"></i>\n </button>\n </div>\n </h5>\n </div>\n\n <div :id=\"'dualbox-event-'+ key + '-collapse'\" class=\"collapse\" :aria-labelledby=\"'dualbox-event-' + key\" data-parent=\"#dualbox-main-events\">\n <div class=\"card-body\" style=\"padding-left: 4px; padding-right: 4px;\">\n <h5 style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Description</h5>\n <p>{{ app.getEventDescription(key) || \"[no description available]\" }} <button class=\"btn btn-editor-xs btn-light btn-edit-event-description\" :data-event=\"key\" @click=\"editEventDescription\"><i class=\"fa fa-edit\"></i></button></p>\n <h5 class=\"mt-3\" style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Triggers</h5>\n\n <table class=\"table-events table-desc\" style=\"font-size: 12px!important;\">\n <thead class=\"thead-dark\">\n <th>Target</th>\n <th>Event</th>\n <!--<th>If</th>-->\n <!--<th>Data</th>-->\n <th>Action</th>\n </thead>\n <tbody>\n <template v-for=\"(evt,index) in app.getEventIn(key)\" :data-index=\"index\">\n <tr class=\"event-rooting\">\n <td>\n <select v-if=\"evt.node !== undefined\" class=\"form-control form-control-sm select-event-target\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" @change=\"selectEventTarget\">\n <option v-for=\"node in getNodesWithInEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()==evt.node\" :key=\"'event-in-target-' + node.getGraphId()\">{{node.getGraphId()}}</option>\n </select>\n <span v-else>{{evt.selector}}</span>\n </td>\n <td>\n <select class=\"form-control form-control-sm select-event-name\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" @change=\"selectEventName\" >\n <template v-if=\"evt.node\">\n <option v-for=\"te in getNodeInEvents(evt.node)\" :value=\"te\" :selected=\"te == evt.event\" :key=\"'app-event-in-target-' + evt.node + '-' + te\">{{te}}</option>\n </template>\n <template v-else>\n <option value=\"hide\">hide</option>\n <option value=\"show\">show</option>\n </template>\n </select>\n </td>\n <td style=\"min-width: 58px;\">\n <button class=\"btn btn-secondary btn-editor-xs\" :data-event=\"key\" :data-index=\"index\" @click=\"toggleAdvancedAppEventSettings\" style=\"margin-left: 10px;\" title=\"Toggle advanced event settings\" >\n <i class=\"fas fa-cog\"></i>\n </button>\n <button class=\"btn btn-danger btn-editor-xs\" :data-event=\"key\" :data-index=\"index\" @click=\"removeInEvent\" >\n <i class=\"fas fa-minus\"></i>\n </button>\n </td>\n </tr>\n <tr v-if=\"evt.if || expanded[key+'##'+index]\" class=\"tr-event-condition\">\n <td colspan=\"3\">\n <span style=\"width: 60px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Occur if:</span>\n\n <input style=\"max-width: 340px; width: 340px;\" class=\"form-control form-control-sm event-if d-inline-block\" type=\"text\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" :value=\"evt.if\" @change=\"setEventIf\" />\n </td>\n </tr>\n <tr v-if=\"evt.data || evt.datatype || expanded[key+'##'+index]\" class=\"tr-event-data\" colspan=\"3\">\n <td colspan=\"3\">\n <span style=\"width: 53px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Data:</span>\n <span style=\"width: 350px;\">\n <display-type :type=\"getDataType(evt)\" @edited=\"onEditEventInDataType(key, index, $event)\"></display-type>\n <display-value :v=\"evt.data\" :type=\"getDataType(evt)\" @edited=\"onEditEventInData(key, index, $event)\"></display-value>\n </span>\n </td>\n </tr>\n </template>\n <tr>\n <td colspan=\"5\" style=\"padding-top: 0px; padding-bottom: 0px;\">\n <button class=\"btn btn-sm btn-add-subevent\" style=\"width: 100%;\" @click=\"addSubEvent(key)\">Add a subevent</button>\n </td>\n </tr>\n </tbody>\n </table>\n\n <h5 class=\"mt-3\" style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Callback</h5>\n\n <table class=\"table-desc table-striped\" style=\"font-size: 12px!important;\">\n <thead class=\"thead-dark\">\n <th>Target</th>\n <th>Event</th>\n <th>Action</th>\n </thead>\n <tbody>\n <tr v-if=\"app.getEventOut(key) !== undefined\">\n <td>\n <select class=\"form-control form-control-sm select-event-target select-callback-target\" dualbox-target=\"events-out\" @change=\"setCallback(key)\">\n <option v-for=\"node in getNodesWithOutEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()===app.getEventOut(key).node\" :key=\"'app-event-out-target-' + node.getGraphId()\">{{ node.getGraphId() }}</option>\n </select>\n </td>\n <td>\n <select class=\"form-control form-control-sm select-event-name select-callback-event\" dualbox-target=\"events-out\">\n <template v-if=\"app.getEventOut(key).node\" @change=\"setCallback(key)\">\n <option v-for=\"(te, index) in getNodeOutEvents(app.getEventOut(key).node)\" :value=\"te\" :selected=\"te == app.getEventOut(key).event\" :key=\"'app-event-out-' + index\">{{te}}</option>\n </template>\n </select>\n </td>\n <td>\n <button class=\"btn btn-danger btn-editor-xs btn-remove-out-event\" :data-event=\"key\" @click=\"removeOutEvent\">\n <i class=\"fa fa-minus\"></i>\n </button>\n </td>\n </tr>\n <tr v-else>\n <td colspan=\"3\" style=\"padding-top: 0px; padding-bottom: 0px;\">\n <button class=\"btn btn-sm btn-add-callback\" style=\"width: 100%;\" @click=\"addCallback(key)\">Add a callback</button>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"modal edit-value-modal\" tabindex=\"-1\" role=\"dialog\">\n <div class=\"modal-dialog\" role=\"document\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">Edit value</h5>\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n <div class=\"modal-body\">\n <div>\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value unset-value\" id=\"unset-value\" name=\"set-value\" value=\"unset-value\" checked>\n <label class=\"form-check-label\" for=\"unset-value\">\n don't set a value\n </label>\n </div>\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value set-value-null\" id=\"set-value-null\" name=\"set-value\" value=\"set-value-null\">\n <label class=\"form-check-label\" for=\"set-value-null\">\n set null\n </label>\n </div>\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value set-value-type\" id=\"set-value-type\" name=\"set-value\" value=\"set-value-type\" aria-label=\"Set a value of type\">\n <div class=\"form-inline form-check-label\" style=\"height: 24px;\">\n <label for=\"set-value-type\">\n set a value of type:\n <select class=\"form-control choose-value-type d-inline-block form-control-sm ml-2\">\n <option value=\"string\">String</option>\n <option value=\"number\">Number</option>\n <option value=\"boolean\">Boolean</option>\n <option value=\"object\">Object</option>\n </select>\n </label>\n </div>\n </div>\n </div>\n <div class=\"has-value\" style=\"display: none;\">\n <hr/>\n <div class=\"define-value define-boolean\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <select class=\"form-control form-control-sm bool-value d-inline-block ml-2\">\n <option value=true>True</option>\n <option value=false>False</option>\n </select>\n </div>\n </div>\n <div class=\"define-value define-number\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <input type=\"number\" class=\"form-control form-control-sm number-value ml-2\"/>\n </div>\n </div>\n <div class=\"define-value define-string\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <input type=\"text\" class=\"form-control form-control-sm text-value ml-2\"/>\n </div>\n </div>\n <div class=\"define-value define-object\" style=\"display: none;\">\n <label>Value: </label>\n <div class=\"json-editor\" style=\"height: 400px;\"></div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-primary btn-save\">Save changes</button>\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n</template>\n\n<script>\nimport _ from 'lodash';\nimport swal from 'sweetalert2';\nimport DisplayTypeVue from './displayType.vue';\nimport DisplayValueVue from './displayValue.vue';\n\nexport default {\n props: [\n \"app\"\n ],\n components: {\n \"display-type\" : DisplayTypeVue,\n \"display-value\" : DisplayValueVue,\n },\n data: function () {\n return {\n expanded: {} // expanded app events (advanced settings)\n };\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n },\n mounted: function() {\n // bind tooltips\n $(this.$el).find('button[data-toggle=\"tooltip\"]').tooltip();\n },\n methods: {\n onEdited: function() {\n this.view.repaint();\n },\n\n getNodesWithInEvents: function() {\n var l = [];\n var nodes = this.view.m.getNodes(\"ui\");\n _.each(nodes, (n) => {\n if( n.getInEventsNames().length > 0 ) {\n l.push(n);\n }\n });\n return l;\n },\n\n getNodesWithOutEvents: function() {\n var l = [];\n var nodes = this.view.m.getNodes(\"ui\");\n _.each(nodes, (n) => {\n if( n.getOutEventsNames().length > 0 ) {\n l.push(n);\n }\n });\n return l;\n },\n\n getNodeEvents: function( nodeId ) {\n var node = this.view.m.getNode(nodeId);\n return node.getEventsNames();\n },\n\n getNodeInEvents: function( nodeId ) {\n var node = this.view.m.getNode(nodeId);\n return node.getInEventsNames();\n },\n\n getNodeOutEvents: function( nodeId ) {\n var node = this.view.m.getNode(nodeId);\n return node.getOutEventsNames();\n },\n\n editAppDescription: function() {\n swal({\n input: 'text',\n title: 'Enter the description',\n }).then((result) => {\n this.view.c.setAppDescription(result.value);\n });\n },\n\n editEventDescription: function(e) {\n var eventName = $(e.target).attr('data-event');\n\n swal({\n input: 'text',\n title: 'Enter the description',\n }).then((result) => {\n this.view.c.setAppEventDescription(eventName, result.value);\n });\n },\n\n removeAppEvent: function(e) {\n var name = $(e.target).attr('data-event');\n this.view.c.removeAppEvent(name);\n this.onEdited();\n },\n\n renameAppEvent: function(e) {\n var name = $(e.target).attr('data-event');\n swal({\n input: 'text',\n title: 'Enter the new event name',\n }).then((result) => {\n if( result.value ) {\n this.view.c.renameAppEvent(name, result.value);\n this.onEdited();\n }\n });\n },\n\n setEventIf: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventIf( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val);\n this.onEdited();\n },\n\n setEventData: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventData( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val);\n this.onEdited();\n },\n\n selectEventTarget: function(e) {\n var target = $(e.target).val();\n\n // change options of closest .select-event-name according to this new target\n var targetNode = this.view.m.getNode(target);\n var targetEvents = targetNode.getEventsNames();\n var select = $(e.target).closest('tr').find('.select-event-name');\n select.html('');\n _.each(targetEvents, (eventName) => {\n select.append( $('<option/>', {\n value: eventName\n }).append(eventName));\n });\n\n var index = parseInt($(e.target).attr('data-index'));\n this.view.c.setEventTarget( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, target);\n this.onEdited();\n },\n\n selectEventName: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventName( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val );\n this.onEdited();\n },\n\n addCallback: function(appEventName) {\n var nodesWithOutEvents = this.getNodesWithOutEvents();\n if( nodesWithOutEvents.length > 0 ) {\n var firstNode = nodesWithOutEvents[0];\n var firstEvent = firstNode.getOutEventsNames()[0];\n this.setCallback(appEventName, firstNode, firstEvent);\n }\n else {\n swal({\n title: \"You can not add an API callback here\",\n text: \"None of the UIs of the application does have an OUT event, usable for API callbacks\",\n type: \"error\"\n })\n }\n },\n\n setCallback: function(appEventName, e) {\n var targetNodeId = $(this.$el).find('.select-callback-target').val();\n var targetNodeEvent = $(this.$el).find('.select-callback-event').val();\n this.view.c.setCallback(appEventName, targetNodeId, targetNodeEvent);\n this.onEdited();\n },\n\n addAppEvent: function(e) {\n swal({\n input: 'text',\n title: 'Enter the event name',\n }).then((result) => {\n this.view.c.addAppEvent(result.value);\n this.onEdited();\n });\n },\n\n removeInEvent: function(e) {\n var eventName = $(e.target).attr('data-event');\n var index = parseInt($(e.target).attr('data-index'));\n this.view.c.removeAppInEvent(eventName, index);\n this.onEdited();\n },\n\n removeOutEvent: function(e) {\n var eventName = $(e.target).attr('data-event');\n this.view.c.removeAppOutEvent(eventName);\n this.onEdited();\n },\n\n addSubEvent: function(eventName) {\n this.view.c.addSubEvent(eventName);\n this.onEdited();\n },\n\n getDataType: function(evt) {\n if( evt.datatype ) {\n return evt.datatype;\n }\n else if( evt.data ) {\n return window.DualBox.Type.detectType(evt.data);\n }\n else {\n return undefined;\n }\n },\n\n toggleAdvancedAppEventSettings: function(e) {\n var key = $(e.target).data('event');\n var index = $(e.target).data('index');\n var k=key+'##'+index;\n this.expanded[k] = this.expanded[k] ? false : true;\n this.$forceUpdate();\n },\n\n onEditEventInData(key, index, val) {\n this.view.c.setEventData( \"#application-events-in-\" + key, index, val);\n this.$emit('edited');\n },\n\n onEditEventInDataType(key, index, type) {\n this.view.c.setEventDataType( \"#application-events-in-\" + key, index, type);\n\n // check that the set value still match the new type\n // delete it otherwise\n var val = this.app.getEventIn(key)[index].data;\n try {\n // TODO: ensure type is already loaded (after dualbox) and remove the try/catch\n if( !window.DualBox.Type.check(type, val) ) {\n // delete data (== set undefined)\n this.view.c.setEventData( \"#application-events-in-\" + key, index, undefined);\n }\n }\n catch(e) {\n this.view.c.setEventData( \"#application-events-in-\" + key, index, undefined);\n }\n\n this.$emit('edited');\n },\n }\n}\n</script>\n"]}, media: undefined });
|
|
65732
|
+
inject("data-v-bdaa381a_0", { source: "\n.card-settings .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n}\n.fa {\n pointer-events: none;\n}\n.table-desc {\n width: 100%;\n}\n.table-desc > thead > th > td {\n margin-right: 6px;\n}\n.table-desc > tbody > tr > td {\n margin-right: 6px;\n padding-top: 8px;\n padding-bottom: 8px;\n height: 40px;\n}\n.application-description {\n margin-top: 20px;\n text-align: left;\n font-size: 12px;\n}\n.card-header[data-toggle=\"collapse\"] {\n cursor: pointer;\n}\n.card-header[data-toggle=\"collapse\"] h5 {\n user-select: none;\n}\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\n text-decoration: none;\n}\n.text-value, .number-value, .boolean-value {\n max-width: 140px;\n}\n.select-event-target, .select-event-name, .event-if, .event-data {\n font-size: 12px;\n}\n.edit-body {\n overflow-y: hidden;\n overflow-x: hidden;\n max-height: calc(100% - 90px);\n}\n\n/* remove bs4 transition on collapsing */\n.edit-main-panel .collapsing {\n -webkit-transition: none!important;\n transition: none!important;\n display: none!important;\n}\n.table-events .event-rooting {\n margin-top: 10px;\n}\n.table-events thead {\n border-bottom: 1px solid #ddd;\n}\n.table-events .tr-event-condition td {\n padding-left: 10px;\n}\n.table-events .tr-event-data td {\n padding-left: 10px;\n}\n.tr-event-condition td, .tr-event-data td {\n height: 20px!important;\n}\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\n padding-top: 1px!important;\n padding-bottom: 1px!important;\n}\n.table-events tr + .event-rooting {\n /* border-top: 1px solid #ddd; */\n}\n.event-rooting td {\n padding-top: 8px!important;\n padding-bottom: 4px!important;\n}\n.event-data-type {\n font-size: 75%;\n border-radius: 5px;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-data-display {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-if {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\ni.fa, i.fas, i.far {\n pointer-events: none;\n}\n.h100 {\n height: 100%;\n}\n\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/editMainSettings.vue"],"names":[],"mappings":";AACA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,oBAAA;AACA;AAEA;IACA,WAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;IACA,YAAA;AACA;AAEA;IACA,gBAAA;IACA,gBAAA;IACA,eAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,kBAAA;IACA,6BAAA;AACA;;AAEA,wCAAA;AACA;IACA,kCAAA;IACA,0BAAA;IACA,uBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,gCAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,oBAAA;AACA;AAEA;IACA,YAAA;AACA","file":"editMainSettings.vue","sourcesContent":["<style>\n.card-settings .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n}\n\n.fa {\n pointer-events: none;\n}\n\n.table-desc {\n width: 100%;\n}\n\n.table-desc > thead > th > td {\n margin-right: 6px;\n}\n\n.table-desc > tbody > tr > td {\n margin-right: 6px;\n padding-top: 8px;\n padding-bottom: 8px;\n height: 40px;\n}\n\n.application-description {\n margin-top: 20px;\n text-align: left;\n font-size: 12px;\n}\n\n.card-header[data-toggle=\"collapse\"] {\n cursor: pointer;\n}\n\n.card-header[data-toggle=\"collapse\"] h5 {\n user-select: none;\n}\n\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\n text-decoration: none;\n}\n\n.text-value, .number-value, .boolean-value {\n max-width: 140px;\n}\n\n.select-event-target, .select-event-name, .event-if, .event-data {\n font-size: 12px;\n}\n\n.edit-body {\n overflow-y: hidden;\n overflow-x: hidden;\n max-height: calc(100% - 90px);\n}\n\n/* remove bs4 transition on collapsing */\n.edit-main-panel .collapsing {\n -webkit-transition: none!important;\n transition: none!important;\n display: none!important;\n}\n\n.table-events .event-rooting {\n margin-top: 10px;\n}\n\n.table-events thead {\n border-bottom: 1px solid #ddd;\n}\n\n.table-events .tr-event-condition td {\n padding-left: 10px;\n}\n\n.table-events .tr-event-data td {\n padding-left: 10px;\n}\n\n.tr-event-condition td, .tr-event-data td {\n height: 20px!important;\n}\n\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\n padding-top: 1px!important;\n padding-bottom: 1px!important;\n}\n\n.table-events tr + .event-rooting {\n /* border-top: 1px solid #ddd; */\n}\n\n.event-rooting td {\n padding-top: 8px!important;\n padding-bottom: 4px!important;\n}\n\n.event-data-type {\n font-size: 75%;\n border-radius: 5px;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n\n.event-data-display {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n\n.event-if {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n\ni.fa, i.fas, i.far {\n pointer-events: none;\n}\n\n.h100 {\n height: 100%;\n}\n\n</style>\n\n<template>\n\n<div class=\"edit-main-panel h100\" id=\"edit-main-panel\">\n <div class=\"edit-main-presentation\" style=\"padding-left: 10px; padding-top: 10px; padding-right: 10px; padding-bottom 10px;\">\n <h2 class=\"edit-dualbox-app\" style=\"margin-bottom: none;\">\n <div class=\"dualbox-node-name\">\n <span class=\"text-truncate d-inline-block\" style=\"width: 290px\">Application</span>\n </div>\n </h2>\n </div>\n\n <div class=\"edit-body h100\">\n <div class=\"card\">\n <div class=\"card-header\" id=\"dualbox-main-desc\" data-toggle=\"collapse\" data-target=\"#dualbox-main-desc-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-main-desc-collapse\">\n <h5 class=\"mb-0 btn-link\">Description</h5>\n </div>\n\n <div id=\"dualbox-main-desc-collapse\" class=\"collapse show\" aria-labelledby=\"dualbox-main-desc\" data-parent=\"#edit-main-panel\">\n <div class=\"card-body\">\n <p class=\"application-description\">{{ app.getDescription() || \"[No description available]\" }} <button class=\"btn btn-editor-xs btn-light btn-edit-app-description\" @click=\"editAppDescription\"><i class=\"fa fa-edit\"></i></button></p>\n </div>\n </div>\n </div>\n <div class=\"card\">\n <div class=\"card-header\" id=\"dualbox-main-events\" data-toggle=\"collapse\" data-target=\"#dualbox-main-events-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-main-events-collapse\">\n <h5 class=\"mb-0 btn-link\">Events</h5>\n </div>\n\n <div id=\"dualbox-main-events-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-main-events\" data-parent=\"#edit-main-panel\">\n <div class=\"card-body\" style=\"padding-left: 4px; padding-right: 4px;\">\n <button class=\"btn btn-success btn-add-app-event mb-3\" @click=\"addAppEvent\">Add application event</button>\n <div v-for=\"key in app.getEventsNames()\" class=\"card\" :key=\"'app-event-' + key\">\n <div class=\"card-header\" :id=\"'dualbox-event-' + key\" data-toggle=\"collapse\" :data-target=\"'#dualbox-event-' + key + '-collapse'\" aria-expanded=\"false\" aria-controls=\"'dualbox-event-' + key + '-collapse'\">\n <h5 class=\"mb-0 btn-link\" style=\"font-size: 16px; font-weight: normal;\">\n {{key}}\n <div class=\"float-right d-inline-block\">\n <button class=\"btn btn-light btn-editor-xs btn-rename-app-event\" :data-event=\"key\" @click=\"renameAppEvent\">\n <i class=\"fa fa-edit\"></i>\n </button>\n <button class=\"btn btn-danger btn-editor-xs btn-remove-app-event\" :data-event=\"key\" @click=\"removeAppEvent\">\n <i class=\"fa fa-minus\"></i>\n </button>\n </div>\n </h5>\n </div>\n\n <div :id=\"'dualbox-event-'+ key + '-collapse'\" class=\"collapse\" :aria-labelledby=\"'dualbox-event-' + key\" data-parent=\"#dualbox-main-events\">\n <div class=\"card-body\" style=\"padding-left: 4px; padding-right: 4px;\">\n <h5 style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Description</h5>\n <p>{{ app.getEventDescription(key) || \"[no description available]\" }} <button class=\"btn btn-editor-xs btn-light btn-edit-event-description\" :data-event=\"key\" @click=\"editEventDescription\"><i class=\"fa fa-edit\"></i></button></p>\n <h5 class=\"mt-3\" style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Triggers</h5>\n\n <table class=\"table-events table-desc\" style=\"font-size: 12px!important;\">\n <thead class=\"thead-dark\">\n <th>Target</th>\n <th>Event</th>\n <!--<th>If</th>-->\n <!--<th>Data</th>-->\n <th>Action</th>\n </thead>\n <tbody>\n <template v-for=\"(evt,index) in app.getEventIn(key)\" :data-index=\"index\">\n <tr class=\"event-rooting\">\n <td>\n <select v-if=\"evt.node !== undefined\" class=\"form-control form-control-sm select-event-target\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" @change=\"selectEventTarget\">\n <option v-for=\"node in getNodesWithInEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()==evt.node\" :key=\"'event-in-target-' + node.getGraphId()\">{{node.getGraphId()}}</option>\n </select>\n <span v-else>{{evt.selector}}</span>\n </td>\n <td>\n <select class=\"form-control form-control-sm select-event-name\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" @change=\"selectEventName\" >\n <template v-if=\"evt.node\">\n <option v-for=\"te in getNodeInEvents(evt.node)\" :value=\"te\" :selected=\"te == evt.event\" :key=\"'app-event-in-target-' + evt.node + '-' + te\">{{te}}</option>\n </template>\n <template v-else>\n <option value=\"hide\">hide</option>\n <option value=\"show\">show</option>\n </template>\n </select>\n </td>\n <td style=\"min-width: 58px;\">\n <button class=\"btn btn-secondary btn-editor-xs\" :data-event=\"key\" :data-index=\"index\" @click=\"toggleAdvancedAppEventSettings\" style=\"margin-left: 10px;\" title=\"Toggle advanced event settings\" >\n <i class=\"fas fa-cog\"></i>\n </button>\n <button class=\"btn btn-danger btn-editor-xs\" :data-event=\"key\" :data-index=\"index\" @click=\"removeInEvent\" >\n <i class=\"fas fa-minus\"></i>\n </button>\n </td>\n </tr>\n <tr v-if=\"evt.if || expanded[key+'##'+index]\" class=\"tr-event-condition\">\n <td colspan=\"3\">\n <span style=\"width: 60px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Occur if:</span>\n\n <input style=\"max-width: 340px; width: 340px;\" class=\"form-control form-control-sm event-if d-inline-block\" type=\"text\" dualbox-target=\"events-in\" :data-event=\"key\" :data-index=\"index\" :value=\"evt.if\" @change=\"setEventIf\" />\n </td>\n </tr>\n <tr v-if=\"evt.data || evt.datatype || expanded[key+'##'+index]\" class=\"tr-event-data\" colspan=\"3\">\n <td colspan=\"3\">\n <span style=\"width: 53px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Data:</span>\n <span style=\"width: 350px;\">\n <display-type :type=\"getDataType(evt)\" @edited=\"onEditEventInDataType(key, index, $event)\"></display-type>\n <display-value :v=\"evt.data\" :type=\"getDataType(evt)\" @edited=\"onEditEventInData(key, index, $event)\"></display-value>\n </span>\n </td>\n </tr>\n </template>\n <tr>\n <td colspan=\"5\" style=\"padding-top: 0px; padding-bottom: 0px;\">\n <button class=\"btn btn-sm btn-add-subevent\" style=\"width: 100%;\" @click=\"addSubEvent(key)\">Add a subevent</button>\n </td>\n </tr>\n </tbody>\n </table>\n\n <h5 class=\"mt-3\" style=\"font-size: 16px; text-decoration: underline; font-weight: normal;\">Callback</h5>\n\n <table class=\"table-desc table-striped\" style=\"font-size: 12px!important;\">\n <thead class=\"thead-dark\">\n <th>Target</th>\n <th>Event</th>\n <th>Action</th>\n </thead>\n <tbody>\n <tr v-if=\"app.getEventOut(key) !== undefined\">\n <td>\n <select class=\"form-control form-control-sm select-event-target select-callback-target\" dualbox-target=\"events-out\" @change=\"setCallback(key)\">\n <option v-for=\"node in getNodesWithOutEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()===app.getEventOut(key).node\" :key=\"'app-event-out-target-' + node.getGraphId()\">{{ node.getGraphId() }}</option>\n </select>\n </td>\n <td>\n <select class=\"form-control form-control-sm select-event-name select-callback-event\" dualbox-target=\"events-out\">\n <template v-if=\"app.getEventOut(key).node\" @change=\"setCallback(key)\">\n <option v-for=\"(te, index) in getNodeOutEvents(app.getEventOut(key).node)\" :value=\"te\" :selected=\"te == app.getEventOut(key).event\" :key=\"'app-event-out-' + index\">{{te}}</option>\n </template>\n </select>\n </td>\n <td>\n <button class=\"btn btn-danger btn-editor-xs btn-remove-out-event\" :data-event=\"key\" @click=\"removeOutEvent\">\n <i class=\"fa fa-minus\"></i>\n </button>\n </td>\n </tr>\n <tr v-else>\n <td colspan=\"3\" style=\"padding-top: 0px; padding-bottom: 0px;\">\n <button class=\"btn btn-sm btn-add-callback\" style=\"width: 100%;\" @click=\"addCallback(key)\">Add a callback</button>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"modal edit-value-modal\" tabindex=\"-1\" role=\"dialog\">\n <div class=\"modal-dialog\" role=\"document\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">Edit value</h5>\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n <div class=\"modal-body\">\n <div>\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value unset-value\" id=\"unset-value\" name=\"set-value\" value=\"unset-value\" checked>\n <label class=\"form-check-label\" for=\"unset-value\">\n don't set a value\n </label>\n </div>\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value set-value-null\" id=\"set-value-null\" name=\"set-value\" value=\"set-value-null\">\n <label class=\"form-check-label\" for=\"set-value-null\">\n set null\n </label>\n </div>\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value set-value-type\" id=\"set-value-type\" name=\"set-value\" value=\"set-value-type\" aria-label=\"Set a value of type\">\n <div class=\"form-inline form-check-label\" style=\"height: 24px;\">\n <label for=\"set-value-type\">\n set a value of type:\n <select class=\"form-control choose-value-type d-inline-block form-control-sm ml-2\">\n <option value=\"string\">String</option>\n <option value=\"number\">Number</option>\n <option value=\"boolean\">Boolean</option>\n <option value=\"object\">Object</option>\n </select>\n </label>\n </div>\n </div>\n </div>\n <div class=\"has-value\" style=\"display: none;\">\n <hr/>\n <div class=\"define-value define-boolean\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <select class=\"form-control form-control-sm bool-value d-inline-block ml-2\">\n <option value=true>True</option>\n <option value=false>False</option>\n </select>\n </div>\n </div>\n <div class=\"define-value define-number\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <input type=\"number\" class=\"form-control form-control-sm number-value ml-2\"/>\n </div>\n </div>\n <div class=\"define-value define-string\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <input type=\"text\" class=\"form-control form-control-sm text-value ml-2\"/>\n </div>\n </div>\n <div class=\"define-value define-object\" style=\"display: none;\">\n <label>Value: </label>\n <div class=\"json-editor\" style=\"height: 400px;\"></div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-primary btn-save\">Save changes</button>\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n</template>\n\n<script>\nimport _ from 'lodash';\nimport swal from 'sweetalert2';\nimport DisplayTypeVue from './displayType.vue';\nimport DisplayValueVue from './displayValue.vue';\n\nexport default {\n props: [\n \"app\"\n ],\n components: {\n \"display-type\" : DisplayTypeVue,\n \"display-value\" : DisplayValueVue,\n },\n data: function () {\n return {\n expanded: {} // expanded app events (advanced settings)\n };\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n },\n mounted: function() {\n // bind tooltips\n $(this.$el).find('button[data-toggle=\"tooltip\"]').tooltip();\n this.fixMaxHeightForCategories();\n },\n updated: function() {\n this.fixMaxHeightForCategories();\n },\n methods: {\n // setup a max height for each menu, so a scroll appears if there's too much item in it\n fixMaxHeightForCategories : function() {\n let nbActiveCategories = $(this.$el).find('.edit-body > .card').length;\n let headerHeight = $(this.$el).find('.edit-body > .card > .card-header').outerHeight();\n let panelHeight = $(this.$el).height() - $(this.$el).find('.edit-main-presentation').outerHeight();\n let maxCategoryHeight = panelHeight - nbActiveCategories * headerHeight;\n $(this.$el).find('.edit-body').css('height', panelHeight);\n $(this.$el).find('.edit-body > .card > .collapse > .card-body').css('max-height', maxCategoryHeight + \"px\");\n },\n\n onEdited: function() {\n this.view.repaint();\n },\n\n getNodesWithInEvents: function() {\n var l = [];\n var nodes = this.view.m.getNodes(\"ui\");\n _.each(nodes, (n) => {\n if( n.getInEventsNames().length > 0 ) {\n l.push(n);\n }\n });\n return l;\n },\n\n getNodesWithOutEvents: function() {\n var l = [];\n var nodes = this.view.m.getNodes(\"ui\");\n _.each(nodes, (n) => {\n if( n.getOutEventsNames().length > 0 ) {\n l.push(n);\n }\n });\n return l;\n },\n\n getNodeEvents: function( nodeId ) {\n var node = this.view.m.getNode(nodeId);\n return node.getEventsNames();\n },\n\n getNodeInEvents: function( nodeId ) {\n var node = this.view.m.getNode(nodeId);\n return node.getInEventsNames();\n },\n\n getNodeOutEvents: function( nodeId ) {\n var node = this.view.m.getNode(nodeId);\n return node.getOutEventsNames();\n },\n\n editAppDescription: function() {\n swal({\n input: 'text',\n title: 'Enter the description',\n }).then((result) => {\n this.view.c.setAppDescription(result.value);\n });\n },\n\n editEventDescription: function(e) {\n var eventName = $(e.target).attr('data-event');\n\n swal({\n input: 'text',\n title: 'Enter the description',\n }).then((result) => {\n this.view.c.setAppEventDescription(eventName, result.value);\n });\n },\n\n removeAppEvent: function(e) {\n var name = $(e.target).attr('data-event');\n this.view.c.removeAppEvent(name);\n this.onEdited();\n },\n\n renameAppEvent: function(e) {\n var name = $(e.target).attr('data-event');\n swal({\n input: 'text',\n title: 'Enter the new event name',\n }).then((result) => {\n if( result.value ) {\n this.view.c.renameAppEvent(name, result.value);\n this.onEdited();\n }\n });\n },\n\n setEventIf: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventIf( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val);\n this.onEdited();\n },\n\n setEventData: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventData( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val);\n this.onEdited();\n },\n\n selectEventTarget: function(e) {\n var target = $(e.target).val();\n\n // change options of closest .select-event-name according to this new target\n var targetNode = this.view.m.getNode(target);\n var targetEvents = targetNode.getEventsNames();\n var select = $(e.target).closest('tr').find('.select-event-name');\n select.html('');\n _.each(targetEvents, (eventName) => {\n select.append( $('<option/>', {\n value: eventName\n }).append(eventName));\n });\n\n var index = parseInt($(e.target).attr('data-index'));\n this.view.c.setEventTarget( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, target);\n this.onEdited();\n },\n\n selectEventName: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventName( \"#application-\" + $(e.target).attr('dualbox-target') + '-' + $(e.target).attr('data-event'), index, val );\n this.onEdited();\n },\n\n addCallback: function(appEventName) {\n var nodesWithOutEvents = this.getNodesWithOutEvents();\n if( nodesWithOutEvents.length > 0 ) {\n var firstNode = nodesWithOutEvents[0];\n var firstEvent = firstNode.getOutEventsNames()[0];\n this.setCallback(appEventName, firstNode, firstEvent);\n }\n else {\n swal({\n title: \"You can not add an API callback here\",\n text: \"None of the UIs of the application does have an OUT event, usable for API callbacks\",\n type: \"error\"\n })\n }\n },\n\n setCallback: function(appEventName, e) {\n var targetNodeId = $(this.$el).find('.select-callback-target').val();\n var targetNodeEvent = $(this.$el).find('.select-callback-event').val();\n this.view.c.setCallback(appEventName, targetNodeId, targetNodeEvent);\n this.onEdited();\n },\n\n addAppEvent: function(e) {\n swal({\n input: 'text',\n title: 'Enter the event name',\n }).then((result) => {\n this.view.c.addAppEvent(result.value);\n this.onEdited();\n });\n },\n\n removeInEvent: function(e) {\n var eventName = $(e.target).attr('data-event');\n var index = parseInt($(e.target).attr('data-index'));\n this.view.c.removeAppInEvent(eventName, index);\n this.onEdited();\n },\n\n removeOutEvent: function(e) {\n var eventName = $(e.target).attr('data-event');\n this.view.c.removeAppOutEvent(eventName);\n this.onEdited();\n },\n\n addSubEvent: function(eventName) {\n this.view.c.addSubEvent(eventName);\n this.onEdited();\n },\n\n getDataType: function(evt) {\n if( evt.datatype ) {\n return evt.datatype;\n }\n else if( evt.data ) {\n return window.DualBox.Type.detectType(evt.data);\n }\n else {\n return undefined;\n }\n },\n\n toggleAdvancedAppEventSettings: function(e) {\n var key = $(e.target).data('event');\n var index = $(e.target).data('index');\n var k=key+'##'+index;\n this.expanded[k] = this.expanded[k] ? false : true;\n this.$forceUpdate();\n },\n\n onEditEventInData(key, index, val) {\n this.view.c.setEventData( \"#application-events-in-\" + key, index, val);\n this.$emit('edited');\n },\n\n onEditEventInDataType(key, index, type) {\n this.view.c.setEventDataType( \"#application-events-in-\" + key, index, type);\n\n // check that the set value still match the new type\n // delete it otherwise\n var val = this.app.getEventIn(key)[index].data;\n try {\n // TODO: ensure type is already loaded (after dualbox) and remove the try/catch\n if( !window.DualBox.Type.check(type, val) ) {\n // delete data (== set undefined)\n this.view.c.setEventData( \"#application-events-in-\" + key, index, undefined);\n }\n }\n catch(e) {\n this.view.c.setEventData( \"#application-events-in-\" + key, index, undefined);\n }\n\n this.$emit('edited');\n },\n }\n}\n</script>\n"]}, media: undefined });
|
|
65684
65733
|
|
|
65685
65734
|
};
|
|
65686
65735
|
/* scoped */
|
|
@@ -65743,6 +65792,7 @@ var script$b = {
|
|
|
65743
65792
|
// adapt the style of the example graph node
|
|
65744
65793
|
// remove the "position: absolute;" that messes up the display
|
|
65745
65794
|
this.fixCardStyle();
|
|
65795
|
+
this.fixMaxHeightForCategories();
|
|
65746
65796
|
|
|
65747
65797
|
// allow tooltips
|
|
65748
65798
|
this.activateTooltip();
|
|
@@ -65760,6 +65810,7 @@ var script$b = {
|
|
|
65760
65810
|
updated: function() {
|
|
65761
65811
|
//console.log('[Updated] node-settings');
|
|
65762
65812
|
this.fixCardStyle();
|
|
65813
|
+
this.fixMaxHeightForCategories();
|
|
65763
65814
|
this.activateTooltip();
|
|
65764
65815
|
this.focus();
|
|
65765
65816
|
},
|
|
@@ -65786,6 +65837,16 @@ var script$b = {
|
|
|
65786
65837
|
});
|
|
65787
65838
|
},
|
|
65788
65839
|
|
|
65840
|
+
// setup a max height for each menu, so a scroll appears if there's too much item in it
|
|
65841
|
+
fixMaxHeightForCategories : function() {
|
|
65842
|
+
let nbActiveCategories = $(this.$el).find('.edit-body > .card-settings').length;
|
|
65843
|
+
let headerHeight = $(this.$el).find('.edit-body > .card-settings > .card-header').outerHeight();
|
|
65844
|
+
let panelHeight = $(this.$el).height() - $(this.$el).find('.edit-node-presentation').outerHeight();
|
|
65845
|
+
let maxCategoryHeight = panelHeight - nbActiveCategories * headerHeight;
|
|
65846
|
+
$(this.$el).find('.edit-body').css('height', panelHeight);
|
|
65847
|
+
$(this.$el).find('.edit-body > .card-settings > .collapse > .card-body').css('max-height', maxCategoryHeight + "px");
|
|
65848
|
+
},
|
|
65849
|
+
|
|
65789
65850
|
activateTooltip: function() {
|
|
65790
65851
|
$(this.$el).find('[data-toggle="tooltip"]').tooltip();
|
|
65791
65852
|
},
|
|
@@ -65836,7 +65897,7 @@ var script$b = {
|
|
|
65836
65897
|
|
|
65837
65898
|
addEvent: function(e) {
|
|
65838
65899
|
this.view.c.addEvent(this.n.id);
|
|
65839
|
-
this
|
|
65900
|
+
this.onEdited();
|
|
65840
65901
|
},
|
|
65841
65902
|
|
|
65842
65903
|
toggleInputVisibility: function(e) {
|
|
@@ -65934,22 +65995,17 @@ var script$b = {
|
|
|
65934
65995
|
// change options of closest .select-event-name according to this new target
|
|
65935
65996
|
var targetNode = this.view.m.getNode(target);
|
|
65936
65997
|
var targetEvents = targetNode.getEventsNames();
|
|
65937
|
-
var select = $(e.target).closest('tr').find('.select-event-name');
|
|
65938
|
-
select.html('');
|
|
65939
|
-
lodash.each(targetEvents, (eventName) => {
|
|
65940
|
-
select.append( $('<option/>', {
|
|
65941
|
-
value: eventName
|
|
65942
|
-
}).append(eventName));
|
|
65943
|
-
});
|
|
65944
65998
|
|
|
65945
65999
|
var index = parseInt($(e.target).attr('data-index'));
|
|
65946
66000
|
this.view.c.setEventTarget( this.n.id, index, target );
|
|
66001
|
+
this.onEdited();
|
|
65947
66002
|
},
|
|
65948
66003
|
|
|
65949
66004
|
selectEventName: function(e) {
|
|
65950
66005
|
var index = parseInt($(e.target).attr('data-index'));
|
|
65951
66006
|
var val = $(e.target).val();
|
|
65952
66007
|
this.view.c.setEventName( this.n.id, index, val );
|
|
66008
|
+
this.onEdited();
|
|
65953
66009
|
},
|
|
65954
66010
|
|
|
65955
66011
|
toggleCache: function(e) {
|
|
@@ -65961,6 +66017,7 @@ var script$b = {
|
|
|
65961
66017
|
var val = $(e.target).is(':checked');
|
|
65962
66018
|
this.view.c.setBoxParallel( this.n.id, val );
|
|
65963
66019
|
this.isParallel = val;
|
|
66020
|
+
this.onEdited();
|
|
65964
66021
|
},
|
|
65965
66022
|
|
|
65966
66023
|
editModuleDescription: function(e) {
|
|
@@ -65999,7 +66056,7 @@ var script$b = {
|
|
|
65999
66056
|
onEditAttributeType(attributeName, typeStr) {
|
|
66000
66057
|
this.n.assignAttributeType(attributeName, typeStr);
|
|
66001
66058
|
this.onEdited();
|
|
66002
|
-
this.view.repaint();
|
|
66059
|
+
this.view.repaint();
|
|
66003
66060
|
},
|
|
66004
66061
|
|
|
66005
66062
|
onEditDefaultValue(val) {
|
|
@@ -66136,10 +66193,12 @@ var __vue_render__$b = function() {
|
|
|
66136
66193
|
_c(
|
|
66137
66194
|
"div",
|
|
66138
66195
|
{
|
|
66196
|
+
staticClass: "edit-node-presentation",
|
|
66139
66197
|
staticStyle: {
|
|
66140
66198
|
"padding-left": "10px",
|
|
66141
66199
|
"padding-top": "10px",
|
|
66142
|
-
"padding-right": "10px"
|
|
66200
|
+
"padding-right": "10px",
|
|
66201
|
+
"padding-bottom": "10px"
|
|
66143
66202
|
}
|
|
66144
66203
|
},
|
|
66145
66204
|
[
|
|
@@ -66187,7 +66246,7 @@ var __vue_render__$b = function() {
|
|
|
66187
66246
|
])
|
|
66188
66247
|
]),
|
|
66189
66248
|
_vm._v(" "),
|
|
66190
|
-
_c("p", [
|
|
66249
|
+
_c("p", { staticStyle: { "margin-bottom": "0" } }, [
|
|
66191
66250
|
_c("small", { staticClass: "edit-dualbox-node-package-name" }, [
|
|
66192
66251
|
_vm._v(_vm._s(_vm.n.getPackageName()))
|
|
66193
66252
|
])
|
|
@@ -66196,7 +66255,7 @@ var __vue_render__$b = function() {
|
|
|
66196
66255
|
),
|
|
66197
66256
|
_vm._v(" "),
|
|
66198
66257
|
_c("div", { staticClass: "edit-body" }, [
|
|
66199
|
-
_c("div", { staticClass: "card" }, [
|
|
66258
|
+
_c("div", { staticClass: "card card-settings" }, [
|
|
66200
66259
|
_vm._m(0),
|
|
66201
66260
|
_vm._v(" "),
|
|
66202
66261
|
_c(
|
|
@@ -66447,37 +66506,10 @@ var __vue_render__$b = function() {
|
|
|
66447
66506
|
"data-id": _vm.n.id
|
|
66448
66507
|
},
|
|
66449
66508
|
domProps: { checked: _vm.n.isParallel() },
|
|
66450
|
-
on: {
|
|
66451
|
-
change: function($event) {
|
|
66452
|
-
return _vm.toggleWorker()
|
|
66453
|
-
}
|
|
66454
|
-
}
|
|
66509
|
+
on: { change: _vm.toggleWorker }
|
|
66455
66510
|
}),
|
|
66456
66511
|
_vm._v(" "),
|
|
66457
|
-
_vm._m(4)
|
|
66458
|
-
_c("br"),
|
|
66459
|
-
_vm.isParallel
|
|
66460
|
-
? _c(
|
|
66461
|
-
"span",
|
|
66462
|
-
{
|
|
66463
|
-
directives: [
|
|
66464
|
-
{
|
|
66465
|
-
name: "show",
|
|
66466
|
-
rawName: "v-show",
|
|
66467
|
-
value: _vm.n.isParallel(),
|
|
66468
|
-
expression: "n.isParallel()"
|
|
66469
|
-
}
|
|
66470
|
-
],
|
|
66471
|
-
staticClass:
|
|
66472
|
-
"text-danger worker-warning"
|
|
66473
|
-
},
|
|
66474
|
-
[
|
|
66475
|
-
_vm._v(
|
|
66476
|
-
"Due to some technical limitations, this will only affect the built bundle. Please run tests on the built bundle as well."
|
|
66477
|
-
)
|
|
66478
|
-
]
|
|
66479
|
-
)
|
|
66480
|
-
: _vm._e()
|
|
66512
|
+
_vm._m(4)
|
|
66481
66513
|
])
|
|
66482
66514
|
])
|
|
66483
66515
|
: _vm._e()
|
|
@@ -67977,7 +68009,7 @@ __vue_render__$b._withStripped = true;
|
|
|
67977
68009
|
/* style */
|
|
67978
68010
|
const __vue_inject_styles__$b = function (inject) {
|
|
67979
68011
|
if (!inject) return
|
|
67980
|
-
inject("data-v-476d4859_0", { source: "\n.edit-dualbox-node-id {\n margin-bottom: 0px;\n display: inline-block;\n width: 100%;\n}\n.edit-dualbox-node-package-name {\n font-style: italic;\n}\n.btn-edit-dualbox-node-name {\n display: inline-block;\n margin-left: 5px;\n margin-top: -10px;\n position: relative;\n top: -10px;\n vertical-align: bottom;\n}\n.module-left-description {\n padding-top: 30px;\n font-size: 12px;\n text-align: center;\n}\n.card-settings .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n}\n.table-desc {\n width: 100%;\n}\n.table-desc > thead > th > td {\n margin-right: 6px;\n}\n.table-desc > tbody > tr > td {\n margin-right: 6px;\n padding-top: 8px;\n padding-bottom: 8px;\n height: 40px;\n}\n.card-header[data-toggle=\"collapse\"] {\n cursor: pointer;\n}\n.card-header[data-toggle=\"collapse\"] h5 {\n user-select: none;\n}\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\n text-decoration: none;\n}\n.dualbox-node-name, .dualbox-node-name-input {\n max-width: 400px;\n}\n.dualbox-node-name-span {\n max-width: 350px;\n}\n.dualbox-node-name-input {\n display: inline-block;\n border-radius: 4px;\n padding: 4px 8px 4px 8px;\n font-size: 20px;\n max-width: 280px;\n}\n.text-value, .number-value, .boolean-value {\n max-width: 140px;\n}\n.event-if, .event-data {\n max-width: 80px;\n}\n.select-event-target, .select-event-name, .event-if, .event-data {\n font-size: 12px;\n}\n.edit-body {\n overflow-y: auto;\n overflow-x: hidden;\n max-height: calc(100% - 80px);\n}\n.table-events .event-rooting {\n margin-top: 10px;\n}\n.table-events thead {\n border-bottom: 1px solid #ddd;\n}\n.table-events .tr-event-condition td {\n padding-left: 10px;\n}\n.table-events .tr-event-data td {\n padding-left: 10px;\n}\n.tr-event-condition td, .tr-event-data td {\n height: 20px!important;\n}\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\n padding-top: 1px!important;\n padding-bottom: 1px!important;\n}\n.table-events tr + .event-rooting {\n /* border-top: 1px solid #ddd; */\n}\n.event-rooting td {\n padding-top: 8px!important;\n padding-bottom: 4px!important;\n}\n.event-data-type {\n font-size: 75%;\n border-radius: 5px;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-data-display {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-if {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\ni.fa, i.fas, i.far {\n pointer-events: none;\n}\n\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/editNodeSettings.vue"],"names":[],"mappings":";AACA;IACA,kBAAA;IACA,qBAAA;IACA,WAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,gBAAA;IACA,iBAAA;IACA,kBAAA;IACA,UAAA;IACA,sBAAA;AACA;AAEA;IACA,iBAAA;IACA,eAAA;IACA,kBAAA;AACA;AAEA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,WAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;IACA,YAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,qBAAA;IACA,kBAAA;IACA,wBAAA;IACA,eAAA;IACA,gBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,gBAAA;IACA,kBAAA;IACA,6BAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,gCAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,oBAAA;AACA","file":"editNodeSettings.vue","sourcesContent":["<style>\n .edit-dualbox-node-id {\n margin-bottom: 0px;\n display: inline-block;\n width: 100%;\n }\n\n .edit-dualbox-node-package-name {\n font-style: italic;\n }\n\n .btn-edit-dualbox-node-name {\n display: inline-block;\n margin-left: 5px;\n margin-top: -10px;\n position: relative;\n top: -10px;\n vertical-align: bottom;\n }\n\n .module-left-description {\n padding-top: 30px;\n font-size: 12px;\n text-align: center;\n }\n\n .card-settings .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n }\n\n .table-desc {\n width: 100%;\n }\n\n .table-desc > thead > th > td {\n margin-right: 6px;\n }\n\n .table-desc > tbody > tr > td {\n margin-right: 6px;\n padding-top: 8px;\n padding-bottom: 8px;\n height: 40px;\n }\n\n .card-header[data-toggle=\"collapse\"] {\n cursor: pointer;\n }\n\n .card-header[data-toggle=\"collapse\"] h5 {\n user-select: none;\n }\n\n .card-header[data-toggle=\"collapse\"]:hover .btn-link {\n text-decoration: none;\n }\n\n .dualbox-node-name, .dualbox-node-name-input {\n max-width: 400px;\n }\n\n .dualbox-node-name-span {\n max-width: 350px;\n }\n\n .dualbox-node-name-input {\n display: inline-block;\n border-radius: 4px;\n padding: 4px 8px 4px 8px;\n font-size: 20px;\n max-width: 280px;\n }\n\n .text-value, .number-value, .boolean-value {\n max-width: 140px;\n }\n\n .event-if, .event-data {\n max-width: 80px;\n }\n\n .select-event-target, .select-event-name, .event-if, .event-data {\n font-size: 12px;\n }\n\n .edit-body {\n overflow-y: auto;\n overflow-x: hidden;\n max-height: calc(100% - 80px);\n }\n\n .table-events .event-rooting {\n margin-top: 10px;\n }\n\n .table-events thead {\n border-bottom: 1px solid #ddd;\n }\n\n .table-events .tr-event-condition td {\n padding-left: 10px;\n }\n\n .table-events .tr-event-data td {\n padding-left: 10px;\n }\n\n .tr-event-condition td, .tr-event-data td {\n height: 20px!important;\n }\n\n .tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\n padding-top: 1px!important;\n padding-bottom: 1px!important;\n }\n\n .table-events tr + .event-rooting {\n /* border-top: 1px solid #ddd; */\n }\n\n .event-rooting td {\n padding-top: 8px!important;\n padding-bottom: 4px!important;\n }\n\n .event-data-type {\n font-size: 75%;\n border-radius: 5px;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n }\n\n .event-data-display {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n }\n\n .event-if {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n }\n\n i.fa, i.fas, i.far {\n pointer-events: none;\n }\n\n</style>\n\n<template>\n <div class=\"edit-node-panel h100\" id=\"edit-node-panel\" :key=\"n.id\">\n <div style=\"padding-left: 10px; padding-top: 10px; padding-right: 10px;\">\n <h2 class=\"edit-dualbox-node-id\">\n <div v-if=\"nowEditingNodeName\" class=\"dualbox-node-name-edit\">\n <input type=\"text\" class=\"form-control dualbox-node-name-input\" style=\"display: inline-block;\" :value=\"n.graphId\" @keypress=\"changeNodeName\" autofocus/>\n <button class=\"btn btn-primary btn-save-node-name-change\" :data-id=\"n.graphId\" style=\"display: inline-block;\" @click=\"saveNodeName\">Save</button>\n </div>\n <div v-else class=\"dualbox-node-name\">\n <button class=\"btn btn-light btn-sm btn-edit-dualbox-node-name\" @click=\"editNodeName\"><i class=\"fa fa-edit\"></i></button>\n <span class=\"dualbox-node-name-span text-truncate d-inline-block\">{{n.graphId}}</span>\n </div>\n </h2>\n <p><small class=\"edit-dualbox-node-package-name\">{{n.getPackageName()}}</small></p>\n </div>\n\n <div class=\"edit-body\">\n <div class=\"card\">\n <div class=\"card-header\" id=\"dualbox-node-desc\" data-toggle=\"collapse\" data-target=\"#dualbox-node-desc-collapse\" aria-expanded=\"true\" aria-controls=\"dualbox-node-desc-collapse\">\n <h5 class=\"mb-0 btn-link\">Description</h5>\n </div>\n\n <div id=\"dualbox-node-desc-collapse\" class=\"collapse show\" aria-labelledby=\"dualbox-node-desc\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n <div class=\"module-left-signature\">\n <graph-node :id=\"n.id\" :example=\"true\" :pkg=\"n.getPackage()\" :n=\"createExampleNode(n)\"></graph-node>\n </div>\n <p class=\"module-left-description\">\n <template v-if=\"n.isInput() || n.isOutput() || n.isMetanode()\">\n <template v-if=\"nowEditingDescription\">\n <textarea class=\"edit-node-description\" rows=4 style=\"width: 100%;\" :value=\"n.getDescription()\" autofocus>\n </textarea>\n <button class=\"btn btn-success\" @click=\"setDescription\">Save</button>\n </template>\n <template v-else>\n <button class=\"btn btn-transparent btn-xs\" @click=\"editDescription\"><i class=\"fa fa-edit\" ></i></button>\n <span> {{ getDescription() }}</span>\n </template>\n </template>\n <span v-else>\n {{ n.getPackage().description || \"[No description available]\" }}\n </span>\n </p>\n </div>\n </div>\n </div>\n\n <div class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-comments\" data-toggle=\"collapse\" data-target=\"#dualbox-node-comments-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-comments-collapse\">\n <h5 class=\"mb-0 btn-link\">Comments</h5>\n </div>\n <div id=\"dualbox-node-comments-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-comments\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <div style=\"padding-left: 15px; padding-right: 15px;\">\n <div v-if=\"nowEditingComment\" class=\"node-comment-edit\">\n <textarea class=\"node-comment\" rows=4 style=\"width: 100%;\" :data-id=\"n.id\" v-model=\"comment\" autofocus>\n </textarea>\n <div style=\"text-align: right; margin-top: 10px;\">\n <button class=\"btn btn-sm btn-secundary\" @click=\"deleteComment\">Delete</button>\n <button class=\"btn btn-sm btn-primary btn-save-comment\" @click=\"saveComment\">Save</button>\n </div>\n </div>\n <p v-else class=\"node-comment-text\">\n <span>{{ n.hasComment() ? n.getComment() : \"[Add a comment]\" }} </span>\n <button class=\"btn btn-sm btn-transparent\" @click=\"editComment\"><i class=\"fa fa-edit\"></i></button>\n </p>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Compute options -->\n <div v-if=\"n.isModule()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-compute-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-compute-collapse\">\n <h5 class=\"mb-0 btn-link\">Compute options</h5>\n </div>\n <div id=\"dualbox-node-compute-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <div class=\"form-group\" style=\"padding-left: 20px;\">\n <div>\n <label>\n <input class=\"input-cache-toggle\" type=\"checkbox\" v-bind:checked=\"n.hasCacheActivated()\" @change=\"toggleCache\">\n <span>Cache result <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Keep the result in memory (the cache) to avoid computing this box every-time its result is required. The cache will be invalidated if an input prior to this box is changed.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button></span>\n </label>\n </div>\n\n <div v-if=\"!n.isMetanode()\">\n <label>\n <input class=\"input-worker-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:checked=\"n.isParallel()\" @change=\"toggleWorker()\" />\n <span>Execute in a worker <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Workers are separate contexts of executions that can execute long-running tasks without blocking the browser execution. Use this for heavy computations.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button></span><br/><span v-if=\"isParallel\" class=\"text-danger worker-warning\" v-show=\"n.isParallel()\">Due to some technical limitations, this will only affect the built bundle. Please run tests on the built bundle as well.</span>\n </label>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Widget options -->\n <div v-if=\"n.isWidget()\" class=\"card card-default\">\n <div class=\"card-header\" id=\"dualbox-node-widget\" data-toggle=\"collapse\" data-target=\"#dualbox-node-widget-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-widget-collapse\">\n <h5 class=\"mb-0 btn-link\">Widget Options</h5>\n </div>\n <div id=\"dualbox-node-widget-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-widget\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <span>Widget registered to: </span>\n <select class=\"form-control form-control-sm select-widget-registerTo\" style=\"max-width: 250px;\" @change=\"registerToWidget\">\n <option value=\"\">none</option>\n <option v-for=\"target in getSpecialUINodes()\" :key=\"'target-'+target.id\" :value=\"target.graphId\" :selected=\"n.getWidgetRegistration() == target.graphId\">{{target.id}}</option>\n\n </select>\n </div>\n </div>\n </div>\n\n <!-- Inputs -->\n <div v-if=\"n.isInput()\" class=\"card card-default\">\n <div class=\"card-header\" id=\"dualbox-node-default\" data-toggle=\"collapse\" data-target=\"#dualbox-node-default-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-default-collapse\">\n <h5 class=\"mb-0 btn-link\">Default value</h5>\n </div>\n <div id=\"dualbox-node-default-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-default\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <span>Default value:</span>\n <span><display-value :v=\"n.getDefaultValue()\" :type=\"n.getType()\" @edited=\"onEditDefaultValue\"></display-value></span>\n </div>\n </div>\n </div>\n <div v-else-if=\"n.hasInputs()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-inputs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-inputs-collapse\">\n <h5 class=\"mb-0 btn-link\">Inputs <small><span class=\"badge badge-secondary\">{{n.getInputsNames().length}}</span></small></h5>\n </div>\n <div id=\"dualbox-node-inputs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Input</th>\n <th>Visible</th>\n <th>Type</th>\n <th>Default</th>\n </thead>\n <tbody>\n <tr v-for=\"key in n.getInputsNames()\" :key=\"'input-'+key\">\n <td>\n {{key}}\n <button v-if=\"n.hasInputDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" v-bind:title=\"n.getInputDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </td>\n <td>\n <input class=\"input-visibility-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:data-input=\"key\" v-bind:checked=\"n.isInputVisible(key)\" @change=\"toggleInputVisibility\">\n </td>\n <td>\n <!-- If there's a start, then we must edit the type -->\n <display-type :type=\"n.getInputType(key)\" :readonly=\"!n.isInputTemplateType(key)\" @edited=\"onEditInputType(key, $event)\"></display-type>\n </td>\n <td>\n <display-value :v=\"n.getInputDefaultValue(key)\" :type=\"n.getInputType(key)\" @edited=\"onEditInputDefaultValue(key, $event)\" :readonly=\"!n.isFullyDefinedInputType(key)\" :readonlyReason=\"!n.isFullyDefinedInputType(key) ? 'You must first define a full type (without *) before you can edit this value' : ''\"></display-value>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <!-- Outputs -->\n <div v-if=\"n.hasOutputs()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-outputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-outputs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-outputs-collapse\">\n <h5 class=\"mb-0 btn-link\">Outputs <small><span class=\"badge badge-secondary\">{{n.getOutputsNames().length}}</span></small></h5>\n </div>\n <div id=\"dualbox-node-outputs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-outputs\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Output</th>\n <th>Type</th>\n <th>Visible</th>\n </thead>\n <tbody>\n <tr v-for=\"key in n.getOutputsNames()\" :key=\"'output-'+key\">\n <td>{{key}}\n <button v-if=\"n.hasOutputDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" v-bind:title=\"n.getOutputDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </td>\n <td><display-type :type=\"n.getOutputType(key)\"></display-type></td>\n <td>\n <input class=\"output-visibility-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:data-output=\"key\" v-bind:checked=\"n.isOutputVisible(key)\" @change=\"toggleOutputVisibility\">\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <!-- Attributes -->\n <div v-if=\"n.hasAttributes()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-attrs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-attrs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-attrs-collapse\">\n <h5 class=\"mb-0 btn-link\">Attributes <small><span class=\"badge badge-secondary\">{{n.getAttributesNames().length}}</span></small></h5>\n </div>\n <div id=\"dualbox-node-attrs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-attrs\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Output</th>\n <th>Type</th>\n <th>Value</th>\n </thead>\n <tbody>\n <tr v-for=\"key in n.getAttributesNames()\" :key=\"'attr-'+key\">\n <td>{{key}}\n <button v-if=\"n.hasAttributeDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" :title=\"n.getAttributeDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </td>\n <td>\n <!-- If there's a start, then we must edit the type -->\n <display-type :type=\"n.getAttributeType(key)\" :readonly=\"!n.isAttributeTemplateType(key)\" @edited=\"onEditAttributeType(key, $event)\"></display-type>\n </td>\n <td>\n <display-value :v=\"n.getAttributeValue(key)\" :type=\"n.getAttributeType(key)\" @edited=\"onEditAttribute(key, $event)\" :readonly=\"!n.isFullyDefinedAttributeType(key)\" :readonlyReason=\"!n.isFullyDefinedInputType(key) ? 'You must first define a full type (without *) before you can edit this value' : ''\"></display-value>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n\n <!-- Loops -->\n <div v-if=\"n.hasInputs()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-loops-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-loops-collapse\">\n <h5 class=\"mb-0 btn-link\">Loops <small><span class=\"badge badge-secondary\">{{ n.hasLoop() ? \"on\" : \"off\" }}</span></small></h5>\n </div>\n <div id=\"dualbox-node-loops-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <h4>Iterators\n <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Iterators will break an array in input into a list of their components. The module will be computed several times, each time with one different component from every iterator input. Inputs that don't define iterators will use their current value as-is for the different computations.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </h4>\n <table class=\"table-desc table-striped\">\n <tbody>\n <tr v-for=\"key in n.getInputsNames()\" :key=\"'loop-iterator-'+key\">\n <td>{{key}}</td>\n <td>\n <input class=\"input-iterator-toggle\" type=\"checkbox\" :data-input=\"key\" :checked=\"n.hasIterator(key)\" @change=\"toggleIterator\" />\n </td>\n </tr>\n </tbody>\n </table>\n\n <h4 class=\"mt-2\">Feedback\n <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Feedback (during a loop) is a reinjection of an output result of one iteration into an input of the next iteration.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </h4>\n <table class=\"table-desc table-striped\">\n <tbody>\n <tr v-for=\"key in n.getOutputsNames()\" :key=\"'loop-feedback-'+key\">\n <td>{{key}}</td>\n <td>\n <select class=\"form-control form-control-sm select-output-feedback\" :data-output=\"key\" @change=\"selectOutputFeedback\">\n <option value=\"none\">No feedback</option>\n <option v-for=\"i in n.getInputsNames()\" :value=\"i\" :selected=\"n.getFeedback(key) == i\" :key=\"'loop-feedback-input-'+i\">{{i}}</option>\n </select>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <!-- Events -->\n <div v-if=\"n.isUI()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-events\" data-toggle=\"collapse\" data-target=\"#dualbox-node-events-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-events-collapse\">\n <h5 class=\"mb-0 btn-link\">Events <small><span class=\"badge badge-secondary\">{{n.getOutboundEvents().length}}</span></small></h5>\n </div>\n <div id=\"dualbox-node-events-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-events\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <table class=\"table-events table-desc\" style=\"font-size: 12px!important;\">\n <thead class=\"thead-dark\">\n <th>Target</th>\n <th>Event</th>\n <th>Action</th>\n </thead>\n <tbody>\n <template v-if=\"n.hasOutEvents()\" v-for=\"(evt, index) in n.getOutboundEvents()\" :data-index=\"index\">\n <tr class=\"event-rooting\">\n <td>\n <select v-if=\"evt.node\" class=\"form-control form-control-sm select-event-target\" :data-index=\"index\"@change=\"selectEventTarget\" >\n <option v-for=\"node in getUINodesWithEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()==evt.node\" :key=\"node.id\">{{node.getGraphId()}}</option>\n </select>\n <span v-else>{{evt.selector}}</span>\n </td>\n <td>\n <select class=\"form-control form-control-sm select-event-name\" :data-index=\"index\" @change=\"selectEventName\">\n <template v-if=\"evt.node\">\n <option v-for=\"targetEvent in getTargetNodeEvents(evt.node)\" :value=\"targetEvent\" :selected=\"evt.event===targetEvent\" :key=\"targetEvent\">{{targetEvent}}</option>\n </template>\n <template v-else>\n <option value=\"hide\">hide</option>\n <option value=\"show\">show</option>\n </template>\n </select>\n </td>\n <td>\n <button class=\"btn btn-secondary btn-editor-xs\" :data-index=\"index\" @click=\"toggleAdvancedAppEventSettings\" style=\"margin-left: 10px;\" title=\"Toggle advanced event settings\" >\n <i class=\"fas fa-cog\"></i>\n </button>\n <button class=\"btn btn-danger btn-editor-xs btn-remove-event\" :data-index=\"index\" @click=\"removeEvent\">\n <i class=\"fa fa-minus\"></i>\n </button>\n </td>\n </tr>\n <tr v-if=\"evt.if || expanded[index]\" class=\"tr-event-condition\">\n <td colspan=\"3\">\n <span style=\"width: 60px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Occur if:</span>\n\n <input style=\"max-width: 340px; width: 340px;\" class=\"form-control form-control-sm event-if d-inline-block\" type=\"text\" dualbox-target=\"events-in\" :data-index=\"index\" :value=\"evt.if\" @change=\"setEventIf\" />\n </td>\n </tr>\n <tr v-if=\"evt.data || evt.datatype || expanded[index]\" class=\"tr-event-data\" colspan=\"3\">\n <td colspan=\"3\">\n <span style=\"width: 53px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Data:</span>\n <span style=\"width: 350px;\">\n <display-type :type=\"getDataType(evt)\" @edited=\"onEditEventInDataType(key, index, $event)\"></display-type>\n <display-value :v=\"evt.data\" :type=\"getDataType(evt)\" @edited=\"onEditEventData(key, index, $event)\"></display-value>\n </span>\n </td>\n </tr>\n </template>\n <tr>\n <td colspan=\"5\" style=\"padding-top: 0px; padding-bottom: 0px;\">\n <button class=\"btn btn-sm\" :data-id=\"n.id\" style=\"width: 100%;\" @click=\"addEvent\">Add event</button>\n </td>\n </tr>\n </tbody>\n </table>\n\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"modal edit-value-modal\" tabindex=\"-1\" role=\"dialog\">\n <div class=\"modal-dialog\" role=\"document\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">Edit value</h5>\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n <div class=\"modal-body\">\n <div class=\"set-type\">\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value unset-value\" id=\"unset-value\" name=\"set-value\" value=\"unset-value\" checked>\n <label class=\"form-check-label\" for=\"unset-value\">\n don't set a value\n </label>\n </div>\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value set-value-null\" id=\"set-value-null\" name=\"set-value\" value=\"set-value-null\">\n <label class=\"form-check-label\" for=\"set-value-null\">\n set null\n </label>\n </div>\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value set-value-type\" id=\"set-value-type\" name=\"set-value\" value=\"set-value-type\" aria-label=\"Set a value of type\">\n <div class=\"form-inline form-check-label\" style=\"height: 24px;\">\n <label for=\"set-value-type\">\n set a value of type:\n <select class=\"form-control choose-value-type d-inline-block form-control-sm ml-2\">\n <option value=\"string\">String</option>\n <option value=\"number\">Number</option>\n <option value=\"boolean\">Boolean</option>\n <option value=\"object\">Object</option>\n <option value=\"file\">File</option>\n </select>\n </label>\n </div>\n </div>\n </div>\n <hr class=\"separator\"/>\n <div class=\"has-value\" style=\"display: none;\">\n <div class=\"define-value define-boolean\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <select class=\"form-control form-control-sm bool-value d-inline-block ml-2\">\n <option value=true>True</option>\n <option value=false>False</option>\n </select>\n </div>\n </div>\n <div class=\"define-value define-file\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>File input</label>\n <input type=\"file\" class=\"form-control-file form-control-sm file-value\">\n </div>\n </div>\n <div class=\"define-value define-number\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <input type=\"number\" class=\"form-control form-control-sm number-value ml-2\"/>\n </div>\n </div>\n <div class=\"define-value define-string\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <input type=\"text\" class=\"form-control form-control-sm text-value ml-2\"/>\n </div>\n </div>\n <div class=\"define-value define-object\" style=\"display: none;\">\n <label>Value: </label>\n <div class=\"json-editor\" style=\"height: 400px;\"></div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-primary btn-save\">Save changes</button>\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\n </div>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script>\nimport _ from 'lodash';\nimport DisplayTypeVue from './displayType.vue';\nimport DisplayValueVue from './displayValue.vue';\nimport GraphNodeVue from './graphNode.vue';\nimport JSONEditor from '@dualbox/dualbox-lib-jsoneditor';\nimport swal from 'sweetalert2';\n\nexport default {\n props: [\n \"id\", // the GraphNode object\n ],\n components: {\n \"display-type\" : DisplayTypeVue,\n \"display-value\" : DisplayValueVue,\n \"graph-node\" : GraphNodeVue\n },\n data: function () {\n return {\n comment: null,\n expanded: {}, // expanded app events (advanced settings)\n\n // states\n isParallel: false,\n nowEditingComment: false,\n nowEditingNodeName: false,\n nowEditingDescription: false,\n };\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n this.n = this.view.m.getNode(this.id);\n\n // fetch the comment for this node\n this.comment = this.n.hasComment() ? this.n.getComment() : \"\";\n this.isParallel = this.n.isParallel();\n },\n mounted: function() {\n // adapt the style of the example graph node\n // remove the \"position: absolute;\" that messes up the display\n this.fixCardStyle();\n\n // allow tooltips\n this.activateTooltip();\n\n // bind the json editor\n editor = new JSONEditor($(this.$el).find('.json-editor')[0], { modes: ['tree', 'code', 'text' ]});\n editor.set({});\n },\n beforeUpdate: function() {\n //console.log('[Updating] node-settings');\n // we need to refresh our node object\n this.n = this.view.m.getNode(this.id); // it breaks updating node name\n this.deactivateTooltip();\n },\n updated: function() {\n //console.log('[Updated] node-settings');\n this.fixCardStyle();\n this.activateTooltip();\n this.focus();\n },\n activate: function() {\n this.activateTooltip();\n this.focus();\n },\n deactivate: function() {\n this.deactivateTooltip();\n },\n methods: {\n fixCardStyle: function() {\n var card = $(this.$el).find('.module-left-signature .card');\n card.css('position', 'static').css('point-events', 'none');\n card.find('.point').css(\"visibibility\", \"visible\").find('svg').css(\"visibibility\", \"visible\");\n card.ready(() => {\n var width = Math.max(\n card.find('.inputs').width() + card.find('.outputs').width() + 20,\n card.find('.title').width() + 60,\n card.find('.subtitle').width() + 40\n );\n card.css('width', width + 'px');\n card.addClass('mx-auto');\n });\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 focus: function() {\n $(this.$el).find('[autofocus]').focus();\n },\n\n // for widget registration\n getSpecialUINodes: function() {\n var targets = this.n.m.getSpecialUINodes( this.n.getRegisterType() );\n return targets;\n },\n\n getUINodesWithEvents : function() {\n var nodes = this.n.m.getNodes(\"ui\");\n var eventNodes = nodes.filter( function(n) {\n return n.getEventsNames().length > 0;\n });\n return eventNodes;\n },\n\n getTargetNodeEvents: function(nodeId) {\n var targetNode = this.n.m.getNode(nodeId);\n return targetNode.getEventsNames();\n },\n\n editComment: function(e) {\n this.nowEditingComment = true;\n },\n\n saveComment: function(e) {\n var val = $(this.$el).find('.node-comment').val();\n this.view.c.setComment(this.n.id, val);\n this.nowEditingComment = false;\n this.onEdited();\n },\n\n deleteComment: function(e) {\n this.view.c.deleteComment(this.n.id);\n this.nowEditingComment = false;\n this.onEdited();\n },\n\n addEvent: function(e) {\n this.view.c.addEvent(this.n.id);\n this.$forceUpdate();\n },\n\n toggleInputVisibility: function(e) {\n var inputName = $(e.target).data('input');\n var visible = $(e.target).is(\":checked\");\n if( !this.view.c.setInputVisibility(this.n.id, inputName, visible) ) {\n // failed, reset this to old value\n $(e.target).prop('checked', !visible);\n }\n },\n\n toggleOutputVisibility: function(e) {\n var outputName = $(e.target).data('output');\n var visible = $(e.target).is(\":checked\");\n if( !this.view.c.setOutputVisibility(this.n.id, outputName, visible) ) {\n // failed, reset this to old value\n $(e.target).prop('checked', !visible);\n }\n },\n\n editNodeName: function(e) {\n this.nowEditingNodeName = true;\n },\n\n changeNodeName: function(e) {\n // user pressed enter\n if(e.which == 13 || e.keyCode == 13) {\n this.saveNodeName(e);\n }\n },\n\n saveNodeName: function(e) {\n var newId = $(e.target).parent().find('.dualbox-node-name-input').val();\n this.view.c.renameBox(this.n.graphId, newId, this.n.type);\n\n // get the new node\n switch( this.n.type ) {\n case \"input\": this.n = this.view.m.getNode(\"in-\"+newId); break;\n case \"output\": this.n = this.view.m.getNode(\"in-\"+newId); break;\n default: this.n = this.view.m.getNode(newId);\n }\n\n this.nowEditingNodeName = false;\n },\n\n toggleIterator: function(e) {\n var destInput = $(e.target).attr('data-input');\n if( $(e.target).is(\":checked\") ) {\n this.view.c.setIterator( this.n.id, destInput );\n }\n else {\n this.view.c.unsetIterator( this.n.id, destInput );\n }\n this.onEdited();\n },\n\n registerToWidget: function(e) {\n var targetId = $(e.target).val();\n this.view.c.registerWidget(this.n.id, targetId);\n },\n\n selectOutputFeedback: function(e) {\n var val = $(e.target).val();\n var destOutput = $(e.target).attr('data-output');\n if( val !== \"none\" ) {\n this.view.c.setFeedback( this.n.id, destOutput, val );\n }\n else {\n this.view.c.unsetFeedback( this.n.id, destOutput );\n }\n },\n\n removeEvent: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n this.view.c.removeEvent( this.n.id, index );\n this.$forceUpdate();\n },\n\n setEventIf: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventIf( this.n.id, index, val );\n },\n\n setEventData: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventData( this.n.id, index, val );\n },\n\n // TODO: remake this into it's own vue\n selectEventTarget: function(e) {\n var target = $(e.target).val();\n\n // change options of closest .select-event-name according to this new target\n var targetNode = this.view.m.getNode(target);\n var targetEvents = targetNode.getEventsNames();\n var select = $(e.target).closest('tr').find('.select-event-name');\n select.html('');\n _.each(targetEvents, (eventName) => {\n select.append( $('<option/>', {\n value: eventName\n }).append(eventName));\n });\n\n var index = parseInt($(e.target).attr('data-index'));\n this.view.c.setEventTarget( this.n.id, index, target );\n },\n\n selectEventName: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventName( this.n.id, index, val );\n },\n\n toggleCache: function(e) {\n var val = $(e.target).is(':checked');\n this.view.c.setBoxCache( this.n.id, val );\n },\n\n toggleWorker: function(e) {\n var val = $(e.target).is(':checked');\n this.view.c.setBoxParallel( this.n.id, val );\n this.isParallel = val;\n },\n\n editModuleDescription: function(e) {\n var desc = $(e.target).attr('data-desc');\n\n swal({\n title: \"Describe what this metabox does\",\n input: \"textarea\",\n inputValue: desc || \"\",\n showCancelButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true,\n animation: \"slide-from-top\",\n inputPlaceholder: \"This metabox...\"\n }).then( (result) => {\n if (result.value === \"\") {\n swal.showInputError(\"You need to write something!\");\n return false;\n }\n else {\n this.view.c.setMetanodeDescription(this.n.id, result.value);\n }\n });\n },\n\n createExampleNode(n) {\n return this.view.m.createCloneNode(n.getPackage().name, n.id)\n },\n\n onEditInputType(inputName, typeStr) {\n this.n.assignInputType(inputName, typeStr);\n this.onEdited();\n this.view.repaint();\n },\n\n onEditAttributeType(attributeName, typeStr) {\n this.n.assignAttributeType(attributeName, typeStr);\n this.onEdited();\n this.view.repaint(); \n },\n\n onEditDefaultValue(val) {\n this.n.setDefaultValue(val);\n this.onEdited();\n this.view.repaint();\n },\n\n onEditInputDefaultValue(inputName, val) {\n if( val === undefined ) {\n this.n.deleteVal(\"input\", inputName);\n this.n.setInputVisibility(inputName, true); // show the input then (connection needed)\n }\n else {\n this.n.val(\"input\", inputName, val );\n this.n.setInputVisibility(inputName, false); // hide inputs with values (no connection needed)\n }\n this.onEdited();\n this.view.repaint();\n },\n\n onEditAttribute(attrName, val) {\n if( val === undefined ) {\n this.n.deleteVal(\"attr\", attrName);\n }\n else {\n this.n.val(\"attr\", attrName, val);\n }\n this.onEdited();\n },\n\n onEditDefaultInput(inputName, val) {\n if( val === undefined ) {\n this.n.deleteVal(\"input\", inputName);\n }\n else {\n this.n.val(\"input\", inputName, val);\n }\n this.onEdited();\n this.view.repaint();\n },\n\n onEdited() {\n // we need to refresh our node object\n this.n = this.view.m.getNode(this.id); // it breaks updating node name\n this.$forceUpdate();\n },\n\n getDataType: function(evt) {\n if( evt.datatype ) {\n return evt.datatype;\n }\n else if( evt.data ) {\n return window.DualBox.Type.detectType(evt.data);\n }\n else {\n return undefined;\n }\n },\n\n toggleAdvancedAppEventSettings: function(e) {\n var index = $(e.target).data('index');\n this.expanded[index] = this.expanded[index] ? false : true;\n this.$forceUpdate();\n },\n\n onEditEventData(key, index, val) {\n this.view.c.setEventData( this.n.id, index, val );\n this.$forceUpdate();\n },\n\n onEditEventInDataType(key, index, type) {\n this.view.c.setEventDataType( this.n.id, index, type);\n\n // check that the set value still match the new type\n // delete it otherwise\n var val = this.n.getOutboundEvents()[index].data;\n try {\n // TODO: ensure type is already loaded (after dualbox) and remove the try/catch\n if( !window.DualBox.Type.check(type, val) ) {\n // delete data (== set undefined)\n this.view.c.setEventData( this.n.id, index, undefined);\n }\n }\n catch(e) {\n this.view.c.setEventData( this.n.id, index, undefined);\n }\n\n this.$forceUpdate();\n },\n\n getDescription() {\n return this.n.getDescription() || \"[Add a description]\"\n },\n\n editDescription() {\n this.nowEditingDescription = true;\n },\n\n setDescription() {\n var val = $(this.$el).find('.edit-node-description').val();\n if( this.n.isInput() ) {\n this.view.c.setInputDescription(this.n.graphId, val);\n }\n else if( this.n.isOutput() ) {\n this.view.c.setOutputDescription(this.n.graphId, val);\n }\n else if( this.n.isMetanode() ) {\n this.view.c.setMetanodeDescription(this.n.graphId, val);\n }\n this.nowEditingDescription = false;\n\n this.$forceUpdate();\n },\n }\n}\n\n\n</script>\n"]}, media: undefined });
|
|
68012
|
+
inject("data-v-5af66f22_0", { source: "\n.edit-dualbox-node-id {\n margin-bottom: 0px;\n display: inline-block;\n width: 100%;\n}\n.edit-dualbox-node-package-name {\n font-style: italic;\n}\n.btn-edit-dualbox-node-name {\n display: inline-block;\n margin-left: 5px;\n margin-top: -10px;\n position: relative;\n top: -10px;\n vertical-align: bottom;\n}\n.module-left-description {\n padding-top: 30px;\n font-size: 12px;\n text-align: center;\n}\n.card-settings .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n overflow-y: auto;\n}\n.table-desc {\n width: 100%;\n}\n.table-desc > thead > th > td {\n margin-right: 6px;\n}\n.table-desc > tbody > tr > td {\n margin-right: 6px;\n padding-top: 8px;\n padding-bottom: 8px;\n height: 40px;\n}\n.card-header[data-toggle=\"collapse\"] {\n cursor: pointer;\n}\n.card-header[data-toggle=\"collapse\"] h5 {\n user-select: none;\n}\n.card-header[data-toggle=\"collapse\"]:hover .btn-link {\n text-decoration: none;\n}\n.dualbox-node-name, .dualbox-node-name-input {\n max-width: 400px;\n}\n.dualbox-node-name-span {\n max-width: 350px;\n}\n.dualbox-node-name-input {\n display: inline-block;\n border-radius: 4px;\n padding: 4px 8px 4px 8px;\n font-size: 20px;\n max-width: 280px;\n}\n.text-value, .number-value, .boolean-value {\n max-width: 140px;\n}\n.event-if, .event-data {\n max-width: 80px;\n}\n.select-event-target, .select-event-name, .event-if, .event-data {\n font-size: 12px;\n}\n.edit-body {\n overflow-y: hidden;\n overflow-x: hidden;\n max-height: calc(100% - 90px);\n}\n.table-events .event-rooting {\n margin-top: 10px;\n}\n.table-events thead {\n border-bottom: 1px solid #ddd;\n}\n.table-events .tr-event-condition td {\n padding-left: 10px;\n}\n.table-events .tr-event-data td {\n padding-left: 10px;\n}\n.tr-event-condition td, .tr-event-data td {\n height: 20px!important;\n}\n.tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\n padding-top: 1px!important;\n padding-bottom: 1px!important;\n}\n.table-events tr + .event-rooting {\n /* border-top: 1px solid #ddd; */\n}\n.event-rooting td {\n padding-top: 8px!important;\n padding-bottom: 4px!important;\n}\n.event-data-type {\n font-size: 75%;\n border-radius: 5px;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-data-display {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.event-if {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\ni.fa, i.fas, i.far {\n pointer-events: none;\n}\n.h100 {\n height: 100%;\n}\n\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/editNodeSettings.vue"],"names":[],"mappings":";AACA;IACA,kBAAA;IACA,qBAAA;IACA,WAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,gBAAA;IACA,iBAAA;IACA,kBAAA;IACA,UAAA;IACA,sBAAA;AACA;AAEA;IACA,iBAAA;IACA,eAAA;IACA,kBAAA;AACA;AAEA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;AACA;AAEA;IACA,WAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;IACA,YAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,qBAAA;IACA,kBAAA;IACA,wBAAA;IACA,eAAA;IACA,gBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,kBAAA;IACA,6BAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,gCAAA;AACA;AAEA;IACA,0BAAA;IACA,6BAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,cAAA;IACA,kBAAA;IACA,sBAAA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;AACA;AAEA;IACA,oBAAA;AACA;AAEA;IACA,YAAA;AACA","file":"editNodeSettings.vue","sourcesContent":["<style>\n .edit-dualbox-node-id {\n margin-bottom: 0px;\n display: inline-block;\n width: 100%;\n }\n\n .edit-dualbox-node-package-name {\n font-style: italic;\n }\n\n .btn-edit-dualbox-node-name {\n display: inline-block;\n margin-left: 5px;\n margin-top: -10px;\n position: relative;\n top: -10px;\n vertical-align: bottom;\n }\n\n .module-left-description {\n padding-top: 30px;\n font-size: 12px;\n text-align: center;\n }\n\n .card-settings .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n overflow-y: auto;\n }\n\n .table-desc {\n width: 100%;\n }\n\n .table-desc > thead > th > td {\n margin-right: 6px;\n }\n\n .table-desc > tbody > tr > td {\n margin-right: 6px;\n padding-top: 8px;\n padding-bottom: 8px;\n height: 40px;\n }\n\n .card-header[data-toggle=\"collapse\"] {\n cursor: pointer;\n }\n\n .card-header[data-toggle=\"collapse\"] h5 {\n user-select: none;\n }\n\n .card-header[data-toggle=\"collapse\"]:hover .btn-link {\n text-decoration: none;\n }\n\n .dualbox-node-name, .dualbox-node-name-input {\n max-width: 400px;\n }\n\n .dualbox-node-name-span {\n max-width: 350px;\n }\n\n .dualbox-node-name-input {\n display: inline-block;\n border-radius: 4px;\n padding: 4px 8px 4px 8px;\n font-size: 20px;\n max-width: 280px;\n }\n\n .text-value, .number-value, .boolean-value {\n max-width: 140px;\n }\n\n .event-if, .event-data {\n max-width: 80px;\n }\n\n .select-event-target, .select-event-name, .event-if, .event-data {\n font-size: 12px;\n }\n\n .edit-body {\n overflow-y: hidden;\n overflow-x: hidden;\n max-height: calc(100% - 90px);\n }\n\n .table-events .event-rooting {\n margin-top: 10px;\n }\n\n .table-events thead {\n border-bottom: 1px solid #ddd;\n }\n\n .table-events .tr-event-condition td {\n padding-left: 10px;\n }\n\n .table-events .tr-event-data td {\n padding-left: 10px;\n }\n\n .tr-event-condition td, .tr-event-data td {\n height: 20px!important;\n }\n\n .tr-event-condition, .tr-event-condition td, .tr-event-data, .tr-event-data td {\n padding-top: 1px!important;\n padding-bottom: 1px!important;\n }\n\n .table-events tr + .event-rooting {\n /* border-top: 1px solid #ddd; */\n }\n\n .event-rooting td {\n padding-top: 8px!important;\n padding-bottom: 4px!important;\n }\n\n .event-data-type {\n font-size: 75%;\n border-radius: 5px;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n }\n\n .event-data-display {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n }\n\n .event-if {\n font-size: 75%;\n border-radius: 5px;\n border: 1px solid #ddd;\n padding-left: 4px;\n padding-right: 4px;\n padding-top: 2px;\n padding-bottom: 2px;\n }\n\n i.fa, i.fas, i.far {\n pointer-events: none;\n }\n\n .h100 {\n height: 100%;\n }\n\n</style>\n\n<template>\n <div class=\"edit-node-panel h100\" id=\"edit-node-panel\" :key=\"n.id\">\n <div class=\"edit-node-presentation\" style=\"padding-left: 10px; padding-top: 10px; padding-right: 10px; padding-bottom: 10px;\">\n <h2 class=\"edit-dualbox-node-id\">\n <div v-if=\"nowEditingNodeName\" class=\"dualbox-node-name-edit\">\n <input type=\"text\" class=\"form-control dualbox-node-name-input\" style=\"display: inline-block;\" :value=\"n.graphId\" @keypress=\"changeNodeName\" autofocus/>\n <button class=\"btn btn-primary btn-save-node-name-change\" :data-id=\"n.graphId\" style=\"display: inline-block;\" @click=\"saveNodeName\">Save</button>\n </div>\n <div v-else class=\"dualbox-node-name\">\n <button class=\"btn btn-light btn-sm btn-edit-dualbox-node-name\" @click=\"editNodeName\"><i class=\"fa fa-edit\"></i></button>\n <span class=\"dualbox-node-name-span text-truncate d-inline-block\">{{n.graphId}}</span>\n </div>\n </h2>\n <p style=\"margin-bottom: 0\"><small class=\"edit-dualbox-node-package-name\">{{n.getPackageName()}}</small></p>\n </div>\n\n <div class=\"edit-body\">\n <div class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-desc\" data-toggle=\"collapse\" data-target=\"#dualbox-node-desc-collapse\" aria-expanded=\"true\" aria-controls=\"dualbox-node-desc-collapse\">\n <h5 class=\"mb-0 btn-link\">Description</h5>\n </div>\n\n <div id=\"dualbox-node-desc-collapse\" class=\"collapse show\" aria-labelledby=\"dualbox-node-desc\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n <div class=\"module-left-signature\">\n <graph-node :id=\"n.id\" :example=\"true\" :pkg=\"n.getPackage()\" :n=\"createExampleNode(n)\"></graph-node>\n </div>\n <p class=\"module-left-description\">\n <template v-if=\"n.isInput() || n.isOutput() || n.isMetanode()\">\n <template v-if=\"nowEditingDescription\">\n <textarea class=\"edit-node-description\" rows=4 style=\"width: 100%;\" :value=\"n.getDescription()\" autofocus>\n </textarea>\n <button class=\"btn btn-success\" @click=\"setDescription\">Save</button>\n </template>\n <template v-else>\n <button class=\"btn btn-transparent btn-xs\" @click=\"editDescription\"><i class=\"fa fa-edit\" ></i></button>\n <span> {{ getDescription() }}</span>\n </template>\n </template>\n <span v-else>\n {{ n.getPackage().description || \"[No description available]\" }}\n </span>\n </p>\n </div>\n </div>\n </div>\n\n <div class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-comments\" data-toggle=\"collapse\" data-target=\"#dualbox-node-comments-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-comments-collapse\">\n <h5 class=\"mb-0 btn-link\">Comments</h5>\n </div>\n <div id=\"dualbox-node-comments-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-comments\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <div style=\"padding-left: 15px; padding-right: 15px;\">\n <div v-if=\"nowEditingComment\" class=\"node-comment-edit\">\n <textarea class=\"node-comment\" rows=4 style=\"width: 100%;\" :data-id=\"n.id\" v-model=\"comment\" autofocus>\n </textarea>\n <div style=\"text-align: right; margin-top: 10px;\">\n <button class=\"btn btn-sm btn-secundary\" @click=\"deleteComment\">Delete</button>\n <button class=\"btn btn-sm btn-primary btn-save-comment\" @click=\"saveComment\">Save</button>\n </div>\n </div>\n <p v-else class=\"node-comment-text\">\n <span>{{ n.hasComment() ? n.getComment() : \"[Add a comment]\" }} </span>\n <button class=\"btn btn-sm btn-transparent\" @click=\"editComment\"><i class=\"fa fa-edit\"></i></button>\n </p>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Compute options -->\n <div v-if=\"n.isModule()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-compute-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-compute-collapse\">\n <h5 class=\"mb-0 btn-link\">Compute options</h5>\n </div>\n <div id=\"dualbox-node-compute-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <div class=\"form-group\" style=\"padding-left: 20px;\">\n <div>\n <label>\n <input class=\"input-cache-toggle\" type=\"checkbox\" v-bind:checked=\"n.hasCacheActivated()\" @change=\"toggleCache\">\n <span>Cache result <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Keep the result in memory (the cache) to avoid computing this box every-time its result is required. The cache will be invalidated if an input prior to this box is changed.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button></span>\n </label>\n </div>\n\n <div v-if=\"!n.isMetanode()\">\n <label>\n <input class=\"input-worker-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:checked=\"n.isParallel()\" @change=\"toggleWorker\" />\n <span>Execute in a worker <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Workers are separate contexts of executions that can execute long-running tasks without blocking the browser execution. Use this for heavy computations.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button></span>\n </label>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Widget options -->\n <div v-if=\"n.isWidget()\" class=\"card card-default\">\n <div class=\"card-header\" id=\"dualbox-node-widget\" data-toggle=\"collapse\" data-target=\"#dualbox-node-widget-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-widget-collapse\">\n <h5 class=\"mb-0 btn-link\">Widget Options</h5>\n </div>\n <div id=\"dualbox-node-widget-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-widget\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <span>Widget registered to: </span>\n <select class=\"form-control form-control-sm select-widget-registerTo\" style=\"max-width: 250px;\" @change=\"registerToWidget\">\n <option value=\"\">none</option>\n <option v-for=\"target in getSpecialUINodes()\" :key=\"'target-'+target.id\" :value=\"target.graphId\" :selected=\"n.getWidgetRegistration() == target.graphId\">{{target.id}}</option>\n\n </select>\n </div>\n </div>\n </div>\n\n <!-- Inputs -->\n <div v-if=\"n.isInput()\" class=\"card card-default\">\n <div class=\"card-header\" id=\"dualbox-node-default\" data-toggle=\"collapse\" data-target=\"#dualbox-node-default-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-default-collapse\">\n <h5 class=\"mb-0 btn-link\">Default value</h5>\n </div>\n <div id=\"dualbox-node-default-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-default\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <span>Default value:</span>\n <span><display-value :v=\"n.getDefaultValue()\" :type=\"n.getType()\" @edited=\"onEditDefaultValue\"></display-value></span>\n </div>\n </div>\n </div>\n <div v-else-if=\"n.hasInputs()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-inputs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-inputs-collapse\">\n <h5 class=\"mb-0 btn-link\">Inputs <small><span class=\"badge badge-secondary\">{{n.getInputsNames().length}}</span></small></h5>\n </div>\n <div id=\"dualbox-node-inputs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Input</th>\n <th>Visible</th>\n <th>Type</th>\n <th>Default</th>\n </thead>\n <tbody>\n <tr v-for=\"key in n.getInputsNames()\" :key=\"'input-'+key\">\n <td>\n {{key}}\n <button v-if=\"n.hasInputDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" v-bind:title=\"n.getInputDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </td>\n <td>\n <input class=\"input-visibility-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:data-input=\"key\" v-bind:checked=\"n.isInputVisible(key)\" @change=\"toggleInputVisibility\">\n </td>\n <td>\n <!-- If there's a start, then we must edit the type -->\n <display-type :type=\"n.getInputType(key)\" :readonly=\"!n.isInputTemplateType(key)\" @edited=\"onEditInputType(key, $event)\"></display-type>\n </td>\n <td>\n <display-value :v=\"n.getInputDefaultValue(key)\" :type=\"n.getInputType(key)\" @edited=\"onEditInputDefaultValue(key, $event)\" :readonly=\"!n.isFullyDefinedInputType(key)\" :readonlyReason=\"!n.isFullyDefinedInputType(key) ? 'You must first define a full type (without *) before you can edit this value' : ''\"></display-value>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <!-- Outputs -->\n <div v-if=\"n.hasOutputs()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-outputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-outputs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-outputs-collapse\">\n <h5 class=\"mb-0 btn-link\">Outputs <small><span class=\"badge badge-secondary\">{{n.getOutputsNames().length}}</span></small></h5>\n </div>\n <div id=\"dualbox-node-outputs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-outputs\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Output</th>\n <th>Type</th>\n <th>Visible</th>\n </thead>\n <tbody>\n <tr v-for=\"key in n.getOutputsNames()\" :key=\"'output-'+key\">\n <td>{{key}}\n <button v-if=\"n.hasOutputDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" v-bind:title=\"n.getOutputDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </td>\n <td><display-type :type=\"n.getOutputType(key)\"></display-type></td>\n <td>\n <input class=\"output-visibility-toggle\" type=\"checkbox\" v-bind:data-id=\"n.id\" v-bind:data-output=\"key\" v-bind:checked=\"n.isOutputVisible(key)\" @change=\"toggleOutputVisibility\">\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <!-- Attributes -->\n <div v-if=\"n.hasAttributes()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-attrs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-attrs-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-attrs-collapse\">\n <h5 class=\"mb-0 btn-link\">Attributes <small><span class=\"badge badge-secondary\">{{n.getAttributesNames().length}}</span></small></h5>\n </div>\n <div id=\"dualbox-node-attrs-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-attrs\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Output</th>\n <th>Type</th>\n <th>Value</th>\n </thead>\n <tbody>\n <tr v-for=\"key in n.getAttributesNames()\" :key=\"'attr-'+key\">\n <td>{{key}}\n <button v-if=\"n.hasAttributeDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" :title=\"n.getAttributeDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </td>\n <td>\n <!-- If there's a start, then we must edit the type -->\n <display-type :type=\"n.getAttributeType(key)\" :readonly=\"!n.isAttributeTemplateType(key)\" @edited=\"onEditAttributeType(key, $event)\"></display-type>\n </td>\n <td>\n <display-value :v=\"n.getAttributeValue(key)\" :type=\"n.getAttributeType(key)\" @edited=\"onEditAttribute(key, $event)\" :readonly=\"!n.isFullyDefinedAttributeType(key)\" :readonlyReason=\"!n.isFullyDefinedInputType(key) ? 'You must first define a full type (without *) before you can edit this value' : ''\"></display-value>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n\n <!-- Loops -->\n <div v-if=\"n.hasInputs()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-inputs\" data-toggle=\"collapse\" data-target=\"#dualbox-node-loops-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-loops-collapse\">\n <h5 class=\"mb-0 btn-link\">Loops <small><span class=\"badge badge-secondary\">{{ n.hasLoop() ? \"on\" : \"off\" }}</span></small></h5>\n </div>\n <div id=\"dualbox-node-loops-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-inputs\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <h4>Iterators\n <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Iterators will break an array in input into a list of their components. The module will be computed several times, each time with one different component from every iterator input. Inputs that don't define iterators will use their current value as-is for the different computations.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </h4>\n <table class=\"table-desc table-striped\">\n <tbody>\n <tr v-for=\"key in n.getInputsNames()\" :key=\"'loop-iterator-'+key\">\n <td>{{key}}</td>\n <td>\n <input class=\"input-iterator-toggle\" type=\"checkbox\" :data-input=\"key\" :checked=\"n.hasIterator(key)\" @change=\"toggleIterator\" />\n </td>\n </tr>\n </tbody>\n </table>\n\n <h4 class=\"mt-2\">Feedback\n <button type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"Feedback (during a loop) is a reinjection of an output result of one iteration into an input of the next iteration.\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </h4>\n <table class=\"table-desc table-striped\">\n <tbody>\n <tr v-for=\"key in n.getOutputsNames()\" :key=\"'loop-feedback-'+key\">\n <td>{{key}}</td>\n <td>\n <select class=\"form-control form-control-sm select-output-feedback\" :data-output=\"key\" @change=\"selectOutputFeedback\">\n <option value=\"none\">No feedback</option>\n <option v-for=\"i in n.getInputsNames()\" :value=\"i\" :selected=\"n.getFeedback(key) == i\" :key=\"'loop-feedback-input-'+i\">{{i}}</option>\n </select>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <!-- Events -->\n <div v-if=\"n.isUI()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"dualbox-node-events\" data-toggle=\"collapse\" data-target=\"#dualbox-node-events-collapse\" aria-expanded=\"false\" aria-controls=\"dualbox-node-events-collapse\">\n <h5 class=\"mb-0 btn-link\">Events <small><span class=\"badge badge-secondary\">{{n.getOutboundEvents().length}}</span></small></h5>\n </div>\n <div id=\"dualbox-node-events-collapse\" class=\"collapse\" aria-labelledby=\"dualbox-node-events\" data-parent=\"#edit-node-panel\">\n <div class=\"card-body\">\n <table class=\"table-events table-desc\" style=\"font-size: 12px!important;\">\n <thead class=\"thead-dark\">\n <th>Target</th>\n <th>Event</th>\n <th>Action</th>\n </thead>\n <tbody>\n <template v-if=\"n.hasOutEvents()\" v-for=\"(evt, index) in n.getOutboundEvents()\" :data-index=\"index\">\n <tr class=\"event-rooting\">\n <td>\n <select v-if=\"evt.node\" class=\"form-control form-control-sm select-event-target\" :data-index=\"index\"@change=\"selectEventTarget\" >\n <option v-for=\"node in getUINodesWithEvents()\" :value=\"node.getGraphId()\" :selected=\"node.getGraphId()==evt.node\" :key=\"node.id\">{{node.getGraphId()}}</option>\n </select>\n <span v-else>{{evt.selector}}</span>\n </td>\n <td>\n <select class=\"form-control form-control-sm select-event-name\" :data-index=\"index\" @change=\"selectEventName\">\n <template v-if=\"evt.node\">\n <option v-for=\"targetEvent in getTargetNodeEvents(evt.node)\" :value=\"targetEvent\" :selected=\"evt.event===targetEvent\" :key=\"targetEvent\">{{targetEvent}}</option>\n </template>\n <template v-else>\n <option value=\"hide\">hide</option>\n <option value=\"show\">show</option>\n </template>\n </select>\n </td>\n <td>\n <button class=\"btn btn-secondary btn-editor-xs\" :data-index=\"index\" @click=\"toggleAdvancedAppEventSettings\" style=\"margin-left: 10px;\" title=\"Toggle advanced event settings\" >\n <i class=\"fas fa-cog\"></i>\n </button>\n <button class=\"btn btn-danger btn-editor-xs btn-remove-event\" :data-index=\"index\" @click=\"removeEvent\">\n <i class=\"fa fa-minus\"></i>\n </button>\n </td>\n </tr>\n <tr v-if=\"evt.if || expanded[index]\" class=\"tr-event-condition\">\n <td colspan=\"3\">\n <span style=\"width: 60px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Occur if:</span>\n\n <input style=\"max-width: 340px; width: 340px;\" class=\"form-control form-control-sm event-if d-inline-block\" type=\"text\" dualbox-target=\"events-in\" :data-index=\"index\" :value=\"evt.if\" @change=\"setEventIf\" />\n </td>\n </tr>\n <tr v-if=\"evt.data || evt.datatype || expanded[index]\" class=\"tr-event-data\" colspan=\"3\">\n <td colspan=\"3\">\n <span style=\"width: 53px; display: inline-block;\"><i class=\"fas fa-caret-right\"></i> Data:</span>\n <span style=\"width: 350px;\">\n <display-type :type=\"getDataType(evt)\" @edited=\"onEditEventInDataType(key, index, $event)\"></display-type>\n <display-value :v=\"evt.data\" :type=\"getDataType(evt)\" @edited=\"onEditEventData(key, index, $event)\"></display-value>\n </span>\n </td>\n </tr>\n </template>\n <tr>\n <td colspan=\"5\" style=\"padding-top: 0px; padding-bottom: 0px;\">\n <button class=\"btn btn-sm\" :data-id=\"n.id\" style=\"width: 100%;\" @click=\"addEvent\">Add event</button>\n </td>\n </tr>\n </tbody>\n </table>\n\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"modal edit-value-modal\" tabindex=\"-1\" role=\"dialog\">\n <div class=\"modal-dialog\" role=\"document\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">Edit value</h5>\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n <div class=\"modal-body\">\n <div class=\"set-type\">\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value unset-value\" id=\"unset-value\" name=\"set-value\" value=\"unset-value\" checked>\n <label class=\"form-check-label\" for=\"unset-value\">\n don't set a value\n </label>\n </div>\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value set-value-null\" id=\"set-value-null\" name=\"set-value\" value=\"set-value-null\">\n <label class=\"form-check-label\" for=\"set-value-null\">\n set null\n </label>\n </div>\n <div class=\"form-check\">\n <input type=\"radio\" class=\"form-check-input set-value set-value-type\" id=\"set-value-type\" name=\"set-value\" value=\"set-value-type\" aria-label=\"Set a value of type\">\n <div class=\"form-inline form-check-label\" style=\"height: 24px;\">\n <label for=\"set-value-type\">\n set a value of type:\n <select class=\"form-control choose-value-type d-inline-block form-control-sm ml-2\">\n <option value=\"string\">String</option>\n <option value=\"number\">Number</option>\n <option value=\"boolean\">Boolean</option>\n <option value=\"object\">Object</option>\n <option value=\"file\">File</option>\n </select>\n </label>\n </div>\n </div>\n </div>\n <hr class=\"separator\"/>\n <div class=\"has-value\" style=\"display: none;\">\n <div class=\"define-value define-boolean\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <select class=\"form-control form-control-sm bool-value d-inline-block ml-2\">\n <option value=true>True</option>\n <option value=false>False</option>\n </select>\n </div>\n </div>\n <div class=\"define-value define-file\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>File input</label>\n <input type=\"file\" class=\"form-control-file form-control-sm file-value\">\n </div>\n </div>\n <div class=\"define-value define-number\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <input type=\"number\" class=\"form-control form-control-sm number-value ml-2\"/>\n </div>\n </div>\n <div class=\"define-value define-string\" style=\"display: none;\">\n <div class=\"form-inline\">\n <label>Value: </label>\n <input type=\"text\" class=\"form-control form-control-sm text-value ml-2\"/>\n </div>\n </div>\n <div class=\"define-value define-object\" style=\"display: none;\">\n <label>Value: </label>\n <div class=\"json-editor\" style=\"height: 400px;\"></div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-primary btn-save\">Save changes</button>\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\n </div>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script>\nimport _ from 'lodash';\nimport DisplayTypeVue from './displayType.vue';\nimport DisplayValueVue from './displayValue.vue';\nimport GraphNodeVue from './graphNode.vue';\nimport JSONEditor from '@dualbox/dualbox-lib-jsoneditor';\nimport swal from 'sweetalert2';\n\nexport default {\n props: [\n \"id\", // the GraphNode object\n ],\n components: {\n \"display-type\" : DisplayTypeVue,\n \"display-value\" : DisplayValueVue,\n \"graph-node\" : GraphNodeVue\n },\n data: function () {\n return {\n comment: null,\n expanded: {}, // expanded app events (advanced settings)\n\n // states\n isParallel: false,\n nowEditingComment: false,\n nowEditingNodeName: false,\n nowEditingDescription: false,\n };\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n this.n = this.view.m.getNode(this.id);\n\n // fetch the comment for this node\n this.comment = this.n.hasComment() ? this.n.getComment() : \"\";\n this.isParallel = this.n.isParallel();\n },\n mounted: function() {\n // adapt the style of the example graph node\n // remove the \"position: absolute;\" that messes up the display\n this.fixCardStyle();\n this.fixMaxHeightForCategories();\n\n // allow tooltips\n this.activateTooltip();\n\n // bind the json editor\n editor = new JSONEditor($(this.$el).find('.json-editor')[0], { modes: ['tree', 'code', 'text' ]});\n editor.set({});\n },\n beforeUpdate: function() {\n //console.log('[Updating] node-settings');\n // we need to refresh our node object\n this.n = this.view.m.getNode(this.id); // it breaks updating node name\n this.deactivateTooltip();\n },\n updated: function() {\n //console.log('[Updated] node-settings');\n this.fixCardStyle();\n this.fixMaxHeightForCategories();\n this.activateTooltip();\n this.focus();\n },\n activate: function() {\n this.activateTooltip();\n this.focus();\n },\n deactivate: function() {\n this.deactivateTooltip();\n },\n methods: {\n fixCardStyle: function() {\n var card = $(this.$el).find('.module-left-signature .card');\n card.css('position', 'static').css('point-events', 'none');\n card.find('.point').css(\"visibibility\", \"visible\").find('svg').css(\"visibibility\", \"visible\");\n card.ready(() => {\n var width = Math.max(\n card.find('.inputs').width() + card.find('.outputs').width() + 20,\n card.find('.title').width() + 60,\n card.find('.subtitle').width() + 40\n );\n card.css('width', width + 'px');\n card.addClass('mx-auto');\n });\n },\n\n // setup a max height for each menu, so a scroll appears if there's too much item in it\n fixMaxHeightForCategories : function() {\n let nbActiveCategories = $(this.$el).find('.edit-body > .card-settings').length;\n let headerHeight = $(this.$el).find('.edit-body > .card-settings > .card-header').outerHeight();\n let panelHeight = $(this.$el).height() - $(this.$el).find('.edit-node-presentation').outerHeight();\n let maxCategoryHeight = panelHeight - nbActiveCategories * headerHeight;\n $(this.$el).find('.edit-body').css('height', panelHeight);\n $(this.$el).find('.edit-body > .card-settings > .collapse > .card-body').css('max-height', maxCategoryHeight + \"px\");\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 focus: function() {\n $(this.$el).find('[autofocus]').focus();\n },\n\n // for widget registration\n getSpecialUINodes: function() {\n var targets = this.n.m.getSpecialUINodes( this.n.getRegisterType() );\n return targets;\n },\n\n getUINodesWithEvents : function() {\n var nodes = this.n.m.getNodes(\"ui\");\n var eventNodes = nodes.filter( function(n) {\n return n.getEventsNames().length > 0;\n });\n return eventNodes;\n },\n\n getTargetNodeEvents: function(nodeId) {\n var targetNode = this.n.m.getNode(nodeId);\n return targetNode.getEventsNames();\n },\n\n editComment: function(e) {\n this.nowEditingComment = true;\n },\n\n saveComment: function(e) {\n var val = $(this.$el).find('.node-comment').val();\n this.view.c.setComment(this.n.id, val);\n this.nowEditingComment = false;\n this.onEdited();\n },\n\n deleteComment: function(e) {\n this.view.c.deleteComment(this.n.id);\n this.nowEditingComment = false;\n this.onEdited();\n },\n\n addEvent: function(e) {\n this.view.c.addEvent(this.n.id);\n this.onEdited();\n },\n\n toggleInputVisibility: function(e) {\n var inputName = $(e.target).data('input');\n var visible = $(e.target).is(\":checked\");\n if( !this.view.c.setInputVisibility(this.n.id, inputName, visible) ) {\n // failed, reset this to old value\n $(e.target).prop('checked', !visible);\n }\n },\n\n toggleOutputVisibility: function(e) {\n var outputName = $(e.target).data('output');\n var visible = $(e.target).is(\":checked\");\n if( !this.view.c.setOutputVisibility(this.n.id, outputName, visible) ) {\n // failed, reset this to old value\n $(e.target).prop('checked', !visible);\n }\n },\n\n editNodeName: function(e) {\n this.nowEditingNodeName = true;\n },\n\n changeNodeName: function(e) {\n // user pressed enter\n if(e.which == 13 || e.keyCode == 13) {\n this.saveNodeName(e);\n }\n },\n\n saveNodeName: function(e) {\n var newId = $(e.target).parent().find('.dualbox-node-name-input').val();\n this.view.c.renameBox(this.n.graphId, newId, this.n.type);\n\n // get the new node\n switch( this.n.type ) {\n case \"input\": this.n = this.view.m.getNode(\"in-\"+newId); break;\n case \"output\": this.n = this.view.m.getNode(\"in-\"+newId); break;\n default: this.n = this.view.m.getNode(newId);\n }\n\n this.nowEditingNodeName = false;\n },\n\n toggleIterator: function(e) {\n var destInput = $(e.target).attr('data-input');\n if( $(e.target).is(\":checked\") ) {\n this.view.c.setIterator( this.n.id, destInput );\n }\n else {\n this.view.c.unsetIterator( this.n.id, destInput );\n }\n this.onEdited();\n },\n\n registerToWidget: function(e) {\n var targetId = $(e.target).val();\n this.view.c.registerWidget(this.n.id, targetId);\n },\n\n selectOutputFeedback: function(e) {\n var val = $(e.target).val();\n var destOutput = $(e.target).attr('data-output');\n if( val !== \"none\" ) {\n this.view.c.setFeedback( this.n.id, destOutput, val );\n }\n else {\n this.view.c.unsetFeedback( this.n.id, destOutput );\n }\n },\n\n removeEvent: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n this.view.c.removeEvent( this.n.id, index );\n this.$forceUpdate();\n },\n\n setEventIf: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventIf( this.n.id, index, val );\n },\n\n setEventData: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventData( this.n.id, index, val );\n },\n\n // TODO: remake this into it's own vue\n selectEventTarget: function(e) {\n var target = $(e.target).val();\n\n // change options of closest .select-event-name according to this new target\n var targetNode = this.view.m.getNode(target);\n var targetEvents = targetNode.getEventsNames();\n\n var index = parseInt($(e.target).attr('data-index'));\n this.view.c.setEventTarget( this.n.id, index, target );\n this.onEdited();\n },\n\n selectEventName: function(e) {\n var index = parseInt($(e.target).attr('data-index'));\n var val = $(e.target).val();\n this.view.c.setEventName( this.n.id, index, val );\n this.onEdited();\n },\n\n toggleCache: function(e) {\n var val = $(e.target).is(':checked');\n this.view.c.setBoxCache( this.n.id, val );\n },\n\n toggleWorker: function(e) {\n var val = $(e.target).is(':checked');\n this.view.c.setBoxParallel( this.n.id, val );\n this.isParallel = val;\n this.onEdited();\n },\n\n editModuleDescription: function(e) {\n var desc = $(e.target).attr('data-desc');\n\n swal({\n title: \"Describe what this metabox does\",\n input: \"textarea\",\n inputValue: desc || \"\",\n showCancelButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true,\n animation: \"slide-from-top\",\n inputPlaceholder: \"This metabox...\"\n }).then( (result) => {\n if (result.value === \"\") {\n swal.showInputError(\"You need to write something!\");\n return false;\n }\n else {\n this.view.c.setMetanodeDescription(this.n.id, result.value);\n }\n });\n },\n\n createExampleNode(n) {\n return this.view.m.createCloneNode(n.getPackage().name, n.id)\n },\n\n onEditInputType(inputName, typeStr) {\n this.n.assignInputType(inputName, typeStr);\n this.onEdited();\n this.view.repaint();\n },\n\n onEditAttributeType(attributeName, typeStr) {\n this.n.assignAttributeType(attributeName, typeStr);\n this.onEdited();\n this.view.repaint();\n },\n\n onEditDefaultValue(val) {\n this.n.setDefaultValue(val);\n this.onEdited();\n this.view.repaint();\n },\n\n onEditInputDefaultValue(inputName, val) {\n if( val === undefined ) {\n this.n.deleteVal(\"input\", inputName);\n this.n.setInputVisibility(inputName, true); // show the input then (connection needed)\n }\n else {\n this.n.val(\"input\", inputName, val );\n this.n.setInputVisibility(inputName, false); // hide inputs with values (no connection needed)\n }\n this.onEdited();\n this.view.repaint();\n },\n\n onEditAttribute(attrName, val) {\n if( val === undefined ) {\n this.n.deleteVal(\"attr\", attrName);\n }\n else {\n this.n.val(\"attr\", attrName, val);\n }\n this.onEdited();\n },\n\n onEditDefaultInput(inputName, val) {\n if( val === undefined ) {\n this.n.deleteVal(\"input\", inputName);\n }\n else {\n this.n.val(\"input\", inputName, val);\n }\n this.onEdited();\n this.view.repaint();\n },\n\n onEdited() {\n // we need to refresh our node object\n this.n = this.view.m.getNode(this.id); // it breaks updating node name\n this.$forceUpdate();\n },\n\n getDataType: function(evt) {\n if( evt.datatype ) {\n return evt.datatype;\n }\n else if( evt.data ) {\n return window.DualBox.Type.detectType(evt.data);\n }\n else {\n return undefined;\n }\n },\n\n toggleAdvancedAppEventSettings: function(e) {\n var index = $(e.target).data('index');\n this.expanded[index] = this.expanded[index] ? false : true;\n this.$forceUpdate();\n },\n\n onEditEventData(key, index, val) {\n this.view.c.setEventData( this.n.id, index, val );\n this.$forceUpdate();\n },\n\n onEditEventInDataType(key, index, type) {\n this.view.c.setEventDataType( this.n.id, index, type);\n\n // check that the set value still match the new type\n // delete it otherwise\n var val = this.n.getOutboundEvents()[index].data;\n try {\n // TODO: ensure type is already loaded (after dualbox) and remove the try/catch\n if( !window.DualBox.Type.check(type, val) ) {\n // delete data (== set undefined)\n this.view.c.setEventData( this.n.id, index, undefined);\n }\n }\n catch(e) {\n this.view.c.setEventData( this.n.id, index, undefined);\n }\n\n this.$forceUpdate();\n },\n\n getDescription() {\n return this.n.getDescription() || \"[Add a description]\"\n },\n\n editDescription() {\n this.nowEditingDescription = true;\n },\n\n setDescription() {\n var val = $(this.$el).find('.edit-node-description').val();\n if( this.n.isInput() ) {\n this.view.c.setInputDescription(this.n.graphId, val);\n }\n else if( this.n.isOutput() ) {\n this.view.c.setOutputDescription(this.n.graphId, val);\n }\n else if( this.n.isMetanode() ) {\n this.view.c.setMetanodeDescription(this.n.graphId, val);\n }\n this.nowEditingDescription = false;\n\n this.$forceUpdate();\n },\n }\n}\n\n\n</script>\n"]}, media: undefined });
|
|
67981
68013
|
|
|
67982
68014
|
};
|
|
67983
68015
|
/* scoped */
|
|
@@ -87044,7 +87076,7 @@ __vue_render__$d._withStripped = true;
|
|
|
87044
87076
|
/* style */
|
|
87045
87077
|
const __vue_inject_styles__$d = function (inject) {
|
|
87046
87078
|
if (!inject) return
|
|
87047
|
-
inject("data-v-402f1ef4_0", { source: "\n.code-panel {\n width: 30%;\n height: 100%;\n vertical-align: top;\n float: left;\n}\n.application-container {\n width: calc(70% - 5px);\n height: 100%;\n display: inline-block;\n vertical-align: top;\n float: right;\n}\n.code-controls, .run-options {\n width: 100%;\n height: 60px;\n}\n.application {\n width: 100%;\n height: calc(100% - 60px);\n background-color: #ccc;\n}\n.dragbar {\n height: 100%;\n width: 5px;\n background-color: #e7e7e7;\n display: inline-block;\n cursor: col-resize;\n}\n.code-content {\n position: relative;\n height: calc(100% - 56px);\n}\n.code-html-container {\n position: relative;\n height: 50%;\n border-bottom: 1px solid #e7e7e7;\n}\n.code-css-container {\n position: relative;\n height: calc(50% - 1px);\n overflow: hidden;\n}\n.code-css {\n width: 100%;\n height: 100%;\n}\n.code-html {\n height: calc(100% - 40px);\n width: 100%;\n}\n.CodeMirror {\n height: 100%!important;\n}\n.code-badge {\n position: absolute;\n top: 10px;\n right: 10px;\n padding: 10px;\n}\n.btn-light.focus, .btn-light:focus {\n box-shadow: none!important;\n}\n.button-bar {\n width: 60px;\n padding: 10px;\n border-bottom: 1px solid #e7e7e7;\n width: 100%;\n background-color: white;\n}\n.noselect {\n -webkit-user-select: none; /* Chrome/Safari */\n -moz-user-select: none; /* Firefox */\n -ms-user-select: none; /* IE10+ */\n -o-user-select: none;\n user-select: none;\n}\n.btn + .btn {\n margin-left: 5px;\n}\n.btn-graph-goto {\n box-shadow: none!important;\n}\n.nav-tabs {\n border-bottom: none;\n}\n.main-navigation a.nav-link {\n color: white;\n}\n.main-navigation a.nav-link.active {\n color: #212529;\n}\n.dualbox-editor-body {\n width: 100%;\n height: 100%;\n overflow: hidden;\n background-color: rgb(85, 85, 85);\n}\n.dualbox-graph-left-section {\n height: 100%;\n width: 500px;\n float: left;\n position: relative;\n overflow: hidden;\n margin-left: -465px;\n transition: margin-left 0.3s ease;\n}\n.dualbox-graph-left-window {\n width: calc(100% - 35px);\n height: calc(100% - 20px);\n margin-top: 10px;\n margin-bottom: 30px;\n /* background-color: #ECF2F8; */\n background-color: #f8f9fa;\n /* border: 1px solid grey; */\n border-radius: 5px;\n position: relative;\n float: left;\n}\n.dualbox-graph-left-panel {\n width: 100%;\n height: 100%;\n}\n.btn-toggle-left-window {\n position: absolute;\n right: 0;\n top: 0;\n margin-right: -35px;\n z-index: 100;\n border-top-left-radius: 0px;\n border-bottom-left-radius: 0px;\n}\n.btn-toggle-left-window:hover, .btn-toggle-right-window:hover, .btn-toggle-left-window:focus, .btn-toggle-right-window:focus, .btn-toggle-left-window:active, .btn-toggle-right-window:active, .btn-toggle-left-window:active:hover, .btn-toggle-right-window:active:hover {\n color: #212529!important;\n background-color: #f8f9fa!important;\n border-color: #f8f9fa!important;\n}\n.dualbox-graph-right-section {\n height: 100%;\n width: 500px;\n float: right;\n position: relative;\n overflow: hidden;\n margin-right: -465px;\n transition: margin-right 0.3s ease;\n}\n.dualbox-graph-right-window {\n width: calc(100% - 35px);\n height: calc(100% - 20px);\n margin-top: 10px;\n margin-bottom: 30px;\n /* background-color: #ECF2F8; */\n background-color: #f8f9fa;\n /* border: 1px solid grey; */\n border-radius: 5px;\n position: relative;\n float: right;\n}\n.dualbox-graph-right-panel {\n width: 100%;\n height: 100%;\n}\n.btn-toggle-right-window {\n position: absolute;\n left: 0;\n top: 0;\n margin-left: -35px;\n z-index: 100;\n border-top-right-radius: 0px;\n border-bottom-right-radius: 0px;\n}\n.dualbox-graph-tab {\n height: 100%;\n width: 100%;\n background-color: #555!important;\n}\n.dualbox-graph-main {\n height: 100%;\n width: calc(100% - 70px);\n float: right;\n background-color: #555!important;\n transition: width 0.3s ease;\n}\n.dualbox-graph-main.left-panel-expanded {\n width: calc(100% - 535px);\n margin-left: -465px;\n}\n.dualbox-graph-main.right-panel-expanded {\n width: calc(100% - 535px);\n}\n.dualbox-graph-main.left-panel-expanded.right-panel-expanded {\n width: calc(100% - 1000px);\n margin-left: -465px;\n}\n.opacity0 {\n opacity: 0;\n}\n.btn-editor-xs {\n width: 18px;\n padding : 3px!important;\n line-height : .5;\n border-radius : 2px;\n}\n.btn-editor-xs > i {\n font-size : 10px;\n}\n.btn-outline-discrete {\n border-color: rgba(0,0,0,0.05);\n border-color: transparent;\n color: rgba(0,0,0,0.3);\n}\n.dualbox-app-navigation {\n background-color: transparent;\n margin-bottom: 0;\n vertical-align: middle;\n padding-top: 7px;\n padding-bottom: 7px;\n font-weight: bold;\n user-select: none;\n}\n.app-topbar {\n border-bottom: none;\n padding-left: 15px;\n padding-right: 15px;\n display: flex;\n width: 100%;\n height: 58px;\n padding-top: 10px;\n padding-bottom: 10px;\n}\n.dark, .graph-tab.active, .nav-item.active .graph-tab {\n color: white!important;\n background-color: #555!important;\n}\n.light {\n color: #4d4d4d!important;\n background-color: #f8f9fa!important;\n}\n.main-navigation .nav-link, .main-navigation .nav-link.active, .nav-item.active .nav-link {\n border-bottom: none;\n border-left: none;\n border-top: none;\n border-right: none;\n position: relative;\n top: 1px;\n}\n.btn:focus, button:focus {\n outline: none;\n box-shadow: none;\n}\n.btn-transparent, .btn-transparent:hover, .btn-transparent:focus {\n background-color: transparent;\n}\n.connection-control {\n position: absolute;\n height: 14px;\n width: 14px;\n background-color: transparent;\n z-index: 19;\n cursor: move;\n}\n.connection-control.selected {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n}\n.connection-label {\n z-index: 22!important;\n color: #004d00!important;\n background-color: white!important;\n padding: 4px 4px;\n border: 2px solid #004d00;\n font-size: 16px!important;\n border-radius: 5px;\n}\n.input-color-tag {\n background-color: #F2D600;\n}\n.output-color-tag {\n background-color: #FFAB4A;\n}\n.ui-color-tag {\n background-color: #61BD4F;\n}\n.metanode-color-tag {\n background-color: #DDDDDD;\n}\n.input {\n}\n.output {\n}\n.fileUpload {\n position: relative;\n overflow: hidden;\n margin: 10px;\n}\n.fileUpload input.upload {\n position: absolute;\n top: 0;\n right: 0;\n margin: 0;\n padding: 0;\n font-size: 20px;\n cursor: pointer;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.module-edit-modal-body .btn+.btn {\n margin-bottom: 0;\n margin-left: 5px;\n}\n.btn-add-node {\n width:46%;\n margin:1%;\n}\nbutton.close {\n position: absolute;\n right: 0;\n margin-right: 5px!important;\n}\n.CodeMirror {\n height: auto;\n min-height: 300px;\n}\n.load-app, .save-app {\n margin-left: 5px;\n margin-right: 5px;\n}\n.btn-xs {\n padding: 0px 4px;\n font-size: 12px;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/main.vue"],"names":[],"mappings":";AACA;IACA,UAAA;IACA,YAAA;IACA,mBAAA;IACA,WAAA;AACA;AAEA;IACA,sBAAA;IACA,YAAA;IACA,qBAAA;IACA,mBAAA;IACA,YAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,WAAA;IACA,yBAAA;IACA,sBAAA;AACA;AAEA;IACA,YAAA;IACA,UAAA;IACA,yBAAA;IACA,qBAAA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;IACA,yBAAA;AACA;AAEA;IACA,kBAAA;IACA,WAAA;IACA,gCAAA;AACA;AAEA;IACA,kBAAA;IACA,uBAAA;IACA,gBAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,yBAAA;IACA,WAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,kBAAA;IACA,SAAA;IACA,WAAA;IACA,aAAA;AACA;AAEA;IACA,0BAAA;AACA;AAEA;IACA,WAAA;IACA,aAAA;IACA,gCAAA;IACA,WAAA;IACA,uBAAA;AACA;AAEA;IACA,yBAAA,EAAA,kBAAA;IACA,sBAAA,EAAA,YAAA;IACA,qBAAA,EAAA,UAAA;IACA,oBAAA;IACA,iBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,0BAAA;AACA;AAEA;IACA,mBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;IACA,gBAAA;IACA,iCAAA;AACA;AAEA;IACA,YAAA;IACA,YAAA;IACA,WAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;IACA,iCAAA;AACA;AAEA;IACA,wBAAA;IACA,yBAAA;IACA,gBAAA;IACA,mBAAA;IACA,+BAAA;IACA,yBAAA;IACA,4BAAA;IACA,kBAAA;IACA,kBAAA;IACA,WAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,MAAA;IACA,mBAAA;IACA,YAAA;IACA,2BAAA;IACA,8BAAA;AACA;AAEA;IACA,wBAAA;IACA,mCAAA;IACA,+BAAA;AACA;AAEA;IACA,YAAA;IACA,YAAA;IACA,YAAA;IACA,kBAAA;IACA,gBAAA;IACA,oBAAA;IACA,kCAAA;AACA;AAEA;IACA,wBAAA;IACA,yBAAA;IACA,gBAAA;IACA,mBAAA;IACA,+BAAA;IACA,yBAAA;IACA,4BAAA;IACA,kBAAA;IACA,kBAAA;IACA,YAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,OAAA;IACA,MAAA;IACA,kBAAA;IACA,YAAA;IACA,4BAAA;IACA,+BAAA;AACA;AAEA;IACA,YAAA;IACA,WAAA;IACA,gCAAA;AACA;AAEA;IACA,YAAA;IACA,wBAAA;IACA,YAAA;IACA,gCAAA;IACA,2BAAA;AACA;AAEA;IACA,yBAAA;IACA,mBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,0BAAA;IACA,mBAAA;AACA;AAEA;IACA,UAAA;AACA;AAEA;IACA,WAAA;IACA,wBAAA;IACA,iBAAA;IACA,mBAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,8BAAA;IACA,yBAAA;IACA,sBAAA;AACA;AAEA;IACA,6BAAA;IACA,gBAAA;IACA,sBAAA;IACA,gBAAA;IACA,mBAAA;IACA,iBAAA;IACA,iBAAA;AACA;AAEA;IACA,mBAAA;IACA,kBAAA;IACA,mBAAA;IACA,aAAA;IACA,WAAA;IACA,YAAA;IACA,iBAAA;IACA,oBAAA;AACA;AAEA;IACA,sBAAA;IACA,gCAAA;AACA;AAEA;IACA,wBAAA;IACA,mCAAA;AACA;AAEA;IACA,mBAAA;IACA,iBAAA;IACA,gBAAA;IACA,kBAAA;IACA,kBAAA;IACA,QAAA;AACA;AAEA;IACA,aAAA;IACA,gBAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,kBAAA;IACA,YAAA;IACA,WAAA;IACA,6BAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,qBAAA;IACA,wBAAA;IACA,iCAAA;IACA,gBAAA;IACA,yBAAA;IACA,yBAAA;IACA,kBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;AACA;AAEA;AACA;AAGA;IACA,kBAAA;IACA,gBAAA;IACA,YAAA;AACA;AACA;IACA,kBAAA;IACA,MAAA;IACA,QAAA;IACA,SAAA;IACA,UAAA;IACA,eAAA;IACA,eAAA;IACA,UAAA;IACA,wBAAA;AACA;AAGA;IACA,gBAAA;IACA,gBAAA;AACA;AAEA;IACA,SAAA;IACA,SAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,2BAAA;AACA;AAEA;IACA,YAAA;IACA,iBAAA;AACA;AAEA;IACA,gBAAA;IACA,iBAAA;AACA;AAEA;IACA,gBAAA;IACA,eAAA;AACA","file":"main.vue","sourcesContent":["<style>\n .code-panel {\n width: 30%;\n height: 100%;\n vertical-align: top;\n float: left;\n }\n\n .application-container {\n width: calc(70% - 5px);\n height: 100%;\n display: inline-block;\n vertical-align: top;\n float: right;\n }\n\n .code-controls, .run-options {\n width: 100%;\n height: 60px;\n }\n\n .application {\n width: 100%;\n height: calc(100% - 60px);\n background-color: #ccc;\n }\n\n .dragbar {\n height: 100%;\n width: 5px;\n background-color: #e7e7e7;\n display: inline-block;\n cursor: col-resize;\n }\n\n .code-content {\n position: relative;\n height: calc(100% - 56px);\n }\n\n .code-html-container {\n position: relative;\n height: 50%;\n border-bottom: 1px solid #e7e7e7;\n }\n\n .code-css-container {\n position: relative;\n height: calc(50% - 1px);\n overflow: hidden;\n }\n\n .code-css {\n width: 100%;\n height: 100%;\n }\n\n .code-html {\n height: calc(100% - 40px);\n width: 100%;\n }\n\n .CodeMirror {\n height: 100%!important;\n }\n\n .code-badge {\n position: absolute;\n top: 10px;\n right: 10px;\n padding: 10px;\n }\n\n .btn-light.focus, .btn-light:focus {\n box-shadow: none!important;\n }\n\n .button-bar {\n width: 60px;\n padding: 10px;\n border-bottom: 1px solid #e7e7e7;\n width: 100%;\n background-color: white;\n }\n\n .noselect {\n -webkit-user-select: none; /* Chrome/Safari */\n -moz-user-select: none; /* Firefox */\n -ms-user-select: none; /* IE10+ */\n -o-user-select: none;\n user-select: none;\n }\n\n .btn + .btn {\n margin-left: 5px;\n }\n\n .btn-graph-goto {\n box-shadow: none!important;\n }\n\n .nav-tabs {\n border-bottom: none;\n }\n\n .main-navigation a.nav-link {\n color: white;\n }\n\n .main-navigation a.nav-link.active {\n color: #212529;\n }\n\n .dualbox-editor-body {\n width: 100%;\n height: 100%;\n overflow: hidden;\n background-color: rgb(85, 85, 85);\n }\n\n .dualbox-graph-left-section {\n height: 100%;\n width: 500px;\n float: left;\n position: relative;\n overflow: hidden;\n margin-left: -465px;\n transition: margin-left 0.3s ease;\n }\n\n .dualbox-graph-left-window {\n width: calc(100% - 35px);\n height: calc(100% - 20px);\n margin-top: 10px;\n margin-bottom: 30px;\n /* background-color: #ECF2F8; */\n background-color: #f8f9fa;\n /* border: 1px solid grey; */\n border-radius: 5px;\n position: relative;\n float: left;\n }\n\n .dualbox-graph-left-panel {\n width: 100%;\n height: 100%;\n }\n\n .btn-toggle-left-window {\n position: absolute;\n right: 0;\n top: 0;\n margin-right: -35px;\n z-index: 100;\n border-top-left-radius: 0px;\n border-bottom-left-radius: 0px;\n }\n\n .btn-toggle-left-window:hover, .btn-toggle-right-window:hover, .btn-toggle-left-window:focus, .btn-toggle-right-window:focus, .btn-toggle-left-window:active, .btn-toggle-right-window:active, .btn-toggle-left-window:active:hover, .btn-toggle-right-window:active:hover {\n color: #212529!important;\n background-color: #f8f9fa!important;\n border-color: #f8f9fa!important;\n }\n\n .dualbox-graph-right-section {\n height: 100%;\n width: 500px;\n float: right;\n position: relative;\n overflow: hidden;\n margin-right: -465px;\n transition: margin-right 0.3s ease;\n }\n\n .dualbox-graph-right-window {\n width: calc(100% - 35px);\n height: calc(100% - 20px);\n margin-top: 10px;\n margin-bottom: 30px;\n /* background-color: #ECF2F8; */\n background-color: #f8f9fa;\n /* border: 1px solid grey; */\n border-radius: 5px;\n position: relative;\n float: right;\n }\n\n .dualbox-graph-right-panel {\n width: 100%;\n height: 100%;\n }\n\n .btn-toggle-right-window {\n position: absolute;\n left: 0;\n top: 0;\n margin-left: -35px;\n z-index: 100;\n border-top-right-radius: 0px;\n border-bottom-right-radius: 0px;\n }\n\n .dualbox-graph-tab {\n height: 100%;\n width: 100%;\n background-color: #555!important;\n }\n\n .dualbox-graph-main {\n height: 100%;\n width: calc(100% - 70px);\n float: right;\n background-color: #555!important;\n transition: width 0.3s ease;\n }\n\n .dualbox-graph-main.left-panel-expanded {\n width: calc(100% - 535px);\n margin-left: -465px;\n }\n\n .dualbox-graph-main.right-panel-expanded {\n width: calc(100% - 535px);\n }\n\n .dualbox-graph-main.left-panel-expanded.right-panel-expanded {\n width: calc(100% - 1000px);\n margin-left: -465px;\n }\n\n .opacity0 {\n opacity: 0;\n }\n\n .btn-editor-xs {\n width: 18px;\n padding : 3px!important;\n line-height : .5;\n border-radius : 2px;\n }\n\n .btn-editor-xs > i {\n font-size : 10px;\n }\n\n .btn-outline-discrete {\n border-color: rgba(0,0,0,0.05);\n border-color: transparent;\n color: rgba(0,0,0,0.3);\n }\n\n .dualbox-app-navigation {\n background-color: transparent;\n margin-bottom: 0;\n vertical-align: middle;\n padding-top: 7px;\n padding-bottom: 7px;\n font-weight: bold;\n user-select: none;\n }\n\n .app-topbar {\n border-bottom: none;\n padding-left: 15px;\n padding-right: 15px;\n display: flex;\n width: 100%;\n height: 58px;\n padding-top: 10px;\n padding-bottom: 10px;\n }\n\n .dark, .graph-tab.active, .nav-item.active .graph-tab {\n color: white!important;\n background-color: #555!important;\n }\n\n .light {\n color: #4d4d4d!important;\n background-color: #f8f9fa!important;\n }\n\n .main-navigation .nav-link, .main-navigation .nav-link.active, .nav-item.active .nav-link {\n border-bottom: none;\n border-left: none;\n border-top: none;\n border-right: none;\n position: relative;\n top: 1px;\n }\n\n .btn:focus, button:focus {\n outline: none;\n box-shadow: none;\n }\n\n .btn-transparent, .btn-transparent:hover, .btn-transparent:focus {\n background-color: transparent;\n }\n\n .connection-control {\n position: absolute;\n height: 14px;\n width: 14px;\n background-color: transparent;\n z-index: 19;\n cursor: move;\n }\n\n .connection-control.selected {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n }\n\n .connection-label {\n z-index: 22!important;\n color: #004d00!important;\n background-color: white!important;\n padding: 4px 4px;\n border: 2px solid #004d00;\n font-size: 16px!important;\n border-radius: 5px;\n }\n\n .input-color-tag {\n background-color: #F2D600;\n }\n\n .output-color-tag {\n background-color: #FFAB4A;\n }\n\n .ui-color-tag {\n background-color: #61BD4F;\n }\n\n .metanode-color-tag {\n background-color: #DDDDDD;\n }\n\n .input {\n }\n\n .output {\n }\n\n\n .fileUpload {\n position: relative;\n overflow: hidden;\n margin: 10px;\n }\n .fileUpload input.upload {\n position: absolute;\n top: 0;\n right: 0;\n margin: 0;\n padding: 0;\n font-size: 20px;\n cursor: pointer;\n opacity: 0;\n filter: alpha(opacity=0);\n }\n\n\n .module-edit-modal-body .btn+.btn {\n margin-bottom: 0;\n margin-left: 5px;\n }\n\n .btn-add-node {\n width:46%;\n margin:1%;\n }\n\n button.close {\n position: absolute;\n right: 0;\n margin-right: 5px!important;\n }\n\n .CodeMirror {\n height: auto;\n min-height: 300px;\n }\n\n .load-app, .save-app {\n margin-left: 5px;\n margin-right: 5px;\n }\n\n .btn-xs {\n padding: 0px 4px;\n font-size: 12px;\n }\n</style>\n\n<template>\n <div class=\"dualbox-editor-body\">\n <nav class=\"main-navigation navbar navbar-default\" style=\"position: relative; margin-bottom: 0px; padding: 0; padding-top: 5px; background-color: #2e6da4;\">\n <ul class=\"nav nav-tabs\">\n <li class=\"nav-item active\">\n <a class=\"nav-link graph-tab\" href=\"#editor-graph-tab\" data-toggle=\"tab\">Application Graph</a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link interface-tab\" href=\"#editor-interface-tab\" data-toggle=\"tab\">Interface Editor</a>\n </li>\n </ul>\n\n <div class=\"nav navbar-right\" style=\"vertical-align: top; margin-top: 5px; margin-right: 10px; margin-bottom: 5px;\">\n <div v-if=\"showLoadButton === true\">\n <button class=\"load-app btn btn-sm btn-light\" style=\"position: relative; bottom: 3px;\" @click=\"loadApp\">Load App</button>\n </div>\n <div v-if=\"showSaveButton\">\n <button class=\"save-app btn btn-sm btn-light\" style=\"position: relative; bottom: 3px;\" @click=\"saveApp\">Save App</button>\n </div>\n </div>\n </nav>\n <div class=\"tab-content dualbox-graph-tab\" style=\"width: 100%; height: calc(100% - 46px);\">\n <div class=\"tab-pane active\" id=\"editor-graph-tab\" style=\"width: 100%; height: 100%;\">\n <div class=\"dualbox-graph-left-section dark\">\n <div class=\"dualbox-graph-left-window\">\n <button class=\"btn btn-light btn-toggle-left-window\" @click=\"toggleLeftWindow\" title=\"shrink window\" data-expanded=\"false\"><i class=\"fa fa-angle-double-right\"></i></button>\n <div class=\"dualbox-graph-left-panel light\">\n <edit-node-settings v-if=\"leftPanelMode == 'node' && selectedNodeId !== null\" :id=\"selectedNodeId\" :key=\"selectedNodeId\"></edit-node-settings>\n <edit-main-settings v-else-if=\"leftPanelMode == 'main'\" :app=\"getCurrentApplication()\" @edited=\"onEdited()\"></edit-main-settings>\n </div>\n </div>\n </div>\n <div class=\"dualbox-graph-right-section dark\">\n <div class=\"dualbox-graph-right-window\">\n <button class=\"btn btn-light btn-toggle-right-window\" @click=\"toggleRightWindow\" title=\"shrink window\" data-expanded=\"false\"><i class=\"fa fa-angle-double-left\"></i></button>\n <div class=\"dualbox-graph-right-panel light\">\n <debug-node-infos v-if=\"debugNodeId !== null\" :id=\"debugNodeId\"></debug-node-infos>\n </div>\n </div>\n </div>\n <div class=\"container-fluid dualbox-graph-main\" @click=\"setMainMenu\">\n <div class=\"row\">\n <div class=\"app-topbar dark\">\n <div class=\"justify-content-left\">\n <div class=\"dropdown\">\n <button class=\"btn btn-primary dropdown-toggle d-none\" type=\"button\" id=\"add-node-dropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" style=\"margin-right: 5px;\">\n Add\n </button>\n <div class=\"dropdown-menu\" aria-labelledby=\"add-node-dropdown\">\n <a class=\"dropdown-item add-box\" @click=\"addBox\" href=\"#\">Add box</a>\n <a class=\"dropdown-item add-metabox\" @click=\"addMetabox\" href=\"#\">Add metabox</a>\n <a class=\"dropdown-item add-input\" @click=\"addInput\" href=\"#\">Add input</a>\n <a class=\"dropdown-item add-output\" @click=\"addOutput\" href=\"#\">Add output</a>\n <a class=\"dropdown-item import-metabox\" @click=\"importMetabox\" href=\"#\">Import metabox</a>\n </div>\n <button class=\"btn btn-light btn-undo\" title=\"undo (ctrl-z)\" @click=\"undo\"><i class=\"fa fa-undo\"></i></button>\n <button class=\"btn btn-light btn-redo\" title=\"redo (ctrl-y)\" @click=\"redo\"><i class=\"fa fa-repeat fa-redo\"></i></button>\n <div class=\"form-check d-inline-block ml-2\">\n <label class=\"form-check-label\">\n <input class=\"form-check-input show-events\" type=\"checkbox\" value=\"false\" @click=\"showEvents\">\n <span class=\"noselect\">Show events</span>\n </label>\n </div>\n </div>\n </div>\n\n <div class=\"justify-content-center mx-auto\">\n <ol class=\"dualbox-app-navigation breadcrumb\"></ol>\n </div>\n\n <div class=\"justify-content-right\">\n <div class=\"dropdown selection-menu\" style=\"display: none;\">\n <button class=\"btn btn-primary dropdown-toggle\" type=\"button\" id=\"selection-dropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">\n Selection\n </button>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"add-node-dropdown\">\n <a class=\"dropdown-item dualbox-merge-selection\" @click=\"mergeSelection\" href=\"#\">Merge</a>\n <a class=\"dropdown-item dualbox-remove-selection\" @click=\"removeSelection\" href=\"#\" style=\"color: red;\">Delete</a>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row\" style=\"height: calc(100% - 58px);\">\n <graph-vue :app=\"app\" ref=\"graph\"></graph-vue>\n </div>\n </div>\n </div>\n <div class=\"tab-pane\" id=\"editor-interface-tab\" style=\"width 100%; height: 100%; background-color: white;\">\n <div class=\"db-editor-main\" style=\"width: 100%; height: 100%; overflow: hidden;\">\n <div class=\"code-panel\">\n <div class=\"button-bar form-inline code-controls\" style=\"position: relative;\">\n <button class=\"btn btn-primary btn-save-interface-element\" @click=\"saveInterfaceElement\">Save changes</button>\n </div>\n <div class=\"code-content\">\n <div class=\"code-html-container\">\n <div style=\"padding-top: 5px; padding-bottom: 5px; height: 50px; position: relative;\">\n <h3 style=\"position: absolute; top: 0; margin: 5px; font-size: 16px; z-index: 100; display: inline-block; margin-top: 5px;\">HTML</h3>\n <div class=\"d-inline-block ml-auto form-inline mr-2 mt-2\" style=\"position: absolute; top: 0; right: 0;\">\n <button class=\"btn btn-success btn-sm btn-add-interface\" @click=\"addInterface\"><i class=\"fas fa-plus\"></i></button>\n <select class=\"form-control btn-sm app-interface-select\" @change=\"selectInterface\" style=\"width: 150px; height: 32px;\">\n <option>Load UI...</option>\n <option v-for=\"interfaceName in getInterfacesNames()\" :value=\"interfaceName\">{{interfaceName}}</option>\n </select>\n <button class=\"btn btn-sm btn-light btn-edit-panel-description\" @click=\"editPanelDescription\"><i class=\"fas fa-info\" style=\"padding-left: 8px; padding-right: 8px;\"></i></button>\n <button class=\"btn btn-danger btn-sm btn-remove-interface\" @click=\"removeInterface\"><i class=\"fas fa-minus\"></i></button>\n </div>\n </div>\n <div class=\"code-html-text-container\" style=\"position: relative; height: calc(100% - 50px);\">\n <textarea class=\"code-html\"></textarea>\n </div>\n </div>\n <div class=\"code-css-container\">\n <div style=\"height: 30px;\">\n <h3 style=\"position: absolute; top: 0; margin: 5px; font-size: 16px; z-index: 100;\">CSS</h3>\n </div>\n <div class=\"colde-css-text-container\" style=\"position: relative; height: calc(100% - 30px);\">\n <textarea class=\"code-css\" v-model=\"appCss\"></textarea>\n </div>\n </div>\n </div>\n </div>\n <div class=\"dragbar\"></div>\n <div class=\"application-container\">\n <div class=\"button-bar form-inline run-options\" style=\"position: relative;\">\n <button class=\"btn btn-success btn-run mr-2\" @click=\"runApp\">Run</button>\n\n <select class=\"form-control run-loglevel mr-1 ml-2\">\n <option>error</option>\n <option>warn</option>\n <option>info</option>\n <option>log</option>\n <option>debug</option>\n </select>\n\n <input class=\"form-control run-noversioncheck mr-1 ml-3\" type=\"checkbox\" checked>No version checking</input>\n <input class=\"form-control run-removetrycatch mr-1 ml-3\" type=\"checkbox\">Remove Try/catch</input>\n <input class=\"form-control run-makesynchrone mr-1 ml-3\" type=\"checkbox\">Make Synchrone</input>\n\n <div class=\"ml-auto\">\n <input class=\"form-control run-profiler mr-1 ml-3\" type=\"checkbox\">Profiler</input>\n <input class=\"form-control run-record mr-1 ml-3\" type=\"checkbox\">Record</input>\n <button class=\"btn btn-secondary btn-snapshot\" @click=\"takeAndLoadSnapshot\">Snapshot</button>\n </div>\n </div>\n <div class=\"application capture-left-click capture-right-click\"></div>\n </div>\n </div>\n </div>\n </div>\n <add-node-vue :display=\"this.addingBox\" :mousePosition=\"this.newBoxPosition\" @closed=\"onAddBoxClosed\"></add-node-vue>\n </div>\n</template>\n\n<script>\nimport _ from 'lodash';\nimport swal from 'sweetalert2';\n\nimport graphVue from './graph.vue';\nimport addNodeVue from './addNode.vue';\nimport editMainSettingsVue from './editMainSettings.vue';\nimport editNodeSettingsVue from './editNodeSettings.vue';\nimport debugNodeInfosVue from './debugNodeInfos.vue';\n\n// CodeMirror\nimport CodeMirror from 'codemirror/lib/codemirror.js';\nimport 'codemirror/mode/xml/xml.js';\nimport 'codemirror/mode/css/css.js';\nimport 'codemirror/mode/javascript/javascript.js';\nimport 'codemirror/mode/htmlmixed/htmlmixed.js';\n\nimport htmltool from '@dualbox/dualbox-lib-htmltool';\n\nexport default {\n props: [\n 'app', // the app\n\n // Display configuration (online or offline ?)\n 'showLoadButton',\n 'showSaveButton',\n 'saveButtonFunction',\n\n // modes\n 'eventVisibility' // are events visible\n ],\n components: {\n 'graph-vue': graphVue,\n 'add-node-vue' : addNodeVue,\n 'edit-main-settings' : editMainSettingsVue,\n 'edit-node-settings' : editNodeSettingsVue,\n 'debug-node-infos' : debugNodeInfosVue,\n },\n data () {\n return {\n // modes\n addingBox : false,\n leftPanelMode : 'main', // 'main' to display main menu, 'node' for a node\n selectedNodeId : null, // id of the node to display in left menu\n debugNodeId: null, // on a snapshot, id of the node to display debug infos\n newBoxPosition: null, // track mouse position relative to the graph when adding a node\n\n // the specific app css\n appCss: \"\",\n }\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n // TODO: restore this when all menus are migrated to Vue.js\n\n this.cssCode = null;\n this.htmlCode = null;\n },\n updated: function() {\n //console.log('updating main view with: ' + JSON.stringify(this.app));\n this.appCss = (this.app && this.app.css) || \"\";\n\n // Update html and css code editor\n this.updateCode();\n },\n mounted: function() {\n //this.view.setMainMenu();\n\n $(this.$el).bind('expandSettings', function(e) {\n // expand\n $(this).find('.dualbox-graph-left-section').css('margin-left', '0');\n $(this).find('.dualbox-graph-main').addClass('left-panel-expanded');\n $(this).find('.btn-toggle-left-window').data('expanded', true).find('i')\n .removeClass('fa-angle-double-right')\n .addClass('fa-angle-double-left')\n .attr('title', 'shrink window');\n });\n\n $(this.$el).bind('shrinkSettings', function(e) {\n // shrink\n $(this).find('.dualbox-graph-left-section').css('margin-left', '-465px');\n $(this).find('.dualbox-graph-main').removeClass('left-panel-expanded');\n $(this).find('.btn-toggle-left-window').data('expanded', false).find('i')\n .removeClass('fa-angle-double-left')\n .addClass('fa-angle-double-right')\n .attr('title', 'expand window');\n });\n\n $(this.$el).bind('expandDebug', function(e) {\n // expand\n $(this).find('.dualbox-graph-right-section').css('margin-right', '0');\n $(this).find('.dualbox-graph-main').addClass('right-panel-expanded');\n $(this).find('.btn-toggle-right-window').data('expanded', true).find('i')\n .removeClass('fa-angle-double-left')\n .addClass('fa-angle-double-right')\n .attr('title', 'shrink window');\n });\n\n $(this.$el).bind('shrinkDebug', function(e) {\n // shrink\n $(this).find('.dualbox-graph-right-section').css('margin-right', '-465px');\n $(this).find('.dualbox-graph-main').removeClass('right-panel-expanded');\n $(this).find('.btn-toggle-right-window').data('expanded', false).find('i')\n .removeClass('fa-angle-double-right')\n .addClass('fa-angle-double-left')\n .attr('title', 'expand window');\n });\n\n // bind tabs\n var self = this;\n $(this.$el).find(\"a[data-toggle='tab']\").on(\"shown.bs.tab\", function(e) {\n var target = $(e.target).attr(\"href\") // activated tab\n if( target == \"#editor-graph-tab\" ) {\n self.view.killApp();\n }\n else if( target == \"#editor-interface-tab\" ) {\n self.htmlCode.refresh();\n self.cssCode.refresh();\n self.view.runApp( self.getOptions() );\n }\n });\n\n $(this.$el).find(\"a[data-toggle='tab']\").on('click', function (e) {\n e.preventDefault()\n $(this).tab('show')\n });\n\n // Update html and css code editor\n this.updateCode();\n\n // Resize horizontally\n $(this.$el).find('.dragbar').mousedown(function(e){\n e.preventDefault();\n $(document).mouseup(function(e){\n $(document).unbind('mousemove');\n });\n $(document).mousemove(function(e){\n $('.code-panel').css('width', e.pageX + \"px\");\n $('.application-container').css('width', ($(\".db-editor-main\").width() - e.pageX - 5) + \"px\");\n })\n });\n\n },\n methods: {\n \"getOptions\": function() {\n return {\n profiler : $(this.$el).find('.run-profiler').is(':checked'),\n logLevel : $(this.$el).find('.run-loglevel').val(),\n options : {\n noVersionCheck: $(this.$el).find('.run-noversioncheck').is(':checked'),\n debug: {\n removeTryCatch: $(this.$el).find('.run-removetrycatch').is(':checked'),\n makeSynchrone: $(this.$el).find('.run-makesynchrone').is(':checked'),\n record: $(this.$el).find('.run-record').is(':checked'),\n }\n }\n }\n },\n\n \"updateCode\": function() {\n // instanciate codemirror for html and css\n if( !this.htmlCode ) {\n this.htmlCode = CodeMirror.fromTextArea( $(this.$el).find(\".code-html\")[0], {\n lineNumbers: true,\n mode : \"htmlmixed\",\n lineWrapping: true\n });\n }\n if( !this.cssCode ) {\n this.cssCode = CodeMirror.fromTextArea( $(this.$el).find(\".code-css\")[0], {\n lineNumbers: true,\n mode : \"css\",\n lineWrapping: true\n });\n }\n this.cssCode.setValue(this.view.m.get().css || \"\");\n },\n\n \"loadApp\" : function() {\n var self = this;\n\n // create a fake input and click it to select a file\n var input = $('<input/>', { \"type\": \"file\", \"class\": \"upload\", \"accept\" : \".json\" });\n input.change( function(e) {\n // if we're not here, go to 1st tab\n $(\"a[data-toggle='tab'][href='#1']\").click();\n\n // parse the file JSON and load it\n var files = e.target.files; // FileList object\n var r = new FileReader();\n r.onload = function(e) {\n var contents = e.target.result;\n var json = JSON.parse(contents);\n self.view.e.setApp(json);\n };\n\n r.readAsText(files[0]);\n });\n input.click();\n },\n \"saveApp\": function() {\n // bind the app load\n if( this.saveButtonFunction ) {\n var saveButtonFunction = (e) => {\n var json = this.view.m.getCleanJson();\n return this.saveButtonFunction(json);\n }\n }\n else {\n var saveButtonFunction = (e) => {\n var app = this.view.m.getCleanJson();\n var text = JSON.stringify(app, null, 2);\n var blob = new Blob([text], { \"type\" : \"application/octet-stream\" });\n\n var a = document.createElement('a');\n a.href = window.URL.createObjectURL(blob);\n a.download = \"app.json\";\n\n // simulate a click on the link\n if (document.createEvent) {\n var event = document.createEvent(\"MouseEvents\");\n event.initEvent(\"click\", true, true);\n a.dispatchEvent(event);\n } else {\n a.click();\n }\n }\n }\n saveButtonFunction();\n },\n \"getCurrentMousePosition\": function(e) {\n return this.$refs.graph.getCurrentMousePosition(e);\n },\n \"addBox\" : function(e) {\n this.addingBox = true;\n this.newBoxPosition = this.getCurrentMousePosition(e);\n this.$forceUpdate();\n },\n \"onAddBoxClosed\" : function() {\n this.addingBox = false;\n this.$forceUpdate();\n },\n \"addMetabox\" : function(e) {\n var self = this;\n e.preventDefault();\n e.stopPropagation();\n\n swal({\n input: 'text',\n title: 'Choose a name for the metabox',\n }).then(function(result) {\n if( result.value ) {\n self.view.c.addNewMetabox(result.value);\n }\n });\n },\n \"addInput\" : function(e) {\n this.view.c.createInput();\n },\n \"addOutput\": function(e) {\n this.view.c.createOutput();\n },\n \"importMetabox\": async function(e) {\n var self = this;\n\n const { value: file } = await swal({\n title: 'Select your metabox file',\n input: 'file',\n inputAttributes: {\n 'accept': 'application/json',\n 'aria-label': 'Select your metabox file'\n }\n })\n\n if (file) {\n const reader = new FileReader()\n reader.onload = (e) => {\n var json = JSON.parse(e.target.result);\n\n self.view.e.loadPackages(json).then(async () => {\n const { value: name } = await swal({\n title: 'Choose a name for your metabox',\n input: 'text',\n showCancelButton: true,\n inputValidator: (value) => {\n return !value && 'You need to write something!'\n }\n });\n\n self.view.c.addNewMetabox(name, json);\n }).catch((err) => {\n console.error(err);\n });\n }\n reader.readAsText(file)\n }\n },\n\n getInterfacesNames : function() {\n return _.keys( _.get(this.view.m, [\"data\",\"root\", \"interface\"]) || {} );\n },\n\n \"selectInterface\": function(e) {\n // Load the interface HTML when selected\n var uiName = $(e.target).val();\n if( uiName !== \"\" && uiName !== \"Load UI...\" ) {\n var itf = this.view.m.data.root.interface;\n var htmlString = htmltool.json2html(itf[uiName]);\n var prettyString = htmltool.htmlPrettyPrint(htmlString);\n this.htmlCode.setValue(prettyString);\n }\n else {\n this.htmlCode.setValue(\"\");\n }\n },\n \"saveInterfaceElement\": function(e) {\n var currentInterface = $(this.$el).find('.app-interface-select').val();\n if( currentInterface !== \"\" ) {\n var currentHTML = this.htmlCode.getValue();\n\n // save html code into app\n this.view.m.data.root.interface[currentInterface] = htmltool.html2json(currentHTML);\n }\n\n // save css code into app\n this.view.m.data.root.css = this.cssCode.getValue();\n },\n \"addInterface\": function(e) {\n var self = this;\n\n swal.mixin({\n confirmButtonText: 'Next →',\n showCancelButton: true,\n progressSteps: ['1', '2', '3']\n }).queue([\n {\n input: 'text',\n title: 'Choose a name',\n text: 'Enter a name for the new interface'\n },\n {\n input: 'select',\n title: 'Choose the type',\n text : 'Is it a viewer panel or a control panel?',\n inputOptions: {\n 'control': 'A control panel',\n 'viewer': 'A viewer',\n },\n },\n {\n input: 'select',\n title: 'Choose the position',\n text : 'Where do you want to position your panel?',\n inputOptions: {\n 'top-left': 'At the top-left',\n 'top-center': 'At the top-center',\n 'top-right': 'At the top-right',\n 'center-left': 'At the center-left',\n 'center': 'At the center',\n 'center-right': 'At the center-right',\n 'bottom-left': 'At the bottom-left',\n 'bottom-center': 'At the bottom-center',\n 'bottom-right': 'At the bottom-right',\n 'whole-screen': 'I want my panel in full-screen',\n },\n }\n ]).then((result) => {\n if (result.value) {\n var name = result.value[0];\n var type = result.value[1];\n var position = result.value[2];\n\n if (name === \"\") {\n swal.showInputError(\"the name is empty!\");\n return false\n }\n\n var appInterface = self.view.m.data.root.interface;\n if( appInterface[name] ) {\n swal.showInputError(\"Interface \" + name + \" already exists!\");\n return false\n }\n else {\n var style={};\n switch(position) {\n case 'top-left': style={ 'position': 'absolute', 'top': 0, 'left': 0, 'margin': '15px' }; break;\n case 'top-center': style={ 'position': 'absolute', 'top': 0, 'margin': '15px auto' }; break;\n case 'top-right': style={ 'position': 'absolute', 'top': 0, 'right': 0, 'margin': '15px' }; break;\n case 'center-left': style={ 'position': 'absolute', 'top': 0, 'bottom': 0, 'left': 0, 'margin': 'auto 15px' }; break;\n case 'center': style={ 'position': 'absolute', 'top': 0, 'bottom': 0, 'left': 0, 'right': 0, 'margin': 'auto' }; break;\n case 'center-right': style={ 'position': 'absolute', 'top': 0, 'bottom': 0, 'right': 0, 'margin': 'auto 15px' }; break;\n case 'bottom-left': style={ 'position': 'absolute', 'bottom': 0, 'left': 0, 'margin': '15px' }; break;\n case 'bottom-center': style={ 'position': 'absolute', 'bottom': 0, 'left': 0, 'right': 0, 'margin': '15px auto' }; break;\n case 'bottom-right': style={ 'position': 'absolute', 'bottom': 0, 'right': 0, 'margin': '15px' }; break;\n case 'whole-screen': style={ 'position': 'absolute', 'top': 0, 'left': 0 }; break;\n }\n\n // some prefilled data\n style['width'] = \"300px\";\n style['padding'] = \"15px\";\n style['border'] = \"1px solid #ccc\";\n style['border-radius'] = \"4px\";\n style['background'] = \"white\";\n if( position.startsWith(\"center\") ) {\n style['height'] = \"60px\"; // must define height\n }\n else {\n style['height'] = \"auto\";\n }\n\n // add a basic control\n appInterface[name] = {\n type: \"Element\",\n tagName: \"div\",\n attributes: {\n className: [\n \"dualbox\",\n \"dualbox-container\",\n \"dualbox-container-\" + name,\n type==\"viewer\" ? \"dualbox-viewer\" : \"dualbox-controls\"\n ],\n style: style,\n },\n children: []\n }\n\n // add the value to our select, and load it\n $(self.$el).find(\".app-interface-select\").append(\n $(\"<option/>\", { \"value\" : name }).append(name)\n );\n $(document).ready(() => {\n $(self.$el).find('.app-interface-select').val(name).change();\n\n // set it into the editor\n var htmlString = htmltool.json2html(appInterface[name]);\n var prettyString = htmltool.htmlPrettyPrint(htmlString);\n this.htmlCode.setValue(prettyString);\n self.updateCode();\n });\n\n self.view.runApp( self.getOptions() );\n }\n }\n })\n },\n \"removeInterface\": function(e) {\n var self = this;\n var name = $('.app-interface-select').val();\n\n swal({\n title: \"Confirm deleting \" + name + \" ?\",\n type: \"warning\",\n showCancelButton: true,\n confirmButtonColor: \"#DD6B55\",\n confirmButtonText: \"Yes, delete it!\",\n closeOnConfirm: true,\n closeOnCancel: true\n }).then((result) => {\n if( result.value ) {\n // set the interface back to first value\n $(this.$el).find(\".app-interface-select option[value='\" + name + \"']\").remove();\n $(this.$el).find(\".app-interface-select\").change();\n delete self.view.m.data.root.interface[name];\n self.htmlCode.setValue(\"\");\n self.view.runApp( self.getOptions() );\n }\n });\n },\n \"editPanelDescription\": function(e) {\n var self = this;\n var name = $('.app-interface-select').val();\n\n swal({\n title: \"Enter a description for this panel!\",\n input: \"textarea\",\n inputValue: this.view.m.data.root.interface[name].description || \"\",\n showCancelButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true,\n animation: \"slide-from-top\",\n inputPlaceholder: \"Write something\"\n }).then( (result) => {\n if (result.value === \"\") {\n swal.showInputError(\"You need to write something!\");\n return false\n }\n else {\n self.view.m.data.root.interface[name].description = result.value;\n }\n });\n },\n \"toggleLeftWindow\": function(e) {\n var expanded = $(e.target).closest('button').data('expanded');\n if( expanded ) {\n $(this.$el).trigger('shrinkSettings');\n }\n else {\n $(this.$el).trigger('expandSettings');\n }\n },\n \"toggleRightWindow\": function(e) {\n var expanded = $(e.target).closest('button').data('expanded');\n if( expanded ) {\n $(this.$el).trigger('shrinkDebug');\n }\n else {\n $(this.$el).trigger('expandDebug');\n }\n },\n\n \"showEvents\": function(e) {\n this.view.setEventsVisibility( $(e.target).is(':checked') );\n },\n\n \"runApp\": function(e) {\n this.view.runApp( this.getOptions() );\n },\n\n \"takeAndLoadSnapshot\": function(e) {\n this.view.takeAndLoadSnapshot();\n },\n\n \"undo\": function(e) {\n this.view.c.undo();\n },\n\n \"redo\" : function(e) {\n this.view.c.redo();\n },\n\n \"removeSelection\": function(e) {\n this.view.c.deleteSelection();\n },\n\n \"mergeSelection\": function(e) {\n this.view.c.mergeSelection();\n },\n\n \"setMainMenu\": function(e) {\n this.view.setMainMenu();\n },\n\n \"getCurrentApplication\" : function(e) {\n // trick to make this function reactive to \"app\" field update\n if( this.app ) {\n return this.view.m.getCurrentApp(true);\n }\n else {\n throw \"Error: no app found\";\n }\n },\n\n \"onEdited\": function(e) {\n console.log('Something was edited, forcing new render');\n this.$forceUpdate();\n },\n\n \"ready\" : function() {\n return new Promise(resolve => {\n this.$nextTick(() => {\n window.requestAnimationFrame(() => {\n $(this.$el).ready(resolve);\n })\n })\n })\n }\n }\n}\n</script>\n"]}, media: undefined });
|
|
87079
|
+
inject("data-v-dc4fde12_0", { source: "\n.code-panel {\n width: 30%;\n height: 100%;\n vertical-align: top;\n float: left;\n}\n.application-container {\n width: calc(70% - 5px);\n height: 100%;\n display: inline-block;\n vertical-align: top;\n float: right;\n}\n.code-controls, .run-options {\n width: 100%;\n height: 60px;\n}\n.application {\n width: 100%;\n height: calc(100% - 60px);\n background-color: #ccc;\n}\n.dragbar {\n height: 100%;\n width: 5px;\n background-color: #e7e7e7;\n display: inline-block;\n cursor: col-resize;\n}\n.code-content {\n position: relative;\n height: calc(100% - 56px);\n}\n.code-html-container {\n position: relative;\n height: 50%;\n border-bottom: 1px solid #e7e7e7;\n}\n.code-css-container {\n position: relative;\n height: calc(50% - 1px);\n overflow: hidden;\n}\n.code-css {\n width: 100%;\n height: 100%;\n}\n.code-html {\n height: calc(100% - 40px);\n width: 100%;\n}\n.CodeMirror {\n height: 100%!important;\n}\n.code-badge {\n position: absolute;\n top: 10px;\n right: 10px;\n padding: 10px;\n}\n.btn-light.focus, .btn-light:focus {\n box-shadow: none!important;\n}\n.button-bar {\n width: 60px;\n padding: 10px;\n border-bottom: 1px solid #e7e7e7;\n width: 100%;\n background-color: white;\n}\n.noselect {\n -webkit-user-select: none; /* Chrome/Safari */\n -moz-user-select: none; /* Firefox */\n -ms-user-select: none; /* IE10+ */\n -o-user-select: none;\n user-select: none;\n}\n.btn + .btn {\n margin-left: 5px;\n}\n.btn-graph-goto {\n box-shadow: none!important;\n}\n.nav-tabs {\n border-bottom: none;\n}\n.main-navigation a.nav-link {\n color: white;\n}\n.main-navigation a.nav-link.active {\n color: #212529;\n}\n.dualbox-editor-body {\n width: 100%;\n height: 100%;\n overflow: hidden;\n background-color: rgb(85, 85, 85);\n}\n.dualbox-graph-left-section {\n height: 100%;\n width: 500px;\n float: left;\n position: relative;\n overflow: hidden;\n margin-left: -465px;\n transition: margin-left 0.3s ease;\n}\n.dualbox-graph-left-window {\n width: calc(100% - 35px);\n height: calc(100% - 10px);\n margin-top: 10px;\n /* background-color: #ECF2F8; */\n background-color: #f8f9fa;\n /* border: 1px solid grey; */\n border-radius: 5px;\n position: relative;\n float: left;\n}\n.dualbox-graph-left-panel {\n width: 100%;\n height: 100%;\n}\n.btn-toggle-left-window {\n position: absolute;\n right: 0;\n top: 0;\n margin-right: -35px;\n z-index: 100;\n border-top-left-radius: 0px;\n border-bottom-left-radius: 0px;\n}\n.btn-toggle-left-window:hover, .btn-toggle-right-window:hover, .btn-toggle-left-window:focus, .btn-toggle-right-window:focus, .btn-toggle-left-window:active, .btn-toggle-right-window:active, .btn-toggle-left-window:active:hover, .btn-toggle-right-window:active:hover {\n color: #212529!important;\n background-color: #f8f9fa!important;\n border-color: #f8f9fa!important;\n}\n.dualbox-graph-right-section {\n height: 100%;\n width: 500px;\n float: right;\n position: relative;\n overflow: hidden;\n margin-right: -465px;\n transition: margin-right 0.3s ease;\n}\n.dualbox-graph-right-window {\n width: calc(100% - 35px);\n height: calc(100% - 20px);\n margin-top: 10px;\n margin-bottom: 30px;\n /* background-color: #ECF2F8; */\n background-color: #f8f9fa;\n /* border: 1px solid grey; */\n border-radius: 5px;\n position: relative;\n float: right;\n}\n.dualbox-graph-right-panel {\n width: 100%;\n height: 100%;\n}\n.btn-toggle-right-window {\n position: absolute;\n left: 0;\n top: 0;\n margin-left: -35px;\n z-index: 100;\n border-top-right-radius: 0px;\n border-bottom-right-radius: 0px;\n}\n.dualbox-graph-tab {\n height: 100%;\n width: 100%;\n background-color: #555!important;\n}\n.dualbox-graph-main {\n height: 100%;\n width: calc(100% - 70px);\n float: right;\n background-color: #555!important;\n transition: width 0.3s ease;\n}\n.dualbox-graph-main.left-panel-expanded {\n width: calc(100% - 535px);\n margin-left: -465px;\n}\n.dualbox-graph-main.right-panel-expanded {\n width: calc(100% - 535px);\n}\n.dualbox-graph-main.left-panel-expanded.right-panel-expanded {\n width: calc(100% - 1000px);\n margin-left: -465px;\n}\n.opacity0 {\n opacity: 0;\n}\n.btn-editor-xs {\n width: 18px;\n padding : 3px!important;\n line-height : .5;\n border-radius : 2px;\n}\n.btn-editor-xs > i {\n font-size : 10px;\n}\n.btn-outline-discrete {\n border-color: rgba(0,0,0,0.05);\n border-color: transparent;\n color: rgba(0,0,0,0.3);\n}\n.dualbox-app-navigation {\n background-color: transparent;\n margin-bottom: 0;\n vertical-align: middle;\n padding-top: 7px;\n padding-bottom: 7px;\n font-weight: bold;\n user-select: none;\n}\n.app-topbar {\n border-bottom: none;\n padding-left: 15px;\n padding-right: 15px;\n display: flex;\n width: 100%;\n height: 58px;\n padding-top: 10px;\n padding-bottom: 10px;\n}\n.dark, .graph-tab.active, .nav-item.active .graph-tab {\n color: white!important;\n background-color: #555!important;\n}\n.light {\n color: #4d4d4d!important;\n background-color: #f8f9fa!important;\n}\n.main-navigation .nav-link, .main-navigation .nav-link.active, .nav-item.active .nav-link {\n border-bottom: none;\n border-left: none;\n border-top: none;\n border-right: none;\n position: relative;\n top: 1px;\n}\n.btn:focus, button:focus {\n outline: none;\n box-shadow: none;\n}\n.btn-transparent, .btn-transparent:hover, .btn-transparent:focus {\n background-color: transparent;\n}\n.connection-control {\n position: absolute;\n height: 14px;\n width: 14px;\n background-color: transparent;\n z-index: 19;\n cursor: move;\n}\n.connection-control.selected {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n}\n.connection-label {\n z-index: 22!important;\n color: #004d00!important;\n background-color: white!important;\n padding: 4px 4px;\n border: 2px solid #004d00;\n font-size: 16px!important;\n border-radius: 5px;\n}\n.input-color-tag {\n background-color: #F2D600;\n}\n.output-color-tag {\n background-color: #FFAB4A;\n}\n.ui-color-tag {\n background-color: #61BD4F;\n}\n.metanode-color-tag {\n background-color: #DDDDDD;\n}\n.input {\n}\n.output {\n}\n.fileUpload {\n position: relative;\n overflow: hidden;\n margin: 10px;\n}\n.fileUpload input.upload {\n position: absolute;\n top: 0;\n right: 0;\n margin: 0;\n padding: 0;\n font-size: 20px;\n cursor: pointer;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.module-edit-modal-body .btn+.btn {\n margin-bottom: 0;\n margin-left: 5px;\n}\n.btn-add-node {\n width:46%;\n margin:1%;\n}\nbutton.close {\n position: absolute;\n right: 0;\n margin-right: 5px!important;\n}\n.CodeMirror {\n height: auto;\n min-height: 300px;\n}\n.load-app, .save-app {\n margin-left: 5px;\n margin-right: 5px;\n}\n.btn-xs {\n padding: 0px 4px;\n font-size: 12px;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/main.vue"],"names":[],"mappings":";AACA;IACA,UAAA;IACA,YAAA;IACA,mBAAA;IACA,WAAA;AACA;AAEA;IACA,sBAAA;IACA,YAAA;IACA,qBAAA;IACA,mBAAA;IACA,YAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,WAAA;IACA,yBAAA;IACA,sBAAA;AACA;AAEA;IACA,YAAA;IACA,UAAA;IACA,yBAAA;IACA,qBAAA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;IACA,yBAAA;AACA;AAEA;IACA,kBAAA;IACA,WAAA;IACA,gCAAA;AACA;AAEA;IACA,kBAAA;IACA,uBAAA;IACA,gBAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,yBAAA;IACA,WAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,kBAAA;IACA,SAAA;IACA,WAAA;IACA,aAAA;AACA;AAEA;IACA,0BAAA;AACA;AAEA;IACA,WAAA;IACA,aAAA;IACA,gCAAA;IACA,WAAA;IACA,uBAAA;AACA;AAEA;IACA,yBAAA,EAAA,kBAAA;IACA,sBAAA,EAAA,YAAA;IACA,qBAAA,EAAA,UAAA;IACA,oBAAA;IACA,iBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,0BAAA;AACA;AAEA;IACA,mBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;IACA,gBAAA;IACA,iCAAA;AACA;AAEA;IACA,YAAA;IACA,YAAA;IACA,WAAA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;IACA,iCAAA;AACA;AAEA;IACA,wBAAA;IACA,yBAAA;IACA,gBAAA;IACA,+BAAA;IACA,yBAAA;IACA,4BAAA;IACA,kBAAA;IACA,kBAAA;IACA,WAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,MAAA;IACA,mBAAA;IACA,YAAA;IACA,2BAAA;IACA,8BAAA;AACA;AAEA;IACA,wBAAA;IACA,mCAAA;IACA,+BAAA;AACA;AAEA;IACA,YAAA;IACA,YAAA;IACA,YAAA;IACA,kBAAA;IACA,gBAAA;IACA,oBAAA;IACA,kCAAA;AACA;AAEA;IACA,wBAAA;IACA,yBAAA;IACA,gBAAA;IACA,mBAAA;IACA,+BAAA;IACA,yBAAA;IACA,4BAAA;IACA,kBAAA;IACA,kBAAA;IACA,YAAA;AACA;AAEA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,OAAA;IACA,MAAA;IACA,kBAAA;IACA,YAAA;IACA,4BAAA;IACA,+BAAA;AACA;AAEA;IACA,YAAA;IACA,WAAA;IACA,gCAAA;AACA;AAEA;IACA,YAAA;IACA,wBAAA;IACA,YAAA;IACA,gCAAA;IACA,2BAAA;AACA;AAEA;IACA,yBAAA;IACA,mBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,0BAAA;IACA,mBAAA;AACA;AAEA;IACA,UAAA;AACA;AAEA;IACA,WAAA;IACA,wBAAA;IACA,iBAAA;IACA,mBAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,8BAAA;IACA,yBAAA;IACA,sBAAA;AACA;AAEA;IACA,6BAAA;IACA,gBAAA;IACA,sBAAA;IACA,gBAAA;IACA,mBAAA;IACA,iBAAA;IACA,iBAAA;AACA;AAEA;IACA,mBAAA;IACA,kBAAA;IACA,mBAAA;IACA,aAAA;IACA,WAAA;IACA,YAAA;IACA,iBAAA;IACA,oBAAA;AACA;AAEA;IACA,sBAAA;IACA,gCAAA;AACA;AAEA;IACA,wBAAA;IACA,mCAAA;AACA;AAEA;IACA,mBAAA;IACA,iBAAA;IACA,gBAAA;IACA,kBAAA;IACA,kBAAA;IACA,QAAA;AACA;AAEA;IACA,aAAA;IACA,gBAAA;AACA;AAEA;IACA,6BAAA;AACA;AAEA;IACA,kBAAA;IACA,YAAA;IACA,WAAA;IACA,6BAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,qBAAA;IACA,wBAAA;IACA,iCAAA;IACA,gBAAA;IACA,yBAAA;IACA,yBAAA;IACA,kBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;AACA;AAEA;AACA;AAGA;IACA,kBAAA;IACA,gBAAA;IACA,YAAA;AACA;AACA;IACA,kBAAA;IACA,MAAA;IACA,QAAA;IACA,SAAA;IACA,UAAA;IACA,eAAA;IACA,eAAA;IACA,UAAA;IACA,wBAAA;AACA;AAGA;IACA,gBAAA;IACA,gBAAA;AACA;AAEA;IACA,SAAA;IACA,SAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,2BAAA;AACA;AAEA;IACA,YAAA;IACA,iBAAA;AACA;AAEA;IACA,gBAAA;IACA,iBAAA;AACA;AAEA;IACA,gBAAA;IACA,eAAA;AACA","file":"main.vue","sourcesContent":["<style>\n .code-panel {\n width: 30%;\n height: 100%;\n vertical-align: top;\n float: left;\n }\n\n .application-container {\n width: calc(70% - 5px);\n height: 100%;\n display: inline-block;\n vertical-align: top;\n float: right;\n }\n\n .code-controls, .run-options {\n width: 100%;\n height: 60px;\n }\n\n .application {\n width: 100%;\n height: calc(100% - 60px);\n background-color: #ccc;\n }\n\n .dragbar {\n height: 100%;\n width: 5px;\n background-color: #e7e7e7;\n display: inline-block;\n cursor: col-resize;\n }\n\n .code-content {\n position: relative;\n height: calc(100% - 56px);\n }\n\n .code-html-container {\n position: relative;\n height: 50%;\n border-bottom: 1px solid #e7e7e7;\n }\n\n .code-css-container {\n position: relative;\n height: calc(50% - 1px);\n overflow: hidden;\n }\n\n .code-css {\n width: 100%;\n height: 100%;\n }\n\n .code-html {\n height: calc(100% - 40px);\n width: 100%;\n }\n\n .CodeMirror {\n height: 100%!important;\n }\n\n .code-badge {\n position: absolute;\n top: 10px;\n right: 10px;\n padding: 10px;\n }\n\n .btn-light.focus, .btn-light:focus {\n box-shadow: none!important;\n }\n\n .button-bar {\n width: 60px;\n padding: 10px;\n border-bottom: 1px solid #e7e7e7;\n width: 100%;\n background-color: white;\n }\n\n .noselect {\n -webkit-user-select: none; /* Chrome/Safari */\n -moz-user-select: none; /* Firefox */\n -ms-user-select: none; /* IE10+ */\n -o-user-select: none;\n user-select: none;\n }\n\n .btn + .btn {\n margin-left: 5px;\n }\n\n .btn-graph-goto {\n box-shadow: none!important;\n }\n\n .nav-tabs {\n border-bottom: none;\n }\n\n .main-navigation a.nav-link {\n color: white;\n }\n\n .main-navigation a.nav-link.active {\n color: #212529;\n }\n\n .dualbox-editor-body {\n width: 100%;\n height: 100%;\n overflow: hidden;\n background-color: rgb(85, 85, 85);\n }\n\n .dualbox-graph-left-section {\n height: 100%;\n width: 500px;\n float: left;\n position: relative;\n overflow: hidden;\n margin-left: -465px;\n transition: margin-left 0.3s ease;\n }\n\n .dualbox-graph-left-window {\n width: calc(100% - 35px);\n height: calc(100% - 10px);\n margin-top: 10px;\n /* background-color: #ECF2F8; */\n background-color: #f8f9fa;\n /* border: 1px solid grey; */\n border-radius: 5px;\n position: relative;\n float: left;\n }\n\n .dualbox-graph-left-panel {\n width: 100%;\n height: 100%;\n }\n\n .btn-toggle-left-window {\n position: absolute;\n right: 0;\n top: 0;\n margin-right: -35px;\n z-index: 100;\n border-top-left-radius: 0px;\n border-bottom-left-radius: 0px;\n }\n\n .btn-toggle-left-window:hover, .btn-toggle-right-window:hover, .btn-toggle-left-window:focus, .btn-toggle-right-window:focus, .btn-toggle-left-window:active, .btn-toggle-right-window:active, .btn-toggle-left-window:active:hover, .btn-toggle-right-window:active:hover {\n color: #212529!important;\n background-color: #f8f9fa!important;\n border-color: #f8f9fa!important;\n }\n\n .dualbox-graph-right-section {\n height: 100%;\n width: 500px;\n float: right;\n position: relative;\n overflow: hidden;\n margin-right: -465px;\n transition: margin-right 0.3s ease;\n }\n\n .dualbox-graph-right-window {\n width: calc(100% - 35px);\n height: calc(100% - 20px);\n margin-top: 10px;\n margin-bottom: 30px;\n /* background-color: #ECF2F8; */\n background-color: #f8f9fa;\n /* border: 1px solid grey; */\n border-radius: 5px;\n position: relative;\n float: right;\n }\n\n .dualbox-graph-right-panel {\n width: 100%;\n height: 100%;\n }\n\n .btn-toggle-right-window {\n position: absolute;\n left: 0;\n top: 0;\n margin-left: -35px;\n z-index: 100;\n border-top-right-radius: 0px;\n border-bottom-right-radius: 0px;\n }\n\n .dualbox-graph-tab {\n height: 100%;\n width: 100%;\n background-color: #555!important;\n }\n\n .dualbox-graph-main {\n height: 100%;\n width: calc(100% - 70px);\n float: right;\n background-color: #555!important;\n transition: width 0.3s ease;\n }\n\n .dualbox-graph-main.left-panel-expanded {\n width: calc(100% - 535px);\n margin-left: -465px;\n }\n\n .dualbox-graph-main.right-panel-expanded {\n width: calc(100% - 535px);\n }\n\n .dualbox-graph-main.left-panel-expanded.right-panel-expanded {\n width: calc(100% - 1000px);\n margin-left: -465px;\n }\n\n .opacity0 {\n opacity: 0;\n }\n\n .btn-editor-xs {\n width: 18px;\n padding : 3px!important;\n line-height : .5;\n border-radius : 2px;\n }\n\n .btn-editor-xs > i {\n font-size : 10px;\n }\n\n .btn-outline-discrete {\n border-color: rgba(0,0,0,0.05);\n border-color: transparent;\n color: rgba(0,0,0,0.3);\n }\n\n .dualbox-app-navigation {\n background-color: transparent;\n margin-bottom: 0;\n vertical-align: middle;\n padding-top: 7px;\n padding-bottom: 7px;\n font-weight: bold;\n user-select: none;\n }\n\n .app-topbar {\n border-bottom: none;\n padding-left: 15px;\n padding-right: 15px;\n display: flex;\n width: 100%;\n height: 58px;\n padding-top: 10px;\n padding-bottom: 10px;\n }\n\n .dark, .graph-tab.active, .nav-item.active .graph-tab {\n color: white!important;\n background-color: #555!important;\n }\n\n .light {\n color: #4d4d4d!important;\n background-color: #f8f9fa!important;\n }\n\n .main-navigation .nav-link, .main-navigation .nav-link.active, .nav-item.active .nav-link {\n border-bottom: none;\n border-left: none;\n border-top: none;\n border-right: none;\n position: relative;\n top: 1px;\n }\n\n .btn:focus, button:focus {\n outline: none;\n box-shadow: none;\n }\n\n .btn-transparent, .btn-transparent:hover, .btn-transparent:focus {\n background-color: transparent;\n }\n\n .connection-control {\n position: absolute;\n height: 14px;\n width: 14px;\n background-color: transparent;\n z-index: 19;\n cursor: move;\n }\n\n .connection-control.selected {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n }\n\n .connection-label {\n z-index: 22!important;\n color: #004d00!important;\n background-color: white!important;\n padding: 4px 4px;\n border: 2px solid #004d00;\n font-size: 16px!important;\n border-radius: 5px;\n }\n\n .input-color-tag {\n background-color: #F2D600;\n }\n\n .output-color-tag {\n background-color: #FFAB4A;\n }\n\n .ui-color-tag {\n background-color: #61BD4F;\n }\n\n .metanode-color-tag {\n background-color: #DDDDDD;\n }\n\n .input {\n }\n\n .output {\n }\n\n\n .fileUpload {\n position: relative;\n overflow: hidden;\n margin: 10px;\n }\n .fileUpload input.upload {\n position: absolute;\n top: 0;\n right: 0;\n margin: 0;\n padding: 0;\n font-size: 20px;\n cursor: pointer;\n opacity: 0;\n filter: alpha(opacity=0);\n }\n\n\n .module-edit-modal-body .btn+.btn {\n margin-bottom: 0;\n margin-left: 5px;\n }\n\n .btn-add-node {\n width:46%;\n margin:1%;\n }\n\n button.close {\n position: absolute;\n right: 0;\n margin-right: 5px!important;\n }\n\n .CodeMirror {\n height: auto;\n min-height: 300px;\n }\n\n .load-app, .save-app {\n margin-left: 5px;\n margin-right: 5px;\n }\n\n .btn-xs {\n padding: 0px 4px;\n font-size: 12px;\n }\n</style>\n\n<template>\n <div class=\"dualbox-editor-body\">\n <nav class=\"main-navigation navbar navbar-default\" style=\"position: relative; margin-bottom: 0px; padding: 0; padding-top: 5px; background-color: #2e6da4;\">\n <ul class=\"nav nav-tabs\">\n <li class=\"nav-item active\">\n <a class=\"nav-link graph-tab\" href=\"#editor-graph-tab\" data-toggle=\"tab\">Application Graph</a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link interface-tab\" href=\"#editor-interface-tab\" data-toggle=\"tab\">Interface Editor</a>\n </li>\n </ul>\n\n <div class=\"nav navbar-right\" style=\"vertical-align: top; margin-top: 5px; margin-right: 10px; margin-bottom: 5px;\">\n <div v-if=\"showLoadButton === true\">\n <button class=\"load-app btn btn-sm btn-light\" style=\"position: relative; bottom: 3px;\" @click=\"loadApp\">Load App</button>\n </div>\n <div v-if=\"showSaveButton\">\n <button class=\"save-app btn btn-sm btn-light\" style=\"position: relative; bottom: 3px;\" @click=\"saveApp\">Save App</button>\n </div>\n </div>\n </nav>\n <div class=\"tab-content dualbox-graph-tab\" style=\"width: 100%; height: calc(100% - 46px);\">\n <div class=\"tab-pane active\" id=\"editor-graph-tab\" style=\"width: 100%; height: 100%;\">\n <div class=\"dualbox-graph-left-section dark\">\n <div class=\"dualbox-graph-left-window\">\n <button class=\"btn btn-light btn-toggle-left-window\" @click=\"toggleLeftWindow\" title=\"shrink window\" data-expanded=\"false\"><i class=\"fa fa-angle-double-right\"></i></button>\n <div class=\"dualbox-graph-left-panel light\">\n <edit-node-settings v-if=\"leftPanelMode == 'node' && selectedNodeId !== null\" :id=\"selectedNodeId\" :key=\"selectedNodeId\"></edit-node-settings>\n <edit-main-settings v-else-if=\"leftPanelMode == 'main'\" :app=\"getCurrentApplication()\" @edited=\"onEdited()\"></edit-main-settings>\n </div>\n </div>\n </div>\n <div class=\"dualbox-graph-right-section dark\">\n <div class=\"dualbox-graph-right-window\">\n <button class=\"btn btn-light btn-toggle-right-window\" @click=\"toggleRightWindow\" title=\"shrink window\" data-expanded=\"false\"><i class=\"fa fa-angle-double-left\"></i></button>\n <div class=\"dualbox-graph-right-panel light\">\n <debug-node-infos v-if=\"debugNodeId !== null\" :id=\"debugNodeId\"></debug-node-infos>\n </div>\n </div>\n </div>\n <div class=\"container-fluid dualbox-graph-main\" @click=\"setMainMenu\">\n <div class=\"row\">\n <div class=\"app-topbar dark\">\n <div class=\"justify-content-left\">\n <div class=\"dropdown\">\n <button class=\"btn btn-primary dropdown-toggle d-none\" type=\"button\" id=\"add-node-dropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\" style=\"margin-right: 5px;\">\n Add\n </button>\n <div class=\"dropdown-menu\" aria-labelledby=\"add-node-dropdown\">\n <a class=\"dropdown-item add-box\" @click=\"addBox\" href=\"#\">Add box</a>\n <a class=\"dropdown-item add-metabox\" @click=\"addMetabox\" href=\"#\">Add metabox</a>\n <a class=\"dropdown-item add-input\" @click=\"addInput\" href=\"#\">Add input</a>\n <a class=\"dropdown-item add-output\" @click=\"addOutput\" href=\"#\">Add output</a>\n <a class=\"dropdown-item import-metabox\" @click=\"importMetabox\" href=\"#\">Import metabox</a>\n </div>\n <button class=\"btn btn-light btn-undo\" title=\"undo (ctrl-z)\" @click=\"undo\"><i class=\"fa fa-undo\"></i></button>\n <button class=\"btn btn-light btn-redo\" title=\"redo (ctrl-y)\" @click=\"redo\"><i class=\"fa fa-repeat fa-redo\"></i></button>\n <div class=\"form-check d-inline-block ml-2\">\n <label class=\"form-check-label\">\n <input class=\"form-check-input show-events\" type=\"checkbox\" value=\"false\" @click=\"showEvents\">\n <span class=\"noselect\">Show events</span>\n </label>\n </div>\n </div>\n </div>\n\n <div class=\"justify-content-center mx-auto\">\n <ol class=\"dualbox-app-navigation breadcrumb\"></ol>\n </div>\n\n <div class=\"justify-content-right\">\n <div class=\"dropdown selection-menu\" style=\"display: none;\">\n <button class=\"btn btn-primary dropdown-toggle\" type=\"button\" id=\"selection-dropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">\n Selection\n </button>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"add-node-dropdown\">\n <a class=\"dropdown-item dualbox-merge-selection\" @click=\"mergeSelection\" href=\"#\">Merge</a>\n <a class=\"dropdown-item dualbox-remove-selection\" @click=\"removeSelection\" href=\"#\" style=\"color: red;\">Delete</a>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row\" style=\"height: calc(100% - 58px);\">\n <graph-vue :app=\"app\" ref=\"graph\"></graph-vue>\n </div>\n </div>\n </div>\n <div class=\"tab-pane\" id=\"editor-interface-tab\" style=\"width 100%; height: 100%; background-color: white;\">\n <div class=\"db-editor-main\" style=\"width: 100%; height: 100%; overflow: hidden;\">\n <div class=\"code-panel\">\n <div class=\"button-bar form-inline code-controls\" style=\"position: relative;\">\n <button class=\"btn btn-primary btn-save-interface-element\" @click=\"saveInterfaceElement\">Save changes</button>\n </div>\n <div class=\"code-content\">\n <div class=\"code-html-container\">\n <div style=\"padding-top: 5px; padding-bottom: 5px; height: 50px; position: relative;\">\n <h3 style=\"position: absolute; top: 0; margin: 5px; font-size: 16px; z-index: 100; display: inline-block; margin-top: 5px;\">HTML</h3>\n <div class=\"d-inline-block ml-auto form-inline mr-2 mt-2\" style=\"position: absolute; top: 0; right: 0;\">\n <button class=\"btn btn-success btn-sm btn-add-interface\" @click=\"addInterface\"><i class=\"fas fa-plus\"></i></button>\n <select class=\"form-control btn-sm app-interface-select\" @change=\"selectInterface\" style=\"width: 150px; height: 32px;\">\n <option>Load UI...</option>\n <option v-for=\"interfaceName in getInterfacesNames()\" :value=\"interfaceName\">{{interfaceName}}</option>\n </select>\n <button class=\"btn btn-sm btn-light btn-edit-panel-description\" @click=\"editPanelDescription\"><i class=\"fas fa-info\" style=\"padding-left: 8px; padding-right: 8px;\"></i></button>\n <button class=\"btn btn-danger btn-sm btn-remove-interface\" @click=\"removeInterface\"><i class=\"fas fa-minus\"></i></button>\n </div>\n </div>\n <div class=\"code-html-text-container\" style=\"position: relative; height: calc(100% - 50px);\">\n <textarea class=\"code-html\"></textarea>\n </div>\n </div>\n <div class=\"code-css-container\">\n <div style=\"height: 30px;\">\n <h3 style=\"position: absolute; top: 0; margin: 5px; font-size: 16px; z-index: 100;\">CSS</h3>\n </div>\n <div class=\"colde-css-text-container\" style=\"position: relative; height: calc(100% - 30px);\">\n <textarea class=\"code-css\" v-model=\"appCss\"></textarea>\n </div>\n </div>\n </div>\n </div>\n <div class=\"dragbar\"></div>\n <div class=\"application-container\">\n <div class=\"button-bar form-inline run-options\" style=\"position: relative;\">\n <button class=\"btn btn-success btn-run mr-2\" @click=\"runApp\">Run</button>\n\n <select class=\"form-control run-loglevel mr-1 ml-2\">\n <option>error</option>\n <option>warn</option>\n <option>info</option>\n <option>log</option>\n <option>debug</option>\n </select>\n\n <input class=\"form-control run-noversioncheck mr-1 ml-3\" type=\"checkbox\" checked>No version checking</input>\n <input class=\"form-control run-removetrycatch mr-1 ml-3\" type=\"checkbox\">Remove Try/catch</input>\n <input class=\"form-control run-makesynchrone mr-1 ml-3\" type=\"checkbox\">Make Synchrone</input>\n\n <div class=\"ml-auto\">\n <input class=\"form-control run-profiler mr-1 ml-3\" type=\"checkbox\">Profiler</input>\n <input class=\"form-control run-record mr-1 ml-3\" type=\"checkbox\">Record</input>\n <button class=\"btn btn-secondary btn-snapshot\" @click=\"takeAndLoadSnapshot\">Snapshot</button>\n </div>\n </div>\n <div class=\"application capture-left-click capture-right-click\"></div>\n </div>\n </div>\n </div>\n </div>\n <add-node-vue :display=\"this.addingBox\" :mousePosition=\"this.newBoxPosition\" @closed=\"onAddBoxClosed\"></add-node-vue>\n </div>\n</template>\n\n<script>\nimport _ from 'lodash';\nimport swal from 'sweetalert2';\n\nimport graphVue from './graph.vue';\nimport addNodeVue from './addNode.vue';\nimport editMainSettingsVue from './editMainSettings.vue';\nimport editNodeSettingsVue from './editNodeSettings.vue';\nimport debugNodeInfosVue from './debugNodeInfos.vue';\n\n// CodeMirror\nimport CodeMirror from 'codemirror/lib/codemirror.js';\nimport 'codemirror/mode/xml/xml.js';\nimport 'codemirror/mode/css/css.js';\nimport 'codemirror/mode/javascript/javascript.js';\nimport 'codemirror/mode/htmlmixed/htmlmixed.js';\n\nimport htmltool from '@dualbox/dualbox-lib-htmltool';\n\nexport default {\n props: [\n 'app', // the app\n\n // Display configuration (online or offline ?)\n 'showLoadButton',\n 'showSaveButton',\n 'saveButtonFunction',\n\n // modes\n 'eventVisibility' // are events visible\n ],\n components: {\n 'graph-vue': graphVue,\n 'add-node-vue' : addNodeVue,\n 'edit-main-settings' : editMainSettingsVue,\n 'edit-node-settings' : editNodeSettingsVue,\n 'debug-node-infos' : debugNodeInfosVue,\n },\n data () {\n return {\n // modes\n addingBox : false,\n leftPanelMode : 'main', // 'main' to display main menu, 'node' for a node\n selectedNodeId : null, // id of the node to display in left menu\n debugNodeId: null, // on a snapshot, id of the node to display debug infos\n newBoxPosition: null, // track mouse position relative to the graph when adding a node\n\n // the specific app css\n appCss: \"\",\n }\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n // TODO: restore this when all menus are migrated to Vue.js\n\n this.cssCode = null;\n this.htmlCode = null;\n },\n updated: function() {\n //console.log('updating main view with: ' + JSON.stringify(this.app));\n this.appCss = (this.app && this.app.css) || \"\";\n\n // Update html and css code editor\n this.updateCode();\n },\n mounted: function() {\n //this.view.setMainMenu();\n\n $(this.$el).bind('expandSettings', function(e) {\n // expand\n $(this).find('.dualbox-graph-left-section').css('margin-left', '0');\n $(this).find('.dualbox-graph-main').addClass('left-panel-expanded');\n $(this).find('.btn-toggle-left-window').data('expanded', true).find('i')\n .removeClass('fa-angle-double-right')\n .addClass('fa-angle-double-left')\n .attr('title', 'shrink window');\n });\n\n $(this.$el).bind('shrinkSettings', function(e) {\n // shrink\n $(this).find('.dualbox-graph-left-section').css('margin-left', '-465px');\n $(this).find('.dualbox-graph-main').removeClass('left-panel-expanded');\n $(this).find('.btn-toggle-left-window').data('expanded', false).find('i')\n .removeClass('fa-angle-double-left')\n .addClass('fa-angle-double-right')\n .attr('title', 'expand window');\n });\n\n $(this.$el).bind('expandDebug', function(e) {\n // expand\n $(this).find('.dualbox-graph-right-section').css('margin-right', '0');\n $(this).find('.dualbox-graph-main').addClass('right-panel-expanded');\n $(this).find('.btn-toggle-right-window').data('expanded', true).find('i')\n .removeClass('fa-angle-double-left')\n .addClass('fa-angle-double-right')\n .attr('title', 'shrink window');\n });\n\n $(this.$el).bind('shrinkDebug', function(e) {\n // shrink\n $(this).find('.dualbox-graph-right-section').css('margin-right', '-465px');\n $(this).find('.dualbox-graph-main').removeClass('right-panel-expanded');\n $(this).find('.btn-toggle-right-window').data('expanded', false).find('i')\n .removeClass('fa-angle-double-right')\n .addClass('fa-angle-double-left')\n .attr('title', 'expand window');\n });\n\n // bind tabs\n var self = this;\n $(this.$el).find(\"a[data-toggle='tab']\").on(\"shown.bs.tab\", function(e) {\n var target = $(e.target).attr(\"href\") // activated tab\n if( target == \"#editor-graph-tab\" ) {\n self.view.killApp();\n }\n else if( target == \"#editor-interface-tab\" ) {\n self.htmlCode.refresh();\n self.cssCode.refresh();\n self.view.runApp( self.getOptions() );\n }\n });\n\n $(this.$el).find(\"a[data-toggle='tab']\").on('click', function (e) {\n e.preventDefault()\n $(this).tab('show')\n });\n\n // Update html and css code editor\n this.updateCode();\n\n // Resize horizontally\n $(this.$el).find('.dragbar').mousedown(function(e){\n e.preventDefault();\n $(document).mouseup(function(e){\n $(document).unbind('mousemove');\n });\n $(document).mousemove(function(e){\n $('.code-panel').css('width', e.pageX + \"px\");\n $('.application-container').css('width', ($(\".db-editor-main\").width() - e.pageX - 5) + \"px\");\n })\n });\n\n },\n methods: {\n \"getOptions\": function() {\n return {\n profiler : $(this.$el).find('.run-profiler').is(':checked'),\n logLevel : $(this.$el).find('.run-loglevel').val(),\n options : {\n noVersionCheck: $(this.$el).find('.run-noversioncheck').is(':checked'),\n debug: {\n removeTryCatch: $(this.$el).find('.run-removetrycatch').is(':checked'),\n makeSynchrone: $(this.$el).find('.run-makesynchrone').is(':checked'),\n record: $(this.$el).find('.run-record').is(':checked'),\n }\n }\n }\n },\n\n \"updateCode\": function() {\n // instanciate codemirror for html and css\n if( !this.htmlCode ) {\n this.htmlCode = CodeMirror.fromTextArea( $(this.$el).find(\".code-html\")[0], {\n lineNumbers: true,\n mode : \"htmlmixed\",\n lineWrapping: true\n });\n }\n if( !this.cssCode ) {\n this.cssCode = CodeMirror.fromTextArea( $(this.$el).find(\".code-css\")[0], {\n lineNumbers: true,\n mode : \"css\",\n lineWrapping: true\n });\n }\n this.cssCode.setValue(this.view.m.get().css || \"\");\n },\n\n \"loadApp\" : function() {\n var self = this;\n\n // create a fake input and click it to select a file\n var input = $('<input/>', { \"type\": \"file\", \"class\": \"upload\", \"accept\" : \".json\" });\n input.change( function(e) {\n // if we're not here, go to 1st tab\n $(\"a[data-toggle='tab'][href='#1']\").click();\n\n // parse the file JSON and load it\n var files = e.target.files; // FileList object\n var r = new FileReader();\n r.onload = function(e) {\n var contents = e.target.result;\n var json = JSON.parse(contents);\n self.view.e.setApp(json);\n };\n\n r.readAsText(files[0]);\n });\n input.click();\n },\n \"saveApp\": function() {\n // bind the app load\n if( this.saveButtonFunction ) {\n var saveButtonFunction = (e) => {\n var json = this.view.m.getCleanJson();\n return this.saveButtonFunction(json);\n }\n }\n else {\n var saveButtonFunction = (e) => {\n var app = this.view.m.getCleanJson();\n var text = JSON.stringify(app, null, 2);\n var blob = new Blob([text], { \"type\" : \"application/octet-stream\" });\n\n var a = document.createElement('a');\n a.href = window.URL.createObjectURL(blob);\n a.download = \"app.json\";\n\n // simulate a click on the link\n if (document.createEvent) {\n var event = document.createEvent(\"MouseEvents\");\n event.initEvent(\"click\", true, true);\n a.dispatchEvent(event);\n } else {\n a.click();\n }\n }\n }\n saveButtonFunction();\n },\n \"getCurrentMousePosition\": function(e) {\n return this.$refs.graph.getCurrentMousePosition(e);\n },\n \"addBox\" : function(e) {\n this.addingBox = true;\n this.newBoxPosition = this.getCurrentMousePosition(e);\n this.$forceUpdate();\n },\n \"onAddBoxClosed\" : function() {\n this.addingBox = false;\n this.$forceUpdate();\n },\n \"addMetabox\" : function(e) {\n var self = this;\n e.preventDefault();\n e.stopPropagation();\n\n swal({\n input: 'text',\n title: 'Choose a name for the metabox',\n }).then(function(result) {\n if( result.value ) {\n self.view.c.addNewMetabox(result.value);\n }\n });\n },\n \"addInput\" : function(e) {\n this.view.c.createInput();\n },\n \"addOutput\": function(e) {\n this.view.c.createOutput();\n },\n \"importMetabox\": async function(e) {\n var self = this;\n\n const { value: file } = await swal({\n title: 'Select your metabox file',\n input: 'file',\n inputAttributes: {\n 'accept': 'application/json',\n 'aria-label': 'Select your metabox file'\n }\n })\n\n if (file) {\n const reader = new FileReader()\n reader.onload = (e) => {\n var json = JSON.parse(e.target.result);\n\n self.view.e.loadPackages(json).then(async () => {\n const { value: name } = await swal({\n title: 'Choose a name for your metabox',\n input: 'text',\n showCancelButton: true,\n inputValidator: (value) => {\n return !value && 'You need to write something!'\n }\n });\n\n self.view.c.addNewMetabox(name, json);\n }).catch((err) => {\n console.error(err);\n });\n }\n reader.readAsText(file)\n }\n },\n\n getInterfacesNames : function() {\n return _.keys( _.get(this.view.m, [\"data\",\"root\", \"interface\"]) || {} );\n },\n\n \"selectInterface\": function(e) {\n // Load the interface HTML when selected\n var uiName = $(e.target).val();\n if( uiName !== \"\" && uiName !== \"Load UI...\" ) {\n var itf = this.view.m.data.root.interface;\n var htmlString = htmltool.json2html(itf[uiName]);\n var prettyString = htmltool.htmlPrettyPrint(htmlString);\n this.htmlCode.setValue(prettyString);\n }\n else {\n this.htmlCode.setValue(\"\");\n }\n },\n \"saveInterfaceElement\": function(e) {\n var currentInterface = $(this.$el).find('.app-interface-select').val();\n if( currentInterface !== \"\" ) {\n var currentHTML = this.htmlCode.getValue();\n\n // save html code into app\n this.view.m.data.root.interface[currentInterface] = htmltool.html2json(currentHTML);\n }\n\n // save css code into app\n this.view.m.data.root.css = this.cssCode.getValue();\n },\n \"addInterface\": function(e) {\n var self = this;\n\n swal.mixin({\n confirmButtonText: 'Next →',\n showCancelButton: true,\n progressSteps: ['1', '2', '3']\n }).queue([\n {\n input: 'text',\n title: 'Choose a name',\n text: 'Enter a name for the new interface'\n },\n {\n input: 'select',\n title: 'Choose the type',\n text : 'Is it a viewer panel or a control panel?',\n inputOptions: {\n 'control': 'A control panel',\n 'viewer': 'A viewer',\n },\n },\n {\n input: 'select',\n title: 'Choose the position',\n text : 'Where do you want to position your panel?',\n inputOptions: {\n 'top-left': 'At the top-left',\n 'top-center': 'At the top-center',\n 'top-right': 'At the top-right',\n 'center-left': 'At the center-left',\n 'center': 'At the center',\n 'center-right': 'At the center-right',\n 'bottom-left': 'At the bottom-left',\n 'bottom-center': 'At the bottom-center',\n 'bottom-right': 'At the bottom-right',\n 'whole-screen': 'I want my panel in full-screen',\n },\n }\n ]).then((result) => {\n if (result.value) {\n var name = result.value[0];\n var type = result.value[1];\n var position = result.value[2];\n\n if (name === \"\") {\n swal.showInputError(\"the name is empty!\");\n return false\n }\n\n var appInterface = self.view.m.data.root.interface;\n if( appInterface[name] ) {\n swal.showInputError(\"Interface \" + name + \" already exists!\");\n return false\n }\n else {\n var style={};\n switch(position) {\n case 'top-left': style={ 'position': 'absolute', 'top': 0, 'left': 0, 'margin': '15px' }; break;\n case 'top-center': style={ 'position': 'absolute', 'top': 0, 'margin': '15px auto' }; break;\n case 'top-right': style={ 'position': 'absolute', 'top': 0, 'right': 0, 'margin': '15px' }; break;\n case 'center-left': style={ 'position': 'absolute', 'top': 0, 'bottom': 0, 'left': 0, 'margin': 'auto 15px' }; break;\n case 'center': style={ 'position': 'absolute', 'top': 0, 'bottom': 0, 'left': 0, 'right': 0, 'margin': 'auto' }; break;\n case 'center-right': style={ 'position': 'absolute', 'top': 0, 'bottom': 0, 'right': 0, 'margin': 'auto 15px' }; break;\n case 'bottom-left': style={ 'position': 'absolute', 'bottom': 0, 'left': 0, 'margin': '15px' }; break;\n case 'bottom-center': style={ 'position': 'absolute', 'bottom': 0, 'left': 0, 'right': 0, 'margin': '15px auto' }; break;\n case 'bottom-right': style={ 'position': 'absolute', 'bottom': 0, 'right': 0, 'margin': '15px' }; break;\n case 'whole-screen': style={ 'position': 'absolute', 'top': 0, 'left': 0 }; break;\n }\n\n // some prefilled data\n style['width'] = \"300px\";\n style['padding'] = \"15px\";\n style['border'] = \"1px solid #ccc\";\n style['border-radius'] = \"4px\";\n style['background'] = \"white\";\n if( position.startsWith(\"center\") ) {\n style['height'] = \"60px\"; // must define height\n }\n else {\n style['height'] = \"auto\";\n }\n\n // add a basic control\n appInterface[name] = {\n type: \"Element\",\n tagName: \"div\",\n attributes: {\n className: [\n \"dualbox\",\n \"dualbox-container\",\n \"dualbox-container-\" + name,\n type==\"viewer\" ? \"dualbox-viewer\" : \"dualbox-controls\"\n ],\n style: style,\n },\n children: []\n }\n\n // add the value to our select, and load it\n $(self.$el).find(\".app-interface-select\").append(\n $(\"<option/>\", { \"value\" : name }).append(name)\n );\n $(document).ready(() => {\n $(self.$el).find('.app-interface-select').val(name).change();\n\n // set it into the editor\n var htmlString = htmltool.json2html(appInterface[name]);\n var prettyString = htmltool.htmlPrettyPrint(htmlString);\n this.htmlCode.setValue(prettyString);\n self.updateCode();\n });\n\n self.view.runApp( self.getOptions() );\n }\n }\n })\n },\n \"removeInterface\": function(e) {\n var self = this;\n var name = $('.app-interface-select').val();\n\n swal({\n title: \"Confirm deleting \" + name + \" ?\",\n type: \"warning\",\n showCancelButton: true,\n confirmButtonColor: \"#DD6B55\",\n confirmButtonText: \"Yes, delete it!\",\n closeOnConfirm: true,\n closeOnCancel: true\n }).then((result) => {\n if( result.value ) {\n // set the interface back to first value\n $(this.$el).find(\".app-interface-select option[value='\" + name + \"']\").remove();\n $(this.$el).find(\".app-interface-select\").change();\n delete self.view.m.data.root.interface[name];\n self.htmlCode.setValue(\"\");\n self.view.runApp( self.getOptions() );\n }\n });\n },\n \"editPanelDescription\": function(e) {\n var self = this;\n var name = $('.app-interface-select').val();\n\n swal({\n title: \"Enter a description for this panel!\",\n input: \"textarea\",\n inputValue: this.view.m.data.root.interface[name].description || \"\",\n showCancelButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true,\n animation: \"slide-from-top\",\n inputPlaceholder: \"Write something\"\n }).then( (result) => {\n if (result.value === \"\") {\n swal.showInputError(\"You need to write something!\");\n return false\n }\n else {\n self.view.m.data.root.interface[name].description = result.value;\n }\n });\n },\n \"toggleLeftWindow\": function(e) {\n var expanded = $(e.target).closest('button').data('expanded');\n if( expanded ) {\n $(this.$el).trigger('shrinkSettings');\n }\n else {\n $(this.$el).trigger('expandSettings');\n }\n },\n \"toggleRightWindow\": function(e) {\n var expanded = $(e.target).closest('button').data('expanded');\n if( expanded ) {\n $(this.$el).trigger('shrinkDebug');\n }\n else {\n $(this.$el).trigger('expandDebug');\n }\n },\n\n \"showEvents\": function(e) {\n this.view.setEventsVisibility( $(e.target).is(':checked') );\n },\n\n \"runApp\": function(e) {\n this.view.runApp( this.getOptions() );\n },\n\n \"takeAndLoadSnapshot\": function(e) {\n this.view.takeAndLoadSnapshot();\n },\n\n \"undo\": function(e) {\n this.view.c.undo();\n },\n\n \"redo\" : function(e) {\n this.view.c.redo();\n },\n\n \"removeSelection\": function(e) {\n this.view.c.deleteSelection();\n },\n\n \"mergeSelection\": function(e) {\n this.view.c.mergeSelection();\n },\n\n \"setMainMenu\": function(e) {\n this.view.setMainMenu();\n },\n\n \"getCurrentApplication\" : function(e) {\n // trick to make this function reactive to \"app\" field update\n if( this.app ) {\n return this.view.m.getCurrentApp(true);\n }\n else {\n throw \"Error: no app found\";\n }\n },\n\n \"onEdited\": function(e) {\n console.log('Something was edited, forcing new render');\n this.$forceUpdate();\n },\n\n \"ready\" : function() {\n return new Promise(resolve => {\n this.$nextTick(() => {\n window.requestAnimationFrame(() => {\n $(this.$el).ready(resolve);\n })\n })\n })\n }\n }\n}\n</script>\n"]}, media: undefined });
|
|
87048
87080
|
|
|
87049
87081
|
};
|
|
87050
87082
|
/* scoped */
|
|
@@ -104022,10 +104054,10 @@ class DualboxEditor {
|
|
|
104022
104054
|
|
|
104023
104055
|
var pkgName = "@dualbox/dualbox";
|
|
104024
104056
|
await this.loadPackage(pkgName);
|
|
104025
|
-
if (
|
|
104026
|
-
this.DualBox = window.DualBox = this.require(pkgName);
|
|
104027
|
-
} else {
|
|
104057
|
+
if (window.DualBox && window.DualBox.start) {
|
|
104028
104058
|
this.DualBox = window.DualBox;
|
|
104059
|
+
} else {
|
|
104060
|
+
this.DualBox = window.DualBox = this.require(pkgName);
|
|
104029
104061
|
}
|
|
104030
104062
|
lodash.each(this.DualBox.core, async corePackage => {
|
|
104031
104063
|
await this.loadPackage(corePackage.name);
|