@dualbox/editor 1.0.35 → 1.0.37
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.
- package/js/dist/GraphEditor.js +231 -227
- package/js/dist/GraphEditor.min.js +230 -226
- package/js/src/GraphEditor.js +246 -242
- package/package.json +1 -1
package/js/src/GraphEditor.js
CHANGED
|
@@ -15,270 +15,274 @@ import jsplumbjs from "jsplumb";
|
|
|
15
15
|
* Main class of the Graph Editor
|
|
16
16
|
*/
|
|
17
17
|
class DualboxEditor {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
18
|
+
// div: selector or jquery div
|
|
19
|
+
constructor(div, attrs) {
|
|
20
|
+
this.div = $(div);
|
|
21
|
+
this.div.addClass("main-editor-div");
|
|
22
|
+
this.attrs = attrs;
|
|
23
|
+
|
|
24
|
+
// export itself top window
|
|
25
|
+
window.dualboxEditor = this;
|
|
26
|
+
|
|
27
|
+
this.rootAppName = attrs.name ? attrs.name : "Application";
|
|
28
|
+
|
|
29
|
+
// MVC model
|
|
30
|
+
this.m = new GraphModel(this);
|
|
31
|
+
this.v = new GraphView(this, div, attrs);
|
|
32
|
+
this.c = new GraphController(this);
|
|
33
|
+
|
|
34
|
+
// bind links
|
|
35
|
+
this.v.m = this.c.m = this.m;
|
|
36
|
+
this.v.c = this.m.c = this.c;
|
|
37
|
+
this.c.v = this.m.v = this.v;
|
|
38
|
+
|
|
39
|
+
// cache for packages
|
|
40
|
+
this.packages = {};
|
|
41
|
+
this.DualBox = null; // local dualbox, for editor use
|
|
42
|
+
|
|
43
|
+
// the function to search for modules
|
|
44
|
+
// attr.search signature: search( text, cb )
|
|
45
|
+
// callback signature: cb( err, packages ), packages is an array of package.json
|
|
46
|
+
this.search = (text, type) => {
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
attrs.search(text, (err, packages) => {
|
|
49
|
+
if (err) {
|
|
50
|
+
reject(err);
|
|
51
|
+
} else {
|
|
52
|
+
// cache packages in this.packages
|
|
53
|
+
_.each(packages, r => {
|
|
54
|
+
if (!this.packages[r.name]) {
|
|
55
|
+
this.packages[r.name] = r;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (type) {
|
|
60
|
+
packages = _.filter(packages, o => {
|
|
61
|
+
return (
|
|
62
|
+
o.name.startsWith("@dualbox/dualbox-" + type) ||
|
|
63
|
+
(type == "module" && o.name.startsWith("dualbox-core"))
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
resolve(packages);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
57
70
|
});
|
|
71
|
+
};
|
|
58
72
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
73
|
+
this.types = [];
|
|
74
|
+
this.getRootTypes = function () {
|
|
75
|
+
if (_.isEmpty(this.types)) {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
this.search("dualbox-type-")
|
|
78
|
+
.then(packages => {
|
|
79
|
+
this.types = _.filter(packages, p => {
|
|
80
|
+
var isType = p.name.startsWith("@dualbox/dualbox-type");
|
|
81
|
+
var hasTypeDef = _.get(p, "dualbox.type");
|
|
82
|
+
|
|
83
|
+
if (isType && !hasTypeDef) {
|
|
84
|
+
console.error(
|
|
85
|
+
"Type package " +
|
|
86
|
+
p.name +
|
|
87
|
+
" has no dualbox Type description.\n" +
|
|
88
|
+
"Type was not imported"
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return isType && hasTypeDef;
|
|
92
|
+
});
|
|
93
|
+
resolve(this.types);
|
|
94
|
+
})
|
|
95
|
+
.catch(e => {
|
|
96
|
+
reject(e);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
return Promise.resolve(this.types);
|
|
66
101
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
this.getAvailableTypes = async function () {
|
|
105
|
+
var types = await this.getRootTypes();
|
|
106
|
+
return _.map(types, t => _.get(t, "dualbox.type.name"));
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// the function to find module by name and version (with cache)
|
|
110
|
+
// signature: find( name, version ), return a Promise which, when resolved, is a package.json
|
|
111
|
+
this.loadPackage = (name, version) => {
|
|
112
|
+
version = version || "*";
|
|
113
|
+
|
|
114
|
+
return new Promise((resolve, reject) => {
|
|
115
|
+
if (name.startsWith("dualbox-core")) {
|
|
116
|
+
var pkg = null;
|
|
117
|
+
_.each(this.DualBox.core, corePackage => {
|
|
118
|
+
if (corePackage.name == name) {
|
|
119
|
+
pkg = corePackage;
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
if (pkg) {
|
|
125
|
+
this.packages[name] = pkg;
|
|
126
|
+
resolve(pkg);
|
|
127
|
+
} else {
|
|
128
|
+
reject("Couldn't resolve core package: " + name);
|
|
129
|
+
}
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
var loadScript = (pkg, cb) => {
|
|
134
|
+
if (attrs.load) {
|
|
135
|
+
attrs.load(pkg.name, pkg.version, cb);
|
|
136
|
+
} else {
|
|
137
|
+
// Local editor. Bind the callback on the local script load
|
|
138
|
+
var script = $('script[data-pkg="' + pkg.name + '"]');
|
|
139
|
+
if (!script) {
|
|
140
|
+
throw "Couldn't find script in the current document: " +
|
|
141
|
+
pkg.name +
|
|
142
|
+
". Did you forget gulp link-editor ?";
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (script.attr("data-loaded") === "true") {
|
|
146
|
+
cb();
|
|
147
|
+
return;
|
|
148
|
+
} else {
|
|
149
|
+
script[0].addEventListener("error", function () {
|
|
150
|
+
throw "Failed to load script " + pkg.name;
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
var timeout = setTimeout(function () {
|
|
154
|
+
cb("Failed to load " + pkg.name + " after 5 seconds");
|
|
155
|
+
}, 5000);
|
|
156
|
+
script[0].addEventListener("load", () => {
|
|
157
|
+
clearTimeout(timeout);
|
|
158
|
+
cb();
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
var onLoadedScript = err => {
|
|
165
|
+
if (err) {
|
|
166
|
+
reject(err);
|
|
167
|
+
} else {
|
|
168
|
+
window.require(name); // make sure the package is required at least once
|
|
169
|
+
resolve(this.packages[name]);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// we need to find the package.json and make sure the script is loaded
|
|
174
|
+
if (this.packages[name]) {
|
|
175
|
+
try {
|
|
176
|
+
loadScript(this.packages[name], onLoadedScript);
|
|
177
|
+
} catch (e) {
|
|
178
|
+
reject(e);
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
// mark the package as beeing resolved
|
|
182
|
+
attrs.find(name, version, (err, result) => {
|
|
183
|
+
if (err) {
|
|
184
|
+
reject(err);
|
|
185
|
+
} else {
|
|
186
|
+
this.packages[name] = result; // cache result
|
|
187
|
+
loadScript(this.packages[name], onLoadedScript);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
90
190
|
}
|
|
91
|
-
return isType && hasTypeDef;
|
|
92
|
-
});
|
|
93
|
-
resolve(this.types);
|
|
94
|
-
})
|
|
95
|
-
.catch(e => {
|
|
96
|
-
reject(e);
|
|
97
191
|
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
this.loadPackage = (name, version) => {
|
|
112
|
-
version = version || "*";
|
|
113
|
-
|
|
114
|
-
return new Promise((resolve, reject) => {
|
|
115
|
-
if (name.startsWith("dualbox-core")) {
|
|
116
|
-
var pkg = null;
|
|
117
|
-
_.each(this.DualBox.core, corePackage => {
|
|
118
|
-
if (corePackage.name == name) {
|
|
119
|
-
pkg = corePackage;
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
if (pkg) {
|
|
125
|
-
this.packages[name] = pkg;
|
|
126
|
-
resolve(pkg);
|
|
127
|
-
} else {
|
|
128
|
-
reject("Couldn't resolve core package: " + name);
|
|
129
|
-
}
|
|
130
|
-
return;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// the function to require a dualbox module
|
|
195
|
+
this.require = (name, version, cb) => {
|
|
196
|
+
return require(name); // TODO: local only for now
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// Safety when the user leave the page,
|
|
200
|
+
// if not already defined externally
|
|
201
|
+
if (!window.onbeforeunload) {
|
|
202
|
+
window.onbeforeunload = function () {
|
|
203
|
+
return "Unsaved changes will be lost, are you sure you want to leave the editor?";
|
|
204
|
+
};
|
|
131
205
|
}
|
|
132
206
|
|
|
133
|
-
|
|
134
|
-
if (attrs.load) {
|
|
135
|
-
attrs.load(pkg.name, pkg.version, cb);
|
|
136
|
-
} else {
|
|
137
|
-
// Local editor. Bind the callback on the local script load
|
|
138
|
-
var script = $('script[data-pkg="' + pkg.name + '"]');
|
|
139
|
-
if (!script) {
|
|
140
|
-
throw "Couldn't find script in the current document: " +
|
|
141
|
-
pkg.name +
|
|
142
|
-
". Did you forget gulp link-editor ?";
|
|
143
|
-
}
|
|
207
|
+
this.loadCorePackages();
|
|
144
208
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
cb("Failed to load " + pkg.name + " after 5 seconds");
|
|
155
|
-
}, 5000);
|
|
156
|
-
script[0].addEventListener("load", () => {
|
|
157
|
-
clearTimeout(timeout);
|
|
158
|
-
cb();
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
};
|
|
209
|
+
if (attrs.json) {
|
|
210
|
+
this.onReady(() => {
|
|
211
|
+
var p = this.setApp(attrs.json);
|
|
212
|
+
if (attrs.onLoaded) {
|
|
213
|
+
p.then(attrs.onLoaded);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
163
218
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
219
|
+
// call cb when the editor is initialized
|
|
220
|
+
onReady(cb) {
|
|
221
|
+
this.v.onReady(cb);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async loadCorePackages() {
|
|
225
|
+
var onError = function (err) {
|
|
226
|
+
console.error(err);
|
|
171
227
|
};
|
|
172
228
|
|
|
173
|
-
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
loadScript(this.packages[name], onLoadedScript);
|
|
177
|
-
} catch (e) {
|
|
178
|
-
reject(e);
|
|
179
|
-
}
|
|
229
|
+
await this.loadPackage("@dualbox/dualbox");
|
|
230
|
+
if (!window.DualBox && window.DualBox.start) {
|
|
231
|
+
this.DualBox = window.DualBox = this.require("@dualbox/dualbox");
|
|
180
232
|
} else {
|
|
181
|
-
|
|
182
|
-
attrs.find(name, version, (err, result) => {
|
|
183
|
-
if (err) {
|
|
184
|
-
reject(err);
|
|
185
|
-
} else {
|
|
186
|
-
this.packages[name] = result; // cache result
|
|
187
|
-
loadScript(this.packages[name], onLoadedScript);
|
|
188
|
-
}
|
|
189
|
-
});
|
|
233
|
+
this.DualBox = window.DualBox;
|
|
190
234
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
// the function to require a dualbox module
|
|
195
|
-
this.require = (name, version, cb) => {
|
|
196
|
-
return require(name); // TODO: local only for now
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
// Safety when the user leave the page,
|
|
200
|
-
// if not already defined externally
|
|
201
|
-
if (!window.onbeforeunload) {
|
|
202
|
-
window.onbeforeunload = function() {
|
|
203
|
-
return "Unsaved changes will be lost, are you sure you want to leave the editor?";
|
|
204
|
-
};
|
|
235
|
+
_.each(this.DualBox.core, async corePackage => {
|
|
236
|
+
await this.loadPackage(corePackage.name);
|
|
237
|
+
});
|
|
205
238
|
}
|
|
206
239
|
|
|
207
|
-
|
|
240
|
+
setApp(json) {
|
|
241
|
+
return this.c.load(json);
|
|
242
|
+
}
|
|
208
243
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
var p = this.setApp(attrs.json);
|
|
212
|
-
if (attrs.onLoaded) {
|
|
213
|
-
p.then(attrs.onLoaded);
|
|
214
|
-
}
|
|
215
|
-
});
|
|
244
|
+
getApp() {
|
|
245
|
+
this.m.get();
|
|
216
246
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
this.promises = promises;
|
|
249
|
-
|
|
250
|
-
var parser = new AppParser(json);
|
|
251
|
-
parser.eachComponent((name, version) => {
|
|
252
|
-
promises.push(this.loadPackage(name, version));
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
/*
|
|
256
|
-
// also load core nodes
|
|
257
|
-
promises.push(this.loadPackage('dualbox-core-if', '*'));
|
|
258
|
-
promises.push(this.loadPackage('dualbox-core-value', '*'));
|
|
259
|
-
promises.push(this.loadPackage('dualbox-core-from-json', '*'));
|
|
260
|
-
promises.push(this.loadPackage('dualbox-core-to-json', '*'));
|
|
261
|
-
promises.push(this.loadPackage('dualbox-core-script', '*'));
|
|
262
|
-
promises.push(this.loadPackage('dualbox-core-switch', '*'));
|
|
263
|
-
*/
|
|
264
|
-
|
|
265
|
-
return Promise.all(promises);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// sync version of this.loadPackage. Will crash if the package has not been loaded yet
|
|
269
|
-
getPackage(name, version) {
|
|
270
|
-
if (this.packages[name] === undefined) {
|
|
271
|
-
throw "Package " + name + " has not been loaded yet.";
|
|
247
|
+
|
|
248
|
+
// load all packages needed in the json
|
|
249
|
+
// return a Promise
|
|
250
|
+
loadPackages(json) {
|
|
251
|
+
var promises = []; // array of promises
|
|
252
|
+
this.promises = promises;
|
|
253
|
+
|
|
254
|
+
var parser = new AppParser(json);
|
|
255
|
+
parser.eachComponent((name, version) => {
|
|
256
|
+
promises.push(this.loadPackage(name, version));
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
/*
|
|
260
|
+
// also load core nodes
|
|
261
|
+
promises.push(this.loadPackage('dualbox-core-if', '*'));
|
|
262
|
+
promises.push(this.loadPackage('dualbox-core-value', '*'));
|
|
263
|
+
promises.push(this.loadPackage('dualbox-core-from-json', '*'));
|
|
264
|
+
promises.push(this.loadPackage('dualbox-core-to-json', '*'));
|
|
265
|
+
promises.push(this.loadPackage('dualbox-core-script', '*'));
|
|
266
|
+
promises.push(this.loadPackage('dualbox-core-switch', '*'));
|
|
267
|
+
*/
|
|
268
|
+
|
|
269
|
+
return Promise.all(promises);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// sync version of this.loadPackage. Will crash if the package has not been loaded yet
|
|
273
|
+
getPackage(name, version) {
|
|
274
|
+
if (this.packages[name] === undefined) {
|
|
275
|
+
throw "Package " + name + " has not been loaded yet.";
|
|
276
|
+
}
|
|
277
|
+
return this.packages[name];
|
|
272
278
|
}
|
|
273
|
-
return this.packages[name];
|
|
274
|
-
}
|
|
275
279
|
}
|
|
276
280
|
|
|
277
281
|
// try to export in window if in browser context
|
|
278
282
|
try {
|
|
279
|
-
|
|
283
|
+
window.DualboxEditor = DualboxEditor;
|
|
280
284
|
} catch (e) {
|
|
281
|
-
|
|
285
|
+
console.log("Could not export to window: " + e);
|
|
282
286
|
}
|
|
283
287
|
|
|
284
|
-
//export default DualboxEditor;
|
|
288
|
+
//export default DualboxEditor;
|