@dualbox/editor 1.0.70 → 1.0.71

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.
@@ -18017,6 +18017,7 @@ class History {
18017
18017
  save() {
18018
18018
  if (!this._holdSaving) {
18019
18019
  var currentAppClone = this.clone(this.m.data);
18020
+ currentAppClone.root = this.m.getCleanJson(); // if it's a snapshot, remove the extra infos
18020
18021
  var previousHash = hash(this.lastState.root);
18021
18022
  var diff = patcher.diff(this.lastState, currentAppClone);
18022
18023
  if (diff) {
@@ -64513,8 +64514,7 @@ var script$8 = {
64513
64514
  if( ["string", "number", "boolean", "array", "map"].indexOf(this.dataType) == -1 ) {
64514
64515
  this.dataType = "object";
64515
64516
  }
64516
-
64517
- console.log(`Type: ${this.type}, Datatype: ${this.dataType}, embeddedType: ${this.embeddedType}`);
64517
+ //console.log(`Type: ${this.type}, Datatype: ${this.dataType}, embeddedType: ${this.embeddedType}`);
64518
64518
  },
64519
64519
 
64520
64520
  initData: function() {
@@ -65007,11 +65007,11 @@ __vue_render__$8._withStripped = true;
65007
65007
  /* style */
65008
65008
  const __vue_inject_styles__$8 = function (inject) {
65009
65009
  if (!inject) return
65010
- inject("data-v-33721d92_0", { source: "\n.template-value-container[data-v-33721d92], .field-editor[data-v-33721d92] {\n margin-bottom: 10px;\n}\n.template-value-message[data-v-33721d92] {\n text-align: center;\n margin-top: 30px;\n margin-bottom: 30px;\n width: 100%;\n opacity: 0.5;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/editValue.vue"],"names":[],"mappings":";AACA;IACA,mBAAA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;IACA,WAAA;IACA,YAAA;AACA","file":"editValue.vue","sourcesContent":["<style scoped>\n .template-value-container, .field-editor {\n margin-bottom: 10px;\n }\n\n .template-value-message {\n text-align: center;\n margin-top: 30px;\n margin-bottom: 30px;\n width: 100%;\n opacity: 0.5;\n }\n</style>\n\n<template>\n <div class=\"w-100\">\n <p style=\"display: none;\">{{cIndex}}</p>\n <template v-if=\"isBasicDataType()\">\n <template v-if=\"dataType === 'string'\">\n <input class=\"edit-value-input\" type=\"text\" @keyup.enter=\"setStringValue\" @keyup.esc=\"setStringValue\" :value=\"v\" @focus=\"$event.target.select()\"></input>\n </template>\n <template v-else-if=\"dataType === 'boolean'\">\n <select class=\"edit-value-input\" @change=\"setBoolValue\">\n <option value=\"true\" :selected=\"v == true\">True</option>\n <option value=\"false\" :selected=\"v == false\">False</option>\n </select>\n </template>\n <template v-else-if=\"dataType === 'number'\">\n <input class=\"edit-value-input\" type=\"number\" @keyup.enter=\"setNumberValue\" @blur=\"setNumberValue\" :value=\"v\" @focus=\"$event.target.select()\" style=\"width: 40px;\"></input>\n </template>\n </template>\n <template v-else>\n <!-- we already are in a modal, don't instanciate another one -->\n <template v-if=\"isTemplateType()\">\n <div class=\"container template-value-container\" style=\"border: 1px solid rgba(0, 0, 0, 0.125);\">\n <div v-if=\"isArrayType()\" class=\"row\" style=\"background-color: rgba(0,0,0,.125);\">Array Editor</div>\n <div v-else-if=\"isMapType()\" class=\"row\" style=\"background-color: rgba(0,0,0,.125);\">Map Editor</div>\n <div class=\"row\" style=\"1px solid rgba(0,0,0,.125);\">\n <div class=\"col list-group-flush\" :class=\"{ 'col-1' : isArrayType(), 'col-2' : isMapType()}\" style=\"padding: 0; background-color: white; overflow-y: auto; border-right: 1px solid rgba(0, 0, 0, 0.125);\">\n <button v-for=\"index in deserializedValue.keys()\" :key=\"index\" :data-key=\"index\" type=\"button\" class=\"list-group-item list-group-item-action\" :class=\"{ active: isSelectedIndex(index) }\" style=\"text-align: center;\" @click=\"selectIndex(index)\">{{index}}</button>\n <button type=\"button\" @click=\"addItem\" class=\"list-group-item list-group-item-action add-item\" style=\"text-align: center;\"><i class=\"fas fa-plus-circle\"></i></button>\n </div>\n <div class=\"col\" style=\"padding: 10px\">\n <edit-value v-if=\"selectedIndex !== undefined && selectedIndex !== null\" :cIndex=\"selectedIndex\" :type=\"embeddedType\" :v=\"getElement(selectedIndex)\" @edited=\"onSubValueEdited(selectedIndex, $event)\"></edit-value>\n <p v-else class=\"template-value-message\">Select an element to edit.</p>\n </div>\n </div>\n </div>\n </template>\n <template v-else>\n <div class=\"field-editor\" :data-value=\"hash()\"></div>\n </template>\n </template>\n\n <!-- set null and delete buttons -->\n <div class=\"d-inline-block float-right\">\n <button class=\"btn btn-secondary btn-sm btn-xs\" title=\"set Null\" @click=\"setNullValue\">null</button>\n <button class=\"btn btn-danger btn-sm btn-xs\" title=\"delete value\" @click=\"deleteValue\" style=\"margin-left: 0px;\"><i class=\"fas fa-trash\"></i></button>\n </div>\n </div>\n\n</template>\n\n<script>\nimport _ from 'lodash-es';\nimport swal from 'sweetalert2';\nimport JSONEditor from '@dualbox/dualbox-lib-jsoneditor';\n\nString.prototype.hashCode = function() {\n var hash = 0, i, chr;\n if (this.length === 0) return hash;\n for (i = 0; i < this.length; i++) {\n chr = this.charCodeAt(i);\n hash = ((hash << 5) - hash) + chr;\n hash |= 0; // Convert to 32bit integer\n }\n return hash;\n};\n\nexport default {\n name : \"edit-value\",\n props: [\n // required\n \"v\", // the value\n \"type\", // the dualbox type of the value\n\n // specific properties (for recursivity)\n \"cIndex\" // index for reference when in an array\n ],\n data: function () {\n return {\n \"dataType\": null, // the real javascript dataType of this.v\n \"deserializedValue\": null,\n\n // if type is a collection (dataType==\"map\" or dataType==\"array\")\n \"embeddedType\": null, // the embedded type of this templated collection\n \"selectedIndex\": null, // the current index of the element we are editing\n };\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n this.editor = null;\n this.edited = false;\n this.initData();\n },\n mounted: function() {\n var self = this;\n\n this.updateEditor();\n\n $(this.$el).find('.edit-value-input').focus(); // focus on the edit element\n },\n beforeUpdate: function() {\n this.updateData();\n },\n updated: function() {\n if( this.autochange ) {\n // change triggered by ourself, skip\n this.autochange = false;\n }\n else {\n this.updateEditor();\n }\n },\n beforeDestroy: function() {\n // make sure the value was set\n if( !this.emitted ) {\n if( this.isBasicDataType()) {\n var elt = $(this.$el).find('.edit-value-input');\n var val = elt.val();\n this.$emit(\"edited\", val);\n }\n else {\n this.saveChanges();\n }\n }\n },\n methods: {\n hash: function() {\n var str = new String(this.v).toString();\n return str.split('').reduce((prevHash, currVal) => (((prevHash << 5) - prevHash) + currVal.charCodeAt(0))|0, 0);\n },\n\n updateEditor: function() {\n if( this.dataType === \"object\" ) {\n if( !this.editor && $(this.$el).find('.field-editor')[0] !== undefined ) {\n // bind the json editor\n this.editor = new JSONEditor(\n $(this.$el).find('.field-editor')[0], {\n modes: ['tree', 'code', 'text' ],\n onChange: () => {\n try {\n var json = this.editor.get();\n this.autochange = true;\n this.$emit('edited', json);\n }\n catch(e) {}\n }\n });\n }\n\n if( this.editor ) {\n this.editor.set(this.v || {});\n }\n }\n },\n resolveDatatype() {\n // determine datatype of the value\n var resolvedType = this.type ? this.type.toLowerCase() : typeof this.v;\n\n // If \"*\", resolve the type by detecting it dynamically from value\n if( resolvedType.indexOf(\"*\") !== -1 ) {\n resolvedType = window.DualBox.Type.detectType(this.v).toLowerCase();\n }\n\n // Check if we have a template type. If so, determine current index and embedded type\n var templateType = null;\n if( resolvedType.startsWith(\"array\") ) {\n templateType = \"array\";\n this.deserializedValue = this.v || [];\n }\n else if( resolvedType.startsWith(\"map\") ) {\n templateType = \"map\";\n this.deserializedValue = window.DualBox.Type.deserialize(this.v || {\n \"metadata\":{\n \"type\":\"Map<String,\"+ this.firstLetterUppercase( this.getEmbeddedType(resolvedType) )+\">\"\n },\n \"data\": {}\n });\n }\n\n if( templateType ) {\n this.dataType = templateType;\n this.embeddedType = this.getEmbeddedType(resolvedType);\n if( this.selectedIndex == null ) {\n var firstKey = this.deserializedValue.keys().next();\n if( firstKey && firstKey.value ) {\n this.selectedIndex = firstKey.value;\n }\n }\n }\n else {\n this.dataType = resolvedType;\n }\n\n // Finally, transform to object if not a basic value\n if( [\"string\", \"number\", \"boolean\", \"array\", \"map\"].indexOf(this.dataType) == -1 ) {\n this.dataType = \"object\";\n }\n\n console.log(`Type: ${this.type}, Datatype: ${this.dataType}, embeddedType: ${this.embeddedType}`);\n },\n\n initData: function() {\n this.v = this.v;\n this.resolveDatatype();\n this.selectNextIndex();\n },\n\n updateData: function() {\n this.resolveDatatype();\n },\n\n isBasicDataType() {\n return this.dataType == \"string\" ||\n this.dataType == \"number\" ||\n this.dataType == \"boolean\";\n },\n\n serialize( value ) {\n if( this.isTemplateType() ) {\n if( this.isArrayType() ) {\n return value; // we store arrays as is\n }\n else if( this.isMapType() ) {\n return window.DualBox.Type.serialize(value);\n }\n }\n else {\n return value;\n }\n },\n\n saveChanges: function() {\n this.$forceUpdate();\n\n if( this.isTemplateType() ) {\n this.$emit(\"edited\", this.serialize(this.deserializedValue));\n this.emitted = true;\n }\n else if( this.isObjectType() ) {\n // emit the result to the parent Vue\n this.$emit(\"edited\", this.editor.get());\n this.emitted = true;\n }\n },\n\n setStringValue: function(e) {\n var val = $(e.target).val();\n this.$emit(\"edited\", val);\n this.emitted = true;\n },\n\n setBoolValue: function(e) {\n var val = $(e.target).val() == \"true\";\n this.$emit(\"edited\", val);\n this.emitted = true;\n },\n\n setNumberValue: function(e) {\n var val = parseFloat($(e.target).val());\n this.$emit(\"edited\", val);\n this.emitted = true;\n },\n\n setNullValue: function() {\n this.$forceUpdate();\n\n // emit the result to the parent Vue\n this.$emit(\"edited\", null);\n },\n\n selectNextIndex: function() {\n if( this.isArrayType() ) {\n this.selectedIndex = this.deserializedValue.length > 0 ? 0 : null;\n }\n else if( this.isMapType() ) {\n var keys = this.deserializedValue.keys();\n var next = keys.next();\n this.selectedIndex = next ? next.value : null;\n }\n },\n\n deleteValue: function(e) {\n this.selectNextIndex();\n this.$forceUpdate();\n\n // emit the result to the parent Vue\n this.$emit(\"edited\", undefined);\n },\n\n isArrayType: function() {\n return this.dataType == \"array\";\n },\n\n isMapType: function() {\n return this.dataType == \"map\";\n },\n\n isObjectType: function() {\n return this.dataType == \"object\";\n },\n\n isTemplateType: function() {\n return this.isArrayType() || this.isMapType();\n },\n\n getEmbeddedType: function(type) {\n var start = type.indexOf('<') + 1;\n var end = type.lastIndexOf('>');\n if( type.toLowerCase().startsWith('array') ) {\n return type.substr(start, end - start).trim().toLowerCase();\n }\n else if( type.toLowerCase().startsWith('map') ) {\n var sub = type.substr(start, end - start);\n return sub.substr(sub.indexOf(',') + 1).trim().toLowerCase();\n }\n },\n\n firstLetterUppercase: function(s) {\n return s.charAt(0).toUpperCase() + s.slice(1)\n },\n\n selectIndex: function(index) {\n if( this.selectedIndex !== index ) {\n this.selectedIndex = index;\n this.$forceUpdate();\n }\n },\n\n isSelectedIndex: function(index) {\n return index == this.selectedIndex;\n },\n\n getElement: function(i) {\n if( Array.isArray(this.v) ) {\n return this.deserializedValue[i];\n }\n else {\n return this.deserializedValue.get(i);\n }\n },\n\n onSubValueEdited: function(index, newValue) {\n console.log(`Edited at index ${index}: ${JSON.stringify(newValue)}`);\n if( this.isArrayType() ) {\n if( newValue === undefined ) {\n // we just remove this value\n this.deserializedValue.splice(index, 1);\n }\n else {\n this.deserializedValue[index] = newValue;\n }\n }\n else if ( this.isMapType() ) {\n if( newValue === undefined ) {\n this.deserializedValue.delete(index);\n }\n else {\n this.deserializedValue.set(index, newValue);\n }\n }\n this.saveChanges();\n this.$forceUpdate();\n },\n\n addItem: function() {\n if( this.isArrayType() ) {\n this.deserializedValue[ this.deserializedValue.length ] = null;\n this.selectedIndex = this.deserializedValue.length - 1;\n this.saveChanges();\n this.$forceUpdate();\n }\n else if( this.isMapType() ) {\n this.swalFixBootstrapModal();\n swal({\n input: 'text',\n title: 'Enter map key',\n }).then((result) => {\n this.swalRestoreBootstrapModal();\n if( result && result.value ) {\n this.selectedIndex = result.value;\n this.deserializedValue.set(result.value, null);\n this.saveChanges();\n this.$forceUpdate();\n }\n });\n }\n },\n\n // call this before showing SweetAlert:\n swalFixBootstrapModal() {\n var modal = $(\"body\").find('.modal[tabindex=\"-1\"]');\n if (!modal) return;\n modal.removeAttr('tabindex');\n modal.addClass('js-swal-fixed');\n },\n\n // call this before hiding SweetAlert (inside done callback):\n swalRestoreBootstrapModal() {\n var modal = $(\"body\").find('.modal.js-swal-fixed');\n if (!modal) return;\n modal.attr('tabindex', '-1');\n modal.removeClass('js-swal-fixed');\n }\n }\n}\n</script>\n"]}, media: undefined });
65010
+ inject("data-v-b2b26ee0_0", { source: "\n.template-value-container[data-v-b2b26ee0], .field-editor[data-v-b2b26ee0] {\n margin-bottom: 10px;\n}\n.template-value-message[data-v-b2b26ee0] {\n text-align: center;\n margin-top: 30px;\n margin-bottom: 30px;\n width: 100%;\n opacity: 0.5;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/editValue.vue"],"names":[],"mappings":";AACA;IACA,mBAAA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,mBAAA;IACA,WAAA;IACA,YAAA;AACA","file":"editValue.vue","sourcesContent":["<style scoped>\n .template-value-container, .field-editor {\n margin-bottom: 10px;\n }\n\n .template-value-message {\n text-align: center;\n margin-top: 30px;\n margin-bottom: 30px;\n width: 100%;\n opacity: 0.5;\n }\n</style>\n\n<template>\n <div class=\"w-100\">\n <p style=\"display: none;\">{{cIndex}}</p>\n <template v-if=\"isBasicDataType()\">\n <template v-if=\"dataType === 'string'\">\n <input class=\"edit-value-input\" type=\"text\" @keyup.enter=\"setStringValue\" @keyup.esc=\"setStringValue\" :value=\"v\" @focus=\"$event.target.select()\"></input>\n </template>\n <template v-else-if=\"dataType === 'boolean'\">\n <select class=\"edit-value-input\" @change=\"setBoolValue\">\n <option value=\"true\" :selected=\"v == true\">True</option>\n <option value=\"false\" :selected=\"v == false\">False</option>\n </select>\n </template>\n <template v-else-if=\"dataType === 'number'\">\n <input class=\"edit-value-input\" type=\"number\" @keyup.enter=\"setNumberValue\" @blur=\"setNumberValue\" :value=\"v\" @focus=\"$event.target.select()\" style=\"width: 40px;\"></input>\n </template>\n </template>\n <template v-else>\n <!-- we already are in a modal, don't instanciate another one -->\n <template v-if=\"isTemplateType()\">\n <div class=\"container template-value-container\" style=\"border: 1px solid rgba(0, 0, 0, 0.125);\">\n <div v-if=\"isArrayType()\" class=\"row\" style=\"background-color: rgba(0,0,0,.125);\">Array Editor</div>\n <div v-else-if=\"isMapType()\" class=\"row\" style=\"background-color: rgba(0,0,0,.125);\">Map Editor</div>\n <div class=\"row\" style=\"1px solid rgba(0,0,0,.125);\">\n <div class=\"col list-group-flush\" :class=\"{ 'col-1' : isArrayType(), 'col-2' : isMapType()}\" style=\"padding: 0; background-color: white; overflow-y: auto; border-right: 1px solid rgba(0, 0, 0, 0.125);\">\n <button v-for=\"index in deserializedValue.keys()\" :key=\"index\" :data-key=\"index\" type=\"button\" class=\"list-group-item list-group-item-action\" :class=\"{ active: isSelectedIndex(index) }\" style=\"text-align: center;\" @click=\"selectIndex(index)\">{{index}}</button>\n <button type=\"button\" @click=\"addItem\" class=\"list-group-item list-group-item-action add-item\" style=\"text-align: center;\"><i class=\"fas fa-plus-circle\"></i></button>\n </div>\n <div class=\"col\" style=\"padding: 10px\">\n <edit-value v-if=\"selectedIndex !== undefined && selectedIndex !== null\" :cIndex=\"selectedIndex\" :type=\"embeddedType\" :v=\"getElement(selectedIndex)\" @edited=\"onSubValueEdited(selectedIndex, $event)\"></edit-value>\n <p v-else class=\"template-value-message\">Select an element to edit.</p>\n </div>\n </div>\n </div>\n </template>\n <template v-else>\n <div class=\"field-editor\" :data-value=\"hash()\"></div>\n </template>\n </template>\n\n <!-- set null and delete buttons -->\n <div class=\"d-inline-block float-right\">\n <button class=\"btn btn-secondary btn-sm btn-xs\" title=\"set Null\" @click=\"setNullValue\">null</button>\n <button class=\"btn btn-danger btn-sm btn-xs\" title=\"delete value\" @click=\"deleteValue\" style=\"margin-left: 0px;\"><i class=\"fas fa-trash\"></i></button>\n </div>\n </div>\n\n</template>\n\n<script>\nimport _ from 'lodash-es';\nimport swal from 'sweetalert2';\nimport JSONEditor from '@dualbox/dualbox-lib-jsoneditor';\n\nString.prototype.hashCode = function() {\n var hash = 0, i, chr;\n if (this.length === 0) return hash;\n for (i = 0; i < this.length; i++) {\n chr = this.charCodeAt(i);\n hash = ((hash << 5) - hash) + chr;\n hash |= 0; // Convert to 32bit integer\n }\n return hash;\n};\n\nexport default {\n name : \"edit-value\",\n props: [\n // required\n \"v\", // the value\n \"type\", // the dualbox type of the value\n\n // specific properties (for recursivity)\n \"cIndex\" // index for reference when in an array\n ],\n data: function () {\n return {\n \"dataType\": null, // the real javascript dataType of this.v\n \"deserializedValue\": null,\n\n // if type is a collection (dataType==\"map\" or dataType==\"array\")\n \"embeddedType\": null, // the embedded type of this templated collection\n \"selectedIndex\": null, // the current index of the element we are editing\n };\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n this.editor = null;\n this.edited = false;\n this.initData();\n },\n mounted: function() {\n var self = this;\n\n this.updateEditor();\n\n $(this.$el).find('.edit-value-input').focus(); // focus on the edit element\n },\n beforeUpdate: function() {\n this.updateData();\n },\n updated: function() {\n if( this.autochange ) {\n // change triggered by ourself, skip\n this.autochange = false;\n }\n else {\n this.updateEditor();\n }\n },\n beforeDestroy: function() {\n // make sure the value was set\n if( !this.emitted ) {\n if( this.isBasicDataType()) {\n var elt = $(this.$el).find('.edit-value-input');\n var val = elt.val();\n this.$emit(\"edited\", val);\n }\n else {\n this.saveChanges();\n }\n }\n },\n methods: {\n hash: function() {\n var str = new String(this.v).toString();\n return str.split('').reduce((prevHash, currVal) => (((prevHash << 5) - prevHash) + currVal.charCodeAt(0))|0, 0);\n },\n\n updateEditor: function() {\n if( this.dataType === \"object\" ) {\n if( !this.editor && $(this.$el).find('.field-editor')[0] !== undefined ) {\n // bind the json editor\n this.editor = new JSONEditor(\n $(this.$el).find('.field-editor')[0], {\n modes: ['tree', 'code', 'text' ],\n onChange: () => {\n try {\n var json = this.editor.get();\n this.autochange = true;\n this.$emit('edited', json);\n }\n catch(e) {}\n }\n });\n }\n\n if( this.editor ) {\n this.editor.set(this.v || {});\n }\n }\n },\n resolveDatatype() {\n // determine datatype of the value\n var resolvedType = this.type ? this.type.toLowerCase() : typeof this.v;\n\n // If \"*\", resolve the type by detecting it dynamically from value\n if( resolvedType.indexOf(\"*\") !== -1 ) {\n resolvedType = window.DualBox.Type.detectType(this.v).toLowerCase();\n }\n\n // Check if we have a template type. If so, determine current index and embedded type\n var templateType = null;\n if( resolvedType.startsWith(\"array\") ) {\n templateType = \"array\";\n this.deserializedValue = this.v || [];\n }\n else if( resolvedType.startsWith(\"map\") ) {\n templateType = \"map\";\n this.deserializedValue = window.DualBox.Type.deserialize(this.v || {\n \"metadata\":{\n \"type\":\"Map<String,\"+ this.firstLetterUppercase( this.getEmbeddedType(resolvedType) )+\">\"\n },\n \"data\": {}\n });\n }\n\n if( templateType ) {\n this.dataType = templateType;\n this.embeddedType = this.getEmbeddedType(resolvedType);\n if( this.selectedIndex == null ) {\n var firstKey = this.deserializedValue.keys().next();\n if( firstKey && firstKey.value ) {\n this.selectedIndex = firstKey.value;\n }\n }\n }\n else {\n this.dataType = resolvedType;\n }\n\n // Finally, transform to object if not a basic value\n if( [\"string\", \"number\", \"boolean\", \"array\", \"map\"].indexOf(this.dataType) == -1 ) {\n this.dataType = \"object\";\n }\n //console.log(`Type: ${this.type}, Datatype: ${this.dataType}, embeddedType: ${this.embeddedType}`);\n },\n\n initData: function() {\n this.v = this.v;\n this.resolveDatatype();\n this.selectNextIndex();\n },\n\n updateData: function() {\n this.resolveDatatype();\n },\n\n isBasicDataType() {\n return this.dataType == \"string\" ||\n this.dataType == \"number\" ||\n this.dataType == \"boolean\";\n },\n\n serialize( value ) {\n if( this.isTemplateType() ) {\n if( this.isArrayType() ) {\n return value; // we store arrays as is\n }\n else if( this.isMapType() ) {\n return window.DualBox.Type.serialize(value);\n }\n }\n else {\n return value;\n }\n },\n\n saveChanges: function() {\n this.$forceUpdate();\n\n if( this.isTemplateType() ) {\n this.$emit(\"edited\", this.serialize(this.deserializedValue));\n this.emitted = true;\n }\n else if( this.isObjectType() ) {\n // emit the result to the parent Vue\n this.$emit(\"edited\", this.editor.get());\n this.emitted = true;\n }\n },\n\n setStringValue: function(e) {\n var val = $(e.target).val();\n this.$emit(\"edited\", val);\n this.emitted = true;\n },\n\n setBoolValue: function(e) {\n var val = $(e.target).val() == \"true\";\n this.$emit(\"edited\", val);\n this.emitted = true;\n },\n\n setNumberValue: function(e) {\n var val = parseFloat($(e.target).val());\n this.$emit(\"edited\", val);\n this.emitted = true;\n },\n\n setNullValue: function() {\n this.$forceUpdate();\n\n // emit the result to the parent Vue\n this.$emit(\"edited\", null);\n },\n\n selectNextIndex: function() {\n if( this.isArrayType() ) {\n this.selectedIndex = this.deserializedValue.length > 0 ? 0 : null;\n }\n else if( this.isMapType() ) {\n var keys = this.deserializedValue.keys();\n var next = keys.next();\n this.selectedIndex = next ? next.value : null;\n }\n },\n\n deleteValue: function(e) {\n this.selectNextIndex();\n this.$forceUpdate();\n\n // emit the result to the parent Vue\n this.$emit(\"edited\", undefined);\n },\n\n isArrayType: function() {\n return this.dataType == \"array\";\n },\n\n isMapType: function() {\n return this.dataType == \"map\";\n },\n\n isObjectType: function() {\n return this.dataType == \"object\";\n },\n\n isTemplateType: function() {\n return this.isArrayType() || this.isMapType();\n },\n\n getEmbeddedType: function(type) {\n var start = type.indexOf('<') + 1;\n var end = type.lastIndexOf('>');\n if( type.toLowerCase().startsWith('array') ) {\n return type.substr(start, end - start).trim().toLowerCase();\n }\n else if( type.toLowerCase().startsWith('map') ) {\n var sub = type.substr(start, end - start);\n return sub.substr(sub.indexOf(',') + 1).trim().toLowerCase();\n }\n },\n\n firstLetterUppercase: function(s) {\n return s.charAt(0).toUpperCase() + s.slice(1)\n },\n\n selectIndex: function(index) {\n if( this.selectedIndex !== index ) {\n this.selectedIndex = index;\n this.$forceUpdate();\n }\n },\n\n isSelectedIndex: function(index) {\n return index == this.selectedIndex;\n },\n\n getElement: function(i) {\n if( Array.isArray(this.v) ) {\n return this.deserializedValue[i];\n }\n else {\n return this.deserializedValue.get(i);\n }\n },\n\n onSubValueEdited: function(index, newValue) {\n console.log(`Edited at index ${index}: ${JSON.stringify(newValue)}`);\n if( this.isArrayType() ) {\n if( newValue === undefined ) {\n // we just remove this value\n this.deserializedValue.splice(index, 1);\n }\n else {\n this.deserializedValue[index] = newValue;\n }\n }\n else if ( this.isMapType() ) {\n if( newValue === undefined ) {\n this.deserializedValue.delete(index);\n }\n else {\n this.deserializedValue.set(index, newValue);\n }\n }\n this.saveChanges();\n this.$forceUpdate();\n },\n\n addItem: function() {\n if( this.isArrayType() ) {\n this.deserializedValue[ this.deserializedValue.length ] = null;\n this.selectedIndex = this.deserializedValue.length - 1;\n this.saveChanges();\n this.$forceUpdate();\n }\n else if( this.isMapType() ) {\n this.swalFixBootstrapModal();\n swal({\n input: 'text',\n title: 'Enter map key',\n }).then((result) => {\n this.swalRestoreBootstrapModal();\n if( result && result.value ) {\n this.selectedIndex = result.value;\n this.deserializedValue.set(result.value, null);\n this.saveChanges();\n this.$forceUpdate();\n }\n });\n }\n },\n\n // call this before showing SweetAlert:\n swalFixBootstrapModal() {\n var modal = $(\"body\").find('.modal[tabindex=\"-1\"]');\n if (!modal) return;\n modal.removeAttr('tabindex');\n modal.addClass('js-swal-fixed');\n },\n\n // call this before hiding SweetAlert (inside done callback):\n swalRestoreBootstrapModal() {\n var modal = $(\"body\").find('.modal.js-swal-fixed');\n if (!modal) return;\n modal.attr('tabindex', '-1');\n modal.removeClass('js-swal-fixed');\n }\n }\n}\n</script>\n"]}, media: undefined });
65011
65011
 
65012
65012
  };
65013
65013
  /* scoped */
65014
- const __vue_scope_id__$8 = "data-v-33721d92";
65014
+ const __vue_scope_id__$8 = "data-v-b2b26ee0";
65015
65015
  /* module identifier */
65016
65016
  const __vue_module_identifier__$8 = undefined;
65017
65017
  /* functional template */
@@ -73666,7 +73666,6 @@ var script$c = {
73666
73666
  beforeUpdate: function() {
73667
73667
  this.n = this.view.m.getNode(this.id); // it breaks updating node name
73668
73668
  this.debug = this.n.getSnapshot(); // shortcut
73669
- this.$forceupdate();
73670
73669
  },
73671
73670
  mounted: function() {
73672
73671
 
@@ -73971,8 +73970,7 @@ var __vue_render__$c = function() {
73971
73970
  attrs: {
73972
73971
  v: _vm.n.m.getSnapshotValue(
73973
73972
  _vm.getInputData(key).value
73974
- ),
73975
- readonly: "true"
73973
+ )
73976
73974
  }
73977
73975
  })
73978
73976
  ]
@@ -73990,8 +73988,7 @@ var __vue_render__$c = function() {
73990
73988
  attrs: {
73991
73989
  v: _vm.n.m.getSnapshotValue(
73992
73990
  _vm.getInputData(key).default
73993
- ),
73994
- readonly: "true"
73991
+ )
73995
73992
  }
73996
73993
  })
73997
73994
  ]
@@ -74053,8 +74050,7 @@ var __vue_render__$c = function() {
74053
74050
  attrs: {
74054
74051
  v: _vm.n.m.getSnapshotValue(
74055
74052
  _vm.debug.cache[_vm.key]
74056
- ),
74057
- readonly: "true"
74053
+ )
74058
74054
  }
74059
74055
  })
74060
74056
  ],
@@ -74242,8 +74238,7 @@ var __vue_render__$c = function() {
74242
74238
  v: _vm.n.m.getSnapshotValue(
74243
74239
  _vm.debug.times.emissions
74244
74240
  .lastData.data[key]
74245
- ),
74246
- readonly: "true"
74241
+ )
74247
74242
  }
74248
74243
  })
74249
74244
  ],
@@ -74696,7 +74691,7 @@ __vue_render__$c._withStripped = true;
74696
74691
  /* style */
74697
74692
  const __vue_inject_styles__$c = function (inject) {
74698
74693
  if (!inject) return
74699
- inject("data-v-27e694bc_0", { source: "\n.card-debug .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/debugNodeInfos.vue"],"names":[],"mappings":";AACA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;AACA","file":"debugNodeInfos.vue","sourcesContent":["<style>\n .card-debug .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n }\n</style>\n\n<template>\n<div class=\"card-debug h100\" id=\"debug-node\">\n <div style=\"padding-left: 10px; padding-top: 10px; padding-right: 10px;\">\n <h2 class=\"edit-dualbox-node-id\">\n <div class=\"dualbox-node-name\">\n <span class=\"text-truncate d-inline-block\" style=\"width: 290px\" :data-id=\"id\">{{n.graphId}}</span>\n </div>\n <div class=\"dualbox-node-name-edit\" style=\"display: none;\">\n <input type=\"text\" class=\"form-control dualbox-node-name-input\" style=\"display: inline-block;\" :value=\"n.graphId\" :data-type=\"n.type\" autofocus/>\n <button class=\"btn btn-primary btn-save-node-name-change\" :data-id=\"n.graphId\" :data-type=\"n.type\" style=\"display: inline-block;\">Save</button>\n </div>\n </h2>\n <p><small class=\"edit-dualbox-node-package-name\">{{n.getPackageName()}}</small></p>\n </div>\n\n <div class=\"edit-body\">\n <div class=\"card card-state\">\n <div class=\"card-header\" id=\"debug-node-state\" data-toggle=\"collapse\" data-target=\"#debug-node-state-collapse\" aria-expanded=\"true\" aria-controls=\"debug-node-state-collapse\">\n <h5 class=\"mb-0 btn-link\">State</h5>\n </div>\n\n <div id=\"debug-node-state-collapse\" class=\"collapse show\" aria-labelledby=\"debug-node-state\" data-parent=\"#debug-node\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Key</th>\n <th>Value</th>\n </thead>\n <tbody>\n <tr>\n <td>status</td>\n <td><span :class=\"{'card-status-idle':n.isSnapshotStatus(0),'card-status-computing':n.isSnapshotStatus(1),'card-status-awaiting-data':n.isSnapshotStatus(2), 'card-status-ready':n.isSnapshotStatus(3)}\">{{ getSnapshotStatus(n) }}</span></td>\n </tr>\n <tr><td>invalidateSent</td><td>{{debug.state.invalidateSent}}</td></tr>\n <tr><td>readSent</td><td>{{debug.state.readSent}}</td></tr>\n <tr><td>allowedToRestart</td><td>{{debug.state.allowedToRestart}}</td></tr>\n <tr><td>evaluating</td><td>{{debug.state.evaluating}}</td></tr>\n <tr><td>initialized</td><td>{{debug.state.initialized}}</td></tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n\n <div v-if=\"n.hasInputs()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"debug-node-inputs\" data-toggle=\"collapse\" data-target=\"#debug-node-inputs-collapse\" aria-expanded=\"false\" aria-controls=\"debug-node-inputs-collapse\">\n <h5 class=\"mb-0 btn-link\">Data <small><span class=\"badge badge-secondary\">{{ n.getInputsNames().length }}</span></small></h5>\n </div>\n <div id=\"debug-node-inputs-collapse\" class=\"collapse\" aria-labelledby=\"debug-node-inputs\" data-parent=\"#card-debug\">\n <div class=\"card-body\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Input</th>\n <th>Valid</th>\n <th>Type</th>\n <th>Value</th>\n <th>Default</th>\n </thead>\n <tbody>\n <tr v-for=\"key in n.getInputsNames()\" :key=\"n.id + '-input-' + key\">\n <td>\n {{key}}\n <button v-if=\"n.hasInputDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" :title=\"n.getInputDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </td>\n <td>{{ getInputData(key).valid }}</td>\n <td>\n <template v-if=\"getInputData(key).value\">\n <template v-if=\"getInputData(key).value.metadata && getInputData(key).value.metadata.type\">{{getInputData(key).value.metadata}}</template>\n <template v-else>{{typeof n.m.getSnapshotValue(getInputData(key).value) }}</template>\n </template>\n </td>\n <td>\n <template v-if=\"getInputData(key).value\">\n <display-value :v=\"n.m.getSnapshotValue(getInputData(key).value)\" readonly=true></display-value>\n </template>\n </td>\n <td>\n <template v-if=\"getInputData(key).default\">\n <display-value :v=\"n.m.getSnapshotValue(getInputData(key).default)\" readonly=true></display-value>\n </template>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <div v-if=\"debug.cache\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"debug-node-cache\" data-toggle=\"collapse\" data-target=\"#debug-node-cache-collapse\" aria-expanded=\"false\" aria-controls=\"debug-node-cache-collapse\">\n <h5 class=\"mb-0 btn-link\">Cache</h5>\n </div>\n <div id=\"debug-node-cache-collapse\" class=\"collapse\" aria-labelledby=\"debug-node-cache\" data-parent=\"#card-debug\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Output</th>\n <th>Value</th>\n </thead>\n <tbody>\n <tr v-for=\"key in Object.keys(debug.cache)\" :key=\"n.id + '-cache-' + key\">\n <tr>\n <td>{{key}}</td>\n <td><display-value :v=\"n.m.getSnapshotValue(debug.cache[key])\" readonly=true></display-value></td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <div v-if=\"debug.times && debug.times.emissions && (debug.times.emissions.lastRead || debug.times.emissions.lastInvalidate || debug.times.emissions.lastData )\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"debug-node-events\" data-toggle=\"collapse\" data-target=\"#debug-node-events-collapse\" aria-expanded=\"false\" aria-controls=\"debug-node-events-collapse\">\n <h5 class=\"mb-0 btn-link\">Last events</h5>\n </div>\n <div id=\"debug-node-events-collapse\" class=\"collapse\" aria-labelledby=\"debug-node-events\" data-parent=\"#card-debug\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n\n <div v-if=\"debug.times.emissions.lastRead\" class=\"mb-3\">\n <p><b><u>Last read {{showNumber(debug.times.emissions.nbRead)}}</u> <span class=\"float-right\">{{ showTime(debug.times.emissions.lastRead.date) }}</span></b></p>\n <span>Missing: <b>{{ debug.times.emissions.lastRead.data.join(', ') }}</b></span><br/>\n </div>\n\n <div v-if=\"debug.times.emissions.lastInvalidate\" class=\"mb-3\">\n <p><b><u>Last Invalidate {{showNumber(debug.times.emissions.nbInvalidate)}}</u> <span class=\"float-right\">{{ showTime(debug.times.emissions.lastInvalidate.date) }}</span></b></p>\n <span>Invalidated keys: <b>{{ debug.times.emissions.lastInvalidate.data.join(', ') }}</b></span><br/>\n </div>\n\n <div v-if=\"debug.times.emissions.lastData\" class=\"mb-3\">\n <p><b><u>Last Data {{ showNumber(debug.times.emissions.nbData) }}</u> <span class=\"float-right\">{{ showTime(debug.times.emissions.lastData.date) }}</span></b></p>\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Output</th>\n <th>Value</th>\n </thead>\n <tbody>\n <tr v-for=\"key in Object.keys(debug.times.emissions.lastData.data)\" :key=\"n.id + '-cache-' + key\">\n <td>{{key}}</td>\n <td><display-value :v=\"n.m.getSnapshotValue(debug.times.emissions.lastData.data[key])\" readonly=true></display-value></td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n\n <div v-if=\"debug.times && debug.times.evaluations && (debug.times.evaluations.lastStart || debug.times.evaluations.lastEnd || debug.times.evaluations.lastCancel )\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"debug-node-evaluations\" data-toggle=\"collapse\" data-target=\"#debug-node-evaluations-collapse\" aria-expanded=\"false\" aria-controls=\"debug-node-evaluations-collapse\">\n <h5 class=\"mb-0 btn-link\">Last evaluations</h5>\n </div>\n <div id=\"debug-node-evaluations-collapse\" class=\"collapse\" aria-labelledby=\"debug-node-evaluations\" data-parent=\"#card-debug\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n\n <div v-if=\"debug.times.evaluations.lastStart\" class=\"mb-3\">\n <p><b><u>Last start</u> <span class=\"float-right\">{{ showTime(debug.times.evaluations.lastStart.date) }}</span></b></p>\n </div>\n\n <div v-if=\"debug.times.evaluations.lastEnd\" class=\"mb-3\">\n <p><b><u>Last end</u> <span class=\"float-right\">{{ showTime(debug.times.evaluations.lastEnd.date) }}</span></b></p>\n </div>\n\n <div v-if=\"debug.times.evaluations.lastCancel\" class=\"mb-3\">\n <p><b><u>Last Cancel</u> <span class=\"float-right\">{{ showTime(debug.times.evaluations.lastCancel.date) }}</span></b></p>\n <span>reason: <b>{{ debug.times.evaluations.lastCancel.reason }}</b></span><br/>\n </div>\n </div>\n </div>\n </div>\n\n\n <div v-if=\"debug.performances\" class=\"card card-performances\">\n <div class=\"card-header\" id=\"debug-node-performances\" data-toggle=\"collapse\" data-target=\"#debug-node-performances-collapse\" aria-expanded=\"false\" aria-controls=\"debug-node-performances-collapse\">\n <h5 class=\"mb-0 btn-link\">Performances</h5>\n </div>\n\n <div id=\"debug-node-performances-collapse\" class=\"collapse\" aria-labelledby=\"debug-node-performances\" data-parent=\"#debug-node\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Stat</th>\n <th>Value</th>\n </thead>\n <tbody>\n <tr><td>min</td><td>{{debug.performances.min && debug.performances.min.toFixed(0)}}ms</td></tr>\n <tr><td>max</td><td>{{debug.performances.max && debug.performances.max.toFixed(0)}}ms</td></tr>\n <tr><td>avg</td><td>{{debug.performances.avg && debug.performances.avg.toFixed(0)}}ms</td></tr>\n <tr><td>total</td><td>{{debug.performances.total && debug.performances.total.toFixed(0)}}ms</td></tr>\n <tr><td>Nb of runs</td><td>{{debug.performances.nbRuns}}</td></tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"modal debug-json-modal\" tabindex=\"-1\" role=\"dialog\">\n <div class=\"modal-dialog\" role=\"document\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">Value debugger</h5>\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n </div>\n <div class=\"modal-body\">\n <div class=\"json-editor\" style=\"height: 400px;\"></div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-primary btn-save\">Save changes</button>\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n</template>\n\n<script>\nimport _ from 'lodash-es';\nimport moment from 'moment';\n\nimport DisplayValueVue from './displayValue.vue';\n\nexport default {\n props: [\n \"id\"\n ],\n components: {\n \"display-value\" : DisplayValueVue,\n },\n data: function () {\n return {\n \"n\" : null,\n \"debug\": null\n };\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n this.n = this.view.m.getNode(this.id);\n this.debug = this.n.getSnapshot(); // shortcut\n },\n beforeUpdate: function() {\n this.n = this.view.m.getNode(this.id); // it breaks updating node name\n this.debug = this.n.getSnapshot(); // shortcut\n this.$forceupdate();\n },\n mounted: function() {\n\n },\n methods: {\n getSnapshotStatus : function(n) {\n if( this.n.isSnapshotStatus(0) ) return \"IDLE\";\n else if( this.n.isSnapshotStatus(1) ) return \"COMPUTING\";\n else if( this.n.isSnapshotStatus(2) ) return \"WAITING\";\n else if( this.n.isSnapshotStatus(3) ) return \"READY\";\n else throw \"Error: unknown status\";\n },\n\n getInputData: function(key) {\n return this.debug.data[key];\n },\n\n // show number if not null, undefined or 0\n showNumber: function(n) {\n return n? n: \"\";\n },\n\n showTime: function(d) {\n return moment(d).format('HH:mm:ss.SSS');\n }\n }\n}\n</script>\n"]}, media: undefined });
74694
+ inject("data-v-55f6b7e6_0", { source: "\n.card-debug .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/debugNodeInfos.vue"],"names":[],"mappings":";AACA;IACA,eAAA;IACA,iBAAA;IACA,kBAAA;AACA","file":"debugNodeInfos.vue","sourcesContent":["<style>\n .card-debug .card-body {\n font-size: 12px;\n padding-left: 5px;\n padding-right: 5px;\n }\n</style>\n\n<template>\n<div class=\"card-debug h100\" id=\"debug-node\">\n <div style=\"padding-left: 10px; padding-top: 10px; padding-right: 10px;\">\n <h2 class=\"edit-dualbox-node-id\">\n <div class=\"dualbox-node-name\">\n <span class=\"text-truncate d-inline-block\" style=\"width: 290px\" :data-id=\"id\">{{n.graphId}}</span>\n </div>\n <div class=\"dualbox-node-name-edit\" style=\"display: none;\">\n <input type=\"text\" class=\"form-control dualbox-node-name-input\" style=\"display: inline-block;\" :value=\"n.graphId\" :data-type=\"n.type\" autofocus/>\n <button class=\"btn btn-primary btn-save-node-name-change\" :data-id=\"n.graphId\" :data-type=\"n.type\" style=\"display: inline-block;\">Save</button>\n </div>\n </h2>\n <p><small class=\"edit-dualbox-node-package-name\">{{n.getPackageName()}}</small></p>\n </div>\n\n <div class=\"edit-body\">\n <div class=\"card card-state\">\n <div class=\"card-header\" id=\"debug-node-state\" data-toggle=\"collapse\" data-target=\"#debug-node-state-collapse\" aria-expanded=\"true\" aria-controls=\"debug-node-state-collapse\">\n <h5 class=\"mb-0 btn-link\">State</h5>\n </div>\n\n <div id=\"debug-node-state-collapse\" class=\"collapse show\" aria-labelledby=\"debug-node-state\" data-parent=\"#debug-node\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Key</th>\n <th>Value</th>\n </thead>\n <tbody>\n <tr>\n <td>status</td>\n <td><span :class=\"{'card-status-idle':n.isSnapshotStatus(0),'card-status-computing':n.isSnapshotStatus(1),'card-status-awaiting-data':n.isSnapshotStatus(2), 'card-status-ready':n.isSnapshotStatus(3)}\">{{ getSnapshotStatus(n) }}</span></td>\n </tr>\n <tr><td>invalidateSent</td><td>{{debug.state.invalidateSent}}</td></tr>\n <tr><td>readSent</td><td>{{debug.state.readSent}}</td></tr>\n <tr><td>allowedToRestart</td><td>{{debug.state.allowedToRestart}}</td></tr>\n <tr><td>evaluating</td><td>{{debug.state.evaluating}}</td></tr>\n <tr><td>initialized</td><td>{{debug.state.initialized}}</td></tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n\n <div v-if=\"n.hasInputs()\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"debug-node-inputs\" data-toggle=\"collapse\" data-target=\"#debug-node-inputs-collapse\" aria-expanded=\"false\" aria-controls=\"debug-node-inputs-collapse\">\n <h5 class=\"mb-0 btn-link\">Data <small><span class=\"badge badge-secondary\">{{ n.getInputsNames().length }}</span></small></h5>\n </div>\n <div id=\"debug-node-inputs-collapse\" class=\"collapse\" aria-labelledby=\"debug-node-inputs\" data-parent=\"#card-debug\">\n <div class=\"card-body\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Input</th>\n <th>Valid</th>\n <th>Type</th>\n <th>Value</th>\n <th>Default</th>\n </thead>\n <tbody>\n <tr v-for=\"key in n.getInputsNames()\" :key=\"n.id + '-input-' + key\">\n <td>\n {{key}}\n <button v-if=\"n.hasInputDesc(key)\" type=\"button\" class=\"btn btn-transparent\" data-toggle=\"tooltip\" data-placement=\"right\" :title=\"n.getInputDesc(key)\" style=\"padding: 0;\"><i class=\"text-info far fa-question-circle\"></i></button>\n </td>\n <td>{{ getInputData(key).valid }}</td>\n <td>\n <template v-if=\"getInputData(key).value\">\n <template v-if=\"getInputData(key).value.metadata && getInputData(key).value.metadata.type\">{{getInputData(key).value.metadata}}</template>\n <template v-else>{{typeof n.m.getSnapshotValue(getInputData(key).value) }}</template>\n </template>\n </td>\n <td>\n <template v-if=\"getInputData(key).value\">\n <display-value :v=\"n.m.getSnapshotValue(getInputData(key).value)\"></display-value>\n </template>\n </td>\n <td>\n <template v-if=\"getInputData(key).default\">\n <display-value :v=\"n.m.getSnapshotValue(getInputData(key).default)\"></display-value>\n </template>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <div v-if=\"debug.cache\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"debug-node-cache\" data-toggle=\"collapse\" data-target=\"#debug-node-cache-collapse\" aria-expanded=\"false\" aria-controls=\"debug-node-cache-collapse\">\n <h5 class=\"mb-0 btn-link\">Cache</h5>\n </div>\n <div id=\"debug-node-cache-collapse\" class=\"collapse\" aria-labelledby=\"debug-node-cache\" data-parent=\"#card-debug\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Output</th>\n <th>Value</th>\n </thead>\n <tbody>\n <tr v-for=\"key in Object.keys(debug.cache)\" :key=\"n.id + '-cache-' + key\">\n <tr>\n <td>{{key}}</td>\n <td><display-value :v=\"n.m.getSnapshotValue(debug.cache[key])\"></display-value></td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <div v-if=\"debug.times && debug.times.emissions && (debug.times.emissions.lastRead || debug.times.emissions.lastInvalidate || debug.times.emissions.lastData )\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"debug-node-events\" data-toggle=\"collapse\" data-target=\"#debug-node-events-collapse\" aria-expanded=\"false\" aria-controls=\"debug-node-events-collapse\">\n <h5 class=\"mb-0 btn-link\">Last events</h5>\n </div>\n <div id=\"debug-node-events-collapse\" class=\"collapse\" aria-labelledby=\"debug-node-events\" data-parent=\"#card-debug\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n\n <div v-if=\"debug.times.emissions.lastRead\" class=\"mb-3\">\n <p><b><u>Last read {{showNumber(debug.times.emissions.nbRead)}}</u> <span class=\"float-right\">{{ showTime(debug.times.emissions.lastRead.date) }}</span></b></p>\n <span>Missing: <b>{{ debug.times.emissions.lastRead.data.join(', ') }}</b></span><br/>\n </div>\n\n <div v-if=\"debug.times.emissions.lastInvalidate\" class=\"mb-3\">\n <p><b><u>Last Invalidate {{showNumber(debug.times.emissions.nbInvalidate)}}</u> <span class=\"float-right\">{{ showTime(debug.times.emissions.lastInvalidate.date) }}</span></b></p>\n <span>Invalidated keys: <b>{{ debug.times.emissions.lastInvalidate.data.join(', ') }}</b></span><br/>\n </div>\n\n <div v-if=\"debug.times.emissions.lastData\" class=\"mb-3\">\n <p><b><u>Last Data {{ showNumber(debug.times.emissions.nbData) }}</u> <span class=\"float-right\">{{ showTime(debug.times.emissions.lastData.date) }}</span></b></p>\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Output</th>\n <th>Value</th>\n </thead>\n <tbody>\n <tr v-for=\"key in Object.keys(debug.times.emissions.lastData.data)\" :key=\"n.id + '-cache-' + key\">\n <td>{{key}}</td>\n <td><display-value :v=\"n.m.getSnapshotValue(debug.times.emissions.lastData.data[key])\"></display-value></td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n\n <div v-if=\"debug.times && debug.times.evaluations && (debug.times.evaluations.lastStart || debug.times.evaluations.lastEnd || debug.times.evaluations.lastCancel )\" class=\"card card-settings\">\n <div class=\"card-header\" id=\"debug-node-evaluations\" data-toggle=\"collapse\" data-target=\"#debug-node-evaluations-collapse\" aria-expanded=\"false\" aria-controls=\"debug-node-evaluations-collapse\">\n <h5 class=\"mb-0 btn-link\">Last evaluations</h5>\n </div>\n <div id=\"debug-node-evaluations-collapse\" class=\"collapse\" aria-labelledby=\"debug-node-evaluations\" data-parent=\"#card-debug\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n\n <div v-if=\"debug.times.evaluations.lastStart\" class=\"mb-3\">\n <p><b><u>Last start</u> <span class=\"float-right\">{{ showTime(debug.times.evaluations.lastStart.date) }}</span></b></p>\n </div>\n\n <div v-if=\"debug.times.evaluations.lastEnd\" class=\"mb-3\">\n <p><b><u>Last end</u> <span class=\"float-right\">{{ showTime(debug.times.evaluations.lastEnd.date) }}</span></b></p>\n </div>\n\n <div v-if=\"debug.times.evaluations.lastCancel\" class=\"mb-3\">\n <p><b><u>Last Cancel</u> <span class=\"float-right\">{{ showTime(debug.times.evaluations.lastCancel.date) }}</span></b></p>\n <span>reason: <b>{{ debug.times.evaluations.lastCancel.reason }}</b></span><br/>\n </div>\n </div>\n </div>\n </div>\n\n\n <div v-if=\"debug.performances\" class=\"card card-performances\">\n <div class=\"card-header\" id=\"debug-node-performances\" data-toggle=\"collapse\" data-target=\"#debug-node-performances-collapse\" aria-expanded=\"false\" aria-controls=\"debug-node-performances-collapse\">\n <h5 class=\"mb-0 btn-link\">Performances</h5>\n </div>\n\n <div id=\"debug-node-performances-collapse\" class=\"collapse\" aria-labelledby=\"debug-node-performances\" data-parent=\"#debug-node\">\n <div class=\"card-body\" style=\"padding-left: 15px;\">\n <table class=\"table-desc table-striped\">\n <thead class=\"thead-dark\">\n <th>Stat</th>\n <th>Value</th>\n </thead>\n <tbody>\n <tr><td>min</td><td>{{debug.performances.min && debug.performances.min.toFixed(0)}}ms</td></tr>\n <tr><td>max</td><td>{{debug.performances.max && debug.performances.max.toFixed(0)}}ms</td></tr>\n <tr><td>avg</td><td>{{debug.performances.avg && debug.performances.avg.toFixed(0)}}ms</td></tr>\n <tr><td>total</td><td>{{debug.performances.total && debug.performances.total.toFixed(0)}}ms</td></tr>\n <tr><td>Nb of runs</td><td>{{debug.performances.nbRuns}}</td></tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"modal debug-json-modal\" tabindex=\"-1\" role=\"dialog\">\n <div class=\"modal-dialog\" role=\"document\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">Value debugger</h5>\n <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n </div>\n <div class=\"modal-body\">\n <div class=\"json-editor\" style=\"height: 400px;\"></div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-primary btn-save\">Save changes</button>\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n</template>\n\n<script>\nimport _ from 'lodash-es';\nimport moment from 'moment';\n\nimport DisplayValueVue from './displayValue.vue';\n\nexport default {\n props: [\n \"id\"\n ],\n components: {\n \"display-value\" : DisplayValueVue,\n },\n data: function () {\n return {\n \"n\" : null,\n \"debug\": null\n };\n },\n created: function() {\n this.view = window.dualboxEditor.v;\n this.n = this.view.m.getNode(this.id);\n this.debug = this.n.getSnapshot(); // shortcut\n },\n beforeUpdate: function() {\n this.n = this.view.m.getNode(this.id); // it breaks updating node name\n this.debug = this.n.getSnapshot(); // shortcut\n },\n mounted: function() {\n\n },\n methods: {\n getSnapshotStatus : function(n) {\n if( this.n.isSnapshotStatus(0) ) return \"IDLE\";\n else if( this.n.isSnapshotStatus(1) ) return \"COMPUTING\";\n else if( this.n.isSnapshotStatus(2) ) return \"WAITING\";\n else if( this.n.isSnapshotStatus(3) ) return \"READY\";\n else throw \"Error: unknown status\";\n },\n\n getInputData: function(key) {\n return this.debug.data[key];\n },\n\n // show number if not null, undefined or 0\n showNumber: function(n) {\n return n? n: \"\";\n },\n\n showTime: function(d) {\n return moment(d).format('HH:mm:ss.SSS');\n }\n }\n}\n</script>\n"]}, media: undefined });
74700
74695
 
74701
74696
  };
74702
74697
  /* scoped */
@@ -88562,11 +88557,10 @@ class GraphView {
88562
88557
  }
88563
88558
 
88564
88559
  async openDebug(id) {
88565
- var expandDebug = () => {
88566
- this.div.find('.dualbox-editor-body').trigger('expandDebug');
88567
- };
88560
+ await this.setDebugMenu(id);
88568
88561
 
88569
- return await this.setDebugMenu(id, expandDebug);
88562
+ // TODO: do this the vue.js way
88563
+ this.div.find('.dualbox-editor-body').trigger('expandDebug');
88570
88564
  }
88571
88565
 
88572
88566
  // TODO: use proper vue.js reactivity here
@@ -93,6 +93,7 @@ class History {
93
93
  save() {
94
94
  if (!this._holdSaving) {
95
95
  var currentAppClone = this.clone(this.m.data);
96
+ currentAppClone.root = this.m.getCleanJson(); // if it's a snapshot, remove the extra infos
96
97
  var previousHash = hash(this.lastState.root)
97
98
  var diff = patcher.diff(this.lastState, currentAppClone);
98
99
  if (diff) {
@@ -268,11 +268,10 @@ class GraphView {
268
268
  }
269
269
 
270
270
  async openDebug(id) {
271
- var expandDebug = () => {
272
- this.div.find('.dualbox-editor-body').trigger('expandDebug');
273
- };
271
+ await this.setDebugMenu(id);
274
272
 
275
- return await this.setDebugMenu(id, expandDebug);
273
+ // TODO: do this the vue.js way
274
+ this.div.find('.dualbox-editor-body').trigger('expandDebug');
276
275
  }
277
276
 
278
277
  // TODO: use proper vue.js reactivity here
@@ -80,12 +80,12 @@
80
80
  </td>
81
81
  <td>
82
82
  <template v-if="getInputData(key).value">
83
- <display-value :v="n.m.getSnapshotValue(getInputData(key).value)" readonly=true></display-value>
83
+ <display-value :v="n.m.getSnapshotValue(getInputData(key).value)"></display-value>
84
84
  </template>
85
85
  </td>
86
86
  <td>
87
87
  <template v-if="getInputData(key).default">
88
- <display-value :v="n.m.getSnapshotValue(getInputData(key).default)" readonly=true></display-value>
88
+ <display-value :v="n.m.getSnapshotValue(getInputData(key).default)"></display-value>
89
89
  </template>
90
90
  </td>
91
91
  </tr>
@@ -110,7 +110,7 @@
110
110
  <tr v-for="key in Object.keys(debug.cache)" :key="n.id + '-cache-' + key">
111
111
  <tr>
112
112
  <td>{{key}}</td>
113
- <td><display-value :v="n.m.getSnapshotValue(debug.cache[key])" readonly=true></display-value></td>
113
+ <td><display-value :v="n.m.getSnapshotValue(debug.cache[key])"></display-value></td>
114
114
  </tr>
115
115
  }
116
116
  </tbody>
@@ -146,7 +146,7 @@
146
146
  <tbody>
147
147
  <tr v-for="key in Object.keys(debug.times.emissions.lastData.data)" :key="n.id + '-cache-' + key">
148
148
  <td>{{key}}</td>
149
- <td><display-value :v="n.m.getSnapshotValue(debug.times.emissions.lastData.data[key])" readonly=true></display-value></td>
149
+ <td><display-value :v="n.m.getSnapshotValue(debug.times.emissions.lastData.data[key])"></display-value></td>
150
150
  </tr>
151
151
  </tbody>
152
152
  </table>
@@ -254,7 +254,6 @@ export default {
254
254
  beforeUpdate: function() {
255
255
  this.n = this.view.m.getNode(this.id); // it breaks updating node name
256
256
  this.debug = this.n.getSnapshot(); // shortcut
257
- this.$forceupdate();
258
257
  },
259
258
  mounted: function() {
260
259
 
@@ -207,8 +207,7 @@ export default {
207
207
  if( ["string", "number", "boolean", "array", "map"].indexOf(this.dataType) == -1 ) {
208
208
  this.dataType = "object";
209
209
  }
210
-
211
- console.log(`Type: ${this.type}, Datatype: ${this.dataType}, embeddedType: ${this.embeddedType}`);
210
+ //console.log(`Type: ${this.type}, Datatype: ${this.dataType}, embeddedType: ${this.embeddedType}`);
212
211
  },
213
212
 
214
213
  initData: function() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dualbox/editor",
3
- "version": "1.0.70",
3
+ "version": "1.0.71",
4
4
  "description": "Editor of Dualbox apps",
5
5
  "browser": "js/dist/GraphEditor.js",
6
6
  "main": "js/dist/GraphEditor.js",