mirror of https://gitee.com/bigwinds/arangodb
gv [ci skip]
This commit is contained in:
parent
08b892f09f
commit
1929b24901
|
@ -65,6 +65,9 @@
|
||||||
"frontend/js/lib/sigma.plugins.fullScreen.js",
|
"frontend/js/lib/sigma.plugins.fullScreen.js",
|
||||||
"frontend/js/lib/sigma.layout.fruchtermanReingold.js",
|
"frontend/js/lib/sigma.layout.fruchtermanReingold.js",
|
||||||
"frontend/js/lib/sigma.exporters.svg.js",
|
"frontend/js/lib/sigma.exporters.svg.js",
|
||||||
|
"frontend/js/lib/sigma.canvas.edges.labels.curve.js",
|
||||||
|
"frontend/js/lib/sigma.canvas.edges.labels.curvedArrow.js",
|
||||||
|
"frontend/js/lib/sigma.canvas.edges.labels.def.js",
|
||||||
"frontend/js/lib/worker.js",
|
"frontend/js/lib/worker.js",
|
||||||
"frontend/js/lib/supervisor.js",
|
"frontend/js/lib/supervisor.js",
|
||||||
// END SIGMA LIBRARIES
|
// END SIGMA LIBRARIES
|
||||||
|
|
|
@ -292,10 +292,33 @@ authRouter.get('/graph/:name', function (req, res) {
|
||||||
|
|
||||||
var graph = gm._graph(name);
|
var graph = gm._graph(name);
|
||||||
var vertexName = graph._vertexCollections()[0].name();
|
var vertexName = graph._vertexCollections()[0].name();
|
||||||
var startVertex = db[vertexName].any();
|
|
||||||
|
var startVertex;
|
||||||
|
var config;
|
||||||
|
|
||||||
|
try {
|
||||||
|
config = req.queryParams;
|
||||||
|
} catch (e) {
|
||||||
|
res.throw('bad request', e.message, {cause: e});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.nodeStart) {
|
||||||
|
try {
|
||||||
|
startVertex = db._document(config.nodeStart);
|
||||||
|
} catch (e) {
|
||||||
|
res.throw('bad request', e.message, {cause: e});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(startVertex);
|
||||||
|
if (!startVertex) {
|
||||||
|
startVertex = db[vertexName].any();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startVertex = db[vertexName].any();
|
||||||
|
}
|
||||||
|
|
||||||
var aqlQuery =
|
var aqlQuery =
|
||||||
'FOR v, e, p IN 1..3 ANY "' + startVertex._id + '" GRAPH "' + name + '"' +
|
'FOR v, e, p IN 1..' + (config.depth || '2') + ' ANY "' + startVertex._id + '" GRAPH "' + name + '"' +
|
||||||
'RETURN p'
|
'RETURN p'
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -307,29 +330,53 @@ authRouter.get('/graph/:name', function (req, res) {
|
||||||
var edgesArr = [];
|
var edgesArr = [];
|
||||||
|
|
||||||
_.each(cursor.json, function (obj) {
|
_.each(cursor.json, function (obj) {
|
||||||
|
var edgeLabel;
|
||||||
|
|
||||||
_.each(obj.edges, function (edge) {
|
_.each(obj.edges, function (edge) {
|
||||||
if (edge._to && edge._from) {
|
if (edge._to && edge._from) {
|
||||||
|
if (config.edgeLabel) {
|
||||||
|
// configure edge labels
|
||||||
|
edgeLabel = edge[config.edgeLabel];
|
||||||
|
|
||||||
|
if (edgeLabel) {
|
||||||
|
edgeLabel = edgeLabel.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!edgeLabel) {
|
||||||
|
edgeLabel = 'attribute ' + config.edgeLabel + ' not found';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
edgesObj[edge._from + edge._to] = {
|
edgesObj[edge._from + edge._to] = {
|
||||||
id: edge._id,
|
id: edge._id,
|
||||||
source: edge._from,
|
source: edge._from,
|
||||||
color: '#cccccc',
|
label: edgeLabel,
|
||||||
|
color: config.edgeColor || '#cccccc',
|
||||||
target: edge._to
|
target: edge._to
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var label;
|
|
||||||
|
var nodeLabel;
|
||||||
|
var nodeSize;
|
||||||
|
|
||||||
_.each(obj.vertices, function (node) {
|
_.each(obj.vertices, function (node) {
|
||||||
if (node.label) {
|
if (config.nodeLabel) {
|
||||||
label = node.label;
|
nodeLabel = node[config.nodeLabel];
|
||||||
} else {
|
}
|
||||||
label = node._id;
|
if (!nodeLabel) {
|
||||||
|
nodeLabel = node._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.nodeSize) {
|
||||||
|
nodeSize = node[config.nodeSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
nodesObj[node._id] = {
|
nodesObj[node._id] = {
|
||||||
id: node._id,
|
id: node._id,
|
||||||
label: label,
|
label: nodeLabel,
|
||||||
size: Math.random(),
|
size: nodeSize || Math.random(),
|
||||||
color: '#2ecc71',
|
color: config.nodeColor || '#2ecc71',
|
||||||
x: Math.random(),
|
x: Math.random(),
|
||||||
y: Math.random()
|
y: Math.random()
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
;(function(undefined) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (typeof sigma === 'undefined')
|
||||||
|
throw 'sigma is not declared';
|
||||||
|
|
||||||
|
// Initialize packages:
|
||||||
|
sigma.utils.pkg('sigma.canvas.edges.labels');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This label renderer will just display the label on the curve of the edge.
|
||||||
|
* The label is rendered at half distance of the edge extremities, and is
|
||||||
|
* always oriented from left to right on the top side of the curve.
|
||||||
|
*
|
||||||
|
* @param {object} edge The edge object.
|
||||||
|
* @param {object} source node The edge source node.
|
||||||
|
* @param {object} target node The edge target node.
|
||||||
|
* @param {CanvasRenderingContext2D} context The canvas context.
|
||||||
|
* @param {configurable} settings The settings function.
|
||||||
|
*/
|
||||||
|
sigma.canvas.edges.labels.curve =
|
||||||
|
function(edge, source, target, context, settings) {
|
||||||
|
if (typeof edge.label !== 'string')
|
||||||
|
return;
|
||||||
|
|
||||||
|
var prefix = settings('prefix') || '',
|
||||||
|
size = edge[prefix + 'size'] || 1;
|
||||||
|
|
||||||
|
if (size < settings('edgeLabelThreshold'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var fontSize,
|
||||||
|
sSize = source[prefix + 'size'],
|
||||||
|
sX = source[prefix + 'x'],
|
||||||
|
sY = source[prefix + 'y'],
|
||||||
|
tX = target[prefix + 'x'],
|
||||||
|
tY = target[prefix + 'y'],
|
||||||
|
dX = tX - sX,
|
||||||
|
dY = tY - sY,
|
||||||
|
sign = (sX < tX) ? 1 : -1,
|
||||||
|
cp = {},
|
||||||
|
c,
|
||||||
|
angle,
|
||||||
|
t = 0.5; //length of the curve
|
||||||
|
|
||||||
|
if (source.id === target.id) {
|
||||||
|
cp = sigma.utils.getSelfLoopControlPoints(sX, sY, sSize);
|
||||||
|
c = sigma.utils.getPointOnBezierCurve(
|
||||||
|
t, sX, sY, tX, tY, cp.x1, cp.y1, cp.x2, cp.y2
|
||||||
|
);
|
||||||
|
angle = Math.atan2(1, 1); // 45°
|
||||||
|
} else {
|
||||||
|
cp = sigma.utils.getQuadraticControlPoint(sX, sY, tX, tY);
|
||||||
|
c = sigma.utils.getPointOnQuadraticCurve(t, sX, sY, tX, tY, cp.x, cp.y);
|
||||||
|
angle = Math.atan2(dY * sign, dX * sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The font size is sublineraly proportional to the edge size, in order to
|
||||||
|
// avoid very large labels on screen.
|
||||||
|
// This is achieved by f(x) = x * x^(-1/ a), where 'x' is the size and 'a'
|
||||||
|
// is the edgeLabelSizePowRatio. Notice that f(1) = 1.
|
||||||
|
// The final form is:
|
||||||
|
// f'(x) = b * x * x^(-1 / a), thus f'(1) = b. Application:
|
||||||
|
// fontSize = defaultEdgeLabelSize if edgeLabelSizePowRatio = 1
|
||||||
|
fontSize = (settings('edgeLabelSize') === 'fixed') ?
|
||||||
|
settings('defaultEdgeLabelSize') :
|
||||||
|
settings('defaultEdgeLabelSize') *
|
||||||
|
size *
|
||||||
|
Math.pow(size, -1 / settings('edgeLabelSizePowRatio'));
|
||||||
|
|
||||||
|
context.save();
|
||||||
|
|
||||||
|
|
||||||
|
if (edge.active) {
|
||||||
|
context.font = [
|
||||||
|
settings('activeFontStyle'),
|
||||||
|
fontSize + 'px',
|
||||||
|
settings('activeFont') || settings('font')
|
||||||
|
].join(' ');
|
||||||
|
|
||||||
|
context.fillStyle =
|
||||||
|
settings('edgeActiveColor') === 'edge' ?
|
||||||
|
(edge.active_color || settings('defaultEdgeActiveColor')) :
|
||||||
|
settings('defaultEdgeLabelActiveColor');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.font = [
|
||||||
|
settings('fontStyle'),
|
||||||
|
fontSize + 'px',
|
||||||
|
settings('font')
|
||||||
|
].join(' ');
|
||||||
|
|
||||||
|
context.fillStyle =
|
||||||
|
(settings('edgeLabelColor') === 'edge') ?
|
||||||
|
(edge.color || settings('defaultEdgeColor')) :
|
||||||
|
settings('defaultEdgeLabelColor');
|
||||||
|
}
|
||||||
|
|
||||||
|
context.textAlign = 'center';
|
||||||
|
context.textBaseline = 'alphabetic';
|
||||||
|
|
||||||
|
context.translate(c.x, c.y);
|
||||||
|
context.rotate(angle);
|
||||||
|
context.fillText(
|
||||||
|
edge.label,
|
||||||
|
0,
|
||||||
|
(-size / 2) - 3
|
||||||
|
);
|
||||||
|
|
||||||
|
context.restore();
|
||||||
|
};
|
||||||
|
}).call(this);
|
|
@ -0,0 +1,25 @@
|
||||||
|
;(function(undefined) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (typeof sigma === 'undefined')
|
||||||
|
throw 'sigma is not declared';
|
||||||
|
|
||||||
|
// Initialize packages:
|
||||||
|
sigma.utils.pkg('sigma.canvas.edges.labels');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This label renderer will just display the label on the curve of the edge.
|
||||||
|
* The label is rendered at half distance of the edge extremities, and is
|
||||||
|
* always oriented from left to right on the top side of the curve.
|
||||||
|
*
|
||||||
|
* @param {object} edge The edge object.
|
||||||
|
* @param {object} source node The edge source node.
|
||||||
|
* @param {object} target node The edge target node.
|
||||||
|
* @param {CanvasRenderingContext2D} context The canvas context.
|
||||||
|
* @param {configurable} settings The settings function.
|
||||||
|
*/
|
||||||
|
sigma.canvas.edges.labels.curvedArrow =
|
||||||
|
function(edge, source, target, context, settings) {
|
||||||
|
sigma.canvas.edges.labels.curve(edge, source, target, context, settings);
|
||||||
|
};
|
||||||
|
}).call(this);
|
|
@ -0,0 +1,96 @@
|
||||||
|
;(function(undefined) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (typeof sigma === 'undefined')
|
||||||
|
throw 'sigma is not declared';
|
||||||
|
|
||||||
|
// Initialize packages:
|
||||||
|
sigma.utils.pkg('sigma.canvas.edges.labels');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This label renderer will just display the label on the line of the edge.
|
||||||
|
* The label is rendered at half distance of the edge extremities, and is
|
||||||
|
* always oriented from left to right on the top side of the line.
|
||||||
|
*
|
||||||
|
* @param {object} edge The edge object.
|
||||||
|
* @param {object} source node The edge source node.
|
||||||
|
* @param {object} target node The edge target node.
|
||||||
|
* @param {CanvasRenderingContext2D} context The canvas context.
|
||||||
|
* @param {configurable} settings The settings function.
|
||||||
|
*/
|
||||||
|
sigma.canvas.edges.labels.def =
|
||||||
|
function(edge, source, target, context, settings) {
|
||||||
|
if (typeof edge.label !== 'string' || source == target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var prefix = settings('prefix') || '',
|
||||||
|
size = edge[prefix + 'size'] || 1;
|
||||||
|
|
||||||
|
if (size < settings('edgeLabelThreshold'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (0 === settings('edgeLabelSizePowRatio'))
|
||||||
|
throw '"edgeLabelSizePowRatio" must not be 0.';
|
||||||
|
|
||||||
|
var fontSize,
|
||||||
|
x = (source[prefix + 'x'] + target[prefix + 'x']) / 2,
|
||||||
|
y = (source[prefix + 'y'] + target[prefix + 'y']) / 2,
|
||||||
|
dX = target[prefix + 'x'] - source[prefix + 'x'],
|
||||||
|
dY = target[prefix + 'y'] - source[prefix + 'y'],
|
||||||
|
sign = (source[prefix + 'x'] < target[prefix + 'x']) ? 1 : -1,
|
||||||
|
angle = Math.atan2(dY * sign, dX * sign);
|
||||||
|
|
||||||
|
// The font size is sublineraly proportional to the edge size, in order to
|
||||||
|
// avoid very large labels on screen.
|
||||||
|
// This is achieved by f(x) = x * x^(-1/ a), where 'x' is the size and 'a'
|
||||||
|
// is the edgeLabelSizePowRatio. Notice that f(1) = 1.
|
||||||
|
// The final form is:
|
||||||
|
// f'(x) = b * x * x^(-1 / a), thus f'(1) = b. Application:
|
||||||
|
// fontSize = defaultEdgeLabelSize if edgeLabelSizePowRatio = 1
|
||||||
|
fontSize = (settings('edgeLabelSize') === 'fixed') ?
|
||||||
|
settings('defaultEdgeLabelSize') :
|
||||||
|
settings('defaultEdgeLabelSize') *
|
||||||
|
size *
|
||||||
|
Math.pow(size, -1 / settings('edgeLabelSizePowRatio'));
|
||||||
|
|
||||||
|
context.save();
|
||||||
|
|
||||||
|
if (edge.active) {
|
||||||
|
context.font = [
|
||||||
|
settings('activeFontStyle'),
|
||||||
|
fontSize + 'px',
|
||||||
|
settings('activeFont') || settings('font')
|
||||||
|
].join(' ');
|
||||||
|
|
||||||
|
context.fillStyle =
|
||||||
|
settings('edgeActiveColor') === 'edge' ?
|
||||||
|
(edge.active_color || settings('defaultEdgeActiveColor')) :
|
||||||
|
settings('defaultEdgeLabelActiveColor');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.font = [
|
||||||
|
settings('fontStyle'),
|
||||||
|
fontSize + 'px',
|
||||||
|
settings('font')
|
||||||
|
].join(' ');
|
||||||
|
|
||||||
|
context.fillStyle =
|
||||||
|
(settings('edgeLabelColor') === 'edge') ?
|
||||||
|
(edge.color || settings('defaultEdgeColor')) :
|
||||||
|
settings('defaultEdgeLabelColor');
|
||||||
|
}
|
||||||
|
|
||||||
|
context.textAlign = 'center';
|
||||||
|
context.textBaseline = 'alphabetic';
|
||||||
|
|
||||||
|
context.translate(x, y);
|
||||||
|
context.rotate(angle);
|
||||||
|
context.fillText(
|
||||||
|
edge.label,
|
||||||
|
0,
|
||||||
|
(-size / 2) - 3
|
||||||
|
);
|
||||||
|
|
||||||
|
context.restore();
|
||||||
|
};
|
||||||
|
}).call(this);
|
|
@ -42,7 +42,7 @@ window.UserConfig = Backbone.Model.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function () {
|
error: function () {
|
||||||
arangoHelper.arangoNotification('User configuration', 'Could not update user configuration for key: ' + keyName);
|
arangoHelper.arangoError('User configuration', 'Could not update user configuration for key: ' + keyName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -61,7 +61,7 @@ window.UserConfig = Backbone.Model.extend({
|
||||||
callback(keyValue);
|
callback(keyValue);
|
||||||
},
|
},
|
||||||
error: function () {
|
error: function () {
|
||||||
arangoHelper.arangoNotification('User configuration', 'Could not fetch user configuration for key: ' + keyName);
|
arangoHelper.arangoError('User configuration', 'Could not fetch user configuration for key: ' + keyName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -671,6 +671,9 @@
|
||||||
this.waitForInit(this.graph2.bind(this), name);
|
this.waitForInit(this.graph2.bind(this), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.graphViewer2) {
|
||||||
|
this.graphViewer2.remove();
|
||||||
|
}
|
||||||
this.graphViewer2 = new window.GraphViewer2({
|
this.graphViewer2 = new window.GraphViewer2({
|
||||||
name: name,
|
name: name,
|
||||||
userConfig: this.userConfig
|
userConfig: this.userConfig
|
||||||
|
@ -684,6 +687,9 @@
|
||||||
this.waitForInit(this.graph2settings.bind(this), name);
|
this.waitForInit(this.graph2settings.bind(this), name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.graphSettingsView) {
|
||||||
|
this.graphSettingsView.remove();
|
||||||
|
}
|
||||||
this.graphSettingsView = new window.GraphSettingsView({
|
this.graphSettingsView = new window.GraphSettingsView({
|
||||||
name: name,
|
name: name,
|
||||||
userConfig: this.userConfig
|
userConfig: this.userConfig
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<% return name.charAt(0).toUpperCase() + string.slice(1);%>
|
<% return name.charAt(0).toUpperCase() + string.slice(1);%>
|
||||||
<% }; %>
|
<% }; %>
|
||||||
|
|
||||||
<div id="shardsContent" class="innerContent">
|
<div id="graphSettingsView" class="innerContent">
|
||||||
|
|
||||||
<div class="pure-g" style="margin-top: -15px">
|
<div class="pure-g" style="margin-top: -15px">
|
||||||
|
|
||||||
|
@ -21,15 +21,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-g pure-table pure-table-header pure-title">
|
|
||||||
<div class="pure-table-row">
|
|
||||||
<div class="<%= genClass %> left">Name</div>
|
|
||||||
<div class="<%= genClass %> left">Property</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pure-g pure-table pure-table-body">
|
<div class="pure-g pure-table pure-table-body">
|
||||||
<% _.each(specific, function(val, key) { %>
|
<% _.each(specific, function(val, key) { %>
|
||||||
|
|
||||||
|
<% if (val.type === 'divider') { %>
|
||||||
|
<div class="heading <%= genClass %> left"><%=val.name%></div>
|
||||||
|
<div class="<%= genClass %> left"></div>
|
||||||
|
<% } else { %>
|
||||||
|
|
||||||
<div class="<%= genClass %> left"><%=val.name%></div>
|
<div class="<%= genClass %> left"><%=val.name%></div>
|
||||||
<div class="<%= genClass %> left">
|
<div class="<%= genClass %> left">
|
||||||
|
|
||||||
|
@ -42,19 +41,23 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<% if (val.type === 'string') { %>
|
<% if (val.type === 'string') { %>
|
||||||
<input type="text" value="<%=VALUE%>" placeholder=""></input>
|
<input id="g_<%=key%>" type="text" placeholder="string"></input>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (val.type === 'number') { %>
|
||||||
|
<input id="g_<%=key%>" type="text" placeholder="number"></input>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<% if (val.type === 'color') { %>
|
<% if (val.type === 'color') { %>
|
||||||
<input type='color' name='color' value="<%=VALUE%>"/>
|
<input id="g_<%=key%>" type='color' name='color' value="<%=VALUE%>"/>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<% if (val.type === 'select') { %>
|
<% if (val.type === 'select') { %>
|
||||||
<div class="<%= genClass %> left">
|
<div class="<%= genClass %> left">
|
||||||
<select>
|
<select id="g_<%=key%>">
|
||||||
<% _.each(val, function(option, optKey) { %>
|
<% _.each(val, function(option, optKey) { %>
|
||||||
<% if (option.name) { %>
|
<% if (option.name) { %>
|
||||||
<option> <%=option.name%> </option>
|
<option value="<%=option.val%>"> <%=option.name%> </option>
|
||||||
<% } %>
|
<% } %>
|
||||||
<% }); %>
|
<% }); %>
|
||||||
</select>
|
</select>
|
||||||
|
@ -62,6 +65,7 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<% } %>
|
||||||
<% }); %>
|
<% }); %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -77,16 +81,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-g pure-table pure-table-header pure-title">
|
|
||||||
<div class="pure-table-row">
|
|
||||||
<div class="<%= genClass %> left">Name</div>
|
|
||||||
<div class="<%= genClass %> left">Property</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pure-g pure-table pure-table-body">
|
<div class="pure-g pure-table pure-table-body">
|
||||||
|
|
||||||
<% _.each(general, function(val, key) { %>
|
<% _.each(general, function(val, key) { %>
|
||||||
|
<% if (val.type === 'divider') { %>
|
||||||
|
<div class="heading <%= genClass %> left"><%=val.name%></div>
|
||||||
|
<div class="<%= genClass %> left"></div>
|
||||||
|
<% } else { %>
|
||||||
<div class="<%= genClass %> left"><%=val.name%></div>
|
<div class="<%= genClass %> left"><%=val.name%></div>
|
||||||
|
|
||||||
<% if (val.type === 'select') { %>
|
<% if (val.type === 'select') { %>
|
||||||
|
@ -101,9 +102,14 @@
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<% if (val.type === 'numeric') { %>
|
<% if (val.type === 'string') { %>
|
||||||
|
<input id="g_<%=key%>" type="text" placeholder="string"></input>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (val.type === 'number') { %>
|
||||||
<input id="g_<%=key%>" type="text" id="<%=val %>" value="<%=val.value %>" placeholder=""></input>
|
<input id="g_<%=key%>" type="text" id="<%=val %>" value="<%=val.value %>" placeholder=""></input>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
<% }); %>
|
<% }); %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,7 +7,23 @@
|
||||||
window.GraphSettingsView = Backbone.View.extend({
|
window.GraphSettingsView = Backbone.View.extend({
|
||||||
el: '#content',
|
el: '#content',
|
||||||
|
|
||||||
|
remove: function () {
|
||||||
|
this.$el.empty().off(); /* off to unbind the events */
|
||||||
|
this.stopListening();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
general: {
|
general: {
|
||||||
|
'graph': {
|
||||||
|
type: 'divider',
|
||||||
|
name: 'Graph'
|
||||||
|
},
|
||||||
|
'nodeStart': {
|
||||||
|
type: 'string',
|
||||||
|
name: 'Starting node',
|
||||||
|
desc: 'A valid node id. If empty, a random node will be chosen.',
|
||||||
|
value: 2
|
||||||
|
},
|
||||||
'layout': {
|
'layout': {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
name: 'Layout algorithm',
|
name: 'Layout algorithm',
|
||||||
|
@ -37,58 +53,73 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'depth': {
|
'depth': {
|
||||||
type: 'numeric',
|
type: 'number',
|
||||||
name: 'Search depth',
|
name: 'Search depth',
|
||||||
value: 2
|
value: 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
specific: {
|
specific: {
|
||||||
|
'nodes': {
|
||||||
|
type: 'divider',
|
||||||
|
name: 'Nodes'
|
||||||
|
},
|
||||||
'nodeLabel': {
|
'nodeLabel': {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
name: 'Node label',
|
name: 'Label',
|
||||||
desc: 'Default node color. RGB or HEX value.',
|
desc: 'Default node color. RGB or HEX value.',
|
||||||
default: '_key'
|
default: '_key'
|
||||||
},
|
},
|
||||||
'nodeColor': {
|
'nodeColor': {
|
||||||
type: 'color',
|
type: 'color',
|
||||||
name: 'Node color',
|
name: 'Color',
|
||||||
desc: 'Default node color. RGB or HEX value.',
|
desc: 'Default node color. RGB or HEX value.',
|
||||||
default: '#2ecc71'
|
default: '#2ecc71'
|
||||||
},
|
},
|
||||||
'nodeSize': {
|
'nodeSize': {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
name: 'Node size',
|
name: 'Sizing attribute',
|
||||||
desc: 'Default node size. Numeric value > 0.',
|
desc: 'Default node size. Numeric value > 0.'
|
||||||
value: undefined
|
},
|
||||||
|
'edges': {
|
||||||
|
type: 'divider',
|
||||||
|
name: 'Edges'
|
||||||
},
|
},
|
||||||
'edgeLabel': {
|
'edgeLabel': {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
name: 'Edge label',
|
name: 'Label',
|
||||||
desc: 'Default edge label.',
|
desc: 'Default edge label.'
|
||||||
value: undefined
|
|
||||||
},
|
},
|
||||||
'edgeColor': {
|
'edgeColor': {
|
||||||
type: 'color',
|
type: 'color',
|
||||||
name: 'Edge color',
|
name: 'Color',
|
||||||
desc: 'Default edge color. RGB or HEX value.',
|
desc: 'Default edge color. RGB or HEX value.',
|
||||||
default: '#cccccc'
|
default: '#cccccc'
|
||||||
},
|
},
|
||||||
'edgeSize': {
|
'edgeSize': {
|
||||||
type: 'string',
|
type: 'number',
|
||||||
name: 'Edge thickness',
|
name: 'Sizing',
|
||||||
desc: 'Default edge thickness. Numeric value > 0.',
|
desc: 'Default edge thickness. Numeric value > 0.'
|
||||||
value: undefined
|
|
||||||
},
|
},
|
||||||
'edgeType': {
|
'edgeType': {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
name: 'Edge type',
|
name: 'Type',
|
||||||
desc: 'The type of the edge',
|
desc: 'The type of the edge',
|
||||||
canvas: {
|
line: {
|
||||||
name: 'Straight'
|
name: 'Line',
|
||||||
|
val: 'line'
|
||||||
},
|
},
|
||||||
webgl: {
|
curve: {
|
||||||
name: 'Curved'
|
name: 'Curve',
|
||||||
|
val: 'curve'
|
||||||
|
},
|
||||||
|
arrow: {
|
||||||
|
name: 'Arrow',
|
||||||
|
val: 'arrow'
|
||||||
|
},
|
||||||
|
curvedArrow: {
|
||||||
|
name: 'Curved Arrow',
|
||||||
|
val: 'curvedArrow'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -112,7 +143,6 @@
|
||||||
this.userConfig.fetch({
|
this.userConfig.fetch({
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
self.graphConfig = data.toJSON().graphs[combinedName];
|
self.graphConfig = data.toJSON().graphs[combinedName];
|
||||||
|
|
||||||
if (render) {
|
if (render) {
|
||||||
self.continueRender();
|
self.continueRender();
|
||||||
}
|
}
|
||||||
|
@ -127,7 +157,15 @@
|
||||||
config[combinedName] = {
|
config[combinedName] = {
|
||||||
layout: $('#g_layout').val(),
|
layout: $('#g_layout').val(),
|
||||||
renderer: $('#g_renderer').val(),
|
renderer: $('#g_renderer').val(),
|
||||||
depth: $('#g_depth').val()
|
depth: $('#g_depth').val(),
|
||||||
|
nodeColor: $('#g_nodeColor').val(),
|
||||||
|
edgeColor: $('#g_edgeColor').val(),
|
||||||
|
nodeLabel: $('#g_nodeLabel').val(),
|
||||||
|
edgeLabel: $('#g_edgeLabel').val(),
|
||||||
|
edgeType: $('#g_edgeType').val(),
|
||||||
|
nodeSize: $('#g_nodeSize').val(),
|
||||||
|
edgeSize: $('#g_edgeSize').val(),
|
||||||
|
nodeStart: $('#g_nodeStart').val()
|
||||||
};
|
};
|
||||||
|
|
||||||
var callback = function () {
|
var callback = function () {
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
/* jshint browser: true */
|
/* jshint browser: true */
|
||||||
/* jshint unused: false */
|
/* jshint unused: false */
|
||||||
/* global arangoHelper, slicePath, icon, wheelnav, document, sigma, Backbone, templateEngine, $, window*/
|
/* global arangoHelper, _, slicePath, icon, wheelnav, document, sigma, Backbone, templateEngine, $, window*/
|
||||||
(function () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
window.GraphViewer2 = Backbone.View.extend({
|
window.GraphViewer2 = Backbone.View.extend({
|
||||||
el: '#content',
|
el: '#content',
|
||||||
|
|
||||||
|
remove: function () {
|
||||||
|
this.$el.empty().off(); /* off to unbind the events */
|
||||||
|
this.stopListening();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
template: templateEngine.createTemplate('graphViewer2.ejs'),
|
template: templateEngine.createTemplate('graphViewer2.ejs'),
|
||||||
|
|
||||||
initialize: function (options) {
|
initialize: function (options) {
|
||||||
|
@ -64,30 +70,104 @@
|
||||||
$('#content').append(
|
$('#content').append(
|
||||||
'<div id="calculatingGraph" style="position: absolute; left: 25px; top: 130px;">' +
|
'<div id="calculatingGraph" style="position: absolute; left: 25px; top: 130px;">' +
|
||||||
'<i class="fa fa-circle-o-notch fa-spin" style="margin-right: 10px;"></i>' +
|
'<i class="fa fa-circle-o-notch fa-spin" style="margin-right: 10px;"></i>' +
|
||||||
'Calculating layout. Please wait ... </div>'
|
'<span id="calcText">Fetching graph data. Please wait ... </span></div>'
|
||||||
);
|
);
|
||||||
|
|
||||||
var fetchGraph = function () {
|
var continueFetchGraph = function () {
|
||||||
|
var ajaxData = {};
|
||||||
|
if (this.graphConfig) {
|
||||||
|
ajaxData = _.clone(this.graphConfig);
|
||||||
|
|
||||||
|
// remove not needed params
|
||||||
|
delete ajaxData.layout;
|
||||||
|
delete ajaxData.edgeType;
|
||||||
|
delete ajaxData.renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setupSigma();
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url: arangoHelper.databaseUrl('/_admin/aardvark/graph/' + encodeURIComponent(this.name)),
|
url: arangoHelper.databaseUrl('/_admin/aardvark/graph/' + encodeURIComponent(this.name)),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
|
data: ajaxData,
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
|
$('#calcText').html('Calculating layout. Please wait ... ');
|
||||||
arangoHelper.buildGraphSubNav(self.name, 'Content');
|
arangoHelper.buildGraphSubNav(self.name, 'Content');
|
||||||
self.renderGraph(data);
|
self.renderGraph(data);
|
||||||
},
|
},
|
||||||
error: function () {
|
error: function (e) {
|
||||||
|
console.log(e);
|
||||||
|
try {
|
||||||
|
arangoHelper.arangoError('Graph', e.responseJSON.exception);
|
||||||
|
} catch (ignore) {}
|
||||||
|
|
||||||
$('#calculatingGraph').html('Failed to fetch graph information.');
|
$('#calculatingGraph').html('Failed to fetch graph information.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
|
|
||||||
// TODO LOAD GRAPH SETTINGS
|
// load graph configuration
|
||||||
this.getGraphSettings(fetchGraph);
|
this.getGraphSettings(continueFetchGraph);
|
||||||
},
|
},
|
||||||
|
|
||||||
clearOldContextMenu: function () {
|
setupSigma: function () {
|
||||||
|
if (this.graphConfig) {
|
||||||
|
if (this.graphConfig.edgeLabel) {
|
||||||
|
// Initialize package:
|
||||||
|
sigma.utils.pkg('sigma.settings');
|
||||||
|
|
||||||
|
var settings = {
|
||||||
|
defaultEdgeLabelColor: '#000',
|
||||||
|
defaultEdgeLabelActiveColor: '#000',
|
||||||
|
defaultEdgeLabelSize: 10,
|
||||||
|
edgeLabelSize: 'fixed',
|
||||||
|
edgeLabelSizePowRatio: 1,
|
||||||
|
edgeLabelThreshold: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Export the previously designed settings:
|
||||||
|
sigma.settings = sigma.utils.extend(sigma.settings || {}, settings);
|
||||||
|
|
||||||
|
// Override default settings:
|
||||||
|
sigma.settings.drawEdgeLabels = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
contextState: {
|
||||||
|
createEdge: false,
|
||||||
|
_from: false,
|
||||||
|
_to: false,
|
||||||
|
fromX: false,
|
||||||
|
fromY: false
|
||||||
|
},
|
||||||
|
|
||||||
|
clearOldContextMenu: function (states) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
// clear dom
|
||||||
$('#nodeContextMenu').remove();
|
$('#nodeContextMenu').remove();
|
||||||
|
var string = '<div id="nodeContextMenu" class="nodeContextMenu"></div>';
|
||||||
|
$('#graph-container').append(string);
|
||||||
|
|
||||||
|
// clear state
|
||||||
|
if (states) {
|
||||||
|
_.each(this.contextState, function (val, key) {
|
||||||
|
self.contextState[key] = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear info div
|
||||||
|
},
|
||||||
|
|
||||||
|
createContextMenu: function (e) {
|
||||||
|
var x = e.data.captor.clientX;
|
||||||
|
var y = e.data.captor.clientX;
|
||||||
|
console.log('Context menu');
|
||||||
|
console.log(x);
|
||||||
|
console.log(y);
|
||||||
|
this.clearOldContextMenu();
|
||||||
},
|
},
|
||||||
|
|
||||||
createNodeContextMenu: function (nodeId, e) {
|
createNodeContextMenu: function (nodeId, e) {
|
||||||
|
@ -97,8 +177,6 @@
|
||||||
var y = e.data.node['renderer1:y'];
|
var y = e.data.node['renderer1:y'];
|
||||||
|
|
||||||
this.clearOldContextMenu();
|
this.clearOldContextMenu();
|
||||||
var string = '<div id="nodeContextMenu" class="nodeContextMenu"></div>';
|
|
||||||
$('#graph-container').append(string);
|
|
||||||
|
|
||||||
var generateMenu = function (e, nodeId) {
|
var generateMenu = function (e, nodeId) {
|
||||||
var hotaru = ['#364C4A', '#497C7F', '#92C5C0', '#858168', '#CCBCA5'];
|
var hotaru = ['#364C4A', '#497C7F', '#92C5C0', '#858168', '#CCBCA5'];
|
||||||
|
@ -110,35 +188,49 @@
|
||||||
wheel.wheelRadius = 50;
|
wheel.wheelRadius = 50;
|
||||||
wheel.clockwise = false;
|
wheel.clockwise = false;
|
||||||
wheel.colors = hotaru;
|
wheel.colors = hotaru;
|
||||||
|
wheel.multiSelect = true;
|
||||||
wheel.clickModeRotate = false;
|
wheel.clickModeRotate = false;
|
||||||
wheel.slicePathFunction = slicePath().DonutSlice;
|
wheel.slicePathFunction = slicePath().DonutSlice;
|
||||||
wheel.createWheel([icon.edit, icon.trash, icon.smallgear, icon.smallgear]);
|
wheel.createWheel([icon.edit, icon.trash, icon.arrowleft2, icon.connect]);
|
||||||
|
|
||||||
|
wheel.navItems[0].selected = false;
|
||||||
|
wheel.navItems[0].hovered = false;
|
||||||
// add menu events
|
// add menu events
|
||||||
|
|
||||||
// function 0: edit
|
// function 0: edit
|
||||||
wheel.navItems[0].navigateFunction = function () {
|
wheel.navItems[0].navigateFunction = function (e) {
|
||||||
self.clearOldContextMenu();
|
self.clearOldContextMenu();
|
||||||
self.editNode(nodeId);
|
self.editNode(nodeId);
|
||||||
};
|
};
|
||||||
|
|
||||||
// function 1:
|
// function 1: delete
|
||||||
wheel.navItems[1].navigateFunction = function () {
|
wheel.navItems[1].navigateFunction = function (e) {
|
||||||
self.clearOldContextMenu();
|
self.clearOldContextMenu();
|
||||||
self.editNode(nodeId);
|
self.deleteNode(nodeId);
|
||||||
};
|
};
|
||||||
|
|
||||||
// function 2:
|
// function 2: mark as start node
|
||||||
wheel.navItems[2].navigateFunction = function () {
|
wheel.navItems[2].navigateFunction = function (e) {
|
||||||
self.clearOldContextMenu();
|
self.clearOldContextMenu();
|
||||||
self.editNode(nodeId);
|
self.setStartNode(nodeId);
|
||||||
};
|
};
|
||||||
|
|
||||||
// function 3: delete
|
// function 3: create edge
|
||||||
wheel.navItems[3].navigateFunction = function () {
|
wheel.navItems[3].navigateFunction = function (e) {
|
||||||
|
self.contextState.createEdge = true;
|
||||||
|
self.contextState._from = nodeId;
|
||||||
|
self.contextState.fromX = x;
|
||||||
|
self.contextState.fromY = y;
|
||||||
|
|
||||||
|
var c = document.getElementsByClassName('sigma-mouse')[0];
|
||||||
|
c.addEventListener('mousemove', self.drawLine.bind(this), false);
|
||||||
|
|
||||||
self.clearOldContextMenu();
|
self.clearOldContextMenu();
|
||||||
self.editNode(nodeId);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// deselect active default entry
|
||||||
|
wheel.navItems[0].selected = false;
|
||||||
|
wheel.navItems[0].hovered = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
$('#nodeContextMenu').css('left', x + 115);
|
$('#nodeContextMenu').css('left', x + 115);
|
||||||
|
@ -149,6 +241,31 @@
|
||||||
generateMenu(e, nodeId);
|
generateMenu(e, nodeId);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clearMouseCanvas: function () {
|
||||||
|
var c = document.getElementsByClassName('sigma-mouse')[0];
|
||||||
|
var ctx = c.getContext('2d');
|
||||||
|
ctx.clearRect(0, 0, $(c).width(), $(c).height());
|
||||||
|
},
|
||||||
|
|
||||||
|
drawLine: function (e) {
|
||||||
|
var context = window.App.graphViewer2.contextState;
|
||||||
|
|
||||||
|
if (context.createEdge) {
|
||||||
|
var fromX = context.fromX;
|
||||||
|
var fromY = context.fromY;
|
||||||
|
var toX = e.offsetX;
|
||||||
|
var toY = e.offsetY;
|
||||||
|
|
||||||
|
var c = document.getElementsByClassName('sigma-mouse')[0];
|
||||||
|
var ctx = c.getContext('2d');
|
||||||
|
ctx.clearRect(0, 0, $(c).width(), $(c).height());
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(fromX, fromY);
|
||||||
|
ctx.lineTo(toX, toY);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
getGraphSettings: function (callback) {
|
getGraphSettings: function (callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var combinedName = window.App.currentDB.toJSON().name + '_' + this.name;
|
var combinedName = window.App.currentDB.toJSON().name + '_' + this.name;
|
||||||
|
@ -158,7 +275,7 @@
|
||||||
self.graphConfig = data.toJSON().graphs[combinedName];
|
self.graphConfig = data.toJSON().graphs[combinedName];
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback(self.graphConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -184,8 +301,6 @@
|
||||||
var renderer = 'canvas';
|
var renderer = 'canvas';
|
||||||
|
|
||||||
if (this.graphConfig) {
|
if (this.graphConfig) {
|
||||||
console.log(this.graphConfig);
|
|
||||||
|
|
||||||
if (this.graphConfig.layout) {
|
if (this.graphConfig.layout) {
|
||||||
algorithm = this.graphConfig.layout;
|
algorithm = this.graphConfig.layout;
|
||||||
}
|
}
|
||||||
|
@ -201,20 +316,28 @@
|
||||||
|
|
||||||
var settings = {
|
var settings = {
|
||||||
doubleClickEnabled: false,
|
doubleClickEnabled: false,
|
||||||
minEdgeSize: 0.5,
|
minNodeSize: 3.5,
|
||||||
|
minEdgeSize: 1,
|
||||||
maxEdgeSize: 4,
|
maxEdgeSize: 4,
|
||||||
enableEdgeHovering: true,
|
enableEdgeHovering: true,
|
||||||
// edgeHoverColor: 'edge',
|
edgeHoverColor: '#000',
|
||||||
// defaultEdgeHoverColor: '#000',
|
defaultEdgeHoverColor: '#000',
|
||||||
// defaultEdgeType: 'curve',
|
defaultEdgeType: 'line',
|
||||||
edgeHoverSizeRatio: 1,
|
edgeHoverSizeRatio: 2,
|
||||||
edgeHoverExtremities: true
|
edgeHoverExtremities: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this.graphConfig) {
|
||||||
|
if (this.graphConfig.edgeType) {
|
||||||
|
settings.defaultEdgeType = this.graphConfig.edgeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// adjust display settings for big graphs
|
// adjust display settings for big graphs
|
||||||
if (graph.nodes.length > 500) {
|
if (graph.nodes.length > 500) {
|
||||||
// show node label if size is 20
|
// show node label if size is 15
|
||||||
settings.labelThreshold = 20;
|
settings.labelThreshold = 15;
|
||||||
|
settings.hideEdgesOnMove = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust display settings for webgl renderer
|
// adjust display settings for webgl renderer
|
||||||
|
@ -271,7 +394,33 @@
|
||||||
e.originalColor = e.color;
|
e.originalColor = e.color;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (renderer !== 'webgl') {
|
// for canvas renderer allow graph editing
|
||||||
|
if (renderer === 'canvas') {
|
||||||
|
s.bind('rightClickStage', function (e) {
|
||||||
|
self.createContextMenu(e);
|
||||||
|
self.clearMouseCanvas();
|
||||||
|
});
|
||||||
|
|
||||||
|
s.bind('clickNode', function (e) {
|
||||||
|
if (self.contextState.createEdge === true) {
|
||||||
|
// create the edge
|
||||||
|
self.contextState._to = e.data.node.id;
|
||||||
|
|
||||||
|
self.currentGraph.graph.addEdge({
|
||||||
|
source: self.contextState._from,
|
||||||
|
target: self.contextState._to,
|
||||||
|
id: Math.random(),
|
||||||
|
color: self.graphConfig.edgeColor
|
||||||
|
});
|
||||||
|
|
||||||
|
// rerender graph
|
||||||
|
self.currentGraph.refresh();
|
||||||
|
|
||||||
|
// then clear states
|
||||||
|
self.clearOldContextMenu(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
s.bind('rightClickNode', function (e) {
|
s.bind('rightClickNode', function (e) {
|
||||||
var nodeId = e.data.node.id;
|
var nodeId = e.data.node.id;
|
||||||
self.createNodeContextMenu(nodeId, e);
|
self.createNodeContextMenu(nodeId, e);
|
||||||
|
@ -314,7 +463,8 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
s.bind('clickStage', function () {
|
s.bind('clickStage', function () {
|
||||||
self.clearOldContextMenu();
|
self.clearOldContextMenu(true);
|
||||||
|
self.clearMouseCanvas();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,11 +477,18 @@
|
||||||
} else if (algorithm === 'force') {
|
} else if (algorithm === 'force') {
|
||||||
s.startForceAtlas2({worker: true, barnesHutOptimize: false});
|
s.startForceAtlas2({worker: true, barnesHutOptimize: false});
|
||||||
|
|
||||||
|
var duration = 3000;
|
||||||
|
|
||||||
|
if (graph.nodes.length > 2500) {
|
||||||
|
duration = 5000;
|
||||||
|
} else if (graph.nodes.length < 50) {
|
||||||
|
duration = 500;
|
||||||
|
}
|
||||||
|
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
s.stopForceAtlas2();
|
s.stopForceAtlas2();
|
||||||
dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
|
dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
|
||||||
console.log('stopped force');
|
}, duration);
|
||||||
}, 3000);
|
|
||||||
} else if (algorithm === 'fruchtermann') {
|
} else if (algorithm === 'fruchtermann') {
|
||||||
// Start the Fruchterman-Reingold algorithm:
|
// Start the Fruchterman-Reingold algorithm:
|
||||||
sigma.layouts.fruchtermanReingold.start(s);
|
sigma.layouts.fruchtermanReingold.start(s);
|
||||||
|
|
|
@ -45,8 +45,19 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
path {
|
#wheelnav-nodeContextMenu-title-0 {
|
||||||
font-size: 2pt !important;
|
transform: translate(24px, 14px) scale(.7) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wheelnav-nodeContextMenu-title-0,
|
||||||
|
#wheelnav-nodeContextMenu-title-1,
|
||||||
|
#wheelnav-nodeContextMenu-title-2,
|
||||||
|
#wheelnav-nodeContextMenu-title-3 {
|
||||||
|
fill: $c-white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
fill: $c-positive;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,13 @@
|
||||||
.dataTables_empty {
|
.dataTables_empty {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
font-weight: 600;
|
||||||
|
height: 40px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.pure-table {
|
.pure-table {
|
||||||
|
|
Loading…
Reference in New Issue