@dualbox/editor 1.0.1 → 1.0.2

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.
Files changed (43) hide show
  1. package/js/src/GraphEditor.js +159 -0
  2. package/js/src/c/GraphController.js +646 -0
  3. package/js/src/libs/CodeMirror.js +8 -0
  4. package/js/src/libs/fontawesome.js +1 -0
  5. package/js/src/libs/jsoneditor.css +2 -0
  6. package/js/src/libs/jsoneditor.js +4 -0
  7. package/js/src/m/DualboxUtils.js +35 -0
  8. package/js/src/m/GraphModel.js +2167 -0
  9. package/js/src/m/History.js +94 -0
  10. package/js/src/m/Merger.js +357 -0
  11. package/js/src/v/AppManager.js +61 -0
  12. package/js/src/v/CanvasSizeHandler.js +136 -0
  13. package/js/src/v/ContextMenu.css +45 -0
  14. package/js/src/v/ContextMenu.js +239 -0
  15. package/js/src/v/GraphView.js +928 -0
  16. package/js/src/v/PlumbStyle.js +254 -0
  17. package/js/src/v/Selector.js +239 -0
  18. package/js/src/v/TemplateManager.js +79 -0
  19. package/js/src/v/Translater.js +174 -0
  20. package/js/src/v/Utils.js +7 -0
  21. package/js/src/v/Zoomer.js +201 -0
  22. package/js/src/v/templates/addNode.css +45 -0
  23. package/js/src/v/templates/addNode.html +62 -0
  24. package/js/src/v/templates/addNode.js +34 -0
  25. package/js/src/v/templates/debugNodeInfos.css +5 -0
  26. package/js/src/v/templates/debugNodeInfos.html +336 -0
  27. package/js/src/v/templates/debugNodeInfos.js +31 -0
  28. package/js/src/v/templates/editMainSettings.css +67 -0
  29. package/js/src/v/templates/editMainSettings.html +265 -0
  30. package/js/src/v/templates/editMainSettings.js +240 -0
  31. package/js/src/v/templates/editNodeSettings.css +86 -0
  32. package/js/src/v/templates/editNodeSettings.html +539 -0
  33. package/js/src/v/templates/editNodeSettings.js +356 -0
  34. package/js/src/v/templates/graphNode.css +333 -0
  35. package/js/src/v/templates/graphNode.html +227 -0
  36. package/js/src/v/templates/graphNode.js +412 -0
  37. package/js/src/v/templates/main.css +353 -0
  38. package/js/src/v/templates/main.html +149 -0
  39. package/js/src/v/templates/main.js +511 -0
  40. package/js/src/v/templates/searchResults.css +50 -0
  41. package/js/src/v/templates/searchResults.html +46 -0
  42. package/js/src/v/templates/searchResults.js +176 -0
  43. package/package.json +4 -3
@@ -0,0 +1,646 @@
1
+ /**
2
+ * Implementing the Controller of the MVC
3
+ * Every change in the application starts here.
4
+ */
5
+
6
+ const _ = require('lodash');
7
+ const utils = require('../m/DualboxUtils');
8
+ const swal = require('sweetalert2');
9
+ const Merger = require('../m/Merger');
10
+ const idx = require('idx');
11
+ const AppParser = require('@dualbox/dualbox-lib-appparser');
12
+
13
+ class GraphController {
14
+ constructor(editor) {
15
+ this.e = editor;
16
+ this.m = editor.m;
17
+ this.v = editor.v;
18
+ }
19
+
20
+ createId(name) {
21
+ var shortName = utils.shortName(name);
22
+ return shortName + '-' + utils.randomString(8);
23
+ }
24
+
25
+ // Add a node from the search results
26
+ addNewBox(packageName) {
27
+ // first, make sure the package is loaded
28
+ this.e.loadPackage(packageName).then(() => {
29
+ var id = this.createId(packageName);
30
+ var pkg = null;
31
+
32
+ // close the modal
33
+ this.v.div.find('.add-node-modal').modal('toggle');
34
+
35
+ // add the node
36
+ var pkg = _.find(this.e.searchResults, { 'name': packageName });
37
+ if( pkg ) {
38
+ // first, add node in the model
39
+ var nodeAdded = this.m.addNode(id, pkg);
40
+ if( nodeAdded ) {
41
+ // if model accepts the operation, add it to the view
42
+ this.v.addNode(id, pkg);
43
+
44
+ // if the node is an UI, we also need to add it to a panel
45
+ var n = this.m.getNode(id);
46
+ if( n.isUI() ) {
47
+ if( n.isWidget() ) {
48
+ var options = {};
49
+ var registerTargets = n.m.getSpecialUINodes( n.getRegisterType() );
50
+ _.each(registerTargets, (n) => options[n.graphId] = n.graphId );
51
+
52
+ swal({
53
+ title: 'Select a registration target',
54
+ text: 'You just added a Widget node. It must be registered to an element of type ' + n.getRegisterType() +
55
+ " to work. Please choose one on the following list.",
56
+ input: 'select',
57
+ inputOptions: options
58
+ }).then( (result) => {
59
+ if( result.value ) {
60
+ // register the widget
61
+ this.registerWidget(n.id, result.value);
62
+
63
+ // find the panel of the target and put the widget on the same panel
64
+ var panel = this.m.getNode(result.value).getPanel();
65
+ this.m.addNodeToPanel(n.id, panel);
66
+
67
+ this.v.repaint();
68
+ }
69
+ });
70
+ }
71
+ else {
72
+ var options = {};
73
+ _.each(this.m.getPanels(), (name) => options[name] = name );
74
+
75
+ swal({
76
+ title: 'Select a panel',
77
+ text: 'You just added an UI. Please select in which panel of the app we should locate it.',
78
+ input: 'select',
79
+ inputOptions: options
80
+ }).then( (result) => {
81
+ if( result.value ) {
82
+ this.m.addNodeToPanel(id, result.value);
83
+ this.v.repaint();
84
+ }
85
+ });
86
+ }
87
+ }
88
+ }
89
+ }
90
+ else {
91
+ console.error('Package ' + packageName + ' not found');
92
+ }
93
+ });
94
+ }
95
+
96
+ // create a new metabox
97
+ addNewMetabox(name, json = {}) {
98
+ if( this.m.hasMetanode(name) ) {
99
+ swal("Can't add metabox", "metabox with name '" + name + "' already exists.", "error");
100
+ }
101
+ else {
102
+ // add metabox def
103
+ this.m.addMetanode(name, json);
104
+
105
+ // add 1 node of this metabox on the graph
106
+ var id = this.createId(name);
107
+
108
+ this.m.addNode(id, {
109
+ "name" : name,
110
+ "version" : "*"
111
+ });
112
+
113
+ // repaint editor
114
+ this.v.repaint();
115
+ }
116
+ }
117
+
118
+ // remove a box from it's id
119
+ removeBox(id) {
120
+ this.m.getNode(id).remove();
121
+ this.v.repaint();
122
+ }
123
+
124
+ duplicateBox(id) {
125
+ // copy def
126
+ var node = this.m.getNode(id);
127
+ var type = node.type;
128
+ var def = _.cloneDeep(node.getDef());
129
+ var newId = this.createId(def.module);
130
+
131
+ // remove links, change position a little bit
132
+ delete def.links;
133
+ var leftPosition = idx(def, o=>o.graph.position.left);
134
+ if( leftPosition ) {
135
+ def.graph.position.left = (parseInt(leftPosition) + 200).toString();
136
+ }
137
+ def.id = newId;
138
+
139
+ this.m.addNodeFromDef(newId, type, def);
140
+ this.v.repaint();
141
+ }
142
+
143
+ setInputVisibility(id, input, visible) {
144
+ var node = this.m.getNode(id);
145
+ if( node.isInputConnected(input) && !visible ) {
146
+ swal('Not yet', 'Please remove all connections to this input before changing its visibility', 'error');
147
+ return false;
148
+ }
149
+ else {
150
+ node.setInputVisibility(input, visible);
151
+ this.v.repaint();
152
+ return true;
153
+ }
154
+ }
155
+
156
+ setOutputVisibility(id, output, visible) {
157
+ var node = this.m.getNode(id);
158
+ if( node.isOutputConnected(output) && !visible ) {
159
+ swal('Not yet', 'Please remove all connections to this output before changing its visibility', 'error');
160
+ return false;
161
+ }
162
+ else {
163
+ node.setOutputVisibility(output, visible);
164
+ this.v.repaint();
165
+ return true;
166
+ }
167
+ }
168
+
169
+ setComment(id, comment) {
170
+ var node = this.m.getNode(id);
171
+ node.setComment(comment);
172
+ this.v.repaint();
173
+ this.v.openBoxSettings(id);
174
+ }
175
+
176
+ deleteComment(id) {
177
+ var node = this.m.getNode(id);
178
+ node.deleteComment();
179
+ this.v.repaint();
180
+ this.v.openBoxSettings(id);
181
+ }
182
+
183
+ registerWidget(id, targetId) {
184
+ var node = this.m.getNode(id);
185
+ node.registerWidget(targetId);
186
+ }
187
+
188
+ renameBox(oldId, newId, type) {
189
+ if( newId == "length" ) {
190
+ // crash jsPlumb to have a div named "length"
191
+ swal("Forbidden name", "Sorry, this is a forbidden name", "error");
192
+ return;
193
+ }
194
+
195
+ // newId can't start with a number
196
+ if( newId.match(/^\d/) ) {
197
+ swal("Wrong name", "You can't set a name that starts with a number.", "error");
198
+ return;
199
+ }
200
+
201
+ if( oldId !== newId ) {
202
+ if( type == "input" ) {
203
+ oldId = this.m.inputPrefix + oldId;
204
+ newId = this.m.inputPrefix + newId;
205
+ }
206
+ else if( type == "output" ) {
207
+ oldId = this.m.outputPrefix + oldId;
208
+ newId = this.m.outputPrefix + newId;
209
+ }
210
+ else {
211
+ if( newId.startsWith(this.m.inputPrefix) ||
212
+ newId.startsWith(this.m.outputPrefix) ) {
213
+ swal('Breaking convention', 'Only input boxes and output boxes can have a name that starts with "' + this.m.inputPrefix + '" or "' + this.m.outputPrefix + '".', "error");
214
+ return;
215
+ }
216
+ }
217
+ this.m.getNode(oldId).rename(newId);
218
+ this.v.repaint();
219
+ }
220
+ this.v.openBoxSettings(newId);
221
+ }
222
+
223
+ addAppEvent(name) {
224
+ this.m.getCurrentApp().addAppEvent(name);
225
+ this.v.setMainMenu();
226
+ }
227
+
228
+ removeEvent(id, index) {
229
+ this.m.getNode(id).removeEvent(index);
230
+ this.v.repaint();
231
+ this.v.openBoxSettings(id);
232
+ }
233
+
234
+ removeAppEvent(name) {
235
+ this.m.getCurrentApp().removeAppEvent(name);
236
+ this.v.repaint();
237
+ this.v.setMainMenu();
238
+ }
239
+
240
+ renameAppEvent(oldName, newName) {
241
+ this.m.getCurrentApp().renameAppEvent(oldName, newName);
242
+ this.v.repaint();
243
+ this.v.setMainMenu();
244
+ }
245
+
246
+ setEventProperty(id, index, prop, val) {
247
+ if( id.startsWith("#application-events-in") ) {
248
+ var eventName = id.split('-')[ id.split('-').length -1 ];
249
+ var def = this.m.getCurrentApp().getEventIn(eventName)[index];
250
+ def[prop] = val;
251
+ }
252
+ else if( id.startsWith("#application-events-out") ) {
253
+ var def = this.m.getCurrentApp().getEventOut();
254
+ def[prop] = val;
255
+ }
256
+ else {
257
+ var def = this.m.getNode(id).getEvent(index);
258
+ def[prop] = val;
259
+ this.m.getNode(id).setEvent(index, def);
260
+ }
261
+
262
+ this.v.repaint();
263
+ }
264
+
265
+ setEventIf(id, index, val) {
266
+ this.setEventProperty(id, index, "if", val);
267
+ }
268
+
269
+ setEventData(id, index, val) {
270
+ this.setEventProperty(id, index, "data", val);
271
+ }
272
+
273
+ setEventTarget(id, index, val) {
274
+ this.setEventProperty(id, index, "node", val);
275
+ }
276
+
277
+ setEventName(id, index, val) {
278
+ this.setEventProperty(id, index, "event", val);
279
+ }
280
+
281
+ setBoxCache(id, val) {
282
+ var n = this.m.getNode(id).setCache(val);
283
+ this.v.repaint();
284
+ }
285
+
286
+ setBoxParallel(id, val) {
287
+ var n = this.m.getNode(id).setParallel(val);
288
+ this.v.repaint();
289
+ }
290
+
291
+ setAppDescription( desc ) {
292
+ this.m.getCurrentApp().setDescription(desc);
293
+ this.v.setMainMenu();
294
+ }
295
+
296
+ setAppEventDescription( name, desc ) {
297
+ this.m.getCurrentApp().setEventDescription(name, desc);
298
+ this.v.setMainMenu();
299
+ }
300
+
301
+ removeAppInEvent(name, index) {
302
+ this.m.getCurrentApp().removeAppInEvent(name, index);
303
+ this.v.setMainMenu();
304
+ }
305
+
306
+ removeAppOutEvent(name) {
307
+ this.m.getCurrentApp().removeAppOutEvent(name);
308
+ this.v.setMainMenu();
309
+ }
310
+
311
+ getFirstNodeWithEvents() {
312
+ var nodes = this.m.getNodes('ui');
313
+ for(var i=0; i<nodes.length; i++) {
314
+ var node = nodes[i];
315
+ if( node.getEventsNames().length !== 0 ) {
316
+ return node;
317
+ }
318
+ }
319
+
320
+ return null;
321
+ }
322
+
323
+ addEvent(id, name) {
324
+ var node = this.getFirstNodeWithEvents();
325
+ if( node != null ) {
326
+ var evtName = node.getEventsNames()[0];
327
+ this.m.addEventLink(id, node.id, evtName);
328
+ }
329
+ else {
330
+ this.m.addEventLink(id, null, null);
331
+ }
332
+
333
+ this.v.openBoxSettings(id);
334
+ }
335
+
336
+ addSubEvent(name) {
337
+ var node = this.getFirstNodeWithEvents();
338
+ if( node != null ) {
339
+ var evtName = node.getEventsNames()[0];
340
+ this.m.getCurrentApp().addSubEvent(name, node.getGraphId(), evtName);
341
+ }
342
+ else {
343
+ this.m.getCurrentApp().addSubEvent(name, null, null);
344
+ }
345
+ this.v.setMainMenu();
346
+ }
347
+
348
+ addCallback(name) {
349
+ this.m.getCurrentApp().addCallback(name);
350
+ this.v.setMainMenu();
351
+ }
352
+
353
+ // create a new input in the current window (metanode)
354
+ createInput() {
355
+ swal.mixin({
356
+ confirmButtonText: 'Next &rarr;',
357
+ showCancelButton: true,
358
+ progressSteps: ['1', '2', '3']
359
+ }).queue([
360
+ {
361
+ input: 'text',
362
+ title: 'Enter the input name',
363
+ },
364
+ {
365
+ input: 'text',
366
+ title: 'Enter the input type',
367
+ },
368
+ {
369
+ input: 'text',
370
+ title: 'Enter a description',
371
+ }
372
+ ]).then(async (result) => {
373
+ if( result.value ) {
374
+ const [ inputName, inputType, inputDesc ] = result.value;
375
+ var input = this.m.addInput(inputName, inputType, inputDesc);
376
+ this.v.repaint();
377
+ }
378
+ });
379
+ }
380
+
381
+ // create a new output in the current window (metanode)
382
+ createOutput() {
383
+ swal.mixin({
384
+ confirmButtonText: 'Next &rarr;',
385
+ showCancelButton: true,
386
+ progressSteps: ['1', '2', '3']
387
+ }).queue([
388
+ {
389
+ input: 'text',
390
+ title: 'Enter the output name',
391
+ },
392
+ {
393
+ input: 'text',
394
+ title: 'Enter the output type',
395
+ },
396
+ {
397
+ input: 'text',
398
+ title: 'Enter a description',
399
+ }
400
+ ]).then(async (result) => {
401
+ if( result.value ) {
402
+ const [ outputName, outputType, outputDesc ] = result.value;
403
+ var output = this.m.addOutput(outputName, outputType, outputDesc);
404
+ this.v.repaint();
405
+ }
406
+ });
407
+ }
408
+
409
+ // create a new input, determine the type from the connection
410
+ createInputFromConnection(id, name) {
411
+ swal.mixin({
412
+ confirmButtonText: 'Next &rarr;',
413
+ showCancelButton: true,
414
+ progressSteps: ['1', '2']
415
+ }).queue([
416
+ {
417
+ input: 'text',
418
+ title: 'Enter the input name',
419
+ },
420
+ {
421
+ input: 'text',
422
+ title: 'Enter a description',
423
+ }
424
+ ]).then(async (result) => {
425
+ if( result.value ) {
426
+ var inputName = result.value[0];
427
+ var inputDesc = result.value[1];
428
+ var inputType = await this.m.getNode(id).getInputType(name);
429
+
430
+ // add the input
431
+ var input = this.m.addInput(inputName, inputType, inputDesc);
432
+
433
+ // make the position a bit to the left
434
+ var pos = _.clone(this.m.getNode(id).getDef().graph.position);
435
+ pos.left = parseInt(pos.left) > 150 ? parseInt(pos.left) - 150 : 0;
436
+ input.graph = {};
437
+ input.graph.position = pos;
438
+
439
+ // add the connection
440
+ this.m.addDataLink("input", inputName, id, name);
441
+
442
+ this.v.repaint();
443
+ }
444
+ });
445
+ }
446
+
447
+ // create a new output, determine the type from the connection
448
+ createOutputFromConnection(id, name) {
449
+ swal.mixin({
450
+ confirmButtonText: 'Next &rarr;',
451
+ showCancelButton: true,
452
+ progressSteps: ['1', '2']
453
+ }).queue([
454
+ {
455
+ input: 'text',
456
+ title: 'Enter the output name',
457
+ },
458
+ {
459
+ input: 'text',
460
+ title: 'Enter a description',
461
+ }
462
+ ]).then(async (result) => {
463
+ if( result.value ) {
464
+ var outputName = result.value[0];
465
+ var outputDesc = result.value[1];
466
+ var outputType = await this.m.getNode(id).getOutputType(name);
467
+
468
+ // add the output
469
+ var output = this.m.addOutput(outputName, outputType, outputDesc);
470
+
471
+ // make the position a bit to the left
472
+ var pos = _.clone(this.m.getNode(id).getDef().graph.position);
473
+ pos.left = parseInt(pos.left) + 250;
474
+ output.graph = {};
475
+ output.graph.position = pos;
476
+
477
+ // add the connection
478
+ this.m.addDataLink(id, name, "output", outputName);
479
+
480
+ this.v.repaint();
481
+ }
482
+ });
483
+ }
484
+
485
+ setIterator(id, input) {
486
+ var node = this.m.getNode(id);
487
+ node.detachInput(input); // this connection is invalid now
488
+ node.setIterator(input);
489
+ this.v.repaint();
490
+ }
491
+
492
+ unsetIterator(id, input) {
493
+ var node = this.m.getNode(id);
494
+ node.detachInput(input); // this connection is invalid now
495
+ node.unsetIterator(input);
496
+ this.v.repaint();
497
+ }
498
+
499
+ setFeedback(id, output, input) {
500
+ this.m.getNode(id).setFeedback(output, input);
501
+ this.v.repaint();
502
+ }
503
+
504
+ unsetFeedback(id, output) {
505
+ this.m.getNode(id).setFeedback(output);
506
+ this.v.repaint();
507
+ }
508
+
509
+ setMetanodeDescription(nodeId, description) {
510
+ var node = this.m.getNode(nodeId);
511
+ var metanodeName = node.def.module;
512
+ this.m.getCurrentApp().json.metanodes[metanodeName].description = description;
513
+ this.v.openBoxSettings(nodeId);
514
+ }
515
+
516
+ // enter inside a metanode
517
+ enterMetanode(nodeId) {
518
+ (async () => {
519
+ // 1 - hide the canvas
520
+ await this.v.hideCanvas();
521
+
522
+ // 2 - Save the actual position/zoom state
523
+ var viewState = this.v.zoomer.saveState();
524
+
525
+ // 3 - Enter the metanode
526
+ this.m.enterMetanode(nodeId, viewState);
527
+
528
+ // 4 - Repaint
529
+ await this.v.repaint();
530
+
531
+ // 5 - Zoom back to 1, position to top-left
532
+ await this.v.zoomer.setZoom(1);
533
+ await this.v.translater.gotoTopLeft();
534
+
535
+ // 6 - Show the canvas back again
536
+ await this.v.showCanvas();
537
+ })();
538
+ }
539
+
540
+ // exit to the given window
541
+ setWindow( w ) {
542
+ this.m.setWindow(w[0]);
543
+ this.v.repaint().then(() => {
544
+ this.v.zoomer.restoreState(w[2]);
545
+ });
546
+ }
547
+
548
+ load( json ) {
549
+ // first load the packages
550
+ this.e.loadPackages(json).then( async () => {
551
+ console.log('LOADED ALL PACKAGES !');
552
+
553
+ // hold state saving for now
554
+ this.m.history.holdSaving(true);
555
+
556
+ // 1st, load the json in the model
557
+ await this.m.load(json);
558
+
559
+ // set the new app's menu
560
+ this.v.setMainMenu();
561
+
562
+ // then, repaint
563
+ this.v.repaint().then(() => {
564
+ this.m.history.holdSaving(false);
565
+ this.m.history.save();
566
+ });
567
+
568
+ // load the css into the css editor
569
+ this.v.cssCode.setValue(this.m.get().css || "");
570
+
571
+ // load the html templates into the html editor
572
+ this.v.div.find('.app-interface-select').empty();
573
+ this.v.div.find('.app-interface-select').append(
574
+ $("<option/>", { "value" : "" }).append('Load UI...')
575
+ );
576
+ _.each(this.m.get().interface, (val, uiName) => {
577
+ this.v.div.find(".app-interface-select").append(
578
+ $("<option/>", { "value" : uiName }).append(uiName)
579
+ );
580
+ });
581
+ });
582
+ }
583
+
584
+ get() {
585
+ return this.m.get();
586
+ }
587
+
588
+ undo() {
589
+ this.m.undo();
590
+ this.v.repaint();
591
+ }
592
+
593
+ redo() {
594
+ this.m.redo();
595
+ this.v.repaint();
596
+ }
597
+
598
+ deleteSelection() {
599
+ var selectedDivs = this.v.selector.getSelection();
600
+ _.each(selectedDivs, (div) => {
601
+ this.m.getNode( $(div).attr('id') ).remove();
602
+ });
603
+ this.v.repaint();
604
+ }
605
+
606
+ mergeSelection() {
607
+ swal.mixin({
608
+ confirmButtonText: 'Next &rarr;',
609
+ showCancelButton: true,
610
+ progressSteps: ['1', '2']
611
+ }).queue([
612
+ {
613
+ input: 'text',
614
+ title: 'Enter the metabox name',
615
+ },
616
+ {
617
+ input: 'text',
618
+ title: 'Enter the metabox description',
619
+ }
620
+ ]).then(async (result) => {
621
+ if( result.value ) {
622
+ var mName = result.value[0];
623
+ var mDesc = result.value[1];
624
+
625
+ var selectedDivs = this.v.selector.getSelection();
626
+ var ids = [];
627
+ _.each(selectedDivs, (div) => {
628
+ if( div.is('.card') ) { // filter cards only
629
+ ids.push( $(div).attr('id') );
630
+ }
631
+ });
632
+
633
+ var merger = new Merger(this.m, ids);
634
+ merger.merge(mName, mDesc);
635
+
636
+ this.v.repaint();
637
+ }
638
+ });
639
+ }
640
+
641
+ removeSplit(id) {
642
+
643
+ }
644
+ }
645
+
646
+ module.exports = GraphController;
@@ -0,0 +1,8 @@
1
+ var CodeMirror = require('codemirror/lib/codemirror.js');
2
+ require('codemirror/lib/codemirror.css');
3
+ require('codemirror/mode/xml/xml.js');
4
+ require('codemirror/mode/css/css.js');
5
+ require('codemirror/mode/javascript/javascript.js');
6
+ require('codemirror/mode/htmlmixed/htmlmixed.js');
7
+
8
+ module.exports = CodeMirror;
@@ -0,0 +1 @@
1
+ module.exports = require('../../../node_modules/@fortawesome/fontawesome-free/css/all.min.css');
@@ -0,0 +1,2 @@
1
+ @import url('../../../node_modules/jsoneditor/dist/jsoneditor.css');
2
+
@@ -0,0 +1,4 @@
1
+ //require('../../../node_modules/jsoneditor/dist/jsoneditor.css');
2
+ require('./jsoneditor.css'); // local import to rebase urls in css
3
+ //require('../../../node_modules/jsoneditor/dist/img/jsoneditor-icons.svg');
4
+ module.exports = require('../../../node_modules/jsoneditor/dist/jsoneditor.js');
@@ -0,0 +1,35 @@
1
+ class DualboxUtils {
2
+ // return the short name of a dualbox package: "@dualbox/dualbox-core-if" => "if"
3
+ shortName(packageName) {
4
+ var str = packageName;
5
+ str = str.replace('@dualbox/', '');
6
+ str = str.replace('dualbox-core-', '');
7
+ str = str.replace('dualbox-lib-', '');
8
+ str = str.replace('dualbox-ui-', '');
9
+ str = str.replace('dualbox-module-', '');
10
+ return str
11
+ }
12
+
13
+ randomString(len) {
14
+ // converts a single byte to a hex string
15
+ function byteToHex(byte) {
16
+ return ('0' + byte.toString(16)).slice(-2);
17
+ }
18
+ var arr = new Uint8Array((len || 40) / 2);
19
+ window.crypto.getRandomValues(arr);
20
+ return [].map.call(arr, byteToHex).join("");
21
+ }
22
+
23
+ // return true if package is an UI
24
+ isUI(packageName) {
25
+ return packageName.indexOf('dualbox-ui-') !== -1;
26
+ }
27
+
28
+ // return true if package is a Module
29
+ isModule(packageName) {
30
+ return packageName.indexOf('dualbox-module-') !== -1 ||
31
+ packageName.indexOf('dualbox-core-') !== -1;
32
+ }
33
+ }
34
+
35
+ module.exports = new DualboxUtils();