<commit_before>/*
 * Copyright © 2015 <NAME>, Inc.
 *
 * Licensed 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.
 */

angular.module(PKG.name + '.commons')
  .controller('MyDAGController', function MyDAGController(jsPlumb, $scope, $timeout, MyDAGFactory, GLOBALS, NodesActionsFactory, $window, NodesStore, $rootScope, HydratorService, $popover, $filter, uuid, $tooltip) {

    var vm = this;

    var numberFilter = $filter('number');

    var endpoints = [];
    var sourceSettings = angular.copy(MyDAGFactory.getSettings(false).source);
    var sinkSettings = angular.copy(MyDAGFactory.getSettings(false).sink);
    var transformSourceSettings = angular.copy(MyDAGFactory.getSettings(false).transformSource);
    var transformSinkSettings = angular.copy(MyDAGFactory.getSettings(false).transformSink);

    var SHOW_METRICS_THRESHOLD = 0.8;
    var METRICS_THRESHOLD = 999999999999;
    var selected = [];
    var labels = [];

    var metricsLabel = [
      [ 'Custom', {
        create: function (label) {
          labels.push(label);
          return angular.element('<div><span class="metric-label-text"></span></div>');
        },
        width: 100,
        location: [4.3, 0],
        id: 'metricLabel',
        cssClass: 'metric-label'
      }]
    ];

    if ($scope.showMetrics) {
      sourceSettings.overlays = metricsLabel;
      transformSourceSettings.overlays = metricsLabel;
    }

    var dragged = false;
    var canvasDragged = false;

    vm.isDisabled = $scope.isDisabled;

    var popovers = [];
    var nodePopovers = {};

    vm.scale = 1.0;

    vm.panning = {
      style: {
        'top': 0,
        'left': 0
      },
      top: 0,
      left: 0
    };

    vm.comments = [];

    /*
    FIXME: This should be fixed. Right now the assumption is to update
     the store before my-dag directive is rendered. What happens if we get the
     data after the rendering? The init function is never called or the DAG is not
     rendered based on the data.

     Right now there is a cycle which prevents us from listening to the NodeStore
     changes. The infinite recurrsion happens like this,
     Assuming we have this
     NodesStore.registerChangeListener(init);
     1. User adds a connection in view
     2. 'connection' event is fired by jsplumb
     3. On connection event we call 'formatConnections' function
     4. 'formatConnections' constructs the 'connections' array and sets it to NodesStore
     5. Now NodesStore fires an update to changelisteners.
     6. 'init' function gets called.
     6. 'init' function again programmatically connects all the nodes and sets it to NodesStore
     7. Control goes to step 5
     7. Hence the loop.

     We need to be able to separate render of graph from data and incremental user interactions.
     - Programmatically it should be possible to provide data and should be able to ask dag to render it at any time post-rendering of the directive
     - User should be able interact with the dag and add incremental changes.
    */
    function init() {
      $scope.nodes = NodesStore.getNodes();
      $scope.connections = NodesStore.getConnections();
      vm.comments = NodesStore.getComments();

      $timeout(function () {
        addEndpoints();

        angular.forEach($scope.connections, function (conn) {
          var sourceNode = $scope.nodes.filter( node => node.name === conn.from);
          var targetNode = $scope.nodes.filter( node => node.name === conn.to);
          if (!sourceNode.length || !targetNode.length) {
            return;
          }
          var sourceId = sourceNode[0].type === 'transform' ? 'Left' + conn.from : conn.from;
          var targetId = targetNode[0].type === 'transform' ? 'Right' + conn.to : conn.to;
          var connObj = {
            uuids: [sourceId, targetId]
          };
          if (vm.isDisabled) {
            connObj.detachable = false;
          }

          vm.instance.connect(connObj);
        });

        // Process metrics data
        if ($scope.showMetrics) {

          angular.forEach($scope.nodes, function (node) {
            var elem = angular.element(document.getElementById(node.name)).children();

            var scope = $rootScope.$new();
            scope.data = {
              nodeName: node.name
            };

            nodePopovers[node.name] = {
              scope: scope,
              element: elem,
              popover: null,
              isShowing: false
            };

            $scope.$on('$destroy', function () {
              scope.$destroy();
            });

          });

          if (vm.scale <= SHOW_METRICS_THRESHOLD) {
            hideMetricsLabel();
          }

          angular.forEach(labels, function (endpoint) {
            var label = endpoint.getOverlay('metricLabel');

            $tooltip(angular.element(label.getElement()).children(), {
              trigger: 'hover',
              title: 'Records Out',
              delay: 300,
              container: 'body'
            });

          });

          $scope.$watch('metricsData', function () {
            if (Object.keys($scope.metricsData).length === 0) {
              angular.forEach(nodePopovers, function (value) {
                value.scope.data.metrics = 0;
              });
            }

            angular.forEach($scope.metricsData, function (value, key) {
              nodePopovers[key].scope.data.metrics = value;
            });

            angular.forEach(labels, function (endpoint) {
              var label = endpoint.getOverlay('metricLabel');
              if ($scope.metricsData[endpoint.elementId] === null || $scope.metricsData[endpoint.elementId] === undefined) {
                angular.element(label.getElement()).children()
                  .text(0);
                return;
              }
$scope.metricsData[endpoint.elementId].recordsOut = METRICS_THRESHOLD + 10;
              var recordsOut = $scope.metricsData[endpoint.elementId].recordsOut;

              // hide label if the length is greater than 12 characters
              if(recordsOut > METRICS_THRESHOLD) {
                label.hide();
              } else if (recordsOut <= METRICS_THRESHOLD && vm.scale >= SHOW_METRICS_THRESHOLD ) {
                label.show();
              }

              angular.element(label.getElement()).children()
                .text(numberFilter(recordsOut, 0));

            });
          }, true);
        }<commit_msg>add comments to explain metrics threshold usage<commit_after>/*
 * Copyright © 2015 <NAME>, Inc.
 *
 * Licensed 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.
 */

angular.module(PKG.name + '.commons')
  .controller('MyDAGController', function MyDAGController(jsPlumb, $scope, $timeout, MyDAGFactory, GLOBALS, NodesActionsFactory, $window, NodesStore, $rootScope, HydratorService, $popover, $filter, uuid, $tooltip) {

    var vm = this;

    var numberFilter = $filter('number');

    var endpoints = [];
    var sourceSettings = angular.copy(MyDAGFactory.getSettings(false).source);
    var sinkSettings = angular.copy(MyDAGFactory.getSettings(false).sink);
    var transformSourceSettings = angular.copy(MyDAGFactory.getSettings(false).transformSource);
    var transformSinkSettings = angular.copy(MyDAGFactory.getSettings(false).transformSink);

    var SHOW_METRICS_THRESHOLD = 0.8;
    var METRICS_THRESHOLD = 999999999999;
    var selected = [];
    var labels = [];

    var metricsLabel = [
      [ 'Custom', {
        create: function (label) {
          labels.push(label);
          return angular.element('<div><span class="metric-label-text"></span></div>');
        },
        width: 100,
        location: [4.3, 0],
        id: 'metricLabel',
        cssClass: 'metric-label'
      }]
    ];

    if ($scope.showMetrics) {
      sourceSettings.overlays = metricsLabel;
      transformSourceSettings.overlays = metricsLabel;
    }

    var dragged = false;
    var canvasDragged = false;

    vm.isDisabled = $scope.isDisabled;

    var popovers = [];
    var nodePopovers = {};

    vm.scale = 1.0;

    vm.panning = {
      style: {
        'top': 0,
        'left': 0
      },
      top: 0,
      left: 0
    };

    vm.comments = [];

    /*
    FIXME: This should be fixed. Right now the assumption is to update
     the store before my-dag directive is rendered. What happens if we get the
     data after the rendering? The init function is never called or the DAG is not
     rendered based on the data.

     Right now there is a cycle which prevents us from listening to the NodeStore
     changes. The infinite recurrsion happens like this,
     Assuming we have this
     NodesStore.registerChangeListener(init);
     1. User adds a connection in view
     2. 'connection' event is fired by jsplumb
     3. On connection event we call 'formatConnections' function
     4. 'formatConnections' constructs the 'connections' array and sets it to NodesStore
     5. Now NodesStore fires an update to changelisteners.
     6. 'init' function gets called.
     6. 'init' function again programmatically connects all the nodes and sets it to NodesStore
     7. Control goes to step 5
     7. Hence the loop.

     We need to be able to separate render of graph from data and incremental user interactions.
     - Programmatically it should be possible to provide data and should be able to ask dag to render it at any time post-rendering of the directive
     - User should be able interact with the dag and add incremental changes.
    */
    function init() {
      $scope.nodes = NodesStore.getNodes();
      $scope.connections = NodesStore.getConnections();
      vm.comments = NodesStore.getComments();

      $timeout(function () {
        addEndpoints();

        angular.forEach($scope.connections, function (conn) {
          var sourceNode = $scope.nodes.filter( node => node.name === conn.from);
          var targetNode = $scope.nodes.filter( node => node.name === conn.to);
          if (!sourceNode.length || !targetNode.length) {
            return;
          }
          var sourceId = sourceNode[0].type === 'transform' ? 'Left' + conn.from : conn.from;
          var targetId = targetNode[0].type === 'transform' ? 'Right' + conn.to : conn.to;
          var connObj = {
            uuids: [sourceId, targetId]
          };
          if (vm.isDisabled) {
            connObj.detachable = false;
          }

          vm.instance.connect(connObj);
        });

        // Process metrics data
        if ($scope.showMetrics) {

          angular.forEach($scope.nodes, function (node) {
            var elem = angular.element(document.getElementById(node.name)).children();

            var scope = $rootScope.$new();
            scope.data = {
              nodeName: node.name
            };

            nodePopovers[node.name] = {
              scope: scope,
              element: elem,
              popover: null,
              isShowing: false
            };

            $scope.$on('$destroy', function () {
              scope.$destroy();
            });

          });

          if (vm.scale <= SHOW_METRICS_THRESHOLD) {
            hideMetricsLabel();
          }

          angular.forEach(labels, function (endpoint) {
            var label = endpoint.getOverlay('metricLabel');

            $tooltip(angular.element(label.getElement()).children(), {
              trigger: 'hover',
              title: 'Records Out',
              delay: 300,
              container: 'body'
            });

          });

          $scope.$watch('metricsData', function () {
            if (Object.keys($scope.metricsData).length === 0) {
              angular.forEach(nodePopovers, function (value) {
                value.scope.data.metrics = 0;
              });
            }

            angular.forEach($scope.metricsData, function (value, key) {
              nodePopovers[key].scope.data.metrics = value;
            });

            angular.forEach(labels, function (endpoint) {
              var label = endpoint.getOverlay('metricLabel');
              if ($scope.metricsData[endpoint.elementId] === null || $scope.metricsData[endpoint.elementId] === undefined) {
                angular.element(label.getElement()).children()
                  .text(0);
                return;
              }

              var recordsOut = $scope.metricsData[endpoint.elementId].recordsOut;

              // hide label if the metric is greater than METRICS_THRESHOLD.
              // the intent is to hide the metrics when the length is greater than 12.
              // Since records out metrics is an integer we can do a straight comparison
              if(recordsOut > METRICS_THRESHOLD) {
                label.hide();
              } else if (recordsOut <= METRICS_THRESHOLD && vm.scale >= SHOW_METRICS_THRESHOLD ) {
                label.show();
              }

              angular.element(label.getElement()).children()
                .text(numberFilter(recordsOut, 0));

            });
          }, true);
        }
{'fraction_non_alphanumeric': 0.10666762054657318, 'fraction_numerical': 0.00801259121476606, 'mean_word_length': 2.1684043517679057, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '6707255', 'n_tokens_mistral': 3835, 'n_tokens_neox': 3652, 'n_words': 1105}