NIFI-13141: (#8752) - Adding a dragging flag to not reset positioning for labels and connection bends if the user is currently performing an action.

This closes #8752
This commit is contained in:
Matt Gilman 2024-05-06 16:15:15 -04:00 committed by GitHub
parent 030435d996
commit e7facda912
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 291 additions and 199 deletions

View File

@ -343,8 +343,9 @@ export class ConnectionManager {
* Saves the connection entry specified by d with the new configuration specified * Saves the connection entry specified by d with the new configuration specified
* in connection. * in connection.
* *
* @param {type} d * @param d
* @param {type} connection * @param connection
* @param restoreOnFailure
*/ */
private save(d: any, connection: any, restoreOnFailure?: any): void { private save(d: any, connection: any, restoreOnFailure?: any): void {
const updateConnection: UpdateComponentRequest = { const updateConnection: UpdateComponentRequest = {
@ -616,7 +617,7 @@ export class ConnectionManager {
// if we are currently dragging the endpoint to a new target, use that // if we are currently dragging the endpoint to a new target, use that
// position, otherwise we need to calculate it for the current target // position, otherwise we need to calculate it for the current target
if (d.end?.dragging) { if (d.end?.endPointDragging) {
// since we're dragging, use the same object thats bound to the endpoint drag event // since we're dragging, use the same object thats bound to the endpoint drag event
end = d.end; end = d.end;
@ -1844,11 +1845,20 @@ export class ConnectionManager {
// handle bend point drag events // handle bend point drag events
this.bendPointDrag = d3 this.bendPointDrag = d3
.drag() .drag()
.on('start', function (event) { .on('start', function (this: any, event) {
// stop further propagation // stop further propagation
event.sourceEvent.stopPropagation(); event.sourceEvent.stopPropagation();
// indicate dragging start
const connection: any = d3.select(this.parentNode);
const connectionData: any = connection.datum();
connectionData.dragging = true;
}) })
.on('drag', function (this: any, event, d: any) { .on('drag', function (this: any, event, d: any) {
const connection: any = d3.select(this.parentNode);
const connectionData: any = connection.datum();
if (connectionData.dragging) {
self.snapEnabled = !event.sourceEvent.shiftKey; self.snapEnabled = !event.sourceEvent.shiftKey;
d.x = self.snapEnabled d.x = self.snapEnabled
? Math.round(event.x / ConnectionManager.SNAP_ALIGNMENT_PIXELS) * ? Math.round(event.x / ConnectionManager.SNAP_ALIGNMENT_PIXELS) *
@ -1864,10 +1874,13 @@ export class ConnectionManager {
updatePath: true, updatePath: true,
updateLabel: false updateLabel: false
}); });
}
}) })
.on('end', function (this: any, event) { .on('end', function (this: any, event) {
const connection: any = d3.select(this.parentNode); const connection: any = d3.select(this.parentNode);
const connectionData: any = connection.datum(); const connectionData: any = connection.datum();
if (connectionData.dragging) {
const bends: Position[] = connection.selectAll('rect.midpoint').data(); const bends: Position[] = connection.selectAll('rect.midpoint').data();
// ensure the bend lengths are the same // ensure the bend lengths are the same
@ -1897,22 +1910,35 @@ export class ConnectionManager {
); );
} }
} }
}
// stop further propagation // stop further propagation
event.sourceEvent.stopPropagation(); event.sourceEvent.stopPropagation();
// indicate dragging complete
connectionData.dragging = false;
}); });
// handle endpoint drag events // handle endpoint drag events
this.endpointDrag = d3 this.endpointDrag = d3
.drag() .drag()
.on('start', function (event, d: any) { .on('start', function (this: any, event, d: any) {
// indicate that dragging has begun // indicate that end point dragging has begun
d.dragging = true; d.endPointDragging = true;
// stop further propagation // stop further propagation
event.sourceEvent.stopPropagation(); event.sourceEvent.stopPropagation();
// indicate dragging start
const connection: any = d3.select(this.parentNode);
const connectionData: any = connection.datum();
connectionData.dragging = true;
}) })
.on('drag', function (this: any, event, d: any) { .on('drag', function (this: any, event, d: any) {
const connection: any = d3.select(this.parentNode);
const connectionData: any = connection.datum();
if (connectionData.dragging) {
d.x = event.x - 8; d.x = event.x - 8;
d.y = event.y - 8; d.y = event.y - 8;
@ -1926,15 +1952,17 @@ export class ConnectionManager {
updatePath: true, updatePath: true,
updateLabel: false updateLabel: false
}); });
}
}) })
.on('end', function (this: any, event, d: any) { .on('end', function (this: any, event, d: any) {
// indicate that dragging as stopped // indicate that end point dragging as stopped
d.dragging = false; d.endPointDragging = false;
// get the corresponding connection // get the corresponding connection
const connection: any = d3.select(this.parentNode); const connection: any = d3.select(this.parentNode);
const connectionData: any = connection.datum(); const connectionData: any = connection.datum();
if (connectionData.dragging) {
// attempt to select a new destination // attempt to select a new destination
const destination: any = d3.select('g.connectable-destination'); const destination: any = d3.select('g.connectable-destination');
@ -1977,7 +2005,8 @@ export class ConnectionManager {
const payload: any = { const payload: any = {
revision: self.client.getRevision(connectionData), revision: self.client.getRevision(connectionData),
disconnectedNodeAcknowledged: self.clusterConnectionService.isDisconnectionAcknowledged(), disconnectedNodeAcknowledged:
self.clusterConnectionService.isDisconnectionAcknowledged(),
component: { component: {
id: connectionData.id, id: connectionData.id,
destination: { destination: {
@ -2020,20 +2049,27 @@ export class ConnectionManager {
); );
} }
} }
}
// stop further propagation // stop further propagation
event.sourceEvent.stopPropagation(); event.sourceEvent.stopPropagation();
// indicate dragging complete
connectionData.dragging = false;
}); });
// label drag behavior // label drag behavior
this.labelDrag = d3 this.labelDrag = d3
.drag() .drag()
.on('start', function (event) { .on('start', function (event, d: any) {
// stop further propagation // stop further propagation
event.sourceEvent.stopPropagation(); event.sourceEvent.stopPropagation();
// indicate dragging start
d.dragging = true;
}) })
.on('drag', function (this: any, event, d: any) { .on('drag', function (this: any, event, d: any) {
if (d && d.bends.length > 1) { if (d.dragging && d.bends.length > 1) {
// get the dragged component // get the dragged component
let drag: any = d3.select('rect.label-drag'); let drag: any = d3.select('rect.label-drag');
@ -2113,7 +2149,7 @@ export class ConnectionManager {
} }
}) })
.on('end', function (this: any, event, d: any) { .on('end', function (this: any, event, d: any) {
if (d.bends.length > 1) { if (d.dragging && d.bends.length > 1) {
// get the drag selection // get the drag selection
const drag: any = d3.select('rect.label-drag'); const drag: any = d3.select('rect.label-drag');
@ -2140,6 +2176,9 @@ export class ConnectionManager {
// stop further propagation // stop further propagation
event.sourceEvent.stopPropagation(); event.sourceEvent.stopPropagation();
// indicate dragging complete
d.dragging = false;
}); });
this.store this.store
@ -2187,12 +2226,38 @@ export class ConnectionManager {
private set(connections: any): void { private set(connections: any): void {
// update the connections // update the connections
this.connections = connections.map((connection: any) => { this.connections = connections.map((connection: any) => {
const currentConnection: any = this.connections.find((c: any) => c.id === connection.id);
// only consider newer when the version is greater which indicates the component configuration has changed.
// when this happens we should override the current dragging action so that the new changes can be realized.
const isNewerRevision = connection.revision.version > currentConnection?.revision.version;
let dragging = false;
if (currentConnection?.dragging && !isNewerRevision) {
dragging = true;
}
let bends: Position[];
if (dragging) {
bends = currentConnection.bends;
} else {
bends = connection.bends.map((bend: Position) => {
return { ...bend };
});
}
let end: Position | undefined;
if (dragging) {
end = currentConnection.end;
}
return { return {
...connection, ...connection,
type: ComponentType.Connection, type: ComponentType.Connection,
bends: connection.bends.map((bend: Position) => { dragging,
return { ...bend }; labelIndex: dragging ? currentConnection.labelIndex : connection.labelIndex,
}) bends,
end
}; };
}); });

View File

@ -304,37 +304,47 @@ export class LabelManager {
// handle bend point drag events // handle bend point drag events
this.labelPointDrag = d3 this.labelPointDrag = d3
.drag() .drag()
.on('start', function (event) { .on('start', function (this: any, event) {
// stop further propagation // stop further propagation
event.sourceEvent.stopPropagation(); event.sourceEvent.stopPropagation();
// indicate dragging start
const label = d3.select(this.parentNode);
const labelData: any = label.datum();
labelData.dragging = true;
}) })
.on('drag', function (this: any, event) { .on('drag', function (this: any, event) {
const label = d3.select(this.parentNode); const label = d3.select(this.parentNode);
const labelData: any = label.datum(); const labelData: any = label.datum();
if (labelData.dragging) {
// update the dimensions and ensure they are still within bounds // update the dimensions and ensure they are still within bounds
// snap between aligned sizes unless the user is holding shift // snap between aligned sizes unless the user is holding shift
self.snapEnabled = !event.sourceEvent.shiftKey; self.snapEnabled = !event.sourceEvent.shiftKey;
labelData.dimensions.width = Math.max( labelData.dimensions.width = Math.max(
LabelManager.MIN_WIDTH, LabelManager.MIN_WIDTH,
self.snapEnabled self.snapEnabled
? Math.round(event.x / LabelManager.SNAP_ALIGNMENT_PIXELS) * LabelManager.SNAP_ALIGNMENT_PIXELS ? Math.round(event.x / LabelManager.SNAP_ALIGNMENT_PIXELS) *
LabelManager.SNAP_ALIGNMENT_PIXELS
: event.x : event.x
); );
labelData.dimensions.height = Math.max( labelData.dimensions.height = Math.max(
LabelManager.MIN_HEIGHT, LabelManager.MIN_HEIGHT,
self.snapEnabled self.snapEnabled
? Math.round(event.y / LabelManager.SNAP_ALIGNMENT_PIXELS) * LabelManager.SNAP_ALIGNMENT_PIXELS ? Math.round(event.y / LabelManager.SNAP_ALIGNMENT_PIXELS) *
LabelManager.SNAP_ALIGNMENT_PIXELS
: event.y : event.y
); );
// redraw this connection // redraw this connection
self.updateLabels(label); self.updateLabels(label);
}
}) })
.on('end', function (this: any, event) { .on('end', function (this: any, event) {
const label = d3.select(this.parentNode); const label = d3.select(this.parentNode);
const labelData: any = label.datum(); const labelData: any = label.datum();
if (labelData.dragging) {
// determine if the width has changed // determine if the width has changed
let different = false; let different = false;
const widthSet = !!labelData.component.width; const widthSet = !!labelData.component.width;
@ -356,7 +366,8 @@ export class LabelManager {
uri: labelData.uri, uri: labelData.uri,
payload: { payload: {
revision: self.client.getRevision(labelData), revision: self.client.getRevision(labelData),
disconnectedNodeAcknowledged: self.clusterConnectionService.isDisconnectionAcknowledged(), disconnectedNodeAcknowledged:
self.clusterConnectionService.isDisconnectionAcknowledged(),
component: { component: {
id: labelData.id, id: labelData.id,
width: labelData.dimensions.width, width: labelData.dimensions.width,
@ -378,20 +389,36 @@ export class LabelManager {
}) })
); );
} }
}
// stop further propagation // stop further propagation
event.sourceEvent.stopPropagation(); event.sourceEvent.stopPropagation();
// indicate dragging complete
labelData.dragging = false;
}); });
} }
private set(labels: any): void { private set(labels: any): void {
// update the labels // update the labels
this.labels = labels.map((label: any) => { this.labels = labels.map((label: any) => {
const currentLabel: any = this.labels.find((l: any) => l.id === label.id);
// only consider newer when the version is greater which indicates the component configuration has changed.
// when this happens we should override the current dragging action so that the new changes can be realized.
const isNewerRevision = label.revision.version > currentLabel?.revision.version;
let dragging = false;
if (currentLabel?.dragging && !isNewerRevision) {
dragging = true;
}
return { return {
...label, ...label,
type: ComponentType.Label, type: ComponentType.Label,
dragging,
dimensions: { dimensions: {
...label.dimensions ...(dragging ? currentLabel.dimensions : label.dimensions)
} }
}; };
}); });

View File

@ -28,7 +28,7 @@
<div>Relationships</div> <div>Relationships</div>
<div class="flex flex-col gap-y-3"> <div class="flex flex-col gap-y-3">
@for (item of relationshipItems; track item; let i = $index) { @for (item of relationshipItems; track item; let i = $index) {
@if (isDisabled && item.selected || !isDisabled) { @if ((isDisabled && item.selected) || !isDisabled) {
<div class="flex flex-col gap-y-1.5"> <div class="flex flex-col gap-y-1.5">
<div class="flex items-center gap-x-2"> <div class="flex items-center gap-x-2">
<mat-checkbox <mat-checkbox