@dualbox/editor 1.0.59 → 1.0.61

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.
@@ -43595,6 +43595,7 @@ class GraphNode {
43595
43595
  return this.setAttributeValue(name, val);
43596
43596
  }
43597
43597
  }
43598
+ this.m.save();
43598
43599
  }
43599
43600
 
43600
43601
  deleteVal(srcType, name) {
@@ -43603,6 +43604,7 @@ class GraphNode {
43603
43604
  } else if (srcType === "attr" && this.def.attr) {
43604
43605
  delete this.def.attr[name];
43605
43606
  }
43607
+ this.m.save();
43606
43608
  }
43607
43609
 
43608
43610
  getValueType(srcType, name) {
@@ -63617,7 +63619,7 @@ var script$8 = {
63617
63619
  else if( resolvedType.startsWith("map") ) {
63618
63620
  templateType = "map";
63619
63621
  this.deserializedValue = window.DualBox.Type.deserialize(this.v || {
63620
- "metadata":{
63622
+ "metadata":{
63621
63623
  "type":"Map<String,"+ this.firstLetterUppercase( this.getEmbeddedType(resolvedType) )+">"
63622
63624
  },
63623
63625
  "data": {}
@@ -63760,7 +63762,7 @@ var script$8 = {
63760
63762
  firstLetterUppercase: function(s) {
63761
63763
  return s.charAt(0).toUpperCase() + s.slice(1)
63762
63764
  },
63763
-
63765
+
63764
63766
  selectIndex: function(index) {
63765
63767
  if( this.selectedIndex !== index ) {
63766
63768
  this.selectedIndex = index;
@@ -64066,7 +64068,7 @@ var __vue_render__$8 = function() {
64066
64068
  _vm.selectedIndex !== null
64067
64069
  ? _c("edit-value", {
64068
64070
  attrs: {
64069
- cIndex: _vm.edit - _vm.value,
64071
+ cIndex: _vm.selectedIndex,
64070
64072
  type: _vm.embeddedType,
64071
64073
  v: _vm.getElement(_vm.selectedIndex)
64072
64074
  },
@@ -64131,11 +64133,11 @@ __vue_render__$8._withStripped = true;
64131
64133
  /* style */
64132
64134
  const __vue_inject_styles__$8 = function (inject) {
64133
64135
  if (!inject) return
64134
- inject("data-v-19f6a0fe_0", { source: "\n.template-value-container[data-v-19f6a0fe], .field-editor[data-v-19f6a0fe] {\n margin-bottom: 10px;\n}\n.template-value-message[data-v-19f6a0fe] {\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=\"edit-value\" :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';\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.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 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 }\n else if( this.isObjectType() ) {\n // emit the result to the parent Vue\n this.$emit(\"edited\", this.editor.get());\n }\n },\n\n setStringValue: function(e) {\n var val = $(e.target).val();\n this.$emit(\"edited\", val);\n },\n\n setBoolValue: function(e) {\n var val = $(e.target).val() == \"true\";\n this.$emit(\"edited\", val);\n },\n\n setNumberValue: function(e) {\n var val = parseFloat($(e.target).val());\n this.$emit(\"edited\", val);\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 });
64136
+ inject("data-v-3b261ff7_0", { source: "\n.template-value-container[data-v-3b261ff7], .field-editor[data-v-3b261ff7] {\n margin-bottom: 10px;\n}\n.template-value-message[data-v-3b261ff7] {\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';\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.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 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 }\n else if( this.isObjectType() ) {\n // emit the result to the parent Vue\n this.$emit(\"edited\", this.editor.get());\n }\n },\n\n setStringValue: function(e) {\n var val = $(e.target).val();\n this.$emit(\"edited\", val);\n },\n\n setBoolValue: function(e) {\n var val = $(e.target).val() == \"true\";\n this.$emit(\"edited\", val);\n },\n\n setNumberValue: function(e) {\n var val = parseFloat($(e.target).val());\n this.$emit(\"edited\", val);\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 });
64135
64137
 
64136
64138
  };
64137
64139
  /* scoped */
64138
- const __vue_scope_id__$8 = "data-v-19f6a0fe";
64140
+ const __vue_scope_id__$8 = "data-v-3b261ff7";
64139
64141
  /* module identifier */
64140
64142
  const __vue_module_identifier__$8 = undefined;
64141
64143
  /* functional template */
@@ -993,6 +993,7 @@ class GraphNode {
993
993
  return this.setAttributeValue(name, val);
994
994
  }
995
995
  }
996
+ this.m.save();
996
997
  }
997
998
 
998
999
  deleteVal(srcType, name) {
@@ -1001,6 +1002,7 @@ class GraphNode {
1001
1002
  } else if (srcType === "attr" && this.def.attr) {
1002
1003
  delete this.def.attr[name];
1003
1004
  }
1005
+ this.m.save();
1004
1006
  }
1005
1007
 
1006
1008
  getValueType(srcType, name) {
@@ -41,7 +41,7 @@
41
41
  <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>
42
42
  </div>
43
43
  <div class="col" style="padding: 10px">
44
- <edit-value v-if="selectedIndex !== undefined && selectedIndex !== null" :cIndex="edit-value" :type="embeddedType" :v="getElement(selectedIndex)" @edited="onSubValueEdited(selectedIndex, $event)"></edit-value>
44
+ <edit-value v-if="selectedIndex !== undefined && selectedIndex !== null" :cIndex="selectedIndex" :type="embeddedType" :v="getElement(selectedIndex)" @edited="onSubValueEdited(selectedIndex, $event)"></edit-value>
45
45
  <p v-else class="template-value-message">Select an element to edit.</p>
46
46
  </div>
47
47
  </div>
@@ -168,7 +168,7 @@ export default {
168
168
  else if( resolvedType.startsWith("map") ) {
169
169
  templateType = "map";
170
170
  this.deserializedValue = window.DualBox.Type.deserialize(this.v || {
171
- "metadata":{
171
+ "metadata":{
172
172
  "type":"Map<String,"+ this.firstLetterUppercase( this.getEmbeddedType(resolvedType) )+">"
173
173
  },
174
174
  "data": {}
@@ -311,7 +311,7 @@ export default {
311
311
  firstLetterUppercase: function(s) {
312
312
  return s.charAt(0).toUpperCase() + s.slice(1)
313
313
  },
314
-
314
+
315
315
  selectIndex: function(index) {
316
316
  if( this.selectedIndex !== index ) {
317
317
  this.selectedIndex = index;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dualbox/editor",
3
- "version": "1.0.59",
3
+ "version": "1.0.61",
4
4
  "description": "Editor of Dualbox apps",
5
5
  "browser": "js/dist/GraphEditor.js",
6
6
  "main": "js/dist/GraphEditor.js",