@dualbox/editor 1.0.92 → 1.0.94
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 +21 -14
- package/js/dist/GraphEditor.js +650 -175
- package/js/dist/GraphEditor.min.js +649 -174
- package/js/src/GraphEditor.js +139 -21
- package/js/src/c/GraphController.js +5 -10
- package/js/src/m/GraphModel.js +157 -26
- package/js/src/v/templates/addNode.vue +17 -21
- package/js/src/v/templates/editType.vue +1 -1
- package/js/src/v/templates/main.vue +10 -16
- package/package.json +2 -1
|
@@ -43766,47 +43766,174 @@ class GraphModel {
|
|
|
43766
43766
|
paste(json) {
|
|
43767
43767
|
var currentMetanode = this.getCurrentMetanode();
|
|
43768
43768
|
|
|
43769
|
-
|
|
43770
|
-
|
|
43769
|
+
var checkValidPaste = () => {
|
|
43770
|
+
let valid = true;
|
|
43771
|
+
|
|
43771
43772
|
lodash.each(json.metamodules, (mmDef, mmName) => {
|
|
43772
43773
|
var metamodule = lodash.get(currentMetanode, ["metanodes", mmName]);
|
|
43773
|
-
if (metamodule
|
|
43774
|
-
|
|
43774
|
+
if (metamodule !== undefined) {
|
|
43775
|
+
valid = false;
|
|
43776
|
+
const Toast = sweetalert2_all.mixin({
|
|
43777
|
+
toast: true,
|
|
43778
|
+
position: 'bottom-end',
|
|
43779
|
+
showConfirmButton: false,
|
|
43780
|
+
timer: 5000,
|
|
43781
|
+
timerProgressBar: true,
|
|
43782
|
+
html: "",
|
|
43783
|
+
onOpen: (toast) => {
|
|
43784
|
+
toast.addEventListener('mouseenter', sweetalert2_all.stopTimer);
|
|
43785
|
+
toast.addEventListener('mouseleave', sweetalert2_all.resumeTimer);
|
|
43786
|
+
}
|
|
43787
|
+
});
|
|
43788
|
+
Toast.fire({
|
|
43789
|
+
icon: 'error',
|
|
43790
|
+
title: '<span class="text-danger">Invalid paste : metanode ' + mmName + ' already exists here</span>'
|
|
43791
|
+
});
|
|
43775
43792
|
}
|
|
43776
43793
|
});
|
|
43777
|
-
|
|
43778
|
-
// paste inputs
|
|
43779
43794
|
lodash.each(json.input, (inputDef, inputName) => {
|
|
43780
43795
|
var input = lodash.get(currentMetanode, ["input", inputName]);
|
|
43781
|
-
if (input
|
|
43782
|
-
|
|
43796
|
+
if (input !== undefined) {
|
|
43797
|
+
valid = false;
|
|
43798
|
+
const Toast = sweetalert2_all.mixin({
|
|
43799
|
+
toast: true,
|
|
43800
|
+
position: 'bottom-end',
|
|
43801
|
+
showConfirmButton: false,
|
|
43802
|
+
timer: 5000,
|
|
43803
|
+
timerProgressBar: true,
|
|
43804
|
+
html: "",
|
|
43805
|
+
onOpen: (toast) => {
|
|
43806
|
+
toast.addEventListener('mouseenter', sweetalert2_all.stopTimer);
|
|
43807
|
+
toast.addEventListener('mouseleave', sweetalert2_all.resumeTimer);
|
|
43808
|
+
}
|
|
43809
|
+
});
|
|
43810
|
+
Toast.fire({
|
|
43811
|
+
icon: 'error',
|
|
43812
|
+
title: '<span class="text-danger">Invalid paste : input ' + inputName + ' already exists here</span>'
|
|
43813
|
+
});
|
|
43783
43814
|
}
|
|
43784
43815
|
});
|
|
43785
|
-
|
|
43786
43816
|
// paste outputs
|
|
43787
43817
|
lodash.each(json.output, (outputDef, outputName) => {
|
|
43788
43818
|
var output = lodash.get(currentMetanode, ["output", outputName]);
|
|
43789
|
-
if (output
|
|
43790
|
-
|
|
43819
|
+
if (output !== undefined) {
|
|
43820
|
+
valid = false;
|
|
43821
|
+
const Toast = sweetalert2_all.mixin({
|
|
43822
|
+
toast: true,
|
|
43823
|
+
position: 'bottom-end',
|
|
43824
|
+
showConfirmButton: false,
|
|
43825
|
+
timer: 5000,
|
|
43826
|
+
timerProgressBar: true,
|
|
43827
|
+
html: "",
|
|
43828
|
+
onOpen: (toast) => {
|
|
43829
|
+
toast.addEventListener('mouseenter', sweetalert2_all.stopTimer);
|
|
43830
|
+
toast.addEventListener('mouseleave', sweetalert2_all.resumeTimer);
|
|
43831
|
+
}
|
|
43832
|
+
});
|
|
43833
|
+
Toast.fire({
|
|
43834
|
+
icon: 'error',
|
|
43835
|
+
title: '<span class="text-danger">Invalid paste : output ' + outputName + ' already exists here</span>'
|
|
43836
|
+
});
|
|
43791
43837
|
}
|
|
43792
43838
|
});
|
|
43793
43839
|
|
|
43794
43840
|
// paste modules
|
|
43795
43841
|
lodash.each(json.modules, (moduleDef, moduleName) => {
|
|
43796
43842
|
var node = lodash.get(currentMetanode, ["modules", moduleName]);
|
|
43797
|
-
if (node
|
|
43798
|
-
|
|
43843
|
+
if (node !== undefined) {
|
|
43844
|
+
valid = false;
|
|
43845
|
+
const Toast = sweetalert2_all.mixin({
|
|
43846
|
+
toast: true,
|
|
43847
|
+
position: 'bottom-end',
|
|
43848
|
+
showConfirmButton: false,
|
|
43849
|
+
timer: 5000,
|
|
43850
|
+
timerProgressBar: true,
|
|
43851
|
+
html: "",
|
|
43852
|
+
onOpen: (toast) => {
|
|
43853
|
+
toast.addEventListener('mouseenter', sweetalert2_all.stopTimer);
|
|
43854
|
+
toast.addEventListener('mouseleave', sweetalert2_all.resumeTimer);
|
|
43855
|
+
}
|
|
43856
|
+
});
|
|
43857
|
+
Toast.fire({
|
|
43858
|
+
icon: 'error',
|
|
43859
|
+
title: '<span class="text-danger">Invalid paste : compute box ' + moduleName + ' already exists here</span>'
|
|
43860
|
+
});
|
|
43799
43861
|
}
|
|
43800
43862
|
});
|
|
43801
43863
|
|
|
43802
43864
|
// paste uis
|
|
43803
43865
|
lodash.each(json.ui, (uiDef, uiName) => {
|
|
43804
43866
|
var ui = lodash.get(currentMetanode, ["ui", uiName]);
|
|
43805
|
-
if (ui
|
|
43806
|
-
|
|
43867
|
+
if (ui !== undefined) {
|
|
43868
|
+
valid = false;
|
|
43869
|
+
const Toast = sweetalert2_all.mixin({
|
|
43870
|
+
toast: true,
|
|
43871
|
+
position: 'bottom-end',
|
|
43872
|
+
showConfirmButton: false,
|
|
43873
|
+
timer: 5000,
|
|
43874
|
+
timerProgressBar: true,
|
|
43875
|
+
html: "",
|
|
43876
|
+
onOpen: (toast) => {
|
|
43877
|
+
toast.addEventListener('mouseenter', sweetalert2_all.stopTimer);
|
|
43878
|
+
toast.addEventListener('mouseleave', sweetalert2_all.resumeTimer);
|
|
43879
|
+
}
|
|
43880
|
+
});
|
|
43881
|
+
Toast.fire({
|
|
43882
|
+
icon: 'error',
|
|
43883
|
+
title: '<span class="text-danger">Invalid paste : ui ' + uiName + ' already exists here</span>'
|
|
43884
|
+
});
|
|
43807
43885
|
}
|
|
43808
43886
|
});
|
|
43809
|
-
|
|
43887
|
+
|
|
43888
|
+
return valid;
|
|
43889
|
+
};
|
|
43890
|
+
|
|
43891
|
+
let validPaste = checkValidPaste();
|
|
43892
|
+
if (validPaste) {
|
|
43893
|
+
this.batch(() => {
|
|
43894
|
+
// paste metanodes
|
|
43895
|
+
lodash.each(json.metamodules, (mmDef, mmName) => {
|
|
43896
|
+
var metamodule = lodash.get(currentMetanode, ["metanodes", mmName]);
|
|
43897
|
+
if (metamodule === undefined) {
|
|
43898
|
+
lodash.set(currentMetanode, ["metanodes", mmName], mmDef);
|
|
43899
|
+
}
|
|
43900
|
+
});
|
|
43901
|
+
|
|
43902
|
+
// paste inputs
|
|
43903
|
+
lodash.each(json.input, (inputDef, inputName) => {
|
|
43904
|
+
var input = lodash.get(currentMetanode, ["input", inputName]);
|
|
43905
|
+
if (input === undefined) {
|
|
43906
|
+
lodash.set(currentMetanode, ["input", inputName], inputDef);
|
|
43907
|
+
}
|
|
43908
|
+
});
|
|
43909
|
+
|
|
43910
|
+
// paste outputs
|
|
43911
|
+
lodash.each(json.output, (outputDef, outputName) => {
|
|
43912
|
+
var output = lodash.get(currentMetanode, ["output", outputName]);
|
|
43913
|
+
if (output === undefined) {
|
|
43914
|
+
lodash.set(currentMetanode, ["output", outputName], outputDef);
|
|
43915
|
+
}
|
|
43916
|
+
});
|
|
43917
|
+
|
|
43918
|
+
// paste modules
|
|
43919
|
+
lodash.each(json.modules, (moduleDef, moduleName) => {
|
|
43920
|
+
var node = lodash.get(currentMetanode, ["modules", moduleName]);
|
|
43921
|
+
if (node === undefined) {
|
|
43922
|
+
lodash.set(currentMetanode, ["modules", moduleName], moduleDef);
|
|
43923
|
+
}
|
|
43924
|
+
});
|
|
43925
|
+
|
|
43926
|
+
// paste uis
|
|
43927
|
+
lodash.each(json.ui, (uiDef, uiName) => {
|
|
43928
|
+
var ui = lodash.get(currentMetanode, ["ui", uiName]);
|
|
43929
|
+
if (ui === undefined) {
|
|
43930
|
+
lodash.set(currentMetanode, ["ui", uiName], uiDef);
|
|
43931
|
+
}
|
|
43932
|
+
});
|
|
43933
|
+
});
|
|
43934
|
+
}
|
|
43935
|
+
|
|
43936
|
+
return validPaste;
|
|
43810
43937
|
}
|
|
43811
43938
|
|
|
43812
43939
|
/**
|
|
@@ -43901,14 +44028,16 @@ class GraphModel {
|
|
|
43901
44028
|
|
|
43902
44029
|
// add pkg dependencies (lib, types, etc) to app graph
|
|
43903
44030
|
async addDependencies(pkg) {
|
|
43904
|
-
|
|
43905
|
-
|
|
43906
|
-
|
|
43907
|
-
|
|
43908
|
-
|
|
43909
|
-
|
|
43910
|
-
|
|
43911
|
-
|
|
44031
|
+
if (pkg.dependencies) {
|
|
44032
|
+
for (const dependencyName of Object.keys(pkg.dependencies)) {
|
|
44033
|
+
if (utils.isLibrary(dependencyName) || utils.isType(dependencyName)) {
|
|
44034
|
+
console.log('[*] Adding dependency: ' + dependencyName);
|
|
44035
|
+
// await this.e.loadPackage(dependencyName, dependencyVersion); // Is this better ?
|
|
44036
|
+
await this.e.loadPackage(dependencyName); // or should we just load the last version ?
|
|
44037
|
+
let pkg = this.e.packages[dependencyName];
|
|
44038
|
+
this.data.root.libs[pkg.name] = pkg.version;
|
|
44039
|
+
await this.addDependencies(pkg);
|
|
44040
|
+
}
|
|
43912
44041
|
}
|
|
43913
44042
|
}
|
|
43914
44043
|
}
|
|
@@ -63541,6 +63670,7 @@ var __vue_render__$4 = function() {
|
|
|
63541
63670
|
return _c(
|
|
63542
63671
|
"option",
|
|
63543
63672
|
{
|
|
63673
|
+
key: typeName,
|
|
63544
63674
|
domProps: {
|
|
63545
63675
|
value: typeName,
|
|
63546
63676
|
selected: typeName == _vm.selectedType
|
|
@@ -63594,7 +63724,7 @@ __vue_render__$4._withStripped = true;
|
|
|
63594
63724
|
/* style */
|
|
63595
63725
|
const __vue_inject_styles__$4 = function (inject) {
|
|
63596
63726
|
if (!inject) return
|
|
63597
|
-
inject("data-v-
|
|
63727
|
+
inject("data-v-b5dab45e_0", { source: "\n.list-types {\n max-height: 518px;\n overflow-y: auto;\n padding-top: 10px;\n}\n.list-types li {\n cursor: pointer;\n}\n.list-types li:hover {\n background-color: rgba(0,0,0,0.1);\n}\nspan.type-display {\n font-size: 16px;\n font-weight: bold;\n}\n.choose-type {\n font-weight: bold;\n font-size: 18px;\n}\n.bs3 {\n display: none!important;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/editType.vue"],"names":[],"mappings":";AACA;IACA,iBAAA;IACA,gBAAA;IACA,iBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iCAAA;AACA;AAEA;IACA,eAAA;IACA,iBAAA;AACA;AAEA;IACA,iBAAA;IACA,eAAA;AACA;AAEA;IACA,uBAAA;AACA","file":"editType.vue","sourcesContent":["<style>\n .list-types {\n max-height: 518px;\n overflow-y: auto;\n padding-top: 10px;\n }\n\n .list-types li {\n cursor: pointer;\n }\n\n .list-types li:hover {\n background-color: rgba(0,0,0,0.1);\n }\n\n span.type-display {\n font-size: 16px;\n font-weight: bold;\n }\n\n .choose-type {\n font-weight: bold;\n font-size: 18px;\n }\n\n .bs3 {\n display: none!important;\n }\n</style>\n\n<template>\n <div style=\"width: 100%;\">\n <span class=\"d-inline-block\"><span class=\"type-display\">{{typePrefix}}</span></span>\n <select class=\"selectpicker d-inline-block\">\n <option disabled value='default' :selected=\"!selectedType || selectedType=='*'\" >Select a type</option>\n <option v-for=\"typeName in getMatchingTypes()\" :key=\"typeName\" :value=\"typeName\" :selected=\"typeName == selectedType\">{{typeName}}</option>\n </select>\n <span class=\"d-inline-block type-display\">{{typeSuffix}}</span>\n <button v-if=\"displayOKButton!==false\" class=\"btn btn-success d-inline-block\" @click=\"emitType\">Ok</button>\n <button v-if=\"displayResetButton!==false\" class=\"btn btn-outline-secondary d-inline-block\" @click=\"resetChanges\">Reset</button>\n <small v-if=\"showExtendedTypeMessage\" class=\"form-text text-muted\">\n You are building a complex type (types with Array or Map). Continue to select the '*' type until all star are resolved.\n </small>\n </div>\n</template>\n\n<script>\nimport _ from 'lodash-es';\n\n// including bootstrap-select doesn't work\n// made a PR for this: see https://github.com/snapappointments/bootstrap-select/issues/2374\nimport 'bootstrap-select/dist/css/bootstrap-select.min.css';\nimport 'bootstrap-select';\nif( $.fn.selectpicker ) {\n $.fn.selectpicker.Constructor.BootstrapVersion = '4';\n}\n\nexport default {\n name : \"edit-type\",\n props: [\n \"type\", // the dualbox type of the value\n \"displayOKButton\",\n \"displayResetButton\"\n ],\n data: function () {\n return {\n \"types\" : null,\n \"searchText\" : null,\n \"selectedType\": null,\n\n \"typePrefix\" : \"\",\n \"typeSuffix\" : \"\",\n \"showExtendedTypeMessage\": false,\n };\n },\n created: async function() {\n this.view = window.dualboxEditor.v;\n this.types = await this.getTypes(); // will reactively update type list when done\n this.initToTypeValue();\n },\n mounted: function() {\n var self = this;\n this.initSelectPicker();\n this.bindSelectPicker();\n },\n updated: function() {\n console.log('updated');\n this.refreshSelectPicker();\n },\n methods: {\n initToTypeValue() {\n if( this.type ) {\n var a = this.type.split('<');\n var fragment = a[ a.length -1 ];\n a = fragment.split('>');\n fragment = a[0];\n a = fragment.split(',');\n fragment = a[ a.length - 1 ];\n\n this.typePrefix = this.type.substr(0, this.type.indexOf(fragment));\n this.selectedType = fragment;\n this.typeSuffix = this.type.substr(this.type.indexOf(fragment) + fragment.length, this.type.length -1);\n }\n },\n\n isSelected(typeName) {\n return typeName == this.selectedType;\n },\n\n initSelectPicker: function() {\n this.selectDiv = $(this.$el).find('select.selectpicker');\n this.selectDiv.selectpicker({\n liveSearch: true,\n liveSearchPlaceholder: \"Search through types\",\n });\n },\n\n removeSelectPicler: function() {\n this.selectDiv.selectpicker('destroy');\n },\n\n unbindSelectPicker: function() {\n this.selectDiv.off('changed.bs.select');\n },\n\n bindSelectPicker: function() {\n this.selectDiv.on('changed.bs.select', (event, clickedIndex, isSelected, previousValue) => {\n var val = this.selectDiv.selectpicker('val');\n this.selectType( val );\n });\n },\n\n destroySelectPicker: function() {\n this.selectDiv.off('changed.bs.select');\n this.selectDiv.selectpicker('destroy');\n },\n\n resetSelectPicker: function() {\n this.unbindSelectPicker();\n this.selectDiv.selectpicker('val', 'default');\n this.bindSelectPicker();\n },\n\n refreshSelectPicker: function() {\n this.selectDiv.selectpicker('refresh');\n },\n\n sleep: function(ms) {\n return new Promise(resolve => setTimeout(resolve, ms));\n },\n\n getTypes: async function() {\n var rootTypesPkg = await this.view.e.getRootTypes();\n var rootTypes = _.map(rootTypesPkg, pkg => _.get(pkg, \"dualbox.type.name\"));\n\n // Remove array and maps, insert them on top\n rootTypes = rootTypes.filter(n => n.toLowerCase()!=='array' && n.toLowerCase()!=='map');\n rootTypes.unshift(\"Array<*>\", \"Map<String, *>\");\n return rootTypes;\n },\n\n getMatchingTypes : function() {\n if( this.searchText ) {\n return _.filter(this.types, t => { return t.indexOf(this.searchText) !== -1; });\n }\n else {\n return this.types;\n }\n },\n\n selectType: function(typeName) {\n // We selected a star-type. Now, continue the selection to resolve the star\n if( typeName.indexOf('*') !== -1 ) {\n this.showExtendedTypeMessage = true;\n\n var prefix, suffix;\n [prefix, suffix] = typeName.split('*');\n this.typePrefix = this.typePrefix + prefix;\n this.typeSuffix = suffix + this.typeSuffix;\n\n // reset the select\n this.resetSelectPicker();\n }\n else {\n this.selectedType = this.typePrefix + typeName + this.typeSuffix;\n }\n },\n\n emitType: function(e) {\n this.$emit('edited', this.get())\n },\n\n get: function() {\n return this.selectedType ? this.selectedType.replace(/\\s/g, \"\") : undefined;\n },\n\n resetChanges: function() {\n this.typePrefix = \"\";\n this.typeSuffix = \"\";\n this.selectedType = null;\n this.showExtendedTypeMessage = false;\n this.searchText = \"\";\n this.resetSelectPicker();\n },\n }\n}\n</script>\n"]}, media: undefined });
|
|
63598
63728
|
|
|
63599
63729
|
};
|
|
63600
63730
|
/* scoped */
|
|
@@ -63638,7 +63768,7 @@ var script$5 = {
|
|
|
63638
63768
|
return {
|
|
63639
63769
|
error: null,
|
|
63640
63770
|
|
|
63641
|
-
searchText: {}, // the search text, indexed by selectedType
|
|
63771
|
+
searchText: { "module": "", "ui": "" }, // the search text, indexed by selectedType
|
|
63642
63772
|
results: {}, // dictionary of arrays, indexed by selectedType
|
|
63643
63773
|
selectedResult: {}, // dictionary of string, indexed by selectedType
|
|
63644
63774
|
selectedType: "module",
|
|
@@ -63648,6 +63778,7 @@ var script$5 = {
|
|
|
63648
63778
|
},
|
|
63649
63779
|
created: function() {
|
|
63650
63780
|
this.view = window.dualboxEditor.v;
|
|
63781
|
+
this.searchModules();
|
|
63651
63782
|
},
|
|
63652
63783
|
updated: function() {
|
|
63653
63784
|
console.log("AddNode updated !");
|
|
@@ -63722,6 +63853,9 @@ var script$5 = {
|
|
|
63722
63853
|
let searchText = this.searchText[this.selectedType];
|
|
63723
63854
|
this.selectedType = t;
|
|
63724
63855
|
this.searchText[t] = searchText;
|
|
63856
|
+
if( t === "module" || t === "ui" ) {
|
|
63857
|
+
this.searchModules();
|
|
63858
|
+
}
|
|
63725
63859
|
},
|
|
63726
63860
|
|
|
63727
63861
|
addSelectedNode: async function(e) {
|
|
@@ -63824,17 +63958,17 @@ var script$5 = {
|
|
|
63824
63958
|
searchModules: async function(e) {
|
|
63825
63959
|
//var text = $(e.target).val();
|
|
63826
63960
|
var text = this.searchText[this.selectedType];
|
|
63827
|
-
try {
|
|
63961
|
+
//try {
|
|
63828
63962
|
this.error = null;
|
|
63829
63963
|
this.results[this.selectedType] = await this.view.e.search(
|
|
63830
63964
|
text,
|
|
63831
63965
|
this.selectedType
|
|
63832
63966
|
);
|
|
63833
63967
|
this.$forceUpdate();
|
|
63834
|
-
} catch (e) {
|
|
63835
|
-
|
|
63836
|
-
|
|
63837
|
-
}
|
|
63968
|
+
//} catch (e) {
|
|
63969
|
+
// this.error = e;
|
|
63970
|
+
// swal("error searching packages", e, "error");
|
|
63971
|
+
//}
|
|
63838
63972
|
},
|
|
63839
63973
|
|
|
63840
63974
|
getSearchText: function() {
|
|
@@ -64077,76 +64211,55 @@ var __vue_render__$5 = function() {
|
|
|
64077
64211
|
}
|
|
64078
64212
|
},
|
|
64079
64213
|
[
|
|
64080
|
-
_c(
|
|
64081
|
-
|
|
64082
|
-
|
|
64083
|
-
|
|
64084
|
-
|
|
64085
|
-
|
|
64086
|
-
|
|
64087
|
-
|
|
64088
|
-
|
|
64089
|
-
|
|
64090
|
-
|
|
64091
|
-
|
|
64092
|
-
|
|
64093
|
-
|
|
64094
|
-
|
|
64095
|
-
|
|
64096
|
-
|
|
64097
|
-
|
|
64098
|
-
|
|
64099
|
-
|
|
64100
|
-
|
|
64101
|
-
|
|
64102
|
-
|
|
64103
|
-
|
|
64104
|
-
|
|
64105
|
-
|
|
64106
|
-
|
|
64107
|
-
|
|
64108
|
-
|
|
64109
|
-
|
|
64110
|
-
|
|
64111
|
-
|
|
64112
|
-
|
|
64113
|
-
|
|
64114
|
-
|
|
64115
|
-
|
|
64116
|
-
|
|
64117
|
-
|
|
64118
|
-
|
|
64119
|
-
|
|
64120
|
-
|
|
64121
|
-
|
|
64122
|
-
|
|
64123
|
-
|
|
64124
|
-
|
|
64125
|
-
|
|
64126
|
-
|
|
64127
|
-
|
|
64128
|
-
|
|
64129
|
-
ref: "displayResults",
|
|
64130
|
-
attrs: {
|
|
64131
|
-
result: _vm.getSelectedResult()
|
|
64132
|
-
}
|
|
64133
|
-
})
|
|
64134
|
-
: _c(
|
|
64135
|
-
"div",
|
|
64136
|
-
{ staticClass: "message-container" },
|
|
64137
|
-
[
|
|
64138
|
-
_c("p", { staticClass: "message" }, [
|
|
64139
|
-
_vm._v("Select a result to display")
|
|
64140
|
-
])
|
|
64141
|
-
]
|
|
64142
|
-
)
|
|
64143
|
-
],
|
|
64144
|
-
1
|
|
64145
|
-
)
|
|
64146
|
-
]
|
|
64147
|
-
],
|
|
64148
|
-
2
|
|
64149
|
-
)
|
|
64214
|
+
_c("div", { staticClass: "row h100" }, [
|
|
64215
|
+
_c(
|
|
64216
|
+
"div",
|
|
64217
|
+
{
|
|
64218
|
+
staticClass: "col-md-4 h100",
|
|
64219
|
+
staticStyle: {
|
|
64220
|
+
"padding-left": "0",
|
|
64221
|
+
"padding-right": "0",
|
|
64222
|
+
"overflow-y": "auto",
|
|
64223
|
+
"overflow-x": "hidden"
|
|
64224
|
+
}
|
|
64225
|
+
},
|
|
64226
|
+
[
|
|
64227
|
+
_c("search-results", {
|
|
64228
|
+
ref: "searchResults",
|
|
64229
|
+
attrs: {
|
|
64230
|
+
results: _vm.getResults(),
|
|
64231
|
+
err: _vm.error
|
|
64232
|
+
},
|
|
64233
|
+
on: { resultSelected: _vm.setSelectedResult }
|
|
64234
|
+
})
|
|
64235
|
+
],
|
|
64236
|
+
1
|
|
64237
|
+
),
|
|
64238
|
+
_vm._v(" "),
|
|
64239
|
+
_c(
|
|
64240
|
+
"div",
|
|
64241
|
+
{
|
|
64242
|
+
staticClass: "col-md-8 h100",
|
|
64243
|
+
staticStyle: {
|
|
64244
|
+
"padding-left": "15px",
|
|
64245
|
+
"padding-right": "0"
|
|
64246
|
+
}
|
|
64247
|
+
},
|
|
64248
|
+
[
|
|
64249
|
+
_vm.getSelectedResult()
|
|
64250
|
+
? _c("display-result", {
|
|
64251
|
+
ref: "displayResults",
|
|
64252
|
+
attrs: { result: _vm.getSelectedResult() }
|
|
64253
|
+
})
|
|
64254
|
+
: _c("div", { staticClass: "message-container" }, [
|
|
64255
|
+
_c("p", { staticClass: "message" }, [
|
|
64256
|
+
_vm._v("Select a search result to display")
|
|
64257
|
+
])
|
|
64258
|
+
])
|
|
64259
|
+
],
|
|
64260
|
+
1
|
|
64261
|
+
)
|
|
64262
|
+
])
|
|
64150
64263
|
]
|
|
64151
64264
|
),
|
|
64152
64265
|
_vm._v(" "),
|
|
@@ -64173,7 +64286,7 @@ var __vue_render__$5 = function() {
|
|
|
64173
64286
|
_vm._v("Add a new input")
|
|
64174
64287
|
]),
|
|
64175
64288
|
_vm._v(" "),
|
|
64176
|
-
_vm._m(
|
|
64289
|
+
_vm._m(4),
|
|
64177
64290
|
_vm._v(" "),
|
|
64178
64291
|
_c(
|
|
64179
64292
|
"div",
|
|
@@ -64199,7 +64312,7 @@ var __vue_render__$5 = function() {
|
|
|
64199
64312
|
1
|
|
64200
64313
|
),
|
|
64201
64314
|
_vm._v(" "),
|
|
64202
|
-
_vm._m(
|
|
64315
|
+
_vm._m(5)
|
|
64203
64316
|
]
|
|
64204
64317
|
)
|
|
64205
64318
|
])
|
|
@@ -64229,7 +64342,7 @@ var __vue_render__$5 = function() {
|
|
|
64229
64342
|
_vm._v("Add a new output")
|
|
64230
64343
|
]),
|
|
64231
64344
|
_vm._v(" "),
|
|
64232
|
-
_vm._m(
|
|
64345
|
+
_vm._m(6),
|
|
64233
64346
|
_vm._v(" "),
|
|
64234
64347
|
_c(
|
|
64235
64348
|
"div",
|
|
@@ -64255,7 +64368,7 @@ var __vue_render__$5 = function() {
|
|
|
64255
64368
|
1
|
|
64256
64369
|
),
|
|
64257
64370
|
_vm._v(" "),
|
|
64258
|
-
_vm._m(
|
|
64371
|
+
_vm._m(7)
|
|
64259
64372
|
]
|
|
64260
64373
|
)
|
|
64261
64374
|
])
|
|
@@ -64287,7 +64400,7 @@ var __vue_render__$5 = function() {
|
|
|
64287
64400
|
)
|
|
64288
64401
|
]),
|
|
64289
64402
|
_vm._v(" "),
|
|
64290
|
-
_vm._m(
|
|
64403
|
+
_vm._m(8),
|
|
64291
64404
|
_vm._v(" "),
|
|
64292
64405
|
_c("div", { staticClass: "form-group" }, [
|
|
64293
64406
|
_c("label", { attrs: { for: "metanode-def" } }, [
|
|
@@ -64301,7 +64414,7 @@ var __vue_render__$5 = function() {
|
|
|
64301
64414
|
})
|
|
64302
64415
|
]),
|
|
64303
64416
|
_vm._v(" "),
|
|
64304
|
-
_vm._m(
|
|
64417
|
+
_vm._m(9)
|
|
64305
64418
|
]
|
|
64306
64419
|
)
|
|
64307
64420
|
])
|
|
@@ -64401,24 +64514,6 @@ var __vue_staticRenderFns__$5 = [
|
|
|
64401
64514
|
[_c("span", { attrs: { "aria-hidden": "true" } }, [_vm._v("×")])]
|
|
64402
64515
|
)
|
|
64403
64516
|
},
|
|
64404
|
-
function() {
|
|
64405
|
-
var _vm = this;
|
|
64406
|
-
var _h = _vm.$createElement;
|
|
64407
|
-
var _c = _vm._self._c || _h;
|
|
64408
|
-
return _c("p", { staticClass: "message" }, [
|
|
64409
|
-
_c("i", { staticClass: "fas fa-search" }),
|
|
64410
|
-
_vm._v(" Type something to search through the Dualbox library.")
|
|
64411
|
-
])
|
|
64412
|
-
},
|
|
64413
|
-
function() {
|
|
64414
|
-
var _vm = this;
|
|
64415
|
-
var _h = _vm.$createElement;
|
|
64416
|
-
var _c = _vm._self._c || _h;
|
|
64417
|
-
return _c("p", { staticClass: "message" }, [
|
|
64418
|
-
_c("i", { staticClass: "fas fa-search" }),
|
|
64419
|
-
_vm._v(" No results.")
|
|
64420
|
-
])
|
|
64421
|
-
},
|
|
64422
64517
|
function() {
|
|
64423
64518
|
var _vm = this;
|
|
64424
64519
|
var _h = _vm.$createElement;
|
|
@@ -64532,11 +64627,11 @@ __vue_render__$5._withStripped = true;
|
|
|
64532
64627
|
/* style */
|
|
64533
64628
|
const __vue_inject_styles__$5 = function (inject) {
|
|
64534
64629
|
if (!inject) return
|
|
64535
|
-
inject("data-v-4feaa5c6_0", { source: "\n.add-node-modal .modal-body[data-v-4feaa5c6] {\n height: 70vh;\n}\n.h100[data-v-4feaa5c6] {\n height: 100% !important;\n min-height: 100% !important;\n}\n.table-desc th[data-v-4feaa5c6],\n.table-desc td[data-v-4feaa5c6] {\n margin-right: 10px;\n}\n#add-node-modal .modal-dialog[data-v-4feaa5c6] {\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-4feaa5c6] {\n height: auto;\n min-height: 100%;\n border-radius: 0;\n}\n.nav-item[data-v-4feaa5c6] {\n margin-left: 15px;\n margin-right: 15px;\n}\n.nav-link[data-v-4feaa5c6] {\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-4feaa5c6] {\n top: 0px;\n border-top-left-radius: 5px;\n border-bottom-left-radius: 5px;\n}\n.nav-link > span[data-v-4feaa5c6] {\n padding-left: 10px;\n padding-right: 10px;\n}\n.nav-link.active > span[data-v-4feaa5c6] {\n color: black;\n}\n.input-search[data-v-4feaa5c6] {\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-4feaa5c6] {\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-4feaa5c6] {\n background-color: rgba(0, 0, 0, 0.3) !important;\n}\n.nav-compute > a.active[data-v-4feaa5c6],\n.nav-compute > a.active > input[data-v-4feaa5c6] {\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-4feaa5c6]::placeholder {\n color: rgba(255, 255, 255, 0.5);\n}\n.nav-uis > a.active[data-v-4feaa5c6],\n.nav-uis > a.active > input[data-v-4feaa5c6] {\n background-color: #bff2ca !important;\n}\n.nav-inputs > a.active[data-v-4feaa5c6] {\n background-color: #f5d76e !important;\n}\n.nav-compute > a.active > input[data-v-4feaa5c6] {\n background-color: rgba(0, 0, 0, 0.8);\n}\n.nav-outputs > a.active[data-v-4feaa5c6],\n.nav-outputs > a.active > input[data-v-4feaa5c6] {\n background-color: #ffb3a7 !important;\n}\n.message-container[data-v-4feaa5c6] {\n position: relative;\n width: 100%;\n height: 100%;\n}\n.message[data-v-4feaa5c6] {\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-4feaa5c6],\n.tab-pane[data-v-4feaa5c6] {\n width: 100%;\n height: 100%;\n}\nlabel[data-v-4feaa5c6] {\n font-size: 20px;\n margin-top: 20px;\n}\nfieldset[data-v-4feaa5c6] {\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,uBAAA;IACA,2BAAA;AACA;AAEA;;IAEA,kBAAA;AACA;AAEA;IACA,uCAAA;IACA,yBAAA;IACA,YAAA;IACA,UAAA;AACA;AAEA;IACA,YAAA;IACA,gBAAA;IACA,gBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,gBAAA;IACA,sBAAA;IACA,kBAAA;IACA,iBAAA;AACA;AAEA;IACA,QAAA;IACA,2BAAA;IACA,8BAAA;AACA;AAEA;IACA,kBAAA;IACA,mBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,aAAA;IACA,UAAA;IACA,YAAA;IACA,2BAAA;IACA,2CAAA;AACA;AAEA;IACA,qBAAA;IACA,2BAAA;IACA,8BAAA;IACA,oBAAA;IACA,YAAA;AACA;AACA;IACA,+CAAA;AACA;AAEA;;IAEA,+CAAA;IACA,+BAAA;AACA;AAEA;IACA,+BAAA;AACA;AAEA;;IAEA,oCAAA;AACA;AAEA;IACA,oCAAA;AACA;AAEA;IACA,oCAAA;AACA;AAEA;;IAEA,oCAAA;AACA;AAEA;IACA,kBAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,2BAAA;IACA,OAAA;IACA,QAAA;IACA,YAAA;IACA,kBAAA;AACA;AAEA;;IAEA,WAAA;IACA,YAAA;AACA;AAEA;IACA,eAAA;IACA,gBAAA;AACA;AAEA;IACA,oCAAA;IACA,YAAA;IACA,aAAA;IACA,gBAAA;AACA","file":"addNode.vue","sourcesContent":["<style scoped>\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,\n.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,\n.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,\n.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,\n.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,\n.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\n <!--<button class=\"btn btn-outline-secondary float-right\" @click=\"importMetabox\"><i class=\"fas fa-upload\"></i></button>-->\n </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-es\";\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 if (!this.display) {\n // make sure the modal disappeared\n $(this.$el).modal(\"hide\");\n $(\"body\").removeClass(\"modal-open\");\n $(\".modal-backdrop\").remove();\n }\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)\n .find('[data-toggle=\"pill\"]')\n .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 } 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\n return new Promise((resolve, reject) => {\n this.$emit(\"closed\");\n\n let forceCloseModal = () => {\n if (!this.display) {\n resolve();\n } else {\n this.$emit(\"closed\");\n setTimeout(forceCloseModal, 100);\n }\n };\n\n this.$nextTick(forceCloseModal);\n });\n },\n\n setSearchFocus: function() {\n $(this.$el)\n .find(\".nav-link.active\")\n .find(\"input\")\n .focus();\n },\n\n selectType(t) {\n let searchText = this.searchText[this.selectedType];\n this.selectedType = t;\n this.searchText[t] = searchText;\n },\n\n addSelectedNode: async function(e) {\n switch (this.selectedType) {\n case \"module\":\n case \"ui\":\n var selectedNode = $(\".node-result.selected\")[0];\n if (selectedNode) {\n await this.closeModal();\n // add node to the controller\n var packageName = $(selectedNode).data(\"package\");\n this.view.c.addNewBox(packageName, this.mousePosition);\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)\n .find(\".input-name\")\n .val();\n var desc = $(this.$el)\n .find(\".input-description\")\n .val();\n if (type !== undefined && name) {\n await this.closeModal();\n this.view.c.addInput(\n name,\n type,\n desc,\n this.mousePosition\n );\n // reset fields\n this.$refs.inputType.resetChanges();\n $(this.$el)\n .find(\".input-name\")\n .val(\"\");\n $(this.$el)\n .find(\".input-description\")\n .val(\"\");\n } else {\n swal(\"Please complete all fields\", \"\", \"error\");\n return;\n }\n break;\n\n case \"output\":\n var name = $(this.$el)\n .find(\".output-name\")\n .val();\n var type = this.$refs.outputType.get();\n var desc = $(this.$el)\n .find(\".output-description\")\n .val();\n if (type !== undefined && name) {\n await this.closeModal();\n this.view.c.addOutput(\n name,\n type,\n desc,\n this.mousePosition\n );\n // reset fields\n this.$refs.outputType.resetChanges();\n $(this.$el)\n .find(\".output-name\")\n .val(\"\");\n $(this.$el)\n .find(\".output-description\")\n .val(\"\");\n } else {\n swal(\"Please complete all fields\", \"\", \"error\");\n return;\n }\n break;\n\n case \"metanode\":\n var name = $(this.$el)\n .find(\".metanode-name\")\n .val();\n var desc = $(this.$el)\n .find(\".metanode-description\")\n .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 await this.closeModal();\n this.view.c.addNewMetabox(name, json, this.mousePosition);\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(\n text,\n this.selectedType\n );\n this.$forceUpdate();\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)\n .find(\".metanode-description\")\n .val(this.metanodeJSON.description);\n }\n };\n reader.readAsText(file);\n }\n }\n};\n</script>\n\n"]}, media: undefined });
|
|
64630
|
+
inject("data-v-095049aa_0", { source: "\n.add-node-modal .modal-body[data-v-095049aa] {\n height: 70vh;\n}\n.h100[data-v-095049aa] {\n height: 100% !important;\n min-height: 100% !important;\n}\n.table-desc th[data-v-095049aa],\n.table-desc td[data-v-095049aa] {\n margin-right: 10px;\n}\n#add-node-modal .modal-dialog[data-v-095049aa] {\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-095049aa] {\n height: auto;\n min-height: 100%;\n border-radius: 0;\n}\n.nav-item[data-v-095049aa] {\n margin-left: 15px;\n margin-right: 15px;\n}\n.nav-link[data-v-095049aa] {\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-095049aa] {\n top: 0px;\n border-top-left-radius: 5px;\n border-bottom-left-radius: 5px;\n}\n.nav-link > span[data-v-095049aa] {\n padding-left: 10px;\n padding-right: 10px;\n}\n.nav-link.active > span[data-v-095049aa] {\n color: black;\n}\n.input-search[data-v-095049aa] {\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-095049aa] {\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-095049aa] {\n background-color: rgba(0, 0, 0, 0.3) !important;\n}\n.nav-compute > a.active[data-v-095049aa],\n.nav-compute > a.active > input[data-v-095049aa] {\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-095049aa]::placeholder {\n color: rgba(255, 255, 255, 0.5);\n}\n.nav-uis > a.active[data-v-095049aa],\n.nav-uis > a.active > input[data-v-095049aa] {\n background-color: #bff2ca !important;\n}\n.nav-inputs > a.active[data-v-095049aa] {\n background-color: #f5d76e !important;\n}\n.nav-compute > a.active > input[data-v-095049aa] {\n background-color: rgba(0, 0, 0, 0.8);\n}\n.nav-outputs > a.active[data-v-095049aa],\n.nav-outputs > a.active > input[data-v-095049aa] {\n background-color: #ffb3a7 !important;\n}\n.message-container[data-v-095049aa] {\n position: relative;\n width: 100%;\n height: 100%;\n}\n.message[data-v-095049aa] {\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-095049aa],\n.tab-pane[data-v-095049aa] {\n width: 100%;\n height: 100%;\n}\nlabel[data-v-095049aa] {\n font-size: 20px;\n margin-top: 20px;\n}\nfieldset[data-v-095049aa] {\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,uBAAA;IACA,2BAAA;AACA;AAEA;;IAEA,kBAAA;AACA;AAEA;IACA,uCAAA;IACA,yBAAA;IACA,YAAA;IACA,UAAA;AACA;AAEA;IACA,YAAA;IACA,gBAAA;IACA,gBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,gBAAA;IACA,sBAAA;IACA,kBAAA;IACA,iBAAA;AACA;AAEA;IACA,QAAA;IACA,2BAAA;IACA,8BAAA;AACA;AAEA;IACA,kBAAA;IACA,mBAAA;AACA;AAEA;IACA,YAAA;AACA;AAEA;IACA,aAAA;IACA,UAAA;IACA,YAAA;IACA,2BAAA;IACA,2CAAA;AACA;AAEA;IACA,qBAAA;IACA,2BAAA;IACA,8BAAA;IACA,oBAAA;IACA,YAAA;AACA;AACA;IACA,+CAAA;AACA;AAEA;;IAEA,+CAAA;IACA,+BAAA;AACA;AAEA;IACA,+BAAA;AACA;AAEA;;IAEA,oCAAA;AACA;AAEA;IACA,oCAAA;AACA;AAEA;IACA,oCAAA;AACA;AAEA;;IAEA,oCAAA;AACA;AAEA;IACA,kBAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,2BAAA;IACA,OAAA;IACA,QAAA;IACA,YAAA;IACA,kBAAA;AACA;AAEA;;IAEA,WAAA;IACA,YAAA;AACA;AAEA;IACA,eAAA;IACA,gBAAA;AACA;AAEA;IACA,oCAAA;IACA,YAAA;IACA,aAAA;IACA,gBAAA;AACA","file":"addNode.vue","sourcesContent":["<style scoped>\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,\n.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,\n.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,\n.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,\n.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,\n.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 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 search result to display</p>\n </div>\n </div>\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\n <!--<button class=\"btn btn-outline-secondary float-right\" @click=\"importMetabox\"><i class=\"fas fa-upload\"></i></button>-->\n </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-es\";\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: { \"module\": \"\", \"ui\": \"\" }, // 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 this.searchModules();\n },\n updated: function() {\n console.log(\"AddNode updated !\");\n this.updateVisibility();\n this.setSearchFocus();\n\n if (!this.display) {\n // make sure the modal disappeared\n $(this.$el).modal(\"hide\");\n $(\"body\").removeClass(\"modal-open\");\n $(\".modal-backdrop\").remove();\n }\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)\n .find('[data-toggle=\"pill\"]')\n .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 } 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\n return new Promise((resolve, reject) => {\n this.$emit(\"closed\");\n\n let forceCloseModal = () => {\n if (!this.display) {\n resolve();\n } else {\n this.$emit(\"closed\");\n setTimeout(forceCloseModal, 100);\n }\n };\n\n this.$nextTick(forceCloseModal);\n });\n },\n\n setSearchFocus: function() {\n $(this.$el)\n .find(\".nav-link.active\")\n .find(\"input\")\n .focus();\n },\n\n selectType(t) {\n let searchText = this.searchText[this.selectedType];\n this.selectedType = t;\n this.searchText[t] = searchText;\n if( t === \"module\" || t === \"ui\" ) {\n this.searchModules();\n }\n },\n\n addSelectedNode: async function(e) {\n switch (this.selectedType) {\n case \"module\":\n case \"ui\":\n var selectedNode = $(\".node-result.selected\")[0];\n if (selectedNode) {\n await this.closeModal();\n // add node to the controller\n var packageName = $(selectedNode).data(\"package\");\n this.view.c.addNewBox(packageName, this.mousePosition);\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)\n .find(\".input-name\")\n .val();\n var desc = $(this.$el)\n .find(\".input-description\")\n .val();\n if (type !== undefined && name) {\n await this.closeModal();\n this.view.c.addInput(\n name,\n type,\n desc,\n this.mousePosition\n );\n // reset fields\n this.$refs.inputType.resetChanges();\n $(this.$el)\n .find(\".input-name\")\n .val(\"\");\n $(this.$el)\n .find(\".input-description\")\n .val(\"\");\n } else {\n swal(\"Please complete all fields\", \"\", \"error\");\n return;\n }\n break;\n\n case \"output\":\n var name = $(this.$el)\n .find(\".output-name\")\n .val();\n var type = this.$refs.outputType.get();\n var desc = $(this.$el)\n .find(\".output-description\")\n .val();\n if (type !== undefined && name) {\n await this.closeModal();\n this.view.c.addOutput(\n name,\n type,\n desc,\n this.mousePosition\n );\n // reset fields\n this.$refs.outputType.resetChanges();\n $(this.$el)\n .find(\".output-name\")\n .val(\"\");\n $(this.$el)\n .find(\".output-description\")\n .val(\"\");\n } else {\n swal(\"Please complete all fields\", \"\", \"error\");\n return;\n }\n break;\n\n case \"metanode\":\n var name = $(this.$el)\n .find(\".metanode-name\")\n .val();\n var desc = $(this.$el)\n .find(\".metanode-description\")\n .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 await this.closeModal();\n this.view.c.addNewMetabox(name, json, this.mousePosition);\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(\n text,\n this.selectedType\n );\n this.$forceUpdate();\n //} catch (e) {\n // this.error = e;\n // swal(\"error searching packages\", e, \"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)\n .find(\".metanode-description\")\n .val(this.metanodeJSON.description);\n }\n };\n reader.readAsText(file);\n }\n }\n};\n</script>\n\n"]}, media: undefined });
|
|
64536
64631
|
|
|
64537
64632
|
};
|
|
64538
64633
|
/* scoped */
|
|
64539
|
-
const __vue_scope_id__$5 = "data-v-
|
|
64634
|
+
const __vue_scope_id__$5 = "data-v-095049aa";
|
|
64540
64635
|
/* module identifier */
|
|
64541
64636
|
const __vue_module_identifier__$5 = undefined;
|
|
64542
64637
|
/* functional template */
|
|
@@ -88840,13 +88935,14 @@ var script$d = {
|
|
|
88840
88935
|
};
|
|
88841
88936
|
|
|
88842
88937
|
// add the value to our select, and load it
|
|
88843
|
-
$(self.$el)
|
|
88844
|
-
|
|
88845
|
-
|
|
88846
|
-
|
|
88847
|
-
|
|
88848
|
-
|
|
88849
|
-
|
|
88938
|
+
// $(self.$el)
|
|
88939
|
+
// .find(".app-interface-select")
|
|
88940
|
+
// .append(
|
|
88941
|
+
// $("<option/>", {
|
|
88942
|
+
// value: name
|
|
88943
|
+
// }).append(name)
|
|
88944
|
+
// );
|
|
88945
|
+
self.$forceUpdate();
|
|
88850
88946
|
$(document).ready(() => {
|
|
88851
88947
|
$(self.$el)
|
|
88852
88948
|
.find(".app-interface-select")
|
|
@@ -88885,17 +88981,10 @@ var script$d = {
|
|
|
88885
88981
|
}).then(result => {
|
|
88886
88982
|
if (result.value) {
|
|
88887
88983
|
// set the interface back to first value
|
|
88888
|
-
$(this.$el)
|
|
88889
|
-
.find(
|
|
88890
|
-
".app-interface-select option[value='" + name + "']"
|
|
88891
|
-
)
|
|
88892
|
-
.remove();
|
|
88893
|
-
$(this.$el)
|
|
88894
|
-
.find(".app-interface-select")
|
|
88895
|
-
.change();
|
|
88896
88984
|
delete self.view.m.data.root.interface[name];
|
|
88897
88985
|
self.htmlCode.setValue("");
|
|
88898
88986
|
self.view.m.save();
|
|
88987
|
+
self.view.m.repaint();
|
|
88899
88988
|
self.view.runApp(self.getOptions());
|
|
88900
88989
|
}
|
|
88901
88990
|
});
|
|
@@ -89491,7 +89580,10 @@ var __vue_render__$d = function() {
|
|
|
89491
89580
|
) {
|
|
89492
89581
|
return _c(
|
|
89493
89582
|
"option",
|
|
89494
|
-
{
|
|
89583
|
+
{
|
|
89584
|
+
key: interfaceName,
|
|
89585
|
+
domProps: { value: interfaceName }
|
|
89586
|
+
},
|
|
89495
89587
|
[_vm._v(_vm._s(interfaceName))]
|
|
89496
89588
|
)
|
|
89497
89589
|
})
|
|
@@ -89769,7 +89861,7 @@ __vue_render__$d._withStripped = true;
|
|
|
89769
89861
|
/* style */
|
|
89770
89862
|
const __vue_inject_styles__$d = function (inject) {
|
|
89771
89863
|
if (!inject) return
|
|
89772
|
-
inject("data-v-2e37bd5a_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,\n.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,\n.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;\n /* Chrome/Safari */\n -moz-user-select: none;\n /* Firefox */\n -ms-user-select: none;\n /* 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,\n.btn-toggle-right-window:hover,\n.btn-toggle-left-window:focus,\n.btn-toggle-right-window:focus,\n.btn-toggle-left-window:active,\n.btn-toggle-right-window:active,\n.btn-toggle-left-window:active:hover,\n.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: 0.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,\n.graph-tab.active,\n.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,\n.main-navigation .nav-link.active,\n.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,\nbutton:focus {\n outline: none;\n box-shadow: none;\n}\n.btn-transparent,\n.btn-transparent:hover,\n.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,\n.save-app {\n margin-left: 5px;\n margin-right: 5px;\n}\n.btn-xs {\n padding: 0px 4px;\n font-size: 12px;\n}\n@media screen and (max-width: 1152px) {\n.code-panel {\n display: none;\n}\n.dragbar {\n display: none !important;\n}\n.application-container {\n width: 100%;\n}\n.run-options {\n display: none;\n}\n.application {\n height: 100%;\n}\n.navbar-right {\n display: none;\n}\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;;IAEA,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,uBAAA;AACA;AAEA;IACA,kBAAA;IACA,SAAA;IACA,WAAA;IACA,aAAA;AACA;AAEA;;IAEA,2BAAA;AACA;AAEA;IACA,WAAA;IACA,aAAA;IACA,gCAAA;IACA,WAAA;IACA,uBAAA;AACA;AAEA;IACA,yBAAA;IACA,kBAAA;IACA,sBAAA;IACA,YAAA;IACA,qBAAA;IACA,UAAA;IACA,oBAAA;IACA,iBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,2BAAA;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;;;;;;;;IAQA,yBAAA;IACA,oCAAA;IACA,gCAAA;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,iCAAA;AACA;AAEA;IACA,YAAA;IACA,wBAAA;IACA,YAAA;IACA,iCAAA;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,uBAAA;IACA,gBAAA;IACA,kBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iCAAA;IACA,yBAAA;IACA,yBAAA;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;;;IAGA,uBAAA;IACA,iCAAA;AACA;AAEA;IACA,yBAAA;IACA,oCAAA;AACA;AAEA;;;IAGA,mBAAA;IACA,iBAAA;IACA,gBAAA;IACA,kBAAA;IACA,kBAAA;IACA,QAAA;AACA;AAEA;;IAEA,aAAA;IACA,gBAAA;AACA;AAEA;;;IAGA,6BAAA;AACA;AAEA;IACA,kBAAA;IACA,YAAA;IACA,WAAA;IACA,6BAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,sBAAA;IACA,yBAAA;IACA,kCAAA;IACA,gBAAA;IACA,yBAAA;IACA,0BAAA;IACA,kBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;AACA;AAEA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,QAAA;IACA,SAAA;IACA,UAAA;IACA,eAAA;IACA,eAAA;IACA,UAAA;IACA,wBAAA;AACA;AAEA;IACA,gBAAA;IACA,gBAAA;AACA;AAEA;IACA,UAAA;IACA,UAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,4BAAA;AACA;AAEA;IACA,YAAA;IACA,iBAAA;AACA;AAEA;;IAEA,gBAAA;IACA,iBAAA;AACA;AAEA;IACA,gBAAA;IACA,eAAA;AACA;AAEA;AACA;QACA,aAAA;AACA;AAEA;QACA,wBAAA;AACA;AAEA;QACA,WAAA;AACA;AAEA;QACA,aAAA;AACA;AAEA;QACA,YAAA;AACA;AAEA;QACA,aAAA;AACA;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,\n.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,\n.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;\n /* Chrome/Safari */\n -moz-user-select: none;\n /* Firefox */\n -ms-user-select: none;\n /* 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,\n.btn-toggle-right-window:hover,\n.btn-toggle-left-window:focus,\n.btn-toggle-right-window:focus,\n.btn-toggle-left-window:active,\n.btn-toggle-right-window:active,\n.btn-toggle-left-window:active:hover,\n.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: 0.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,\n.graph-tab.active,\n.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,\n.main-navigation .nav-link.active,\n.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,\nbutton:focus {\n outline: none;\n box-shadow: none;\n}\n\n.btn-transparent,\n.btn-transparent:hover,\n.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.fileUpload {\n position: relative;\n overflow: hidden;\n margin: 10px;\n}\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.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\nbutton.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,\n.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\n@media screen and (max-width: 1152px) {\n .code-panel {\n display: none;\n }\n\n .dragbar {\n display: none !important;\n }\n\n .application-container {\n width: 100%;\n }\n\n .run-options {\n display: none;\n }\n\n .application {\n height: 100%;\n }\n\n .navbar-right {\n display: none;\n }\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: #0B6D80;\">\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\" :displayEvents=\"displayEvents\"></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\" v-html=\"getSelectedInterfaceCode()\"></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 <input class=\"form-control run-ressourcecaching mr-1 ml-3\" type=\"checkbox\">Ressource caching</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=\"addingBox\" :mousePosition=\"this.newBoxPosition\" @closed=\"onAddBoxClosed\"></add-node-vue>\n </div>\n</template>\n\n<script>\nimport _ from \"lodash-es\";\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 displayEvents: false,\n selectedInterface: null,\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)\n .find(\".dualbox-graph-left-section\")\n .css(\"margin-left\", \"0\");\n $(this)\n .find(\".dualbox-graph-main\")\n .addClass(\"left-panel-expanded\");\n $(this)\n .find(\".btn-toggle-left-window\")\n .data(\"expanded\", true)\n .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)\n .find(\".dualbox-graph-left-section\")\n .css(\"margin-left\", \"-465px\");\n $(this)\n .find(\".dualbox-graph-main\")\n .removeClass(\"left-panel-expanded\");\n $(this)\n .find(\".btn-toggle-left-window\")\n .data(\"expanded\", false)\n .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)\n .find(\".dualbox-graph-right-section\")\n .css(\"margin-right\", \"0\");\n $(this)\n .find(\".dualbox-graph-main\")\n .addClass(\"right-panel-expanded\");\n $(this)\n .find(\".btn-toggle-right-window\")\n .data(\"expanded\", true)\n .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)\n .find(\".dualbox-graph-right-section\")\n .css(\"margin-right\", \"-465px\");\n $(this)\n .find(\".dualbox-graph-main\")\n .removeClass(\"right-panel-expanded\");\n $(this)\n .find(\".btn-toggle-right-window\")\n .data(\"expanded\", false)\n .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)\n .find(\"a[data-toggle='tab']\")\n .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 } 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)\n .find(\"a[data-toggle='tab']\")\n .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)\n .find(\".dragbar\")\n .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(\n \"width\",\n $(\".db-editor-main\").width() - e.pageX - 5 + \"px\"\n );\n });\n });\n\n // prevent default behavior for ctrl+s / cmd+s\n $(document).keydown(function(event) {\n if ((event.ctrlKey || event.metaKey) && event.which == 83) {\n event.preventDefault();\n return false;\n }\n });\n },\n destroyed: function() {\n console.log(\"Graph vue destroyed\");\n $(\".ContextMenu\").remove();\n },\n methods: {\n getOptions: function() {\n return {\n profiler: $(this.$el)\n .find(\".run-profiler\")\n .is(\":checked\"),\n logLevel: $(this.$el)\n .find(\".run-loglevel\")\n .val(),\n options: {\n noVersionCheck: $(this.$el)\n .find(\".run-noversioncheck\")\n .is(\":checked\"),\n debug: {\n removeTryCatch: $(this.$el)\n .find(\".run-removetrycatch\")\n .is(\":checked\"),\n makeSynchrone: $(this.$el)\n .find(\".run-makesynchrone\")\n .is(\":checked\"),\n record: $(this.$el)\n .find(\".run-record\")\n .is(\":checked\"),\n ressourceCaching: $(this.$el)\n .find(\".run-ressourcecaching\")\n .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(\n $(this.$el).find(\".code-html\")[0],\n {\n lineNumbers: true,\n mode: \"htmlmixed\",\n lineWrapping: true,\n extraKeys: {\n \"Ctrl-S\": () => {\n this.saveInterfaceElement();\n this.runApp();\n },\n \"Cmd-S\": () => {\n this.saveInterfaceElement();\n this.runApp();\n }\n }\n }\n );\n }\n if (!this.cssCode) {\n this.cssCode = CodeMirror.fromTextArea(\n $(this.$el).find(\".code-css\")[0],\n {\n lineNumbers: true,\n mode: \"css\",\n lineWrapping: true,\n extraKeys: {\n \"Ctrl-S\": () => {\n // save css code into app\n this.view.m.data.root.css = this.cssCode.getValue();\n this.view.m.save();\n this.runApp();\n },\n \"Cmd-S\": () => {\n // save css code into app\n this.view.m.data.root.css = this.cssCode.getValue();\n this.view.m.save();\n this.runApp();\n }\n }\n }\n );\n }\n\n this.htmlCode.setValue(this.getSelectedInterfaceCode());\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/>\", {\n type: \"file\",\n class: \"upload\",\n accept: \".json\"\n });\n input.change(function(e) {\n // if we're not here, go to 1st tab\n $(\"a[data-toggle='tab'][href='#editor-graph-tab']\").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 } 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], {\n type: \"application/octet-stream\"\n });\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 console.log('opening addbox modal');\n this.addingBox = true;\n this.newBoxPosition = this.getCurrentMousePosition(e);\n this.$forceUpdate();\n },\n onAddBoxClosed: function() {\n console.log('closing modal');\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\n .loadPackages(json)\n .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 (\n !value && \"You need to write something!\"\n );\n }\n });\n\n self.view.c.addNewMetabox(name, json);\n })\n .catch(err => {\n console.error(err);\n });\n };\n reader.readAsText(file);\n }\n },\n\n getInterfacesNames: function() {\n return _.keys(\n _.get(this.view.m, [\"data\", \"root\", \"interface\"]) || {}\n );\n },\n\n getInterfaceCode: function(uiName) {\n var itf = this.view.m.data.root.interface;\n var htmlString = htmltool.json2html(itf[uiName]);\n var prettyString = htmltool.htmlPrettyPrint(htmlString);\n return prettyString;\n },\n\n getSelectedInterfaceCode: function() {\n return this.selectedInterface\n ? this.getInterfaceCode(this.selectedInterface)\n : \"\";\n },\n\n selectInterface: function(e) {\n // Load the interface HTML when selected\n var uiName = $(e.target).val();\n this.selectedInterface = uiName;\n if (uiName !== \"\" && uiName !== \"Load UI...\") {\n var prettyString = this.getInterfaceCode(uiName);\n this.htmlCode.setValue(prettyString);\n } else {\n this.htmlCode.setValue(\"\");\n }\n },\n saveInterfaceElement: function(e) {\n var currentInterface = $(this.$el)\n .find(\".app-interface-select\")\n .val();\n if (currentInterface !== \"\") {\n var currentHTML = this.htmlCode.getValue();\n\n // save html code into app\n this.view.m.data.root.interface[\n currentInterface\n ] = htmltool.html2json(currentHTML);\n }\n\n // save css code into app\n this.view.m.data.root.css = this.cssCode.getValue();\n this.view.m.save();\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 })\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 ])\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(\n \"Interface \" + name + \" already exists!\"\n );\n return false;\n } else {\n var style = {};\n var cssPositionClass = \"dualbox-panel-\" + position;\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\"\n ? \"dualbox-viewer dualbox-mobile-h60\"\n : \"dualbox-controls\",\n \"dualbox-panel\",\n cssPositionClass\n ]\n },\n children: []\n };\n\n // add the value to our select, and load it\n $(self.$el)\n .find(\".app-interface-select\")\n .append(\n $(\"<option/>\", {\n value: name\n }).append(name)\n );\n $(document).ready(() => {\n $(self.$el)\n .find(\".app-interface-select\")\n .val(name)\n .change();\n\n // set it into the editor\n var htmlString = htmltool.json2html(\n appInterface[name]\n );\n var prettyString = htmltool.htmlPrettyPrint(\n htmlString\n );\n this.htmlCode.setValue(prettyString);\n self.updateCode();\n });\n\n self.view.m.save();\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)\n .find(\n \".app-interface-select option[value='\" + name + \"']\"\n )\n .remove();\n $(this.$el)\n .find(\".app-interface-select\")\n .change();\n delete self.view.m.data.root.interface[name];\n self.htmlCode.setValue(\"\");\n self.view.m.save();\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:\n 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 } else {\n self.view.m.data.root.interface[name].description =\n result.value;\n }\n });\n },\n toggleLeftWindow: function(e) {\n var expanded = $(e.target)\n .closest(\"button\")\n .data(\"expanded\");\n if (expanded) {\n $(this.$el).trigger(\"shrinkSettings\");\n } else {\n $(this.$el).trigger(\"expandSettings\");\n }\n },\n toggleRightWindow: function(e) {\n var expanded = $(e.target)\n .closest(\"button\")\n .data(\"expanded\");\n if (expanded) {\n $(this.$el).trigger(\"shrinkDebug\");\n } else {\n $(this.$el).trigger(\"expandDebug\");\n }\n },\n\n showEvents: function(e) {\n //this.view.setEventsVisibility( $(e.target).is(':checked') );\n this.displayEvents = $(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: async function(e) {\n await 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 } 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 });
|
|
89864
|
+
inject("data-v-4f46e4b2_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,\n.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,\n.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;\n /* Chrome/Safari */\n -moz-user-select: none;\n /* Firefox */\n -ms-user-select: none;\n /* 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,\n.btn-toggle-right-window:hover,\n.btn-toggle-left-window:focus,\n.btn-toggle-right-window:focus,\n.btn-toggle-left-window:active,\n.btn-toggle-right-window:active,\n.btn-toggle-left-window:active:hover,\n.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: 0.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,\n.graph-tab.active,\n.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,\n.main-navigation .nav-link.active,\n.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,\nbutton:focus {\n outline: none;\n box-shadow: none;\n}\n.btn-transparent,\n.btn-transparent:hover,\n.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,\n.save-app {\n margin-left: 5px;\n margin-right: 5px;\n}\n.btn-xs {\n padding: 0px 4px;\n font-size: 12px;\n}\n@media screen and (max-width: 1152px) {\n.code-panel {\n display: none;\n}\n.dragbar {\n display: none !important;\n}\n.application-container {\n width: 100%;\n}\n.run-options {\n display: none;\n}\n.application {\n height: 100%;\n}\n.navbar-right {\n display: none;\n}\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;;IAEA,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,uBAAA;AACA;AAEA;IACA,kBAAA;IACA,SAAA;IACA,WAAA;IACA,aAAA;AACA;AAEA;;IAEA,2BAAA;AACA;AAEA;IACA,WAAA;IACA,aAAA;IACA,gCAAA;IACA,WAAA;IACA,uBAAA;AACA;AAEA;IACA,yBAAA;IACA,kBAAA;IACA,sBAAA;IACA,YAAA;IACA,qBAAA;IACA,UAAA;IACA,oBAAA;IACA,iBAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,2BAAA;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;;;;;;;;IAQA,yBAAA;IACA,oCAAA;IACA,gCAAA;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,iCAAA;AACA;AAEA;IACA,YAAA;IACA,wBAAA;IACA,YAAA;IACA,iCAAA;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,uBAAA;IACA,gBAAA;IACA,kBAAA;AACA;AAEA;IACA,eAAA;AACA;AAEA;IACA,iCAAA;IACA,yBAAA;IACA,yBAAA;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;;;IAGA,uBAAA;IACA,iCAAA;AACA;AAEA;IACA,yBAAA;IACA,oCAAA;AACA;AAEA;;;IAGA,mBAAA;IACA,iBAAA;IACA,gBAAA;IACA,kBAAA;IACA,kBAAA;IACA,QAAA;AACA;AAEA;;IAEA,aAAA;IACA,gBAAA;AACA;AAEA;;;IAGA,6BAAA;AACA;AAEA;IACA,kBAAA;IACA,YAAA;IACA,WAAA;IACA,6BAAA;IACA,WAAA;IACA,YAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,sBAAA;IACA,yBAAA;IACA,kCAAA;IACA,gBAAA;IACA,yBAAA;IACA,0BAAA;IACA,kBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;IACA,yBAAA;AACA;AAEA;AACA;AAEA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,YAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,QAAA;IACA,SAAA;IACA,UAAA;IACA,eAAA;IACA,eAAA;IACA,UAAA;IACA,wBAAA;AACA;AAEA;IACA,gBAAA;IACA,gBAAA;AACA;AAEA;IACA,UAAA;IACA,UAAA;AACA;AAEA;IACA,kBAAA;IACA,QAAA;IACA,4BAAA;AACA;AAEA;IACA,YAAA;IACA,iBAAA;AACA;AAEA;;IAEA,gBAAA;IACA,iBAAA;AACA;AAEA;IACA,gBAAA;IACA,eAAA;AACA;AAEA;AACA;QACA,aAAA;AACA;AAEA;QACA,wBAAA;AACA;AAEA;QACA,WAAA;AACA;AAEA;QACA,aAAA;AACA;AAEA;QACA,YAAA;AACA;AAEA;QACA,aAAA;AACA;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,\n.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,\n.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;\n /* Chrome/Safari */\n -moz-user-select: none;\n /* Firefox */\n -ms-user-select: none;\n /* 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,\n.btn-toggle-right-window:hover,\n.btn-toggle-left-window:focus,\n.btn-toggle-right-window:focus,\n.btn-toggle-left-window:active,\n.btn-toggle-right-window:active,\n.btn-toggle-left-window:active:hover,\n.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: 0.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,\n.graph-tab.active,\n.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,\n.main-navigation .nav-link.active,\n.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,\nbutton:focus {\n outline: none;\n box-shadow: none;\n}\n\n.btn-transparent,\n.btn-transparent:hover,\n.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.fileUpload {\n position: relative;\n overflow: hidden;\n margin: 10px;\n}\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.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\nbutton.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,\n.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\n@media screen and (max-width: 1152px) {\n .code-panel {\n display: none;\n }\n\n .dragbar {\n display: none !important;\n }\n\n .application-container {\n width: 100%;\n }\n\n .run-options {\n display: none;\n }\n\n .application {\n height: 100%;\n }\n\n .navbar-right {\n display: none;\n }\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: #0B6D80;\">\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\" :displayEvents=\"displayEvents\"></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()\" :key=\"interfaceName\" :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\" v-html=\"getSelectedInterfaceCode()\"></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 <input class=\"form-control run-ressourcecaching mr-1 ml-3\" type=\"checkbox\">Ressource caching</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=\"addingBox\" :mousePosition=\"this.newBoxPosition\" @closed=\"onAddBoxClosed\"></add-node-vue>\n </div>\n</template>\n\n<script>\nimport _ from \"lodash-es\";\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 displayEvents: false,\n selectedInterface: null,\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)\n .find(\".dualbox-graph-left-section\")\n .css(\"margin-left\", \"0\");\n $(this)\n .find(\".dualbox-graph-main\")\n .addClass(\"left-panel-expanded\");\n $(this)\n .find(\".btn-toggle-left-window\")\n .data(\"expanded\", true)\n .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)\n .find(\".dualbox-graph-left-section\")\n .css(\"margin-left\", \"-465px\");\n $(this)\n .find(\".dualbox-graph-main\")\n .removeClass(\"left-panel-expanded\");\n $(this)\n .find(\".btn-toggle-left-window\")\n .data(\"expanded\", false)\n .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)\n .find(\".dualbox-graph-right-section\")\n .css(\"margin-right\", \"0\");\n $(this)\n .find(\".dualbox-graph-main\")\n .addClass(\"right-panel-expanded\");\n $(this)\n .find(\".btn-toggle-right-window\")\n .data(\"expanded\", true)\n .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)\n .find(\".dualbox-graph-right-section\")\n .css(\"margin-right\", \"-465px\");\n $(this)\n .find(\".dualbox-graph-main\")\n .removeClass(\"right-panel-expanded\");\n $(this)\n .find(\".btn-toggle-right-window\")\n .data(\"expanded\", false)\n .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)\n .find(\"a[data-toggle='tab']\")\n .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 } 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)\n .find(\"a[data-toggle='tab']\")\n .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)\n .find(\".dragbar\")\n .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(\n \"width\",\n $(\".db-editor-main\").width() - e.pageX - 5 + \"px\"\n );\n });\n });\n\n // prevent default behavior for ctrl+s / cmd+s\n $(document).keydown(function(event) {\n if ((event.ctrlKey || event.metaKey) && event.which == 83) {\n event.preventDefault();\n return false;\n }\n });\n },\n destroyed: function() {\n console.log(\"Graph vue destroyed\");\n $(\".ContextMenu\").remove();\n },\n methods: {\n getOptions: function() {\n return {\n profiler: $(this.$el)\n .find(\".run-profiler\")\n .is(\":checked\"),\n logLevel: $(this.$el)\n .find(\".run-loglevel\")\n .val(),\n options: {\n noVersionCheck: $(this.$el)\n .find(\".run-noversioncheck\")\n .is(\":checked\"),\n debug: {\n removeTryCatch: $(this.$el)\n .find(\".run-removetrycatch\")\n .is(\":checked\"),\n makeSynchrone: $(this.$el)\n .find(\".run-makesynchrone\")\n .is(\":checked\"),\n record: $(this.$el)\n .find(\".run-record\")\n .is(\":checked\"),\n ressourceCaching: $(this.$el)\n .find(\".run-ressourcecaching\")\n .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(\n $(this.$el).find(\".code-html\")[0],\n {\n lineNumbers: true,\n mode: \"htmlmixed\",\n lineWrapping: true,\n extraKeys: {\n \"Ctrl-S\": () => {\n this.saveInterfaceElement();\n this.runApp();\n },\n \"Cmd-S\": () => {\n this.saveInterfaceElement();\n this.runApp();\n }\n }\n }\n );\n }\n if (!this.cssCode) {\n this.cssCode = CodeMirror.fromTextArea(\n $(this.$el).find(\".code-css\")[0],\n {\n lineNumbers: true,\n mode: \"css\",\n lineWrapping: true,\n extraKeys: {\n \"Ctrl-S\": () => {\n // save css code into app\n this.view.m.data.root.css = this.cssCode.getValue();\n this.view.m.save();\n this.runApp();\n },\n \"Cmd-S\": () => {\n // save css code into app\n this.view.m.data.root.css = this.cssCode.getValue();\n this.view.m.save();\n this.runApp();\n }\n }\n }\n );\n }\n\n this.htmlCode.setValue(this.getSelectedInterfaceCode());\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/>\", {\n type: \"file\",\n class: \"upload\",\n accept: \".json\"\n });\n input.change(function(e) {\n // if we're not here, go to 1st tab\n $(\"a[data-toggle='tab'][href='#editor-graph-tab']\").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 } 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], {\n type: \"application/octet-stream\"\n });\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 console.log('opening addbox modal');\n this.addingBox = true;\n this.newBoxPosition = this.getCurrentMousePosition(e);\n this.$forceUpdate();\n },\n onAddBoxClosed: function() {\n console.log('closing modal');\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\n .loadPackages(json)\n .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 (\n !value && \"You need to write something!\"\n );\n }\n });\n\n self.view.c.addNewMetabox(name, json);\n })\n .catch(err => {\n console.error(err);\n });\n };\n reader.readAsText(file);\n }\n },\n\n getInterfacesNames: function() {\n return _.keys(\n _.get(this.view.m, [\"data\", \"root\", \"interface\"]) || {}\n );\n },\n\n getInterfaceCode: function(uiName) {\n var itf = this.view.m.data.root.interface;\n var htmlString = htmltool.json2html(itf[uiName]);\n var prettyString = htmltool.htmlPrettyPrint(htmlString);\n return prettyString;\n },\n\n getSelectedInterfaceCode: function() {\n return this.selectedInterface\n ? this.getInterfaceCode(this.selectedInterface)\n : \"\";\n },\n\n selectInterface: function(e) {\n // Load the interface HTML when selected\n var uiName = $(e.target).val();\n this.selectedInterface = uiName;\n if (uiName !== \"\" && uiName !== \"Load UI...\") {\n var prettyString = this.getInterfaceCode(uiName);\n this.htmlCode.setValue(prettyString);\n } else {\n this.htmlCode.setValue(\"\");\n }\n },\n saveInterfaceElement: function(e) {\n var currentInterface = $(this.$el)\n .find(\".app-interface-select\")\n .val();\n if (currentInterface !== \"\") {\n var currentHTML = this.htmlCode.getValue();\n\n // save html code into app\n this.view.m.data.root.interface[\n currentInterface\n ] = htmltool.html2json(currentHTML);\n }\n\n // save css code into app\n this.view.m.data.root.css = this.cssCode.getValue();\n this.view.m.save();\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 })\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 ])\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(\n \"Interface \" + name + \" already exists!\"\n );\n return false;\n } else {\n var style = {};\n var cssPositionClass = \"dualbox-panel-\" + position;\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\"\n ? \"dualbox-viewer dualbox-mobile-h60\"\n : \"dualbox-controls\",\n \"dualbox-panel\",\n cssPositionClass\n ]\n },\n children: []\n };\n\n // add the value to our select, and load it\n // $(self.$el)\n // .find(\".app-interface-select\")\n // .append(\n // $(\"<option/>\", {\n // value: name\n // }).append(name)\n // );\n self.$forceUpdate();\n $(document).ready(() => {\n $(self.$el)\n .find(\".app-interface-select\")\n .val(name)\n .change();\n\n // set it into the editor\n var htmlString = htmltool.json2html(\n appInterface[name]\n );\n var prettyString = htmltool.htmlPrettyPrint(\n htmlString\n );\n this.htmlCode.setValue(prettyString);\n self.updateCode();\n });\n\n self.view.m.save();\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 delete self.view.m.data.root.interface[name];\n self.htmlCode.setValue(\"\");\n self.view.m.save();\n self.view.m.repaint();\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:\n 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 } else {\n self.view.m.data.root.interface[name].description =\n result.value;\n }\n });\n },\n toggleLeftWindow: function(e) {\n var expanded = $(e.target)\n .closest(\"button\")\n .data(\"expanded\");\n if (expanded) {\n $(this.$el).trigger(\"shrinkSettings\");\n } else {\n $(this.$el).trigger(\"expandSettings\");\n }\n },\n toggleRightWindow: function(e) {\n var expanded = $(e.target)\n .closest(\"button\")\n .data(\"expanded\");\n if (expanded) {\n $(this.$el).trigger(\"shrinkDebug\");\n } else {\n $(this.$el).trigger(\"expandDebug\");\n }\n },\n\n showEvents: function(e) {\n //this.view.setEventsVisibility( $(e.target).is(':checked') );\n this.displayEvents = $(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: async function(e) {\n await 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 } 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 });
|
|
89773
89865
|
|
|
89774
89866
|
};
|
|
89775
89867
|
/* scoped */
|
|
@@ -91361,16 +91453,11 @@ class GraphController {
|
|
|
91361
91453
|
var clipboard = await this.getClipboard();
|
|
91362
91454
|
try {
|
|
91363
91455
|
var json = JSON.parse(clipboard);
|
|
91364
|
-
|
|
91365
|
-
|
|
91366
|
-
|
|
91367
|
-
|
|
91368
|
-
|
|
91369
|
-
await this.e.loadPackages(json);
|
|
91370
|
-
this.m.paste(json);
|
|
91371
|
-
await this.v.repaint();
|
|
91372
|
-
}
|
|
91373
|
-
}]);
|
|
91456
|
+
await this.e.loadPackages(json);
|
|
91457
|
+
let validPaste = this.m.paste(json);
|
|
91458
|
+
if (validPaste) {
|
|
91459
|
+
await this.v.repaint();
|
|
91460
|
+
}
|
|
91374
91461
|
} catch (e) {
|
|
91375
91462
|
sweetalert2_all.fire("Invalid content for copy/paste", "You must first copy boxes from Dualbox", "error");
|
|
91376
91463
|
return;
|
|
@@ -108186,6 +108273,281 @@ var defaultApp = {
|
|
|
108186
108273
|
}
|
|
108187
108274
|
};
|
|
108188
108275
|
|
|
108276
|
+
const FuzzySet = function(arr, useLevenshtein, gramSizeLower, gramSizeUpper) {
|
|
108277
|
+
var fuzzyset = {
|
|
108278
|
+
|
|
108279
|
+
};
|
|
108280
|
+
|
|
108281
|
+
// default options
|
|
108282
|
+
arr = arr || [];
|
|
108283
|
+
fuzzyset.gramSizeLower = gramSizeLower || 2;
|
|
108284
|
+
fuzzyset.gramSizeUpper = gramSizeUpper || 3;
|
|
108285
|
+
fuzzyset.useLevenshtein = (typeof useLevenshtein !== 'boolean') ? true : useLevenshtein;
|
|
108286
|
+
|
|
108287
|
+
// define all the object functions and attributes
|
|
108288
|
+
fuzzyset.exactSet = {};
|
|
108289
|
+
fuzzyset.matchDict = {};
|
|
108290
|
+
fuzzyset.items = {};
|
|
108291
|
+
|
|
108292
|
+
// helper functions
|
|
108293
|
+
var levenshtein = function(str1, str2) {
|
|
108294
|
+
var current = [], prev, value;
|
|
108295
|
+
|
|
108296
|
+
for (var i = 0; i <= str2.length; i++)
|
|
108297
|
+
for (var j = 0; j <= str1.length; j++) {
|
|
108298
|
+
if (i && j)
|
|
108299
|
+
if (str1.charAt(j - 1) === str2.charAt(i - 1))
|
|
108300
|
+
value = prev;
|
|
108301
|
+
else
|
|
108302
|
+
value = Math.min(current[j], current[j - 1], prev) + 1;
|
|
108303
|
+
else
|
|
108304
|
+
value = i + j;
|
|
108305
|
+
|
|
108306
|
+
prev = current[j];
|
|
108307
|
+
current[j] = value;
|
|
108308
|
+
}
|
|
108309
|
+
|
|
108310
|
+
return current.pop();
|
|
108311
|
+
};
|
|
108312
|
+
|
|
108313
|
+
// return an edit distance from 0 to 1
|
|
108314
|
+
var _distance = function(str1, str2) {
|
|
108315
|
+
if (str1 === null && str2 === null) throw 'Trying to compare two null values';
|
|
108316
|
+
if (str1 === null || str2 === null) return 0;
|
|
108317
|
+
str1 = String(str1); str2 = String(str2);
|
|
108318
|
+
|
|
108319
|
+
var distance = levenshtein(str1, str2);
|
|
108320
|
+
if (str1.length > str2.length) {
|
|
108321
|
+
return 1 - distance / str1.length;
|
|
108322
|
+
} else {
|
|
108323
|
+
return 1 - distance / str2.length;
|
|
108324
|
+
}
|
|
108325
|
+
};
|
|
108326
|
+
var _nonWordRe = /[^a-zA-Z0-9\u00C0-\u00FF, ]+/g;
|
|
108327
|
+
|
|
108328
|
+
var _iterateGrams = function(value, gramSize) {
|
|
108329
|
+
gramSize = gramSize || 2;
|
|
108330
|
+
var simplified = '-' + value.toLowerCase().replace(_nonWordRe, '') + '-',
|
|
108331
|
+
lenDiff = gramSize - simplified.length,
|
|
108332
|
+
results = [];
|
|
108333
|
+
if (lenDiff > 0) {
|
|
108334
|
+
for (var i = 0; i < lenDiff; ++i) {
|
|
108335
|
+
simplified += '-';
|
|
108336
|
+
}
|
|
108337
|
+
}
|
|
108338
|
+
for (var i = 0; i < simplified.length - gramSize + 1; ++i) {
|
|
108339
|
+
results.push(simplified.slice(i, i + gramSize));
|
|
108340
|
+
}
|
|
108341
|
+
return results;
|
|
108342
|
+
};
|
|
108343
|
+
|
|
108344
|
+
var _gramCounter = function(value, gramSize) {
|
|
108345
|
+
// return an object where key=gram, value=number of occurrences
|
|
108346
|
+
gramSize = gramSize || 2;
|
|
108347
|
+
var result = {},
|
|
108348
|
+
grams = _iterateGrams(value, gramSize),
|
|
108349
|
+
i = 0;
|
|
108350
|
+
for (i; i < grams.length; ++i) {
|
|
108351
|
+
if (grams[i] in result) {
|
|
108352
|
+
result[grams[i]] += 1;
|
|
108353
|
+
} else {
|
|
108354
|
+
result[grams[i]] = 1;
|
|
108355
|
+
}
|
|
108356
|
+
}
|
|
108357
|
+
return result;
|
|
108358
|
+
};
|
|
108359
|
+
|
|
108360
|
+
// the main functions
|
|
108361
|
+
fuzzyset.get = function(value, defaultValue, minMatchScore) {
|
|
108362
|
+
// check for value in set, returning defaultValue or null if none found
|
|
108363
|
+
if (minMatchScore === undefined) {
|
|
108364
|
+
minMatchScore = .33;
|
|
108365
|
+
}
|
|
108366
|
+
var result = this._get(value, minMatchScore);
|
|
108367
|
+
if (!result && typeof defaultValue !== 'undefined') {
|
|
108368
|
+
return defaultValue;
|
|
108369
|
+
}
|
|
108370
|
+
return result;
|
|
108371
|
+
};
|
|
108372
|
+
|
|
108373
|
+
fuzzyset._get = function(value, minMatchScore) {
|
|
108374
|
+
var results = [];
|
|
108375
|
+
// start with high gram size and if there are no results, go to lower gram sizes
|
|
108376
|
+
for (var gramSize = this.gramSizeUpper; gramSize >= this.gramSizeLower; --gramSize) {
|
|
108377
|
+
results = this.__get(value, gramSize, minMatchScore);
|
|
108378
|
+
if (results && results.length > 0) {
|
|
108379
|
+
return results;
|
|
108380
|
+
}
|
|
108381
|
+
}
|
|
108382
|
+
return null;
|
|
108383
|
+
};
|
|
108384
|
+
|
|
108385
|
+
fuzzyset.__get = function(value, gramSize, minMatchScore) {
|
|
108386
|
+
var normalizedValue = this._normalizeStr(value),
|
|
108387
|
+
matches = {},
|
|
108388
|
+
gramCounts = _gramCounter(normalizedValue, gramSize),
|
|
108389
|
+
items = this.items[gramSize],
|
|
108390
|
+
sumOfSquareGramCounts = 0,
|
|
108391
|
+
gram,
|
|
108392
|
+
gramCount,
|
|
108393
|
+
i,
|
|
108394
|
+
index,
|
|
108395
|
+
otherGramCount;
|
|
108396
|
+
|
|
108397
|
+
for (gram in gramCounts) {
|
|
108398
|
+
gramCount = gramCounts[gram];
|
|
108399
|
+
sumOfSquareGramCounts += Math.pow(gramCount, 2);
|
|
108400
|
+
if (gram in this.matchDict) {
|
|
108401
|
+
for (i = 0; i < this.matchDict[gram].length; ++i) {
|
|
108402
|
+
index = this.matchDict[gram][i][0];
|
|
108403
|
+
otherGramCount = this.matchDict[gram][i][1];
|
|
108404
|
+
if (index in matches) {
|
|
108405
|
+
matches[index] += gramCount * otherGramCount;
|
|
108406
|
+
} else {
|
|
108407
|
+
matches[index] = gramCount * otherGramCount;
|
|
108408
|
+
}
|
|
108409
|
+
}
|
|
108410
|
+
}
|
|
108411
|
+
}
|
|
108412
|
+
|
|
108413
|
+
function isEmptyObject(obj) {
|
|
108414
|
+
for(var prop in obj) {
|
|
108415
|
+
if(obj.hasOwnProperty(prop))
|
|
108416
|
+
return false;
|
|
108417
|
+
}
|
|
108418
|
+
return true;
|
|
108419
|
+
}
|
|
108420
|
+
|
|
108421
|
+
if (isEmptyObject(matches)) {
|
|
108422
|
+
return null;
|
|
108423
|
+
}
|
|
108424
|
+
|
|
108425
|
+
var vectorNormal = Math.sqrt(sumOfSquareGramCounts),
|
|
108426
|
+
results = [],
|
|
108427
|
+
matchScore;
|
|
108428
|
+
// build a results list of [score, str]
|
|
108429
|
+
for (var matchIndex in matches) {
|
|
108430
|
+
matchScore = matches[matchIndex];
|
|
108431
|
+
results.push([matchScore / (vectorNormal * items[matchIndex][0]), items[matchIndex][1]]);
|
|
108432
|
+
}
|
|
108433
|
+
var sortDescending = function(a, b) {
|
|
108434
|
+
if (a[0] < b[0]) {
|
|
108435
|
+
return 1;
|
|
108436
|
+
} else if (a[0] > b[0]) {
|
|
108437
|
+
return -1;
|
|
108438
|
+
} else {
|
|
108439
|
+
return 0;
|
|
108440
|
+
}
|
|
108441
|
+
};
|
|
108442
|
+
results.sort(sortDescending);
|
|
108443
|
+
if (this.useLevenshtein) {
|
|
108444
|
+
var newResults = [],
|
|
108445
|
+
endIndex = Math.min(50, results.length);
|
|
108446
|
+
// truncate somewhat arbitrarily to 50
|
|
108447
|
+
for (var i = 0; i < endIndex; ++i) {
|
|
108448
|
+
newResults.push([_distance(results[i][1], normalizedValue), results[i][1]]);
|
|
108449
|
+
}
|
|
108450
|
+
results = newResults;
|
|
108451
|
+
results.sort(sortDescending);
|
|
108452
|
+
}
|
|
108453
|
+
newResults = [];
|
|
108454
|
+
results.forEach(function(scoreWordPair) {
|
|
108455
|
+
if (scoreWordPair[0] >= minMatchScore) {
|
|
108456
|
+
newResults.push([scoreWordPair[0], this.exactSet[scoreWordPair[1]]]);
|
|
108457
|
+
}
|
|
108458
|
+
}.bind(this));
|
|
108459
|
+
return newResults;
|
|
108460
|
+
};
|
|
108461
|
+
|
|
108462
|
+
fuzzyset.add = function(value) {
|
|
108463
|
+
var normalizedValue = this._normalizeStr(value);
|
|
108464
|
+
if (normalizedValue in this.exactSet) {
|
|
108465
|
+
return false;
|
|
108466
|
+
}
|
|
108467
|
+
|
|
108468
|
+
var i = this.gramSizeLower;
|
|
108469
|
+
for (i; i < this.gramSizeUpper + 1; ++i) {
|
|
108470
|
+
this._add(value, i);
|
|
108471
|
+
}
|
|
108472
|
+
};
|
|
108473
|
+
|
|
108474
|
+
fuzzyset._add = function(value, gramSize) {
|
|
108475
|
+
var normalizedValue = this._normalizeStr(value),
|
|
108476
|
+
items = this.items[gramSize] || [],
|
|
108477
|
+
index = items.length;
|
|
108478
|
+
|
|
108479
|
+
items.push(0);
|
|
108480
|
+
var gramCounts = _gramCounter(normalizedValue, gramSize),
|
|
108481
|
+
sumOfSquareGramCounts = 0,
|
|
108482
|
+
gram, gramCount;
|
|
108483
|
+
for (gram in gramCounts) {
|
|
108484
|
+
gramCount = gramCounts[gram];
|
|
108485
|
+
sumOfSquareGramCounts += Math.pow(gramCount, 2);
|
|
108486
|
+
if (gram in this.matchDict) {
|
|
108487
|
+
this.matchDict[gram].push([index, gramCount]);
|
|
108488
|
+
} else {
|
|
108489
|
+
this.matchDict[gram] = [[index, gramCount]];
|
|
108490
|
+
}
|
|
108491
|
+
}
|
|
108492
|
+
var vectorNormal = Math.sqrt(sumOfSquareGramCounts);
|
|
108493
|
+
items[index] = [vectorNormal, normalizedValue];
|
|
108494
|
+
this.items[gramSize] = items;
|
|
108495
|
+
this.exactSet[normalizedValue] = value;
|
|
108496
|
+
};
|
|
108497
|
+
|
|
108498
|
+
fuzzyset._normalizeStr = function(str) {
|
|
108499
|
+
if (Object.prototype.toString.call(str) !== '[object String]') throw 'Must use a string as argument to FuzzySet functions';
|
|
108500
|
+
return str.toLowerCase();
|
|
108501
|
+
};
|
|
108502
|
+
|
|
108503
|
+
// return length of items in set
|
|
108504
|
+
fuzzyset.length = function() {
|
|
108505
|
+
var count = 0,
|
|
108506
|
+
prop;
|
|
108507
|
+
for (prop in this.exactSet) {
|
|
108508
|
+
if (this.exactSet.hasOwnProperty(prop)) {
|
|
108509
|
+
count += 1;
|
|
108510
|
+
}
|
|
108511
|
+
}
|
|
108512
|
+
return count;
|
|
108513
|
+
};
|
|
108514
|
+
|
|
108515
|
+
// return is set is empty
|
|
108516
|
+
fuzzyset.isEmpty = function() {
|
|
108517
|
+
for (var prop in this.exactSet) {
|
|
108518
|
+
if (this.exactSet.hasOwnProperty(prop)) {
|
|
108519
|
+
return false;
|
|
108520
|
+
}
|
|
108521
|
+
}
|
|
108522
|
+
return true;
|
|
108523
|
+
};
|
|
108524
|
+
|
|
108525
|
+
// return list of values loaded into set
|
|
108526
|
+
fuzzyset.values = function() {
|
|
108527
|
+
var values = [],
|
|
108528
|
+
prop;
|
|
108529
|
+
for (prop in this.exactSet) {
|
|
108530
|
+
if (this.exactSet.hasOwnProperty(prop)) {
|
|
108531
|
+
values.push(this.exactSet[prop]);
|
|
108532
|
+
}
|
|
108533
|
+
}
|
|
108534
|
+
return values;
|
|
108535
|
+
};
|
|
108536
|
+
|
|
108537
|
+
|
|
108538
|
+
// initialization
|
|
108539
|
+
var i = fuzzyset.gramSizeLower;
|
|
108540
|
+
for (i; i < fuzzyset.gramSizeUpper + 1; ++i) {
|
|
108541
|
+
fuzzyset.items[i] = [];
|
|
108542
|
+
}
|
|
108543
|
+
// add all the items to the set
|
|
108544
|
+
for (i = 0; i < arr.length; ++i) {
|
|
108545
|
+
fuzzyset.add(arr[i]);
|
|
108546
|
+
}
|
|
108547
|
+
|
|
108548
|
+
return fuzzyset;
|
|
108549
|
+
};
|
|
108550
|
+
|
|
108189
108551
|
//import fa from '@dualbox/dualbox-lib-font-awesome';
|
|
108190
108552
|
//console.log('FontAwesome loaded: ' + fa);
|
|
108191
108553
|
// Display dependencies
|
|
@@ -108216,8 +108578,15 @@ class DualboxEditor {
|
|
|
108216
108578
|
this.v.c = this.m.c = this.c;
|
|
108217
108579
|
this.c.v = this.m.v = this.v;
|
|
108218
108580
|
|
|
108219
|
-
//
|
|
108581
|
+
// packages can be passed at init time or searched dynamically
|
|
108220
108582
|
this.packages = {};
|
|
108583
|
+
if (attrs.packages) {
|
|
108584
|
+
for (let p of Object.values(attrs.packages)) {
|
|
108585
|
+
this.packages[p.name] = p;
|
|
108586
|
+
}
|
|
108587
|
+
}
|
|
108588
|
+
this.allPackagesFetched = !!attrs.packages; // assume ALL packages are passed if this argument exists
|
|
108589
|
+
|
|
108221
108590
|
this.DualBox = null; // local dualbox, for editor use
|
|
108222
108591
|
|
|
108223
108592
|
this.appDescription = attrs.appDescription || null;
|
|
@@ -108226,31 +108595,137 @@ class DualboxEditor {
|
|
|
108226
108595
|
// the function to search for modules
|
|
108227
108596
|
// attr.search signature: search( text, cb )
|
|
108228
108597
|
// callback signature: cb( err, packages ), packages is an array of package.json
|
|
108229
|
-
this.search = (text, type) => {
|
|
108230
|
-
|
|
108231
|
-
|
|
108232
|
-
|
|
108233
|
-
|
|
108234
|
-
|
|
108235
|
-
|
|
108236
|
-
|
|
108237
|
-
|
|
108238
|
-
|
|
108239
|
-
|
|
108240
|
-
|
|
108598
|
+
this.search = async (text, type) => {
|
|
108599
|
+
if (this.allPackagesFetched) {
|
|
108600
|
+
let packages = lodash.cloneDeep(this.packages);
|
|
108601
|
+
|
|
108602
|
+
if (type) {
|
|
108603
|
+
packages = lodash.filter(packages, o => {
|
|
108604
|
+
return (
|
|
108605
|
+
o.name.startsWith("@dualbox/dualbox-" + type) ||
|
|
108606
|
+
(type == "module" && o.name.startsWith("dualbox-core"))
|
|
108607
|
+
);
|
|
108608
|
+
});
|
|
108609
|
+
}
|
|
108241
108610
|
|
|
108242
|
-
|
|
108243
|
-
|
|
108244
|
-
|
|
108245
|
-
|
|
108246
|
-
|
|
108247
|
-
|
|
108611
|
+
if (text) {
|
|
108612
|
+
packages = this.filterPackages(text, packages);
|
|
108613
|
+
}
|
|
108614
|
+
|
|
108615
|
+
return Promise.resolve(packages);
|
|
108616
|
+
} else {
|
|
108617
|
+
return new Promise((resolve, reject) => {
|
|
108618
|
+
attrs.search(text, (err, packages) => {
|
|
108619
|
+
if (err) {
|
|
108620
|
+
reject(err);
|
|
108621
|
+
} else {
|
|
108622
|
+
// cache packages in this.packages
|
|
108623
|
+
lodash.each(packages, r => {
|
|
108624
|
+
if (!this.packages[r.name]) {
|
|
108625
|
+
this.packages[r.name] = r;
|
|
108626
|
+
}
|
|
108248
108627
|
});
|
|
108628
|
+
|
|
108629
|
+
if (type) {
|
|
108630
|
+
packages = lodash.filter(packages, o => {
|
|
108631
|
+
return (
|
|
108632
|
+
o.name.startsWith("@dualbox/dualbox-" + type) ||
|
|
108633
|
+
(type == "module" && o.name.startsWith("dualbox-core"))
|
|
108634
|
+
);
|
|
108635
|
+
});
|
|
108636
|
+
}
|
|
108637
|
+
resolve(packages);
|
|
108638
|
+
}
|
|
108639
|
+
});
|
|
108640
|
+
});
|
|
108641
|
+
}
|
|
108642
|
+
};
|
|
108643
|
+
|
|
108644
|
+
// filter results from text
|
|
108645
|
+
this.filterPackages = function(text, packages) {
|
|
108646
|
+
text = text.toLowerCase();
|
|
108647
|
+
|
|
108648
|
+
// ponderate search
|
|
108649
|
+
let ponderation = {
|
|
108650
|
+
"shortName": 0.7,
|
|
108651
|
+
"description": 0.3
|
|
108652
|
+
};
|
|
108653
|
+
|
|
108654
|
+
var splitWords = function(text) {
|
|
108655
|
+
return text.trim().replace(/[\W_]+/g, ' ').split(' ');
|
|
108656
|
+
};
|
|
108657
|
+
|
|
108658
|
+
let words = splitWords(text);
|
|
108659
|
+
|
|
108660
|
+
var isObject = function(o) {
|
|
108661
|
+
return typeof o === 'object' && o !== null;
|
|
108662
|
+
};
|
|
108663
|
+
|
|
108664
|
+
var getFuzzySearchResult = function(word, field) {
|
|
108665
|
+
var arr = [];
|
|
108666
|
+
lodash.each(packages, (r) => {
|
|
108667
|
+
if (r[field]) {
|
|
108668
|
+
let fieldWords = r[field].trim().split('-').join(' ') || "";
|
|
108669
|
+
r.searchString = fieldWords;
|
|
108670
|
+
arr.push(fieldWords);
|
|
108671
|
+
}
|
|
108672
|
+
});
|
|
108673
|
+
var set = new FuzzySet(arr, false);
|
|
108674
|
+
return set.get(word, null, 0.05);
|
|
108675
|
+
};
|
|
108676
|
+
|
|
108677
|
+
var setFuzzySearchResultScore = function(word, field) {
|
|
108678
|
+
var fuzzyResults = getFuzzySearchResult(word, field);
|
|
108679
|
+
lodash.each(fuzzyResults, (fuzzyResult) => {
|
|
108680
|
+
let resultIndexes = lodash.keys(lodash.pickBy(packages, r => r.searchString == fuzzyResult[1]));
|
|
108681
|
+
if (resultIndexes.length == 0) {
|
|
108682
|
+
console.error("Could not retrieve result for: " + fuzzyResult);
|
|
108683
|
+
}
|
|
108684
|
+
for (let resultIndex of resultIndexes) {
|
|
108685
|
+
let result = packages[resultIndex];
|
|
108686
|
+
|
|
108687
|
+
if (!isObject(result.wordscore)) {
|
|
108688
|
+
result.wordscore = {};
|
|
108249
108689
|
}
|
|
108250
|
-
|
|
108690
|
+
|
|
108691
|
+
if (!isObject(result.wordscore[field])) {
|
|
108692
|
+
result.wordscore[field] = {};
|
|
108693
|
+
}
|
|
108694
|
+
|
|
108695
|
+
result.wordscore[field][word] = result.wordscore[field][word] || 0;
|
|
108696
|
+
result.wordscore[field][word] += fuzzyResult[0];
|
|
108251
108697
|
}
|
|
108698
|
+
|
|
108699
|
+
// let resultIndex = _.findIndex(results, r => r[field] == fuzzyResult[1]);
|
|
108700
|
+
// if (resultIndex == -1) {
|
|
108701
|
+
// throw `Could not find result ${field}:${fuzzyResult[1]}`;
|
|
108702
|
+
// }
|
|
108703
|
+
});
|
|
108704
|
+
};
|
|
108705
|
+
|
|
108706
|
+
// create FuzzySets and search them
|
|
108707
|
+
for (let word of words) {
|
|
108708
|
+
setFuzzySearchResultScore(word, "shortName");
|
|
108709
|
+
setFuzzySearchResultScore(word, "description");
|
|
108710
|
+
}
|
|
108711
|
+
|
|
108712
|
+
// aggregate scores
|
|
108713
|
+
lodash.each(packages, r => {
|
|
108714
|
+
r.score = 0;
|
|
108715
|
+
lodash.each(r.wordscore, (wordScores, field) => {
|
|
108716
|
+
let fieldScore = 0;
|
|
108717
|
+
lodash.each(wordScores, (val, key) => {
|
|
108718
|
+
fieldScore += val;
|
|
108719
|
+
});
|
|
108720
|
+
fieldScore /= words.length;
|
|
108721
|
+
r.score += fieldScore * ponderation[field];
|
|
108252
108722
|
});
|
|
108253
108723
|
});
|
|
108724
|
+
|
|
108725
|
+
packages = lodash.filter(packages, r => r.score > 0);
|
|
108726
|
+
|
|
108727
|
+
// return result sorted by score
|
|
108728
|
+
return lodash.sortBy(packages, r => 1 - (r.score || 0));
|
|
108254
108729
|
};
|
|
108255
108730
|
|
|
108256
108731
|
this.types = [];
|