@dualbox/editor 1.0.71 → 1.0.73

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.
@@ -1,55 +1,62 @@
1
1
  <style scoped>
2
- .template-value-container, .field-editor {
3
- margin-bottom: 10px;
4
- }
2
+ .template-value-container,
3
+ .field-editor {
4
+ margin-bottom: 10px;
5
+ }
5
6
 
6
- .template-value-message {
7
- text-align: center;
8
- margin-top: 30px;
9
- margin-bottom: 30px;
10
- width: 100%;
11
- opacity: 0.5;
12
- }
7
+ .template-value-message {
8
+ text-align: center;
9
+ margin-top: 30px;
10
+ margin-bottom: 30px;
11
+ width: 100%;
12
+ opacity: 0.5;
13
+ }
13
14
  </style>
14
15
 
15
16
  <template>
16
17
  <div class="w-100">
17
18
  <p style="display: none;">{{cIndex}}</p>
18
19
  <template v-if="isBasicDataType()">
19
- <template v-if="dataType === 'string'">
20
- <input class="edit-value-input" type="text" @keyup.enter="setStringValue" @keyup.esc="setStringValue" :value="v" @focus="$event.target.select()"></input>
21
- </template>
22
- <template v-else-if="dataType === 'boolean'">
23
- <select class="edit-value-input" @change="setBoolValue">
24
- <option value="true" :selected="v == true">True</option>
25
- <option value="false" :selected="v == false">False</option>
26
- </select>
27
- </template>
28
- <template v-else-if="dataType === 'number'">
29
- <input class="edit-value-input" type="number" @keyup.enter="setNumberValue" @blur="setNumberValue" :value="v" @focus="$event.target.select()" style="width: 40px;"></input>
30
- </template>
20
+ <template v-if="dataType === 'string'">
21
+ <input class="edit-value-input" type="text" @keyup.enter="setStringValue" @keyup.esc="setStringValue" :value="v" @focus="$event.target.select()"></input>
22
+ </template>
23
+
24
+ <template v-else-if="dataType === 'boolean'">
25
+ <select class="edit-value-input" @change="setBoolValue">
26
+ <option value="true" :selected="v == true">True</option>
27
+ <option value="false" :selected="v == false">False</option>
28
+ </select>
29
+ </template>
30
+
31
+ <template v-else-if="dataType === 'number'">
32
+ <input class="edit-value-input" type="number" @keyup.enter="setNumberValue" @blur="setNumberValue" :value="v" @focus="$event.target.select()" style="width: 40px;">
33
+ </input>
34
+ </template>
31
35
  </template>
32
- <template v-else>
33
- <!-- we already are in a modal, don't instanciate another one -->
34
- <template v-if="isTemplateType()">
35
- <div class="container template-value-container" style="border: 1px solid rgba(0, 0, 0, 0.125);">
36
- <div v-if="isArrayType()" class="row" style="background-color: rgba(0,0,0,.125);">Array Editor</div>
37
- <div v-else-if="isMapType()" class="row" style="background-color: rgba(0,0,0,.125);">Map Editor</div>
38
- <div class="row" style="1px solid rgba(0,0,0,.125);">
39
- <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);">
40
- <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>
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
- </div>
43
- <div class="col" style="padding: 10px">
44
- <edit-value v-if="selectedIndex !== undefined && selectedIndex !== null" :cIndex="selectedIndex" :type="embeddedType" :v="getElement(selectedIndex)" @edited="onSubValueEdited(selectedIndex, $event)"></edit-value>
45
- <p v-else class="template-value-message">Select an element to edit.</p>
36
+
37
+ <template v-else>
38
+ <!-- we already are in a modal, don't instanciate another one -->
39
+ <template v-if="isTemplateType()">
40
+ <div class="container template-value-container" style="border: 1px solid rgba(0, 0, 0, 0.125);">
41
+ <div v-if="isArrayType()" class="row" style="background-color: rgba(0,0,0,.125);">Array Editor</div>
42
+ <div v-else-if="isMapType()" class="row" style="background-color: rgba(0,0,0,.125);">Map Editor</div>
43
+ <div class="row" style="1px solid rgba(0,0,0,.125);">
44
+ <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);">
45
+ <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>
46
+ <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>
47
+ </div>
48
+ <div class="col" style="padding: 10px">
49
+ <edit-value v-if="selectedIndex !== undefined && selectedIndex !== null" :cIndex="selectedIndex" :type="embeddedType" :v="getElement(selectedIndex)" @edited="onSubValueEdited(selectedIndex, $event)"></edit-value>
50
+ <p v-else class="template-value-message">Select an element to edit.</p>
51
+ </div>
46
52
  </div>
47
53
  </div>
48
- </div>
49
- </template>
50
- <template v-else>
51
- <div class="field-editor" :data-value="hash()"></div>
52
- </template>
54
+ </template>
55
+
56
+ <template v-else>
57
+ <div class="field-editor" :data-value="hash()">
58
+ </div>
59
+ </template>
53
60
  </template>
54
61
 
55
62
  <!-- set null and delete buttons -->
@@ -67,34 +74,35 @@ import swal from 'sweetalert2';
67
74
  import JSONEditor from '@dualbox/dualbox-lib-jsoneditor';
68
75
 
69
76
  String.prototype.hashCode = function() {
70
- var hash = 0, i, chr;
77
+ var hash = 0,
78
+ i, chr;
71
79
  if (this.length === 0) return hash;
72
80
  for (i = 0; i < this.length; i++) {
73
- chr = this.charCodeAt(i);
74
- hash = ((hash << 5) - hash) + chr;
81
+ chr = this.charCodeAt(i);
82
+ hash = ((hash << 5) - hash) + chr;
75
83
  hash |= 0; // Convert to 32bit integer
76
84
  }
77
85
  return hash;
78
86
  };
79
87
 
80
88
  export default {
81
- name : "edit-value",
89
+ name: "edit-value",
82
90
  props: [
83
91
  // required
84
- "v", // the value
85
- "type", // the dualbox type of the value
92
+ "v", // the value
93
+ "type", // the dualbox type of the value
86
94
 
87
95
  // specific properties (for recursivity)
88
- "cIndex" // index for reference when in an array
96
+ "cIndex" // index for reference when in an array
89
97
  ],
90
- data: function () {
98
+ data: function() {
91
99
  return {
92
- "dataType": null, // the real javascript dataType of this.v
100
+ "dataType": null, // the real javascript dataType of this.v
93
101
  "deserializedValue": null,
94
102
 
95
103
  // if type is a collection (dataType=="map" or dataType=="array")
96
- "embeddedType": null, // the embedded type of this templated collection
97
- "selectedIndex": null, // the current index of the element we are editing
104
+ "embeddedType": null, // the embedded type of this templated collection
105
+ "selectedIndex": null, // the current index of the element we are editing
98
106
  };
99
107
  },
100
108
  created: function() {
@@ -114,23 +122,21 @@ export default {
114
122
  this.updateData();
115
123
  },
116
124
  updated: function() {
117
- if( this.autochange ) {
125
+ if (this.autochange) {
118
126
  // change triggered by ourself, skip
119
127
  this.autochange = false;
120
- }
121
- else {
128
+ } else {
122
129
  this.updateEditor();
123
130
  }
124
131
  },
125
132
  beforeDestroy: function() {
126
133
  // make sure the value was set
127
- if( !this.emitted ) {
128
- if( this.isBasicDataType()) {
134
+ if (!this.emitted) {
135
+ if (this.isBasicDataType()) {
129
136
  var elt = $(this.$el).find('.edit-value-input');
130
137
  var val = elt.val();
131
138
  this.$emit("edited", val);
132
- }
133
- else {
139
+ } else {
134
140
  this.saveChanges();
135
141
  }
136
142
  }
@@ -138,28 +144,27 @@ export default {
138
144
  methods: {
139
145
  hash: function() {
140
146
  var str = new String(this.v).toString();
141
- return str.split('').reduce((prevHash, currVal) => (((prevHash << 5) - prevHash) + currVal.charCodeAt(0))|0, 0);
147
+ return str.split('').reduce((prevHash, currVal) => (((prevHash << 5) - prevHash) + currVal.charCodeAt(0)) | 0, 0);
142
148
  },
143
149
 
144
150
  updateEditor: function() {
145
- if( this.dataType === "object" ) {
146
- if( !this.editor && $(this.$el).find('.field-editor')[0] !== undefined ) {
151
+ if (this.dataType === "object") {
152
+ if (!this.editor && $(this.$el).find('.field-editor')[0] !== undefined) {
147
153
  // bind the json editor
148
154
  this.editor = new JSONEditor(
149
155
  $(this.$el).find('.field-editor')[0], {
150
- modes: ['tree', 'code', 'text' ],
156
+ modes: ['tree', 'code', 'text'],
151
157
  onChange: () => {
152
158
  try {
153
159
  var json = this.editor.get();
154
160
  this.autochange = true;
155
161
  this.$emit('edited', json);
156
- }
157
- catch(e) {}
162
+ } catch (e) {}
158
163
  }
159
164
  });
160
165
  }
161
166
 
162
- if( this.editor ) {
167
+ if (this.editor) {
163
168
  this.editor.set(this.v || {});
164
169
  }
165
170
  }
@@ -169,42 +174,40 @@ export default {
169
174
  var resolvedType = this.type ? this.type.toLowerCase() : typeof this.v;
170
175
 
171
176
  // If "*", resolve the type by detecting it dynamically from value
172
- if( resolvedType.indexOf("*") !== -1 ) {
177
+ if (resolvedType.indexOf("*") !== -1) {
173
178
  resolvedType = window.DualBox.Type.detectType(this.v).toLowerCase();
174
179
  }
175
180
 
176
181
  // Check if we have a template type. If so, determine current index and embedded type
177
182
  var templateType = null;
178
- if( resolvedType.startsWith("array") ) {
183
+ if (resolvedType.startsWith("array")) {
179
184
  templateType = "array";
180
185
  this.deserializedValue = this.v || [];
181
- }
182
- else if( resolvedType.startsWith("map") ) {
186
+ } else if (resolvedType.startsWith("map")) {
183
187
  templateType = "map";
184
188
  this.deserializedValue = window.DualBox.Type.deserialize(this.v || {
185
- "metadata":{
186
- "type":"Map<String,"+ this.firstLetterUppercase( this.getEmbeddedType(resolvedType) )+">"
189
+ "metadata": {
190
+ "type": "Map<String," + this.firstLetterUppercase(this.getEmbeddedType(resolvedType)) + ">"
187
191
  },
188
192
  "data": {}
189
193
  });
190
194
  }
191
195
 
192
- if( templateType ) {
196
+ if (templateType) {
193
197
  this.dataType = templateType;
194
198
  this.embeddedType = this.getEmbeddedType(resolvedType);
195
- if( this.selectedIndex == null ) {
199
+ if (this.selectedIndex == null) {
196
200
  var firstKey = this.deserializedValue.keys().next();
197
- if( firstKey && firstKey.value ) {
201
+ if (firstKey && firstKey.value) {
198
202
  this.selectedIndex = firstKey.value;
199
203
  }
200
204
  }
201
- }
202
- else {
205
+ } else {
203
206
  this.dataType = resolvedType;
204
207
  }
205
208
 
206
209
  // Finally, transform to object if not a basic value
207
- if( ["string", "number", "boolean", "array", "map"].indexOf(this.dataType) == -1 ) {
210
+ if (["string", "number", "boolean", "array", "map"].indexOf(this.dataType) == -1) {
208
211
  this.dataType = "object";
209
212
  }
210
213
  //console.log(`Type: ${this.type}, Datatype: ${this.dataType}, embeddedType: ${this.embeddedType}`);
@@ -220,22 +223,20 @@ export default {
220
223
  this.resolveDatatype();
221
224
  },
222
225
 
223
- isBasicDataType() {
226
+ isBasicDataType() {
224
227
  return this.dataType == "string" ||
225
228
  this.dataType == "number" ||
226
229
  this.dataType == "boolean";
227
230
  },
228
231
 
229
- serialize( value ) {
230
- if( this.isTemplateType() ) {
231
- if( this.isArrayType() ) {
232
+ serialize(value) {
233
+ if (this.isTemplateType()) {
234
+ if (this.isArrayType()) {
232
235
  return value; // we store arrays as is
233
- }
234
- else if( this.isMapType() ) {
236
+ } else if (this.isMapType()) {
235
237
  return window.DualBox.Type.serialize(value);
236
238
  }
237
- }
238
- else {
239
+ } else {
239
240
  return value;
240
241
  }
241
242
  },
@@ -243,11 +244,10 @@ export default {
243
244
  saveChanges: function() {
244
245
  this.$forceUpdate();
245
246
 
246
- if( this.isTemplateType() ) {
247
+ if (this.isTemplateType()) {
247
248
  this.$emit("edited", this.serialize(this.deserializedValue));
248
249
  this.emitted = true;
249
- }
250
- else if( this.isObjectType() ) {
250
+ } else if (this.isObjectType()) {
251
251
  // emit the result to the parent Vue
252
252
  this.$emit("edited", this.editor.get());
253
253
  this.emitted = true;
@@ -268,8 +268,13 @@ export default {
268
268
 
269
269
  setNumberValue: function(e) {
270
270
  var val = parseFloat($(e.target).val());
271
- this.$emit("edited", val);
272
- this.emitted = true;
271
+ if (isNaN(val)) {
272
+ this.deleteValue(e);
273
+ }
274
+ else {
275
+ this.$emit("edited", val);
276
+ this.emitted = true;
277
+ }
273
278
  },
274
279
 
275
280
  setNullValue: function() {
@@ -280,10 +285,9 @@ export default {
280
285
  },
281
286
 
282
287
  selectNextIndex: function() {
283
- if( this.isArrayType() ) {
288
+ if (this.isArrayType()) {
284
289
  this.selectedIndex = this.deserializedValue.length > 0 ? 0 : null;
285
- }
286
- else if( this.isMapType() ) {
290
+ } else if (this.isMapType()) {
287
291
  var keys = this.deserializedValue.keys();
288
292
  var next = keys.next();
289
293
  this.selectedIndex = next ? next.value : null;
@@ -316,22 +320,21 @@ export default {
316
320
 
317
321
  getEmbeddedType: function(type) {
318
322
  var start = type.indexOf('<') + 1;
319
- var end = type.lastIndexOf('>');
320
- if( type.toLowerCase().startsWith('array') ) {
323
+ var end = type.lastIndexOf('>');
324
+ if (type.toLowerCase().startsWith('array')) {
321
325
  return type.substr(start, end - start).trim().toLowerCase();
322
- }
323
- else if( type.toLowerCase().startsWith('map') ) {
326
+ } else if (type.toLowerCase().startsWith('map')) {
324
327
  var sub = type.substr(start, end - start);
325
328
  return sub.substr(sub.indexOf(',') + 1).trim().toLowerCase();
326
329
  }
327
330
  },
328
331
 
329
- firstLetterUppercase: function(s) {
332
+ firstLetterUppercase: function(s) {
330
333
  return s.charAt(0).toUpperCase() + s.slice(1)
331
334
  },
332
335
 
333
336
  selectIndex: function(index) {
334
- if( this.selectedIndex !== index ) {
337
+ if (this.selectedIndex !== index) {
335
338
  this.selectedIndex = index;
336
339
  this.$forceUpdate();
337
340
  }
@@ -342,30 +345,26 @@ export default {
342
345
  },
343
346
 
344
347
  getElement: function(i) {
345
- if( Array.isArray(this.v) ) {
348
+ if (Array.isArray(this.v)) {
346
349
  return this.deserializedValue[i];
347
- }
348
- else {
350
+ } else {
349
351
  return this.deserializedValue.get(i);
350
352
  }
351
353
  },
352
354
 
353
355
  onSubValueEdited: function(index, newValue) {
354
356
  console.log(`Edited at index ${index}: ${JSON.stringify(newValue)}`);
355
- if( this.isArrayType() ) {
356
- if( newValue === undefined ) {
357
+ if (this.isArrayType()) {
358
+ if (newValue === undefined) {
357
359
  // we just remove this value
358
360
  this.deserializedValue.splice(index, 1);
359
- }
360
- else {
361
+ } else {
361
362
  this.deserializedValue[index] = newValue;
362
363
  }
363
- }
364
- else if ( this.isMapType() ) {
365
- if( newValue === undefined ) {
364
+ } else if (this.isMapType()) {
365
+ if (newValue === undefined) {
366
366
  this.deserializedValue.delete(index);
367
- }
368
- else {
367
+ } else {
369
368
  this.deserializedValue.set(index, newValue);
370
369
  }
371
370
  }
@@ -374,20 +373,19 @@ export default {
374
373
  },
375
374
 
376
375
  addItem: function() {
377
- if( this.isArrayType() ) {
378
- this.deserializedValue[ this.deserializedValue.length ] = null;
376
+ if (this.isArrayType()) {
377
+ this.deserializedValue[this.deserializedValue.length] = null;
379
378
  this.selectedIndex = this.deserializedValue.length - 1;
380
379
  this.saveChanges();
381
380
  this.$forceUpdate();
382
- }
383
- else if( this.isMapType() ) {
381
+ } else if (this.isMapType()) {
384
382
  this.swalFixBootstrapModal();
385
383
  swal({
386
384
  input: 'text',
387
385
  title: 'Enter map key',
388
386
  }).then((result) => {
389
387
  this.swalRestoreBootstrapModal();
390
- if( result && result.value ) {
388
+ if (result && result.value) {
391
389
  this.selectedIndex = result.value;
392
390
  this.deserializedValue.set(result.value, null);
393
391
  this.saveChanges();
@@ -399,18 +397,18 @@ export default {
399
397
 
400
398
  // call this before showing SweetAlert:
401
399
  swalFixBootstrapModal() {
402
- var modal = $("body").find('.modal[tabindex="-1"]');
403
- if (!modal) return;
404
- modal.removeAttr('tabindex');
405
- modal.addClass('js-swal-fixed');
400
+ var modal = $("body").find('.modal[tabindex="-1"]');
401
+ if (!modal) return;
402
+ modal.removeAttr('tabindex');
403
+ modal.addClass('js-swal-fixed');
406
404
  },
407
405
 
408
406
  // call this before hiding SweetAlert (inside done callback):
409
407
  swalRestoreBootstrapModal() {
410
- var modal = $("body").find('.modal.js-swal-fixed');
411
- if (!modal) return;
412
- modal.attr('tabindex', '-1');
413
- modal.removeClass('js-swal-fixed');
408
+ var modal = $("body").find('.modal.js-swal-fixed');
409
+ if (!modal) return;
410
+ modal.attr('tabindex', '-1');
411
+ modal.removeClass('js-swal-fixed');
414
412
  }
415
413
  }
416
414
  }