<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
nf.Draggable = (function () {

    var drag;

    /**
     * Updates the positioning of all selected components.
     * 
     * @param {selection} dragSelection The current drag selection
     */
    var updateComponentsPosition = function (dragSelection) {
        var revision = nf.Client.getRevision();
        var updates = d3.map();

        // determine the drag delta
        var dragData = dragSelection.datum();
        var delta = {
            x: dragData.x - dragData.original.x,
            y: dragData.y - dragData.original.y
        };

        // if the component didn't move, return
        if (delta.x === 0 && delta.y === 0) {
            return;
        }
        
        var updateComponentPosition = function(d) {
            var newPosition = {
                x: d.component.position.x + delta.x,
                y: d.component.position.y + delta.y
            };

            // update the component positioning
            return $.Deferred(function (deferred) {
                $.ajax({
                    type: 'PUT',
                    url: d.component.uri,
                    data: {
                        version: revision.version,
                        clientId: revision.clientId,
                        x: newPosition.x,
                        y: newPosition.y
                    },
                    dataType: 'json'
                }).done(function (response) {
                    // update the revision
                    nf.Client.setRevision(response.revision);

                    // store the updated location
                    d.component.position = newPosition;

                    // resolve with an object so we can refresh when finished
                    deferred.resolve({
                        type: d.type,
                        id: d.component.id
                    });
                }).fail(function (xhr, status, error) {
                    if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) {
                        nf.Dialog.showOkDialog({
                            dialogContent: nf.Common.escapeHtml(xhr.responseText),
                            overlayBackground: true
                        });
                    } else {
                        nf.Common.handleAjaxError(xhr, status, error);
                    }

                    deferred.reject();
                });
            }).promise();
        };
        
        var updateConnectionPosition = function(d) {
            // only update if necessary
            if (d.component.bends.length === 0) {
                return;
            }

            // calculate the new bend points
            var newBends = $.map(d.component.bends, function (bend) {
                return {
                    x: bend.x + delta.x,
                    y: bend.y + delta.y
                };
            });

            var entity = {
                revision: revision,
                connection: {
                    id: d.component.id,
                    bends: newBends
                }
            };

            // update the component positioning
            return $.Deferred(function (deferred) {
                $.ajax({
                    type: 'PUT',
                    url: d.component.uri,
                    data: JSON.stringify(entity),
                    dataType: 'json',
                    contentType: 'application/json'
                }).done(function (response) {
                    // update the revision
                    nf.Client.setRevision(response.revision);

                    // store the updated bend points
                    d.component.bends = response.connection.bends;
                    d.bends = $.map(d.component.bends, function (bend) {
                        return {
                            x: bend.x,
                            y: bend.y
                        };
                    });

                    // resolve with an object so we can refresh when finished
                    deferred.resolve({
                        type: d.type,
                        id: d.component.id
                    });
                }).fail(function (xhr, status, error) {
                    if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) {
                        nf.Dialog.showOkDialog({
                            dialogContent: nf.Common.escapeHtml(xhr.responseText),
                            overlayBackground: true
                        });
                    } else {
                        nf.Common.handleAjaxError(xhr, status, error);
                    }

                    deferred.reject();
                });
            }).promise();
        };

        // go through each selected connection
        d3.selectAll('g.connection.selected').each(function (d) {
            updates.set(d.component.id, updateConnectionPosition(d));
        });
        
        // go through each selected component
        d3.selectAll('g.component.selected').each(function (d) {
            // consider any self looping connections
            var connections = nf.Connection.getComponentConnections(d.component.id);
            $.each(connections, function(_, connection) {
                if (!updates.has(connection.id) && nf.CanvasUtils.getConnectionSourceComponentId(connection) === nf.CanvasUtils.getConnectionDestinationComponentId(connection)) {
                    updates.set(connection.id, updateConnectionPosition(nf.Connection.get(connection.id)));
                }
            });
            
            // consider the component itself
            updates.set(d.component.id, updateComponentPosition(d));
        });

        // wait for all updates to complete
        $.when.apply(window, updates.values()).done(function () {
            var dragged = $.makeArray(arguments);
            var connections = d3.set();

            // refresh this component
            $.each(dragged, function (_, component) {
                // check if the component in question is a connection
                if (component.type === 'Connection') {
                    connections.add(component.id);
                } else {
                    // get connections that need to be refreshed because its attached to this component
                    var componentConnections = nf.Connection.getComponentConnections(component.id);
                    $.each(componentConnections, function (_, connection) {
                        connections.add(connection.id);
                    });

                    // refresh the component
                    nf[component.type].position(component.id);
                }
            });

            // refresh the connections
            connections.forEach(function (connectionId) {<commit_msg>NIFI-223: - Addressing issue when dragging multiple components. Issue stemmed from skipping the PUT request when the component (a connection with no bends points) was included in the selection.<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
nf.Draggable = (function () {

    var drag;

    /**
     * Updates the positioning of all selected components.
     * 
     * @param {selection} dragSelection The current drag selection
     */
    var updateComponentsPosition = function (dragSelection) {
        var revision = nf.Client.getRevision();
        var updates = d3.map();

        // determine the drag delta
        var dragData = dragSelection.datum();
        var delta = {
            x: dragData.x - dragData.original.x,
            y: dragData.y - dragData.original.y
        };

        // if the component didn't move, return
        if (delta.x === 0 && delta.y === 0) {
            return;
        }
        
        var updateComponentPosition = function(d) {
            var newPosition = {
                x: d.component.position.x + delta.x,
                y: d.component.position.y + delta.y
            };

            // update the component positioning
            return $.Deferred(function (deferred) {
                $.ajax({
                    type: 'PUT',
                    url: d.component.uri,
                    data: {
                        version: revision.version,
                        clientId: revision.clientId,
                        x: newPosition.x,
                        y: newPosition.y
                    },
                    dataType: 'json'
                }).done(function (response) {
                    // update the revision
                    nf.Client.setRevision(response.revision);

                    // store the updated location
                    d.component.position = newPosition;

                    // resolve with an object so we can refresh when finished
                    deferred.resolve({
                        type: d.type,
                        id: d.component.id
                    });
                }).fail(function (xhr, status, error) {
                    if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) {
                        nf.Dialog.showOkDialog({
                            dialogContent: nf.Common.escapeHtml(xhr.responseText),
                            overlayBackground: true
                        });
                    } else {
                        nf.Common.handleAjaxError(xhr, status, error);
                    }

                    deferred.reject();
                });
            }).promise();
        };
        
        var updateConnectionPosition = function(d) {
            // only update if necessary
            if (d.component.bends.length === 0) {
                return null;
            }

            // calculate the new bend points
            var newBends = $.map(d.component.bends, function (bend) {
                return {
                    x: bend.x + delta.x,
                    y: bend.y + delta.y
                };
            });

            var entity = {
                revision: revision,
                connection: {
                    id: d.component.id,
                    bends: newBends
                }
            };

            // update the component positioning
            return $.Deferred(function (deferred) {
                $.ajax({
                    type: 'PUT',
                    url: d.component.uri,
                    data: JSON.stringify(entity),
                    dataType: 'json',
                    contentType: 'application/json'
                }).done(function (response) {
                    // update the revision
                    nf.Client.setRevision(response.revision);

                    // store the updated bend points
                    d.component.bends = response.connection.bends;
                    d.bends = $.map(d.component.bends, function (bend) {
                        return {
                            x: bend.x,
                            y: bend.y
                        };
                    });

                    // resolve with an object so we can refresh when finished
                    deferred.resolve({
                        type: d.type,
                        id: d.component.id
                    });
                }).fail(function (xhr, status, error) {
                    if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) {
                        nf.Dialog.showOkDialog({
                            dialogContent: nf.Common.escapeHtml(xhr.responseText),
                            overlayBackground: true
                        });
                    } else {
                        nf.Common.handleAjaxError(xhr, status, error);
                    }

                    deferred.reject();
                });
            }).promise();
        };

        // go through each selected connection
        d3.selectAll('g.connection.selected').each(function (d) {
            var connectionUpdate = updateConnectionPosition(d);
            if (connectionUpdate !== null) {
                updates.set(d.component.id, connectionUpdate);
            }
        });
        
        // go through each selected component
        d3.selectAll('g.component.selected').each(function (d) {
            // consider any self looping connections
            var connections = nf.Connection.getComponentConnections(d.component.id);
            $.each(connections, function(_, connection) {
                if (!updates.has(connection.id) && nf.CanvasUtils.getConnectionSourceComponentId(connection) === nf.CanvasUtils.getConnectionDestinationComponentId(connection)) {
                    var connectionUpdate = updateConnectionPosition(nf.Connection.get(connection.id));
                    if (connectionUpdate !== null) {
                        updates.set(connection.id, connectionUpdate);
                    }
                }
            });
            
            // consider the component itself
            updates.set(d.component.id, updateComponentPosition(d));
        });

        // wait for all updates to complete
        $.when.apply(window, updates.values()).done(function () {
            var dragged = $.makeArray(arguments);
            var connections = d3.set();

            // refresh this component
            $.each(dragged, function (_, component) {
                // check if the component in question is a connection
                if (component.type === 'Connection') {
                    connections.add(component.id);
                } else {
                    // get connections that need to be refreshed because its attached to this component
                    var componentConnections = nf.Connection.getComponentConnections(component.id);
                    $.each(componentConnections, function (_, connection) {
                        connections.add(connection.id);
                    });

                    // refresh the component
                    nf[component.type].position(component.id);
                }
            });

            // refresh the connections
            connections.forEach(function (connectionId) {
{'fraction_non_alphanumeric': 0.09283481145919735, 'fraction_numerical': 0.003892043641931985, 'mean_word_length': 1.278860133759814, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3026375', 'n_tokens_mistral': 3711, 'n_tokens_neox': 3425, 'n_words': 974}