Skip to content

Commit 8ddfe7e

Browse files
committed
sankey: node.(x|y) honors uirevision
1 parent 370250e commit 8ddfe7e

File tree

3 files changed

+78
-2
lines changed

3 files changed

+78
-2
lines changed

src/plot_api/plot_api.js

+1
Original file line numberDiff line numberDiff line change
@@ -2524,6 +2524,7 @@ var traceUIControlPatterns = [
25242524
// "visible" includes trace.transforms[i].styles[j].value.visible
25252525
{pattern: /(^|value\.)visible$/, attr: 'legend.uirevision'},
25262526
{pattern: /^dimensions\[\d+\]\.constraintrange/},
2527+
{pattern: /^node\.(x|y)/}, // for Sankey nodes
25272528

25282529
// below this you must be in editable: true mode
25292530
// TODO: I still put name and title with `trace.uirevision`

src/traces/sankey/render.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ function sankeyModel(layout, d, traceIndex) {
208208
var columns = [];
209209
var colNumber = -1;
210210
var colX; // Position of column
211-
var lastX = -nodeThickness; // Position of last node
211+
var lastX = -Infinity; // Position of last node
212212
var dx;
213213
for(i = 0; i < orderedNodes.length; i++) {
214214
var node = nodes[orderedNodes[i].index];
@@ -751,7 +751,7 @@ function persistFinalNodePositions(d, gd) {
751751
x.push(nodeX / d.figure.width);
752752
y.push(nodeY / d.figure.height);
753753
}
754-
Plotly.restyle(gd, {
754+
Plotly._guiRestyle(gd, {
755755
'node.x': [x],
756756
'node.y': [y]
757757
}, d.trace.index)

test/jasmine/tests/sankey_test.js

+75
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ var defaultColors = require('@src/components/color/attributes').defaults;
2222

2323
var drag = require('../assets/drag');
2424
var checkOverlap = require('../assets/check_overlap');
25+
var delay = require('../assets/delay');
2526

2627
describe('sankey tests', function() {
2728

@@ -1150,6 +1151,80 @@ describe('sankey tests', function() {
11501151
});
11511152
});
11521153
});
1154+
1155+
describe('in relation to uirevision', function() {
1156+
var gd;
1157+
1158+
beforeEach(function() {
1159+
gd = createGraphDiv();
1160+
});
1161+
1162+
afterEach(function() {
1163+
Plotly.purge(gd);
1164+
destroyGraphDiv();
1165+
});
1166+
1167+
['0', '1'].forEach(function(finalUIRevision) {
1168+
it('on Plotly.react, it preserves the position of nodes depending on layout.uirevision', function(done) {
1169+
var nodes, node, positionBeforeDrag, positionAfterDrag;
1170+
var move = [-50, 100];
1171+
var uirevisions = ['0', finalUIRevision];
1172+
1173+
// Use a freeform arrangement
1174+
var mockCircularFreeform = Lib.extendDeep({}, mockCircular);
1175+
mockCircularFreeform.data[0].arrangement = 'freeform';
1176+
1177+
var mockCopy = Lib.extendDeep({}, mockCircularFreeform);
1178+
mockCopy.layout.uirevision = uirevisions[0];
1179+
1180+
Plotly.plot(gd, mockCopy)
1181+
.then(function() {
1182+
// move a node around
1183+
nodes = document.getElementsByClassName('sankey-node');
1184+
node = Array.prototype.slice.call(nodes).find(function(n) { return n.textContent === '0';});
1185+
positionBeforeDrag = getNodeCoords(node);
1186+
positionBeforeDrag = [positionBeforeDrag.x, positionBeforeDrag.y];
1187+
positionAfterDrag = [positionBeforeDrag[0] + move[0], positionBeforeDrag[1] + move[1]];
1188+
return drag(node, move[0], move[1], false, false, false, 10, false, 1000);
1189+
})
1190+
.then(function() {
1191+
// Check that the node was really moved
1192+
nodes = document.getElementsByClassName('sankey-node');
1193+
node = Array.prototype.slice.call(nodes).find(function(n) { return n.textContent === '0';});
1194+
var newPosition = getNodeCoords(node);
1195+
expect(newPosition.x).toBeCloseTo(positionAfterDrag[0], 2, 'final x position is off');
1196+
expect(newPosition.y).toBeCloseTo(positionAfterDrag[1], 2, 'final y position is off');
1197+
1198+
// Change color of nodes
1199+
var mockCopy = Lib.extendDeep({}, mockCircularFreeform);
1200+
mockCopy.data[0].node.color = 'orange';
1201+
mockCopy.layout.uirevision = uirevisions[1];
1202+
return Plotly.react(gd, mockCopy);
1203+
})
1204+
.then(delay(1000))
1205+
.then(function() {
1206+
nodes = document.getElementsByClassName('sankey-node');
1207+
node = Array.prototype.slice.call(nodes).find(function(n) { return n.textContent === '0';});
1208+
var newPosition = getNodeCoords(node);
1209+
1210+
var pos, msg;
1211+
if(uirevisions[0] === uirevisions[1]) {
1212+
// If uirevision is the same, the node should stay where it is
1213+
pos = positionAfterDrag;
1214+
msg = 'should stay the same because uirevision did not change';
1215+
} else {
1216+
// If uirevision changed, the node should go back to its default position
1217+
pos = positionBeforeDrag;
1218+
msg = 'should go back to its default because uirevision changed';
1219+
}
1220+
expect(newPosition.x).toBeCloseTo(pos[0], 2, 'x position ' + msg);
1221+
expect(newPosition.y).toBeCloseTo(pos[1], 2, 'y position ' + msg);
1222+
})
1223+
.catch(failTest)
1224+
.then(done);
1225+
});
1226+
});
1227+
});
11531228
});
11541229

11551230
it('emits a warning if node.pad is too large', function(done) {

0 commit comments

Comments
 (0)