@dualbox/editor 1.0.1 → 1.0.3

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 +3 -2
@@ -0,0 +1,174 @@
1
+ const _ = require('lodash');
2
+
3
+ class Translater {
4
+ constructor(view, container, canvas) {
5
+ this.view = view;
6
+ this.container = container;
7
+ this.canvas = canvas;
8
+
9
+ this.translating = false;
10
+
11
+ this.startEventHandler = this.onTranslateStart.bind(this);
12
+ this.moveEventHandler = this.onTranslateMove.bind(this);
13
+ this.stopEventHandler = this.onTranslateStop.bind(this);
14
+
15
+ this.originalOffset = this.canvas.offset();
16
+
17
+ this.x = null;
18
+ this.y = null;
19
+
20
+ this.dragging = false;
21
+ }
22
+
23
+ getTranslation() {
24
+ return {
25
+ top: this.canvas.offset().top - this.originalOffset.top,
26
+ left: this.canvas.offset().left - this.originalOffset.left
27
+ }
28
+ }
29
+
30
+ setTranslation( t ) {
31
+ this.canvas.offset({
32
+ top: this.originalOffset.top + t.top,
33
+ left: this.originalOffset.left + t.left,
34
+ });
35
+ }
36
+
37
+ translate( t ) {
38
+ this.canvas.offset({
39
+ top: this.canvas.offset().top + t.top,
40
+ left: this.canvas.offset().left + t.left
41
+ });
42
+ }
43
+
44
+ initialize() {
45
+ this.container.off('mousedown', this.startEventHandler);
46
+ $(document).off('mousemove', this.moveEventHandler);
47
+ $(document).off('mouseup', this.stopEventHandler);
48
+ this.container.on('mousedown', this.startEventHandler);
49
+ $(document).on('mousemove', this.moveEventHandler);
50
+ $(document).on('mouseup', this.stopEventHandler);
51
+
52
+ // override the context menu default behavior
53
+ this.container.off('contextmenu');
54
+ this.container.on('contextmenu', (e) => {
55
+ if( !this.isCapturingRightClick(e.target) ) {
56
+ e.stopPropagation();
57
+ e.preventDefault();
58
+ return false;
59
+ }
60
+ });
61
+ }
62
+
63
+ isCapturingRightClick(target) {
64
+ return $(target).closest('.capture-right-click').length !== 0;
65
+ }
66
+
67
+ onTranslateStart(e) {
68
+ if( e.which === 3 && !this.isCapturingRightClick(e.target) && $('.capture-right-click:hover').length == 0 ) { // right click
69
+ if( !$('div:hover').is('.contextmenu') ) {
70
+ e.preventDefault();
71
+ e.stopImmediatePropagation();
72
+ }
73
+
74
+ //console.log('[TRANSLATION] start');
75
+ this.translating = true;
76
+ this.container.addClass('translating');
77
+
78
+ this.x = e.pageX;
79
+ this.y = e.pageY;
80
+
81
+ this.dragging = false;
82
+ }
83
+ }
84
+
85
+ onTranslateMove(e) {
86
+ if( this.translating ) {
87
+ e.preventDefault();
88
+ e.stopPropagation();
89
+
90
+ //console.log('[TRANSLATION] moving');
91
+ var translateX = this.x - e.pageX;
92
+ var translateY = this.y - e.pageY;
93
+
94
+ var offset = this.canvas.offset();
95
+ this.canvas.offset({
96
+ top: offset.top - translateY,
97
+ left: offset.left - translateX
98
+ });
99
+
100
+ this.x = e.pageX;
101
+ this.y = e.pageY;
102
+
103
+ this.dragging = true;
104
+ }
105
+ }
106
+
107
+ onTranslateStop(e) {
108
+ if( this.translating && e.which === 3 ) {
109
+ if( this.dragging ) {
110
+ e.preventDefault();
111
+ e.stopImmediatePropagation();
112
+ }
113
+ else {
114
+ // there wasnt any movement, trigger a contextmenu here
115
+ if( !this.isCapturingRightClick(e.target) ) {
116
+ $('.capture-right-click:hover').triggerHandler('contextmenu');
117
+ }
118
+ }
119
+
120
+ //console.log('[TRANSLATION] stop');
121
+ this.translating = false;
122
+ this.container.removeClass('translating');
123
+ }
124
+ }
125
+
126
+ // correct offset if the left menu is open
127
+ correctOffset( offset ) {
128
+ if( this.view.isLeftMenuExpanded() ) {
129
+ offset.left += 465;
130
+ }
131
+ /*
132
+ if( this.view.isRightMenuExpanded() ) {
133
+ offset.left += 35;
134
+ }
135
+ */
136
+ return offset;
137
+ }
138
+
139
+ gotoTopLeft() {
140
+ var offset = this.correctOffset(_.clone(this.originalOffset));
141
+ this.canvas.offset(offset);
142
+ return new Promise((resolve) => this.canvas.ready(resolve));
143
+ }
144
+
145
+ gotoBottomLeft() {
146
+ var zoom = this.view.zoomer.getZoom();
147
+ var offset = _.clone(this.originalOffset);
148
+ offset.top += this.container.height() - this.canvas.height() * zoom - 2; /* canvas border */
149
+ offset = this.correctOffset(offset);
150
+ this.canvas.offset(offset);
151
+ return new Promise((resolve) => this.canvas.ready(resolve));
152
+ }
153
+
154
+ gotoTopRight() {
155
+ var zoom = this.view.zoomer.getZoom();
156
+ var offset = _.clone(this.originalOffset);
157
+ offset.left += this.container.width() - this.canvas.width() * zoom - 2; /* canvas border */
158
+ offset = this.correctOffset(offset);
159
+ this.canvas.offset(offset);
160
+ return new Promise((resolve) => this.canvas.ready(resolve));
161
+ }
162
+
163
+ gotoBottomRight() {
164
+ var zoom = this.view.zoomer.getZoom();
165
+ var offset = _.clone(this.originalOffset);
166
+ offset.top += this.container.height() - this.canvas.height() * zoom - 2; /* canvas border */
167
+ offset.left += this.container.width() - this.canvas.width() * zoom - 2; /* canvas border */
168
+ offset = this.correctOffset(offset);
169
+ this.canvas.offset(offset);
170
+ return new Promise((resolve) => this.canvas.ready(resolve));
171
+ }
172
+ }
173
+
174
+ module.exports = Translater;
@@ -0,0 +1,7 @@
1
+ function htmlentities(str) {
2
+ return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
3
+ }
4
+
5
+ module.exports = {
6
+ htmlentities : htmlentities
7
+ };
@@ -0,0 +1,201 @@
1
+ class Zoomer {
2
+ constructor(view, container, canvas) {
3
+ this.view = view;
4
+ this.container = container;
5
+ this.canvas = canvas;
6
+ this.currentZoom = 1;
7
+
8
+ this.canvasWidth = this.canvas.width();
9
+ this.canvasHeight = this.canvas.height();
10
+
11
+ this.transform = null;
12
+
13
+ this.currentlyZooming = false;
14
+ this.nextZoom = false;
15
+ }
16
+
17
+ initialize() {
18
+ this.container.off('mousewheel');
19
+ this.container.on('mousewheel', (e) => {
20
+ // normalize wheel to +1 or -1
21
+ if(e.originalEvent.wheelDelta / 120 > 0) {
22
+ this.zoomIn(e);
23
+ }
24
+ else{
25
+ this.zoomOut(e);
26
+ }
27
+ });
28
+ }
29
+
30
+ getZoom() {
31
+ return this.currentZoom;
32
+ }
33
+
34
+ saveState() {
35
+ var el = this.view.jsPlumbInstance.getContainer();
36
+ return {
37
+ "currentZoom" : this.currentZoom,
38
+ "offset" : this.canvas.offset(),
39
+ "transform" : el.style["transform"],
40
+ "transition" : el.style["transition"],
41
+ "transformOrigin" : el.style["transform-origin"],
42
+ }
43
+ }
44
+
45
+ restoreState( savedZoom ) {
46
+ this.currentZoom = savedZoom.currentZoom;
47
+ var el = this.view.jsPlumbInstance.getContainer();
48
+ $(el).one("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", () => {
49
+ $(this.canvas).offset(savedZoom.offset);
50
+ this.view.jsPlumbInstance.setZoom(this.currentZoom);
51
+ this.view.jsPlumbInstance.repaintEverything();
52
+ });
53
+ el.style["transition"] = savedZoom.transition;
54
+ el.style["transform"] = savedZoom.transform;
55
+ el.style["transform-origin"] = savedZoom.transformOrigin;
56
+ }
57
+
58
+ // zoom in or out
59
+ // - zoom: value between 0 and 1
60
+ // - e: if e is defined, we make sure the mouse stays on the same point
61
+ setZoom(zoom, e) {
62
+ this.currentlyZooming = true;
63
+
64
+ var el = this.view.jsPlumbInstance.getContainer();
65
+
66
+ // set the scale
67
+ var s = "scale(" + zoom + ")";
68
+
69
+ var elOffset = this.canvas.offset();
70
+
71
+ // set the transform origin
72
+ if( e ) {
73
+ /*
74
+ // NODE: this works exactly like 50% 50%
75
+ // compute current distance from the center of the canvas
76
+ var canvasCenterX = this.canvas.width()/ 2;
77
+ var canvasCenterY = this.canvas.height()/ 2;
78
+ var oString = canvasCenterX + "px " + canvasCenterY + "px";
79
+ */
80
+
81
+ // find our current mouse position on this canvas
82
+ var mouseX = (e.pageX - this.canvas.offset().left) / (this.canvas.width() * this.currentZoom);
83
+ var mouseY = (e.pageY - this.canvas.offset().top) / (this.canvas.height() * this.currentZoom);
84
+
85
+ var oString = (mouseX*100) + "% " + (mouseY*100) + "%";
86
+ }
87
+ else {
88
+ var oString = "50% 50%";
89
+ }
90
+
91
+ return new Promise( (resolve) => {
92
+ if( this.currentZoom == zoom ) {
93
+ this.currentlyZooming = false;
94
+ resolve();
95
+ }
96
+ else {
97
+ $(el).one("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", () => {
98
+ this.view.jsPlumbInstance.setZoom(this.currentZoom, true);
99
+ this.currentlyZooming = false;
100
+ $(el).ready(resolve);
101
+ });
102
+
103
+ // before we apply the transformation, remove the previous transform-origin as it messes up the new transform
104
+ el.style["transform"] = s;
105
+ el.style["transition"] = "transform 1ms ease";
106
+ el.style["transform-origin"] = oString;
107
+ $(el).offset(elOffset);
108
+
109
+ this.currentZoom = zoom;
110
+ }
111
+ });
112
+ }
113
+
114
+ zoomIn(e) {
115
+ // On big apps, zoom can be not real-time.
116
+ if( this.currentlyZooming ) {
117
+ clearTimeout(this.nextZoom);
118
+ this.nextZoom = setTimeout(() => {
119
+ this.zoomIn(e);
120
+ });
121
+ }
122
+ else {
123
+ if( this.currentZoom + 0.1 <= 1 ) {
124
+ var newZoom = this.currentZoom + 0.1;
125
+ this.setZoom(newZoom, e);
126
+ }
127
+ }
128
+ }
129
+
130
+ zoomOut(e) {
131
+ if( this.currentlyZooming ) {
132
+ clearTimeout(this.nextZoom);
133
+ this.nextZoom = setTimeout(() => {
134
+ this.zoomOut(e);
135
+ });
136
+ }
137
+ else {
138
+ if( this.currentZoom - 0.1 >= 0.1 ) {
139
+ var newZoom = this.currentZoom - 0.1;
140
+ this.setZoom(newZoom, e);
141
+ }
142
+ }
143
+ }
144
+
145
+ sleep( count ) {
146
+ return new Promise((resolve) => {
147
+ setTimeout(resolve, count);
148
+ });
149
+ }
150
+
151
+ /*
152
+ // temporary remove zoom if some lib/component needs it
153
+ deactivate() {
154
+ if( this.getZoom() !== 1 ) {
155
+ var el = this.view.jsPlumbInstance.getContainer();
156
+
157
+ this.transform = el.style["transform"];
158
+ el.style["visibility"] = "hidden"; // better than resize glitch
159
+ el.style["transform"] = "scale(1)";
160
+
161
+ //el.style["transition"] = "none";
162
+ //el.style["transform-origin"] = "none";
163
+ return new Promise((resolve) => {
164
+ $(el).one("transitionend", resolve);
165
+ });
166
+ }
167
+ else {
168
+ this.transform = null;
169
+ return new Promise(resolve => resolve());
170
+ }
171
+ }
172
+
173
+ activate(cb) {
174
+ if( this.transform !== null ) {
175
+ var el = this.view.jsPlumbInstance.getContainer();
176
+ el.style["transform"] = this.transform;
177
+ return new Promise((resolve) => {
178
+ $(el).one("transitionend", () => {
179
+ el.style["visibility"] = "visible";
180
+ resolve();
181
+ });
182
+ });
183
+ }
184
+ else {
185
+ this.transform = null;
186
+ return new Promise(resolve => resolve());
187
+ }
188
+ }
189
+ */
190
+
191
+ deactivate() {
192
+ this.previousZoom = this.currentZoom;
193
+ return this.setZoom(1);
194
+ }
195
+
196
+ activate() {
197
+ return this.setZoom(this.previousZoom);
198
+ }
199
+ }
200
+
201
+ module.exports = Zoomer;
@@ -0,0 +1,45 @@
1
+ .add-node-modal .modal-body {
2
+ height: 70vh;
3
+ }
4
+
5
+ .h100 {
6
+ height: 100%!important;
7
+ min-height: 100%!important;
8
+ }
9
+
10
+ .module-name {
11
+ font-size: 18px;
12
+ font-weight: bold;
13
+ margin-bottom: 10px;
14
+ }
15
+
16
+ .module-show-description, .module-show-inputs, .module-show-outputs, .module-show-attributes {
17
+ margin-top: 20px;
18
+ display: none;
19
+ font-size: 14px;
20
+ }
21
+
22
+ .table-desc th, .table-desc td {
23
+ margin-right: 10px;
24
+ }
25
+
26
+ #add-node-modal .modal-dialog {
27
+ min-width: calc(100% - 40px)!important;
28
+ height: calc(100% - 40px);
29
+ margin: 20px;
30
+ padding: 0;
31
+ }
32
+
33
+ #add-node-modal .modal-content {
34
+ height: auto;
35
+ min-height: 100%;
36
+ border-radius: 0;
37
+ }
38
+
39
+ .node-description {
40
+ max-height: 100%;
41
+ overflow-y: scroll;
42
+ overflow-x: hidden;
43
+ padding-right: 15px;
44
+ }
45
+
@@ -0,0 +1,62 @@
1
+ @!(attrs)
2
+ <div class="modal fade add-node-modal" id="add-node-modal" tabindex="-1" role="dialog">
3
+ <div class="modal-dialog" role="document">
4
+ <div class="modal-content h100">
5
+ <div class="modal-header">
6
+ <h5 class="modal-title">Add a new Module</h5>
7
+
8
+ <div class="mx-auto">
9
+ <input class="form-control mx-auto search-modules" type="text" placeholder="Search modules..." id="search-nodes" style="width: 300px;"/>
10
+ </div>
11
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
12
+ <span aria-hidden="true">&times;</span>
13
+ </button>
14
+ </div>
15
+ <div class="modal-body">
16
+ <div class="container-fluid h100">
17
+ <div class="row h100">
18
+ <div class="col-md-4 h100" style="padding-left: 0; padding-right: 0;">
19
+ <div class="search-nodes-results h100"></div>
20
+ </div>
21
+ <div class="col-md-8 h100" style="padding-left: 15px; padding-right: 0;">
22
+ <div class="node-description h100">
23
+ <div class="row">
24
+ <div class="col-md-4 module-show">
25
+ <div class="module-name"></div>
26
+ <div class="module-signature" id="module-signature"></div>
27
+ </div>
28
+ <div class="col-md-8">
29
+ <div class="module-show-description">
30
+ <label style="text-decoration: underline;">Description: </label>
31
+ <div class="module-long-description"></div>
32
+ </div>
33
+ </div>
34
+ <hr/>
35
+ </div>
36
+
37
+ <div class="module-show-inputs">
38
+ <label style="text-decoration: underline;">Inputs: </label>
39
+ <div class="module-inputs"></div>
40
+ </div>
41
+
42
+ <div class="module-show-outputs">
43
+ <label style="text-decoration: underline;">Outputs: </label>
44
+ <div class="module-outputs"></div>
45
+ </div>
46
+
47
+ <div class="module-show-attributes">
48
+ <label style="text-decoration: underline;">Attributes: </label>
49
+ <div class="module-attributes"></div>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ <div class="modal-footer">
57
+ <button type="button" class="btn btn-primary add-node-btn">Add node</button>
58
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
@@ -0,0 +1,34 @@
1
+ const swal = require('sweetalert2');
2
+
3
+ var TemplateBinds = function(view) {
4
+ $('.btn-cancel-add-node').click(function(e) {
5
+ $('.add-node-modal').removeClass('show');
6
+ });
7
+
8
+ $('.add-node-btn').click(function(e) {
9
+ var selectedNode = $('.node-result.selected')[0];
10
+ if( selectedNode ) {
11
+ // add node to the controller
12
+ var packageName = $(selectedNode).data('package');
13
+ window.dualboxEditor.c.addNewBox(packageName);
14
+ }
15
+ else {
16
+ swal('Please select a node', '', 'error');
17
+ return;
18
+ }
19
+ });
20
+
21
+ // bind the search to the search input
22
+ $('.search-modules').on("input", (e) => {
23
+ var text = $('.search-modules').val();
24
+ var resultDiv = $('.search-nodes-results');
25
+ resultDiv.empty().append('<p>Searching...</p>');
26
+ view.e.search(text).catch( (err) => {
27
+ swal('error searching packages', err.reason, "error");
28
+ }).then((results) => {
29
+ view.templateMgr.replaceTemplate(resultDiv, "searchResults", { results: results });
30
+ });
31
+ });
32
+ }
33
+
34
+ module.exports = TemplateBinds;
@@ -0,0 +1,5 @@
1
+ .card-debug .card-body {
2
+ font-size: 12px;
3
+ padding-left: 5px;
4
+ padding-right: 5px;
5
+ }